Alert Source Discuss
⚠️ Review Standards Track: Core

EIP-7932: 算法交易包装器

引入一种新的交易类型,用于包装使用替代签名算法的交易

Authors James Kempton (@SirSpudlington)
Created 2025-04-12
Requires EIP-155, EIP-1559, EIP-2718, EIP-2930, EIP-4844, EIP-7702

摘要

本 EIP 引入了一个新的 EIP-2718 类型化交易,它包装(包含)另一个交易。本 EIP 使默认签名参数无效,并将签名数据附加到交易的开头,并带有一个选择器。这有效地包装了一个交易,并将签名数据替换为替代算法和数据。它还创建了一个新的预编译合约,以便能够解码这些额外的签名算法。

动机

随着量子计算机的日益发展,已经设计了几种新的后量子(PQ)算法。这些算法都包含缺点,例如大密钥大小(> 1KiB)、大签名大小或长验证时间。这些问题使得它们的计算和存储成本高于当前使用的 secp256k1 曲线(截至 2025-04-12)。

本 EIP 通过添加一种标准化方式来表示交易中的替代算法,从而为这些算法提供了一种面向未来的解决方案。

规范

本文档中的关键词“必须”、“不得”、“必需”、“应”、“不应”、“应该”、“不应该”、“推荐”、“不推荐”、“可以”和“可选”应按照 RFC 2119 和 RFC 8174 中的描述进行解释。

注意:本 EIP 引用的“验证函数”是由额外的 EIP 及其签名类型指定的函数。在显式调用“验证函数”时,由于 gas 成本不同,实现必须不调用预编译合约。

参数

常量
ALG_TX_TYPE Bytes1(0x07)
GAS_PER_ADDITIONAL_VERIFICATION_BYTE 16
SIGRECOVER_PRECOMPILE_ADDRESS Bytes20(0x12)
SIGRECOVER_PRECOMPILE_BASE_GAS 3000

算法交易

本 EIP 引入了一个新的 EIP-2718 交易,其 TransactionTypeALG_TX_TYPETransactionPayload 为下面定义的 AlgTransactionPayloadBody 的 RLP 序列化:

[alg_type, signature_info, parent, additional_info]

字段 alg_type 是一个无符号 8 位整数 (uint8),表示用于对 parent 字段中的交易进行签名的算法。本 EIP 没有定义与此交易类型一起使用的算法;但是,它确实指定了一个 NULL 算法 (0xFF),该算法必须触发实现来验证交易字段。

signature_info 字段包含验证 parent 字段中交易的签名所需的信息。这是一个任意长度的字节数组,它将被传递给验证函数。

parent 字段包含另一个序列化的 EIP-2718 类型化交易信封(即 parent 字段类型为 bytes),它必须能够包含每个可能的 TransactionType,包括 TransactionType> 0x7f 的旧式交易,但此规则的唯一例外是 Algorithmic Transaction 本身,它不得放置在自身内部。

这些 parent 交易都包含 y_parityrs 值,如果包装在 AlgTransactionPayloadBody 中,则必须将其设置为 Bytes0()。但此规则有两个例外:

  • 如果 alg_typeNULL 算法,则签名字段必须保持不变。
  • 如果交易类型是旧式交易,其中 y_parity 必须等于链 ID 值,则交易的签名数据必须按照 EIP-155 指定的相同方式计算

所有其他交易值必须与其原始值保持不变。

只有在需要额外的协议级别签名时,才需要填充 additional_info 字段,例如 EIP-7702authorization_list。此字段必须包含签名列表 [alg_type, signature_info] 的 RLP 序列化,并且必须为每个交易中的空 (0x0) rv 值重复,s必须设置为 keccak256(alg_type || signature_info)。顺序必须与签名在 parent 交易中出现的顺序相同。还必须检查此签名以确保 alg_type 是已知的,并且不是 NULL 算法 (0xFF) 并且 len(signature_info) <= alg.MAX_SIZE。这还必须使用特定算法的 verify 函数进行验证。

如果指定了新的交易类型,则它们不得尝试基于此 EIP 构建,而必须包含 y_parityrs 值。这将防止向后兼容性问题,并确保可以安全地假定除 EIP-7932 交易之外的任何交易都是 secp256k1。

算法交易不得生成 TransactionTypeALG_TX_TYPE 的交易收据,它必须发出它包装的交易(parent 字段中的交易)的收据。实现必须不能仅通过收据来区分未包装和已包装的交易。

