이더리움 가상 머신

Bora Lee
8 min readSep 27, 2023

이더리움 노드를 구성하는 이더리움 가상 머신에 대해 알아보는 글입니다.

이더리움 네트워크는 단일하고 연속적이며 누군가에 의해 차단이나 방해받지 않고 불변성을 유지하는 상태 기계(state machine)인 이더리움 블록체인을 유지하기 위해 존재합니다.

모든 이더리움 계정과 스마트 컨트랙트, 데이터는 이더리움 블록체인이라는 환경에 존재합니다. 현존하는 이더리움 블록체인 노드 수는 수십만 개인데, 이더리움 블록체인은 상태 기계라는 특성상 블록 번호가 같으면 노드 역시 동일한 상태를 유지합니다. 이더리움 가상 머신(Ethereum Virtual Machine, EVM)은 블록이 추가될 때 어떻게 상태를 바꿀지 계산하는 규칙을 정의합니다.

사전지식

EVM을 잘 이해하려면 디지털 정보의 한 단위인 바이트와 이를 담는 공간인 메모리, 자료구조의 한 종류인 스택을 알아야 합니다. 여기에 더하여 암호학 기초인 해시 함수에 대해서도 알아두면 좋습니다.

상태 기계

비트코인 등의 블록체인은 중개자 없이 탈 중앙화된 통화(암호 화폐)가 존재할 수 있도록 하는 ‘분산 원장’으로 설명되기도 합니다.

비트코인 네트워크에선 계정에 있는 BTC보다 많은 BTC를 사용하거나 보낼 수 없습니다. 이처럼 블록체인엔 악의적인 원장 수정을 막고, 정상 거래를 처리하는 규칙이 정해져 있어서 블록체인을 기반으로 한 암호 화폐는 ‘일반’ 통화처럼 작동할 수 있습니다.

이더리움에도 자체 암호화폐인 ETH가 있고, ETH의 거래를 보장하고 기록한다는 측면에서 이더리움 네트워크를 분산 원장이라고 설명하기도 합니다. 하지만 이더리움엔 비트코인 네트워크엔 없는 기능인 ‘스마트 컨트랙트’가 있기 때문에 이더리움 네트워크를 단순한 분산 원장으로 설명하기엔 부족합니다. 더 강력한 비유가 필요합니다.

이더리움은 분산 원장이 아닌 ‘분산 상태 기계(distributed state machine)’로 더 잘 설명할 수 있습니다.

상태 기계는 입력값에 따라 동적으로 상태를 변경하는 모든 기계를 의미합니다. 대표적인 상태 기계론 동전을 넣거나 카드를 터치하여 통과하는 지하철 개찰구가 있습니다.

개찰구엔 ‘닫힘(locked)’과 ‘열림(un-locked)’ 두 가지 상태가 존재합니다. 개찰구가 닫힌 상태에선 개찰구를 밀어도 그 상태는 닫힘으로 유지됩니다. 하지만 동전을 넣거나 카드를 대는 등, 비용을 지불하면 개찰구의 상태는 닫힘에서 열림으로 바뀝니다. 열려있는 상태에선 동전을 넣거나 카드를 대더라도 여전히 개찰구는 열린 상태를 유지합니다. 하지만 열린 상태의 개찰구를 밀면 개찰구는 닫힘 상태로 돌아갑니다.

이더리움의 경우 지하철 개찰구보다 더 상태가 복잡하긴 하지만 일반적인 원칙은 같습니다. 이더리움 전체 네트워크는 모든 상태를 대규모 데이터에 저장하고, EVM에 정의된 규칙(트랜잭션의 유형에 따라 어떻게 상태를 변경할지에 대한 규칙)에 따라 이더리움 네트워크의 상태를 변경합니다.

이더리움 상태 기계

고차원 수준에서 EVM은 결정론적 유한 상태 전환 함수와 유사하게 작동합니다. 현재 상태(S)와 새로운 유효 트랜잭션 집합(T)이 주어지면 새로운 상태(S’)로 전환이 이뤄지는데, 이때 같은 입력(새로운 유효 트랜잭션 집합)엔 항상 같은 출력(변경 후 상태)이 발생합니다.

> Y(S, T) = S’

위 식에서 Y는 상태 전환 함수를 의미합니다.

EVM OPCODES

