You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在ethers中能否嵌套发送不同签名者的已签名消息以实现联合签名?

嵌套联合签名方案实现说明

Ethers.js 完全支持在已签名消息内嵌套其他签名者签署的已签名消息,这种方案可以实现你需要的联合签名能力,同时将大部分编码、拼接逻辑转移到链下执行,有效降低链上gas消耗,具体实现逻辑如下:

链下签名流程

  • 签名本身本质是对任意字节内容的哈希运算后再做私钥签名,所以你可以将第一个签名者生成的签名、原始消息、签名地址作为字段,打包成新的待签名内容,再交给第二个签名者做签名即可。
  • 更推荐使用 EIP-712 结构化签名 实现,不需要手动拼接字符串,自定义结构体时直接将内层签名相关字段作为结构体成员即可,编码和解码都更安全,也更容易避免哈希不一致的问题。

Ethers 端示例代码(v6版本)

// 第一步:生成内层签名
const innerBusinessData = {
  orderId: 12345,
  amount: ethers.parseEther("1")
};
// 普通签名直接调用signMessage即可,复杂场景推荐替换为EIP-712签名
const innerSig = await signerA.signMessage(ethers.encodeBytes32String(JSON.stringify(innerBusinessData)));
const innerSignerAddr = await signerA.getAddress();

// 第二步:构造外层待签名内容,嵌套内层的所有数据
const outerSignContent = {
  innerData: innerBusinessData,
  innerSig: innerSig,
  innerSigner: innerSignerAddr,
  deadline: Math.floor(Date.now() / 1000) + 86400
};
const outerSig = await signerB.signMessage(ethers.encodeBytes32String(JSON.stringify(outerSignContent)));

// 最终将上述所有字段提交到链上做校验即可

链上校验逻辑

智能合约侧不需要做复杂的编码运算,只需要按照约定的编码规则依次校验各层签名合法性即可:

  1. 先取出内层原始业务数据,按照约定规则生成哈希,调用ecrecover(或OpenZeppelin的ECDSA库)还原内层签名地址,和提交的内层签名地址比对
  2. 内层校验通过后,再将内层所有数据和外层字段拼接生成哈希,同理校验外层签名的合法性
  3. 所有签名校验通过后即可执行后续业务逻辑

合约侧伪代码示例

// 引入OpenZeppelin的ECDSA工具库
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

contract NestedSigVerifier {
    using ECDSA for bytes32;

    function verifyCoSign(
        bytes calldata innerData,
        bytes calldata innerSig,
        address innerSigner,
        uint256 deadline,
        bytes calldata outerSig,
        address outerSigner
    ) external view returns (bool) {
        // 校验有效期
        require(deadline > block.timestamp, "signature expired");

        // 校验内层签名
        bytes32 innerHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(innerData)));
        if (innerHash.recover(innerSig) != innerSigner) return false;

        // 校验外层签名
        bytes32 outerHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encode(innerData, innerSig, innerSigner, deadline))));
        return outerHash.recover(outerSig) == outerSigner;
    }
}

注意事项

  • 必须严格对齐链下和链上的消息编码规则,包括字符串拼接顺序、编码格式、EIP-712的domain参数等,否则会出现签名校验失败的问题
  • 该方案可以扩展到任意多签名者的联合签名场景,链上只需要增加对应次数的ecrecover校验即可,gas消耗增长极低
  • 普通signMessage生成的签名前缀是固定的\x19Ethereum Signed Message:\n,链上校验时记得要加上该前缀再算哈希,避免校验不通过

内容的提问来源于stack exchange,提问作者rami1988

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 11:42:00