1. 为什么要构建私链?

构建私链有多个理由,主要包括:

  1. 数据隐私与安全性
    • 控制数据访问:私链允许组织对谁可以访问和参与区块链网络进行控制,从而保护敏感数据。
    • 防止恶意行为:与公链相比,私链更容易限制恶意攻击,因为只有经过授权的参与者才能加入。
  2. 高性能与可扩展性
    • 快速交易处理:由于参与者数量较少,私链通常可以处理更高的交易速度,减少交易确认时间。
    • 定制化配置:可以根据特定需求优化网络参数(如区块生成时间、共识算法等)。
  3. 定制化特性
    • 灵活性:可以根据组织的需求定制共识机制、合约功能和网络架构,适应特定的业务场景。
    • 专有协议:可实现专门的协议或应用,与公链的标准化和限制不同。
  4. 合规性与监管
    • 满足合规要求:私链能够帮助企业遵循行业法规和标准,比如金融行业的合规要求。
    • 审计和监管:能够更容易地实施审计和监控机制,确保遵循法律和规定。
  5. 低成本与资源优化
    • 资源节省:在私链中,通常只需要维护少量的节点,减少了硬件和网络带宽的需求。
    • 控制网络费用:由于没有激励机制(如矿工奖励),运营成本通常较低。
  6. 业务合作与联盟链
    • 跨组织协作:私链可用于多个组织之间的合作,尤其是在供应链管理和金融交易中。
    • 联盟链:可以构建联盟链,让特定合作伙伴共同参与,确保数据的透明性和可追溯性。
  7. 测试与开发:开发人员可以在私链上进行测试,验证智能合约和应用程序的功能,而不必担心对公共网络的影响。

2. 构建基于PoA的ethereum私链

2.1 创建账户

创建两个账户,分别为account 1account 2,用做初始的验证者地址。

# node
# account 1
$ geth --datadir ./node account new
INFO [09-27|09:40:38.644] Maximum peer count                       ETH=50 total=50
INFO [09-27|09:40:38.645] Smartcard socket not found, disabling    err="stat /run/pcscd/pcscd.comm: no such file or directory"
Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:

Your new key was generated

Public address of the key:   0x51C4d2FeEBBAd01c2202d7CE772de1D953571201
Path of the secret key file: node/keystore/UTC--2024-09-27T01-40-44.544853516Z--51c4d2feebbad01c2202d7ce772de1d953571201

- You can share your public address with anyone. Others need it to interact with you.
- You must NEVER share the secret key with anyone! The key controls access to your funds!
- You must BACKUP your key file! Without the key, it's impossible to access account funds!
- You must REMEMBER your password! Without the password, it's impossible to decrypt the key!

# account 2
$ geth --datadir ./node account new
INFO [09-27|09:41:29.078] Maximum peer count                       ETH=50 total=50
INFO [09-27|09:41:29.079] Smartcard socket not found, disabling    err="stat /run/pcscd/pcscd.comm: no such file or directory"
Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:

Your new key was generated

Public address of the key:   0x19Eac074dba9BBa2Eb97FFE7BBA80A9E9E83EcBe
Path of the secret key file: node/keystore/UTC--2024-09-27T01-41-34.412585202Z--19eac074dba9bba2eb97ffe7bba80a9e9e83ecbe

- You can share your public address with anyone. Others need it to interact with you.
- You must NEVER share the secret key with anyone! The key controls access to your funds!
- You must BACKUP your key file! Without the key, it's impossible to access account funds!
- You must REMEMBER your password! Without the password, it's impossible to decrypt the key!

2.2 创建创世区块

配置创世区块的配置文件genesis.json,内容如下:

{
    "config": {
        "chainId": 377777,
        "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": "0x000000000000000000000000000000000000000000000000000000000000000051C4d2FeEBBAd01c2202d7CE772de1D95357120119Eac074dba9BBa2Eb97FFE7BBA80A9E9E83EcBe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "alloc": {
        "51C4d2FeEBBAd01c2202d7CE772de1D953571201": {
            "balance": "100000000000000000000"
        },
        "19Eac074dba9BBa2Eb97FFE7BBA80A9E9E83EcBe": {
            "balance": "100000000000000000000"
        }
    }
}

初始验证者地址必须通过extradata字段指定。

$ geth --datadir ./node init ./genesis.json

2.3 启动节点

创世区块创建后,就可以启动私链节点了。

# networkid 是genesis.json中指定的chainId
$ geth --datadir ./node --networkid 377777 

2.4 进入 Geth 控制台测试

$ geth attach ./node/geth.ipc
Welcome to the Geth JavaScript console!

