玩转Web3:Geth搭建联盟链
开篇
从本篇开始,我们准备更新 《玩转Web3》 系统文章,web3 的技术圈非常有趣,有很多思想的迭代,接下来就让我们开始 《玩转Web3》 吧!
本章主要内容
- 了解
Geth
的作用以及使用方法 - 搭建
Geth
联盟链,让区块链中的各个节点进行账本同步 - 使用
Metamask
在搭建好的联盟链中进行交易转账
初识Geth
Geth
是以太坊的客户端,客户端是能够与其他客户端建立 p2p
通信信道、签署广播交易、挖矿、部署和与智能合约交的软件。 以太坊节点必须遵循的功能的正式定义在以太坊黄皮书中定义。
黄皮书定义了网络上节点所需的函数,挖矿算法、私钥/公钥ECDSA 参数等,它定义了使节点与以太坊客户端完全兼容的全部功能。
大家按照自己的操作系统去官网上下载 Geth
就可以了,安装好后按如下教程进行使用
初始化创世块
- genesis.json 区块链初始文件
{
"alloc": { // 创世时,一开始的代币分配(非必须)
},
"config": {
"chainId": 6668, // 该链的ID。在用geth 启动区块链时,还需要指定一个network 参数。只有当network、chainID、创世区块配置都相同时,才是同一条链。
"homesteadBlock": 0, // 相关协议机制的升级区块所在的高度,签名算法是homestead ->eip155 -> eip158,所以从homesteadBlock 之前区块都通过homestead 相关算法机制来验证,homesteadBlock 到eip155Block 之间的用eip155 算法来验证,依次类推
"eip150Block": 0,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"ethash": {}
},
"nonce": "0x000000000000002a", // 预定一个随机数,这是一个与PoW 机制有关的值
"difficulty": "0x020000", // 定义了每次挖矿时,最终确定nonce 的难度
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", // 一个与PoW 机制有关的值
"coinbase": "0x0000000000000000000000000000000000000000", // 每挖出一个区块,都会获得奖励。该值指定默认情况下把奖励给到哪个账户。实际上,我们每次挖矿开始之前,都会自己指定miner.setEtherbase(UserAddress),一般都会把奖励给自己
"timestamp": "0x00", // 时间戳,规定创世区块开始的时间
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", // 在区块链中,区块是相连的,parentHash 指定了本区块的上一个区块Hash。对于创世区块来说,parentHash 为0
"extraData": "0x", // 扩展数据
"gasLimit": "0x2fefd8" // 规定该区块链中,gas 的上限
}
- 利用 Geth 初始化区块链
# 初始化
geth --datadir "D:\block\gt\data0" init genesis.json
# 启动
geth --identity "node0" --datadir "D:\block\gt\data" --http --http.port 8545 --http.corsdomain="*" --http.addr "0.0.0.0" --http.api "eth,web3,miner,admin,personal,net" --nodiscover --networkid 15 --allow-insecure-unlock --port 30303 --ipcdisable
# 通过http协议加入进入 console
geth attach http://127.0.0.1:8545
- 命令参数说明
参数 | 说明 |
---|---|
--datadir | 指定节点数据目录 |
init | 指定初始化节点使用的配置文件 genesis.json |
--identity | 设定节点标识 |
--http | 开启http rpc 服务 |
--http.port | 指定http rpc端口 |
--http.corsdomain | 指定跨域 |
--http.addr | 监听地址,默认为127.0.0.1,只能本地访问 |
--http.api | 设置节点上启用RPC接口 |
--nodiscover | 使用此选项可确保未手动添加您的人员无法发现您的节点。否则,如果您的节点具有相同的创世纪文件和网络ID,则可能无意中将您的节点添加到陌生人的区块链中 |
--networkid | 设定网络ID,当创建的链的 genesis block 和 network id 刚好与网络上其他人的链相同,那么就看哪条链长,如果比对方的短,那么链上的数据会全部被覆盖,变成对方的链。 |
--allow-insecure-unlock | 允许使用 http 协议进行账户解锁 |
--port | 网络侦听端口,对等端连接端口 |
--ipcdisable | 指定跨域 |
这样一个单节点就搭建好了,这里我们就可以利用刚刚启动后的 console
操作里面的模块了
console 模块
模块 | 作用 |
---|---|
eth | 区块操作 |
web3 | 包含了其他模块对象中的方法外,还包含一些单位换算的方法 |
miner | 挖矿操作 |
admin | 节点操作 |
personal | 账户操作 |
net | 网络操作 |
我们主要了解 miner
、admin
以及personal
模块,我们先简单实现创建一个账户,然后将这个账户设置为矿工,获取以太币收益
# 创建账户 会让输入密码 会返回一个地址
personal.newAccount() # "0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322"
# 设置矿工 返回true
miner.setEtherbase("0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322")
# 开始挖矿获取收益 返回 null
miner.start()
# 稍等一会就可以 停止挖矿
miner.stop()
# 然后我们查看账户余额
eth.getBalance("0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322")
# 以以太为单位查看,默认是 wei
web3.fromWei(eth.getBalance("0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322"),'ether')
现在我们已经可以进行单节点交互了,但是我们区块链主要是要交易记账,所以我们接下来要再新建一个账户,然后利用之前账户的以太进行转账
personal.newAccount() # "0x035bafe05b4a7a4eba9accf2c692785798b7132c"
# 转账 from -> to value 付多少
eth.sendTransaction({from:"0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322",to:"0x035bafe05b4a7a4eba9accf2c692785798b7132c",value:1000000000000})
# 但是在进行转账之前,我们需要先解锁我们的账户,相当于证明这个账户是我们自己的
personal.unlockAccount("0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322")
# 交易创建之后 每笔交易都会写入在区块中,但是需要挖矿才会被确认,所以我们发起了一笔交易,还需要进行挖矿才能使交易成功
miner.start()
miner.stop()
eth.getBalance("0x035bafe05b4a7a4eba9accf2c692785798b7132c") # 1000000000000
到这里,我们就看到了关于区块链的基本操作啦,但是单节点的区块链很明显信任度是不够的,而且单点故障问题也存在,所以我们需要构建一个分布式点对点系统。
搭建联盟链
我们准备在本机中,再启动两个节点,和之前流程一样,先初始化节点,然后去主节点上添加那两个节点(因为我们把自动发现给关闭了,所以我们需要手动去加入,正常是不用的)
# 指定新的数据目录 新的端口
geth --datadir "D:\block\gt\data1" init genesis.json
geth --identity "node1" --datadir "D:\block\gt\data1" --http --http.port 8546 --http.corsdomain="*" --http.addr "0.0.0.0" --http.api "eth,web3,miner,admin,personal,net" --nodiscover --networkid 15 --allow-insecure-unlock --port 30304 --ipcdisable
# 指定新的数据目录 新的端口
geth --datadir "D:\block\gt\data2" init genesis.json
geth --identity "node2" --datadir "D:\block\gt\data2" --http --http.port 8547 --http.corsdomain="*" --http.addr "0.0.0.0" --http.api "eth,web3,miner,admin,personal,net" --nodiscover --networkid 15 --allow-insecure-unlock --port 30305 --ipcdisable
加入其它节点
当启动新的两个节点 console
后,查看 enode
,到 node0
上面去加入 node1
和 node2
的 enode
# node1操作
admin.nodeInfo.enode # enode://5a0e1b6a2c4232a5e774a69a7c660acfa5cb7f573e89e55283c5a438c8d6280539c23cfe68bfdf4873b62da463eae4bc0add8adb9e806e261b875a32b83c7a7c@127.0.0.1:30304?discport=0
# node2操作
admin.nodeInfo.enode # enode://afd9e6d63588bcb070c8245f4c78612c8dd9a57def78aed85e135318397f43bbc01a47fdbb44f990304eefa59bdaae2d91ec5c2190f02bc52d7fdcec26c86a12@127.0.0.1:30305?discport=0
# node0操作
admin.addPeer("enode://afd9e6d63588bcb070c8245f4c78612c8dd9a57def78aed85e135318397f43bbc01a47fdbb44f990304eefa59bdaae2d91ec5c2190f02bc52d7fdcec26c86a12@127.0.0.1:30305?discport=0")
admin.addPeer("enode://5a0e1b6a2c4232a5e774a69a7c660acfa5cb7f573e89e55283c5a438c8d6280539c23cfe68bfdf4873b62da463eae4bc0add8adb9e806e261b875a32b83c7a7c@127.0.0.1:30304?discport=0")
admin.peers # 查看加入的节点
看到如下状态即成功
查看区块同步是否正常
我们通过在 node0
上挖矿,查看其他节点的日志是否处于同步状态,然后在 node1
和 node2
上去查看 node0
里面的账户余额
miner.start()
miner.stop()
看到其他节点都有成功日志
- 在
node0
和node1
查看挖矿账户的余额
# node1
geth attach http://127.0.0.1:8546
web3.fromWei(eth.getBalance("0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322"),'ether') # 85.999998
# node2
geth attach http://127.0.0.1:8547
web3.fromWei(eth.getBalance("0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322"),'ether') # 85.999998
通过 Metamask 在联盟链中转账
我们通过下面流程进行操作:
- 在
metamask
中添加我们的测试网络 - 导入我们之前创建的挖矿账户,在
node2
中创建一个账户,然后通过metamask
进行转账 - 然后挖矿查看结果
添加测试网络
利用 metamask 转账
去 node0
的数据目录中,找到 keystore
,里面都是账户的 json
文件,找到我们的矿工账户文件
去 metamask 中进行导入,输入创建账户时的密码
点击确定之后,可能会出现卡顿,过几分钟重新打开,会发现账户已经导入成功
node2中创建账户
geth attach http://127.0.0.1:8547
personal.newAccount() # "0xc1864e1f2b262ef89228eb1ebde9be6a6165cbe7"
使用 metamask 向地址转账
挖矿确认这笔交易
miner.start()
miner.stop()
成功,查询一下余额
web3.fromWei(eth.getBalance("0xc1864e1f2b262ef89228eb1ebde9be6a6165cbe7"),'ether') # 20
踩坑
- Erro starting protocol stack:Access is denied
增加参数 --ipcdisable
,禁用 ipc
- 为什么我使用了
admin.addPeer
加入了正确的enode
,而且结果也返回了true
,通过admin.peers
还是看不到加入的节点呢?
这个原因很简单,因为其他节点的初始化与主节点不一致,例如,忘记执行 init
步骤了,或者 init
选择的配置不一致,一定要保证和主节点初始化启动保持一致
- Error: The method personal_newAccount does not exist/is not available
--http.api
没有开启 personal
模块
总结
本章,我们搭建了私有联盟链,利用 metamask
进行操作,这个系统我们需要保留下来,之后可以用来部署合约,发布 ERC
系列货币,深入研究区块链原理和结构。
玩转Web3:Geth搭建联盟链
开篇
从本篇开始,我们准备更新 《玩转Web3》 系统文章,web3 的技术圈非常有趣,有很多思想的迭代,接下来就让我们开始 《玩转Web3》 吧!
本章主要内容
- 了解
Geth
的作用以及使用方法 - 搭建
Geth
联盟链,让区块链中的各个节点进行账本同步 - 使用
Metamask
在搭建好的联盟链中进行交易转账
初识Geth
Geth
是以太坊的客户端,客户端是能够与其他客户端建立 p2p
通信信道、签署广播交易、挖矿、部署和与智能合约交的软件。 以太坊节点必须遵循的功能的正式定义在以太坊黄皮书中定义。
黄皮书定义了网络上节点所需的函数,挖矿算法、私钥/公钥ECDSA 参数等,它定义了使节点与以太坊客户端完全兼容的全部功能。
大家按照自己的操作系统去官网上下载 Geth
就可以了,安装好后按如下教程进行使用
初始化创世块
- genesis.json 区块链初始文件
{
"alloc": { // 创世时,一开始的代币分配(非必须)
},
"config": {
"chainId": 6668, // 该链的ID。在用geth 启动区块链时,还需要指定一个network 参数。只有当network、chainID、创世区块配置都相同时,才是同一条链。
"homesteadBlock": 0, // 相关协议机制的升级区块所在的高度,签名算法是homestead ->eip155 -> eip158,所以从homesteadBlock 之前区块都通过homestead 相关算法机制来验证,homesteadBlock 到eip155Block 之间的用eip155 算法来验证,依次类推
"eip150Block": 0,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"ethash": {}
},
"nonce": "0x000000000000002a", // 预定一个随机数,这是一个与PoW 机制有关的值
"difficulty": "0x020000", // 定义了每次挖矿时,最终确定nonce 的难度
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", // 一个与PoW 机制有关的值
"coinbase": "0x0000000000000000000000000000000000000000", // 每挖出一个区块,都会获得奖励。该值指定默认情况下把奖励给到哪个账户。实际上,我们每次挖矿开始之前,都会自己指定miner.setEtherbase(UserAddress),一般都会把奖励给自己
"timestamp": "0x00", // 时间戳,规定创世区块开始的时间
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", // 在区块链中,区块是相连的,parentHash 指定了本区块的上一个区块Hash。对于创世区块来说,parentHash 为0
"extraData": "0x", // 扩展数据
"gasLimit": "0x2fefd8" // 规定该区块链中,gas 的上限
}
- 利用 Geth 初始化区块链
# 初始化
geth --datadir "D:\block\gt\data0" init genesis.json
# 启动
geth --identity "node0" --datadir "D:\block\gt\data" --http --http.port 8545 --http.corsdomain="*" --http.addr "0.0.0.0" --http.api "eth,web3,miner,admin,personal,net" --nodiscover --networkid 15 --allow-insecure-unlock --port 30303 --ipcdisable
# 通过http协议加入进入 console
geth attach http://127.0.0.1:8545
- 命令参数说明
参数 | 说明 |
---|---|
--datadir | 指定节点数据目录 |
init | 指定初始化节点使用的配置文件 genesis.json |
--identity | 设定节点标识 |
--http | 开启http rpc 服务 |
--http.port | 指定http rpc端口 |
--http.corsdomain | 指定跨域 |
--http.addr | 监听地址,默认为127.0.0.1,只能本地访问 |
--http.api | 设置节点上启用RPC接口 |
--nodiscover | 使用此选项可确保未手动添加您的人员无法发现您的节点。否则,如果您的节点具有相同的创世纪文件和网络ID,则可能无意中将您的节点添加到陌生人的区块链中 |
--networkid | 设定网络ID,当创建的链的 genesis block 和 network id 刚好与网络上其他人的链相同,那么就看哪条链长,如果比对方的短,那么链上的数据会全部被覆盖,变成对方的链。 |
--allow-insecure-unlock | 允许使用 http 协议进行账户解锁 |
--port | 网络侦听端口,对等端连接端口 |
--ipcdisable | 指定跨域 |
这样一个单节点就搭建好了,这里我们就可以利用刚刚启动后的 console
操作里面的模块了
console 模块
模块 | 作用 |
---|---|
eth | 区块操作 |
web3 | 包含了其他模块对象中的方法外,还包含一些单位换算的方法 |
miner | 挖矿操作 |
admin | 节点操作 |
personal | 账户操作 |
net | 网络操作 |
我们主要了解 miner
、admin
以及personal
模块,我们先简单实现创建一个账户,然后将这个账户设置为矿工,获取以太币收益
# 创建账户 会让输入密码 会返回一个地址
personal.newAccount() # "0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322"
# 设置矿工 返回true
miner.setEtherbase("0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322")
# 开始挖矿获取收益 返回 null
miner.start()
# 稍等一会就可以 停止挖矿
miner.stop()
# 然后我们查看账户余额
eth.getBalance("0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322")
# 以以太为单位查看,默认是 wei
web3.fromWei(eth.getBalance("0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322"),'ether')
现在我们已经可以进行单节点交互了,但是我们区块链主要是要交易记账,所以我们接下来要再新建一个账户,然后利用之前账户的以太进行转账
personal.newAccount() # "0x035bafe05b4a7a4eba9accf2c692785798b7132c"
# 转账 from -> to value 付多少
eth.sendTransaction({from:"0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322",to:"0x035bafe05b4a7a4eba9accf2c692785798b7132c",value:1000000000000})
# 但是在进行转账之前,我们需要先解锁我们的账户,相当于证明这个账户是我们自己的
personal.unlockAccount("0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322")
# 交易创建之后 每笔交易都会写入在区块中,但是需要挖矿才会被确认,所以我们发起了一笔交易,还需要进行挖矿才能使交易成功
miner.start()
miner.stop()
eth.getBalance("0x035bafe05b4a7a4eba9accf2c692785798b7132c") # 1000000000000
到这里,我们就看到了关于区块链的基本操作啦,但是单节点的区块链很明显信任度是不够的,而且单点故障问题也存在,所以我们需要构建一个分布式点对点系统。
搭建联盟链
我们准备在本机中,再启动两个节点,和之前流程一样,先初始化节点,然后去主节点上添加那两个节点(因为我们把自动发现给关闭了,所以我们需要手动去加入,正常是不用的)
# 指定新的数据目录 新的端口
geth --datadir "D:\block\gt\data1" init genesis.json
geth --identity "node1" --datadir "D:\block\gt\data1" --http --http.port 8546 --http.corsdomain="*" --http.addr "0.0.0.0" --http.api "eth,web3,miner,admin,personal,net" --nodiscover --networkid 15 --allow-insecure-unlock --port 30304 --ipcdisable
# 指定新的数据目录 新的端口
geth --datadir "D:\block\gt\data2" init genesis.json
geth --identity "node2" --datadir "D:\block\gt\data2" --http --http.port 8547 --http.corsdomain="*" --http.addr "0.0.0.0" --http.api "eth,web3,miner,admin,personal,net" --nodiscover --networkid 15 --allow-insecure-unlock --port 30305 --ipcdisable
加入其它节点
当启动新的两个节点 console
后,查看 enode
,到 node0
上面去加入 node1
和 node2
的 enode
# node1操作
admin.nodeInfo.enode # enode://5a0e1b6a2c4232a5e774a69a7c660acfa5cb7f573e89e55283c5a438c8d6280539c23cfe68bfdf4873b62da463eae4bc0add8adb9e806e261b875a32b83c7a7c@127.0.0.1:30304?discport=0
# node2操作
admin.nodeInfo.enode # enode://afd9e6d63588bcb070c8245f4c78612c8dd9a57def78aed85e135318397f43bbc01a47fdbb44f990304eefa59bdaae2d91ec5c2190f02bc52d7fdcec26c86a12@127.0.0.1:30305?discport=0
# node0操作
admin.addPeer("enode://afd9e6d63588bcb070c8245f4c78612c8dd9a57def78aed85e135318397f43bbc01a47fdbb44f990304eefa59bdaae2d91ec5c2190f02bc52d7fdcec26c86a12@127.0.0.1:30305?discport=0")
admin.addPeer("enode://5a0e1b6a2c4232a5e774a69a7c660acfa5cb7f573e89e55283c5a438c8d6280539c23cfe68bfdf4873b62da463eae4bc0add8adb9e806e261b875a32b83c7a7c@127.0.0.1:30304?discport=0")
admin.peers # 查看加入的节点
看到如下状态即成功
查看区块同步是否正常
我们通过在 node0
上挖矿,查看其他节点的日志是否处于同步状态,然后在 node1
和 node2
上去查看 node0
里面的账户余额
miner.start()
miner.stop()
看到其他节点都有成功日志
- 在
node0
和node1
查看挖矿账户的余额
# node1
geth attach http://127.0.0.1:8546
web3.fromWei(eth.getBalance("0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322"),'ether') # 85.999998
# node2
geth attach http://127.0.0.1:8547
web3.fromWei(eth.getBalance("0x9c0e89ab86f0874e9977f89c64e2eb6bfd981322"),'ether') # 85.999998
通过 Metamask 在联盟链中转账
我们通过下面流程进行操作:
- 在
metamask
中添加我们的测试网络 - 导入我们之前创建的挖矿账户,在
node2
中创建一个账户,然后通过metamask
进行转账 - 然后挖矿查看结果
添加测试网络
利用 metamask 转账
去 node0
的数据目录中,找到 keystore
,里面都是账户的 json
文件,找到我们的矿工账户文件
去 metamask 中进行导入,输入创建账户时的密码
点击确定之后,可能会出现卡顿,过几分钟重新打开,会发现账户已经导入成功
node2中创建账户
geth attach http://127.0.0.1:8547
personal.newAccount() # "0xc1864e1f2b262ef89228eb1ebde9be6a6165cbe7"
使用 metamask 向地址转账
挖矿确认这笔交易
miner.start()
miner.stop()
成功,查询一下余额
web3.fromWei(eth.getBalance("0xc1864e1f2b262ef89228eb1ebde9be6a6165cbe7"),'ether') # 20
踩坑
- Erro starting protocol stack:Access is denied
增加参数 --ipcdisable
,禁用 ipc
- 为什么我使用了
admin.addPeer
加入了正确的enode
,而且结果也返回了true
,通过admin.peers
还是看不到加入的节点呢?
这个原因很简单,因为其他节点的初始化与主节点不一致,例如,忘记执行 init
步骤了,或者 init
选择的配置不一致,一定要保证和主节点初始化启动保持一致
- Error: The method personal_newAccount does not exist/is not available
--http.api
没有开启 personal
模块
总结
本章,我们搭建了私有联盟链,利用 metamask
进行操作,这个系统我们需要保留下来,之后可以用来部署合约,发布 ERC
系列货币,深入研究区块链原理和结构。