3

玩转Web3:Geth搭建联盟链

 2 years ago
source link: https://aoppp.com/wan-zhuan-web3-gethda-jian-lian-meng-lian/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

玩转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 网络操作

我们主要了解 mineradmin以及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 上面去加入 node1node2enode

# 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 上挖矿,查看其他节点的日志是否处于同步状态,然后在 node1node2 上去查看 node0 里面的账户余额

miner.start()
miner.stop()

看到其他节点都有成功日志

  • node0node1 查看挖矿账户的余额
# 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 网络操作

我们主要了解 mineradmin以及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 上面去加入 node1node2enode

# 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 上挖矿,查看其他节点的日志是否处于同步状态,然后在 node1node2 上去查看 node0 里面的账户余额

miner.start()
miner.stop()

看到其他节点都有成功日志

成功

  • node0node1 查看挖矿账户的余额
# 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 系列货币,深入研究区块链原理和结构。

本文为作者原创或转载,允许转载,由憧憬在 aoppp.com发布 转载请说明文章出处。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK