EIP-8268 블록 접근 목록에 스토리지 루트 추가 (Storage Roots in Block Access Lists)

포함 제안 (PFI) · 확장성·데이터 · 원문 상태 Draft · 2026-05-21 작성

EIP-7928의 블록 접근 목록(BAL)에 상태가 바뀐 계정마다 블록 실행 후 스토리지 트라이 루트를 실어, 상태 일부만 보관하는 노드도 블록의 상태 루트를 검증할 수 있게 합니다.

왜 필요한가

이더리움 노드가 블록을 검증하려면 블록 실행 후의 상태 루트(state root), 곧 모든 계정 상태를 요약한 값을 직접 계산해 블록 헤더와 맞춰 봐야 합니다. EIP-7928의 블록 접근 목록(Block Access List, BAL)은 블록이 어떤 계정의 어떤 저장 슬롯을 어떤 값으로 바꿨는지 알려 주지만 바뀐 계정의 저장소 전체를 요약한 스토리지 트라이 루트(storage trie root)는 담지 않습니다. 그래서 상태의 일부만 보관하는 부분 상태 노드(partially stateful node)는 자신이 들고 있지 않은 계정이 수정되면 그 계정의 스토리지 루트를 구할 수 없고 상태 트라이 잎(leaf)을 만들지 못해 블록의 상태 루트 검증도 할 수 없습니다. 이 EIP는 수정된 계정마다 블록 실행 후 스토리지 루트를 BAL에 함께 실어 이 공백을 메웁니다. 잔액, 논스, 코드 정보는 BAL에 이미 들어 있으므로, 스토리지 루트만 더해지면 어떤 노드든 자신이 어느 부분의 상태를 보관하든 수정된 모든 계정의 상태 트라이 잎을 조립할 수 있습니다.

무엇이 바뀌나

지금

EIP-8268 이후

누구에게 영향이 있나

심층 설명

AccountChanges에 storage_root 필드 추가

상태 변경 목록(storage_changes, balance_changes, nonce_changes, code_changes) 중 하나라도 비어 있지 않은 AccountChanges 항목은 끝에 storage_root 필드를 반드시(MUST) 붙입니다. 타입은 StorageRoot = bytes32이고 블록 실행 후 상태를 기준으로 평가한 그 계정의 스토리지 트라이 루트입니다. 접근만 하고 아무것도 바꾸지 않은 계정(모든 변경 목록이 빈 항목)은 storage_root를 포함해서는 안 되며(MUST NOT) EIP-7928의 6필드 구조를 그대로 유지합니다. 정렬, 유일성, block_access_list_hash 계산, 엔진 API 인코딩 등 EIP-7928의 나머지 규칙은 바뀌지 않고 storage_root는 해시가 커밋하는 RLP에 포함됩니다.

빈 스토리지 트라이의 인코딩 규칙

블록 실행 후 스토리지 트라이가 빈 계정은 storage_root를 빈 바이트 문자열(RLP 인코딩 0x80)로 적어야 하고 32바이트 표준 빈 트라이 루트 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421을 써서는 안 됩니다(MUST NOT). 읽는 쪽은 빈 바이트 문자열을 그 표준 빈 트라이 루트로 간주해 상태 트라이 잎을 복원해야 합니다(MUST). 이 규칙은 계정 종류가 아니라 블록 후 스토리지 트라이가 비었는지로만 판단하므로, 외부 소유 계정(EOA), 새로 만들어지거나 비워진 컨트랙트, EIP-7702 위임 계정이 모두 코드를 들여다보지 않고 같은 규칙으로 처리됩니다.

블록 유효성 검증 조건

storage_root를 가진 AccountChanges 항목에 대해 두 경우 중 하나라도 성립하면 블록이 무효입니다. 첫째, 블록 후 스토리지 트라이가 비어 있지 않은데 storage_root가 블록 실행으로 나온 32바이트 스토리지 트라이 루트가 아닌 경우입니다. 둘째, 블록 후 스토리지 트라이가 비어 있는데 storage_root가 빈 바이트 문자열이 아닌 경우입니다. 빈 트라이는 반드시 빈 바이트 문자열로, 비어 있지 않은 트라이는 반드시 32바이트 루트로 인코딩해야 하므로 블록마다 유효한 인코딩이 정확히 하나만 존재합니다.

왜 스토리지 루트만 추가하는가

스토리지 루트는 수정된 슬롯만이 아니라 계정의 스토리지 트라이 전체에 의존하므로, BAL 내용만으로 복원할 수 없는 유일한 블록 후 상태 값입니다. 잔액, 논스, 코드는 BAL의 변경 기록에서 이미 복원할 수 있어 스토리지 루트만 커밋하면 완전한 상태 트라이 잎을 만들 수 있습니다. 필드를 상태가 바뀐 계정으로 한정해 부담을 수정 계정당 32바이트로 묶었고 접근만 한 항목에는 아무것도 더하지 않습니다. 한 블록에서 바뀌는 계정 대부분은 잔액이나 논스만 바뀌고 저장소가 없는 EOA라서 블록 후 스토리지 트라이가 빕니다. 이 경우를 32바이트 표준 빈 루트 대신 빈 바이트 문자열(0x80)로 적으면 그런 계정마다 32바이트를 아낄 수 있고 0x80은 어떤 32바이트 루트와도 겹칠 수 없어 모호함이 없습니다.

하위 호환성과 보안

이 제안은 EIP-7928이 도입한 BAL 인코딩을 바꾸므로 하드포크가 필요합니다. 두 인코딩은 서로 호환되지 않아, EIP-7928만 구현한 클라이언트는 이 EIP의 블록을 거부하고 그 반대도 마찬가지입니다. storage_root는 실행 과정에서 이미 만들어지는 데이터에 대한 중복 커밋이라 값이 어긋나면 일반 BAL 검증 과정에서 바로 잡힙니다. 추가 대역폭은 32 * modified_accounts로 묶이며 EIP-7928이 기술한 BAL 크기 범위를 밑돕니다. 빈 트라이 인코딩을 하나로 강제한 덕분에 block_access_list_hash가 결정적으로 유지되고 같은 블록 후 상태에 대해 클라이언트들이 서로 다른 커밋을 낼 수 없습니다.

진행 상태와 콜 논의

이 EIP는 Draft 상태라 명세가 아직 바뀔 수 있습니다. 07.16 ACDE #241 콜에서는 발표자가 없어 이번 헤고타(Hegota) 논의에서 다뤄지지 않았습니다. 카를로스가 PFI 상태로 접수해 둔 상태이며 발표는 다음 ACDE로 미뤄졌습니다.

EIP 원문 · ← EIPs