How to connect the thinWallet provided by NEL to the NEO private chain

Author: Joit

Original link: https://mp.weixin.qq.com/s/ZEFlFRB6MTNaYXuvBYOZVg


sequence

At the end of 2017, I just started to contact the blockchain, and I am currently being tortured by NEO.
In the beginning, it was completely overwhelmed by official documents and NEO-GUI (especially the legendary F12), and I also found various debugging tools to use NeoContract, but they all came together.
Until one day, I discovered NewEconoLab. There is a project neo-thinsdk-cs on its github, which implements a light wallet-thinWallet in C#.
This light wallet only does one thing, which is to make transactions. It reflects the entire transaction process and shows developers a clear visual transaction splicing process (including Attribute, Inputs, Outputs, Script, Witness, etc., I I have used VS F11 to debug and trace its source code line by line, and all the data necessary for these transactions are assembled and put into a data structure, very clear).
The most important thing is to decompose UTXO and make Witness tractable to achieve operations that NEO-GUI cannot.
In addition, the current thinWallet, which is connected to Testnet by default, does not support direct access to Mainnet, nor to NEO private chain. We all know that Gas on Testnet is very precious and needs to apply for it. We deploy the contract , consumes 990 Gas at every turn. On your own private chain, Gas is Chinese cabbage, you can just play around.
So in order to facilitate the deployment of contract debugging, today's task is to connect thinWallet to the private chain.

