EIP-4895 비컨체인 인출의 푸시 방식 처리 (Beacon chain push withdrawals as operations)
최종 확정 · 합의·스테이킹 · 원문 상태 Final · 2022-03-10 작성
비컨체인에서 확정된 검증자 인출을 새로운 "시스템 수준 연산"으로 실행 레이어에 전달해 지정된 주소의 잔액을 가스비 없이 무조건 늘려 주는 EIP입니다.
왜 필요한가
이더리움은 합의를 담당하는 비컨체인(Beacon chain)과 거래를 처리하는 실행 레이어(EVM)로 나뉘어 있습니다. 검증자(validator)가 비컨체인에서 인출을 확정해도, 그 ETH를 실행 레이어의 계정으로 옮기는 경로가 없었습니다. 이 EIP는 비컨체인이 인출을 실행 레이어로 "밀어 넣는"(push) 방식을 정의합니다. 합의 레이어의 대기열에서 인출이 빠져나오는 즉시 실행 레이어가 처리해야 합니다. 인출을 일반 거래의 새 유형으로 만드는 이전 방식 대신, 거래와는 다른 영역의 "연산(operation)"이라는 새 객체로 분리했습니다. 시스템 차원의 일과 사용자 데이터가 섞이면서 생기는 상호작용을 줄여 테스트가 단순해지고 그만큼 보안 검토도 쉬워진다는 것이 원문이 밝힌 이유입니다.
무엇이 바뀌나
지금
- 비컨체인에서 인출이 확정돼도 그 ETH가 실행 레이어 계정으로 들어올 방법이 없습니다
- 인출을 처리하려면 일반 거래에 새 거래 유형을 추가하는 방식이 먼저 논의됐습니다
- 블록에는 인출 정보를 담는 자리가 없습니다
EIP-4895 이후
- 블록의 실행 페이로드에 withdrawals 목록이 생겨 인출이 블록마다 자동으로 반영됩니다
- 인출은 일반 거래와 분리된 시스템 수준 연산으로 처리돼 테스트와 보안 검토가 단순해집니다
- 인출은 가스비 없이 지정 주소의 잔액을 무조건 늘리며 실패할 수 없습니다
누구에게 영향이 있나
- 검증자·스테이커: 비컨체인에서 확정된 인출 ETH를 실행 레이어의 지정 주소로 받을 수 있습니다.
- 클라이언트 팀: 실행 페이로드의 withdrawals 필드, 헤더의 withdrawals_root 검증, 거래 처리 뒤의 잔액 증가 로직을 구현해야 합니다.
- 사용자·앱 개발자: 인출은 거래가 아니어서 코드 실행을 일으키지 않습니다. 수령 주소의 잔액만 늘어납니다.
심층 설명
Withdrawal 객체의 구조
withdrawal은 페이로드 수준 객체로, 사용자 거래와 문법은 비슷하지만 다른 도메인에 속합니다. 필드는 네 개입니다. (1) index: 0부터 시작해 인출마다 1씩 늘어나는 uint64 값으로, 전체 인출 시퀀스를 관통하는 전역 카운터입니다. (2) validator_index: 해당 인출이 속한 합의 레이어 검증자의 uint64 인덱스입니다. (3) address: 인출된 이더를 받을 20바이트 수령 주소입니다. (4) amount: Gwei(1e9 wei) 단위의 0이 아닌 uint64 금액입니다. 직렬화는 RLP 리스트 [index, validator_index, address, amount] 스키마를 따릅니다.
실행 페이로드의 새 필드 withdrawals
실행 페이로드에 Withdrawal 데이터의 RLP 리스트인 withdrawals 필드가 추가됩니다. 기존 필드들 뒤에 인코딩되며 페이로드 본문(body)의 일부로 취급됩니다. 구조는 execution_payload_rlp = RLP([header, transactions, [], withdrawals]), execution_payload_body_rlp = RLP([transactions, [], withdrawals])입니다. 중간의 빈 리스트는 EIP-3675가 ommers 값을 고정 상수로 정했기 때문에 남아 있는 자리입니다.
헤더의 withdrawals_root 커밋먼트
실행 페이로드 헤더에 인출 목록을 커밋하는 32바이트 필드 withdrawals_root가 추가됩니다. 기존 헤더의 transactions root와 동일한 방식으로 만듭니다. 각 withdrawal을 withdrawals 리스트 안의 인덱스를 키로 하는 머클 패트리샤 트라이(Merkle-Patricia trie)에 넣고 그 루트를 취합니다. 헤더 RLP에서는 base_fee_per_gas 뒤, 마지막 자리에 위치합니다.
페이로드 유효성 검증
실행 클라이언트는 페이로드가 올바른 형식이라는 전제 아래 추가 검증을 수행합니다. 페이로드에 담긴 withdrawals 리스트로 트라이 루트를 계산한 값이 헤더의 withdrawals_root와 같아야 합니다. 원문 의사코드로는 assert execution_payload_header.withdrawals_root == compute_trie_root_from_indexed_data(execution_payload.withdrawals)입니다.
상태 전이: 거래 뒤 무조건 잔액 증가
withdrawals는 사용자 거래가 모두 적용된 뒤에 처리됩니다. 각 withdrawal에 대해 지정된 address의 잔액을 amount만큼 늘립니다. amount는 Gwei 단위이므로 실행 상태의 잔액에 반영할 때 wei로 변환해야 합니다. 이 잔액 변경은 무조건적이며 실패해서는 안 됩니다(MUST not fail). 연관된 가스 비용도 없습니다. 적용 시점은 실행 타임스탬프 FORK_TIMESTAMP(1681338455)부터입니다.
왜 새 거래 타입이 아닌가
인출은 최종 사용자가 아니라 시스템 전체가 시작하는 작업이어서 기존 EVM 거래와 의미가 다릅니다. 완전히 새로운 객체 유형으로 만들면 일반 EVM 실행과 이 처리를 방화벽처럼 분리할 수 있어 인출 기능의 테스트와 보안 검토가 단순해집니다. 원문은 이 방식이 거래 타입을 추가하는 이전 접근보다 더 손이 가지만, 시스템 수준 관심사를 일반 거래에서 깨끗하게 떼어낸다고 설명합니다.
왜 가스비가 없고, 왜 잔액 증가만 하는가
한 번에 실행 레이어에 도달할 수 있는 인출 수는 합의 레이어가 상한을 강제합니다. 이 상한은 실행 레이어의 운영 비용이 전체 페이로드 실행 대비 무시할 수준이 되도록 정해졌습니다. 계산 비용은 상태의 잔액 몇 건 갱신에 그치고 추가 저장·네트워크 부담은 현재 파라미터 기준 평균 페이로드 크기의 약 1%입니다. 또 인출에서 일반 EVM 실행을 허용하면 실패 가능성이 생겨 비컨체인 쪽 회계가 복잡해지므로, 잔액 증가만 허용해 최소 복잡도로 대부분의 이점을 얻는 경로를 택했습니다.
보안 고려사항과 현재 상태
합의 레이어에서 인출을 올바르게 검증하는 일이 핵심입니다. 정확한 양의 ETH가 실행 레이어로 되돌아오는지를 합의 레이어가 보장해야 하기 때문입니다. 합의 레이어에서 실행 레이어로 ETH가 이동하는 일은 기존 EVM에 유사 사례가 없어 매우 높은 수준의 보안 검토가 필요하다고 원문은 밝힙니다. 이 EIP의 상태는 Final로, 명세가 확정되어 있습니다.