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.