目录

区块链学习 1 - 基于 Geth 搭建私链

最近申请了一张 U 卡,基于 USDC 进行充值,然后提现到 U 卡进行消费。这让我想起了 19 年挖过人人影视的 CVNT 币,当时也是可以闪兑成 ETH 的。

当时好奇 ETH 的原理,但没有现在学习这么方便(有 AI 加成),一直想搭建私链却没成功,后来在 ETH 的测试链上玩了一段时间(主要想体验一下转账、发币等)。现在各种开源工具非常丰富,技术也趋于成熟,所以决定自己搭建一个私链来研究一下。

其次的目的就是想学习区块链实战,例如如何让业务系统的关键数据上链,如:交易(hash)、文章防伪(hash)、存证(hash)等。

本文基于 Geth 搭建以太坊私链,选择它的理由如下:

  • 官方支持:以太坊官方参考实现
  • 生态完善:支持 EVM、Solidity、MetaMask、ethers.js
  • 场景灵活:公链 / 私链 / 离线私链均可运行
  • 资源丰富:文档齐全,社区活跃

准备工作

  • 运行环境:Windows 10 + PowerShell。如果是 Linux 环境,只需自行配置环境变量并微调命令格式即可,差异不大。
  • 共识机制:Clique PoA。

1. 下载 Geth

下载 Geth 1.13.X 版本,本文使用的是 1.13.15 版本。

[!IMPORTANT] 版本注意:1.13.x 之后的版本不再支持 PoA/PoW 这种“传统执行层单机共识”链。它要求 PoS(合并后)网络,否则你会看到如下报错:

ERROR[01-17|18:18:27.324] Geth only supports PoS networks. Please transition legacy networks using Geth v1.13.x.

2. 安装与配置

  • 解压并安装到特定目录,设置好环境变量
  • 准备私链目录结构,例如我的路径是 E:\geth\geth-ledger

后续所有命令均在此目录下执行。在文件夹内使用 SHIFT + 右键,选择“在此处打开 PowerShell 窗口”。

创建账户

我们需要创建 2 个账户:一个用于出块,一个用于转账测试。

  1. 出块者:负责签块(PoA)。
  2. 转账者:负责转账(用于体验,创世时会分配 1000 个 ETH)。
geth --datadir data account new
geth --datadir data account new

返回数据示例

Public address of the key:   0x2F02cA3b39C3e86566246489787F37C0453888A2
Path of the secret key file: data\keystore\UTC--2026-01-17T09-27-07.047721600Z--2f02ca3b39c3e86566246489787f37c0453888a2

- 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!
  • 执行后会提示输入密码,请务必牢记!
  • 目录下会生成一个 keystore 文件,里面存储了加密后的私钥。

保存密码到文件

为了方便后续启动,我们将密码保存到文件中(请妥善保管):

PowerShell (Windows)

Set-Content -Path .\miner.pass -Value "miner_password" -NoNewline -Encoding ASCII
Set-Content -Path .\biz.pass -Value "biz_password" -NoNewline -Encoding ASCII

Bash (Linux)

echo "miner_password" > miner.pass
echo "biz_password" > biz.pass

在本教程中,我的地址分配如下:

  • 出块者地址 (miner): 0x2F02cA3b39C3e86566246489787F37C0453888A2
  • 转账者地址 (biz): 0xe8aCb15b1d4dB40292B10C8169d369dff180C2f9

创建 genesis.json 文件

这是 Clique (PoA) 私链的创世块配置文件。

