0%

搭建以太坊私链

这里的命令以 Linux 系统为准,但是在 Windows 系统下也是基本相同的

配置Go环境

1、首先切换到管理员身份

1
sudo -s

2、下载官⽅的 go 语⾔编译器压缩包

1
wget https://go.dev/dl/go1.21.3.linux-amd64.tar.gz

3、解压缩刚下载的新版本并放置到合适的位置

1
2
tar -C /usr/local -xzf go1.21.3.linux-amd64.tar.gz
(如果有旧版本,先输入 `rm -rf /usr/local/go` 移除)

4、设定环境变量

1
export PATH=$PATH:/usr/local/go/bin

试试看是否正常(应该会看到版本号)

1
go version

构建geth

1、下载git

1
sudo apt install git

2、克隆以太坊源码
这一步很可能连不上github,没什么解决方法,多试

1
git clone https://github.com/ethereum/go-ethereum.git

3、进入ethereum所在文件夹
24-04-09更新: 现在直接克隆以太坊仓库下载的 geth 版本是 1.14.0-unstable,所以在运行链的时候就会出现以下报错,应该要先切换到 1.13版本

1
2
3
cd go-ethereum
git checkout release/1.13
git pull

4、编译geth

1
make geth

如果发现下载很慢,可以终止掉,设置代理

1
export GOPROXY=https://goproxy.io,direct

下载完成,应该可以看到以下画面

5、进⼊⽬录

1
cd build/bin

6、启动主程序,连接主⽹并同步

1
./geth

7、配置环境变量

1
nano ~/.bashrc

在该文件最后添加以下语句,要注意替换成自己主机的geth所在路径 (前面的~也要修改)

1
export PATH=$PATH:~/Desktop/go-ethereum/build/bin

退出后输入以下语句让更改生效,并检测是否配置成功

1
2
source ~/.bashrc
geth version

搭建私链

1、创造配置文件
在不同于以太坊源码的文件路径下创一个文件夹和.json文件,命名为genesis.json,可以在桌面创建

1
2
3
4
5
6
// 注意要记得切换到管理员模式,才能创建文件夹
sudo -s
mkdir ./project
mkdir ./project/MyChain
vim ./project/MyChain/genesis.json
// 修改完输入:wq退出vim

在这个 json 文件下,配置这个私链的参数
这里使用的共识机制是 Clique

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"config": {
"chainId": 12345,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"berlinBlock": 0,
"clique": {
"period": 5,
"epoch": 30000
}
},
"difficulty": "1",
"gasLimit": "8000000",
"extradata": "0x0000000000000000000000000000000000000000000000000000000000000000890fb1799fe7fa4b8e01ccf343e088d946fcd5560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"alloc": {
"890fb1799fe7fa4b8e01ccf343e088d946fcd556": { "balance": "300000" },
"14c6ead33b265da463eef7367798ade6aa8e9d12": { "balance": "400000" }
}
}

2、初始化链

1
geth --datadir ./project/MyChain/ init ./project/MyChain/genesis.json

成功后会出现以下提示 (可能会有 Error 信息,可以忽略)

假如出现以下报错,可以删除 ./project/MyChain/ 目录下新生成的两个文件夹,只保留 .json 文件

3、启用链
此处启用私链,并且开启RPC接口

24-04-09 更新: 在实验的时候发现,在较新版本的 geth 中,rpc 相关的指令已经不用 –rpcxxx,改为 –http.xxx

  • http:开启 RPC 接口
  • http.port:指定端口
  • http.api:开启的RPC API
  • http.corsdomain:跨域请求,”*”为允许所有来源的跨域请求
    而且,db 接口也已经被弃用,
    所以,该命令将变为
1
geth --datadir ./project/MyChain/ --identity "MyETH" --http --http.port 8545  --http.api "eth,net,web3,personal" --http.corsdomain "*" --networkid 12345 console

成功后将出现以下页面


1
geth --datadir ./project/MyChain/ --identity "MyETH" --rpc --rpcport 8545  --rpcapi "db,eth,net,web3,personal" --rpccorsdomain "*" --networkid 15 console
  • identity “MyETH”:节点身份标识
  • rpc:开启 RPC 接口
  • rpcport:指定端口
  • rpcapi:开启的RPC API
  • rpccorsdomain:跨域请求,”*”为允许所有来源的跨域请求
  • networkid:网络标识符,用于连上私链,networkid是在genesis.json中确定的
    console:打开geth控制台,用于创建节点和部署智能合约

创建用户并挖矿

1、在控制台中创建用户

