搭建以太坊私有链(PoA)--CentOS7.6 on 阿里云ECS、macOS Catalina on Mac、Ubuntu20.04 on Raspberry Pi 4B
使用Geth搭建以太坊PoA私有链
搭建以太坊私有链(PoA)
环境说明:
- 阿里云ECS上配置了 CentOS 7.6,上面运行了两个 node,其中 node1 用来做 bootnode, 创建一个账户,并分配一定的 ether;node2 创建一个账户,但是没钱。
- macOS Catalina 上运行了一个 node,创建一个账号,没钱。
- Raspberry Pi 4B model 上运行了 Ubuntu 20.04.1 for ARM64,运行一个nodePi4,创建一个账户,没钱。
1 阿里云ECS上的操作步骤
1.1 准备环境
通过SSH登录到阿里云服务器上,并执行系统更新以及必备软件安装命令
[root@Aliyun ~]# yum update -y && yum install git wget bzip2 vim gcc-c++ ntp epel-release nodejs tree -y
配置CentOS的防火墙,允许 30303、30304、8545、8645 可以被访问。
[root@Aliyun ~]# firewall-cmd --zone=public --add-port=8545/tcp --permanent
[root@Aliyun ~]# firewall-cmd --zone=public --add-port=30303/tcp --permanent
[root@Aliyun ~]# firewall-cmd --zone=public --add-port=8645/tcp --permanent
[root@Aliyun ~]# firewall-cmd --zone=public --add-port=30304/tcp --permanent
[root@Aliyun ~]# firewall-cmd --reload
1.2 安装Geth及Tools
Ethereum 在 这里 提供了针对各种版本的Geth及工具包的可执行文件下载,根据阿里云的服务器配置,选择下图所示的版本。

复制该版本的下载地址,然后在终端输入以下命令,将压缩包下载到当前路径中。
[root@Aliyun ~]# wget -c https://gethstore.blob.core.windows.net/builds/geth-alltools-linux-amd64-1.9.24-cc05b050.tar.gz ./
解压该压缩包
[root@Aliyun ~]# tar -zxvf geth-alltools-linux-amd64-1.9.24-cc05b050.tar.gz
于是在当前路径下出现了 geth-alltools-linux-amd64-1.9.24-cc05b050 文件夹,进入该文件夹,会看到以下文件。

