피드백과 검토를 해주신 Péter Garamvölgyi , Thomas Thiery , Francesco Risitano , Jihoon Song 님께 감사드립니다.
본 문서는 FOCIL (SFI), 선택적 실행 증명 (PFI), 블록 수준 접근 목록 (SFI), 유효성 전용 부분 무상태화 ( 이더리움 개선 제안(EIP) 없음), 네이티브 롤업 (아직 제안되지 않음) 등 매우 다양한 도입 단계 에 있는 EIP를 기반으로 하거나 관련되어 있습니다. 따라서 세부 사항은 시간이 지남에 따라 변경될 수 있습니다. 본 연구는 주로 네이티브 롤업을 위한 간단한 강제 트랜잭션 메커니즘을 찾는 데서 비롯되었지만, 연구 결과는 기존 EVM L2를 포함한 모든 이더리움 가상 머신(EVM) L2에 일반적으로 적용될 수 있습니다.
추상적인
본 논문에서는 기존 솔루션과 달리 상태 전이 함수나 새로운 트랜잭션 유형을 수정하지 않고도 이더리움 가상 머신(EVM) L2의 중앙 집중식 시퀀서를 우회하는 데 사용할 수 있는 FOCIL 기반의 강제 트랜잭션 메커니즘 구현을 제시합니다.
배경
FOCIL은 이더리움의 STF를 업데이트하여 블록 인증되기 위해 충족해야 하는 새로운 트랜잭션 목록("포함 목록")을 추가합니다. 이러한 트랜잭션은 CL 측의 16개 검증자로 구성된 "IL 위원회"에서 선택되며, 업데이트된 엔진 API를 통해 EL로 전달됩니다.
def state_transition ( chain: BlockChain, block: Block, inclusion_list_transactions: Tuple [LegacyTransaction | Bytes, ...] ) -> None :IL에서의 거래는 다음 세 가지 이유로 블록 에서 유효하게 제외될 수 있습니다.
내부 검사 실패: 잘못된 트랜잭션 형식, 잘못된 체인 ID, 가스 부족, 유효하지 않은 서명, 매개변수 범위 초과;
상태 기반 검사 실패: 논스 불일치, 잔액 부족;
블록 관련 검사 실패: 가스 부족(기본 수수료 기준), 블록 공간 부족.
빌더가 "블록 스터핑"을 통해 의도적으로 트랜잭션을 제외할 수 있지만, 프로토콜은 이더리움 개선 제안(EIP)-1559 기본 수수료를 인상하고 해당 트랜잭션을 멤풀에 유지하여 다음 IL에 삽입함으로써 공격자에게 기하급수적인 비용을 부과하여 검열 저항성을 제공합니다.
현재 존재하는 모든 이더리움 가상 머신(EVM) L2는 새로운 트랜잭션 유형을 도입하고 상태 전환 함수를 수정하여 강제 트랜잭션을 구현합니다. 옵티미즘(OP) 스택은 L1 이벤트에서 파생되어 해당 L2 블록 의 맨 위에 자동으로 삽입되고, L2에서 서명이 없으며, L1에서 가스비를 지불하고 L2에서는 가스비를 소모하지 않는 "입금 트랜잭션" 유형을 도입했습니다. geth 위에 op-geth가 적용한 모든 변경 사항은 여기에서 확인할 수 있습니다. 아비트럼(Arbitrum) 스택 또한 서명이 없는 새로운 트랜잭션 유형(실제로는 여러 개)을 도입했는데, 이 트랜잭션은 온체인 강제 트랜잭션 큐에 의해 포함이 강제되지만 L2에서 가스비를 지불합니다. geth 위에 적용된 모든 변경 사항은 여기에서 확인할 수 있습니다. 가장 중요한 것은 두 경우 모두 강제 포함 대상 트랜잭션 목록에 포함된 유효한 트랜잭션은 블록 초과나 기본 수수료 때문에 유효하게 제외되지 않는다는 것입니다. 해당 트랜잭션을 위한 공간은 항상 예약되며, 기본 수수료는 계산되지 않거나 재시도 메커니즘이 구현됩니다.
메커니즘
핵심 아이디어는 FOCIL의 CL 및 멤풀 로직을 L1 스마트 계약으로 완전히 대체하고 복제할 수 있다는 것입니다. 사용자는 기존의 L2 멤풀 대신 L1 스마트 계약(아마도 L1 FOCIL을 통해!)에 강제 트랜잭션을 제출하고, 이 스마트 계약은 포함 목록을 생성하여 엔진 API가 EL에 전달하는 방식과 유사하게 L2 STF 검증기에 입력으로 전달합니다. L2 STF는 이더리움 개선 제안(EIP)-8025에서 도입된 상태 비저장 STF 함수와 완전히 동일하다고 가정합니다. 8025는 아직 Hegotá를 기반으로 구축되지 않았고 FOCIL을 고려하지 않았기 때문에, 상태 비저장 IL 인터페이스를 자유롭게 구상할 수 있습니다.
L1의 FOCIL 검사에 사용되는 CL 및 EL 구성 요소를 "L2 FOCIL"이 어떻게 대체하는지 보여주는 그림입니다.
멤풀 동작을 모방하고 검열 저항성을 보장하기 위해, 기존의 강제 트랜잭션 메커니즘과 달리 FOCIL은 특정 블록 에 포함되는 것을 보장하지 않으므로, L2 IL에 포함된 트랜잭션이 자동으로 삭제되지 않도록 해야 합니다. 또한, 증명자 측의 연산 낭비와 유효한 트랜잭션에 대한 DoS 공격을 방지하기 위해, 유효하지 않은 트랜잭션은 IL을 최대한 오염시키지 않아야 합니다.
우리는 운영자가 게시하는 각 L2 배치(batch)가 하나의 L2 블록 에 해당한다고 가정합니다. 그렇지 않으면 운영자가 기본 수수료를 낮추고 블록 스터핑 공격을 저렴하게 수행하기 위해 항상 빈 블록을 생성할 수 있기 때문입니다. 현재 대부분의 롤업(rollup)에서는 이러한 가정이 성립하지 않지만, 플래시 블록(flashblock) 과 같은 기술을 사용하여 더 빠른 블록 생성을 시뮬레이션할 수 있습니다.
따라서 우리는 다음과 같이 강제 트랜잭션 계약을 설계합니다. 사용자는 서명된 트랜잭션을 온체인 목록에 제출하며, 이 목록은 `maxFeePerGas` 값이 큰 순서대로 내림차순으로 정렬됩니다. 제출 시 모든 내재적(즉, 상태 비저장) 검사가 수행됩니다. 유효성 검사 전용 부분 상태 비저장(VOPS) 연구 게시물과 여기 에서 설명했듯이, 상태 저장 검사를 수행하는 것은 건전한 멤풀을 유지하는 데 필수적입니다. L2 FOCIL에서 제출된 트랜잭션이 L1에서 가스비를 지불하더라도, `maxFeePerGas` 값이 매우 높지만 논스 값이 유효하지 않거나 잔액이 부족한 트랜잭션으로 목록의 맨 앞부분을 채우는 것은 비용이 저렴하여 IL에 유효하지 않은 트랜잭션만 포함하게 됩니다. 따라서 VOPS는 상태 비저장 노드가 BAL을 통해 각 계정의 잔액과 논스 유지해야 한다고 제안합니다. 이더리움 가상 머신(EVM) L2도 BAL을 생성하고 게시할 수 있지만, 스마트 계약에 잔액과 논스를 유지하는 것은 현실적으로 불가능합니다. L1의 경우 예상 저장 공간이 이미 약 8.4GB에 달하며, L2의 경우 훨씬 더 높을 것으로 예상됩니다. 따라서 사용자는 최근 L2 상태를 기반으로 eth_getProof를 통해 얻은 계정 증명을 제출해야만 목록에 포함될 수 있습니다. FOCIL은 트랜잭션이 포함 목록에 포함되었는지 여부와 그 이유를 알려주지 않기 때문에, 이러한 검사 후에도 포함 목록에 포함된 트랜잭션을 자동으로 삭제할 수 없습니다. 두 가지 메커니즘을 사용할 수 있습니다.
비허가형(Permissionless) '가지치기' 기능이 추가되었는데, 이 기능은 최신 블록 에 대한 계정 증명을 입력받아 논스 변경되었거나 잔액이 부족해졌음을 증명합니다. 이더리움 개선 제안(EIP)-7702 에서 계정 잔액은 논스 증가할 때만 감소할 수 있다는 불변 조건이 깨졌기 때문에 논스 검사만으로는 충분하지 않다는 점을 기억해야 합니다. 인센티브 호환성을 확보하기 위해, 강제로 트랜잭션을 제출하는 사용자에게 트랜잭션이 무효화될 때 가지치기 작업에 참여한 사용자에게 환불해 줄 소액의 보증금을 제출하도록 요청할 수 있습니다.
운영자는 정산 과정에서 트랜잭션 루트에 대한 머클 증명을 제공합니다. IL이 STF(예: ZK 증명)에 의해 검증된다는 점을 고려할 때, 트랜잭션이 포함되지 않았고 블록 에 공간이 남아 있었다면 해당 트랜잭션은 유효하지 않은 것으로 판단하여 삭제할 수 있습니다. 예상 비용은 IL 트랜잭션당 약 275,000 가스이며, 32개의 트랜잭션은 1,000만 가스 이내로 계산되고, 멀티프루프를 사용하면 더 낮아질 수 있습니다. IL의 트랜잭션이 유효하지 않지만 블록에 공간이 부족한 경우, 전체 블록 사례와 유효하지 않은 사례를 구분할 수 없으므로 해당 트랜잭션은 삭제되지 않습니다. 1559 기본 수수료 메커니즘은 충분한 탄력성이 확보된다면 블록 에 충분한 공간이 확보된 블록 최종적으로 생성될 것을 보장합니다.
L2 운영자는 L2 블록 사용하여 정산 함수를 호출할 때, 미리 정의된 가스 예산까지 또는 거래가 현재 기본 수수료를 충당할 만큼 충분한 금액을 지불하지 않을 때까지 목록 상단의 거래에서 현재 IL(Inventory List)을 가져옵니다. 이러한 IL은 온체인 검증자의 입력으로 사용되며, IL의 충족 여부가 유효성 규칙으로 간주됩니다. 경쟁 조건 및 악의적인 공격을 방지하기 위해, IL은 스레스홀드(Threshold) 보다 오래된 거래만으로 구성될 수 있으므로, 검증자는 포함해야 하는 정확한 거래를 사전에 알 수 있습니다. L2 중앙 집중식 시퀀서가 블록 생성을 완전히 거부하는 경우, 온체인에서 타임아웃이 발생하여 화이트리스트를 제거하고 검열 저항성을 복원할 수 있습니다.
구체적인 구현 예시는 여기에서 확인할 수 있습니다. 제출 작업에는 약 130만 가스가, 가지치기 작업에는 약 110만 가스가 소모될 것으로 예상되며, 이는 1gwei당 가스 기준으로 약 0.001 이더리움(ETH) 에 해당합니다.
이 연구 게시물의 범위를 벗어나지만, 강제 거래 계약은 특정 L2 요구 사항에 따라 승인 전에 추가 검사를 수행하도록 자연스럽게 맞춤 설정할 수 있습니다.
계정 전용 노드
현재 계정 증명을 얻으려면 풀 노드에 연결해야 하는데, 이는 대부분의 사용자, 특히 L2 사용자에게는 부담스러운 일입니다. VOPS 제안은 zkEVM과 결합하여 증명만을 사용하여 상태를 검증하고 BAL을 통해 얻은 잔액과 논스만 저장하여 메모리 풀을 적정 수준으로 유지함으로써 증명자와 포함자의 저장 부하를 약 233GiB에서 약 8.4GiB로 줄이는 것을 목표로 합니다. L2 사용자 또한 증명을 게시하고 BAL을 게시할 수 있으므로, L2 사용자를 위한 유사한 유형의 노드를 구상할 수 있습니다. 이를 통해 사용자는 전체 상태를 유지하지 않고도 검열 시 강제 거래를 더 쉽게 제출할 수 있습니다. 그러나 BAL은 저장 차이만 저장하므로 계정 증명을 제공하는 데 필요한 저장 루트를 재구성하려면 전체 상태를 추적해야 합니다. 참고로 밸런서(BAL) 다음과 같이 정의됩니다.
BlockAccessList = List [AccountChanges]AccountChanges = [Address, # address List [SlotChanges], # storage_changes (slot -> [block_access_index -> new_value]) List [StorageKey], # storage_reads (read-only storage keys) List [BalanceChange], # balance_changes ([block_access_index -> post_balance]) List [NonceChange], # nonce_changes ([block_access_index -> new_nonce]) List [CodeChange] # code_changes ([block_access_index -> new_code]) ]계정은 트라이에서 다음과 같이 직렬화됩니다.
def encode_account ( raw_account_data: Account, storage_root: Bytes ) -> Bytes: """Encode `Account` dataclass.Storage is not stored in the `Account` dataclass, so `Accounts` cannot beencoded without providing a storage root.""" return rlp.encode((raw_account_data.nonce,raw_account_data.balance,storage_root,raw_account_data.code_hash,))만약 BAL(블록 주소 목록)이 저장소 루트 변경 사항까지 포함하도록 수정된다면(이 중 마지막 블록 끝 부분의 변경 사항만 필요함), 노드는 전체 상태를 유지하지 않고도 계정 증명을 구성할 수 있게 됩니다. 이더리움 개선 제안(EIP)-8268 (참고 자료를 제공해 주신 Toni 님께 감사드립니다!)은 바로 이러한 변경을 제안합니다.




