EIP-158 빈 계정 상태 정리 (State clearing)

최종 확정 · EVM·실행 · 원문 상태 Final · 2016-10-16 작성

잔액, 논스, 코드가 모두 비어 있는 '빈 계정'을 이더리움 상태에서 지우고 앞으로 새로 생기지 않게 막는 변경입니다. 모든 노드가 저장해야 하는 상태 크기가 크게 줄어듭니다.

왜 필요한가

이더리움 초기 프로토콜에는 아주 적은 비용으로 '빈 계정'을 상태에 넣을 수 있는 결함이 있었습니다. 빈 계정은 잔액이 0이고 거래 횟수(논스, nonce)도 0이며 코드와 저장소가 모두 비어 있어 아무 쓸모가 없지만 한번 만들어지면 모든 노드가 계속 저장해야 했습니다. 그 결과 상태(state) 크기가 크게 불어나 풀 노드의 하드디스크 부담이 커지고 새 노드가 네트워크를 따라잡는 빠른 동기화(fast sync) 시간도 길어졌습니다. 이 제안은 이런 빈 계정을 상태에서 지우고 새로 생기지 않게 막아 상태 크기를 줄입니다. 또 빈 계정이 모두 사라지면 '계정이 비어 있다'와 '계정이 존재하지 않는다'를 구분할 필요가 없어져 프로토콜이 장기적으로 단순해집니다.

무엇이 바뀌나

지금

EIP-158 이후

누구에게 영향이 있나

심층 설명

빈 계정의 정의와 두 가지 삭제 규칙

block.number >= FORK_BLKNUM(원문 기준 TBA)인 모든 블록에 적용됩니다. 첫째, 어떤 계정에 상태 변경이 일어났고 그 결과가 nonce = 0, balance = 0, 코드 없음, 저장소 비어 있음인 '빈 계정(empty account)'으로 저장될 상황이면, 저장하는 대신 그 계정을 삭제합니다. 둘째, 어떤 주소가 '터치(touch)'되었고 그 주소에 빈 계정이 있으면 삭제합니다. 터치는 '해당 주소에 계정이 존재하지 않았다면 계정이 생성되었을 모든 상황'으로 정의됩니다.

터치가 일어나는 여섯 가지 경우

원문이 열거하는 터치 사례는 0 이더를 보내는 CALL, CREATE(최종 저장되는 코드가 비어 있고 저장 시점에 계정에 이더가 남아 있지 않은 경우), 0 이더를 보내는 SUICIDE, 트랜잭션 수신자, 컨트랙트 생성 트랜잭션으로 만들어진 컨트랙트, 그리고 트랜잭션 수수료를 받는 마이너입니다. 마이너의 경우 gasprice가 0이고 블록·엉클·조카 보상은 모든 트랜잭션을 처리한 뒤에야 받기 때문에 계정이 아직 존재하지 않을 수 있다는 점을 원문이 따로 짚습니다.

비어 있음과 비존재의 동치, 25000 가스 폐지

EVM이 계정 존재 여부를 검사할 때마다 비어 있음(emptiness)을 비존재(nonexistence)와 동등하게 취급합니다. 이 변경이 켜지면 EVM 실행 관점에서 비어 있음과 비존재 사이에 더 이상 의미 있는 차이가 없습니다. 또 0 이더 호출(zero-value call)과 0 이더 SUICIDE는 어떤 경우에도 계정 생성 가스 비용 25000을 소비하지 않습니다.

Specification (1b): 저장소는 비어 있음 판정에서 제외

25000 가스 적용 여부를 판단하는 비어 있음 검사는 is_empty(acct): return get_balance(acct) == 0 and get_code(acct) == "" and get_nonce(acct) == 0 으로 정의하며 저장소의 비어 있음은 보지 않습니다. 캐시를 올바른 방식으로 열거 가능하게 만드는 추가 복잡성이 필요 없어 클라이언트 구현이 단순해집니다. balance·code·nonce는 비어 있는데 저장소만 남아 있어 25000 가스를 더 내게 되는 경우는 병적인(pathological) 사례로 실사용 가치가 없다고 원문은 설명합니다.

Specification (1c): 블록마다 1000개씩 지우는 대안

위 2항(터치 시 삭제)을 구현하지 않는 대안입니다. 새 빈 계정이 생기는 것은 막되, 기존 빈 계정은 상태가 실제로 변경되지 않는 한 자동으로 파괴하지 않습니다. 대신 블록 N부터 시작해 null 계정이 하나도 남지 않을 때까지, 각 블록에서 sha3(address) 순서로 가장 왼쪽에 있는 null 계정 1000개를 골라 삭제합니다. 해시 순서로 정렬하는 것은 트리를 순회하면서 계정을 쉽게 찾을 수 있게 하기 위해 필요합니다.

효과와 일시적 부작용

이 변경은 초기 프로토콜 결함 때문에 매우 낮은 비용으로 상태에 들어간 대량의 빈 계정을 제거해 상태 크기를 크게 줄이고 풀 클라이언트의 하드디스크 부담과 빠른 동기화 시간을 함께 줄입니다. 빈 객체가 모두 정리되면 비어 있음과 비존재의 구분이 사라져 프로토콜도 장기적으로 단순해집니다. 다만 일시적으로 기존 보장이 깨집니다. 이미 존재하는 빈 계정에 0 이더 호출을 반복하면 통상 최소 5000 가스가 아니라 계정당 700 가스(SUICIDE 환불을 쓰면 350 가스)로 상태 변경을 일으킬 수 있습니다. 블록당 상태 쓰기가 많아지면 블록 처리 시간이 늘고 단기적으로 엉클 비율이 높아지지만 빈 계정이 모두 정리되면 이 문제는 사라집니다.

EIP 원문 · ← EIPs