将图片中看到的所有绿色的文件依次复制到 /usr/local/bin 目录下,这样可以全局调用,也省得配置环境变量。
[root@Aliyun geth-alltools-linux-amd64-1.9.24-cc05b050]# cp ./abigen /usr/local/bin/abigen
[root@Aliyun geth-alltools-linux-amd64-1.9.24-cc05b050]# cp ./bootnode /usr/local/bin/bootnode
[root@Aliyun geth-alltools-linux-amd64-1.9.24-cc05b050]# cp ./clef /usr/local/bin/clef
[root@Aliyun geth-alltools-linux-amd64-1.9.24-cc05b050]# cp ./evm /usr/local/bin/evm
[root@Aliyun geth-alltools-linux-amd64-1.9.24-cc05b050]# cp ./geth /usr/local/bin/geth
[root@Aliyun geth-alltools-linux-amd64-1.9.24-cc05b050]# cp ./puppeth /usr/local/bin/puppeth
[root@Aliyun geth-alltools-linux-amd64-1.9.24-cc05b050]# cp ./rlpdump /usr/local/bin/rlpdump
然后回到用户目录下,测试 geth 命令是否可用。
[root@Aliyun geth-alltools-linux-amd64-1.9.24-cc05b050]# cd ~
[root@Aliyun ~]# geth version
Geth
Version: 1.9.24-stable
Git Commit: cc05b050df5f88e80bb26aaf6d2f339c49c2d702
Git Commit Date: 20201112
Architecture: amd64
Protocol Versions: [65 64 63]
Go Version: go1.15.5
Operating System: linux
GOPATH=
GOROOT=go
如果看到以上的输出,就表示 Geth 安装成功了。
1.3 创建以太坊私有链的数据文件夹
创建两个node的文件夹
[root@Aliyun ~]# mkdir -p Ursamjnor/node1
[root@Aliyun ~]# mkdir -p Ursamjnor/node2
为 node1 创建账户
[root@Aliyun ~]# cd Ursamjnor
[root@Aliyun Ursamjnor]# geth --datadir node1/ account new
这里执行后会要求我们输入新建账户的密码(两次输入),这里假设我们设定密码是“pwdfornode1”,然后终端会出现我们创建的账户地址,这个地址以及刚才的密码最好存放在文本文件中,便于以后使用。
[root@Aliyun Ursamjnor]# echo "node1的账户地址" >> accounts.txt
[root@Aliyun Ursamjnor]# echo "pwdfornode1" >> node1/password.txt
为 node2 创建账户的操作步骤跟node1的一样
1.4 用puppeth配置以太坊私有链
以下是在终端进行的操作,按照提示输入数字或者信息后完成配置。
[root@Aliyun Ursamjnor]# puppeth
Please specify a network name to administer (no spaces, hyphens or capital letters please)
> ursamjnor
Sweet, you can set this via --network=ursamjnor next time!
INFO [09-17|11:43:03.307] Administering Ethereum network name=ursamjnor
WARN [09-17|11:43:03.367] No previous configurations found path=/root/.puppeth/ursamjnor
What would you like to do? (default = stats)
1. Show network stats
2. Configure new genesis
3. Track new remote server
4. Deploy network components
> 2
What would you like to do? (default = create)
1. Create new genesis from scratch
2. Import already existing genesis
> 1
Which consensus engine to use? (default = clique)
1. Ethash - proof-of-work
2. Clique - proof-of-authority
> 2
How many seconds should blocks take? (default = 15)
> 10
Which accounts are allowed to seal? (mandatory at least one)
> 0x //这里是node1的账户地址
> 0x
Which accounts should be pre-funded? (advisable at least one)
> 0x //再输入一遍node1的账户地址
> 0x
Should the precompile-addresses (0x1 .. 0xff) be pre-funded with 1 wei? (advisable yes)
> yes
Specify your chain/network ID if you want an explicit one (default = random)
> 8848 //这里输入一个大于2018的整数
INFO [09-20|10:07:39.675] Configured new genesis block
What would you like to do? (default = stats)
1. Show network stats
2. Manage existing genesis
3. Track new remote server
4. Deploy network components
> 2
1. Modify existing configurations
2. Export genesis configurations
3. Remove genesis configuration
> 2
Which folder to save the genesis specs into? (default = current)
Will create ursamjnor.json, ursamjnor-aleth.json, ursamjnor-harmony.json, ursamjnor-parity.json
>
INFO [09-20|10:07:58.879] Saved native genesis chain spec path=ursamjnor.json
ERROR[09-20|10:07:58.879] Failed to create Aleth chain spec err="unsupported consensus engine"
ERROR[09-20|10:07:58.915] Failed to create Parity chain spec err="unsupported consensus engine"
INFO [09-20|10:07:58.916] Saved genesis chain spec client=harmony path=ursamjnor-harmony.json
What would you like to do? (default = stats)
1. Show network stats
2. Manage existing genesis
3. Track new remote server
4. Deploy network components
> ^C // Ctrl+c to exit
以上全部完成后会在当前路径下出现 ursamjnor.json 和 ursamjnor-harmony.json 两个文件,其中 ursamjnor.json 是我们的genesis block配置信息文件。
接下来用 ursamjnor.json 初始化node1和node2。
[root@Aliyun Ursamjnor]# geth --datadir node1 init ursamjnor.json
执行成功后,会看到终端返回:Successfully wrote genesis state 字样,表明初始化成功。
node2的初始化也一样,只需要把 --datadir 后面的 node1 改成 node2 即可。
1.5 启动 node1
启动命令如下:
[root@Aliyun Ursamjnor]# geth --networkid 8848 --datadir node1 --http --http.port 8545 --http.addr "0.0.0.0" --port 30303 --http.corsdomain "*" --http.api "eth,net,web3,personal,miner" --unlock 0 --password ./node1/password.txt --allow-insecure-unlock console
这里有必要把一些参数解释一下,省得以后自己也忘了。
- –networkid:我们创建的私有链的网络id
- –datadir:节点的数据文件夹
- –http:表示允许远程调用。这个参数以前叫rpc,后来在新版的Geth中改成http了,当然用rpc也可以,只不过这个参数很快就被丢弃了,还是早点改的好,这个可以在Geth的帮助中看到。
- –http.port:表示允许远程调用的端口。默认是8545。这个参数以前是rpcport。
- –http.addr:把这个值写成“0.0.0.0”表示允许远程访问,否则只能本地访问。这个参数以前是rpcaddr。
- –port:表示网络监听端口,默认值是30303。
- –http.corsdomain:允许跨域请求的域列表,这里指定为“*”。这个参数以前是rpccorsdomain
- –http.api:允许远程调用的API,用逗号间隔,凡是列出来的,在远程调用时均可以使用。
- –unlock:表示被解锁账户的编号,0表示node数据文件中第一个被创建的账户,这个账户被解锁才能使用该账户进行交易。
- –password:表示解锁账户时的账户密码,就是在创建账户时输入的密码。
- –allow-insecure-unlock:允许使用不安全的账户解锁(???翻译的不好,大概是这个意思吧)。
- console:表示打开Geth JavaScript console。
这时可以看到node1被成功启动,而且可以看到以下输出:
Welcome to the Geth JavaScript console!
instance: Geth/v1.9.24-stable-cc05b050/linux-amd64/go1.15.5
coinbase: 0xf0ce9c088f3f7e9c43387dfe5666405e4873206e
at block: 490 (Sun Nov 15 2020 18:19:25 GMT+0800 (CST))
datadir: /root/Ursamjnor/node1
modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
To exit, press ctrl-d
>
输入命令时会被终端的节点同步信息覆盖,不过没关系,直接输入就行,不受影响。这里我们输入eth.coinbase 查看coinbase账户地址:
> eth.coinbase
"0xf0。。。。。6e"
这里返回的是node1的第一个账户地址,我这里把地址中的部分字符隐藏了。
查看账户有多少钱用eth.getBalance(“账户地址”) 命令
> eth.getBalance(eth.coinbase)
9.046256971665327767466483203803742801036717552003169065582623750618213253e+74
好多钱,但是可惜不是真钱,只能在我们这个私有链上用。
我们可以通过personal.newAccount() 命令再给node1创建一个账户。
> personal.newAccount("123456")
"0x35。。。。。4a"
我写了个最简单的123456做密码,实际操作时应该改成复杂一些的,而且最好把密码也保存一下,用于解锁账户。返回值是新创建的账户地址。
通过eth.accounts命令可以看到当前两个账户放在accounts数组中,新创建的是第二个元素。
> eth.accounts
["0x0xf0。。。。。6e", "0x35。。。。。4a"]
查看第二个账户有多少钱
> eth.getBalance(eth.accounts[1])
0
没有钱,但是我们可以从第一个账户上转点钱给第二个账户。在对这个账户进行操作之前,我们最好也把这个账户解锁,因为第一个账户是在启动node1的时候解锁的,而第二个账户是在之后建立的,所以解锁需要通过personal.unlockAccount("账户地址","账户密码",解锁的秒数)。
> personal.unlockAccount(eth.accounts[1],"123456",150000)
true
返回true表示解锁成功。
发送交易的命令是web3.eth.sendTranscation({from:to:value:}) ,我们使用这个命令从账户1上转一些钱给账户2。
- from:是交易的发起方地址,就是付钱的地址。
- to:是收钱地址。
- value:是交易额,以太币。
> web3.eth.sendTransaction({from: eth.coinbase, to: eth.accounts[1], value: web3.toWei(300,"ether")})
"0x7d....................88"
返回的是一个交易的Hash值,这时交易虽然发布了,但是并不能被确认,因为网络中没有矿工来记账,所以要开启node1的挖矿功能。如果这时查看第二个账户的余额,还是 0
> eth.getBalance(eth.accounts[1])
0
执行以下命令:
> miner.start()
然后再次执行 eth.getBalance(eth.accounts[1]) ,会看到它有钱了。
> eth.getBalance(eth.accounts[1])
300000000000000000000
退出这个交互式命令行工具,可以输入 exit 退出,也可以输入 CTRL-D 退出。
把刚才的启动命令存放到 startnode1.sh 中,便于以后使用。
[root@Aliyun Ursamjnor]# vi startnode1.sh
输入 ‘i’,进入插入模式,将下述内容填写在文件中。
#!/bin/bash
geth --networkid 8848 --datadir node1 --http --http.port 8545 --http.addr "0.0.0.0" --port 30303 --http.corsdomain "*" --http.api "eth,net,web3,personal,miner" --unlock 0 --password ./node1/password.txt --allow-insecure-unlock console
ESC退出插入模式,输入“:wq”回车执行保存并退出功能。
命令中最后一个 console 是开启JavaScript CLI模式,如果不想开启,把这个参数去掉即可。
给 startnode1.sh文件添加可执行权限。
[root@Aliyun Ursamjnor]# chmod +x ./startnode1.sh
以后要启动node1,只需要在终端执行该文件即可。
[root@Aliyun Ursamjnor]# ./startnode1.sh
1.6 启动 node2
因为node2跟node1在同一台机器上,所以启动时需要选择不同的“http.port”、“port”。这里只给出具体命令文件内容,其他跟node1的操作相同。
#!/bin/bash
geth --networkid 8848 --datadir node2 --http --http.port 8645 --http.addr "0.0.0.0" --port 30304 --http.corsdomain "*" --http.api "eth,net,web3,personal,miner" --unlock 0 --password ./node2/password.txt --allow-insecure-unlock console
node2 启动后,需要加入node1启动的网络,必须知道node1的 enode 值才可以。
在node1的 Geth JavaScript console 可以找到 enode的值:
enode://1fb9c826c44.............064@127.0.0.1:30303
我们需要把这个值告诉给node2,于是在node2的 Geth JavaScript console 中执行以下命令:
> admin.addPeer("enode://1fb9c826c44.............064@127.0.0.1:30303")
true
返回值为true表示加入成功,这里可以获取以下node2的账户,然后从node1转一些钱过去。
在node1的 Geth JavaScript console 中执行
> web3.eth.sendTransaction({from: eth.coinbase, to: "node2 的账户地址", value: web3.toWei(100,"ether")})
"0x..........................."
接下来在node2的 Geth JavaScript console 里执行eth.getBalance(eth.coinbase)查询一下,查到node2的账户上也有钱了。
2 在Mac上配置node3
2.1 准备工作
安装或更新Homebrew。这个是Mac系统的软件管理工具,如果没有Homebrew,就需要在终端里安装一下。
➜ ~ $ sh -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
执行后有可能会启动xcode的管理工具界面,点击install就行。
安装必要的软件工具:
- tree:这个工具可以让我们在终端看到目录的树形结构,比较有用。
- go-lang:go语言开发和编译必备软件包
➜ ~ $ brew install tree
➜ ~ $ brew install go
- Geth:Ethereum的客户端工具。
这个客户端工具最好别在终端运行命令安装,奇慢无比,建议还是访问 Ethereum 的Download页面,找到 Mac 选项卡,选择对应的版本下载最好。
或者,如果你打算在 Mac 上开发智能合约的话,通过安装 Ganache 也能同时安装了 Geth,
2.2 创建数据文件夹
在用户目录下也创建一个用来存放数据的文件夹,最好跟network的名字一样,然后进入文件夹后,从阿里云服务器上把 ursamjnor.json 文件下载到该目录下:
➜ ~ $ mkdir ursamjnor
➜ ~ $ cd ursamjnor
➜ ursamjnor $ mkdir node3
➜ ursamjnor $ scp root@阿里云服务器地址:/root/Ursamjnor/ursamjnor.json ./
2.3 初始化node3并启动
➜ ursamjnor $ geth --datadir node3 init ursamjnor.json
...
➜ ursamjnor $ geth --datadir node3 account new
...
➜ ursamjnor $ geth echo "123456" >> ./node3/password.txt
➜ ursamjnor $ geth --networkid 8848 --datadir node3 --http --http.port 8545 --http.addr "0.0.0.0" --port 30303 --http.corsdomain "*" --http.api "eth,net,web3,personal,miner" --unlock 0 --password ./node3/password.txt --allow-insecure-unlock console
同样也最好把启动命令写入 .sh 文件中,便于以后调用。
2.4 加入node1的enode
在node3的 Geth JavaScript console 中执行以下命令:
> admin.addPeer("enode://1fb9c826c44.............064@阿里云服务器地址:30303")
true
注意这里的@后面不是127.0.0.1 ,而是阿里云服务的外网访问地址。
返回值为true表示加入成功。
2.5 交易一下
在 node3 的 Geth JavaScript console 里查看刚才创建的那个账户的余额
> eth.getBanlance(eth.coinbase)
0
因为在启动 node3 之前已经为其创建了账户,所以这个被创建的账户会默认为 eth.coinbase。
我们回到 node1 的 Geth JavaScript console 中执行
> web3.eth.sendTransaction({from: eth.coinbase, to: "node3 的账户地址", value: web3.toWei(100,"ether")})
"0x..........................."
因为 node1 的 miner 始终是 start 状态,所以很快交易就会被确认,我们再次回到 node3 的 Geth JavaScript console 中,查看账户余额
> eth.getBanlance(eth.coinbase)
100000000000000000000
至此,我们的私有链上已经出现了两台不同位置的机器(一台阿里云,一台我手边的Mac)以及三个node,其中只有node1具有miner功能。
3 在Raspberry Pi上配置nodePi4
3.1 准备工作
Raspberry Pi 4B 的 CPU 是 64位的ARM,访问 Ubuntu 的官网,找到 Download 菜单,然后选择下图中的链接点击

