~/blockchain-dev.md
BLOCKCHAIN_DEV

블록은 실행 전에 무엇을 만질지 말해야 한다: EIP-7928 BAL로 보는 병렬 실행의 전제

10분 읽기·2026.06.09·출처 4·00
오늘의 질문

Ethereum이 병렬 실행을 하려면 왜 트랜잭션 결과보다 ‘상태 접근 목록’을 먼저 합의해야 할까?

blockchain-dev.md
SURVIVE.exe

블록은 실행 전에 무엇을 만질지 말해야 한다: EIP-7928 BAL로 보는 병렬 실행의 전제

1. 왜 지금 봐야 하나

Ethereum의 Glamsterdam 업그레이드 로드맵은 H2 2026을 목표로 L1 확장, blob 확장, 상태 데이터 지속가능성을 같이 다룬다. 여기서 개발자가 눈여겨볼 부분은 “더 빠른 EVM”이라는 구호가 아니라, 블록이 어떤 계정과 storage slot을 건드렸는지 검증 가능한 데이터로 만들려는 시도다.

현재 Ethereum 실행은 기본적으로 순차적이다. 트랜잭션 A가 어떤 storage slot을 읽거나 쓸지 실행 전에는 일반 노드가 확정적으로 알기 어렵다. 두 트랜잭션이 서로 독립적이면 병렬 처리할 수 있지만, 그 독립성을 잘못 판단하면 상태 루트가 달라진다. 블록체인에서 병렬화는 단순 성능 최적화가 아니라 합의 안전 문제다.

EIP-7928의 Block-Level Access Lists, 줄여서 BAL은 이 병목을 건드린다. 블록 단위로 “이 블록 실행 중 접근한 계정, storage key, 그리고 post-execution 값”을 기록하고, 그 해시를 블록 헤더에 커밋한다. 즉 블록은 더 이상 트랜잭션 묶음만이 아니라, 실행이 어떤 상태 표면을 만졌는지에 대한 증거도 함께 가진다.

2. 핵심 개념

BAL의 핵심은 세 가지다.

첫째, access list가 트랜잭션 선택사항에서 블록 검증 조건으로 올라간다. 기존 EIP-2930 access list는 트랜잭션 작성자가 미리 상태 접근을 알려주는 선택적 힌트에 가깝다. EIP-7928은 블록 실행 결과 실제로 접근된 계정과 storage 위치를 블록 수준에서 강제한다. 누락되거나 불필요한 항목이 있으면 블록이 유효하지 않을 수 있다.

둘째, 헤더에는 전체 목록이 아니라 커밋먼트가 들어간다. EIP-7928은 block_access_list_hash = keccak256(rlp.encode(block_access_list)) 필드를 블록 헤더에 추가한다. 전체 BAL은 블록 바디에 직접 포함되지 않고 execution layer가 별도로 저장·전달한다. 그래서 노드는 받은 BAL을 RLP 인코딩하고 해시를 계산해 헤더와 맞는지 확인할 수 있다.

셋째, 목록은 읽기만 한 상태도 포함한다. BAL은 잔액, nonce, code, storage 변경뿐 아니라 읽기만 한 storage key와 상태 변화가 없는 계정 접근도 다룬다. 예를 들어 BALANCE, EXTCODEHASH, CALL, DELEGATECALL, STATICCALL, SLOAD 같은 접근은 결과가 revert되더라도 gas validation 규칙에 따라 실제 state access가 발생했다면 포함 대상이 된다.

한 문장으로 정리하면 이렇다. 병렬 실행의 전제는 CPU 코어 수가 아니라, 서로 겹치지 않는 상태 의존성을 합의 레벨에서 증명하는 것이다.

3. 최신 이슈와 연결

ethereum.org의 Glamsterdam 문서는 BAL을 ePBS와 함께 주요 제안으로 설명한다. ePBS가 block building과 proposal의 신뢰 경계를 프로토콜 안으로 끌어들이는 쪽이라면, BAL은 block execution과 state sync의 병목을 줄이는 쪽이다.

EIP-7928 스펙은 BAL이 네 가지를 가능하게 한다고 설명한다.

  • parallel disk reads
  • parallel transaction validation
  • parallel state root computation
  • executionless state updates

여기서 “executionless”라는 단어를 조심해서 읽어야 한다. 아무 검증 없이 결과를 믿는다는 뜻이 아니다. 블록 헤더의 BAL 해시와 전달받은 BAL, 그리고 필요한 검증 규칙을 이용해 상태 업데이트를 더 효율적으로 따라갈 수 있다는 의미다. 전체 EVM 실행을 항상 같은 방식으로 재생하지 않아도 되는 경로가 생긴다.

또 하나 중요한 연결점은 EIP-8159다. BAL이 별도 실행 계층 artifact라면, 네트워크는 이 데이터를 어떻게 주고받을 것인가? EIP-8159는 eth/71에서 GetBlockAccessLists, BlockAccessLists 메시지를 추가해 peer 간 BAL 요청과 응답을 정의한다. 즉 BAL은 “스펙 문서에 있는 추가 필드”로 끝나지 않고, p2p 전파와 sync 프로토콜까지 같이 바꿔야 하는 기능이다.

