
비탈릭 최신 글: ZK-EVM의 미래와 과제 탐색
작성: Vitalik Buterin
번역: 1912212.eth, Foresight News
옵티미스틱 롤업과 ZK 롤업을 포함한 이더리움 위의 레이어 2 EVM 프로토콜은 모두 EVM 검증에 의존한다. 그러나 이는 방대한 코드베이스를 신뢰해야 하며, 해당 코드베이스에 오류가 존재할 경우 이러한 VM들이 해킹될 위험이 있다. 또한 이는 L1 EVM과 완전히 동등하려는 ZK-EVM조차도 자신의 EVM 구현에 L1 EVM의 변경 사항을 복사하기 위해 어떤 형태의 거버넌스가 필요하다는 것을 의미한다.
이러한 상황은 이상적이지 않다. 왜냐하면 이러한 프로젝트들은 이미 이더리움 프로토콜 내에 존재하는 기능을 재현하고 있으며, 이더리움 거버넌스는 업그레이드와 버그 수정을 담당하기 때문이다. ZK-EVM은 기본적으로 1단계 이더리움 블록 검증 작업과 동일하다! 게다가 향후 몇 년 안에 경량 클라이언트가 점점 더 강력해져 곧 ZK-SNARKs를 사용하여 1단계 EVM 실행을 완전히 검증하는 수준에 이를 것으로 예상된다. 그때쯤이면 이더리움 네트워크는 사실상 내장된 ZK-EVM을 갖게 될 것이다. 따라서 문제는 왜 롤업에도 ZK-EVM 자체를 적용하지 않느냐는 것이다.
본 문서에서는 실현 가능한 여러 형태의 '내장형 ZK-EVM'에 대해 소개하고, 각각의 트레이드오프와 설계 과제, 그리고 특정 방향을 선택하지 않는 이유들을 논의할 것이다. 프로토콜 기능을 도입함으로써 얻는 이점을 생태계에 맡기고 기본 프로토콜을 단순하게 유지함으로써 얻는 이점과 균형을 맞춰야 한다.
내장형 ZK-EVM에서 기대하는 핵심 기능은 무엇인가?
-
기본 기능: 이더리움 블록 검증. 프로토콜 기능(현재로서는 오퍼코드, 사전 컴파일 또는 기타 메커니즘인지 명확하지 않음)은 최소한 하나의 사전 상태 루트(pre-state root), 하나의 블록, 하나의 사후 상태 루트(post-state root)를 입력으로 받아, 사후 상태 루트가 실제로 블록 실행 후의 결과임을 검증해야 한다.
-
여러 이더리움 클라이언트와의 호환성. 즉, 단일 증명 시스템만을 채택하는 것이 아니라 서로 다른 클라이언트가 서로 다른 증명 시스템을 사용할 수 있도록 해야 한다. 이는 다음과 같은 요소들로 이어진다:
-
데이터 가용성 요구사항: 내장형 ZK-EVM을 사용하여 EVM 실행을 증명하는 모든 경우, 해당 기본 데이터의 가용성이 보장되어야 하며, 이를 통해 다른 증명 시스템을 사용하는 증명자가 실행을 다시 증명할 수 있고, 해당 증명 시스템에 의존하는 클라이언트가 새로 생성된 증명을 검증할 수 있어야 한다.
-
EVM 및 블록 데이터 구조 외부에 존재하는 증명: 내장형 ZK-EVM 기능은 서로 다른 클라이언트가 서로 다른 유형의 SNARK를 기대하기 때문에 SNARK를 EVM 내 입력으로 받지 않는다. 대신 blob 검증과 유사할 수 있다. 즉, 트랜잭션은 (사전 상태, 블록 본문, 사후 상태)를 증명해야 할 선언을 포함할 수 있으며, 오퍼코드나 사전 컴파일이 이러한 선언의 내용에 접근할 수 있고, 클라이언트 합의 규칙이 각 선언의 데이터 가용성과 존재 증명을 별도로 검사한다.
-
감사 가능성(Auditability): 어떤 실행이라도 증명되면, 문제가 발생했을 때 사용자와 개발자가 이를 확인할 수 있도록 하기 위해 기본 데이터가 가용하도록 해야 한다. 실제로 이것은 데이터 가용성 요구사항이 왜 중요한지에 대한 또 다른 이유를 제공한다.
-
업그레이드 가능성: 만약 특정 ZK-EVM 방식에 버그가 발견되면 이를 신속하게 수정할 수 있어야 한다. 즉, 하드포크 없이도 수정할 수 있어야 한다. 이것이 증명이 EVM 및 블록 데이터 구조 외부에 존재해야 하는 이유 중 하나이다.
-
거의 모든 EVM 지원: L2의 매력 중 하나는 실행 계층에서 혁신을 이루고 EVM을 확장하는 것이다. 주어진 L2의 VM이 EVM과 약간만 다르다면, L2가 여전히 EVM과 동일한 부분에서는 내장형 프로토콜 ZK-EVM을 사용하고, 다른 부분에서는 자신의 코드에만 의존할 수 있으면 좋을 것이다. 이는 호출자가 비트필드 또는 오퍼코드 목록, 혹은 외부에서 제공된 테이블에서 처리되는 주소 목록을 지정할 수 있는 ZK-EVM 기능을 설계함으로써 가능하다. 또한 일정 정도까지 가스 비용을 열어 수정 가능하게 할 수도 있다.
"열린"과 "닫힌" 다중 클라이언트 시스템
"다중 클라이언트 철학"은 아마도 이 목록에서 가장 주관적인 요구사항일 것이다. 이를 포기하고 ZK-SNARK 방식에 집중하는 선택을 할 수 있는데, 이는 설계를 단순화시키지만 대신 이더리움의 더 큰 "철학적 전환점"이 되며(실제로 이는 이더리움의 오랜 다중 클라이언트 철학을 포기하는 것과 같다), 더 큰 위험을 수반한다. 미래에 형식적 검증 기술이 더 좋아질 경우 이런 방식이 더 나을 수 있지만, 현재로서는 위험이 너무 크다고 생각된다.
또 다른 선택은 프로토콜 내에 고정된 일련의 증명 시스템이 알려진 '닫힌' 다중 클라이언트 시스템이다. 예를 들어, PSE ZK-EVM, Polygon ZK-EVM, Kakarot 등 세 가지 ZK-EVM을 사용하기로 결정할 수 있다. 블록은 이들 중 두 개의 증명을 제공해야 유효하다. 단일 증명 시스템보다는 낫지만, 시스템의 적응력을 저하시킨다. 사용자는 존재하는 모든 증명 시스템에 대해 검증기를 유지해야 하며, 새로운 증명 시스템을 포함하기 위한 정치적 거버넌스 과정이 불가피하게 발생한다.
이러한 이유로 나는 증명이 '블록 외부'에 배치되고 클라이언트별로 독립적으로 검증되는 '열린' 다중 클라이언트 시스템을 선호한다. 개인 사용자는 원하는 클라이언트를 사용하여 블록을 검증할 수 있으며, 해당 증명 시스템에 대해 증명을 생성하는 증명자가 하나만 있으면 된다. 증명 시스템은 프로토콜 거버넌스 과정을 설득하는 것이 아니라 사용자가 자신을 실행하도록 설득함으로써 영향력을 얻게 된다. 그러나 이 방법은 우리가 보게 되겠지만 더 높은 복잡성 비용을 수반한다.
ZK-EVM 구현에서 기대하는 핵심 속성은 무엇인가?
기본적인 기능 정확성과 보안 보장을 제외하면 가장 중요한 속성은 속도이다. 프로토콜 내 ZK-EVM 기능을 비동기식으로 설계하여 N개 슬롯의 지연 후에 각 선언에 대한 답을 반환하게 할 수는 있지만, 몇 초 안에 증명을 생성할 수 있다는 것을 신뢰할 수 있다면, 각 블록에서 발생하는 모든 것이 자체적으로 포함되어 문제를 훨씬 쉽게 만들 수 있다.
오늘날 이더리움 블록에 대한 증명 생성에는 수십 분 또는 수시간이 소요되지만, 대규모 병렬화를 막는 이론적 이유는 없다는 것을 알고 있다. 우리는 항상 충분한 GPU를 결합하여 블록 실행의 각 부분을 개별적으로 증명하고, 재귀적 SNARK를 사용하여 증명을 통합할 수 있다. 또한 FPGA 및 ASIC 하드웨어 가속을 통해 증명을 더욱 최적화할 수 있다. 그러나 실제로 이 단계에 도달하는 것은 경시할 수 없는 거대한 공학적 도전이다.
프로토콜 내 ZK-EVM 기능의 구체적인 형태는 어떻게 될 수 있을까?
EIP-4844 blob 트랜잭션과 유사하게, ZK-EVM 선언을 포함하는 새로운 유형의 트랜잭션을 도입한다:
class ZKEVMClaimTransaction(Container):
pre_state_root: bytes32
post_state_root: bytes32
transaction_and_witness_blob_pointers: List[VersionedHash]
EIP-4844와 마찬가지로, 메모리풀에서 전달되는 객체는 트랜잭션의 수정된 버전이다:
class ZKEvmClaimNetworkTransaction(Container):
pre_state_root: bytes32
post_state_root: bytes32
proof: bytes
transaction_and_witness_blobs: List[Bytes[FIELD_ELEMENTS_PER_BLOB * 31]]
후자는 전자로 변환될 수 있지만 그 반대는 불가능하다. 또한 블록 사이드카드 객체(EIP-4844에서 도입됨)를 확장하여 블록 내 선언에 대한 증명 목록을 포함시킨다.