24-04-09 更新: 实验中发现 personal 已经被弃用,geth 控制台似乎也没有其他方法新创建账户。官方给出的解决方案是使用和 geth 解耦的 clef 创建账号
个人认为,通过另开一个终端,使用以下命令创建账户会更方便

1
geth account new --datadir ./project/MyChain/

1
2
3
4
personal.newAccount("123456")//括号内是自定义的密码,返回“0x......”为创建出来的用户的地址。之后要用到。
eth.accounts //查询用户
eth.getBalance(eth.accounts[0]) // 通过eth.accounts[0]查询账户余额。若私链上有多个用户,第一个用户为eth.accounts[0],第二个为eth.accounts[1]。以此类推。
eth.getBalance("0x......账户地址") // 通过地址查询出账户余额

2、开始挖矿

1
2
3
4
eth.coinbase // 第一种查看矿工的账户地址的方式,该地址默认为第一个账户地址
web3.eth.coinbase // 第二种查看方式矿工地址的方式
miner.setEtherbase(eth.accounts[0])
//设置矿工用户

3、停止挖矿
挖一段时间后,账户就有钱了,可以部署智能合约(部署智能合约需要花钱),可以停止挖矿

1
2
3
miner.stop()
eth.getBalance(eth.accounts[0])
//再查账户,发现自己突然有钱了。

24-04-15 更新: miner.start() 必须先解锁账户,而 personal.unlockAccount 在较新版本的 geth 已经被弃用,不进行挖矿会导致所有交易都不能上链,包括智能合约的部署

目前的解决方法是,修改私链启动语句,将所有和 HTTP-RPC 相关的参数都删去 (不能与 –unlock 并存),并添加 –unlock 参数,在启动链的时候就解锁账户,之后的步骤和之前相同

1
geth --datadir ./project/MyChain/ --unlock 0x890fb1799fe7fa4b8e01ccf343e088d946fcd556 console

但是这样会产生新的问题,即无法远程调用 geth 提供的 HTTP-RPC API。目前想到的曲线救国方法是,一部分节点只用于挖矿 (以下称挖矿节点),一部分节点用于提供 HTTP-RPC API (以下称链接节点),但还未测试过,不知是否可行。


24-04-15 更新: 这种方法似乎是可行的,但是不一定符合工业标准,具体做法是:
1、创建新目录

1
mkdir ./project/node2

2、用原来的 genesis.json 初始化链

1
geth --datadir ./project/node2 init ./project/MyChain/genesis.json

并把 ./project/MyChain/keystore 复制到 ./project/node2/keystore

3、启用链

1
geth --datadir ./project/node2 --http --http.port 8545 --http.corsdomain "*" --networkid 12345 --port 30305 --authrpc.port 8552 --ipcpath \\.\pipe\geth2.ipc

4、添加节点
复制链接节点的enode值,并在挖矿节点所在链控制台中输入

1
admin.addPeer("enode://94d8388d7e97a8be1ee6005cc2bd81ad2b9f3e6580bec8a1305cac6271c5319b6a7e8273dfc82b0dab9c4c11ab71433f29ca30df3a4e327527a570ef1ed4bc28@127.0.0.1:30305")

成功后会出现以下界面,可以看到两次 Looking for peers 的 peercount 值发生了改变

5、使用 node.js 远程创建交易
以下是一个简单的转账交易例子,在任意位置创建文件 tx.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const Web3 = require('web3').default;

const web3 = new Web3('http://localhost:8545');

(async () => {
const privateKey = '替换成您的私钥'; // 私钥,确保正确和安全地处理
var tx = {
from: "0x890fb1799fe7fa4b8e01ccf343e088d946fcd556",
to: "0x4c6ead33b265da463eef7367798ade6aa8e9d12",
value: web3.utils.toWei(1, "ether"), // 转账金额,单位为以太
gas: 21000, // 交易的 gas 限额
gasPrice: web3.utils.toWei(10, "gwei") // gas 价格,单位为 wei
};

// 签名交易
try {
const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey);
const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
console.log('交易收据:', receipt);
} catch (err) {
console.error('签名或发送交易出错:', err);
}
})();

在挖矿节点所在链用 miner.start() 等待交易提交上链 (这里作者不确定是否需要在链接节点所在链用 miner.start(),正常来说会因为没有解锁账户而失败,但是似乎要这样做才能使两个节点同步)
创建好交易后,就可以使用以下命令提交交易

1
node tx.js

然后同时在两条链都查询账户余额,发现数额相同,说明两条节点成功同步

部署智能合约

参照下一篇文章

以太坊私链部署智能合约
赏个鸡腿🍗