EIP-1898: 向 defaultBlock 方法添加 `blockHash`
向当前支持 defaultBlock 参数的 JSON-RPC 方法添加 `blockHash` 选项。
Authors | Charles Cooper (@charles-cooper) |
---|---|
Created | 2019-04-01 |
Requires | EIP-234 |
摘要
对于当前接受默认区块参数的 JSON-RPC 方法,额外允许该参数为一个区块哈希。
此 EIP 可以被认为是 EIP-234 的泛化。它将使客户端能够明确指定他们想要查询的特定 JSON-RPC 方法的区块,即使该区块不在规范链中。这允许客户端维护他们感兴趣的区块链状态的连贯视图,即使在存在重组的情况下,也无需节点维护与客户端的持久连接或存储任何客户端特定的状态。
规范
以下 JSON-RPC 方法受到影响:
eth_getBalance
eth_getStorageAt
eth_getTransactionCount
eth_getCode
eth_call
eth_getProof
以下选项(引自 Ethereum JSON-RPC 规范)目前可用于 defaultBlock 参数:
- HEX String - 一个整数区块号
- String “earliest” - 用于最早/创世区块
- String “latest” - 用于最新的规范区块
- String “pending” - 用于待处理状态/交易
- String “safe” - 用于最新的安全区块
- String “finalized” - 用于最新的最终确定区块
由于没有办法清楚地区分 DATA 参数和 QUANTITY 参数,因此本 EIP 提出了一种新的区块参数方案。另外允许以下选项:
- OBJECT
blockNumber
: QUANTITY - 一个区块号blockHash
: DATA - 一个区块哈希
如果未找到该区块,则被调用者应引发 JSON-RPC 错误(建议的错误代码为 -32001: Resource not found
)。
如果标签是 blockHash
,则可以向区块参数提供一个额外的布尔字段 requireCanonical
,其默认为 false
,并定义根据被调用者,该区块是否必须是规范区块。如果 requireCanonical
为 false
,则仅当未找到该区块时,被调用者才应引发 JSON-RPC 错误(如上所述)。如果 requireCanonical
为 true
,则如果该区块不在规范链中,被调用者还应引发 JSON-RPC 错误(建议的错误代码为 -32000: Invalid input
,并且在任何情况下都应与未找到区块的情况的错误代码不同,以便调用者可以区分这些情况)。未找到区块的检查应优先于区块是否规范的检查,因此如果未找到区块,则被调用者应引发未找到区块的错误,而不是区块不规范的错误。
为了保持向后兼容性,区块号可以指定为十六进制字符串或使用新的区块参数方案。换句话说,对于默认区块参数,以下是等效的:
"earliest"
"0x0"
{ "blockNumber": "0x0" }
{ "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }
(以太坊主链上创世区块的哈希){ "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true }
{ "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false }
理由
目前,上述状态查询 JSON-RPC 方法没有明确指定要查询哪个区块的状态的选项。这可能会给需要多次调用 RPC 的应用程序带来问题。例如,刚刚执行了转账的钱包可能想要显示发送者和接收者的余额。如果在通过 eth_getBalance
查询发送者的余额和查询接收者的余额之间存在重组,则余额可能无法协调。作为一个稍微复杂一点的例子,去中心化交易所的 UI(在链上托管订单)可以通过为每个订单调用 eth_call
来获取订单数据,从而遍历订单列表。另一种用例是应用程序需要根据多个状态来做出决策,例如基于同时拥有两个 NFT 的支付。
为了确保状态是连贯的(即,对于每次调用,eth_call
都使用完全相同的区块调用),应用程序目前可以使用以下几种策略之一:
- 决定要使用的区块号(例如,应用程序已知的最新区块号)。在使用该区块号的每个
eth_call
之后,也使用该区块号调用eth_getBlockByNumber
。如果区块哈希与该区块号的已知哈希不匹配,则回滚当前活动并从头开始重试。这增加了O(n)
次调用作为基线开销,并为每次需要的重试增加了另一次O(n)
次调用。此外,无法检测到相关区块在eth_call
之前被重组出去,然后在eth_getBlockByNumber
之前被重组回来的(不太可能但可能发生的)情况。 - 依赖于日志,由于
blockHash
参数,日志 可以 被明确查询。但是,这需要智能合约的语义支持;如果智能合约不发出适当的事件,客户端将无法重构其感兴趣的特定状态。 - 依赖于非标准扩展,如
parity_subscribe
。这需要在客户端和节点之间建立持久连接(通过 IPC 或 websockets),增加了客户端和节点之间的耦合,并且无法处理eth_call
调用之间存在依赖关系的用例,例如,遍历链表。
允许 eth_call
及其友元明确指定要查询的区块,为应用程序开发人员提供了一种强大而直观的方式来解决这些问题。多个连续查询将查询相同的状态,使应用程序开发人员不必担心其区块链状态视图中的不一致性。
向后兼容性
向后兼容。
测试用例
eth_getStorageAt [ "0x<address>", { "blockNumber": "0x0" }
-> 返回创世区块中给定地址的存储eth_getStorageAt [ "0x<address>", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }
-> 返回创世区块中给定地址的存储eth_getStorageAt [ "0x<address>", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false }
-> 返回创世区块中给定地址的存储eth_getStorageAt [ "0x<address>", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true }
-> 返回创世区块中给定地址的存储eth_getStorageAt [ "0x<address>", { "blockHash": "0x<non-existent-block-hash>" }
-> 引发 block-not-found 错误eth_getStorageAt [ "0x<address>", { "blockHash": "0x<non-existent-block-hash>", "requireCanonical": false }
-> 引发 block-not-found 错误eth_getStorageAt [ "0x<address>", { "blockHash": "0x<non-existent-block-hash>", "requireCanonical": true }
-> 引发 block-not-found 错误eth_getStorageAt [ "0x<address>", { "blockHash": "0x<non-canonical-block-hash>" }
-> 返回指定区块中给定地址的存储eth_getStorageAt [ "0x<address>", { "blockHash": "0x<non-canonical-block-hash>", "requireCanonical": false }
-> 返回指定区块中给定地址的存储eth_getStorageAt [ "0x<address>", { "blockHash": "0x<non-canonical-block-hash>", "requireCanonical": true }
-> 引发 block-not-canonical 错误
安全考虑
无
版权
通过 CC0 放弃版权及相关权利。
Citation
Please cite this document as:
Charles Cooper (@charles-cooper), "EIP-1898: 向 defaultBlock 方法添加 `blockHash`," Ethereum Improvement Proposals, no. 1898, April 2019. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-1898.