# 编程日记：连接本地区块链（2022-08-21）

By [Corror](https://paragraph.com/@corror) · 2022-08-25

---

编程学习
----

### 行动目录

1.  搭建运行环境：
    
    1.  安装 VSCode,
        
    2.  安装 Node.js
        
    3.  安装 VSCode 插件
        
2.  迁移智能合约：
    
    1.  简化笔记内容，探索笔记格式。
        
    2.  重写代码，并修改报错。
        
3.  编译智能合约：
    
    1.  安装 solc 包。
        
    2.  学习使用 solc 命令，学习使用脚本打包命令。
        
4.  部署智能合约：
    
    1.  安装和运行 WSL 上的本地区块链网络 Ganache, 使用 Ganache 在本地部署合约。
        
    2.  **_td_** 使用 Ether.js 执行区块链操作。
        

### 做了什么？

1.  成功理解了 JavaScript Promise 的本质，并将其用笔记清晰地表述了出来。
    
2.  成功理解了包 solc 的作用，并知道了每一个 option 的具体作用和用法，最后还将 solc 编译命令用脚本打包表示。
    
3.  成功解决 Ganache 在 WSL 上的安装和运行问题。
    
4.  成功理解了 RPC 是什么。
    
5.  成功理解了服务器地址的本质，也具体了解了地址的三个组成部分： Protocal, IP 和 Port.
    
6.  成功就 WSL-2 无法连接到代理的问题，在 Stack Overflow 上进行了提问。
    

### 问题

#### 编译器版本问题

报错：

    ParserError: Source file requires different compiler version (current compiler is 0.8.7+commit.e28d00a7.Emscripten.clang)
    

原因：solc 0.8.7-fixed 的版本存在问题。

解决方法：当 solc 更新至最新版本后，compiler version 的问题就不存在了。

#### package.json 无法链接到代理

警告：

    Failed to establish a socket connection to proxies
    

原因推测：

根据[这个 Github 回答](https://github.com/microsoft/vscode/issues/136598#issuecomment-962926338)，可能是 WSL 在使用代理的过程中，出现了问题。根据回答中提到的 [VSCode 官方文档](https://code.visualstudio.com/docs/setup/network#_proxy-server-support)来看，可能是因为我的代理设置出现了问题。

解决方法：

根据 VSCode 官方文档，我想尝试 Manual proxy address, 但是遇见了两个问题：

1.  根据 VSCode 官方文档来看，如何在命令行当中使用如下命令：`--proxy-server=<scheme>=<uri>[:<port>][;...] | <uri>[:<port>] | "direct://"`？
    
2.  根据 Github 回答来看，WSL Server IP 在 `/etc/resolv.conf` 当中，但是我还是不知道如何根据这个路径找到 `resolv.conf` 文件？
    

对于以上两个问题，我将自己的思路用英文表述了一遍，并在 Stackoverflow 上面进行了[提问](https://stackoverflow.com/questions/73429921/wsl2-proxy-problem-failed-to-establish-a-socket-connection-to-proxies)。

重启 VSCode 以后，warning 就消失了。

### 收获了什么？

#### JS Promise

##### Promise 是什么？有什么用？

"Producing code" 是提供数据的函数，执行该函数需要一段时间； "Consuming code" 是使用数据的函数，执行该函数前需要等待数据处理出来。 Promise, 则是连接 producing code 和 consuming code 的 JavaScript 对象。

Promise 可以从 state 和 result 的角度，分为两类：

*   Promise state 有三种，分别是 pending, fulfilled, rejected.
    
*   Promise result 也有三种，且与 state 一一对应，分别是：undefined, a result value, an error object.
    

##### 如何使用 Promise?

Promise 从用法上看，分为 producing code 和 consuming code 两个部分。

举个例子：

    let myPromise = new Promise(function(meResolve, myRejected) => {
        /* producing code */
        myResolve();
        myRejected();
    });
    
    /* comsuming code */
    myPromise.then(
        function(value) { /* code if resolve */ },
        function(error) { /* code if rejected */ }
    );
    

其中，创建 Promise 的代码就叫做 producing code, 而根据 Promise 的情况去决定下一步该怎么做的代码就叫做 consuming code.

**_td_** 如果碰见了新的不会的内容，可以再回过头来，完善对 Promise 使用部分的理解和记录。

#### solc

solc 是用于编译 Solidity 的包。

它的安装方式有两种，一种是通过 nmp 包管理器，命令行为： `npm install solc`；另一种是通过 yarn 包管理器，命令行为：`yarn add solc`.

通过运行 solc 脚本，可以将指定的 solidity 合约以指定的形式编译出来。

举个例子：

    solcjs --bin --include-path node_modules/ --base-path . MainContract.sol
    

这是 solc 官网给出的例子，根据官网的提示和 `yarn solcjs --help` 自带的提示，可以知道以上 options 的含义：

*   "--bin": 代表编译出合约的二进制形式，并以 .bin 文件的形式表示。
    
*   "--include-path": 代表合约所导入的包的位置
    
*   "--base-path": 代表合约的位置。
    

再举个例子：

    yarn solcjs --bin --abi --include-path node_module/ --base-path . -o . SimpleStorage.sol
    

这是 Patrick 视频教程中的例子，分别解释一下官网当中所没有的 options 及其含义：

*   "--abi": 代表编译出合约的 ABI, 并以 .abi 文件的形式表示。
    
*   "-o": 代表编译后的内容的输出目录 (output directory) ，即 .bin 文件和 .abi 文件的存放位置。
    

#### 用脚本打包命令

对于一长串的命令，可以通过脚本来简化输入。

举个例子：

我们可以在 package.json 文件中，添加如下代码：

    {
        "scripts": {
            "compile": "yarn solcjs --bin --abi --include-path node_module/ --base-path . -o . SimpleStorage.sol"
        }
    }
    

这样一来，我们输入 `yarn compile` 就等同于输入 `yarn solcjs --bin --abi --include-path node_module/ --base-path . -o . SimpleStorage.sol`. 因此也就通过脚本，简化了输入。

#### RPC

> RPC 维基百科解释：
> 
> RPC is a request-response protocal.
> 
> An RPC is initiated by the client, which sends a request messega to a known remote server to execute a specific procedure with supplied parameter.
> 
> The remote server sends a response to the client, and the applications continue its process.

RPC 指 Remote Procedure Call 即远程过程调用。个人认为，它和 http 请求很像，向服务器发送请求，服务器返回响应。

#### 服务器地址

对于 Ganache 上的 RPC Server 来说，它由协议、 ip 地址和端口组成的服务器地址为：[http://0.0.0.0:8545](http://0.0.0.0:8545).

如何理解这些信息呢？可以分成三个部分来看：

1.  **Protocal 协议**：与 RPC 服务器通讯的客户端，需要遵守 http 协议，这样客户端的请求才能够被服务器理解。
    
2.  **IP 地址**：0.0.0.0 代表本地 IP 地址，代表该服务器是本地服务器。
    
3.  **Port 端口**：8545 代表访问该 Ganache 服务器所应当通过的端口，因为**每一个应用程序都在监听一个端口，只有通过特定的端口，才能访问到该服务器上特定的应用**。
    

对于 Ganache 而言，Ganache 就运行在端口 8545 上，因此想要访问 Ganache 本地服务器，那么就需要通过 8545 来找到 Ganache.

---

*Originally published on [Corror](https://paragraph.com/@corror/2022-08-21)*