실제로는 사이드카드를 blobs용 하나, 증명용 하나로 분리하고, 각 유형의 증명(및 blobs에 대한 추가 서브넷)마다 별도의 서브넷을 설정하는 것이 바람직할 수 있다.
컨센서스 레이어에서는 클라이언트가 블록 내 각 선언에 대한 유효한 증명을 확인했을 때만 블록을 수락하는 검증 규칙을 추가한다. 증명은 transaction_and_witness_blobs의 연결이 (Block, Witness) 쌍의 직렬화임을 증명하는 ZK-SNARK여야 하고, witness에 대해 pre_state_root를 사용하여 블록을 실행했을 때
(i) 유효하며,
(ii) 올바른 post_state_root를 출력해야 한다. 클라이언트는 M-of-N 방식으로 여러 유형의 증명을 기다릴 수 있다.
여기서 주목할 점은 블록 실행 자체도 ZKEVMClaimTransaction 객체에 제공된 삼원조(σpre,σpost,Proof)와 함께 검사해야 하는 삼원조 중 하나로 간주될 수 있다는 것이다. 따라서 사용자의 ZK-EVM 구현은 실행 클라이언트를 대체할 수 있다. 실행 클라이언트는 여전히
(i) 증명자와 블록 빌더, 그리고
(ii) 로컬에서 인덱싱 및 저장 데이터를 사용하려는 노드에 의해 사용된다.
또한 이러한 아키텍처는 실행과 검증을 분리하므로 이더리움 생태계 내 다양한 역할에 더 많은 유연성과 효율성을 제공할 수 있다. 예를 들어, 증명자는 실행 세부 사항을 걱정하지 않고 증명 생성에 집중할 수 있으며, 실행 클라이언트는 빠른 동기화 또는 고급 인덱싱 기능과 같은 특정 사용자 요구에 맞게 최적화될 수 있다.
검증 및 재증명
PSE ZK-EVM을 사용하는 이더리움 클라이언트 하나와 Polygon ZK-EVM을 사용하는 다른 클라이언트 하나가 있다고 가정하자. 이 두 구현 모두 이더리움 블록 실행을 5초 이내에 증명할 수 있는 수준까지 발전했으며, 각 증명 시스템에 대해 증명을 생성하기 위해 충분한 수의 독립적인 자원봉사자가 하드웨어를 운영하고 있다.
불행히도 개별 증명 시스템이 공식적으로 확정되지 않았기 때문에 프로토콜 내에서 인센티브를 받을 수 없다. 그러나 연구 및 개발에 비해 증명 실행 비용은 낮을 것으로 예상되므로, 공공재 기금 기관을 통해 증명자에게 자금을 지원하는 것이 용이할 것이다.
누군가 ZKEvmClaimNetworkTransaction을 게시했지만 PSE ZK-EVM 버전의 증명만 게시했다고 가정하자. Polygon ZK-EVM의 증명 노드가 이를 확인하고, 계산을 수행한 후 Polygon ZK-EVM의 증명을 첨부하여 해당 객체를 다시 게시한다.