在下图的页面中,按照箭头的指示去下载镜像文件即可。如果觉得官网慢,可以自己去国内的镜像源里找对应的版本下载。

其实网上有很多好心人写好安装过程了,这里给个传送门:
Raspberry Pi 安装 Ubuntu Server 20.04 LTS (无显示器, 无网线) – 极夜喵
以及下面这个博文
树莓派4安装ubuntu server20.04 &&WIFI 配置(提供WIFI配置文件 —避免入坑,亲测有效!!!)
参考上面的文章把Ubuntu安装好之后,就可以通过Mac的终端去操作Raspberry Pi 了,包括将Raspberry Pi上的Ubuntu的软件更新,并安装必备的软件环境(git、golang、libgmp3-dev)。
➜ ~ ssh ubuntu@你的树莓派在本地局域网的地址
......
ubuntu ~ $ sudo apt-get update
ubuntu ~ $ sudo apt-get upgrade
ubuntu ~ $ sudo apt install tree vim git golang libgmp3-dev
ubuntu ~ $ mkdir Ursamjnor
ubuntu ~ $ exit
以上执行完成后就可以先退出ssh了,因为后面需要通过Mac把准备好的Geth客户端以及创世区块配置文件传送到树莓派上。
由于Raspberry Pi下载Geth的客户端比较慢,可以在Mac上先下载了之后,通过scp命令传输给Raspberry Pi。
下载的Geth版本是ARM64的

