理解账户抽象 #4:聚合签名

Coset2023-03-26 08:26
  • 原文链接:https://www.alchemy.com/blog/account-abstraction-aggregate-signatures
  • 译文出自:登链翻译计划[1]
  • 译者:Tiny 熊[2]

这里理解账户抽象的第 4 篇,前面几篇为:

  1. 从零开始设计智能合约钱包[3];

  2. 使用 Paymaster 赞助交易[4];

  3. 使用 create2 创建钱包[5];

  4. (本文)使用 聚合签名[6]

聚合签名

我们目前的实现是分别验证捆绑在一起的每个用户操作。这是一种非常直接的验证方式,但有可能造成浪费。检查签名最终可能会导致昂贵的 Gas,因为这样做需要相当多的密码运算。

我们可以用一个签名而不是许多签名来同时验证许多操作,这不是很好吗?

要做到这一点取决于密码学的一个概念,聚合签名(aggregate signatures)。

一个支持聚合的签名方案提供了一种方法,给定多个用不同密钥签名的信息,生成一个单一的组合签名,这样,验证组合签名就意味着所有的组成签名也是有效的。

支持聚合的签名方案的一个常见例子是BLS[7]。

这种优化对实现 rollup 特别有用,因为 rollup 的主要目标是数据压缩,而签名聚合让我们压缩签名部分数据大小。

关于签名聚合节省空间的更多信息,请参见Vitalik 关于这个问题的推特[8]。

聚合器的介绍

马上,我们就会看到,并不是一个捆绑包(bundle)中的所有用户操作都可以将其签名聚合在一起。请记住,一个钱包被允许使用任何想要的逻辑来验证给定的签名,所以在同一个捆绑中可能有各种签名方案。

由于我们可能无法聚合不同方案的签名,我们的捆绑包最终会有几组操作,每组使用不同的聚合方案或根本没有聚合方案。

由于我们需要在链上代表各种聚合方案,每个方案都有自己的逻辑,我们将用一个合约来代表每个聚合方案,我们称之为聚合器。

聚合方案是指:如何将多个签名合并成一个签名以及如何验证合并后的签名 ,所以聚合器将这两个功能作为函数公开:

contract Aggregator {
  function aggregateSignatures(UserOperation[] ops)
    returns (bytes aggregatedSignature)
;

  function validateSignatures(UserOperation[] ops, bytes signature);
}

聚合器合约将来自多个用户的操作组合成一个具有单一签名的组。

由于每个钱包都在定义自己的签名方案,因此由每个钱包决定它与哪个聚合器兼容,如果有的话。

如果一个钱包想参与聚合,它得暴露一个方法来选择它的聚合器:

contract Wallet {
  // ...

  function getAggregator() returns (address);
}

使用这个新的getAggregator方法,捆绑者可以将具有相同聚合器的操作分组,并使用该聚合器的 aggregateSignatures 方法为它们计算一个组合签名。

一个组可能看起来像这样:

struct UserOpsPerAggregator {
  UserOperation[] ops;
  address aggregator;
  bytes combinedSignature;
}

如果一个捆绑者拥有关于特定聚合器的链外知识,它可以通过硬编码签名聚合算法的原生版本进行优化,而不是作为 EVM 代码运行aggregateSignatures。

接下来,我们需要更新入口点合约以利用新的聚合器。

回顾一下,入口点有一个handleOps方法,它接收一个用户操作(OP)列表。

我们将给它一个新的方法,handleAggregatedOps,它做同样的事情,但接受按聚合器分组的操作 (Ops):。

contract EntryPoint {
  function handleOps(UserOperation[] ops);

 function handleAggregatedOps(UserOpsPerAggregator[] ops);

  // ...
}

这个新方法,handleAggregatedOps,与 handleOps 的工作原理基本相同。唯一的区别是它的验证步骤。

handleOps 通过调用每个钱包的validateOp方法进行验证,而handleAggregatedOps将调用聚合器的validateSignatures方法对每个组的组合签名使用该组的聚合器。

执行器 (executor) 使用聚合器 (aggregator) 在将用户操作发送到入口点之前将它们组合在一起,因此它们可以同时被验证。

我们几乎完成了!

但这里有一个问题,现在已经很熟悉了。

捆绑者想要模拟验证,并检查聚合器是否会在将一组操作纳入捆绑之前验证这些操作,因为如果验证失败,捆绑者就会被迫支付 Gas 费。但一个具有任意逻辑的聚合器在模拟过程中很容易成功,但在执行过程中却会失败。

我们将以与 paymasters 和工厂完全相同的方式来解决这个问题:我们限制聚合器可以访问哪些存储[9]以及可以使用哪些操作码,并要求它在进入点中存入 ETH,除非它不访问存储。

这就是聚合签名的内容!

总结

