测试网是一个独立的区块链网络,它足够贴近主网行为,可用于测试合约、钱包、升级和基础设施,而无需冒真实资产的风险。本指南解释了从开发网到测试网再到主网的生命周期,测试代币和水龙头如何运作,以及如何配置和验证测试网 RPC 连接。它还涵盖了常见故障模式、测试网证据的局限性,以及如何自信地将变更晋升到主网。
什么是测试网以及本指南涵盖的内容
测试网是一个独立的区块链网络,运行与其主网对应网络相同的协议规则,但使用没有货币价值的代币。它的存在是为了让开发者能够在任何内容触及生产资金之前部署合约、测试钱包、演练协议升级并对基础设施进行压力测试。测试网上的交易不会影响主网账本,其中的错误是可以恢复的。
本指南面向已经理解基本区块链概念并需要可重复测试网工作流的开发者和基础设施运营者。它涵盖了从开发网到测试网再到主网的生命周期、如何获取测试代币、如何配置测试网 RPC 端点、如何验证部署是否真正落地,以及测试网证据在何处不再可信。具体的端点和提供商选择有意留给 RPC Assistant;本页侧重于方法。
假设与前提条件
以下流程假设你拥有一个已充值的测试网钱包、一个想要执行的合约或交易,以及一个测试网 RPC 端点的访问权限。你不需要特定的提供商即可跟随操作;任何可用的测试网端点都可以,并且你应该将端点 URL 视为配置值,而不是硬编码到项目中的内容。
你还应该知道你要针对哪个测试网。网络通常会运行多个具有不同目的和生命周期的并行测试网,并且测试网可能被弃用或替换。在开始之前,从网络自身的文档中确认当前的测试网名称和链 ID,并将该标识符保留在项目配置中,以免环境混淆。
- 一个测试网钱包地址及其私钥,存储在源代码管理之外
- 通过环境变量(如 RPC_URL)提供的测试网 RPC URL
- 目标链 ID 和测试网的区块浏览器 URL
- 从水龙头获取的少量测试网原生代币
开发网、测试网和主网作为生命周期
大多数团队会经历三个环境。开发网是本地或团队控制的链,用于快速迭代,你可以随意重置状态,区块时间和 Gas 规则可能较为宽松。测试网是一个共享的、面向公众的网络,其行为更像主网:它具有真实的共识、真实的对等节点和真实的延迟,但其代币毫无价值。主网是生产网络,资产具有价值,错误代价高昂。
测试网阶段的价值在于它引入了开发网无法复现的条件。公共测试网让你的代码暴露在真实的区块时间、内存池竞争、RPC 速率限制和其他参与者之下。这使得测试网成为在晋升之前验证部署脚本、Gas 估算、事件索引和监控的正确场所。一个只在开发网上运行过的变更,尚未针对它将在生产环境中遇到的网络条件进行测试。
测试代币和水龙头如何运作
测试网代币由网络自身的规则铸造或分发,不具有市场价值。水龙头是向请求地址发送少量测试网原生代币的服务,以便开发者支付 Gas。由于水龙头是免费的,它们经常受到速率限制、受验证码或账户要求限制,或被自动领取耗尽。将水龙头可用性视为运营依赖,而非保证。
一个实用的习惯是尽早请求测试代币,并在专用的测试网钱包中保留少量储备。如果你的工作流依赖于特定的水龙头,记录你使用了哪个水龙头以及何时使用,以便后续故障可以与代码问题区分开来。永远不要假设测试网代币可以转换为主网代币;它们不能,任何声称相反的服务都是骗局。
配置测试网 RPC 连接
最常见的测试网故障是端点配置错误:客户端指向主网、错误的测试网,或已轮换的 URL。将端点和链 ID 保留在环境变量中,并在启动时断言链 ID。以下 shell 片段在发送任何交易之前检查端点报告的链 ID 是否与你预期的一致。将 RPC_URL 和 EXPECTED_CHAIN_ID 替换为你自己的值。
export RPC_URL="https://your-testnet-endpoint.example"
export EXPECTED_CHAIN_ID="0x0"
ACTUAL_CHAIN_ID=$(curl -s -X POST "$RPC_URL" \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}' \
| python3 -c 'import sys,json; print(json.load(sys.stdin)["result"])')
echo "expected=$EXPECTED_CHAIN_ID actual=$ACTUAL_CHAIN_ID"
[ "$ACTUAL_CHAIN_ID" = "$EXPECTED_CHAIN_ID" ] || { echo "chain ID mismatch"; exit 1; }可运行的部署与验证流程
一旦链 ID 匹配,部署或发送你的交易,然后独立于客户端库的返回值进行验证。交易哈希不是成功的证明;你必须读取收据并确认状态字段。下面的 Python 示例通过测试网 RPC 端点发送签名交易,然后轮询收据。它使用端点、密钥和接收者的占位符。
预期的验证结果是收据的状态等于 1 且区块号大于零。如果多次轮询后收据为 null,交易可能仍在待处理、可能已被丢弃,或可能已发送到你正在查询的网络之外的其他网络。始终在你发送时使用的同一链 ID 上确认收据。
import os, time, json, urllib.request
RPC_URL = os.environ["RPC_URL"]
PRIVATE_KEY = os.environ["PRIVATE_KEY"] # never commit this
TO_ADDRESS = os.environ["TO_ADDRESS"]
def rpc(method, params):
body = json.dumps({"jsonrpc":"2.0","id":1,"method":method,"params":params}).encode()
req = urllib.request.Request(RPC_URL, data=body, headers={"Content-Type":"application/json"})
with urllib.request.urlopen(req, timeout=30) as resp:
payload = json.load(resp)
if "error" in payload:
raise RuntimeError(payload["error"])
return payload["result"]
# Build and sign the transaction with your preferred library, then:
tx_hash = rpc("eth_sendRawTransaction", ["0xSIGNED_TX_HEX"])
print("submitted", tx_hash)
for attempt in range(30):
receipt = rpc("eth_getTransactionReceipt", [tx_hash])
if receipt is not None:
print("status", receipt["status"], "block", int(receipt["blockNumber"], 16))
assert receipt["status"] == "0x1", "transaction reverted"
break
time.sleep(2)
else:
raise TimeoutError("no receipt after polling; check network and nonce")记录结果以便测试可复现
测试网运行只有在其他人可以重复时才有用。记录链 ID、RPC 端点主机(不是完整的秘密 URL)、合约地址、交易哈希以及每个步骤观察到的收据状态。将这些与受测代码的提交哈希一起存储在运行日志中。当后续运行失败时,日志可以让你将代码回归与基础设施或水龙头问题区分开来。
下表是模板,不是测量数据。从你自己的运行中填写;不要从其他环境复制值。
- | 字段 | 示例占位符 | 备注 |
- | 链 ID | EXPECTED_CHAIN_ID | 必须与端点匹配 |
- | RPC 主机 | your-testnet-endpoint.example | 记录主机,而非凭证 |
- | 合约地址 | 0xCONTRACT | 来自部署输出 |
- | 交易哈希 | 0xTXHASH | 每笔交易一行 |
- | 收据状态 | 0x1 或 0x0 | 0x1 表示成功 |
- | 区块号 | 十进制 | 确认包含 |
排查常见的测试网故障
大多数测试网问题属于少数几类。链 ID 不匹配意味着你查询的网络与你发送的网络不同。资金不足通常意味着水龙头没有交付或储备已用完。Nonce 错误意味着之前的交易卡住或从同一密钥在另一条链上发送。公共端点的速率限制表现为 HTTP 429 响应或负载下的间歇性超时。
对于每个故障,在更改代码之前确认层。重新运行链 ID 检查,查询发送者余额,并获取交易计数以与你预期的 nonce 比较。如果问题是端点,切换到托管提供商,而不是围绕不稳定的公共节点进行调试;RPC Assistant 可以帮助你选择支持测试网的端点,多链 RPC 端点指南解释了如何在一个项目中构建多个网络。
- 链 ID 不匹配:重新检查 RPC_URL 和 EXPECTED_CHAIN_ID
- 资金不足:确认水龙头交付并保留储备
- Nonce 过低或过高:将 eth_getTransactionCount 与本地 nonce 比较
- 超时或 429:迁移到托管端点并添加带退避的重试
- 收据为 null:确认交易已广播到你正在轮询的同一条链
测试网证据的局限性与权衡
通过的测试网运行是强有力的证据,但不是证明。测试网通常具有较少的验证者数量、不同的 Gas 市场和比主网更少的对抗性流量,因此性能和安全结论不能直接转移。测试网状态也可能被重置或网络被弃用,这意味着长期存在的测试夹具很脆弱。将测试网结果视为一道关卡,而非保证。
还有成本权衡。公共测试网端点免费但受速率限制且偶尔不稳定;托管端点花钱但提供可预测的吞吐量和支持。对于一次性合约检查,公共端点通常足够。对于每次提交都部署的 CI 管道,具有文档化限制的托管端点通常是更可靠的选择。在将管道提交给提供商之前,查看 RPC 定价选项。
将变更从测试网晋升到主网
晋升应该是一个有自己检查清单的刻意步骤。以试运行模式针对主网配置重新运行部署脚本,确认链 ID 和 Gas 设置,并验证没有引用任何测试网地址或密钥。将测试网运行日志附加到发布记录中,以便审查者可以看到实际执行了什么。
晋升后,密切监控首批交易,并将其行为与测试网运行进行比较。如果你运营自己的基础设施,专用节点可以在晋升窗口期间让你控制端点。对于需要并排比较多个网络的团队,网络目录列出了支持的链及其测试网可用性。
- 确认主网链 ID 并移除所有测试网默认值
- 试运行部署并审查差异
- 将测试网运行日志附加到发布记录
- 根据预期行为监控首批主网交易
后续步骤
首先标准化你的测试网配置:每个网络一个环境文件、启动时链 ID 断言和运行日志模板。然后自动化收据检查,以便失败的交易无法静默通过 CI。如果你仍在选择端点,使用 RPC Assistant 获取具体建议,并阅读 RPC 端点指南了解通用配置模式。对于运行自己基础设施的团队,区块链节点托管指南涵盖了运营方面。