1. Environmental preparation

  • Basic requirements : Four Debian 9 (other distributions are as you like, click here to view supported machines, it is recommended to create a virtual machine to configure the environment and then clone directly, don't forget to force refresh the MAC address, or IP conflicts) , a Windows 10, .net core sdk, visual studio 2017 community, .net framework 4.7 SDK, NEO-CLI, run consensus on a private chain, build a wallet, get 100 million NEO coins and at least 1000 Gas (equivalent to Your block height is more than 125, which takes at least 31 minutes), these things are all in the documentation, so I won't repeat them here.

  • Clone projects : NeoBlock-Mongo-Storage, NEO_Block_API, neo-thinsdk-cs, all three projects can use the master branch directly.

Here is an explanation of the relationship between the three cloned projects. All three are .net projects.

  1. neo-thinsdk-cs is a whole solution. It is opened with vs 2017. There is a WPF project called thinWallet. Set it as the startup project and run it directly by CTRL+F5. Of course, the default is to connect to Testnet. There is a "NEO Smart Contract Development (1) Impossible Task.docx" in the project, take a good look. The results are as follows:


    Here we just press the second button ThinWallet Test, and enter the interface like this:


  2. We can see that an API for UTXO is being called in the upper right corner. This is a webapi provided by NEO_Block_API. You can see that this place is Testnet by default, and the block height is also the height of Testnet. The button to switch the network has not yet written a function. A total of five large panels are easy to understand, the first login method, the second api information, the third account information (your utxo will appear here), the fourth transaction three elements, and the fifth decision is what type of transaction.


  3. NEO_Block_API uses mongodb, so our third project NeoBlock-Mongo-Storage runs as a scheduling task to collect transaction information on the chain in real time and store it in mongodb for NEO_Block_API to use.


  4. By the way, vs 2017 is very user-friendly, you can directly CTRL+F5 or generate a solution, it will help you restore the dependent library, don't panic when you see the yellow exclamation mark. If you can't open the project or can't restore or have any exception, believe me, it must be the wrong way for you to open it, or you have changed the content in it, or there is a problem with the environment, there is absolutely no error in the three projects, I After verifying it several times, please go back and check your environment and other infrastructure.

Configure NEO_Block_API

At this point, the basic environment is all set up, thinWallet can also be used normally on the Testnet, then you need to start connecting to the private chain. First of all, we need to add and modify the source code of NEO_Block_API so that it supports access to the private chain.
Let's take a look at what the source code looks like, or open it with vs 2017:


I have already generated the solution, so the dependencies are all fine, the structure is very simple. Controllers are controllers, that is, some web interfaces are implemented here, lib is the tools to be used, RPC defines some data structures, plus a Startup.cs and Program.cs files, a typical .net core web project.
We can see that there is a mongodbsettings.json file with a yellow warning sign, indicating that this file is missing, because it is written in .gitignore, so git ignores it, the problem is not big, we delete it It's good to re-create a file with the same name. We can find out where this file is used. You can search globally with CTRL+SHIFT+F, and finally find that   there is such a paragraph in mongoHelper.cs :

public mongoHelper() {    var config = new ConfigurationBuilder()
        .AddInMemoryCollection()    //将配置文件的数据加载到内存中
        .SetBasePath(System.IO.Directory.GetCurrentDirectory())   //指定配置文件所在的目录
        .AddJsonFile("mongodbsettings.json", optional: true, reloadOnChange: true)  //指定加载的配置文件
        .Build();    //编译成对象  
    mongodbConnStr_testnet = config["mongodbConnStr_testnet"];
    mongodbDatabase_testnet = config["mongodbDatabase_testnet"];
    neoCliJsonRPCUrl_testnet = config["neoCliJsonRPCUrl_testnet"];

    mongodbConnStr_mainnet = config["mongodbConnStr_mainnet"];
    mongodbDatabase_mainnet = config["mongodbDatabase_mainnet"];
    neoCliJsonRPCUrl_mainnet = config["neoCliJsonRPCUrl_mainnet"];

    mongodbConnStr_NeonOnline = config["mongodbConnStr_NeonOnline"];
    mongodbDatabase_NeonOnline = config["mongodbDatabase_NeonOnline"];
}

那么事情就简单了,我们看到这里面一共有 8 个字段要用到,给它就是了,我们在新建的 mongodbsettings.json 文件写上这些内容:

{
  "mongodbConnStr_testnet": "mongodb://127.0.0.1:27017",
  "mongodbDatabase_testnet": "testnet",
  "neoCliJsonRPCUrl_testnet": "http://47.96.168.8:20332",

  "mongodbConnStr_mainnet": "mongodb://127.0.0.1:27017",
  "mongodbDatabase_mainnet": "mainnet",
  "neoCliJsonRPCUrl_mainnet": "",

  "mongodbConnStr_privatenet": "mongodb://127.0.0.1:27017",
  "mongodbDatabase_privatenet": "privatenet",
  "neoCliJsonRPCUrl_privatenet": "http://192.168.1.135:20332",

  "mongodbConnStr_NeonOnline": "mongodb://127.0.0.1:27017",
  "mongodbDatabase_NeonOnline": "neononline"}

mainnet 一时半会儿肯定用不着,我懒得写了,testnet 还是保留原样,加一个 privatenet 。注意 neoCliJsonRPCUrl_privatenet 这个字段的值是 http://192.168.1.135:20332 ,192.168.1.135 这台机器是四台共识机中的一台,开了 RPC ,就是:dotnet neo-cli.dll /rpc 。我们可以用 postman 来测试一下,随便找个接口,路由是: http://192.168.1.135:20332 就用 getbestblockhash 吧:
先看一下我跑的四个共识节点,我的共识跑了挺久了,现在高度接近 7000 :

接下来我们看一下 rpc 接口调用结果:

如果你无法得到类似的结果,那还是得去多看看文档,跑跑共识。现在我们得到了正确结果,说明私链的 RPC 完全没有问题。此刻我们得到了第一个需要的接口就是刚才打开的 thinWallet 右上角 RPC Node 所需要的接口地址:http://192.168.1.151:59908/api/privatenet 。


mongodb 你得装一下(随你 linux 还是 windows,推荐 linux),为了演示方便,我装在了 windows 里面。装完之后就是 C:\Program Files\MongoDB\Server\3.6\bin 里面有一堆东西。其中 mongod.exe 这个是服务端,因为国际惯例有个 d 。别急着双击它,你得先建立两个文件夹:C:\data\db,不然双击就闪退了,其实你可以用 cmd 来打开,可以看到异常信息。现在你可以双击它了,结果就是一个控制台,打印了一堆日志,你可以用 mongodb 自带的可视化客户端连接一下。这边注意,我们不需要事先创建数据库。
下面开始创建 webapi 接口,也就是新建一个控制器,在项目的 Controllers 文件夹下,新建一个类,取名:PrivatenetController.cs ,然后把随便 TestnetController.cs 或者 ** MainnetController.cs** 里面的内容全部复制粘贴到我们的 PrivatenetController.cs 中,改一下两个地方,变成 privatenet :

[Route("api/[controller]")]public class PrivatenetController : Controller{
    Api api = new Api("privatenet");


接着 mongoHelper.cs 里面改一下,把私链的东西加进去:

public string mongodbConnStr_testnet = string.Empty;
public string mongodbDatabase_testnet = string.Empty;
public string neoCliJsonRPCUrl_testnet = string.Empty;
public string mongodbConnStr_mainnet = string.Empty;
public string mongodbDatabase_mainnet = string.Empty;
public string neoCliJsonRPCUrl_mainnet = string.Empty;
public string mongodbConnStr_privatenet = string.Empty;
public string mongodbDatabase_privatenet = string.Empty;
public string neoCliJsonRPCUrl_privatenet = string.Empty;public string mongodbConnStr_NeonOnline = string.Empty;public string mongodbDatabase_NeonOnline = string.Empty;public mongoHelper() {    var config = new ConfigurationBuilder()        .AddInMemoryCollection()    //将配置文件的数据加载到内存中        .SetBasePath(System.IO.Directory.GetCurrentDirectory())   //指定配置文件所在的目录        .AddJsonFile("mongodbsettings.json", optional: true, reloadOnChange: true)  //指定加载的配置文件        .Build();    //编译成对象      mongodbConnStr_testnet = config["mongodbConnStr_testnet"];    mongodbDatabase_testnet = config["mongodbDatabase_testnet"];    neoCliJsonRPCUrl_testnet = config["neoCliJsonRPCUrl_testnet"];    mongodbConnStr_mainnet = config["mongodbConnStr_mainnet"];    mongodbDatabase_mainnet = config["mongodbDatabase_mainnet"];    neoCliJsonRPCUrl_mainnet = config["neoCliJsonRPCUrl_mainnet"];    mongodbConnStr_privatenet = config["mongodbConnStr_privatenet"];    mongodbDatabase_privatenet = config["mongodbDatabase_privatenet"];    neoCliJsonRPCUrl_privatenet = config["neoCliJsonRPCUrl_privatenet"];    mongodbConnStr_NeonOnline = config["mongodbConnStr_NeonOnline"];    mongodbDatabase_NeonOnline = config["mongodbDatabase_NeonOnline"]; }


最后,Api.cs 里面加私链的东西:

public Api(string node) {
    netnode = node;    switch (netnode) {        case "testnet":
            mongodbConnStr = mh.mongodbConnStr_testnet;
            mongodbDatabase = mh.mongodbDatabase_testnet;
            neoCliJsonRPCUrl = mh.neoCliJsonRPCUrl_testnet;            break;        case "mainnet":
            mongodbConnStr = mh.mongodbConnStr_mainnet;
            mongodbDatabase = mh.mongodbDatabase_mainnet;
            neoCliJsonRPCUrl = mh.neoCliJsonRPCUrl_mainnet;            break;        case "privatenet":
            mongodbConnStr = mh.mongodbConnStr_privatenet;
            mongodbDatabase = mh.mongodbDatabase_privatenet;
            neoCliJsonRPCUrl = mh.neoCliJsonRPCUrl_privatenet;            break;
    }
}

打完收工我们来试一下,CTRL+F5,我们可以看到内置的 IIS Express 被启动了,可以访问这个地址:
http://localhost:59908/api/privatenet
显示的结果是:

{"jsonrpc":"2.0","id":0,"error":{"code":-100,"message":"Parameter Error","data":"Value cannot be null.\r\nParameter name: s"}}


那说明 webapi 本身已经没问题了,我们看到用的是 localhost ,如果想局域网都能用的话我们可以改一下 .vs\config\applicationhost.config 里面的配置再运行,或者我们用典型的 .net core 方法(我采用这种),就是在 Program.cs 里面加一点料:.UseUrls("http://*:59908"),详细如下,这是允许局域网 ip 访问的第一步:

public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .UseUrls("http://*:59908")
                .Build();


第二步我们改一下启动方式,先重新生成解决方案,然后把 appsettings.json 和 mongodbsettings.json 两个文件复制到 bin\Debug\netcoreapp2.0 里面去,关掉刚才启动的 IIS Express,然后我们以管理员身份打开 cmd ,cd 到你的 bin\Debug\netcoreapp2.0 文件夹里面,然后 dotnet NEO_Block_API.dll 就好了,结果如下:

你可以去局域网的其他机器上用 postman 访问一下,没啥问题,用 getblockcount 接口吧,路由是这个: http://192.168.1.151:59908/api/privatenet ,文档在这:http://www.xiaoyaoji.cn/share/1H0gjTDtfk/1GzzPWtpFG 。
我在这台 windows 10 上操作的,IP 是 192.168.1.151 ,所以我们得到了第二个想要的接口地址,就是 API for UTXO 的 api 地址:http://192.168.1.151:59908/api/privatenet 。


thinWallet 接入私链

现在我们来观察一下 thinWallet 的代码结构:

很显然,上面三个项目都是通用库,第三个是用户端,而且我们只需要改一个地方就可以了,双击打开 Window_thinwallet.xaml,WPF 的界面文件,打开是这样的:


简直不能忍,不仅丑爆了,还影响阅读和写代码,我们做一下调整,下面图里面中间,左右两个红圈圈出来的按钮,先按左边那个,上下窗口对调,然后按右边那个,把下窗口缩进去,这样就是纯代码界面了,又好看又能高效阅读。


接下来我们要把它接入私链,其实就该两个接口地址,就在这个界面代码里面,thinWallet 对这两个地址目前是写死在界面上的,我们在界面代码里面查找一下 CTRL+F ,输入 47.96 就能找到了,一共两个地方,分别对应的填进去:

打完收工我们来访问一下,CTRL+F5:


我们发现一个很诡异的数字,下面那个直接访问 neo rpc 的已经完全正常了,但是上面那个访问 webapi 的居然是这么个诡异的数字,那么碰到问题,我们首先得想到的事情只有一件,就是 F5,首先我们先打开 Window_thinwallet.xaml 这个文件的后台文件,就是 Window_thinwallet.xaml.cs ,我们观察一下里面的代码,发现有一个异步更新界面的地方:

再来看一下这个 api_getHeight 是怎么实现的,F12 过去:

真相在这里,请求了 webapi 的一个 getblockcount 的接口,那么现在来看一下 NEO_Block_API 项目对 getblockcount 是怎么实现的:


At this time, we found that the data of mongodb is actually being called here. If we recall, there seems to be no place to operate mongodb, that is to say, there is no data, then we can guess that the getblockcount interface returns a 0, and in our  Window_thinwallet.xaml.cs file The place where the interface is updated asynchronously, finally  var height = ulong.Parse(json[0].AsDict()["blockcount"].ToString()) - 1; came this sentence, it is very clear, unsigned long integer, minus 1, resulting in that number, now come to F5 to prove it, the breakpoint hits  api_getHeight the last sentence of this method return on the code:


The result is the request result, which is 0, which has explained everything. So what's wrong, think about it, we seem to have missed a project, and yes, the last scheduling task project is not configured.

NeoBlock-Mongo-Storage enables task scheduling for private chains

Observing the code in the same way:

very simple, one entry, two data interfaces, one tool, gone.
We can find  Program.cs this paragraph in it:

var config = new ConfigurationBuilder()
    .AddInMemoryCollection()    //将配置文件的数据加载到内存中
    .SetBasePath(System.IO.Directory.GetCurrentDirectory())   //指定配置文件所在的目录
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)  //指定加载的配置文件
    .Build();    //编译成对象  mongodbConnStr = config["mongodbConnStr"];
mongodbDatabase = config["mongodbDatabase"];
NeoCliJsonRPCUrl = config["NeoCliJsonRPCUrl"];
sleepTime = int.Parse(config["sleepTime"]);if (int.Parse(config["utxoIsSleep"]) == 1) {
    utxoIsSleep = true;
}

Very simple, add a file, appsettings.json :

{
  "mongodbConnStr": "mongodb://127.0.0.1:27017",
  "mongodbDatabase": "privatenet",
  "NeoCliJsonRPCUrl": "http://192.168.1.135:20332",
  "sleepTime": "0",
  "utxoIsSleep": "0"}

同样道理,重新生成解决方案,把这个 json 文件复制到 bin\Debug\netcoreapp2.0 里面去,然后管理员身份打开 cmd ,然后 cd 进去,然后 dotnet NeoBlockMongoStorage.dll ,看下结果:

这个狂暴的气息,然后我们开一下 thinWallet,看下结果:

这个高度正在快速地向最高高度同步过去,同步完成之后,我们就完成了 thinWallet 接入私链的所有步骤,你的 thinWallet 就可以在私链中随便玩了。
同步完成之后,我们最好把 NeoBlock-Mongo-Storage 项目的 appsettings.json 改一下,把 sleepTime 从 0 改为 2000,utxoIsSleep 从 0 改为 1,因为调度是个无限循环,如果不让它睡一会,就会一直浪费你的 cpu ,同步完成了,没那么多数据要写了,让它休息休息,这样造成的效果是,上面那个高度永远比下面那个高度更新慢半拍。单位是毫秒。自己随便调节。

{
  "mongodbConnStr": "mongodb://127.0.0.1:27017",
  "mongodbDatabase": "privatenet",
  "NeoCliJsonRPCUrl": "http://192.168.1.135:20332",
  "sleepTime": "2000",
  "utxoIsSleep": "1"}

然后对着这两篇质量文档去玩吧。
不可能任务一
不可能任务二


本文由NEL内容激励计划支持




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325546953&siteId=291194637