들어가며
이달 초 미국에서 열린 ETHdenver 2023 행사에서 새로운 이더리움 업그레이드가 공개되었습니다. 이번 버전에 포함된 업데이트 중에서는 계정 추상화(Account Abstraction) 표준인 ERC-4337이 특히 관심을 받고 있는데요, 기존 이더리움 계정 체계가 가지고 있던 한계를 넘어 편리하고 확장성있는 기능 구현이 가능해질 것이라는 기대감 때문입니다. 이번 포스팅에서는 Account Abstraction이 어떤 기술인지 이해해보고, 앞으로 어떻게 다양한 Use-case로 활용될 수 있을지에 대해 다루어봅니다.
AA(Account Abstraction)는 왜 등장하게 되었을까?
AA(Account Abstraction, 계정 추상화)란 단어 그대로, 이더리움 계정(Account)의 타입에 따른 기능 제약을 극복하기 위해 프로토콜의 상위 레이어에서 계정의 개념을 하나로 추상화하는 기술입니다. AA의 등장 배경을 이해하기 위해서는, 먼저 기존 이더리움 프로토콜에서 ‘계정’이 어떤 특성을 가지는지를 알아야합니다.
‘계정’은 이더리움 프로토콜에서 자산을 거래하고 스마트 계약을 수행하는 과정에서 각 Entity들의 Identity, 즉 구분자로 사용되는 개념입니다. 계정은 크게 일반 계정인 EOA(Externally Owned Accounts)와 컨트랙트에 할당된 계정인 CA(Contract Account)로 구분됩니다. EOA는 일반적인 사용자 계정의 유형으로 계정의 주소를 통제할 수 있는 개인키가 존재하여 트랜잭션을 서명, 실행시킬 수 있습니다. 때문에 해당 계정에서 소유하고 있는 자산을 다른 EOA나 CA에 전송하거나 스마트 컨트랙트를 호출할 수 있습니다. 우리가 보통 암호화폐나 NFT같은 자산들을 보유하기 위해 MetaMask등의 지갑 어플리케이션을 통해 관리하는 계정이 모두 EOA에 해당합니다. 반면 CA는 스마트 컨트랙트를 블록체인에 배포할때 할당되는 계정으로서, 특정 스마트 컨트랙트를 구분하기 위한 용도로 사용됩니다. CA는 별도의 개인키를 가지지 않기 때문에 스스로 트랜잭션을 서명 및 발행할 수 없고, 다른 EOA가 발행한 트랜잭션이나 다른 컨트랙트의 실행에 따른 호출에 의해서만 데이터를 수신받아 내장된 고정 코드를 온체인으로 실행할 수 있습니다. 정리하자면 계정 타입에 따라 EOA는 트랜잭션을 생성 및 실행할 수 있으나 스스로 온체인 코드를 수행할 수 없고, 반대로 CA는 내장된 온체인 코드를 수행할 수 있으나 트랜잭션을 생성할 수 없는 제약이 존재하는 것입니다.
그간 계정 타입에 따른 기능 제약사항은 사용자들로 하여금 많은 불편을 야기해왔습니다. 컨트랙트에서 새로운 트랜잭션을 발생시키거나 컨트랙트를 배포해야 하는 경우 CA로 처리가 불가해 항상 별도의 EOA를 통한 트랜잭션 처리를 수행해야 했으며 이로 인해 기본 가스비도 이중으로 지불해야 하는 불편함이 있었습니다. EOA는 어떨까요? EOA를 사용하기 위해 요구되어왔던 개인키의 안전한 보관은 블록체인의 대중화를 막는 가장 큰 요소 중 하나로 손꼽혀왔습니다. 실제로 비트코인 자산의 약 20%가 EOA 소유자의 개인키 분실로 인해 방치되고 있다는 보고가 있을 정도로 개인키 관리는 매우 번거로운 일입니다. 또한 EOA로부터의 트랜잭션 처리 과정에서 특정 조건(계정별 송신 금액 제한이나 송신처 제한 등)을 적용하고자 하는 경우에도 온체인 코드로의 처리가 불가하여 오프체인 시스템으로 이를 보완해야 했기 때문에 높은 신뢰성을 요구하는 지갑이나 결제 서비스 구현에 많은 노력과 보완 장치 구축이 필요했습니다. AA는 이러한 문제점들을 해결하기 위해 등장한 개념입니다. 계정을 추상화하여 스마트 컨트랙트 형태로 구현함으로서 위와 같은 제약사항을 없애고 다양한 온체인 기능 실행과 트랜잭션의 발행을 모두 가능하게 하는 것이죠. 이를 통해 계정 관리의 불편함과 구현의 한계를 최소화 함으로서 이더리움 어플리케이션의 확장성을 높이는 것이 AA의 도입 목표라고 할 수 있습니다.
ERC-4337로 구현된 AA의 기본 처리 구조
AA는 최초 EIP-2938을 통해 제안되었으나 구현 사항 내에 이더리움 프로토콜의 수정이 포함되어 있어 최종 반영되지 못하였습니다. 이후 표준으로 채택된 ERC-4337의 제안인 EIP-4337에서는 이더리움 프로토콜에서 계정과 트랜잭션을 실제 처리하는 합의 레이어의 구현은 그대로 유지하되, 상위 레이어인 어플리케이션 및 인프라 레이어를 통해 EOA와 CA의 구분 없이 하나의 ‘계정 컨트랙트’를 통해 트랜잭션 처리와 온체인 코드 수행을 모두 가능하도록 했습니다. 어떻게 이러한 구현이 가능했을까요?
Basic Idea: 트랜잭션을 처리하듯, 추상화된 트랜잭션인 User Operation을 처리하자.
ERC-4337에서는 이더리움의 합의 레이어에서 일어나는 프로토콜 처리 과정을 닮은 새로운 레이어를 통해 계정 추상화를 제공합니다. 쉽게 설명하자면, 합의 레이어에서 각 노드들이 Mempool에 수집된 여러 트랜잭션 중 높은 수수료의 트랜잭션들을 골라 하나의 블록으로 제안하는 과정을 본따 이를 어플리케이션 레이어에 구현하고, 이 과정에서 계정의 개념을 통합하여 지원하는 것입니다. 추상화된 레이어에서는 노드 대신 ‘Bundler’라는 새로운 Actor가 등장합니다. 노드와 마찬가지로 이더리움 네트워크에서는 누구나 Bundler로 참여할 수 있으며 이는 분산화된 트랜잭션 처리를 지향하는 이더리움의 철학을 반영합니다. 새로운 레이어에서 사용자들은 트랜잭션 대신 유효한 서명을 포함하는 ‘User Operation’을 생성하고 Bundler의 RPC-Endpoint들을 통해 이를 전달합니다. 이 때 User Operation은 다음과 같은 데이터 구조로 구성되어 있는데, 트랜잭션과 동일하게 sender
, to
, calldata
, maxFeePerGas
, masPriorityFee
, signature
,nonce
등의 필드를 포함합니다.
Field | Type | Description |
---|---|---|
sender | address | 작업을 수행하는 계정 |
nonce | uint256 | anti-replay 파라미터; 최초 계정 생성을 위한 salt로도 사용 |
initCode | bytes | 계정이 아직 on-chain에 없을 때 필요 |
callData | bytes | main execution call 중에 sender에게 보낼 데이터 |
callGasLimit | uint256 | main execution call에 할당할 가스의 양 |
verificationGasLimit | uint256 | verification 단계에서 할당할 가스의 양 |
preVerificationGas | uint256 | pre-verification execution과 callData를 처리한 bundler에게 보상으로 지불할 가스의 양 |
maxFeePerGas | uint256 | EIP-1559 max_fee_per_gas |
maxPriorityFeePerGas | uint256 | EIP-1559 max_priority_fee_per_gas |
paymaster | Address | 트랜잭션 수수료를 대납하는 paymaster 주소 (주소가 0일 경우 수수료는 직접 지불) |
paymasterData | bytes | paymaster에게 보낼 추가 데이터 |
signature | bytes | verification step에서 nonce와 함께 계정으로 전달된 데이터 |
Bundler는 수신한 User Operation들을 전용 Mempool에 수집한 뒤 높은 수수료를 지불하는 User Operation들을 모아 Bundling하여 Bundle Transaction으로 만든 뒤, 이를 검증하고 처리하기 위해 ‘EntryPoint 컨트랙트’를 호출합니다.
EntryPoint 컨트랙트를 통한 UserOperation 처리
이제 User Operation들을 검증하고 실행하기 위한 룰이 필요합니다. EntryPoint 컨트랙트는 User Operation을 검증하고 처리하기 위한 공통 로직이 구현된 스마트 컨트랙트로서, 전체 이더리움 네트워크에서 표준으로 정의된 싱글톤 컨트랙트로 존재합니다. AA를 지원하기 위한 공통 로직을 포함하고 있어 그 신뢰성이 매우 중요하기 때문입니다. 합의 레이어에서 트랜잭션의 검증 및 블록 생성 등의 로직이 프로토콜레벨에서 지원되었다면, AA에서는 이런 로직을 EntryPoint 컨트랙트로 구현 해 온체인 로직 처리가 가능하도록 만든 것이라고 볼 수 있습니다. EntryPoint 컨트랙트에서 지원하는 다양한 인터페이스 중 simulateValidation(UserOperation upserOp)
과 handleOps(UserOperation[] ops, address beneficiary)
함수가 기본적인 User Operation 처리에 사용됩니다.
simulateValidation
함수는 노드가 프로토콜에 따라 트랜잭션의 nonce와 내용, 서명을 검증하는 것과 같이 Bundler가 Mempool로 수집된 User Operation의 서명 및 수수료 지불 가능성을 검증하고자 할 때 호출됩니다. 이러한 검증을 통해 Bundler는 잘못된 User Operation을 요청하여 발생하는 처리 실패로 인한 불필요한 가스 소모를 최소화할 수 있습니다.- 검증이 완료된 User Operation들은 Bundle Transaction으로 가공된 뒤
handleOps
함수를 통해 전달됩니다. 이후 EntryPoint내의 검증 루프(Verficiation loop)와 실행 루프(Execution Loop)를 통해 최종 검증 및 실행이 완료됩니다.
실제 비즈니스 로직 처리는 다시 계정 컨트랙트로 위임
이 두 루프에서의 비즈니스 로직 처리는 EntryPoint 컨트랙트 내부가 아닌, User Operation의 sender에 해당하는 계정 컨트랙트(Account Contract)로 위임되어 처리됩니다. 즉, EntryPoint 컨트랙트는 이름 그대로 Bundle Transaction을 앞단에서 받아 처리하는 일종의 프록시로서, 프로토콜과 같은 역할을 수행한 뒤 실제 User Operation실행은 계정 컨트랙트의 구현부 호출을 통해 진행하는 것입니다.
- 검증 루프에서는 계정 컨트랙트에 구현된
validateUserOp(UserOperation userOp, bytes32 userOpHash, uint256 missingAccountFunds)
함수로 User Operation이 전달되어 정의된 로직에 따른 검증이 수행됩니다. - 실행 루프에서는 User Operation에 포함된 calldata를 통한 계정 컨트랙트 호출이 발생하며, 이때 계정 컨트랙트의 구현에 따른 다양한 Custom 기능이 실행될 수 있습니다.
이후 미리 지불된 가스 중 남는 가스에 대한 환불을 마지막으로 User Operation의 처리는 완료됩니다. 여기까지 잘 따라오셨다면, ERC-4337에서 어떻게 ‘계정’이 트랜잭션(User Operation) 생성과 온체인 로직 수행을 모두 수행할 수 있는 개념으로 확장되었는지에 대해 이해하셨을 것이라고 생각합니다 🙂
Extension: Aggregator와 Paymaster
기본적인 계정 추상화의 처리 과정 외에, ERC-4337은 구현의 편의를 위한 몇가지 확장 개념을 포함하고 있습니다. Aggregator 컨트랙트와 Paymaster 컨트랙트가 그것입니다. 이 두 확장 개념의 경우 AA 처리과정에서 계정 및 사용자에 의해 선택적으로 사용될 수 있습니다.
Aggregate Signature와 Aggregator
첫번째 확장 개념인 Aggregator는 계정 컨트랙트가 신뢰하는 외부 도우미 컨트랙트로서, EntryPoint 컨트랙트 및 계정 컨트랙트에게 ‘Aggregate Signature 검증’ 기능을 제공합니다. 앞에서 살펴본 기본 프로세스를 다시 떠올려보면, Bundler가 개별 User Operation들의 유효성을 검증하기 위해 각각의 Operation들에 대해 EntryPoint 컨트랙트에 정의된 simulateValidation 함수를 호출하였으며, 이후 EntryPoint에서도 다시 개별 Operation들에 대해 계정 컨트랙트로 validateUserOp 함수를 수행한다는 것을 기억하실 겁니다. 이렇게 각각의 Operation을 매번 검증하는 것은 매우 직관적인 검증 방법이지만, 어차피 여러개의 Bundle Transaction으로 묶여 처리되는 프로세스 상에서 각각의 Operation을 다시 검증하는 것은 다소 비효율적으로 보이기도 합니다. 이를 개선하기 위한 개념이 Aggregate Signature입니다.
Aggregate Signature는 BLS와 같은 서명 기법을 사용하여 개별 키로 서명된 여러 메시지들을 묶어서 하나의 서명 구조를 구축하고 이를 검증할 수 있도록 하는 기법입니다. Aggregator는 여러 User Operation들에 대해 AggregateSignature를 생성하고, 생성된 서명을 다시 검증하는 역할을 수행함으로서 개별 User Operation단위의 서명 검증이 아닌 Bundle 단위의 서명 검증을 가능하게 돕는 컨트랙트를 지칭합니다. Aggregator 컨트랙트는 aggregateSignature(UserOperation[] ops)
함수와 validateSignature(UserOperation[] ops, bytes signature)
함수를 제공해야 하며, 그 구현을 안전하다고 판단하는 계정 컨트랙트들에 의해 사용될 수 있습니다. 이를 위해 계정 컨트랙트는 getAggregator()
함수 내부에서 사용하고자 하는 Aggregator 컨트랙트의 주소를 반환할 수 있습니다.
EntryPoint로부터 Aggregator가 사용되는 방식은 아래와 같습니다.
- 먼저 Bundler에 의해
simulateValidation
함수가 호출되었을 때 만약 해당 계정이 Aggregator를 사용하는 계정이라면, EntryPoint 컨트랙트는 ValidationResult 객체 대신 ValidationResultWithAggregator 객체를 반환합니다. - Bundler는 이를 통해 Aggregator 사용 여부를 인지하고 이후 검증 과정에서 aggregator를 통한 검증을 수행하게 되며, 실제 User Operation의 처리를 위해 EntryPoint 컨트랙트를 호출할때도
handleOps
함수 대신handleAggregatedOps
함수를 호출함으로서 서명 검증을 계정 컨트랙트가 아닌, Aggregator에게 위임하여 진행할 수 있도록 합니다.
Paymaster
블록체인 기반 어플리케이션을 운영해봤거나 사용해본 분이라면 누구나, 트랜잭션 수수료 처리로 인한 번거로움을 경험하신 적이 있을겁니다. 예를 들어, 이더리움 환경에서 특정 ERC20 토큰을 기반으로 운영되는 어플리케이션을 사용하고자 내 EOA로부터 트랜잭션을 발행하려고 보니 결국 트랜잭션 처리를 위한 가스 수수료로 사용될 이더리움도 별도로 구매하여 충전했어야 하는 경험들 말입니다. 이렇듯 EVM기반 체인들에서는 트랜잭션 처리 수수료를 무조건 Native token으로만 지불해야 했기에 사용자들은 많은 번거로움을 감수해야 했습니다.
ERC-4337의 두번째 확장개념인 Paymaster 컨트랙트는 DApp 제공자가 자신의 서비스를 사용하는 사람들을 위한 가스 수수료를 대납해주거나, ERC20 토큰으로 수수료를 처리할 수 있도록 도와주는 일종의 Custom한 결제 대행 컨트랙트입니다. AA를 기반으로 구현한 어플리케이션들은 Paymaster 컨트랙트를 활용함으로서 유연하고 확장성있는 서비스를 구현할 수 있게 되었습니다.
Paymaster 컨트랙트는 Aggregator와 유사한 과정을 통해 EntryPoint 컨트랙트 및 계정 컨트랙트와 상호작용합니다.
- 먼저 User Operation 구조체에 paymaster필드가 존재하는 경우 이 요청은 특정 Paymaster를 통해 처리되어야 하는 Operation으로 간주되어 EntryPoint의 검증 루프에서 계정 컨트랙트의
validationOp
을 수행하는 시점에 해당 필드의 주소로 이 요청의 검증을 일부 위임하게 됩니다. 이때 호출되는 Paymaster의 함수가 표준 스펙에 해당하는validatePaymasterOp(UserOperation op)
입니다. - Paymaster 컨트랙트는 내부에 정의된 로직에 따라 대납 요청을 한 해당 계정을 확인하고 보유하고 있는 잔고를 확인한 뒤 지불 의사를 전달합니다. 이에 따라 EntryPoint 컨트랙트는 실행 루프가 종료되고 난 뒤 이 Paymaster 컨트랙트의
postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost
함수를 호출하여 수수료 지불을 요청하게 됩니다.
이렇게 구현된 AA로 뭘 할 수 있을까?
지금까지 살펴본 내용을 정리하자면, 우리는 앞으로 AA를 활용하여 기존 이더리움에서는 구현할 수 없었던 아래 내용들을 구현할 수 있게 되었습니다.
- 계정을 컨트랙트로 정의함으로서, 개인키의 관리 없이도 트랜잭션을 발행할 수 있게 되었습니다.
- 계정을 컨트랙트로 정의함으로서, 계정 내부에서Custom한 온체인 코드를 정의하고 실행할 수 있게 되었습니다.
- 계정 컨트랙트를 통해, 일반 스마트 컨트랙트들도 이제 트랜잭션을 발행할 수 있게 되었습니다. 이를 기반으로 스마트 컨트랙트를 통해 여러 트랜잭션을 한번에 처리함으로서 수수료를 절약하거나 Atomic한 액션을 수행하도록 하는 구현 등이 가능해졌습니다.
- Paymaster기능을 활용하여 트랜잭션 수수료를 대납할 수 있게 되었습니다.
이러한 변화를 통해 궁극적으로는 사용자들의 사용성이 개선되어 Web3 생태계가 확장될 것이라는 기대가 뜨겁습니다. 계정 기반 구현의 제약이 사라지면서 아래와 같이 다양한 시나리오를 가지는 어플리케이션의 온체인 구현이 가능해지기 때문입니다.
- 토큰의 송수신에 특정 인원 수 이상의 서명이 필요한 Multi-sig 기능 또는 이를 활용한 계정 복구 기능
- Multi-factor 인증을 통한 자산 이동 또는 트랜잭션 생성 기능
- Paymaster를 활용한 일정 기간 수수료 무료 서비스, 카드 결제 등 실물 가치 지불을 통한 가스비 처리, 특정 ERC20 토큰 기반 트랜잭션 처리 시스템 등
- 다양한 계정 접근 제한 기능; 내 계정에서 토큰을 송신할 수 있는 계정을 허용/블락하는 allolist/blocklist 기능, 송금 한도 지정 기능, 일정 시간만 토큰의 이동을 제한하는 기능 등
크립토 시장의 불황에도 불구하고 블록체인 대중화를 위한 다양한 Web3 제품들이 출시되고 있습니다. 이더리움 메인넷에서의 AA지원은 사용성 개선 측면과 어플리케이션의 확장성 제공 측면 모두에서 Web3 시장의 발전에 큰 기회가 될 것으로 보입니다. 특히 그동안 사용성 이슈로 인해 Web2 사용자들에게 매력적으로 다가가지 못했던 지갑 서비스들이 AA의 활용을 통해 다양한 결제 수단 지원, 소셜 계정 복구, Web2 인프라를 활용한 계정 인증 등 그 사용성을 확대할 수 있을 것으로 많은 기대를 모으고 있습니다.
마치며
이번 포스팅을 통해 최근 이더리움에 적용된 AA(계정 추상화) 기능이란 무엇이며 어떤 기술인지, 앞으로 어떤 변화를 불러올 것인지에 대해 정리해보았습니다. 최근 이더리움 등 퍼블릭 체인을 위한 노드 서비스 및 다양한 API를 구현하고 있는 루니버스 팀에서도 AA 상용화에 따른 신규 개발자 도구 및 다양한 Use-case들을 제공하기 위해 관련 기술을 빠르게 검토하고 있습니다. 추상화라는 단어가 주는 모호함과 새로운 개념들로 인해 다소 어렵다고 느껴질 수 있는 기술이지만, AA에 대해 조금이나마 이해할 수 있는 기회가 되셨기를 바랍니다. 더 자세한 사항을 알고 싶은 분들은 ERC-4337의 상세 스펙 및 보안 관련 고려사항들을 찾아보시는 것을 추천드립니다. 🙂 루니버스는 새로운 기술 아티클로 다시 찾아뵙도록 하겠습니다!
Join Luniverse Community Now
오늘 아티클에 대해 추가로 궁금하신 점이 있으시거나, 루니버스 서비스를 체험해 보시고 싶으시다면 루니버스 커뮤니티를 찾아주세요! 루니버스 최신 소식과 웹3 기술 트렌드를 알아보실 수 있습니다.