Logo
新用户订阅 RPC,首月享 6.5 折优惠查看优惠
OnFinality Learn
网络与协议指南阅读约 11 分钟

如何创建区块链链:从创世块到可验证的本地网络

一套可复现的工作流程,用于创建你自己的 EVM 兼容区块链链,涵盖创世配置、节点启动、RPC 验证和故障排除。

TL;DR

创建区块链链意味着定义创世状态、就共识和网络参数达成一致、运行至少一个节点,并通过 JSON-RPC 证明链可以正常工作。本指南使用创世 JSON、节点配置和验证脚本,逐步演示一套可复现的 EVM 兼容搭建流程。它将有文档记录的客户端行为与你应当自行运行的测量区分开来,并说明当链离开你的笔记本电脑后,托管 RPC 层适合放在哪里。最终你将拥有一条可以查询的链、一套验证方法,以及一份针对最常阻碍首次启动的故障的排查清单。

创建链实际上涉及什么

区块链链不是单个文件或单条命令。它是一组约定参数(链 ID、创世状态、共识规则、分叉时间表)、一组各自验证这些参数的节点,以及一个在节点之间传播区块的点对点网络。创建链意味着定义该约定,然后运行强制执行该约定的软件。

本文聚焦于 EVM 兼容链,因为相关工具文档齐全且易于验证。同样的思维模型也适用于非 EVM 链:定义创世块、配置节点、启动节点,并通过链的原生 RPC 接口进行验证。如果你只需要连接到现有网络而不是创建新网络,端点选择的工作属于 RPC Assistant;本页专注于创建和验证工作流程。

  • 创世块:初始状态和全链参数。
  • 共识:区块如何产生和最终确定。
  • 节点配置:数据目录、端口、对等节点和 RPC 暴露。
  • 验证:证明链能正确响应标准调用。

前提条件和假设

你需要一台安装了 Docker 或原生 EVM 客户端的机器、一个空闲的本地端口范围,以及基本的命令行操作能力。下面的示例使用 RPC_URL 和 PRIVATE_KEY 等占位符;切勿将真实密钥提交到代码仓库。对于生产或共享网络,应规划专用基础设施而非笔记本电脑,并在公开暴露任何内容之前查看专用节点选项。

假设:你首先构建的是私有链或测试链,你控制所有初始验证者,并且在链经过独立审查之前不会桥接真实资产。创建链很简单;安全地运营一条链才是更难的问题。

定义创世文件

创世文件是新链的信任根。每个节点必须使用字节完全相同的创世文件,否则节点会拒绝彼此的区块。至少需要定义链 ID、初始账户余额、Gas 上限和共识配置。下面的示例是一个最小的开发用创世块;请将分配地址替换为你控制的地址。

将创世文件纳入版本控制并记录其哈希值。当你之后更改共识或分叉参数时,实际上是在创建一条新链,因此应将这些更改视为破坏性变更。

{
  "config": {
    "chainId": 1337,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "berlinBlock": 0,
    "londonBlock": 0,
    "clique": { "period": 5, "epoch": 30000 }
  },
  "difficulty": "0x1",
  "gasLimit": "0x1c9c380",
  "alloc": {
    "0x0000000000000000000000000000000000000001": {
      "balance": "0xde0b6b3a7640000"
    }
  }
}

配置并启动第一个节点

定义创世块后,初始化节点的数据目录,并仅在 localhost 上启用 RPC 来启动它。具体标志取决于你的客户端;模式是一致的:指向创世文件、设置数据目录、启用你需要的 HTTP RPC 命名空间,并在验证链之前限制主机绑定。

下面的命令使用通用客户端二进制名称作为占位符。请替换为你安装的二进制文件,并对照该客户端的文档确认标志名称,因为不同客户端和版本的标志有所不同。

# Initialize the data directory with the genesis file
your-client init --datadir ./chain-data genesis.json

# Start the node with local-only RPC
your-client \
  --datadir ./chain-data \
  --networkid 1337 \
  --http \
  --http.addr 127.0.0.1 \
  --http.port 8545 \
  --http.api eth,net,web3 \
  --mine \
  --miner.etherbase 0x0000000000000000000000000000000000000001

通过 JSON-RPC 验证链

只有当链能响应标准调用时,它才真正存在。使用 curl 确认链 ID,然后确认区块正在产生。将 RPC_URL 设置为你的本地端点,例如 http://127.0.0.1:8545。这些调用是只读的,可以安全地重复执行。