{
  "config": {
    "chainId": 202601,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "clique": { 
      "period": 2, 
      "epoch": 30000 
    }
  },
  "nonce": "0x0",
  "timestamp": "0x0",
  "extraData": "0x00000000000000000000000000000000000000000000000000000000000000002f02ca3b39c3e86566246489787f37c0453888a2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "gasLimit": "0x2FAF080",
  "difficulty": "0x1",
  "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x0000000000000000000000000000000000000000",
  "alloc": {
    "0xe8aCb15b1d4dB40292B10C8169d369dff180C2f9": { "balance": "0x3635C9ADC5DEA00000" }

带注释版本:

{
  "config": {
  // 链ID:用于交易签名防重放;与你的 networkid 不强制相等,但通常保持一致更清晰
    "chainId": 202601, // 链ID,必须唯一,不能和主网、测试网冲突

    // 下面这些 *Block=0 表示:从创世块开始就启用对应的硬分叉规则
    // 好处:规则一致、少踩坑;坏处:没什么坏处(私链推荐这样写)
    "homesteadBlock": 0, // 升级到 Homestead 协议的区块高度
    "eip150Block": 0, // 升级到 EIP150 协议的区块高度
    "eip155Block": 0, // 升级到 EIP155 协议的区块高度
    "eip158Block": 0, // 升级到 EIP158 协议的区块高度
    "byzantiumBlock": 0, // 升级到 Byzantium 协议的区块高度
    "constantinopleBlock": 0, // 升级到 Constantinople 协议的区块高度
    "petersburgBlock": 0, // 升级到 Petersburg 协议的区块高度
    "istanbulBlock": 0, // 升级到 Istanbul 协议的区块高度
    "clique": { "period": 2, "epoch": 30000 } // Clique 共识机制配置
  },
  "nonce": "0x0", // 随机数,用于挖矿
  "timestamp": "0x0", // 时间戳,创世区块时间
  "extraData": "0x00000000000000000000000000000000000000000000000000000000000000002f02ca3b39c3e86566246489787f37c0453888a2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", // 额外数据,包含出块者地址
  "gasLimit": "0x2FAF080", // 创世区块的 Gas 上限
  "difficulty": "0x1", // 创世区块的难度
  "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", // 混合哈希
  "coinbase": "0x0000000000000000000000000000000000000000", // 创世区块的矿工地址
  "alloc": { // 创世区块的预分配账户
    "0xe8aCb15b1d4dB40292B10C8169d369dff180C2f9": { "balance": "0x3635C9ADC5DEA00000" } // 预分配1000个ETH
  }
}

更详细查看genesis.json 详解

初始化链

只用执行一次,除非你想重置。

geth --datadir data init genesis.json

执行后,会在运行目录下生成 data 生成相关文件。

启动 signer 节点(PowerShell)

geth `
 --datadir data `
 --networkid 202601 `
 --http --http.addr 0.0.0.0 --http.port 8545 `
 --http.api eth,net,web3,txpool,admin `
 --http.corsdomain "*" --http.vhosts "*" `
 --allow-insecure-unlock `
 --unlock 0x2F02cA3b39C3e86566246489787F37C0453888A2 --password miner.pass `
 --mine --miner.etherbase 0x2F02cA3b39C3e86566246489787F37C0453888A2 `
 --txpool.pricelimit 0

带注释版本:

# 使用 PowerShell 的反引号 ` 作为换行续写符
geth `
  # 指定区块数据、状态数据、keystore 的存放目录
  # 不写的话默认是 ~/.ethereum
  # 私链/多链并行时一定要显式指定
  --datadir data `

  # 网络 ID(P2P 层用)
  # 必须与 genesis.json 中的 chainId 区分理解
  # networkid 用来防止节点连错网络
  --networkid 202601 `

  # 开启 HTTP RPC 服务(旧称 JSON-RPC)
  # 业务系统、脚本、控制台通常都通过它与 geth 交互
  --http `
  # HTTP RPC 监听地址
  # 0.0.0.0 表示对外暴露(局域网/容器/宿主机可访问)
  --http.addr 0.0.0.0 `
  # HTTP RPC 监听端口(以太坊传统默认 8545)
  --http.port 8545 `

  # 允许通过 HTTP RPC 调用的 API 模块
  # eth    : 区块、交易、合约相关核心接口
  # net    : 网络信息(networkId、peer 数等)
  # web3   : 工具类接口(编码、hash 等)
  # txpool : 交易池状态(pending / queued)
  # admin  : 节点管理(peers、enode、addPeer 等,生产环境要谨慎)
  --http.api eth,net,web3,txpool,admin `

  # 允许任意来源的跨域请求(CORS)
  # 方便浏览器、前端、内部系统直接访问
  --http.corsdomain "*" `
  # 允许任意 Host 头访问 HTTP RPC
  # 在 Docker / 反向代理 / 内网环境中很常见
  --http.vhosts "*" `

  # 允许通过 RPC 解锁账户(非常危险的能力)
  # 在私链、内网、测试环境中常用
  # 生产环境一般禁用
  --allow-insecure-unlock `

  # 启动时解锁指定账户
  # 该账户通常是:
  # - Clique 的 signer(出块账户)
  # - 或业务服务用于发送交易的账户
  --unlock 0x2F02cA3b39C3e86566246489787F37C0453888A2 `
  # 解锁账户所使用的密码文件
  # 文件内容是纯文本密码
  --password miner.pass `

  # 开启挖矿(在 Clique 中含义是:参与出块/签名)
  # 如果不加这个参数,节点只同步,不会出块
  --mine `
  # 指定出块收益地址 / 签名者地址
  # 在 Clique 中通常与 --unlock 的账户相同
  --miner.etherbase 0x2F02cA3b39C3e86566246489787F37C0453888A2 `

  # 设置交易池最低 gas price
  # 0 表示:接受所有交易(即使 gasPrice = 0)
  # 私链里非常常见,避免“没钱发不了交易”
  --txpool.pricelimit 0

此时要是没有错误,输出类似:

INFO [01-19|22:37:23.582] Maximum peer count                       ETH=50 total=50
WARN [01-19|22:37:23.600] Lowering memory allowance on 32bit arch  available=65460 addressable=2048
WARN [01-19|22:37:23.600] Sanitizing cache to Go's GC limits       provided=1024 updated=682
INFO [01-19|22:37:23.600] Set global gas cap                       cap=50,000,000
INFO [01-19|22:37:23.602] Initializing the KZG library             backend=gokzg
INFO [01-19|22:37:23.687] Allocated trie memory caches             clean=102.00MiB dirty=170.00MiB
INFO [01-19|22:37:23.688] Using pebble as the backing database
INFO [01-19|22:37:23.688] Allocated cache and file handles         database=E:\geth\geth-ledger\data\geth\chaindata cache=341.00MiB handles=8192
INFO [01-19|22:37:23.944] Opened ancient database                  database=E:\geth\geth-ledger\data\geth\chaindata\ancient/chain readonly=false
INFO [01-19|22:37:23.945] State scheme set to already existing     scheme=hash
INFO [01-19|22:37:23.949] Initialising Ethereum protocol           network=202,601 dbversion=8

INFO [01-19|22:37:54.864] Looking for peers                        peercount=0 tried=22 static=0
INFO [01-19|22:37:56.005] Successfully sealed new block            number=29638 sealhash=8f8d95..7a6364 hash=867994..fb1bd1 elapsed=2.000s
INFO [01-19|22:37:56.005] Commit new sealing work                  number=29639 sealhash=7be5a2..646ead txs=0 gas=0 fees=0 elapsed=0s
INFO [01-19|22:37:58.005] Successfully sealed new block            number=29639 sealhash=7be5a2..646ead hash=76321e..2e22ae elapsed=1.999s
INFO [01-19|22:37:58.005] Commit new sealing work                  number=29640 sealhash=1c9f2d..35c595 txs=0 gas=0 fees=0 elapsed="27.2µs"
INFO [01-19|22:38:00.004] Successfully sealed new block            number=29640 sealhash=1c9f2d..35c595 hash=53ecc6..63b509 elapsed=1.999s
INFO [01-19|22:38:00.004] Commit new sealing work                  number=29641 sealhash=2b4a8a..d9688c txs=0 gas=0 fees=0 elapsed=0s

那就代表出快了。

验证测试

浏览器安装MetaMask扩展

到各自浏览器的扩展商店搜索MetaMask并安装。

导入钱包

在MetaMask中点击“添加钱包”,类型选择“JSON文件”(选择biz账户,里面有我们分配的1000ETH)

https://s3.aixfan.com/img/screenshot/2026/01/19/1768834715_114b.png

选择刚才生成的keystore文件,输入密码,等待1-5分钟即可导入成功。

https://s3.aixfan.com/img/screenshot/2026/01/19/1768834715_114b.png

配置MetaMask连接到私链

此时导入的钱包并没有ETH,我们需要在 MetaMask 切换到本地网络。

网络名称:本地测试网络
新 RPC URL:http://localhost:8545
链 ID:202601
货币符号:ETH(随意)

https://s3.aixfan.com/img/screenshot/2026/01/19/1768834148_104b.png https://s3.aixfan.com/img/screenshot/2026/01/19/1768834169_106b.png https://s3.aixfan.com/img/screenshot/2026/01/19/1768834204_108b.png

选择本地测试网络

https://s3.aixfan.com/img/screenshot/2026/01/19/1768834524_112b.png

这时,就能看见1000ETH了。(我已经用了一些) https://s3.aixfan.com/img/screenshot/2026/01/19/1768834975_118b.png

发送交易

https://s3.aixfan.com/img/screenshot/2026/01/19/1768835130_120b.png https://s3.aixfan.com/img/screenshot/2026/01/19/1768835155_122b.png

可以临时转到第一步生成的出块者地址,当然,你也可以再创建一个钱包测试。

这里,我的数量输入 10。

https://s3.aixfan.com/img/screenshot/2026/01/19/1768835204_124b.png

点击发送,MetaMask 会弹出确认窗口。这里可以更改燃料价格,因为我们在启动时设置了参数pricelimit,所以可以为 0。

燃料限制为ETH内置常量(这是怎么计算的,查看详情) https://s3.aixfan.com/img/screenshot/2026/01/19/1768835303_126b.png

https://s3.aixfan.com/img/screenshot/2026/01/19/1768835319_128b.png https://s3.aixfan.com/img/screenshot/2026/01/19/1768835341_130b.png https://s3.aixfan.com/img/screenshot/2026/01/19/1768835355_131b.png

验证交易

此时,可以用MetaMask导入收币的钱包,变能看见余额增加了。

下一节,部署合约,让业务系统的业务数据上链。

编写中……

此篇内容仅为搭建记录,其中关于很多名词,我放在WIKI中了,避免污染格式。如有兴趣,可以去WIKI查看。