传送命令
➜ ~ scp -P 22 geth-linux-arm64-1.9.24*.tar.gz ubuntu@你的树莓派本地局域网地址:/home/ubuntu
3.2 创建 nodePi4 数据文件夹并启动
创建好文件夹之后,还要把刚才在Mac的Ursamjnor目录中从阿里云服务上下载的 ursamjnor.json 文件传输到Raspberry Pi中,这样才能对 nodePi4 初始化为同一个network的node。
➜ ~ scp ./Ursamjnor/ursamjnor.json ubuntu@192.168.31.150:/user/ubuntu/Ursamjnor
➜ ~ ssh ubuntu@你的树莓派在本地局域网的地址
......
ubuntu ~ $ cd Ursamjnor
ubuntu Ursamjnor $ mkdir nodePi4
ubuntu Ursamjnor $ cd nodePi4
ubuntu Ursamjnor $ geth --datadir nodePi4 init ursamjnor.json
ubuntu Ursamjnor $ geth --datadir nodePi4 account new
......
ubuntu Ursamjnor $ echo "123456" >> ./nodePi4/password.txt
ubuntu Ursamjnor $ geth --networkid 8848 --datadir nodePi4 --http --http.port 8545 --http.addr "0.0.0.0" --port 30303 --http.corsdomain "*" --http.api "eth,net,web3,personal,miner" --unlock 0 --password ./node4/password.txt --allow-insecure-unlock console
当Raspberry Pi上的nodePi4成功启动后,还要把node1的enode值添加到peer中才可以成功连接网络并同步节点信息。添加方法同Mac上的操作。
可以试着在node1的 Geth JavaScript console 中操作向Raspberry Pi的账户转一笔钱,并查看账户的变化。
这篇文章编写时参考了以下文章,在此对文章作者表示感谢!
[1] CentOS 7.6 以太坊Ethereum環境建置 - Geth篇
[2] Build Proof of Authority Ethereum Network with Geth
注:
2020年11月15日第一次编写
2020年11月16日重新编辑过
更多推荐
所有评论(0)