Alert Source Discuss
Standards Track: ERC

ERC-5732: 提交接口

一个简单但通用的提交接口,用于支持提交-揭示方案。

Authors Zainan Victor Zhou (@xinbenlv), Matt Stam (@mattstam)
Created 2022-09-29
Requires EIP-165, EIP-1271

摘要

一个简单的提交接口,用于支持提交-揭示方案,它提供一个提交方法,但没有揭示方法,允许实现将此接口与任意揭示方法(如 votetransfer)集成。

动机

  1. 支持投票等应用程序的提交-揭示隐私。
  2. 使攻击者更难进行抢先交易、后向交易或三明治攻击。

规范

本文档中使用的关键词“必须 (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);
}
  1. 符合标准的合约必须实现 IERC_COMMIT_CORE 接口。
  2. 符合标准的合约应该实现 IERC_COMMIT_GENERAL 接口。
  3. 实现了 IERC_COMMIT_GENERAL 接口的符合标准的合约必须接受 commit(_commitment),等同于 commitFrom(msg.sender, _commitment, [/*empty array*/])
  4. 建议 commitFromtimePoint 返回值使用 block.timestampblock.number 或一个指示不同提交顺序的数字。 当 commitFrom 被调用时。
  5. 实现了 IERC_COMMIT_GENERAL 的符合标准的合约必须在接受并记录提交时发出 Commit 事件。在 CommitcommitFrom 方法的参数中,_timePoint 是一个表示时间点的值,它表示提交的顺序,其中后面的提交将始终具有_大于或等于_于先前提交的值,例如 block.timestampblock.number 或实施合约选择的其他时间尺度。

  6. extraData 保留用于将来的行为扩展。如果 _from 与 TX 签名者不同,建议符合标准的合约应该验证 _from 的签名。对于 EOA,这将是在链上验证其 ECDSA 签名。对于智能合约帐户,建议使用 EIP-1271 来验证签名。

  7. 一个或多个符合标准的合约的方法可以用于揭示。

但是必须有一种方法来提供一个额外的 secret_salt 字段,以便提交者以后可以在暴露 secret_salt 的揭示 TX 中打开 secret_salt。 此 EIP 中有意未指定 secret_salt 的大小和位置,以最大程度地提高集成的灵活性。

  1. 建议符合标准的合约实现 EIP-165

理由

  1. 一种设计选择是,我们可以将提交接口附加到任何单独的 ERC,例如投票标准或代币标准。 我们选择使用一个简单且通用的提交接口,以便所有 ERC 都可以扩展以支持提交-揭示,而无需更改其基本方法签名。

  2. 我们做出的关键派生设计决策是我们将拥有一个标准化的 commit 方法,而没有标准化的 reveal 方法,从而为自定义的 reveal 方法或将 commit 与现有标准一起使用留出空间。

  3. 我们选择在核心接口中使用一个简单的单参数 commit 方法,以使其与一些先前的采用(例如 ENS)完全向后兼容。

  4. 我们还添加了 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(...);
}

安全注意事项

  1. 请勿在生产中使用参考实现。 它仅用于演示目的。
  2. 揭示交易和参数,尤其是 secret_salt,在揭示之前必须保密。
  3. secret_salt 的长度必须足够长才能进行密码学保护,并且用于生成 secret_salt 的随机值必须是密码学安全的。
  4. 用户绝对不能重复使用已使用的 secret_salt。 建议客户端应用程序警告尝试这样做的用户。
  5. 合约实现应考虑立即删除给定发送者的提交,以减少重放攻击或重入攻击的机会。
  6. 合约实现可以考虑包括接收到的提交的顺序,以增加对揭示交易顺序的限制。
  7. 存在跨不同 chainId 或由分叉产生的链的重放攻击的风险。 在这些情况下,chainId 必须包含在提交的生成中。 对于具有较高重放攻击风险的应用程序,实施者应考虑经过实战检验且具有密码学安全性的解决方案,例如 EIP-712,以在创建自己的新解决方案之前编写提交。
  8. 如果目的是避免抢先交易攻击,建议采用适当的时间间隔。
  9. 对于要求来自下一次交易的 _timePoint _严格大于_任何先前交易的符合标准的合约,block.timestampblock.number 是不可靠的,因为两个交易可以共存于同一区块中,从而导致相同的 _timePoint 值。 在这种情况下,需要采取额外的措施来强制执行这种严格的单调性,例如在合约中使用单独的状态变量来跟踪其接收到的提交数量,或者拒绝共享相同 block.timestampblock.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.