---
title: "계정 추상화 4부: 집계 서명(Aggregate Signatures)"
description: "집계 서명을 활용한 ERC-4337의 혁신을 살펴봅니다. 단일 암호 서명으로 여러 user op 검증을 처리하여 트랜잭션 효율성을 높입니다."
---

## 집계 서명(Aggregate signatures)

현재 구현은 번들 내 각 user op을 개별적으로 검증합니다. 검증을 생각하는 매우 직관적인 방법이지만, 낭비가 있을 수 있습니다. 서명 검증에는 상당한 양의 암호학적 연산이 필요하기 때문에 가스 측면에서 비용이 많이 들 수 있습니다.

**여러 op을 여러 서명 대신 서명 하나로 동시에 검증할 수 있다면 좋지 않을까요?**

이를 위해서는 암호학의 한 개념인 **집계 서명(aggregate signatures)**이 필요합니다.

집계를 지원하는 서명 스킴은, 서로 다른 키로 서명된 여러 메시지가 주어졌을 때 하나의 결합된 서명을 생성하는 방법을 제공하며, 이 결합된 서명을 검증하면 구성 서명들이 모두 유효하다는 것을 의미하게 됩니다.

집계를 지원하는 서명 스킴의 대표적인 예로 [BLS](https://en.wikipedia.org/wiki/BLS_digital_signature)가 있습니다.

이 최적화는 롤업을 구현할 때 특히 유용한데, 롤업의 주요 목표가 데이터 압축이고 서명 집계를 통해 서명 부분을 압축할 수 있기 때문입니다.

서명 집계로 절약되는 공간에 대해 더 알아보려면 [이 주제에 관한 Vitalik의 트윗](https://twitter.com/VitalikButerin/status/1554983955182809088)을 참고하세요.

### 애그리게이터(aggregator) 소개

우선, 번들 내의 모든 user op의 서명을 함께 집계할 수는 없다는 점을 알 수 있습니다. 지갑은 자신에게 주어진 서명을 검증하기 위해 임의의 로직을 자유롭게 사용할 수 있으므로, 같은 번들 안에 다양한 서명 스킴이 존재할 수 있다는 점을 기억하세요.

서로 다른 스킴의 서명은 아마도 집계할 수 없으므로, 번들은 결국 op들의 그룹으로 구성되며, 각 그룹은 고유한 집계 스킴을 사용하거나 아예 집계 스킴을 사용하지 않게 됩니다.

체인 상에 각각 고유한 로직을 가진 다양한 집계 스킴을 표현해야 하므로, 각 집계 스킴을 **애그리게이터(aggregator)**라고 부르는 컨트랙트로 표현하겠습니다.

집계 스킴은 여러 서명을 하나로 결합하는 방식과 결합된 서명을 검증하는 방식으로 정의되므로, 애그리게이터는 이 두 기능을 메서드로 노출합니다:

<ImageBlock
  src="https://media.alchemy.com/1704793497-aggregator-contract-combining-user-ops-to-single-signature.jpeg"
  alt="aggregator 컨트랙트는 여러 사용자의 op를 하나의 서명으로 그룹화합니다."
  width={960}
  height={540}
  caption="aggregator 컨트랙트는 여러 사용자의 op를 하나의 서명으로 그룹화합니다."
/>

각 지갑이 자신만의 서명 스킴을 정의하고 있으므로, 어떤 애그리게이터와 호환되는지(호환되는 것이 있다면) 결정하는 것은 각 지갑에 달려 있습니다.

**지갑이 집계에 참여하고자 한다면, 자신의 애그리게이터를 선택하는 메서드를 노출합니다:**

이 새로운 `getAggregator` 메서드를 사용하여, 번들러는 같은 애그리게이터를 가진 op들을 그룹으로 묶고, 해당 애그리게이터의 `aggregateSignatures` 메서드를 사용해 그것들의 결합된 서명을 계산할 수 있습니다.

**그룹은 다음과 같은 모습일 수 있습니다:**

<CalloutBlock>

💡 번들러가 특정 애그리게이터에 대한 오프체인 지식을 가지고 있다면, `aggregateSignatures`를 EVM 코드로 실행하는 대신 서명 집계 알고리즘의 네이티브 버전을 하드코딩하여 최적화할 수 있습니다.

</CalloutBlock>

다음으로, 새로운 애그리게이터를 활용할 수 있도록 엔트리 포인트 컨트랙트를 업데이트해야 합니다.

엔트리 포인트에는 op 목록을 받는 `handleOps` 메서드가 있었던 것을 기억하세요.

**여기에 새로운 메서드인** `handleAggregatedOps`**를 추가하겠습니다. 이 메서드는 동일한 작업을 수행하지만, op들이 애그리게이터별로 그룹화되어 입력됩니다:**

새로운 메서드인 `handleAggregatedOps`는 `handleOps`과 대체로 동일하게 동작합니다. 유일한 차이점은 검증 단계에 있습니다.

`handleOps`이 각 지갑의 `validateOp` 메서드를 호출하여 검증을 수행하는 반면, `handleAggregatedOps`는 대신 각 그룹의 애그리게이터를 사용하여 해당 그룹의 결합된 서명에 대해 애그리게이터의 `validateSignatures` 메서드를 호출합니다.

<ImageBlock
  src="https://media.alchemy.com/1703863779-account-abstraction-key-concepts.jpeg"
  alt="다이어그램: executor가 entry point로 전송하기 전에 aggregator를 사용해 user op를 그룹화하여 일괄 검증을 준비하는 과정"
  width={960}
  height={540}
  caption="executor는 aggregator를 사용해 op를 그룹화한 뒤 entry point로 전송하여 한 번에 검증되도록 합니다."
/>

거의 다 됐습니다!

하지만 지금쯤이면 익숙할 문제가 하나 있습니다.

번들러는 애그리게이터가 op 그룹을 검증에 성공시킬 것인지 시뮬레이션을 통해 확인하고자 합니다. 검증에 실패하면 번들러가 가스 비용을 부담해야 하기 때문입니다. 하지만 임의의 로직을 가진 애그리게이터는 시뮬레이션에서는 쉽게 성공하고 실행 시에는 실패할 수 있습니다.

이는 페이마스터와 팩토리에서 했던 것과 정확히 같은 방식으로 해결하겠습니다: 애그리게이터가 접근할 수 있는 [스토리지](https://www.alchemy.com/docs/smart-contract-storage-layout)와 사용할 수 있는 opcode를 제한하고, 스토리지에 접근하지 않는 경우가 아니라면 엔트리 포인트에 ETH를 스테이킹하도록 요구합니다.

이것으로 집계 서명에 대한 설명을 마칩니다!

### 마무리

여기까지 만들어낸 것은 사실상 [ERC-4337의 전체 아키텍처](https://eips.ethereum.org/EIPS/eip-4337)입니다! 일부 메서드의 이름과 인자 등 세부 사항에서 차이가 있긴 하지만, 아키텍처상의 차이라고 부를 만한 것은 더 이상 없습니다. 제가 설명을 잘 했다면, 이제 여러분은 실제 ERC-4337을 읽고 무슨 내용인지 이해할 수 있을 것입니다.

여기까지 읽으셨다면, 제 설명을 읽어주셔서 정말 감사합니다! 이 글을 쓰면서 저에게 도움이 되었던 만큼 여러분에게도 도움이 되었기를 바랍니다.

## 부록: ERC-4337과의 차이점

지금까지 계정 추상화의 전체적인 아키텍처를 살펴보았지만, ERC-4337을 만든 똑똑한 사람들은 위에서 설명한 것과 약간 다른 몇 가지 사항을 고안했습니다.

몇 가지를 살펴보겠습니다!

### 1. 검증 시간 범위

위에서는 지갑의 `validateOp`과 페이마스터의 `validatePaymasterOp`의 반환 타입에 대해 다소 모호하게 설명했습니다. ERC-4337은 이를 잘 활용하는 방법을 찾았습니다.

지갑이 매우 하고 싶어 할 만한 것 중 하나는 user op이 일정 시간 동안만 유효하도록 하는 것입니다. 그렇지 않으면 악의적인 번들러가 해당 op을 아주 오랫동안 보류했다가, 나중에 자신에게 유리한 시점에 번들에 포함시킬 수 있습니다.

지갑은 이를 방지하기 위해 검증 중에 `TIMESTAMP`을 확인하여 그 값이 너무 먼 미래가 아닌지 검사하고 싶을 수 있지만, 그럴 수 없습니다. 시뮬레이션이 부정확해지는 것을 막기 위해 검증 중 `TIMESTAMP`를 금지했기 때문입니다. 즉, 지갑은 op이 유효한 시간대를 나타낼 다른 방법이 필요합니다.

**따라서 ERC-4337은** `validateOp`**에 지갑이 시간 범위를 선택할 수 있는 반환값을 부여합니다:**

이 반환값은 op이 유효한 시간 범위를 8바이트 정수 두 개를 이어붙인 형태로 나타냅니다.

ERC-4337에서 언급하는 또 다른 사항: 지갑은 검증 실패 시 revert하는 대신 validateOp에서 특정 sentinel 값을 반환해야 합니다. 이는 가스 추정에 도움이 되는데, [eth_estimateGas](https://www.alchemy.com/docs/chains/ethereum/ethereum-api-endpoints/eth-estimate-gas)는 revert된 트랜잭션에서 얼마나 많은 가스가 사용되었는지 알려주지 않기 때문입니다.

### 2. 지갑과 팩토리를 위한 임의의 콜 데이터

우리는 지갑의 인터페이스가 다음과 같다고 설명했습니다:

ERC-4337에서 지갑은 실제로 `executeOp`이라는 이름의 메서드를 가지고 있지 않습니다.

**대신, user operation은** `callData`** 필드를 가집니다:**

이 값은 콜 데이터로서 지갑에 전달됩니다.

일반적인 스마트 컨트랙트의 경우, 이 데이터의 처음 4바이트는 함수 셀렉터로, 나머지는 함수 인자로 해석됩니다.

즉, 필수적인 `validateOp` 메서드를 제외하면 지갑은 자신만의 인터페이스를 자유롭게 정의할 수 있으며, user operation을 사용해 지갑의 임의의 메서드를 호출할 수 있습니다.

같은 맥락에서, ERC-4337의 팩토리 컨트랙트도 실제로는 `deployContract`라는 메서드를 가지고 있지 않습니다. 팩토리 역시 임의의 콜 데이터를 받는데, 이 경우에는 op의 `initCode` 필드로부터 받습니다.

### 3. 페이마스터와 팩토리를 위한 압축된 데이터

위에서는 user operation이 페이마스터를 지정하는 필드와 페이마스터에 전달할 데이터를 지정하는 필드를 각각 포함한다고 설명했습니다:

**ERC-4337에서는 이 두 필드가 최적화를 위해 하나의 필드로 결합되며, 필드의 처음 20바이트는 페이마스터 주소이고 나머지는 데이터입니다:**

팩토리와 팩토리에 전달되는 데이터도 마찬가지입니다: 우리는 `factory`과 `factoryData`라는 두 개의 필드를 사용했지만, ERC-4337은 이를 `initCode`이라는 하나의 필드로 결합합니다.

자, 해내셨습니다!

계정 추상화에 대해 많은 것을 배우셨기를 바랍니다.

### 계정 추상화, 당신도 발명할 수 있었다

이 4부작 시리즈의 시작 부분을 놓치셨나요? 처음부터 다시 읽어보세요!

1. [계정 추상화 1부: 우리의 자산 보호하기](https://www.alchemy.com/overviews/what-is-account-abstraction)
1. [계정 추상화 2부: 페이마스터로 트랜잭션 후원하기](https://www.alchemy.com/overviews/what-is-account-abstraction-paymasters)
1. [계정 추상화 3부: 지갑 생성](https://www.alchemy.com/overviews/what-is-account-abstraction-wallet-creation)