当客户端通过 gossip 或 RPC 接收到算法交易时,它们必须验证算法交易和 parent 字段中的交易,并且交易顺序计算(例如,基于 gas 价格)必须parent 字段中的交易上完成。如果任一交易无效,则整个交易无效,并且它们不得将该交易传播给对等方。

算法规范

进一步的算法必须通过额外的 EIP 来指定。

每种类型的算法必须指定以下字段: | 字段名称 | 描述 | |-|-| |ALG_TYPE| 算法唯一 ID 的 uint8 | |MAX_SIZE| 交易中 signature_info 字段的最大大小 | |GAS_PENALTY| 验证签名产生的额外 gas 惩罚 |

GAS_PENALTY 字段必须仅考虑验证成本,而不考虑存储或签名成本。

新算法必须还指定如何从交易中的 signature_info 字段中恢复和验证有效的地址 (bytes20),验证函数必须遵循以下签名:

def verify(signature_info: bytes, parent_hash: bytes32) -> bytes20

如果从签名中恢复有效地址时出错,则验证函数必须返回 0x0,否则该函数必须返回签名者的地址。

规范必须还证明为什么它们的 GAS_PENALTY 足够高以至于不会导致 DOS 向量,并且必须包括对该算法的某种形式的安全分析,并且它不会导致潜在的安全问题。

可以在此处找到此规范的示例。

本 EIP 使用 Algorithms 对象来表示最终且活跃的算法。这些算法通过 EIP 流程和硬分叉包含来选择。

验证

实现必须认为 len(tx.signature_info) > alg.MAX_SIZE 的交易无效,这也适用于 additional_info 中的对象。

必须始终对任何类型的 signature_infoalg_type 进行以下检查。如果这些检查的结果未通过,则适用以下其中一项:

  1. 交易无效
  2. 如果从预编译合约调用,则预编译合约必须返回 0x0 作为地址。
assert(Algorithms[alg_type] != None)  # `Algorithms` 是一个包含每个已定义算法的字典
assert(len(signature_info) <= alg.MAX_SIZE)

交易必须还遵守 规范部分 中概述的所有规则。

Gas 计算

所有使用比 secp256k1 曲线更多资源的交易都会受到额外的惩罚。此惩罚必须按如下方式计算:

def calculate_penalty(signing_data: bytes, algorithm: int) -> int:
  gas_penalty_base = max(len(signing_data) - 65, 0) * GAS_PER_ADDITIONAL_VERIFICATION_BYTE
  total_gas_penalty = gas_penalty_base + ALGORITHMS[algorithm].GAS_PENALTY
  return total_gas_penalty

在处理交易之前,必须将惩罚添加到每个交易的 21000 基本 gas 上。如果包装的交易的 gas_limit 小于 21000 + calculate_penalty(signing_data, algorithm),则必须认为该交易无效,并且不得将其包含在区块中。此交易还必须继承包装的交易的费用结构的内在属性(例如,包装的 EIP-1559 交易的行为类似于 EIP-1559 交易)。

必须将惩罚应用于 additional_info 对象的每个实例,然后必须将其添加到交易的初始 gas 上。无论是否使用签名,都这样做。

NULL 算法

如果包装的交易中的签名参数对于 secp256k1 仍然有效,但交易中有更多参数(例如 EIP-7702authorization_list)需要替换为不同的算法,则必须存在 NULL 算法 (0xFF)。

如果不存在 NULL 算法,则 signature_info 字段必须为零大小。

如果交易不包含额外的签名,则不得存在 NULL 算法。

sigrecover 预编译

本 EIP 还引入了一个位于 SIGRECOVER_PRECOMPILE_ADDRESS 的新预编译合约。

验证交易参数时不必须调用此预编译合约,而是应按照上述指定验证此调用。

即使算法不存在,调用此预编译合约必须花费 SIGRECOVER_PRECOMPILE_BASE_GAS,此价格必须与算法特定的 GAS_PENALTY 和签名数据的 calculate_penalty 的输出聚合,此惩罚在 sigrecover 预编译合约执行后收取。

sigrecover 预编译合约不得包含 NULL 算法。

预编译合约逻辑执行以下逻辑:


