ERC-5732: 提交接口
一个简单但通用的提交接口,用于支持提交-揭示方案。
Authors | Zainan Victor Zhou (@xinbenlv), Matt Stam (@mattstam) |
---|---|
Created | 2022-09-29 |
Requires | EIP-165, EIP-1271 |
摘要
一个简单的提交接口,用于支持提交-揭示方案,它仅提供一个提交方法,但没有揭示方法,允许实现将此接口与任意揭示方法(如 vote
或 transfer
)集成。
动机
- 支持投票等应用程序的提交-揭示隐私。
- 使攻击者更难进行抢先交易、后向交易或三明治攻击。
规范
本文档中使用的关键词“必须 (MUST)”,“禁止 (MUST NOT)”,“需要 (REQUIRED)”,“应当 (SHALL)”,“不应当 (SHALL NOT)”,“应该 (SHOULD)”,“不应该 (SHOULD NOT)”,“推荐 (RECOMMENDED)”,“可以 (MAY)”和“可选 (OPTIONAL)”应按照 RFC 2119 中的描述进行解释。
本规范中引用的接口如下:
pragma solidity >=0.7.0 <0.9.0;
// 此接口的 EIP-165 标识符为 0xf14fcbc8
interface IERC_COMMIT_CORE {
function commit(bytes32 _commitment) payable external;
}
pragma solidity >=0.7.0 <0.9.0;
// 此接口的 EIP-165 标识符为 0x67b2ec2c
interface IERC_COMMIT_GENERAL {
event Commit(
uint256 indexed _timePoint,
address indexed _from,
bytes32 indexed _commitment,
bytes _extraData);
function commitFrom(
address _from,
bytes32 _commitment,
bytes calldata _extraData)
payable external returns(uint256 timePoint);
}
- 符合标准的合约必须实现
IERC_COMMIT_CORE
接口。 - 符合标准的合约应该实现
IERC_COMMIT_GENERAL
接口。 - 实现了
IERC_COMMIT_GENERAL
接口的符合标准的合约必须接受commit(_commitment)
,等同于commitFrom(msg.sender, _commitment, [/*empty array*/])
。 - 建议
commitFrom
的timePoint
返回值使用block.timestamp
或block.number
或一个指示不同提交顺序的数字。 当commitFrom
被调用时。 -
实现了
IERC_COMMIT_GENERAL
的符合标准的合约必须在接受并记录提交时发出Commit
事件。在Commit
和commitFrom
方法的参数中,_timePoint
是一个表示时间点的值,它表示提交的顺序,其中后面的提交将始终具有_大于或等于_于先前提交的值,例如block.timestamp
或block.number
或实施合约选择的其他时间尺度。 -
extraData
保留用于将来的行为扩展。如果_from
与 TX 签名者不同,建议符合标准的合约应该验证_from
的签名。对于 EOA,这将是在链上验证其 ECDSA 签名。对于智能合约帐户,建议使用 EIP-1271 来验证签名。 - 一个或多个符合标准的合约的方法可以用于揭示。
但是必须有一种方法来提供一个额外的 secret_salt
字段,以便提交者以后可以在暴露 secret_salt
的揭示 TX 中打开 secret_salt
。 此 EIP 中有意未指定 secret_salt
的大小和位置,以最大程度地提高集成的灵活性。
- 建议符合标准的合约实现 EIP-165。
理由
-
一种设计选择是,我们可以将提交接口附加到任何单独的 ERC,例如投票标准或代币标准。 我们选择使用一个简单且通用的提交接口,以便所有 ERC 都可以扩展以支持提交-揭示,而无需更改其基本方法签名。
-
我们做出的关键派生设计决策是我们将拥有一个标准化的
commit
方法,而没有标准化的reveal
方法,从而为自定义的 reveal 方法或将commit
与现有标准一起使用留出空间。 -
我们选择在核心接口中使用一个简单的单参数
commit
方法,以使其与一些先前的采用(例如 ENS)完全向后兼容。 -
我们还添加了
commitFrom
,以便轻松地从链下生成提交,并由某个帐户代表另一个帐户提交。
向后兼容性
此 EIP 与所有具有 extraData 的现有 ERC 方法签名向后兼容。 可以使用额外的 “salt” 字段来设计新的 EIP,以使其更容易支持此 EIP,但不是必需的。
IERC_COMMIT_CORE
与 ENS 实现和其他现有的先前技术向后兼容。
参考实现
使用 ENS 注册作为展示进行提交
在 ENS 注册过程中,当前在 ETHRegistrarController
合约中,正在使用一个提交函数来允许注册者公平地注册一个想要的域,以避免被抢先交易。
以下是 ENS 在其注册逻辑中使用提交的方式:
function commit(bytes32 commitment) public {
require(commitments[commitment] + maxCommitmentAge < now);
commitments[commitment] = now;
}
使用此 EIP,可以将其更新为
function commit(bytes32 commitment, bytes calldata data) public {
require(commitments[commitment] + maxCommitmentAge < now);
commitments[commitment] = now;
emit Commit(...);
}
安全注意事项
- 请勿在生产中使用参考实现。 它仅用于演示目的。
- 揭示交易和参数,尤其是
secret_salt
,在揭示之前必须保密。 secret_salt
的长度必须足够长才能进行密码学保护,并且用于生成secret_salt
的随机值必须是密码学安全的。- 用户绝对不能重复使用已使用的
secret_salt
。 建议客户端应用程序警告尝试这样做的用户。 - 合约实现应考虑立即删除给定发送者的提交,以减少重放攻击或重入攻击的机会。
- 合约实现可以考虑包括接收到的提交的顺序,以增加对揭示交易顺序的限制。
- 存在跨不同 chainId 或由分叉产生的链的重放攻击的风险。 在这些情况下,chainId 必须包含在提交的生成中。 对于具有较高重放攻击风险的应用程序,实施者应考虑经过实战检验且具有密码学安全性的解决方案,例如 EIP-712,以在创建自己的新解决方案之前编写提交。
- 如果目的是避免抢先交易攻击,建议采用适当的时间间隔。
- 对于要求来自下一次交易的
_timePoint
_严格大于_任何先前交易的符合标准的合约,block.timestamp
和block.number
是不可靠的,因为两个交易可以共存于同一区块中,从而导致相同的_timePoint
值。 在这种情况下,需要采取额外的措施来强制执行这种严格的单调性,例如在合约中使用单独的状态变量来跟踪其接收到的提交数量,或者拒绝共享相同block.timestamp
或block.number
的任何第二个/其他 TX。
版权
在 CC0 下放弃版权及相关权利。
Citation
Please cite this document as:
Zainan Victor Zhou (@xinbenlv), Matt Stam (@mattstam), "ERC-5732: 提交接口," Ethereum Improvement Proposals, no. 5732, September 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-5732.