在 Wake 测试中签名消息:EIP-712、EIP-191 和哈希

  • Ackee
  • 发布于 1天前
  • 阅读 74

本文介绍了如何在 Wake 测试框架中使用 Account 对象生成签名,包括原始消息签名(EIP-191)、结构化消息签名(EIP-712)和低级哈希签名,并提供了签名测试的hardening技巧以及一个简单的permit测试示例,从而可以在测试中验证签名逻辑而无需外部钱包。

为什么签名在测试中很重要

类型签名驱动许可流程、元交易和链下审批。能够在测试中生成它们,可以让你在不连接外部钱包的情况下确认你的验证逻辑。Wake 在 Account 上公开了一个重点 API,涵盖了三个常见的场景:原始消息签名 (sign)、EIP-712 结构化签名 (sign_structured) 和底层哈希签名 (sign_hash)。本指南将官方的 账户和地址 文档提炼成你可以直接放入测试中的实际例子。

准备一个带有私钥的账户

Wake 只有当账户持有私钥时才会签名。你可以在一行中导入或生成一个:

from wake.testing import Account

account = Account.from_mnemonic(" ".join(["test"] * 11 + ["junk"]))
## 其他选项:
## Account.from_key("0x" + "a" * 64)
## Account.from_alias("alice")  # 使用配置文件中的别名
## Account.new()                # 新的随机密钥

该账户现在已准备好进行交易和所有三种签名模式。

签署原始消息 (EIP-191)

使用 Account.sign 处理人类可读的字节,例如当你在测试中需要 personal_sign 风格的流程时:

from wake.testing import Account

account = Account.from_mnemonic(" ".join(["test"] * 11 + ["junk"]))
signature = account.sign(b"Hello, world!")

Wake 会自动应用 EIP-191 前缀(版本 0x45),因此签名与标准钱包行为匹配。对于 UX 提示或有意避免类型数据的遗留流程,请使用此模式。

签署结构化消息 (EIP-712)

类型化数据使审批保持明确。Wake 使用数据类和显式域镜像 EIP-712 管道:

from dataclasses import dataclass
from wake.testing import *

@dataclass
class Transfer:
    sender: Address
    recipient: Address
    amount: uint256

account = Account.from_mnemonic(" ".join(["test"] * 11 + ["junk"]))
signature = account.sign_structured(
    Transfer(
        sender=account.address,
        recipient=Address(1),
        amount=10,
    ),
    domain=Eip712Domain(
        name="Test",
        chainId=chain.chain_id,
        verifyingContract=Address(0),  # 如果需要,设置为你的合约
    ),
)

Wake 构建类型字符串,Hash 每个字段,并签署 EIP-712 摘要。在协议测试中,将其与 Solidity 函数(例如 hashTypedData)配对使用,以确认合约在验证签名之前计算出相同的摘要。

签署预先计算的哈希值

仅当外部 API 已经给你摘要时才使用 Account.sign_hash。此方法会跳过前缀并按原样签署字节:

from wake.testing import *

account = Account.from_mnemonic(" ".join(["test"] * 11 + ["junk"]))
message_hash = keccak256(b"Hello, world!")
signature = account.sign_hash(message_hash)

当你必须匹配已知哈希值时(例如合约的 hashTypedData 输出),请使用此方法。如果你不控制或不理解原像,请不要签署它。

签名测试的强化技巧

  • 对齐域:确保 nameversionchainIdverifyingContract 在 Wake 和合约代码之间完全匹配。
  • 分隔原始流程和类型化流程:使用 sign 处理带有前缀的个人消息,使用 sign_structured 处理类型化数据,并使用 sign_hash 处理刻意的极端情况。
  • 标记测试参与者:chain.accounts[i].label = "ALICE" 提高了跟踪可读性,而不会影响行为。
  • 捕获失败时的跟踪:使用 @on_revert 包装测试,并在调试与签名相关的还原时打印 e.tx.call_trace
  • 断言端到端:在 Solidity 内部,重新计算摘要并检查 ecrecover 是否返回 account.address,以便尽早捕获编码错误。

一个简单的许可测试方案

  1. 将许可结构定义为 Wake 数据类,镜像 Solidity 结构。
  2. 使用合约的实际名称、版本、链 ID 和验证地址构建域。
  3. 使用 sign_structured 生成签名,并在测试中调用许可或验证函数。
  4. 在 Solidity 中重新计算摘要,并确保 ecrecover 产生你的签名者。
  5. 添加模糊测试以测试金额和截止日期,以确认哈希在各种输入中保持稳定。

结论

Wake 的签名助手将类似钱包的界面放入你的测试中,因此你无需连接外部工具即可执行许可流程和类型化审批。对 EIP-712 路径使用 sign_structured,对旧版 Prompts 使用 sign,并将 sign_hash 视为有意的极端情况Hook。API 保持单行,让你专注于断言合约行为,而不是与签名管道搏斗。

  • 原文链接: ackee.xyz/blog/signing-d...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Ackee
Ackee
Cybersecurity experts | We audit Ethereum and Solana | Creators of @WakeFramework , Solidity (Wake) & @TridentSolana | Educational partner of Solana Foundation