EIP-7805 포크 초이스로 강제하는 포함 목록 (Fork-choice enforced Inclusion Lists (FOCIL))
콜 결정 없음 · 합의·스테이킹 · 원문 상태 Draft · 2024-11-01 작성
매 슬롯 검증자 16명으로 이루어진 위원회가 공개 멤풀의 거래로 포함 목록을 만들고 그 거래를 넣지 않은 블록에는 증명자가 투표하지 않게 해 거래가 검열 없이 제때 들어가게 합니다.
왜 필요한가
이더리움은 검증자 집단이 중앙화되는 것을 막으려고 블록을 만드는 권한을 빌더(builder)라는 전문 업체에 경매로 넘겨 왔습니다. 그 결과 소수의 정교한 빌더가 블록 생산을 장악했고 네트워크가 특정 거래를 빼먹지 못하게 하는 검열 저항성이 나빠졌습니다. 이를 풀기 위해 검증자가 빌더에게 제약을 걸 수 있게 하는 연구가 이어졌고 그 방법이 포함 목록(inclusion list, IL)으로 거래를 블록에 강제로 넣는 것입니다. 다만 앞선 포함 목록 설계와 블록 공동 생성 제안에는 매수·협박 공격, 목록 이중 서명, 계정 추상화, 거래 무효화 문제가 있었습니다. FOCIL은 여러 검증자로 이루어진 위원회가 목록을 만들고 목록을 만족하지 않는 블록에는 증명자가 투표하지 않도록 포크 초이스 규칙에 넣어 이 문제들을 다룹니다.
무엇이 바뀌나
지금
- 블록을 만드는 권한이 소수의 전문 빌더에게 집중돼 있고 빌더가 특정 거래를 빼도 막을 방법이 없습니다.
- 앞선 포함 목록 설계(EIP-7547)는 선행형이라 거래가 한 슬롯 늦게 강제됩니다.
- 포함 목록을 제안자 한 명이 만들면 매수·협박 공격에 노출됩니다.
EIP-7805 이후
- 매 슬롯 16명의 위원회가 각자 공개 멤풀에서 거래를 골라 포함 목록을 퍼뜨립니다.
- 제안자나 빌더는 모은 목록의 거래를 블록에 넣어야 하고 넣지 않은 블록은 증명자가 투표하지 않아 정식 체인이 되지 못합니다.
- 슬롯 N에 제출된 거래가 슬롯 N+1 블록에 바로 강제될 수 있습니다.
- 목록 거래를 블록 끝에 붙여도 무효이거나 블록이 가득 찼으면 빠져도 됩니다(조건부 포함).
누구에게 영향이 있나
- 사용자: 거래를 공개 멤풀에 올리면 빌더가 임의로 빼기 어려워집니다. 지갑 사용 방식이나 경험은 바뀌지 않습니다.
- 검증자: 위원회로 뽑히면 매 슬롯 목록을 만들어 퍼뜨리고 증명자는 목록 조건을 확인한 블록에만 투표합니다. 별도 보상은 없습니다.
- 빌더·제안자: 슬롯 N의 목록을 모두 받아 11초에 페이로드를 갱신해야 하므로 위원회 멤버와 잘 연결돼 있어야 합니다.
- 클라이언트 팀: 합의 계층의 비콘 체인·포크 초이스·P2P 변경과 실행 계층의 엔진 API 변경을 함께 구현해야 하며 하드 포크가 필요합니다.
심층 설명
실행 계층의 포함 목록 검사
실행 계층은 새 페이로드를 받을 때 검사를 하나 더 합니다. 블록 B의 거래를 모두 실행한 뒤 상태를 S, 남은 가스를 gas_left라 두고 포함 목록에 있는 거래 T마다 다음 순서로 봅니다. 첫째, T가 B에 이미 있으면 다음 거래로 넘어갑니다. 둘째, T.gas가 gas_left보다 크면 다음 거래로 넘어갑니다. 셋째, S를 기준으로 T.origin의 논스와 잔액을 검사합니다. 무효이면 다음 거래로 넘어가고 유효하면 즉시 멈추고 INCLUSION_LIST_UNSATISFIED 상태를 돌려줍니다. 즉 블록에 빠진 목록 거래 중 끝에 붙여도 실행될 수 있는 것이 하나라도 있으면 목록을 만족하지 못한 것입니다. 이때 블록 자체는 유효하지만 합의 계층은 그 블록에 증명하지 않습니다.
Engine API 변경과 목록 작성 규칙
엔진 API에 세 가지 변경이 들어갑니다. ExecutionEngine에서 포함 목록을 가져오는 engine_getInclusionListV1 엔드포인트를 새로 추가합니다. engine_forkchoiceUpdated는 블록을 만들 때 쓸 포함 목록을 payloadAttributes에 넣어 전달하도록 확장합니다. engine_newPayload에는 위원회가 정한 포함 목록 거래를 담는 매개변수를 추가하고 목록이 만족되지 않으면 INCLUSION_LIST_UNSATISFIED 상태를 반드시 돌려줍니다. 목록을 어떻게 채울지는 구현자 재량입니다. 공개 멤풀에서 무작위로 고르거나, 우선순위 수수료 순으로 고르거나, 대기 시간이 긴 순으로 고를 수 있습니다. 다만 RLP로 인코딩한 거래 전체 크기가 MAX_BYTES_PER_INCLUSION_LIST = 8 KiB를 넘을 수 없습니다.
비콘 체인 상수와 새 컨테이너
비콘 체인 프리셋에 세 값이 추가됩니다. DOMAIN_IL_COMMITTEE는 DomainType('0x0C000000'), IL_COMMITTEE_SIZE는 uint64(2**4)로 16명, MAX_BYTES_PER_INCLUSION_LIST는 uint64(2**13)으로 8192바이트입니다. 새 컨테이너 InclusionList에는 slot, validator_index, inclusion_list_committee_root, transactions 네 필드가 있습니다. transactions는 List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD] 타입입니다. SignedInclusionList는 InclusionList를 message로 담고 BLSSignature 타입의 signature를 붙입니다. 비콘 체인, 포크 초이스, P2P, 정직한 검증자 안내서의 전체 변경 내용은 consensus-specs 저장소의 _features/eip7805 아래에 나뉘어 있습니다.
포크 초이스와 P2P 변경
포크 초이스에는 세 규칙이 더해집니다. 뷰 동결 시점 전에 가십으로 받은 포함 목록을 저장합니다. 같은 위원회 멤버에게서 목록을 두 개 이상 받으면 그 멤버를 이중 서명자로 표시하고 이후 목록은 무시합니다. 현재 슬롯의 비콘 블록은 이중 서명자가 아닌 멤버의 저장된 목록을 모두 만족할 때만 증명합니다. P2P에는 SignedInclusionList를 퍼뜨리는 전역 토픽 하나와, 위원회 인덱스로 SignedInclusionList를 요청하는 RPC 토픽 하나가 새로 생깁니다. 검증자는 슬롯 N+1의 증명 마감(t=4s)이 지나면 직전 슬롯 위원회의 새 목록을 무시하고 이중 서명 증거 기록도 멈춥니다.
합의 계층 P2P 검증 규칙 여섯 가지
검증자는 포함 목록을 받으면 전파하거나 저장하기 전에 여섯 가지를 확인합니다. 1) 목록의 슬롯이 현재 또는 직전 슬롯과 일치합니다. 2) 목록이 가리키는 위원회 루트가 해당 슬롯의 기대 위원회 루트와 일치합니다. 3) 이 멤버에게서 받은 목록이 두 개 이하입니다. 4) 검증자 서명이 올바릅니다. 5) 그 검증자가 위원회에 속합니다. 6) 목록 크기가 MAX_BYTES_PER_INCLUSION_LIST = 8 KiB를 넘지 않습니다. 이 규칙은 목록 크기를 제한하고 작성 권한을 소수 위원회로 묶어 대역폭 소모를 좁게 묶습니다. 전파 중 의미 있는 검사는 서명 검증뿐이라 검증 시간 부담도 작습니다. 이 단계에서는 실행 계층 쪽 유효성 검사를 하지 않으므로 유효하지 않은 거래가 목록에 들어 있어도 전파됩니다. 추가 연산 부담을 피하려는 선택입니다.
설계 원칙 여섯 가지
위원회 기반: 제안자 한 명이 아니라 여러 검증자가 목록을 만들어 매수·협박 공격 표면을 크게 줄입니다. 포크 초이스 강제: 강제 포함을 합의 과정의 핵심인 포크 초이스 규칙에 넣어 누구도 우회하지 못하게 합니다. 조건을 만족하지 못한 블록은 증명자가 투표하지 않으므로 정식 체인이 될 수 없습니다. 같은 슬롯: 슬롯 N 동안 슬롯 N+1 블록 생성과 병렬로 돌아가므로 슬롯 N에 제출된 거래를 바로 강제할 수 있습니다. 한 슬롯 지연이 있던 EIP-7547 같은 선행형 목록 설계보다 확실히 나아진 점입니다. 조건부 포함: 블록 끝에 붙일 수 없거나 블록이 가득 찼으면 일부 목록 거래가 빠져도 받아들입니다. 위치 무관: 목록 거래가 블록 어디에 있든 상관하지 않아 사이드 채널로 우회할 유인을 줄이고 조건부 포함과 합쳐져 프로토콜 밖 시장이 생길 매력을 떨어뜨립니다. 보상 없음: 위원회 멤버에게 명시적 보상을 주지 않습니다. 수수료 체계를 더하는 복잡성이 정당화되지 않는다고 보며 위원회 N명 중 1명만 정직하면 되는 가정이라 이타적 참여에 기댑니다.
보안 고려: 라이브니스, 이중 서명, 페이로드 구성
합의 라이브니스: 슬롯 N+1의 빌더는 슬롯 N에 퍼진 목록을 받기 전에는 정식 블록을 만들 수 없습니다. 따라서 빌더(제안자가 직접 만드는 경우 포함)는 위원회 멤버와 잘 연결돼 있어야 하고 뷰 동결(슬롯 N의 t=9s)과 블록 전파 사이에 목록을 모아 페이로드를 갱신할 시간이 충분해야 합니다. 이중 서명: 멤버당 목록 두 개까지만 전파하는 P2P 규칙을 둡니다. 같은 멤버가 보낸 다른 목록 두 개를 보면 그 멤버의 목록을 전부 무시합니다. 최악의 경우 가십 서브넷 대역폭은 두 배까지 늘 수 있습니다. 페이로드 구성: 미포함 목록 거래를 사후 상태에 대고 확인하고 유효하면 끝에 붙인 뒤 다시 처음부터 확인하는 단순한 방식은 n개 거래에 n + (n-1) + (n-2) + ... 번, 즉 O(n^2) 검사가 필요할 수 있습니다. n번째 거래만 유효한데 그 실행이 n-1번째 거래 발신자에게 잔액을 보내 차례로 유효해지는 경우가 그 예입니다. 대신 빌더는 페이로드를 만들기 전에 목록 거래에 관련된 모든 EOA의 nonce와 balance를 저장해 두고 nonce가 오르거나 nonce 변화 없이 balance가 바뀔 때(예: 계정 추상화 거래가 그 EOA와 상호작용한 경우)만 갱신하면서 실시간으로 유효성을 판단할 수 있습니다.
상태와 포크 포함 논의
이 EIP는 Draft 상태라 내용이 바뀔 수 있습니다. 원문도 빌더가 목록 뷰를 동결하고 페이로드를 갱신하는 정확한 시점은 테스트와 벤치마크 뒤에 정하겠다고 적고 있습니다. 합의 계층 블록 검증 규칙을 바꾸는 하위 호환 불가 변경이라 하드 포크가 필요하지만 현재 사용자 활동과 경험을 깨뜨리는 부분은 없습니다. 코어 개발자 콜에서는 09.21 ACDT #97에서 헤고타(Hegota) 데브넷을 FOCIL 전용과 프레임 전용으로 따로 시작한 뒤 안정되면 통합 헤고타 데브넷으로 합치기로 확정했습니다. 복잡한 상호작용을 초반에 분리해 원인 파악을 쉽게 하려는 결정입니다. 10.12 ACDT #100에서는 heze-devnet-2에 EIP-7805(FOCIL)를 EIP-8015(eth1data 제거), EIP-8365(0x00 검증자 금지), EIP-8198(퀵 슬롯, 12초)과 함께 포함하기로 확정해 합의 계층 쪽 헤고타 후보들을 한 데브넷에서 같이 검증합니다.