About zk-EVM
zk-EVM의 목표는 트랜잭션 실행의 유효성을 증명하는 암호학적 증명을 생성하는 것입니다. 여기서 말하는 암호학적 증명은 영지식 증명입니다. 즉, 초기 world state S, 트랜잭션 T, 결과 world state S’이 주어졌을 때, zk-EVM은 f(S,T) = S’를 증명하는 영지식 증명(ZKP)를 생성해야 합니다. 여기서 f는 Ethereum yellow paper에 명시된 상태 변환 함수입니다.
많은 zk-EVM 프로젝트(Scroll, Polygon, Kakarot, Tokamak, etc)들이 있지만, 모든 프로젝트의 핵심 목표는 동일합니다. ZKP 기술을 사용하여 Ethereum과 유사한 트랜잭션 실행에 대한 암호화 증명을 만드는 것입니다. 이 설명은 Scroll blog, Vitalik’s blog를 참고한 것입니다. (더 자세하게 알고 싶다면 블로그 링크를 참고해 주세요.)
하지만 명칭에서도 알 수 있듯이, zk-EVM은 “EVM의 올바른 실행을 증명하는 시스템”으로 소개되는 경우가 많습니다. 앞선 소개와 다른 점을 찾을 수 있나요?
단순히 계정(구체적으로 EOA)간의 Ether를 전송하는 트랜잭션을 생각해 보겠습니다. 해당 트랜잭션은 sender의 Ether 잔고가 차감되고, receiver의 잔고가 증가하는 상태변환을 일으킵니다. 하지만 이것이 EVM이 수행한 일일까요? 아래에서 천천히 알아보겠습니다.
EVM: Ethereum Virtual Machine
EVM은 Ethereum Virtual Machine의 약자로 스마트 컨트랙트라고 불리는 이더리움 프로그램을 실행하는 이더리움의 실행 엔진입니다. EVM은 스택 기반 가상 머신 형태로 고유한 명령어 집합(opcodes)을 가지고 있고, 스마트 컨트랙트를 EVM이 이해할 수 있는 일련의 명령어 형태(Bytecode)로 입력받아 동작합니다. 즉, Bytecode 입력이 없다면 EVM은 동작하지 않습니다. 그렇지만, world state는 트랜잭션을 통해서 변경된다고 하였는데 위의 그림에서 EVM에 world state가 포함된 것 아닌가요? 이 질문에 대해서는 world state를 정확히 이해해야 할 필요가 있습니다.
World state
World state는 이더리움 내에 모든 계정 정보를 영구적으로 저장하고 있는 마치 이더리움의 뇌와 같습니다. 각 계정마다 계정 상태가 존재합니다. 더 자세하게는 우리가 비밀키를 통해 사용하는 이더리움 계정(EOA: Externally Owned Account)뿐만 아니라, 이더리움 네트워크에 배포된 스마트 컨트랙트 또한 계정(CA: Contract Account)입니다. 이 둘의 계정 상태에는 명확한 차이가 있습니다. EOA에는 이중지불을 방지하기 위한 nonce와 이더리움 잔액을 나타내는 balance에만 유효한 값이 존재합니다. CA에는 그 둘과 “스마트 컨트랙트 내 영구 저장소 storage”와 “변경될 수 없는 실제 스마트 컨트랙트의 bytecode표현인 code”가 추가로 존재합니다. (‘hash’의 의미는 긴 코드나, 많은 데이터를 요약해서 표현하기 위해 사용하는 암호화 방법이지만 직관적인 설명을 위해 생략하겠습니다.)
앞선 EVM 그림에서 말하는 world state는 CA의 account storage입니다. Storage는 스마트 컨트랙트의 실행을 담당하는 EVM을 통해서만 변경이 가능하지만, EOA의 balance는 조금 더 유연합니다.
다시 질문으로 돌아가 답을 하자면, EOA 계정 간의 Ether를 전송하는 트랜잭션은 스마트 컨트랙트 생성도 아니며 호출도 아닙니다. 이 말은 곧 수행할 bytecode가 없다는 말을 의미하고 EVM은 개입되지 않습니다.
EVM ⊂ Execution client
많은 사람들이 Ethereum의 execution client와 EVM을 동일하게 생각하는 경우가 많습니다. 하지만 EVM은 Execution client에서 코드 수행을 담당하고 있는 “하위집합”일 뿐입니다. Execution client에 대해 익숙하지 않은 사람들을 위해 이더리움 구조를 조금 더 설명해 보겠습니다.
위 그림과 같이 이더리움 네트워크는 각 로컬 노드가 분산된 형태로 이루어져 있습니다. 각 노드는 두 가지 클라이언트로 구성되어 있고, 이들 간의 통신을 통해 동작합니다:
- Execution client: 네트워크에서 전파된 트랜잭션을 처리하고 검증하며 상태 관리를 담당합니다. (e.g. Geth, Reth)
- Consensus client: 합의 프로세스를 통해 실제 이더리움 네트워크와 동기화 상태를 유지합니다. (e.g. Prysm, Lighthouse)
2022년 한 해 이더리움에서 가장 큰 변화를 맞이했던 “The Merge”이전에는 이더리움 노드가 단일 클라이언트로 실행과 합의 역할을 모두 수행했습니다. The Merge 이후에는 이 역할들이 완벽하게 분리되었습니다. Conensus client가 지분 증명(PoS) 합의 알고리즘을 통해 네트워크 합의를 담당하고 있으며, 트랜잭션 실행에 관련된 모든 역할은 Execution client에게 있습니다.
실제 모든 트랜잭션은 Execution client가 처리하고 검증하며, 코드 실행이 필요한 경우 Execution client가 내부에서 EVM을 동작시킵니다. 즉, zk-EVM이 트랜잭션 실행의 유효성을 증명하는 목표를 가지고 있는 한, EVM이 하는 일보다 더 많은 일을 해야 합니다. 이는 단순히 스마트 컨트랙트 코드 실행을 넘어, 전체 트랜잭션 처리 과정의 정확성을 보장해야 함을 의미합니다.
Real world zk-EVM
이제 이 글의 제목에 대해 답변할 차례입니다. zk-EVM은 단지 EVM의 올바른 실행을 증명하는 것일까요? 그렇지 않습니다. 현재 통용되어 쓰이는 명칭인 zk-EVM은 zk-Execution client에 더 가깝습니다. zk-EVM 프로젝트들은 Execution client의 기능을 에뮬레이션하며 단순한 이더 전송을 포함한 모든 트랜잭션의 유효성을 증명하는 것을 목표로 합니다. 실제 Scroll zk-EVM, Polygon zk-EVM의 프로세스를 통해 더 명확히 하는 시간을 가져보겠습니다.
Scroll zk-EVM
Scroll zk-EVM은 geth 기반의 execution client를 사용하여 트랜잭션을 실행하고, 이를 바탕으로 증명을 생성하는 방식을 채택하고 있습니다. 앞서 말했듯이 단순한 이더 전송은 EVM 명령어를 실행하는 것이 아니기 때문에 execution client가 제공하는 EVM 실행 추적에서 아무런 단계도 발견할 수 없습니다. Scroll의 zk-EVM은 스마트 컨트랙트 실행과 별개로 이러한 트랜잭션들도 증명하기 위해 begin_tx, end_tx라는 가상의 단계를 추가해서 해당 동작을 수행합니다. 즉, Scroll zk-EVM은 EVM bytecode 수행뿐만 아니라 가상의 단계 또한 증명하므로 모든 트랜잭션의 올바른 실행을 증명할 수 있습니다.
Polygon zk-EVM
Polygon zk-EVM은 zkASM(Zero-Knowledge Assembly)이라는 새로운 어셈블리 언어를 사용합니다. zkASM을 통해 작성된 프로그램(ROM이라고 불림)이 execution client의 동작을 모방하여 트랜잭션에 대해 더 상세한 execution trace를 생성할 수 있게 합니다. 이 execution trace에는 기본적인 EVM 실행 추적과 계정의 nonce 증가 및 balance 변경의 내용도 모두 포함하고 있기에, 단순한 이더 전송을 비롯한 모든 트랜잭션의 실행을 증명할 수 있습니다(관련내용). 하지만 해당 excution trace는 EVM bytecode형태가 아닌 zkASM의 명령어 형태로, EVM 명령어들이 zkASM 명령어 형태로 구현되어 있습니다. 이는 증명 생성을 더 효율적으로 하기 위해 Polygon zk-EVM이 선택한 방식입니다.
이 글에서는 두 프로젝트만 살펴보았지만, 이외에도 더 많은 zk-EVM이 있으며 어떤 영지식 증명 시스템을 사용하느냐(e.g. Scroll — halo2, Polygon — plonky2), 어떤 방식으로 “증명 생성의 효율성”과 “이더리움과 동등성”을 가져갈 것이냐에 따라 다양한 접근방식이 있습니다. 이와 같은 내용이 흥미롭다면 더 많은 zk-EVM 프로젝트들을 언급한 Vitalik의 블로그글을 읽는 것이 궁금증을 해소하는데 도움이 될 것입니다.
다양한 접근방식으로 인해, 어떤 방식이 절대적으로 더 좋은 것인지 객관적인 비교가 힘들뿐더러 알 수 없습니다. 다만 모든 zk-EVM들은 공통된 목적으로 Ethereum 확장성을 위해 연구되고 있다는 핵심 가치는 동일합니다.
결론
이 글에서는 zk-EVM이 단지 EVM의 올바른 실행을 증명하는 것인지에 대한 질문을 다루었습니다. 결론적으로, zk-EVM의 목표는 단순히 EVM의 실행을 증명하는 것을 넘어, 전체 트랜잭션 처리 과정의 정확성을 보장하는 것입니다. 이는 EVM이 스마트 컨트랙트 코드를 실행하는 것 외에도, Ethereum Execution client가 담당하는 모든 트랜잭션 처리 과정의 유효성을 영지식 증명을 통해 보장해야 한다는 것을 의미합니다. Scroll과 Polygon의 접근 방식에서 보듯이, zk-EVM은 모든 트랜잭션의 실행을 증명하기 위해 EVM 실행 뿐만 아니라 내부적인 로직 추가로 전체 트랜잭션 처리 과정을 포괄하고 있습니다. 이 글을 통해 zk-EVM을 이해하는데 조금은 도움이 되었기를 바랍니다.
참고자료
- https://docs.scroll.io/en/technology/zkevm/zkevm-overview/
- https://github.com/scroll-tech/zkevm-circuits/blob/develop/zkevm-circuits/src/evm_circuit.rs
- https://www.youtube.com/watch?v=01U8O2I3quI&list=PLTRy4klU2Ahkm0oIsm5XFEktzr6aM2cZw&index=30
- https://hackmd.io/@dieGzUCgSGmRZFQ7SDxXCA/SJgnAL7qo
- https://docs.polygon.technology/zkEVM/architecture/zkprover/