EVM은 각 항목이 256비트(32바이트) 워드로 구성되고 최대 1,024개 항목을 쌓을 수 있는 스택처럼 작동합니다.

트랜잭션을 실행하는 동안 EVM 내 임시 메모리가 유지되는데, 이 메모리는 새 트랜잭션을 실행할 때 리셋(재설정) 됩니다.

한편, 스마트 컨트랙트는 블록체인상에서 자신만의 상태를 유지합니다. 트랜잭션이 실행되는 동안에 유지되는 이 상태를 일반적으로 EVM Storage(스토리지)라 칭합니다. 정리하자면, 스토리지는 스마트 컨트랙트의 장기 메모리이고 메모리는 EVM 내의 단기 메모리라 할 수 있습니다.

EVM에는 스마트 컨트랙트의 실행을 제어하고, 데이터를 저장하고, 데이터를 검색하며, 논리 연산을 수행하고, 산술 연산을 수행하는 등의 다양한 작업을 수행하는 바이트 코드 형태의 개별 명령어인 OPCODE가 존재합니다. EVM OPCODES의 대표적인 예로는 `ADD` (두 값을 더함), `MUL` (두 값을 곱함), `PUSH` (값을 스택에 푸시), `POP` (스택의 최상단 값을 제거), `JUMP` (특정 주소로 점프) 등이 있고, 이더리움에 특화된 BALANCE(주소의 현재 ETH 잔액 조회)와 BLOCKHASH(해당 블록의 해시값 조회)라는 OPCODES도 존재합니다.

솔리디티로 작성한 스마트 컨트랙트를 컴파일하면 해당 코드는 EVM OPCODES로 컴파일됩니다. EVM이 이해할 수 없는 고수준의 솔리디티 코드는 컴파일을 거쳐 낮은 수준의 OPCODES로 변환됩니다. EVM은 이 OPCODES를 전 세계 노드에서 실행합니다.

Bytecode vs Opcodes

bytecode는 EVM에서 실행될 수 있는 이진 형식의 코드이며, 이 bytecode는 여러 개의 opcodes로 구성되어 있습니다. Opcodes는 EVM의 기본 연산을 나타내는 개별 명령어입니다.

EVM Bytecode

  • 정의: Bytecode는 Ethereum 스마트 컨트랙트를 컴파일한 후의 결과물로, EVM에서 직접 실행될 수 있는 이진 형식의 코드입니다.
  • 생성: 고수준 언어로 작성된 스마트 컨트랙트 (예: Solidity)는 컴파일러에 의해 bytecode로 변환됩니다.
  • 사용: Bytecode는 Ethereum 네트워크에 스마트 컨트랙트를 배포할 때 사용됩니다. 사용자가 스마트 컨트랙트를 호출할 때, EVM은 해당 bytecode를 실행합니다.
  • 가독성: Bytecode는 사람이 직접 읽거나 이해하기 어려운 이진 형식입니다.

EVM Opcodes

  • 정의: Opcodes는 EVM에서 인식하고 실행할 수 있는 개별 명령어 또는 연산 코드입니다.
  • 예시: `PUSH`, `ADD`, `MUL`, `JUMP`, `BALANCE` 등과 같은 명령어들이 opcodes에 해당합니다.
  • 관계: Bytecode는 이러한 opcodes의 연속적인 시퀀스로 구성됩니다. 즉, bytecode는 여러 opcodes로 이루어진 집합입니다.
  • 가독성: Opcodes는 각각의 연산을 나타내는 명확한 이름을 가지고 있어, bytecode보다는 조금 더 가독성이 있습니다. 그러나 이를 완전히 이해하기 위해서는 EVM의 작동 방식에 대한 깊은 지식이 필요합니다.

EVM 구현

모든 EVM 구현체는 이더리움 옐로 페이퍼(Yellowpaper)에 구현된 명세를 준수해야 합니다. 탄생 이후 이더리움은 여러번의 개정과 개선를 거쳤습니다. 옐로 페이퍼엔 이 모든 사항을 반영한 최신 명세가 담겨있습니다.

모든 이더리움 클라이언트(Geth, Nethermind, Erigon 등)는 노드가 트랜잭션을 실행하고 검증할 수 있도록 EVM을 반드시 구현해야 합니다. 참고로 go언어 이외에 다른 언어로 구현한 EVM 구현체(`ethereumjs-evm`, `evmone`, `py-evm`)도 존재합니다.

참고 자료

--

--