EIP-2681 계정 논스 상한을 2^64-1로 제한 (Limit account nonce to 2^64-1)
최종 확정 · EVM·실행 · 원문 상태 Final · 2020-04-25 작성
계정 논스가 가질 수 있는 값을 0부터 2^64-1까지로 제한합니다. 논스가 한도에 닿으면 거래가 무효가 되고 CREATE·CREATE2 명령어는 0을 반환하며 끝납니다.
왜 필요한가
이더리움 계정에는 논스(nonce)라는 거래 순번이 붙습니다. 지금 규격에서는 이 숫자의 길이에 제한이 없어서 이론상 얼마든지 커질 수 있습니다. 그런데 길이가 정해지지 않은 숫자는 다루기 번거롭습니다. 계정 상태가 맞다는 것을 증명하는 데이터인 상태 증인(state witness)에 논스를 담을 때 최적의 표현이 어렵고, 노드 소프트웨어인 클라이언트도 논스를 256비트 숫자로 넉넉하게 들고 있어야 합니다. 이 EIP는 논스의 상한을 2^64-1로 정합니다. 그러면 증명 데이터가 논스를 더 효율적으로 표현할 수 있고, 클라이언트는 논스를 64비트로 저장하는 작은 최적화를 얻습니다. 원문은 거래 형식 개선을 노리는 다른 제안 최소 세 개에도 도움이 될 수 있다고 적습니다.
무엇이 바뀌나
지금
- 논스는 길이 제한이 없는 정수여서 규격상 한없이 커질 수 있습니다
- 상태 증인이 임의 길이의 논스를 담아야 해서 최적화가 어렵습니다
- 규격대로라면 클라이언트는 논스를 256비트 숫자로 다뤄야 합니다
EIP-2681 이후
- 논스가 0부터 2^64-1 사이로 제한되고 이 규칙은 제네시스부터 소급 적용됩니다
- 상태 증인이 논스를 더 최적화된 방식으로 표현할 수 있습니다
- 클라이언트가 논스를 64비트 숫자로 저장할 수 있습니다
누구에게 영향이 있나
- 사용자: 체감 변화가 없습니다. 원문 기준(2020년 11월) 가장 높은 계정 논스가 약 2,900만으로 한도에 한참 못 미칩니다.
- 클라이언트 팀: go-ethereum처럼 이미 논스를 64비트로 다루던 구현이 많아 규격이 실제 구현과 일치하게 됩니다.
- 컨트랙트·앱 개발자: 논스가 한도에 닿은 계정에서는 CREATE·CREATE2가 스택에 0을 올리며 끝난다는 규칙이 추가됩니다.
심층 설명
거래 유효성 규칙: 2^64-1 이상이면 무효
이 EIP는 제네시스 블록부터 소급 적용되는 제한 두 가지를 도입합니다. 첫째는 거래 유효성 규칙으로, 논스가 2^64-1과 같거나 그보다 큰 거래는 무효로 간주합니다. 상한값인 2^64-1 자체를 무효로 두는 이유도 원문에 있습니다. 그 거래가 블록에 포함되면 보낸 계정의 논스가 2^64-1을 넘어서기 때문입니다. 따라서 계정 논스가 실제로 가질 수 있는 값은 0부터 2^64-1까지이고, 논스가 상한에 닿은 계정은 거래를 더 보낼 수 없습니다.
CREATE·CREATE2는 0을 반환하며 끝남
둘째 제한은 EVM의 컨트랙트 생성 명령어에 걸립니다. 계정 논스가 2^64-1인 상태에서 CREATE 또는 CREATE2 명령어를 실행하면, 실행이 스택에 결과값 0을 올리며 끝납니다. 이때 initcode(새 컨트랙트를 만들 때 실행하는 초기화 코드)의 실행 가스는 차감하지 않습니다. 즉 상한에 닿은 계정에서는 새 컨트랙트 생성이 진행되지 않고 호출한 쪽은 스택에 올라온 0으로 생성이 이뤄지지 않았음을 알 수 있습니다.
한도에 도달하는 비용
원문은 어떤 계정의 논스가 제안된 한도에 닿거나 넘을 가능성이 낮다고 봅니다. 외부 거래로 그 한도에 도달하려면 최소 21000 * (2^64-1) = 387_381_625_547_900_583_915_000 가스가 들기 때문입니다. 거래 한 건에 최소 21000 가스가 들고 거래마다 논스가 1씩 오르므로, 이를 2^64-1번 반복하는 비용을 계산한 것입니다. 또 원문은 대부분의 클라이언트가 이미 논스 필드를 64비트로 간주한다고 적습니다. go-ethereum이 그 예입니다.
Morden 테스트넷과 EIP-155
과거 Morden 테스트넷에서는 새 계정의 시작 논스를 2^20으로 두어 메인넷 거래와 테스트넷 거래를 구분했습니다. 같은 거래가 두 네트워크에서 다시 처리되는 것을 논스로 막은 방식입니다. 원문은 EIP-155가 체인 식별자(chain identifier)를 쓰는 더 우아한 방법을 도입한 뒤로 이런 방식은 더 이상 쓰이지 않는다고 적습니다. 논스에 거래 순번 이외의 의미를 얹던 용례가 사라졌다는 점을 짚은 것입니다.
하위 호환성과 현재 상태
규격상으로는 소급 적용되는 파괴적 변경(breaking change)이지만 실제로 보이는 효과는 없을 것이라고 원문은 설명합니다. 2020년 11월 기준으로 상태에 논스가 한도를 넘는 계정이 없고 가장 높은 논스는 0xea674fdde714fd979de3edf0f56aa9716b898ec8 계정의 약 2,900만 수준입니다. go-ethereum은 state.Account.Nonce와 types.txdata.AccountNonce를 64비트 숫자로 두어 이 제한을 이미 부분적으로 적용하고 있습니다. 원문은 보안 고려사항이 없다고 적으며 이 EIP의 상태는 Final로 명세가 확정됐습니다.