按 EIP-1474 调用 Ethereum JSON-RPC 时如何正确编码 Quantity 与 Data 参数?
【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs
EIP-1474(Remote procedure call specification)为标准 Ethereum RPC 接口定义了两类必须特殊编码的值:Quantity与Data。当你用脚本或程序直接调用 Ethereum 节点的 JSON-RPC 端点时,块号、gas、value、gasPrice 等字段按Quantity编码,地址、哈希、合约调用数据等字段按Data编码;两者规则不同,编码写错会被节点以参数错误拒绝。本文依据 EIP-1474 正文和它引用的 EIP-1898,给出两条编码规则、逐条自检表,以及一条完整的curl调用与结果判定路径。
适用前提:你已有可访问的 Ethereum 节点 RPC 端点。EIP 文档中的命令统一用<url>占位,执行前需替换为你自己的节点端点地址;替换方式在首次出现时说明,后文不再重复。另请注意 EIP-1474 的 frontmatter 中状态为Stagnant,本文只描述该 EIP 明确规定的行为。
JSON-RPC 请求的形状
按 EIP 的规定,Ethereum RPC 方法 MUST 使用 JSON-RPC request object 发起调用,MUST 以 JSON-RPC response object 响应。文档给出的调用形式是curl发送 POST 请求:
curl -X POST --data '{ "id": 1337, "jsonrpc": "2.0", "method": "eth_getBalance", "params": ["0xc94770007dda54cF92009BFF0dE90c06F603a09f", "latest"] }' <url>命令末尾的<url>是文档占位符,替换为你节点的 RPC 端点。请求体四个成员为id、jsonrpc、method、params。对于对象形式的参数,EIP 的参数表会逐个标注字段类型,例如eth_estimateGas的第一个参数中,data、from、to是Data,gas、gasPrice、value是Quantity:
curl -X POST --data '{ "id": 1337, "jsonrpc": "2.0", "method": "eth_estimateGas", "params": [{ "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155", "gas": "0x76c0", "gasPrice": "0x9184e72a000", "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", "value": "0x9184e72a" }] }' <url>成功时响应包含result成员(文档示例,eth_estimateGas的返回是Quantity):
{ "id": 1337, "jsonrpc": "2.0", "result": "0x5208" }失败时响应包含error成员,EIP 规定它 MUST 是含code与描述性message的对象,例如(文档示例):
{ "id": 1337, "jsonrpc": "2.0", "error": { "code": -32003, "message": "Transaction rejected" } }Quantity:四条强制规则与自检表
EIP 对Quantity给出四条 MUST 规则:
Quantity值 MUST 是十六进制编码;- MUST 带
"0x"前缀; - MUST 使用每字节最少的十六进制位数(不允许前导零);
- 零 MUST 写作
"0x0"。
EIP 正文自带的合法/非法示例表(保留原文标注):
| Value | Valid | Reason |
|---|---|---|
0x | invalid | empty not a valid quantity |
0x0 | valid | interpreted as a quantity of zero |
0x00 | invalid | leading zeroes not allowed |
0x41 | valid | interpreted as a quantity of 65 |
0x400 | valid | interpreted as a quantity of 1024 |
0x0400 | invalid | leading zeroes not allowed |
ff | invalid | values must be prefixed |
自检要点:0x00与0x400虽然都是合法字符,但带前导零的一律非法。组装块号、gas、value 这类字段时,先把数值转成常规十六进制数(不补零到固定宽度),再加0x前缀;零值只写0x0。
Data:三条强制规则与自检表
Data的 MUST 规则是:
- MUST 是十六进制编码;
- MUST 带
"0x"前缀; - MUST 每字节用两个十六进制数字表示。
EIP 正文的示例表(原文对后半部分用true/false标注,此处照录):
| Value | Valid | Reason |
|---|---|---|
0x | valid | interpreted as empty data |
0x0 | invalid | each byte must be represented using two hex digits |
0x00 | valid | interpreted as a single zero byte |
0x41 | true | interpreted as a data value of 65 |
0x004200 | true | interpreted as a data value of 16896 |
0xf0f0f | false | bytes require two hex digits |
004200 | false | values must be prefixed |
Data与Quantity最容易混淆的三处差异:
Data允许空值,0x合法;Quantity的0x非法,零必须写0x0;Data允许前导零(0x004200合法);Quantity必须去掉前导零;Data的十六进制位数必须为偶数,0xf0f0f(7 位)非法。
一个典型的出错场景:把存储读到的全零字节当块号传出去。同一个"零",作为数据字节应写0x00,作为数量应写0x0。
实际调用并判定结果
以文档中eth_getBalance的示例为完整路径:第一个参数是Data(地址),第二个参数是块号,可以是Quantity或"latest"、"earliest"、"pending"之一。
curl -X POST --data '{ "id": 1337, "jsonrpc": "2.0", "method": "eth_getBalance", "params": ["0xc94770007dda54cF92009BFF0dE90c06F603a09f", "latest"] }' <url>文档示例的响应:
{ "id": 1337, "jsonrpc": "2.0", "result": "0x0234c8a3397aab58" }判定方式:
- 响应带
result且其Quantity字段符合上文规则(示例中的0x0234c8a3397aab58无前导零),说明请求被接受、编码正确;注意这是文档示例输出,实际数值随节点状态变化。 - 响应带
error时,按 EIP 的错误码表定位。EIP 列出的全部错误码如下:
| Code | Message | Meaning | Category |
|---|---|---|---|
| -32700 | Parse error | Invalid JSON | standard |
| -32600 | Invalid request | JSON is not a valid request object | standard |
| -32601 | Method not found | Method does not exist | standard |
| -32602 | Invalid params | Invalid method parameters | standard |
| -32603 | Internal error | Internal JSON-RPC error | standard |
| -32000 | Invalid input | Missing or invalid parameters | non-standard |
| -32001 | Resource not found | Requested resource not found | non-standard |
| -32002 | Resource unavailable | Requested resource not available | non-standard |
| -32003 | Transaction rejected | Transaction creation failed | non-standard |
| -32004 | Method not supported | Method is not implemented | non-standard |
| -32005 | Limit exceeded | Request exceeds defined limit | non-standard |
| -32006 | JSON-RPC version not supported | Version of JSON-RPC protocol is not supported | non-standard |
对编码问题,-32602(Invalid params)和-32000(Invalid input)是 EIP 中与"参数本身有问题"直接对应的两个码;查不到资源(如不存在的块)对应-32001。
分不清 Quantity 与 Data 时:Block Identifier 对象
EIP-1474 原文指出:由于Data参数与Quantity参数无法清晰区分,引用 EIP-1898 的格式来指定块。块参数可以是 JSON 对象,字段为:
| Property | Type | Description |
|---|---|---|
blockNumber | Quantity | The block in the canonical chain with this number |
blockHash(与blockNumber互斥,二者必须恰好设置一个) | Data | The block uniquely identified by this hash |
requireCanonical(可选) | boolean | 块不在 canonical chain 时是否抛错,只能与blockHash同用,默认false |
EIP-1898 给出的受影响方法:eth_getBalance、eth_getStorageAt、eth_getTransactionCount、eth_getCode、eth_call、eth_getProof。
EIP-1898 还给出针对创世块的等价写法(文档示例,0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3是 Ethereum 主链创世块哈希):
"earliest" "0x0" { "blockNumber": "0x0" } { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true }用blockNumber对象写法同时满足两条编码规则:对象键明确声明了这是数量而不是数据,blockNumber的值本身仍是合法Quantity。错误行为同样有规定:块未找到时推荐抛-32001;requireCanonical为true且块不在 canonical chain 时应抛不同于"未找到"的错误码(推荐-32000)以便调用方区分两种情况;块未找到检查优先于 canonical 检查。
限制
- EIP-1474 状态为
Stagnant,它描述的是该提案规定的 RPC 行为,具体节点实现以各客户端为准。 - EIP 中对关键字(MUST、SHOULD 等)的解释依据 RFC-2119;本文按"必须/应当"理解。
eth_estimateGas的返回值可能显著高于交易实际使用的 gas(EIP 原文提示了这一点),不要把估算值当成固定预期。
按上面顺序操作,一次调用即可完成核对:先用两条自检表检查params里每个Quantity/Data字段,发出请求后看result是否存在、返回的十六进制值是否合规;出现error时按错误码表对照-32602、-32000、-32001定位是编码、缺参还是资源问题。
【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考