EIP-7807 SSZ 실행 블록 (SSZ execution blocks)

Hegota 포함 제외 (DFI) · EVM·실행 · 원문 상태 Draft · 2024-10-28 작성

실행 블록의 직렬화 방식을 RLP에서 합의 계층이 쓰는 SSZ로 바꾸고 블록 해시를 SSZ의 hash_tree_root로 계산하게 합니다. 개별 트랜잭션·영수증·출금 항목과 상태 트라이는 그대로 둡니다.

왜 필요한가

지금 이더리움은 같은 체인의 블록을 두 가지 방식으로 표현합니다. 실행 계층 블록은 RLP 인코딩과 머클 패트리샤 트라이를 쓰고 합의 계층은 SSZ(Simple Serialize)를 씁니다. 표현이 달라서 생기는 비용이 큽니다. 합의 계층은 빌더가 약속한 실행 블록 해시를 스스로 확인할 수 없어 실행 계층과 비동기로 통신해야 하고 두 계층을 잇는 엔진 API는 텍스트 기반 JSON이라 데이터가 크고 인코딩·파싱이 느립니다. 블록의 특정 필드 하나를 증명하려 해도 블록 전체가 있어야 합니다. 작업증명(PoW) 시절의 오래된 필드와 비효율적인 로그 블룸(logs bloom)도 그대로 남아 있습니다. 이 EIP는 실행 블록과 블록 해시, 블록 단위 트라이를 SSZ로 옮겨 두 계층의 블록 표현을 통일하고 이런 문제를 정리하려는 제안입니다.

무엇이 바뀌나

지금

EIP-7807 이후

누구에게 영향이 있나

심층 설명

ExecutionPayload 컨테이너

새 실행 블록은 18개 필드를 가진 ProgressiveContainer인 ExecutionPayload로 정의합니다. parent_hash, miner, state_root, transactions, receipts_root, number, gas_limits, gas_used, timestamp, extra_data, mix_hash, base_fees_per_gas, withdrawals, excess_gas, parent_beacon_block_root, requests_hash, block_access_list, slot_number로 구성됩니다. 일반 가스와 블롭 가스는 GasAmounts(GasAmount는 uint64)와 BlobFeesPerGas(FeePerGas는 uint256) 구조로 묶습니다. 트랜잭션과 영수증 목록의 각 원소는 기존 EIP-2718 타입 봉투 표현을 유지하고 출금 원소와 block_access_list는 기존 RLP 표현을 유지합니다. receipts_root는 블록 영수증 목록(ProgressiveList[ProgressiveByteList])의 hash_tree_root이고, requests_hash는 합의 계층이 쓰는 ExecutionRequests의 hash_tree_root와 같습니다.

헤더는 SSZ 요약으로 파생

별도의 헤더 포맷을 두지 않고 실행 블록 헤더를 ExecutionPayload의 SSZ 요약(summary)으로 파생합니다. transactions, withdrawals, block_access_list 세 필드를 각각의 hash_tree_root로 바꾼 형태입니다. 이렇게 정의한 ExecutionPayload는 합의 계층 명세(gloas)의 ExecutionPayload 정의를 대체하며 ExecutionPayloadEnvelope에 실려 전달됩니다. 두 계층이 같은 자료 구조를 쓰게 되므로 합의·실행 통합 구현에서 자료 구조를 공유하기도 쉬워집니다.

블록 해시는 hash_tree_root로 통일

실행 블록 해시를 모든 맥락에서 ExecutionPayload.hash_tree_root()로 계산합니다. BLOCKHASH 명령어, JSON-RPC의 blockHash 필드, devp2p 네트워킹, 그리고 합의 계층의 BeaconState.latest_block_hash와 ExecutionPayloadBid.block_hash 참조가 모두 해당합니다. SSZ 블록 해시는 SHA256 기반으로, 기존 keccak256 기반 블록 해시와 같은 이름 공간을 공유하지만 두 해시 알고리즘이 근본적으로 달라 의미 있는 충돌 위험은 없다고 원문은 설명합니다.

logsBloom은 전부 1로 채움

JSON-RPC 블록 응답의 logsBloom 필드는 모든 비트가 1인 값(256바이트의 0xff)으로 설정해야 합니다(MUST). 비효율적인 로그 블룸 메커니즘을 SSZ 전환을 계기로 버리는 것인데, 전부 1인 값은 '원하는 로그가 있을 수도 있다'는 뜻이라 소비자가 모든 영수증을 직접 확인하도록 유도합니다. 반대로 전부 0인 값은 로그가 확실히 없다는 신호가 되어 로그를 놓치게 만들 수 있어 쓰지 않습니다.

엔진 API와 증명에서 얻는 이득

모든 교환 데이터가 SSZ를 지원하면 엔진 API를 텍스트 JSON에서 바이너리 SSZ 인코딩으로 바꿀 수 있습니다. 교환 데이터 크기가 약 50% 줄고 인코딩·파싱 효율이 크게 좋아집니다. 블록 해시를 공유하므로 중복된 block_hash 필드를 없애고 ForkDigest 컨텍스트 인코딩을 채택할 수 있습니다. 증명 측면에서는 블록 전체 없이 개별 필드 증명이 가능해집니다. EIP-7495 ProgressiveContainer와 EIP-7916 ProgressiveList를 쓰기 때문에 블록 정의가 진화해도 generalized index가 안정적으로 유지되고 목록은 하드코딩된 한도 없이 커질 수 있습니다. 필드의 의미가 변하지 않는 한 증명이 전방 호환되므로 스마트 컨트랙트와 검증 애플리케이션의 유지보수 부담이 줄어듭니다.

기존 컨트랙트와의 호환성

이 EIP는 기존 블록 헤더의 바이너리 포맷에 의존하는 스마트 컨트랙트의 호환성을 깨뜨립니다. 헤더들에 공통 프리픽스가 있다고 가정하고 데이터 전체를 선형으로 keccak256 해시하는 '범용' 구현도 포함됩니다. 한편 JSON-RPC로 logsBloom을 읽는 소비자는 SSZ 블록에서 전부 1인 값을 보게 되는데 이는 하위 호환되는 동작이며 영수증의 logsBloom은 이 EIP의 영향을 받지 않습니다.

진행 상황: Draft, Hegota에서 제외

이 제안은 Draft 상태라 내용이 아직 바뀔 수 있습니다. 코어 개발자 콜에서는 07.30 ACDE #242에서 블록 해시만 SSZ 방식으로 계산하도록 축소한 EIP-7807이 Hegota 포함 후보(PFI)로 접수됐습니다. 합의 계층이 블록 해시를 자체 계산할 수 있어 동기화가 개선된다는 이유였습니다. 그러나 09.10 ACDE #245에서 제외(DFI)가 결정됐습니다. 헤더와 블록을 읽는 모든 코드가 바뀌어야 해 파급 범위(blast radius)가 큰 반면 사용자 이득은 작다는 판단이었습니다.

EIP 원문 · ← EIPs