从今天开始我们将进入新的专题 - 区块链。
开这个专题之前我也思考再三,要讲区块链其实是比较困难的。时至今日,区块链其实也并不像17年刚开始时那么高深了,很多概念性的东西有很多博主和小编都已经讲得很清晰。撇除概念性的内容讲算法和底层又会变得太过枯燥,那个“度”其实很难拿捏。
为了让大家快速入门我决定先教大家怎么搭建,让大家能够先看到效果或许这样大家会感兴趣得多。而且现在网上一般都是介绍Hyperledger Fabric比较多(毕竟大厂商用的多嘛),我们反其道而行之介绍以太坊系列,希望各位能够多多支持。 所以接下来的区块链系列会按照以下顺序进行分享:
- 简单搭建Geth私有链;
- 介绍Hyperledger Besu区块链;
- 以Docker版本Hyperledger Besu为基础搭建一个完整的区块链网络;
当然了,因为一些不能说的原因我会将与现公司利益相关的部分剔除(其中包括一键部署脚本和web3j底层优化的内容),所以难免会有点“点到为止”的感觉还望各位多多包涵。
区块链我这边是选择了以太坊的区块链,主要是因为门槛低、学习成本低,最最主要的还是对于Java项目而言以太坊系列的区块链客户端都相对比较友好。在初接触的时候我选用了Geth解决方案作为入门,下面给各位讲述关于Geth的整个部署过程。
1. Geth客户端下载
由于本地使用的是Ubuntu操作系统,因此接下来提到的系统代指Ubuntu 14.04操作系统。
我们先到公网下载Geth客户端,访问Geth官方网站https://geth.ethereum.org/,如下图:
PS:由于文章编写时是2018年的,因此官网界面已经改版了,但是操作步骤基本一致。在基于本文操作是基于当时的情况进行操作的。现在官网是这个样子的,如下图:
Geth全称叫做Go Ethereum,由于Geth是Go语言编写的,所以在Ethereum前加上Go的字眼。在官网的顶部点击“Downloads”导航条进入下载页面,进入页面后Geth网站的服务端将会检查并列出所有发布版本Geth客户端。https://geth.ethereum.org/downloads/这个下载页面经常获取失败,多刷几次就好,如下图:
PS:改版后已经没有了下载问题,现在的界面是这样的,如下图:
如上图所示,目前Geth客户端的最新版本是1.10.26,由于这个版本产生区块的实现方式不适合部署的需要,在经过多次尝试后决定使用1.7.2版本作为跑合区块链的基础版本。1.7.2版本下载地址:https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.7.2-1db4ecdc.tar.gz,如下图:
2. 设置Geth环境变量
将下载后的压缩包解压到另一个目录
mkdir /home/yzh/Downloads/install/geth-linux
tar -xzvf geth-linux-amd64-1.7.2-1db4ecdc.tar.gz -C /home/yzh/Downloads/install/geth-linux
配置geth到系统环境变量
# 修改环境变量
sudo vim /etc/profile
export GETH=/home/yzh/Downloads/install/geth-linux
export PATH=$PATH:$GETH
# 执行使其生效
source /etc/profile
3. 创建创世块配置文件(genesis.json)
先创建geth_base目录并创建genesis.json文件
mkdir /home/yzh/Documents/geth_base
sudo vim /home/yzh/Documents/geth_base/genesis.json
至于genesis.json内容如下所示
{
"config": {
"chainId": 20,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"nonce":"0x0000000000000042",
"timestamp":"0x0",
"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData":"",
"gasLimit":"0xffffffff",
"difficulty":"0x40",
"mixhash":"0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase":"0x0000000000000000000000000000000000000000",
"alloc":{}
}
从genesis.json文件中可以看出,由于要生成一条私有链,所以将挖矿难度设置得比较低后面出块的速度会提高。关于上面参数的说明如下所示:
- mixhash:与nonce配合用于挖矿,由上一个区块的一部分生成的hash。
- nonce: 就是一个64位随机数,用于挖矿。
- difficulty:设置当前区块的难度,如果难度过大,cpu挖矿就很难,这里设置较小难度。
- alloc:用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以我们不需要预置有币的账号,需要的时候自己创建即可以。
- coinbase:矿工的账号,随便填。
- timestamp:设置创世块的时间戳。
- parentHash:上一个区块的hash值,因为是创世块,所以这个值是0
- extraData:附加信息,随便填,可以填你的个性信息,必须为十六进制的偶位字符串。
- gasLimit:该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们是私有链,所以填最大。
各位可以按照自己实际需要进行配置。
4. 多节点部署
创世块配置有了,客户端有了可以准备多节点部署了,我们先创建节点文件夹(先做个3个节点的吧,不然看不出效果)
mkdir /home/yzh/Documents/geth_base/01
mkdir /home/yzh/Documents/geth_base/02
mkdir /home/yzh/Documents/geth_base/03
sudo chmod 777 -R /home/yzh/Documents/geth_base
三个目录分别使用创世块配置进行初始化得到创世块
geth --datadir "/home/yzh/Documents/geth_base/01" init /home/yzh/Documents/geth_base/genesis.json
geth --datadir "/home/yzh/Documents/geth_base/02" init /home/yzh/Documents/geth_base/genesis.json
geth --datadir "/home/yzh/Documents/geth_base/03" init /home/yzh/Documents/geth_base/genesis.json
创建创世块后后台的输出如下图所示:
有了创世块后就能够启动Geth节点,这里为了方便展示将启动配置直接写在语句上面了,按道理这部分配置信息应该写在配置文件中以便后面多处引用。
geth --identity "yzh" \
--maxpeers 3 \
--networkid 355419 \
--datadir /home/yzh/Documents/geth_base/01 \
--nodiscover \
--syncmode "fast" \
--cache 2048 \
--rpccorsdomain "*" \
--rpcapi "db,eth,net,web3,personal" \
--rpc \
--rpcport 30001 \
--port 60001 console 2>>/home/yzh/Documents/geth_base/01/geth_01.log
参数解释如下所示:
- --identity "yzh":geth客户端唯一id为“yzh”
- --maxpeers 3: 最大节点为3个
- --networkid 355419:geth网络id为355419
- --datadir /home/yzh/Documents/geth_base/01:数据文件地址
- --syncmode "fast":使用快速同步的区块同步模式
- --cache 2048:使用2G的内存
- --nodiscover:禁用私有链以外的区块链网络
- --rpccorsdomain "*" :rpc域名为全部
- --rpcapi "db,eth,net,web3,personal":开启geth客户端可以使用的rpc接口
- --rpc :开启rpc模式
- --rpcport 30001 :rpc端口(java端连接需要)
- --port 60001 : geth第一节点访问端口
- console 2>>/home/yzh/Documents/geth_base/01/geth_01.log :geth第一节点输出文件
节点启动后后台输出如下:
节点启动之后要留意输入admin.nodeInfo.enode并记录返回信息,譬如:
"enode://394262e127403680db4611c1a0ef4b74af70a5a150e9cb4095745c5a6de7a631d5ee195d071b563ed4c26a4aa341f76b22105e0fa611812f8750583e3106c1d5@10.0.2.15:60001"
接下来就要启动第二个Geth节点,启动语句跟第一个节点的语句一样,只是有关路径的地方稍微改变一下即可,如下所示:
geth --identity "yzh" \
--maxpeers 3 \
--networkid 355419 \
--datadir /home/yzh/Documents/geth_base/02 \
--nodiscover \
--syncmode "fast" \
--cache 2048 \
--rpccorsdomain "*" \
--rpcapi "db,eth,net,web3,personal" \
--rpc \
--rpcport 30002 \
--port 60002 console 2>>/home/yzh/Documents/geth_base/02/geth_02.log
执行上面语句启动了之后若执行admin.peers命令会发现返回的是空数组,这时就需要添加节点集群。节点集群配置需要在/home/yzh/Documents/geth_base/02路径下添加static-nodes.json文件配置集群节点,譬如:
["enode://394262e127403680db4611c1a0ef4b74af70a5a150e9cb4095745c5a6de7a631d5ee195d071b563ed4c26a4aa341f76b22105e0fa611812f8750583e3106c1d5@10.0.2.15:60001"]
注意,这里填的就是刚刚在节点1中截取下来的admin.nodeInfo.enode记录,填写完成后节点2就能够与节点1通讯了。这个时候输入admin.peers命令可以看到输出,如下图:
同理,按照节点2的部署方式启动第三个Geth节点,当第二、三个节点都完成启动后分别输入admin.nodeInfo.enode来获取节点地址,如下所示:
# 节点2 enode地址
"enode://021b44c675b7867a04eda5b2659bfcda5bb0859bc6cc0ed19b6ceaa5cd82a7dc49fa83868c62c9496cd668baf624178053f7c19c9e0df4fcfe1e2a85b266365f@10.0.2.15:60002"
#节点3 enode地址
"enode://dfa979251744737fa4282b56a0d17ea1846077f7d8969266690b804700317ffd5c69d9a199dd5d2c7eeca5d67f6ad0742fcb7634a6dc64c8e17884e063a8496b@10.0.2.15:60003"
之后就简单了,既然节点之间需要互为通讯就必须建立static-nodes.json文件并将其他节点的enode地址补上,那么节点3和节点2的static-nodes.json文件只需要将其余两个节点的enode地址补全就可以了,以节点3为例如下图:
至此,节点通讯配置就完成了。
5. Geth基本操作
- 创建矿工账号
Geth区块链若需要交易必须要用以太币驱动,而以太币则需要通过矿工挖矿来体现(POW)。因此在每个Geth客户端中的第一个账号就是矿工的账号。创建矿工账号coinbase通过personal.newAccount(密码)来创建。 当然,在多账号的情况下矿工的账号是可以通过miner.setEtherbase(personal.listAccounts[0])来切换。
- 创建普通账号
同样使用personal.newAccount(密码)来创建普通账号。
- 查询账号余额和区块信息
使用eth.getBalance(eth.accounts[0]) 可以查询账号的余额信息,在还没有挖矿的情况下应该全部都是0。 使用eth.blockNumber可以查询区块链上的区块数,在还没有开始挖矿之前也应该是0。
- 启动节点
每个客户端节点都可以通过miner.start()来启动,第一次节点的启动会先进入初始化模式,等初始化成功后开始挖矿。挖矿余额会自动存入矿工账号,同时整个链的区块数也会增多,如下图:
如上图所示,第一个节点已经在挖矿了,当查询区块数的时候发现已经有76个块通过以太币的方式加入到区块链中。第二个节点虽然没有启动,但是由于三个节点都已经做了同步,因此通过eth.blockNumber也查询到链上存在77个区块。由此证明三个节点都成功接入到同一区块链中,而且区块也已经实现实时同步。