我们在这里所创建的或多或少是ERC-4337 的完整架构[10]!在细节上有一些差异,比如一些方法的名称和参数,但没有我认为是架构上的差异。如果我的工作做得很好,你现在应该能够读懂真正的 ERC-4337,并理解发生了什么。

补遗与 ERC-4337 的区别

虽然我们已经有了账户抽象的整体架构,但 ERC-4337 背后的聪明人想到了一些与我们上述描述略有不同的东西。

让我们来看看其中的一些差别:

1. 验证时间范围

上面,我们文中对钱包的validateOp和 paymaster 的validatePaymasterOp的返回类型相当模糊。ERC-4337 找到了一个很好的方法来利用这个。

钱包非常想做的事情是只允许用户操作在一定时间内有效。否则,一个流氓捆绑者可以在该操作保持很长时间,然后在对捆绑者有利的时候将其纳入捆绑。

钱包可能想通过在验证过程中检查TIMESTAMP来防御这种情况,以确保它不会在太久之后执行,但钱包做不到,因为我们在验证过程中禁止TIMESTAMP来阻止模拟的不准确。这意味着钱包需要另一种方式来表明在什么时候操作是有效的。

因此,ERC-4337 给了 validateOp 一个返回值,钱包可以用它来选择一个时间范围:

contract Wallet {
  function validateOp(UserOperation op, uint256 requiredPayment)
    returns (uint256 sigTimeRange)
;
  // ...
}

这个返回值表示操作有效的时间范围,是两个挨着的 8 字节整数。

来自 ERC-4337 的另一个说明:钱包应该从validateOp返回一个哨兵值,而不是在验证失败的情况下回退,这有助于 Gas 估计,因为eth_estimateGas[11]不会告诉你在一个回退的交易中使用了多少 Gas。

2. 钱包和工厂的任意调用数据

我们的钱包的接口是:

contract Wallet {
  function validateOp(UserOperation op, uint256 requiredPayment);
  function executeOp(UserOperation op);
}

在 ERC-4337 中,钱包的实际上并没有一个名为executeOp的方法。

相反,用户操作(UserOperation)有一个 callData 字段:

struct UserOperation {
  // ...
  bytes callData;
}

这将作为调用数据传递给钱包。

对于一个典型的智能合约,这个数据的前四个字节将被解释为一个函数选择器,其余的是函数参数。

这意味着,除了必要的验证 Op 方法外,钱包可以定义自己的接口,用户操作可以用来调用钱包上的任意方法。

按照同样的思路,在 ERC-4337 中,工厂合约实际上并没有deployContract方法。他们也接收任意的调用数据,在此案例中,是来自操作的initCode字段。

3. paymaster 和工厂的数据压缩

上面我们说过,用户操作包含的字段可以指定一个付款人,以及要传递给它的数据:

struct UserOperation {
  // ...
  address paymaster;
  bytes paymasterData;
}

在 ERC-4337 中,这些字段被合并为一个字段,作为一种优化,其中字段的前 20 个字节是付款人地址,其余的是数据:

struct UserOperation {
  // ...
  bytes paymasterAndData;
}

对于工厂和发送到工厂的数据也是如此:虽然我们使用两个字段 factory 和 factoryData,但 ERC-4337 将这些字段合并为一个字段initCode。

关于账户抽象的分享到这里了, 我们希望你学到了很多关于账户抽象的知识。


参考资料

[1]

登链翻译计划: https://github.com/lbc-team/Pioneer

[2]

Tiny 熊: https://learnblockchain.cn/people/15

[3]

从零开始设计智能合约钱包: https://learnblockchain.cn/article/5426

[4]

使用 Paymaster 赞助交易: https://learnblockchain.cn/article/5432

[5]

使用 create2 创建钱包: https://learnblockchain.cn/article/5442

[6]

(本文)使用 聚合签名: https://learnblockchain.cn/article/5483

[7]

BLS: https://en.wikipedia.org/wiki/BLS_digital_signature

[8]

Vitalik 关于这个问题的推特: https://twitter.com/VitalikButerin/status/1554983955182809088

[9]

存储: https://docs.alchemy.com/docs/smart-contract-storage-layout

[10]

ERC-4337 的完整架构: https://eips.ethereum.org/EIPS/eip-4337

[11]

eth_estimateGas: https://docs.alchemy.com/reference/eth-estimategas


推荐阅读


Antalpha Labs 是一个非盈利的 Web3 开发者社区,致力于通过发起和支持开源软件推动 Web3 技术的创新和应用。

官网:https://labs.antalpha.com

Twitter:https://twitter.com/Antalpha_Labs

Youtube:https://www.youtube.com/channel/UCNFowsoGM9OI2NcEP2EFgrw

联系我们:hello.labs@antalpha.com

【免责声明】市场有风险,投资需谨慎。本文不构成投资建议,用户应考虑本文中的任何意见、观点或结论是否符合其特定状况。据此投资,责任自负。

来源链接

相关Wiki

相关标签