이로 인해 가장 빠른 정직한 노드가 블록을 수락하고 가장 느린 정직한 노드가 동일한 블록을 수락하는 사이의 총 최대 지연 시간이 δ에서 2δ+Tprove(여기서 Tprove<5s라고 가정)로 증가한다.
그러나 좋은 소식은 단일 슬롯 최종성(SSF)을 채택한다면 이 추가 지연 시간을 SSF의 고유한 다중 라운드 컨센서스 지연과 거의 확실히 '파이프라인' 처리할 수 있다는 것이다. 예를 들어 이 4단계 제안에서 '헤드 투표(head vote)' 단계는 기본 블록의 유효성만 검사할 수 있지만, '냉각 및 확정(freeze and finalize)' 단계는 증명이 존재해야 한다.
확장: "거의 EVM(almost-EVMs)" 지원
ZK-EVM 기능의 바람직한 목표는 추가 기능을 갖춘 EVM인 '거의 EVM(almost-EVMs)'을 지원하는 것이다. 여기에는 새로운 사전 컴파일, 새로운 오퍼코드, EVM 또는 완전히 다른 VM(예: Arbitrum Stylus)에서 코드를 작성할 수 있는 컨트랙트, 심지어 동기화된 교차 통신을 갖춘 여러 병렬 EVM을 포함할 수 있다.
일부 수정은 간단한 방식으로 지원될 수 있다: ZKEVMClaimTransaction이 수정된 EVM 규칙의 전체 설명을 전달할 수 있도록 언어를 정의할 수 있다. 이는 다음의 경우에 사용할 수 있다:
-
사용자 정의 가스 비용표(사용자는 가스 비용을 줄일 수 없지만 늘릴 수 있음)
-
특정 오퍼코드 비활성화
-
블록 번호 설정(이는 하드포크에 따라 다른 규칙을 의미함)
-
플래그 설정하여 L2 사용을 위해 표준화되었지만 L1 사용에는 적용되지 않는 일련의 EVM 변경 사항이나 기타 더 간단한 변경 사항 활성화
새로운 사전 컴파일(또는 오퍼코드)을 도입하여 사용자가 더욱 개방적인 방식으로 새 기능을 추가할 수 있도록 하기 위해, ZKEVMClaimNetworkTransaction의 blob 부분에 사전 컴파일 입력/출력 기록을 포함하는 방식을 추가할 수 있다:
class PrecompileInputOutputTranscript(Container):
used_precompile_addresses: List[Address]
inputs_commitments: List[VersionedHash]
outputs: List[Bytes]
EVM 실행은 다음과 같이 수정된다. inputs라는 배열이 빈 상태로 초기화된다. used_precompile_addresses에 있는 주소가 호출될 때마다 inputs에 InputsRecord(callee_address, Gas, input_calldata) 객체를 추가하고, 호출의 RETURNDATA를 outputs[i]로 설정한다. 마지막으로 used_precompile_addresses가 총 len(outputs)번 호출되었는지, 그리고 inputs_commitments가 inputs의 SSZ 직렬화 결과에 대한 blob의 커밋과 일치하는지 확인한다. inputs_commitments를 노출하는 목적은 외부 SNARK가 inputs와 outputs 사이의 관계를 증명할 수 있도록 하기 위해서이다.
inputs와 outputs 사이의 비대칭성에 주목하라. inputs는 해시로 저장되고, outputs는 반드시 제공되어야 하는 바이트로 저장된다. 이는 입력만을 보고 EVM을 이해하는 클라이언트에 의해 실행되어야 하기 때문이다. EVM 실행은 이미 입력을 생성했으므로, 생성된 입력이 선언된 입력과 일치하는지 확인하기만 하면 되며, 이는 해시 검사만 필요하다. 그러나 outputs는 완전히 제공되어야 하므로 데이터 가용성이 보장되어야 한다.
또 다른 유용한 기능은 임의의 송신자 계정에서 호출할 수 있는 '특권 트랜잭션(privileged transaction)'을 허용하는 것이다. 이러한 트랜잭션은 두 트랜잭션 사이에 실행되거나, 다른(아마도 특권) 트랜잭션 내에서 동시에 사전 컴파일을 호출할 수 있다. 이는 비 EVM 메커니즘이 EVM으로 다시 호출하는 것을 허용하는 데 사용할 수 있다.
이 설계는 새로운 또는 수정된 사전 컴파일뿐 아니라 새로운 또는 수정된 오퍼코드를 지원하도록 수정될 수 있다. 사전 컴파일만으로도 이 설계는 매우 강력하다. 예를 들어:
used_precompile_addresses를 상태 내 계정 객체에 특정 플래그가 설정된 일련의 일반 계정 주소 목록으로 설정하고, 그 올바른 구성에 대한 증명을 생성하는 SNARK를 만들어 Arbitrum Stylus처럼 컨트랙트가 EVM 또는 WASM(또는 다른 VM)에서 코드를 작성할 수 있도록 지원할 수 있다. 특권 트랜잭션은 WASM 계정이 EVM으로 다시 호출할 수 있도록 허용할 수 있다.
여러 EVM 실행의 입력/출력 기록과 특권 트랜잭션이 올바른 방식으로 일치하는지 보장하는 외부 검사를 추가함으로써 동기화된 채널을 통해 서로 통신하는 여러 EVM의 병렬 시스템을 증명할 수 있다.
타입 4 ZK-EVM은 두 가지 구현을 갖는 방식으로 작동할 수 있다: 하나는 Solidity 또는 다른 고수준 언어를 직접 SNARK 친화적인 VM으로 변환하는 구현, 다른 하나는 EVM 코드로 컴파일하여 규정된 ZK-EVM에서 실행하는 구현. 후자는(불가피하게 느리지만) 오류가 있다고 주장하는 오류 증명자가 트랜잭션을 보내고, 두 구현이 처리하는 트랜잭션이 다름을 입증할 수 있을 경우 보상을 받을 수 있을 때만 실행된다.
모든 호출이 0을 반환하도록 하고 호출을 블록 끝에 추가된 특권 트랜잭션에 매핑함으로써 순수 비동기 VM을 구현할 수 있다.
확장: 상태 증명자(state provers) 지원
위 설계의 도전 과제는 그것이 완전히 무상태(stateless)라는 점이며, 이는 데이터 효율성 측면에서 좋지 않다. 이상적인 데이터 압축을 사용하면 무상태 압축만 사용하는 것에 비해 상태 압축은 ERC20 전송에서 공간 활용도를 최대 3배까지 더 효율적으로 만들 수 있다.

