이더리움은 거래에 기반을 둔 상태머신이다. 여기서 상태 머신이란 어떠한 입력을 읽고, 그 입력을 기반으로 새로운 상태로 전환하는 것을 의미한다. 이더리움의 상태 머신은 Genesis State에서 시작한다. 그리고 트랜잭션이 실행되면, 다음 상태로 전환하게 된다. 트랜잭션이 더 이상 들어오지 않은 마지막 상태가 이더리움의 현재 상태이다.
이더리움에는 수 천개의 트랜잭션이 있다. 이 트랜잭션은 블록으로 묶여 있으며, 블록은 직전에 만들어진 블록과 이어져 있다.
이더리움에는 EOA와 CA라는 두 종류의 계정이 있다. 모든 계정은 160bit 길이의 주소로 식별 되고, 동일한 주소 공간을 가진다.
EOA와 CA는 잔액(Balance), 논스(Nonce), 스토리지(Storage), 컨트랙트 코드(Contract Code)로 구성되어 있다. EOA의 주소는 상응하는 비밀 키를 가지고 있지만, CA는 비밀 키가 없다.
여기서 CA는 새로운 트랜잭션을 만들 수 없고, EOA나 다른 CA에게서 받은 트랜잭션에 대한 응답의 트랜잭션만 만들 수 있다. 따라서, 이더리움 블록체인에서 일어나는 모든 액션은 항상 EOA에서 만든 트랜잭션에서부터 시작한다.
이더리움의 전역상태는 계정 주소와 계정 상태를 매핑한 것으로 구성되어 있다. 이 매핑은 머클 패트리샤 트리형태로 저장되어 있다.
트리 맨 아래에 있는 데이터는 저장하려는 데이터를 청크(Chunk)로 분할한 다음, 각 청크를 두 개씩 모아 해시를 취하여 부모 노드를 만든다. 이렇게 하나의 루트 노드가 만들어질 때까지 동일한 과정을 반복한다. 이더리움의 블록 헤더에는 세 개의 머클트리 구조의 루트 노드의 해시값이 저장되어 있다.
부모 노드는 자식 노드의 해싱 값이기 때문에, 단방향 함수인 해시의 특성상 자식 노드의 값이 조금이라도 바뀌면 부모 노드의 값도 바뀌게 된다. 따라서 머클 패트리샤 트리에서 변조는 즉시 발견된다.
트랜잭션은 EOA에서 생성되고, 일련의 과정을 거쳐 블록체인에 올라간 암호화 서명된 명령어의 집합이다. 그 외의 트랜잭션은 메시지 호출과 컨트랙트 생성 두 종류로 나뉜다. 이더리움의 모든 트랜잭션은 항상 EOA에서 만들어지고 블록체인에 올라간다. 즉, 트랜잭션은 외부 세계를 이더리움 내부의 상태로 연결해주는 다리 역할이고, 그 연결의 창구가 바로 CA이다.
새로운 CA를 만들기 위해서는 먼저 특별한 공식을 이용해 새로운 계정의 주소를 정의해야 한다. 그리고 다음의 과정을 통해 만들어진다.
한번 계정을 초기화하고 나면, 트랜잭션에서 보낸 init코드를 사용해 새로운 CA를 생성할 수 있다. 이 init 코드가 실행되는 동안에 계약 생성자에 따라 CA의 스토지리를 업데이트 하거나, 다른 CA를 새롭게 생성하거나, 다른 메시지호출을 만들 수 있다.
계약을 초기화하는 이 init 코드를 실행할 때는 가스를 사용한다. 트랜잭션은 남아있는 가스보다 더 많은 가스를 소비할 수 없기 때문에, 만약 남아있는 가스를 다 사용한 경우 OOG(Out-of-Gas) 예외 처리와 함께 코드 실행이 종료된다. OOG로 인한 트랜잭션 종료가 발생하면 상태는 트랜잭션 실행 이전 상태로 돌아간다.
트랜잭션이 실패해도 트랜잭션 송신자는 소진된 가스를 환불받을 수 없다. 그러나, 송신자가 트랜잭션과 함께 보낸 이더값은 환불된다.
init코드가 성공적으로 실행되면, 마지막으로 CA 코드에 대한 비용이 지불된다. 이 비용은 스토리지 비용이며, 생성된 CA코드의 크기에 비례한다. 예외 없이 트랜잭션 생성이 완료된 경우, 미사용된 가스는 송신자에게 환불되고, 변경된 상태가 저장된다.
메시지 호출을 실행하는 것은 CA 생성과 비슷하지만, 몇 가지 다른 점이 있다.
새 계정이 생성되지 않기 때문에 메시지 호출 상태에는 init 코드가 포함되지 않는다. 그러나, 입력 데이터를 가지고 있을 수는 있다. 메시지 호출은 한번 실행되면 출력 데이터를 포함한 추가적인 요소들을 가지게 될 수도 있는데, 이 추 가요소들은 뒤에 이어질 다른 실행에 필요한 데이터이다.
CA생성과 마찬가지로, 메시지 호출을 실행할 때 가스가 부족하거나, 트랜잭션이 잘못되어 종료되는 경우(스택 오버플로우가 발생하거나, 잘못된 명령어를 사용할 경우) 사용된 가스는 환불되지 않으며 직전 상태로 돌아간다.
다음으로 트랜잭션이 실제로 EVM에서 어떻게 동작되는지 보고자 한다.
EVM의 구성요소는 다음과 같다.
EVM이 솔리디티 코드를 컴파일한 바이트 코드를 받으면 실행이 시작되고, 맨 처음에는 메모리와 스택은 비어있다. 프로그램 카운터(연산 실행 횟수)는 0이다.
EVM은 트랜잭션을 반복적으로 실행하며, 각 사이클에서 시스템 상태(이더리움 전역상태)와 머신 상태를 게산한다. 머신 상태는 다음과 같이 구성된다.
코드가 실행되면서 스택에 있는 요소들은 왼쪽에서부터 순서대로 추가되거나 제거되며, 남은 가스에서 적절한 양의 가스가 제거되고, 프로그램 카운터가 올라간다.
매 사이클이 끝날 때 다음과 같은 케이스가 발생할 수 있다.
머신이 정상적으로 실행을 마치면, 결과적으로 발생한 상태와 남아 있는 가스, 발생한 세부 상태, 결과값을 생성한다.