---
title: "Abstracción de cuentas parte 4: firmas agregadas"
description: "Explora el avance de ERC-4337 con firmas agregadas. Simplifica la validación de múltiples user ops usando una sola firma criptográfica, mejorando la eficiencia de las transacciones."
---

## Firmas agregadas

Nuestra implementación actual valida cada user op del bundle por separado. Es una forma muy directa de pensar la validación, pero potencialmente ineficiente. Verificar firmas puede terminar siendo costoso en términos de gas porque requiere bastante aritmética criptográfica.

**¿No sería bueno poder validar muchas ops al mismo tiempo con una sola firma en lugar de muchas?**

Hacerlo depende de un concepto de la criptografía: las **firmas agregadas**.

Un esquema de firmas que soporta agregación provee una forma, dados múltiples mensajes firmados con distintas claves, de generar una única firma combinada tal que verificar la firma combinada implica que todas las firmas que la componen también son válidas.

Un ejemplo común de un esquema de firmas que soporta agregación es [BLS](https://en.wikipedia.org/wiki/BLS_digital_signature).

Esta optimización es particularmente útil para implementar rollups, ya que el objetivo principal de un rollup es la compresión de datos, y la agregación de firmas nos permite comprimir la parte correspondiente a las firmas.

Para más información sobre el ahorro de espacio que produce la agregación de firmas, ver [el tweet de Vitalik sobre el tema](https://twitter.com/VitalikButerin/status/1554983955182809088).

### Presentando los aggregators

De inmediato, vemos que no todas las user ops de un bundle pueden tener sus firmas agregadas entre sí. Recordemos que una wallet tiene permitido usar la lógica arbitraria que quiera para validar la firma que recibe, por lo que puede haber varios esquemas de firma presentes en el mismo bundle.

Como probablemente no podamos agregar firmas de distintos esquemas, nuestro bundle terminará con grupos de ops, cada grupo usando un esquema de agregación distinto o ningún esquema de agregación.

Como necesitamos tener varios esquemas de agregación representados on chain, cada uno con su propia lógica, haremos que cada esquema de agregación esté representado por un contrato que llamaremos **aggregator**.

Un esquema de agregación se define por cómo combina múltiples firmas en una y por cómo valida la firma combinada, así que un aggregator expone estas dos funciones como métodos:

<ImageBlock
  src="https://media.alchemy.com/1704793497-aggregator-contract-combining-user-ops-to-single-signature.jpeg"
  alt="Un contrato agregador combina operaciones de múltiples usuarios en un grupo con una sola firma."
  width={960}
  height={540}
  caption="Un contrato agregador combina operaciones de múltiples usuarios en un grupo con una sola firma."
/>

Como cada wallet define su propio esquema de firma, depende de cada wallet decidir con qué aggregator es compatible, si es que lo es con alguno.

**Si una wallet quiere participar en la agregación, expone un método para elegir su aggregator:**

Usando este nuevo método `getAggregator`, el bundler puede agrupar las ops que tienen el mismo aggregator y usar el método `aggregateSignatures` de ese aggregator para calcular una firma combinada para ellas.

**Un grupo podría verse así:**

<CalloutBlock>

💡 Si un bundler tiene conocimiento off-chain sobre un aggregator en particular, puede optimizar codificando de forma nativa una versión del algoritmo de agregación de firmas en lugar de ejecutar `aggregateSignatures` como código EVM.

</CalloutBlock>

A continuación, necesitamos actualizar el contrato entry point para que haga uso de los nuevos aggregators.

Recordemos que el entry point tiene un método `handleOps` que recibe una lista de ops.

**Le daremos un nuevo método,** `handleAggregatedOps`**, que hace lo mismo pero recibe las ops agrupadas por aggregator:**

El nuevo método, `handleAggregatedOps`, funciona en gran medida igual que `handleOps`. La única diferencia está en su paso de validación.

Mientras que `handleOps` realiza la validación llamando al método `validateOp` de cada wallet, `handleAggregatedOps` en cambio llamará al método `validateSignatures` del aggregator sobre la firma combinada de cada grupo, usando el aggregator de ese grupo.

<ImageBlock
  src="https://media.alchemy.com/1703863779-account-abstraction-key-concepts.jpeg"
  alt="Diagrama: el executor agrupa las user ops con el aggregator antes de enviarlas al entry point para su validación por lotes"
  width={960}
  height={540}
  caption="El executor usa el aggregator para agrupar las operaciones antes de enviarlas al entry point, de modo que todas puedan validarse al mismo tiempo."
/>

¡Ya casi terminamos!

Pero hay un problema aquí que ya nos resulta bastante familiar.

El bundler quiere simular la validación y comprobar que el aggregator validará un grupo de ops antes de incluirlas en el bundle, porque si la validación falla, el bundler se ve obligado a pagar el gas. Pero un aggregator con lógica arbitraria puede fácilmente tener éxito durante la simulación y fallar durante la ejecución.

Resolveremos esto exactamente de la misma forma en que lo hicimos para los paymasters y las factories: restringimos qué [storage](https://www.alchemy.com/docs/smart-contract-storage-layout) puede acceder el aggregator y qué opcodes puede usar, y exigimos que haga stake de ETH en el entry point a menos que no acceda a storage.

¡Y eso es todo respecto a las firmas agregadas!

### Cierre

Lo que hemos creado aquí es, más o menos, la [arquitectura completa de ERC-4337](https://eips.ethereum.org/EIPS/eip-4337). Hay algunas diferencias en los detalles, como los nombres y argumentos de algunos de los métodos, pero no queda nada que yo consideraría una diferencia arquitectónica. Si hice bien mi trabajo, ahora deberías poder leer el ERC-4337 real y entender qué está pasando.

Si llegaste hasta acá, ¡muchas gracias por leer esta explicación! Espero que te haya ayudado tanto como a mí me ayudó escribirla.

## Apéndice: diferencias con ERC-4337

Si bien ya tenemos clara la arquitectura general de la abstracción de cuentas, las personas inteligentes detrás de ERC-4337 pensaron en algunas cosas que son ligeramente distintas de lo que describimos arriba.

¡Repasemos algunas de ellas!

### 1. Rangos de tiempo de validación

Arriba fui bastante vago respecto al tipo de retorno del `validateOp` de la wallet y del `validatePaymasterOp` del paymaster. ERC-4337 encuentra una buena manera de aprovechar esto.

Algo que a una wallet le gustaría mucho hacer es permitir que una user op sea válida solo durante cierto período de tiempo. De lo contrario, un bundler malicioso podría quedarse con esa operación durante mucho tiempo y luego incluirla en un bundle mucho después, en un momento que le resulte ventajoso al bundler.

La wallet podría querer defenderse de esto verificando el `TIMESTAMP` durante la validación para asegurarse de que no esté demasiado lejos en el futuro, pero no puede, porque hemos prohibido `TIMESTAMP` durante la validación para evitar que las simulaciones sean inexactas. Esto significa que la wallet necesita otra forma de indicar en qué momentos la operación es válida.

**Por eso, ERC-4337 le da a** `validateOp` **un valor de retorno que la wallet puede usar para elegir un rango de tiempo:**

Este valor de retorno representa el rango de tiempo en el que la operación es válida como dos enteros de 8 bytes, uno después del otro.

Otra nota de ERC-4337: las wallets deberían devolver un valor centinela desde validateOp en lugar de revertir en caso de fallo de validación, lo cual ayuda con la estimación de gas, porque [eth_estimateGas](https://www.alchemy.com/docs/chains/ethereum/ethereum-api-endpoints/eth-estimate-gas) no indica cuánto gas se usó en una transacción que revierte.

### 2. Call data arbitrario para wallets y factories

Dijimos que la interfaz de nuestra wallet era:

En ERC-4337, las wallets en realidad no tienen un método llamado `executeOp`.

**En cambio, la user operation tiene un campo** `callData`**:**

Esto se pasa a la wallet como call data.

Para un contrato inteligente típico, los primeros cuatro bytes de estos datos se interpretarán como un selector de función y el resto como argumentos de la función.

Esto significa que, aparte del método requerido `validateOp`, las wallets pueden definir su propia interfaz, y las user operations pueden usarse para llamar a métodos arbitrarios de la wallet.

De manera similar, en ERC-4337 los contratos factory tampoco tienen realmente un método `deployContract`. Ellos también reciben call data arbitrario, en este caso desde el campo `initCode` de la op.

### 3. Datos compactos para paymasters y factories

Arriba dijimos que la user operation contenía campos para especificar un paymaster, así como qué datos pasarle:

**En ERC-4337, estos se combinan en un solo campo como optimización, donde los primeros 20 bytes del campo son la dirección del paymaster y el resto son los datos:**

Lo mismo ocurre con las factories y los datos que se les envían: mientras que nosotros usamos dos campos, `factory` y `factoryData`, ERC-4337 los combina en un solo campo, `initCode`.

Bueno, ¡lo lograste!

Esperamos que hayas aprendido mucho sobre la Abstracción de Cuentas.

### Podrías haber inventado la abstracción de cuentas

¿Te perdiste el comienzo de esta serie de 4 partes? ¡Vuelve atrás y léela desde el principio!

1. [Abstracción de Cuentas Parte 1: Protejamos Nuestros Activos](https://www.alchemy.com/overviews/what-is-account-abstraction)
1. [Abstracción de Cuentas Parte 2: Patrocinando Transacciones con Paymasters](https://www.alchemy.com/overviews/what-is-account-abstraction-paymasters)
1. [Abstracción de Cuentas Parte 3: Creación de Wallets](https://www.alchemy.com/overviews/what-is-account-abstraction-wallet-creation)
