Alert Source Discuss
🛑 Withdrawn Standards Track: Core

EIP-2972: 封装的传统交易

Authors Micah Zoltu (@MicahZoltu)
Created 2020-09-12
Discussion Link https://ethereum-magicians.org/t/eip-2972-wrapped-legacy-transactions/4604
Requires EIP-155, EIP-2718

简述

两种新的交易类型,用于封装带或不带链 ID 的传统交易。

摘要

引入了两种新的 EIP-2718 交易,它们与传统交易的签名兼容,并且可以被任何客户端自动升级。

  • 0x00 || ssz.serialize(yParity, r, s, rlp([nonce, gasPrice, gasLimit, to, value, data]))
  • 0x01 || ssz.serialize(yParity, r, s, rlp([nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0]))

动机

我们希望最终弃用传统交易,这样我们就不必在网络和签名层中保留处理它们的代码。 但是,我们还希望确保在该弃用之前生成的交易签名仍然有效,并且资金不会因为无法签署新样式的交易而最终卡住。 此 EIP 提供了一种传输/包含交易的机制,该机制与 EIP-2718 兼容,同时仍然与传统交易的签名兼容。

规范

定义

  • || 是字节/字节数组连接运算符。
  • yParity 是 secp256k1 签名过程中 rx 值的曲线点的 y 值的奇偶性(偶数为 0,奇数为 1)。

交易

FORK_BLOCK_NUMBER 开始,0x00 || ssz.serialize(yParity, r, s, rlp([nonce, gasPrice, gasLimit, to, value, data])) 将是一个有效的交易,其中:

  • RLP 编码的交易部分以与传统交易签名/处理/处理完全相同的方式进行签名/处理/处理,但最终编码除外
  • TODO: 用于区块交易根的哈希或 Merkle 树

FORK_BLOCK_NUMBER 开始,0x01 || ssz.serialize(yParity, r, s, rlp([nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0])) 将是一个有效的交易,其中:

  • RLP 编码的交易部分以与传统交易签名/处理/处理完全相同的方式进行签名/处理/处理,但最终编码除外
  • TODO: 用于区块交易根的哈希或 Merkle 树

两种交易类型的 SSZ 模式为:

  Transaction[
    yParity: boolean,
    r: bytes32,
    s: bytes32,
    signedData: bytes,
  ]

注意:sszencode(yParity, r, s, rlp(...))yParity || r || s || 0x45000000 || rlp(...) 相同

FORK_BLOCK_NUMBER 开始,rlp(nonce, gasPrice, gasLimit, to, value, data, v, r, s) 将不再是区块中的有效交易。

收据

FORK_BLOCK_NUMBER 开始,0 || ssz.serialize(status, cumulativeGasUsed, logsBloom, logs) 将是一个有效的收据,其中:

  • ReceiptPayload 将以与传统收据处理/处理完全相同的方式生成/处理/处理,但其编码除外
  • TODO: 用于区块收据根的哈希或 Merkle 树

FORK_BLOCK_NUMBER 开始,1 || ssz.serialize(status, cumulativeGasUsed, logsBloom, logs) 将是一个有效的收据,其中:

  • ReceiptPayload 将以与传统收据处理/处理完全相同的方式生成/处理/处理,但其编码除外
  • TODO: 用于区块收据根的哈希或 Merkle 树

两种收据类型的 SSZ 模式为:

Log[
  address: bytes20,
  topics: List[bytes32, 4],
  data: List[uint8, 0xffffff],
]
Receipt[
  status: uint8,
  cumulativeGasUsed: uint64,
  logsBloom: BitVector[2048],
  logs: List[Log, 0xffffff],
]

FORK_BLOCK_NUMBER 开始,rlp(status, cumulativeGasUsed, logsBloom, logs) 将不再是区块中的有效收据。

理由

签名不包括交易类型作为第一个签名字节

这些交易类型被明确设计为与传统交易的签名兼容,这意味着我们不能更改被签名的数据。 有关更多详细信息,请参阅“安全注意事项”部分。

两种交易类型而不是一种

随着类型化交易的引入,我们不再需要进行位压缩以避免更改签名的形状。 传统交易在 EIP-155 中引入了链 ID,并且想要避免更改交易数组的长度,因此它将 chainID 位压缩到签名的 v 值中。 由于我们不再需要保证交易类型之间一致的有效负载长度,因此我们选择了两种具有清晰字段的交易类型。

签名与签名数据分开

验证签名时,必须首先将签名数据与签名分开,然后针对签名数据验证签名。 对于传统交易,这有点麻烦,因为您必须首先 RLP 解码交易,然后提取签名,然后 RLP 编码交易的子集。 EIP-155 通过要求验证者进一步解码 v 签名值以提取链 ID(如果存在)并将其包含在签名数据有效负载中,使此过程更加糟糕。 通过将签名数据完全按照签名方式进行编码,我们可以确保可以验证交易的签名,而无需事先进行任何解码。 通过预先对签名进行 SSZ 编码,我们可以轻松提取签名,甚至无需使用解码器。

SSZ 用于序列化

存在一个微弱的共识,即 RLP 对于哈希数据来说不是一个特别好的编码方案,部分原因是它无法被流式传输。 SSZ 几乎肯定会在未来的某个时候包含在以太坊中,因此客户端可能会访问 SSZ 解码器。 对于这个特定情况,在没有完整的 SSZ 解码器的情况下进行手动解码并不是太复杂,尽管它确实需要做一些“指针运算”,因为 logs 是一个可变长度项目的数组。

弃用传统交易

通过弃用传统交易,我们可以让客户端更容易,因为他们始终可以在区块中处理类型化交易。

日志和日志数据的最大长度

EIP-706 将 devp2p 消息限制为 24 位长度,这为我们提供了一个实用的上限,即目前任何单个交易的上限。 这个数字似乎远远超过了近期任何时候的合理范围,因此感觉像任何合理的上限。

向后兼容性

新交易与传统交易的签名兼容。 传统交易可以解码,然后编码为类型 0 或类型 1 交易。 此 EIP 没有为传统编码交易引入任何弃用过程,但作者鼓励客户端开发人员尽快将传统编码交易升级为类型化交易(只要合理)。

签名兼容性意味着客户端可能会看到以两种方式编码的同一交易。 在这种情况下,客户端可以选择保留哪个,但建议保留类型化交易而不是传统编码交易。 由于这两个交易将共享一个 nonce,因此一次只有一个交易在链中有效。

测试用例

待定

实现

待定

安全注意事项

虽然 EIP-2718 强烈建议将交易类型作为签名数据的第一个字节包含在内,但在这种情况下我们无法做到这一点,因为我们需要与传统交易保持签名兼容。 幸运的是,EIP-2718 还将交易类型 0xc00xfe 排除在有效的交易类型之外,并且在这种情况下签名的第一个字节在该范围内,因此我们可以确保这不会与任何未来的交易类型冲突。

这些交易类型的签名确实与传统交易冲突,但是交易的处理方式相同,因此交易最终包含为传统交易还是类型化交易都无关紧要。

版权

版权及相关权利通过 CC0 放弃。

Citation

Please cite this document as:

Micah Zoltu (@MicahZoltu), "EIP-2972: 封装的传统交易 [DRAFT]," Ethereum Improvement Proposals, no. 2972, September 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2972.