EIP-2711: 赞助、过期和批量交易。
Authors | Micah Zoltu (@MicahZoltu) |
---|---|
Created | 2020-06-11 |
Discussion Link | https://ethereum-magicians.org/t/eip-2711-separate-gas-payer-from-msg-sender/4353 |
Requires | EIP-2718 |
Table of Contents
简要总结
创建一个新的交易类型,支持赞助交易(将 gas 支付者与发送者分离)、批量交易(按顺序执行的多个交易)和过期交易(在特定时间戳之后无效的交易)。
摘要
类型编号为 2
的 EIP-2718 交易是一种新的交易类型,包括对以下内容的支持:
- 赞助交易:一个可选的附加签名,从中可以恢复将支付 gas 的帐户 (
GAS_PAYER
) - 批量交易:来自同一发送者的多个交易,将按顺序执行
- 过期交易:一个可选的
validUntil
字段,使交易在特定时间点之后无效
动机
赞助交易
随着代币,尤其是稳定币的出现,用户通常不在帐户中持有 ETH,而他们可能在该帐户中拥有其他有价值的资产。一些用户不想暴露于 ETH 的感知波动性,而是更喜欢使用其他资产进行交易。不幸的是,由于 gas 必须用 ETH 支付,这阻止了用户在不首先使用其他方式获取一些 ETH,然后使用该 ETH 支付费用的情况下,使用他们的资产进行交易。
本 EIP 提出了一种机制,通过该机制,我们可以允许人们在无需拥有任何 ETH 的情况下进行交易,方法是允许其他人支付 gas 费用。实现 gas 费用支付的安排不在本 EIP 的范围之内,但它可以是协议外的每月订阅,付款可以在提交交易时发生,接收者可能愿意支付 gas 费用,或者它可以是由您合作的公司提供的增值免费服务。
虽然可以在单个合约层实现这些类型的机制,但此类解决方案需要几乎每个合约都进行集成,并且这些解决方案最终还取决于 gas 成本随时间的推移保持稳定,以便适当地将其烘焙到合约中,而不会使任何一方面临系统恶意参与者的风险。因此,我们认为在协议层将 GAS_PAYER
与 msg.sender
分离是有价值的。
批量交易
通常,EOA 可能希望执行一系列交易,并强烈保证它们按顺序发生,并且它们之间没有任何事情发生。例如,可能希望将一些代币发送到合约,然后通过另一笔交易来调用目标地址上的合约,从而使这些代币注册到他们。通过在第 1 层支持交易批处理,我们可以确保用户可以在签名时获得跨交易原子性的有力保证。
过期交易
- 如果引入任何形式的尘埃账户清理,例如 (https://github.com/ethereum/EIPs/issues/168),则有必要引入重放保护,例如 https://github.com/ethereum/EIPs/issues/169 。具有时间重放保护消除了更改状态中 nonce 行为的需要,因为交易在用户明确设置的较晚日期之后将不可重放。
- 在许多情况下,例如在 ICO 期间,很多人希望他们的交易要么尽快(在几个小时内)被包括在内,要么根本不包括在内。目前,交易会排队,并且可能会在几天内没有执行,这会给用户(最终为失败的购买支付 gas)和网络(处理大型交易队列)带来成本。
- 节点实现没有普遍认可的指标来决定保留、丢弃或传播哪些交易。在交易上设置 TTL 将使从系统中删除过时交易变得更容易。
规范
定义
TransactionType
2。请参阅 EIP-2718
TransactionSubtype
为 1、2、3 或 4。
ChainId
如果此值为 0
,或者它包含在链 ID 等于此值的链上的区块中,则该交易有效。
ValidUntil
如果此值是 0
,或者它包含在一个 timestamp
小于或等于此值的区块中,则该交易有效。
YParity
secp256k1 签名的 y 值的奇偶性(0 表示偶数,1 表示奇数)。
ChildTransaction
一个嵌套的交易,由 [to, value, data]
组成。
SenderPayload
根据 TransactionSubtype
定义如下:
[1, ChildTransaction[], nonce, ChainId, ValidUntil, gasLimit, gasPrice]
[2, ChildTransaction[], nonce, ChainId, ValidUntil, gasLimit, gasPrice]
[3, ChildTransaction[], nonce, ChainId, ValidUntil, gasLimit]
[4, ChildTransaction[], nonce, ChainId, ValidUntil]
SenderSignature
secp256k1(keccak256(rlp([TransactionType, SenderPayload])))
的 [YParity, r, s]
GasPayerPayload
基于 TransactionSubtype
定义如下:
[]
[]
[gasPrice]
[gasLimit, gasPrice]
GasPayerSignature
对于 TransactionSubType
1
为 []
,对于其他 TransactionSubType
,为 secp256k1(keccak256(rlp([SenderPayload, SenderSignature, GasPayerPayload])))
的 [YParity, r, s]
。
新的交易类型
从 FORK_BLOCK_NUMBER
开始,TransactionType
为 2
的 EIP-2718 交易将将其 Payload
解释为以下内容的 RLP 编码元组:
[...SenderPayload, ...SenderSignature, ...GasPayerPayload, ...GasPayerSignature]
从该 SenderSignature
恢复的地址是…
- …交易的第一个调用帧期间由
CALLER
操作码(0x33,又名msg.sender
)返回的 - …由
ORIGIN
操作码(0x32,又名tx.origin
)返回的 - …使用其
nonce
的 - …如果任何值附加到交易,则扣除其 ETH 余额
- …如果
GasPayerSignature
不存在,则扣除其 ETH 余额以支付 gas
如果存在 GasPayerSignature
,则从中恢复的地址是…
- …扣除其 ETH 余额以支付 gas
此类型交易的基本 gas 成本将是 TRANSACTION_TYPE_2_BASE_GAS_PRICE
+ TRANSACTION_TYPE_2_CHILD_GAS_PRICE
* n
,而不是与类型 0
交易和旧交易相关的成本。
新的交易回执
从 FORK_BLOCK_NUMBER
开始,TransactionType
为 2
的 EIP-2718 交易回执将将其 Payload
解释为 rlp([status, cumulativeGasUsed, logsBloom, logs][])
,其中数组的每个项目都对应于交易类型 2 Payload
中匹配偏移量的子交易。
理由
一个整体的 EIP
本 EIP 可以分为多个 EIP,每个子类型一个,元类型一个。或者,每个子类型都可以是唯一的 TransactionType。我们选择使用带有子类型的单个 EIP 的原因是,这 4 个事务都具有很多共同点,并且每个单独的 EIP 几乎与上一个相同。我们认为在这种情况下,拆分为多个 EIP 不值得重复 EIP 内容。
ChainID 未与 v
一起编码
虽然我们可以通过将签名的 y 奇偶校验位与 EIP-155 中的 Chain ID 捆绑在一起来节省常见情况下的一个字节,但这会增加签名工具的复杂性,作者认为考虑到交易的整体大小,这不值得。
ChainID 的可选性
有时拥有可以在多个链上可以重放的交易是有用的。一个例子是当你为交易构造一个虚荣签名并让 from
成为该签名恢复到的任何地址时。通过让其他人成为 gas 支付者(设置 gas 限制和 gas 价格),可以拥有部署合约的交易,这些合约存在于每个链上的相同地址。虽然可以使用旧交易通过 CREATE2 来完成此操作,但我们有机会简化该过程,并通过使 ChainID 成为可选的来启用确定性交易的潜在其他未来用途。
ValidUntil 的可选性
用户可以将 ValidUntil
设置为一个非常大的数字,从而有效地使其永不过期。通过使 ValidUntil
成为可选的,我们可以通过允许此类交易简单地为此字段设置一个 0
(RLP 中为 1 个字节)值来节省一些传输量。
SENDER
设置 gasLimit
和 gasPrice
当交易可能会根据这些值的设置方式以不同的方式执行时,此类型的交易非常有用。通过让 SENDER
同时设置它们,我们可以确保 SENDER
完全控制交易细节。
SENDER
设置 gasLimit
,GAS_PAYER
设置 gasPrice
当交易可能会根据允许的 gas 量(例如,循环次数)以不同的方式执行,但 SENDER
希望让 GAS_PAYER
能够为交易定价以最大化纳入机会时,此类型的交易非常有用。
GAS_PAYER
设置 gasLimit
和 gasPrice
这种类型的交易允许 SENDER
定义他们想要做什么,并将所有关于 gas 的担忧留给 GAS_PAYER
。这对于发送者不关心使用了多少 gas 或支付的价格,并且要么信任 GAS_PAYER
是非恶意的,要么不关心 SENDERP
的 nonce 会增加的交易非常有用。当您在 SENDER
和 GAS_PAYER
之间存在协议外信任,并且您想要出于安全或复杂性的原因将关注点(做什么与如何包含)分开时,这种情况非常有用。
Nonce
内部交易需要 nonce 来保护自己免受重放攻击。由于内部交易具有 nonce,我们也获得了外部交易的重放保护,因此对于安全而言,让多个参与者提供 nonce 并非至关重要。
我们可以让 GAS_PAYER
提供第二个 nonce,但这会增加 payload 大小,并且如果他们想要插入一个具有更高 gas 价格的新(不同的内部)交易,则需要 GAS_PAYER
进行替换费用(对 gossip 来说很吵)。如果 SENDER
nonce 的排序与 GAS_PAYER
nonce 的排序不同,并且如果 SENDER
nonce 不是 SENDER
的最低有效 nonce,则还会产生死锁的可能性,那么 GAS_PAYER
还无法签名和提交。最后,如果交易有两个 nonce,则客户端复杂性会略有增加,因为您必须保护自己免受死锁的影响,并做更多的工作来确定有效性。
ValidUntil
对于尘埃帐户清理用例,
- 此更改对共识引擎的侵入性要小得多。
- 无需维护“最高已知 nonce”的共识字段或限制来自发送者的区块中的交易数量。
- 仅触及共识引擎的交易验证部分
- 使用
nonce
的其他模式可能会产生意外的副作用,- 例如无法在某些地址创建合约。
- 更难与离线签名器集成,因为更复杂的 nonce 方案需要状态访问才能确定。
- 更复杂的方案(如
highest-nonce
)要困难得多,因为 highest-known-nonce 将是一个共识结构,该结构在交易执行期间会递增并可能恢复,从而需要一个额外的日记字段。
ValidUntil 作为时间戳而不是区块号
- unix 时间通常在大多数设置中都可用,即使在一台离线计算机上也是如此。这意味着即使在区块链信息不可用的设置中,签名交易的参与者也可以生成具有所需属性的交易。
- 时间和区块号之间的相关性不是固定的;即使 13 秒的区块时间是“理想的”,但这会因网络哈希率和难度炸弹的进展而异。
- 对于测试网和私有网络,区块号作为时间戳更加不可靠。
- unix 时间对用户更友好,用户可以更容易地确定交易的合理结束日期,而不是合适的有效区块数。
向后兼容性
没有已知问题。
测试用例
实现
安全注意事项
版权
版权和相关权利通过 CC0 放弃。
Citation
Please cite this document as:
Micah Zoltu (@MicahZoltu), "EIP-2711: 赞助、过期和批量交易。 [DRAFT]," Ethereum Improvement Proposals, no. 2711, June 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2711.