Optimism Bedrock Wrap Up Series 1 [KR]
Bedrock 업그레이드 개요 및 계층별 구성요소
포스팅을 작성하는 데에 도움을 주신 Theo L. Steven L. Austin O. Justin G. 님에게 감사를 표합니다.
2023년 초, Ethereum의 공동 창립자인 Vitalik Buterin은 “2023년에는 롤업(Roll-up)과 같은 레이어2 스케일링 솔루션이 중요한 이정표에 도달하게 될 것”이라고 언급했습니다. 그리고 실제로 Vitalik Buterin의 발표와 함께 Ethereum 생태계에서 레이어2의 역할은 비약적으로 확장되고 있으며, 작성일 기준 약 100억 달러(한화 약 13조 2,960억 원)의 TVL(Total Value Locked, 총예치금)을 유지하고 있습니다.
해당 포스팅은 총 5편의 시리즈로 구성되며, OP Labs의 수년간의 연구로 다져진 ‘Optimism Bedrock Upgrade’에 대한 개요와 업그레이드 내용을 상세히 설명하고 분석합니다. 시리즈의 후반부로 갈수록 Optimism Bedrock 프로토콜에 대한 디테일한 분석 내용이 담겨 있습니다.
Onther는 본 시리즈를 통해 Optimism 레이어2 솔루션과 Ethereum 생태계의 발전에 관심 있는 현직 개발자에게 유용한 정보를 제공하고자 합니다.
본 글은 Onther에서 기획한 ‘Optimism Bedrock Wrap Up 시리즈’ 총 5편의 1번째 글로 Bedrock 업그레이드의 개요와 계층별 구성 요소 그리고 계층별 배포된 스마트 컨트랙트를 다룹니다. 시리즈의 구성이 서로 연관되어 있으므로, 차례대로 읽어보시는 것을 추천해 드립니다.
2. Bedrock 업그레이드 이후 주요 변경 사항: Bedrock 업그레이드 이후 주요 변경 사항을 이해하기 쉽게 설명하여 이후 시리즈에 대한 이해를 돕고자 합니다.
3. 입·출금 프로세스 분석: 입·출금 프로세스의 흐름을 계층별 핵심 코드 로직을 통해 순차적으로 분석합니다.
4. 블록의 파생(Block Derivation): Optimism은 OP 메인넷(레이어2)에서 블록이 생성된 후, 해당 블록을 다시 레이어1으로 rollup 하는 과정을 거칩니다. 그리고 그 rollup 된 데이터만을 활용하여 L2 블록을 재생성하는 프로세스를 Block Derivation이라고 하며, 이프로세스를 단계별로 분석합니다.
5. Optimism Bedrock 구성 요소들의 역할 및 동작: 해당 시리즈의 마지막 구성으로 Op-Batcher와 Op-Proposer의 역할과 동작 로직을 종합적으로 살펴봅니다.
들어가며
작성일 기준 3개월 전에 이루어진 Bedrock 업그레이드는 Ethereum의 레이어2 솔루션인 Optimism을 혁신적으로 개선하여 Ethereum 생태계에 중요한 변화를 불러왔다. ‘Bedrock’이라는 단어를 한국어로 번역하면 ‘기반암(基盤岩)’으로 이는 대륙 지각을 형성하는 암석의 집합을 의미한다. 해당 비유는 Optimism 생태계에 큰 대륙이 되어줄 ‘슈퍼체인(Superchain)’에 필요한 기반을 마련한다는 의미로 사용됐다.
슈퍼체인은 “사람들 사이에 다리를 놓아 하나로 모은다(Bridging people together)”라는 Optimism의 핵심 가치를 반영하고 있으며, Optimism의 OP 스택(OP Stack) 기반의 여러 L2 체인으로 구성된 탈중앙화 블록체인 플랫폼이다. 최근에는 코인베이스의 베이스(Base), 바이낸스의 opBNB 등 다양한 L2 솔루션들이 OP 생태계에 온보딩하여 협력 관계를 이어가고 있다.
Optimism Bedrock 업그레이드 궁극적 미션
Bedrock 업그레이드의 목표는 다음과 같다.
- 빠른 속도: 사용자가 트랜잭션을 전송할 때 발생하는 지연 시간을 최대한 줄이고 해당 트랜잭션에 대한 신뢰성을 확보하는 것을 목표로 한다. 이번 Bedrock 업그레이드를 통해 입금 지연 시간을 10분에서 3분 이내로 단축했다.
- 확장성: 초당 엄청난 수의 트랜잭션을 처리할 수 있어야 하며, 이를 통해 이용자에게 낮은 수수료를 부과할 수 있어야 한다. Bedrock 업그레이드 이전 Optimism에서는 레이어2에서 처리된 거래의 결과값을 레이어1의 스마트 컨트랙트에서 관리, 검증했다. 하지만, Bedrock에서는 해당 결과값을 EOA에 보관하고, 일괄 압축 기능을 통해 데이터를 최적화하여 가스 수수료의 40% 이상 절약했다.
- 모듈화: Optimism의 구조 설계는 합의, 실행, 그리고 거래의 완결성을 담당하는 각각의 레이어를 모듈화하여 복잡성을 줄이고 병렬적인 기능을 구현하는 것을 목표로 한다. 이를 통해 매우 복잡한 소프트웨어도 Optimism 모듈 안에서 간단히 구현할 수 있다. 즉, Optimism 체인 위에서 폭넓은 DApp의 범용성과 구조적 간소화를 이루어 내려 한다. (예: OP Stack, Superchain)
- EVM 동등성: Optimism은 Ethereum 프로토콜의 공식 표준을 완전히 준수하는 것을 목표로 한다. 이를 위해 Ethereum의 ‘geth’ 클라이언트에서 최소한의 롤업 기능을 위한 로직 추가 이외에 다른 부분은 수정하지 않고 Bedrock을 위한 op-geth 클라이언트를 개발했다. 현재 Optimism의 OVM은 Ethereum 메인넷 EVM과 대략 1~2천 줄 정도의 미비한 차이로 구성되어 있다. Optimism의 이런 전략적인 접근은 결국 메인넷 개발자들로 하여금 Optimism 생태계로 쉽게 전환할 수 있도록 하는 것에 있다. 결국 이상적인 롤업의 설계는 Ethereum 클라이언트 소프트웨어와의 최소한의 차이로 결정된다. (예: L2geth, Code re-use, Derivation)
- 탈중앙화 가능: 현재 Optimism이 가지고 있는 한계라고 한다면 바로 시퀀서(Sequencer)가 중앙화되어 있다는 사실이다. 물론 그 어떠한 롤업 솔루션도 아직은 시퀀서를 완전히 탈중앙화 한 곳은 없다(시퀀서가 중앙화되어 있기에 네트워크 운용이 원활하다). 이에 Optimism은 다중 시퀀서 도입을 통해 시퀀서 탈중앙화를 계획하고 있으며, 이것이 완료되면 누구든 L2 블록 생산자로서 네트워크에 참여할 수 있다.
계층별 구성 요소
L1 구성 요소
OptimismPortal: OptimismPortal은 입금과 출금을 담당하는 컨트랙트이다.
- 입금 시에는 Rollup Node에게 입금 요청 트랜잭션(DepositTransaction) 이벤트를 전달한다. 여기서 입금되는 Ethereum/ERC-20은 L1에서 잠긴 다음 입금 트랜잭션을 통해 L2에서 발행(mint)된다.
- 출금 시에는 반대로 L2에서 출금 트랜잭션을 받아오는 역할을 담당한다. 이때 출금 검증 과정에 있는 L2 출금 트랜잭션의 전송자(인출자, L2Sender)의 출금 상태를 추적하여 출금 완료까지의 과정을 총괄하는 역할을 한다.
- 가디언(Guardian, 입출금을 일시 중지할 수 있는 권한을 가진 주소)에 의해서 OptimismPortal은 일시 정지가 되거나 일시 정지가 해제될 수 있다.
BatchInbox: Sequencer가 트랜잭션 배치(batch)를 저장하는(저장소) L1 주소이다. 트랜잭션 배치는 L2에서 처리된 트랜잭션 데이터이며, BatchInbox에 발생된 모든 배치를 저장하게 된다.(여기서 배치는 ‘최적화된 트랜잭션의 모음’으로 생각하면 편하다.) 트랜잭션 배치에는 L2 transaction의 calldata, timestamp와 같은 거래의 전반적인 내역이 포함된다.
- 업그레이드 이전 Optimism에서 CanonicalTransactionChain(CTC) 컨트랙트의 대체재 역할을 담당하며, CTC 컨트랙트와 다르게 EOA 주소를 사용함으로 EVM 코드를 실행하지 않아 가스 비용을 절감할 수 있다.
L2OutputOracle: L2에서 생성되는 모든 블록의 결과 내역에 대한 Output Root(state)를 저장하는 저장소이다. 따라서 Proposer는 주기적으로 L1 블록에서 파생된 L2 블록의 최신 Output Root를 쿼리해서 해당 컨트랙트에 저장한다.
- L2OutputOracle은 업그레이드 이전 Optimism에서 StateCommitmentChain(SCC) 컨트랙트의 대체재 역할을 담당한다.
L2 구성요소
Rollup Node(OP-Node: Sequencer / Verifier): Rollup Node가 하는 역할은 크게 두 가지로 나뉜다. 하나는 시퀀서(Sequencer)로 블록을 생성하는 역할이고, 다른 하나는 블록을 검증하는 검증자(Verifier)의 역할이다.
시퀀서: 우선 두 가지 종류의 트랜잭션을 나누어 생각해야 한다.
- 하나는 L1에서부터 발생한 입금 트랜잭션(DepositTransaction)으로 입금이 발생할 때마다 OptimismPortal을 통해 해당 트랜잭션을 받아온다.
- 다른 하나는 L1에서부터 파생되지 않고 L2 자체에서 발생한 트랜잭션이 있다.(예: L2 DApp에서 발생한 트랜잭션 / L2 계정 사이에서 발생한 트랜잭션)
- 이제 위 두 종류의 트랜잭션을 가져다가 L2 체인에 새로운 블록을 생성하게 된다. 이때 시퀀서는 Engine API를 사용하여 새로 생성할 블록에 대한 데이터를 전달하고 최종적으로 Execution Engine에서 블록을 생성하여 L2 체인에 추가 된다.
검증자: 검증자가 구성한 체인의 Output Root vs. L1의 L2OutputRoot
- L1에 올라가 있는 롤업 데이터, 즉 BatchInbox에 있는 Batch를 가져다가 Rollup Node 자체적으로 체인을 생성해 L2 체인과 비교하며 체인을 검증할 수 있다.
- 이때 체인을 검증하는 데이터는 Rollup Node가 로컬에서 자체적으로 생성한 체인의 output root와 L2OutputOracle(L1)에 이미 올라가 있는 L2 output root를 서로 비교하며 검증하는 방식으로 진행된다.
따라서 Rollup Node에는 두 가지 모드(시퀀서 모드, 검증자 모드)가 있으며 두 가지 역할을 아예 따로 이해하는 편이 편하다.
Execution Engine (EE): Ethereum의 Geth 클라이언트를 약간 수정하여 만들어 졌으며, Rollup Node에게 Engine API를 제공하는 역할을 한다. Rollup Node가 블록 생성을 위한 준비를 마치면 Engine API를 사용해 Execution Engine에서 실제 블록이 생성된다. 여기서 Engine API는 Engine JSON-RPC API라고도 하며 실행 클라이언트(execution clients)가 구현하는 메서드의 모음이다.
Batch Submitter(Op-Batcher): 검증자가 사용할 트랜잭션 배치를 BatchInbox 주소로 제출하는 역할을 담당하며 이 또한 시퀀서가 제출한다. (자세한 사항은 5번째 시리즈에서 다룰 예정이다.)
Output Submitter(Op-Proposer): L2에서 처리된 거래의 결과값인 output root를 L2OutputOracle에 제출하는 백그라운드 프로세스로 시퀀서가 제출한다. (자세한 사항은 5번째 시리즈에서 다룰 예정이다.)
계층별 배포된 스마트컨트랙트
L1 contracts
OptimismPortal: 위 L1 구성 요소에서의 설명과 동일하며 추가 설명을 더 하자면 L2의 입구이자 출구의 역할을 하며 레이어 간 이동되는 자산과 메시지를 위한 로우레벨 API를 제공한다.
Legacy Optimism 사용자를 위해 계속 사용하는 컨트랙트
- L1CrossDomainMessenger: 레이어 간에 이동되는 메시지를 관리하는 컨트랙트이다.
- L1StandardBridge: 레이어 간에 Ethereum이나 ERC 토큰을 전송하기 위한 표준 인터페이스를 제공하는 컨트랙트이다.
L2OutputOracle: 위 L1 구성 요소에서의 설명과 동일하며, 시퀀서가 L2 output root를 게시하고 나면, 검증자는 해당 output root를 가지고 검증 과정을 거친다.
- 검증자가 로컬에서 만든 체인의 output root와 시퀀서가 제출한 L2outputOracle에 있는 output root가 불일치할 경우 결함 증명이 이어서 진행되어야 한다. 하지만, 아직까지는 결함 증명 기능이 지원되지 않았으며 테스트 중이다.
L2 contracts
L1Block: 사용자는 L1Block 컨트랙트를 통해 마지막 L1 블록에 대한 정보에 액세스할 수 있다. 마지막 L1 블록의 값은 에폭(epoch)당 한 번 업데이트된다. 여기서 에폭은 블록체인 검증자가 검증 작업을 할 때 블록을 일정 단위로 묶는 것으로, 하나로 묶은 체크포인트 사이 블록 간격을 지칭하는 말이다. Optimism의 경우 2초에 하나씩 블록이 생성되어, 6개의 블록을 한 에폭으로 설정했다.
위 optimistic.etherscan.io 캡처 사진에서 맨 왼쪽 사진을 보면 블록이 2초마다 생성되고 있고, 오른쪽 사진에는 109844341번째 블록의 L1BlockValue(L1Block 컨트랙에 의해서 생성)가 보인다. 이를 보면 _sequenceNumber가 000…000으로 해당 에폭의 첫 번째 블록임을 확인 할 수 있다. 그리고 해당 블록으로부터 6번째 이후 블록인 109844347번째 블록은 다음 에폭의 첫 번째 블록일 것이다.
L1Block 컨트랙트의 주소는 0x4200000000000000000000000000000000000015 이며, ‘getter’ 함수를 통해 아래와 같은 파라미터를 얻을 수 있다.
- number: L2에 올라온 최신 L1 블록 번호
- timestamp: 가장 최근 L1 블록의 타임스탬프
- basefee: 가장 최근 L1 블록의 기본 수수료
- hash: 가장 최근 L1 블록의 해시
- sequenceNumber: 에폭 내 L2 블록의 순번(새로운 L1 블록이 생기면 에폭이 변경됨)
L1Block 컨트랙트의 사용 목적은 다음과 같다.
- L2에서 트랜잭션을 처리하며 사용될 L1 가스 가격을 계산
- 시퀀서가 제출한 L1 블록에 대한 정보 검증
- 특정 L1 트랜잭션이 L2에서 성공적으로 처리됐는지 여부 확인
현재 L1의 정보는 재구성(reorgs)의 영향을 최소화하기 위해 2 block confirmation을 사용하여 약 24초의 지연을 거쳐 업데이트된다.
SequencerFeeVault: 시퀀서에게 전달될 L2에서의 거래 수수료가 저장된 금고이다. L2에서 트랜잭션을 발생시키는 과정에서 부과되는 기본 수수료이며, Ethereum이 사용된다.
L2ToL1MessagePasser: L2에서 L1으로 전송되는 메시지를 저장할 수 있는 전용 컨트랙트로 L2CrossDomainMessenger에서 내부적으로 인출을 시작하는 데 사용된다.
- Legacy 컨트랙트 주소: 0x4200000000000000000000000000000000000000
- Bedrock 컨트랙트 주소: 0x4200000000000000000000000000000000000016
Legacy Optimism 사용자를 위해 계속 사용하는 컨트랙트
- L1BlockNumber: 최신 L1 블록의 번호를 제공하는 컨트랙트이다.
- L2CrossDomainMessenger: 컨트랙트는 L2(OP)에서 L1(Ethereum)으로 메시지를 전송하는 데 사용하는 컨트랙트이다.
- L2StandardBridge: 레이어 간에 Ethereum이나 ERC 토큰을 전송하기 위한 표준 인터페이스를 제공하는 컨트랙트이다.
- WETH9: Wrapped Ether를 구현하기 위한 표준 컨트랙트이다.
마치며
여기까지 Bedrock 업그레이드의 개요와 계층별 핵심 요소에 대한 전반적인 내용을 살펴보았습니다. 아직까지는 Optimism의 L2 솔루션이 최고라고 말하기는 어렵지만, 시간이 흐름에 따라 OP Stack을 기반으로 한 다양한 L2 체인 간의 협업으로 무한한 발전 가능성이 열릴 것으로 기대됩니다. 다음 시리즈에서는 Bedrock 업그레이드가 가져온 변화를 더욱 세부적으로 살펴보도록 하겠습니다.