ERC-191:数据签名标准
简要说明
该 ERC 提出了关于如何处理以太坊合约种签名数据的规范
原文章:https://eips.ethereum.org/EIPS/eip-191
动机
已经创建了几种接受presigned
(预签名)交易的多重签名钱包实现。预签名交易presigned
是一块二进制的signed_data
,以及签名(r
、s
、v
)。尚未指定signed_data
的解释,导致了以下几个问题:
- 标准以太坊交易可以作为提交
signed_data
,以太坊交易可以被解包为以下组件:RLP<nonce, gasPrice, startGas, to, value, data>
(在这里成为RLPdata
),r
、s
、v
。如果signed_data
没有语法约束,这意味着:RLPdata
可以用作语法上有效的预签名交易。 - 多重签名钱包还存在一个问题,即预签名交易并未与特定验证器(即特定钱包)绑定如:
- 用户 A、B、C 拥有 2/3 钱包 X
- 用户 A、B、D 拥有 2/3 钱包 Y
- 用户 A 和 B 向 X 提交预签名交易
- 攻击中现在就可以将预签名交易重用到 X。并提交给 Y。
规范
我们建议 signed_data
采用下面的格式:
1 | 0x19 <1 bytes version> <version specific data> <data to sign> |
初始0x19
字节旨在确保signed_data
不是有效的 RLP
对于值在 [0x00, 0x7f] 范围内的单个字节,该字节是其自己的 RLP 编码
这意味着任何 signed_data 都不能是一个 RLP 结构。而是一个 1 字节的 RLP
payload,后跟其他内容。因此,任何 EIP-191 signed_data
永远不可能是以太坊交易。
此外,选择0x19
是因自 ethereum/go-ethereum#2940 以来,在 personal_sign 种的哈希之前添加了以下内容:
1 | "\x19Ethereum Signed Message:\n" + len(message). |
因此,使用 0x19
可以通过定义版本 0x45
(E
) 来扩展该方案来处理此类签名。
版本字节表
版本字节 | EIP | 描述 |
---|---|---|
0x00 |
191 | 具有预期验证器的数据 |
0x01 |
712 | 结构化数据 |
0x45 |
191 | personal_sign 消息 |
Version 0x00
1 | 0x19 <0x00> <intended validator address> <data to sign> |
这个版本具有用于版本特定数据的<intended validator address>
。对于基本传递的签名执行的多重签名钱包,验证器地址是多重签名本身的地址。要签名的数据可以是任意的
Version 0x01
这个版本适用于 EIP-712 种定义的结构化数据。
Version 0x45
(E)
1 | 0x19 <0x45 (E)> <thereum Signed Message:\n" + len(message)> <data to sign> |
该版本有 <thereum Signed Message:\n" + len(message)>
用于版本特定数据。要签名的数据可以是任意数据。
注意:以太坊签名消息中的 E 指的是版本字节 0x45。字符 E 是十六进制的 0x45,它的余数为
Siigned Message:\n + len(message)
,即版本特定数据
例子
下面的代码片段是用 Solidity 0.8.0 编写的
**Version0x00
**:
1 | function signatureBasedExecution(address target, uint256 nonce, bytes memory payload, uint8 v, bytes32 r, bytes32 s) public payable { |