execution-apis PR #727도 같은 문제를 보여준다. PR 논의에서는 BAL이 ExecutionPayload의 일부이면서, execution layer가 실제 실행에 필요로 하는 무거운 artifact라는 점이 반복해서 나온다. 어떤 클라이언트는 BAL을 오래 저장하지 않고 root만 남기고 싶을 수 있다. 그러면 consensus layer와 execution layer 사이에서 payload body를 재구성하거나 가져오는 API 경계가 중요해진다.

4. 개발자 관점 해석

블록체인 개발자에게 BAL은 “Ethereum이 빨라질 수도 있다”보다 더 구체적인 의미가 있다.

첫째, 인덱서와 explorer는 블록 스키마 변화에 대비해야 한다. 헤더에 block_access_list_hash가 생기고, block-level state access artifact가 별도로 존재한다면, 블록을 저장·표시·검증하는 데이터 모델이 바뀐다. 지금까지 state diff를 만들기 위해 tracing이나 자체 재실행에 의존했다면, 향후에는 BAL을 authenticated feed처럼 다루는 경로가 생길 수 있다.

둘째, L2와 proving 시스템은 “어떤 상태를 증명해야 하는가”를 더 명시적으로 다룰 수 있다. 병렬 실행, stateless 또는 executionless sync, ZK proving 비용 최적화는 모두 상태 접근 표면을 줄이거나 예측 가능하게 만드는 문제와 연결된다. BAL은 이 표면을 프로토콜 객체로 만든다.

셋째, 노드 운영자는 저장 비용과 pruning 정책을 새로 봐야 한다. BAL은 블록 바디 안에 단순히 붙는 작은 필드가 아니다. execution layer가 별도 저장하고, peer에게 제공해야 하며, 일정 기간 이후에는 root만 보존하는 식의 정책이 논의된다. “archive node면 다 저장한다” 같은 단순 가정도 비용 추정에서 다시 계산해야 한다.

넷째, 보안 관점에서는 새로운 failure mode가 생긴다. BAL 생성 규칙이 클라이언트마다 다르게 구현되면 consensus split 위험이 생긴다. 어떤 opcode가 pre-state validation 실패로 실제 접근하지 않은 것으로 봐야 하는지, revert된 call target을 포함해야 하는지, system contract access를 어떤 index로 기록해야 하는지 같은 세부 규칙이 곧 합의 규칙이 된다.

5. 내 프로젝트에 적용할 체크포인트

  • 우리 인덱서가 block header schema 변경을 하드코딩하고 있지 않은가?
  • 실행 클라이언트 RPC나 Engine API 버전을 가정하는 코드가 있는가?
  • state diff를 만들 때 trace 재실행에만 의존하는가, 아니면 향후 BAL 같은 authenticated artifact를 받아들일 수 있는 추상화가 있는가?
  • L2, bridge, oracle, risk engine이 “source chain에서 실제로 어떤 상태가 변했는지”를 검증할 때 암묵적으로 archive node나 특정 RPC provider를 신뢰하고 있지 않은가?
  • 노드 운영 비용 추정에 blob, receipt, payload body뿐 아니라 신규 block artifact의 저장·전파 비용을 넣고 있는가?
  • 테스트에서 revert, out-of-gas, DELEGATECALL, CREATE2, precompile, system contract 접근 같은 edge case를 state access 관점으로 분리해 보고 있는가?

6. 오늘 10분 액션

10분만 쓴다면 아래 순서로 해보자.

  1. EIP-7928 문서에서 Scope and Inclusion 섹션을 연다.
  2. CALL, SLOAD, SSTORE, CREATE2, SELFDESTRUCT가 BAL에 언제 들어가고 언제 안 들어가는지 한 줄씩 메모한다.
  3. 내 프로젝트에서 사용하는 contract interaction 중 하나를 고른다.
  4. 그 트랜잭션이 읽는 account, 쓰는 storage slot, 단순히 code만 조회하는 address를 나눠 적는다.
  5. 마지막으로 질문한다. “이 접근 목록이 틀리면 어떤 노드가 다른 상태 루트를 계산할까?”

이 연습의 목적은 BAL 스펙을 외우는 것이 아니다. 스마트컨트랙트를 “함수 호출”이 아니라 “상태 표면을 읽고 쓰는 연산”으로 보는 습관을 만드는 것이다.

7. 더 볼 자료

중복 회피 메모

최근 blockchain_dev 글은 PeerDAS와 blob data availability, Arbitrum Nova 오프보딩, Ethereum native account abstraction, Zcash 비상 차단, Gnosis Pay 모듈 권한 검증을 다뤘다. 이번 글은 데이터 가용성이나 지갑 권한이 아니라 EIP-7928 Block-Level Access Lists가 실행 상태 접근을 합의 객체로 바꾸는 원리와 그로 인한 병렬 실행·sync·인덱싱 실패 모드에 집중해 기존 글과 관점을 분리했다.

댓글 0

최신순 ▾
한 줄 남기기

혹시 이 글을 읽는 동료 개발자가 있다면, GitHub으로 로그인하고 한 줄 흔적을 남겨줘요. (스팸 방지용 로그인이에요)