def sigrecover_precompile(input: Bytes) -> Bytes:
  # 恢复签名长度和类型
  assert(len(input) >= 64)
  hash = input[:32]
  alg_type = input[32]
  sig_length = int.from_bytes(input[33:64], "little")

  # 确保算法存在并且签名大小正确
  if alg_type not in Algorithms:
    return bytes20(0x0)

  alg = Algorithms[alg_type]

  # 签名长度必须小于 alg.MAX_SIZE 并且
  # 等于剩余的调用数据
  if sig_length > alg.MAX_SIZE or sig_length != (len(input) - 64):
    return bytes20(0x0)

  # 运行验证函数
  return alg.verify(input[64:64 + sig_length], hash)

原理

y_parityrs 值设置为零而不是删除它们

y_parityrs 值保留在交易中可以保持以前的解析、验证和处理逻辑不变,并允许对其他规范进行最小的修改,同时仍然防止过度占用空间。

不透明的 signature_info 类型

由于每种算法都具有独特的属性,即签名恢复和密钥大小,因此需要一个对象来保存每个可能的密钥和签名的所有排列。动态大小的字节数组可以实现此目标,但这会导致 DoS 向量,Gas 惩罚 部分以及 MAX_SIZE 参数解决了这个问题。

Gas 惩罚

拥有多种不同的算法会导致多种不同的签名大小和验证成本。因此,每种比默认 ECDSA secp256k1 曲线更昂贵的签名算法都会产生额外的 gas 惩罚,这是为了阻止毫无特定原因地使用过于昂贵的算法。

GAS_PER_ADDITIONAL_VERIFICATION_BYTE 值为 16 取自交易的 calldata 成本,因为它是一种类似的数据类型,并且必须无限期地保持存在以确保以后的验证。

不添加 secp256k1 曲线

secp256k1 设置类型允许在网络上存在同一对象的多次迭代。此外,此曲线的唯一目的将是与客户端团队一起进行原型设计和测试,因为生成的收据、日志和状态更改将与未包装的交易相同。

不指定帐户密钥共享/迁移

允许单个帐户共享多个密钥会带来安全风险,因为它会将安全性降低到最弱的算法。这也不在本 EIP 的范围内,可以通过未来的 EIP 来实现。

保持相似的地址而不是引入新的地址格式

虽然为每种新算法添加一个新的地址格式将确保永远不会发生冲突,并且安全性不受最低公分母的限制,但必须进行的更改数量和向后兼容性问题将太大而无法保证这一点。

与修改 ecrecover 预编译合约相比,新的预编译合约

最初,与创建新的预编译合约相比,将选择修改 ecrecover 预编译合约,但是,在实现起来过于复杂或可能破坏向后兼容性之后,这一点被排除在外。

硬分叉优于 EIP‑4337 帐户抽象

本 EIP 允许 EIP‑4337 Bundler 使用不同的算法在链上结算 UserOperation,如果后量子问题导致 secp256k1 曲线被逐步淘汰,这在未来可能是唯一的选择。

向后兼容性

非 EIP-7932 交易仍将包含在区块中,并将被视为默认的 secp256k1 曲线。因此,处理其他交易将不会有向后兼容性问题。但是,由于添加了新的 EIP-2718 交易,因此未升级的客户端将无法处理这些交易或包含这些交易的区块。

测试用例

这些测试用例不涉及处理其他类型的交易。仅涉及这些交易的包装、解包和验证,而不与 parent 交易交互。

以下所有测试用例都使用 算法规范部分 中指定的示例 eip 中的参数,此外还添加了一个 0xfe 算法类型,该类型将始终返回 0x0

这些测试用例可以在 此处 以 JSON 格式找到

安全注意事项

允许更多可能为单个帐户创建交易的方式可能会降低该特定帐户的整体安全性,但是,通过增加试验所有算法所需的处理能力,可以部分缓解这种情况。即便如此,添加额外的算法可能需要进一步讨论,以确保网络的安全性不会受到损害。

使 signature_info 没有具体的类型会创建一个机会,即算法逻辑可能会被错误地指定或实现,这可能导致,在最好的情况下,无效的区块,或者在最坏的情况下,允许任何人为任何帐户签署欺诈性交易。此安全注意事项已委派给算法规范,因此在编写这些算法规范时必须小心,以避免出现严重的安全漏洞。

版权

通过 CC0 放弃版权和相关权利。

Citation

Please cite this document as:

James Kempton (@SirSpudlington), "EIP-7932: 算法交易包装器 [DRAFT]," Ethereum Improvement Proposals, no. 7932, April 2025. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7932.