预期结果是链 ID 与你的创世块匹配,并且区块号随时间增加。如果链 ID 错误,说明你的节点读取了不同的创世块。如果区块号保持为零,说明区块生产未运行。

curl -s -X POST "$RPC_URL" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'

curl -s -X POST "$RPC_URL" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"eth_blockNumber","params":[]}'

可重复的测量流程

不要相信单次成功的调用。运行一个短脚本,随时间对链进行采样并记录结果。下表是一个模板:填入你自己运行中观察到的值,而不是从其他地方复制数字。这能保持验证的诚实性和可复现性。

检查项方法预期观察值
链身份eth_chainId与创世块 chainId 匹配(记录)
区块生产两次采样 eth_blockNumber第二个值更大(记录)
对等节点数net_peerCount多节点时至少为 1(记录)
RPC 延迟定时 curl 循环稳定,无超时(记录)

下面的 JavaScript 代码片段自动化了采样过程。它使用现代 Node.js 中内置的 fetch,并写入简单的通过/失败摘要。将 RPC_URL 替换为你的端点。

const RPC_URL = process.env.RPC_URL;

async function call(method, params = []) {
  const res = await fetch(RPC_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params })
  });
  const json = await res.json();
  if (json.error) throw new Error(json.error.message);
  return json.result;
}

(async () => {
  const chainId = await call('eth_chainId');
  const first = await call('eth_blockNumber');
  await new Promise(r => setTimeout(r, 12000));
  const second = await call('eth_blockNumber');
  const advanced = parseInt(second, 16) > parseInt(first, 16);
  console.log({ chainId, first, second, advanced });
})();

添加第二个节点并确认共识

单个节点证明软件可以运行;两个节点证明网络可以工作。使用相同的创世块和网络 ID 启动第二个节点,然后使用第一个节点的 enode URL 将其连接到第一个节点。确认两个节点上的 net_peerCount 都上升,并且两者报告相同的最新区块哈希。

如果第二个节点拒绝区块或始终无法同步,最常见的原因是创世哈希不匹配、网络 ID 不同或防火墙阻止了点对点端口。在调试其他任何内容之前,先比较两台机器上的创世哈希。

排查首次启动故障

创建链时的大多数故障都属于少数几类。按顺序逐一排查,因为一旦修复了较早的原因,后面的症状往往就会消失。

如果节点立即退出,请检查数据目录是否使用正确的创世块初始化,以及二进制文件是否支持你传入的标志。如果 RPC 调用失败,请确认 HTTP 服务器已启用并绑定到你调用的地址。如果区块未产生,请确认挖矿或验证者配置,以及签名账户已解锁或配置正确。

  • 创世块不匹配:节点会静默拒绝对等节点;比较创世哈希。
  • 端口冲突:另一个进程占用了 8545 或 P2P 端口。
  • RPC 命名空间被禁用:方法返回 'method not found'。
  • 时钟偏差:时间戳导致某些共识引擎拒绝区块。
  • 磁盘空间不足:节点停止写入并看似挂起。

局限性与权衡

本地创建的链是开发产物,不是生产网络。它没有经济安全性、没有独立验证者,也没有对运营者故障的恢复能力。迈向生产需要验证者入驻、监控、升级治理以及 RPC 可用性计划。

运行你自己的 RPC 层可以让你掌控,但会增加运营负担:正常运行时间、速率限制和版本升级。许多团队保留自托管节点用于验证,并使用托管服务处理公共读取流量。RPC 端点指南解释了如何考虑这种分工,而 RPC 定价有助于估算服务外部流量的成本。

链运行后的后续步骤

一旦你的链产生区块并且第二个节点同步成功,接下来的工作就是工具和访问。部署一个测试合约、连接一个钱包,并确认日志和收据的行为符合预期。然后决定外部开发者将如何访问该链。

如果你计划将链暴露给其他团队,请查看 API 服务选项和支持的网络列表,以了解托管访问的结构。对于特定端点的建议,请使用 RPC Assistant,而不是猜测公共 URL。将你的创世文件、节点配置和验证脚本放在一起,以便团队中的任何人都可以从头重建该链。

永远不用担心基础设施

OnFinality 消除了 DevOps 的繁重工作,让您能够更聪明、更快地构建。

开始