게다가, 상태 기반 EVM은 witness 데이터를 제공할 필요가 없다.두 경우 모두 원칙은 동일하다: 우리가 이미 데이터가 가용하다는 것을 알고 있을 때—즉, 이전 EVM 실행에 의해 입력되거나 생성된 데이터일 때—데이터 가용성을 요구하는 것은 낭비이다.
ZK-EVM 기능을 상태 기반으로 만들고자 한다면 두 가지 선택지가 있다:
σpre가 비어 있거나, 데이터 가용한 미리 선언된 키와 값 목록이거나, 이전 실행의 σpost 중 하나여야 한다.
블록에 의해 생성된 영수증 R에 blob 커밋을 (σpre, σpost, Proof) 튜플에 추가한다. ZKEVMClaimTransaction 내에서 이전에 생성되거나 사용된 blob 커밋을 참조하고 실행 중에 접근할 수 있으며, 블록, witness, 영수증 또는 일반 EIP-4844 blob 트랜잭션을 나타내는 커밋을 포함할 수 있다(일정한 시간 제한이 있을 수 있으며, 일련의 명령어를 통해 참조 가능: "j 위치의 블록 + witness 데이터에서 i번째 커밋의 N...N+k-1 바이트를 삽입").
(1) 기본적으로 무상태 EVM 검증을 확립하는 대신 EVM 서브체인을 확립한다는 의미이다.
(2) 이전에 사용되거나 생성된 blob을 사전으로 사용하는 최소한의 내장형 상태 기반 압축 알고리즘을 본질적으로 생성하는 것이다. 두 경우 모두 증명자 노드에 더 많은 정보를 저장해야 하는 부담을 주지만, 증명자 노드에만 부담을 준다.
경우 (2)에서는 이러한 부담에 시간 제한을 두기 더 쉬우며, 경우 (1)에서는 더 어렵다.
닫힌 다중 증명자 시스템과 오프체인 데이터에 대한 주장
M-of-N 구조에서 고정된 수의 증명 시스템을 갖는 닫힌 다중 증명자 시스템은 위에서 언급한 많은 복잡성을 피할 수 있다. 특히, 닫힌 다중 증명자 시스템은 체인 상에 데이터가 존재하는지 보장할 필요가 없다. 또한 닫힌 다중 증명자 시스템은 ZK-EVM이 오프체인 실행을 증명할 수 있게 하며, 이를 통해 EVM 플라즈마 솔루션과 호환 가능하게 만든다.
그러나 닫힌 다중 증명자 시스템은 거버넌스 복잡성을 증가시키고 감사 가능성을 약화시킨다. 이는 이러한 장점들과 상충되는 높은 비용이다.
내장형 ZK-EVM을 프로토콜 기능으로 도입하면 L2 프로젝트의 지속적인 역할은 무엇인가?
현재 L2 팀이 자체적으로 구현하는 EVM 검증 기능은 프로토콜이 처리하게 되지만, L2 프로젝트는 여전히 많은 중요한 기능을 담당하게 된다:
-
빠른 사전 확인: 단일 슬롯 최종성은 L1 슬롯을 느리게 만들 수 있으며, L2는 이미 자체 보안을 통해 사전 확인을 지원하는 서비스를 제공함으로써 사용자에게 한 슬롯보다 훨씬 낮은 지연 시간을 제공하고 있다. 이 서비스는 계속해서 완전히 L2가 책임진다.
-
MEV 완화 전략: 이는 암호화된 메모리풀, 평판 기반 순서 선택 등의 기능을 포함할 수 있으며, L1은 이를 시행하기를 꺼린다.
-
EVM 확장: 레이어 2 프로젝트는 EVM에 중요한 확장을 도입하여 사용자에게 상당한 가치를 제공할 수 있다. 여기에는 "거의 -EVMs"와 완전히 다른 접근 방식, 예를 들어 Arbitrum Stylus의 WASM 지원과 SNARK 친화적인 Cairo 언어가 포함된다.
-
사용자 및 개발자를 위한 편의성: 레이어 2 팀은 자신의 생태계로 사용자와 프로젝트를 유치하고 환영받는 느낌을 주기 위해 많은 노력을 기울인다. 그들은 네트워크 내에서 MEV와 혼잡료를 포획함으로써 보상을 받는다. 이러한 관계는 계속 유지될 것이다.
TechFlow 공식 커뮤니티에 오신 것을 환영합니다
Telegram 구독 그룹:https://t.me/TechFlowDaily
트위터 공식 계정:https://x.com/TechFlowPost
트위터 영어 계정:https://x.com/BlockFlow_News