instance: Geth/v1.13.15-stable-c5ba367e/linux-amd64/go1.22.7
at block: 1 (Fri Sep 27 2024 10:01:07 GMT+0800 (CST))
 datadir: /root/vscode/ethereum/node
 modules: admin:1.0 clique:1.0 debug:1.0 engine:1.0 eth:1.0 miner:1.0 net:1.0 rpc:1.0 txpool:1.0 web3:1.0

To exit, press ctrl-d or type exit
# 获取最新区块高度
> eth.blockNumber
1
# 获取最新区块信息
> eth.getBlock('latest')
{
  difficulty: 2,
  extraData: "0xd883010d0f846765746888676f312e32312e39856c696e757800000000000000ebcda637df33928e4ce34051f777ccac21c643a8dcd1984b019984af41d99d5c41ff73559c837b0204c7764c71d8b5b49ecf63a555ee127e3d0cc86673d3214100",
  gasLimit: 8007811,
  gasUsed: 0,
  hash: "0xe4c14eb995dbcc9652a53fa8d47402dead30fa82af57b11399f9db23b06ab78b",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x0000000000000000000000000000000000000000",
  mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  nonce: "0x0000000000000000",
  number: 1,
  parentHash: "0xb2ad7555b68d5c1e334d44033ef78c869fa4248a64a976a172318126a3db55a7",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 606,
  stateRoot: "0xc5f02ccb91cfbde9f92912bb02aac9b2601e9a6e41ea9335343fa1991d277a5a",
  timestamp: 1727402467,
  totalDifficulty: 3,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}
# 获取账户余额
> eth.getBalance("0x51C4d2FeEBBAd01c2202d7CE772de1D953571201")
100000000000000000000
> eth.getBalance("0x19Eac074dba9BBa2Eb97FFE7BBA80A9E9E83EcBe")
100000000000000000000
# 获取账户列表
> eth.accounts
["0x51c4d2feebbad01c2202d7ce772de1d953571201", "0x19eac074dba9bba2eb97ffe7bba80a9e9e83ecbe"]

curl 命令测试:

# 获取最新区块高度,result 为十六进制字符串
$ curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' http://localhost:8545
{"jsonrpc":"2.0","id":1,"result":"0x1"}
# 获取账户余额
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x19Eac074dba9BBa2Eb97FFE7BBA80A9E9E83EcBe","latest"],"id":1}' http://localhost:8545
{"jsonrpc":"2.0","id":1,"result":"0x56bc75e2d63100000"}

3. 扩展:extradata 字段介绍

extradata 字段是以太坊区块头的一部分,主要用于 Proof of Authority (PoA) 共识机制(如 Clique)。它包含特定的信息,以便于节点之间的共识和验证。以下是对 extradata 字段的详细介绍:

3.1 功能

  • 签名者信息extradata 通常包含当前区块的签名者(或验证者)地址。这些地址是网络中被授权生成区块的节点。
  • 额外元数据:在某些情况下,可以包括其他自定义信息,如版本号或链的特定参数。

3.2 格式

extradata 是一个字节数组,其结构通常如下:

  • 32个零字节:用于预留空间。
  • 签名者地址:包含网络中所有签名者的地址,每个地址占 20 字节(40 个十六进制字符)。
  • 65个零字节:用于填充,确保 extradata 的总字节长度符合要求。

3.3 示例

假设你有三个签名者地址,extradata 的构建步骤如下:

  1. 32个零字节(在十六进制表示为):
    0000000000000000000000000000000000000000000000000000000000000000
    
  2. 签名者地址
    0xD22688d01E3345Cc2911C95447a3a1bcE32CB741
    0x9A265B5Ef402813ae057e53f12D2B19d9aA5CEb4
    0x843D259ab8C380FA576Cb013503CF961B63d12BB
    
  3. 65个零字节
    00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    
  4. 拼接结果
    0x0000000000000000000000000000000000000000000000000000000000000000D22688d01E3345Cc2911C95447a3a1bcE32CB7419A265B5Ef402813ae057e53f12D2B19d9aA5CEb4843D259ab8C380FA576Cb013503CF961B63d12BB00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    

4. 使用场景

  • 共识机制:在 PoA 网络中,extradata 用于确定哪个节点在某一时刻被授权生成新区块。
  • 数据完整性:由于 extradata 是区块头的一部分,确保了与块的其他信息一起传递,增强了数据的完整性和一致性。

5. 注意事项

  • 字节长度:确保 extradata 的字节长度符合预期,错误的格式可能导致链启动失败。
  • 动态更新:在网络运行过程中,可以使用相应的 API 更新签名者信息,确保网络的正常运作。

孟斯特

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。

Author: mengbin

blog: mengbin

Github: mengbin92

cnblogs: 恋水无意

腾讯云开发者社区:孟斯特