EIP-3607 코드 배포된 주소의 거래 차단 (Reject transactions from senders with deployed code)

최종 확정 · 보안·프라이버시 · 원문 상태 Final · 2021-06-10 작성

컨트랙트 코드가 이미 배포된 주소를 보내는 계정으로 쓰는 거래를 무효로 정합니다. 주소 충돌을 노린 자금 탈취 공격을 막는 규칙입니다.

왜 필요한가

이더리움 주소는 160비트로 짧은 편이라, 약 2의 80제곱 번의 연산을 하면 외부 소유 계정(EOA, 개인 키로 움직이는 일반 계정)과 컨트랙트가 같은 주소를 갖는 충돌을 만들 수 있습니다. 원문은 하드웨어와 전기료로 약 100억 달러를 들이면 1년 안에 가능하다고 추정합니다. 공격자가 이런 충돌 주소에 토큰 래퍼나 AMM처럼 안전해 보이는 컨트랙트를 배포해 사용자 자금을 모은 뒤, 같은 주소의 개인 키로 그 돈을 빼 갈 수 있습니다. 그런데 옐로페이퍼는 코드가 배포된 계정에서 거래를 보내는 경우를 명시하지 않았고 대부분의 클라이언트는 이런 거래를 허용하는 상태였습니다. 이 EIP는 그런 거래를 항상 금지하도록 규칙을 못 박아 가장 심각한 공격을 차단합니다.

무엇이 바뀌나

지금

EIP-3607 이후

누구에게 영향이 있나

심층 설명

명세: 코드해시 검사와 거부 규칙

tx.sender의 CODEHASH가 EMPTYCODEHASH와 다른 거래는 반드시(MUST) 무효로 거부합니다. EMPTYCODEHASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470이며 빈 코드의 해시 값입니다. 무효 거래는 클라이언트가 거부해 블록에 포함하지 않아야 하고 그런 거래를 포함한 블록은 무효로 간주해야 합니다. 즉 개별 거래 검증과 블록 검증 양쪽에 걸리는 합의 규칙입니다.

공격 비용 추정: 2^80 연산과 사이클 탐색

EOA 키 2^80개를 만들고 각 EOA에서 컨트랙트 배포를 시뮬레이션하면 충돌이 약 하나 나올 것으로 기대됩니다. 단순한 방식은 주소 2^80개를 저장해야 해서 2.4*10^25바이트(24요타바이트)의 메모리가 필요하지만 사이클 탐색(cycle finding) 알고리즘을 쓰면 큰 저장 공간 없이 충돌을 찾을 수 있습니다. 원문은 하드웨어와 전기에 약 100억 달러를 투자하면 1년 정도에 컨트랙트와 EOA의 충돌을 찾을 수 있다고 추정합니다. 256비트 주소로 옮기면 복잡도가 2^128이 돼 당분간 불가능해지지만 160비트 주소에서도 이 EIP로 문제를 지금 해결할 수 있다는 것이 배경입니다.

성격: 업그레이드가 아니라 미정의 동작의 명확화

컨트랙트 계정의 동작은 그 코드로 제약된다는 것, 즉 계정의 자금이 갑자기 어떤 개인 키로 쓰일 수 없다는 것은 원래부터 기대된 성질입니다. 과거에는 160비트 주소면 충돌 저항이 충분해 이런 경우가 생길 수 없다고 암묵적으로 가정했을 뿐입니다. 그래서 원문은 이 EIP를 합의 규칙의 명시적 업그레이드가 아니라, 이전에 정의되지 않았던 경우에 대한 프로토콜 동작의 명확화로 봐야 한다고 설명합니다.

남는 공격 경로 세 가지

이 EIP는 가장 심각한 경로만 막고 모든 충돌 공격을 없애지는 않습니다. 우선 배포 전 주소로 자금을 보내도록 사용자를 설득하는 공격이 남습니다. 스테이트 채널처럼 이런 동작을 요구하는 앱이 있습니다. 다음으로 컨트랙트 배포 후 체인 재구성(reorg)이 일어나 배포 거래가 사라지면 개인 키로 자금에 접근할 수 있습니다. 컨트랙트가 셀프디스트럭트하면서 안의 ERC20 등이 소각된다고 알렸더라도, 그 주소의 키로 접근할 수 있습니다. 원문은 이들 시나리오가 훨씬 악용하기 어렵고 수익도 낮아 경제적으로 성립하기 어렵다고 봅니다.

참조 구현: 논스 검사 뒤의 EOA 확인

상태 전이 검사에서 보낸 계정의 논스가 올바른지 확인한 다음에 이 검사를 추가합니다. 보낸 계정은 거래 서명에서 복구한 주소입니다. 보낸 계정의 CodeHash가 EmptyCodeHash와 다르면 ErrSenderNoEOA를 반환합니다. go-ethereum에 적용하는 diff가 원문 자산으로 제공됩니다. 테스트 케이스는 제네시스에서 주소 0x71562b71999873DB5b286dF957af199Ec94617F7에 1 이더와 코드 0xB0B0FACE를 할당하고 대응하는 개인 키로 서명한 모든 거래가 거부되고 블록에 포함되지 않아야 한다고 규정합니다.

호환성: 소프트 포크 가능, RPC 예외 허용

원문은 이런 공격이 메인넷에서 이미 일어났을 가능성은 낮다고 봅니다. 일어났다면 알려졌을 것이기 때문입니다. 컨트랙트 겸 EOA를 기능으로 쓸 이유도 없습니다. 같은 효과를 컨트랙트에 메서드를 추가해 얻을 수 있는데 충돌을 찾는 데 수십억 달러를 쓸 사람은 없기 때문입니다. 다만 프라이빗 네트워크는 제네시스에 그런 계정이 있을 수 있어 점검이 필요합니다. 일부 멀티시그 컨트랙트가 eth_call이나 eth_estimateGas를 자기 주소에서 보낸 것처럼 쓰므로, 클라이언트는 이들 RPC 호출에서는 규칙을 꺼도 됩니다. 새 유효성 규칙이 기존 규칙의 엄격한 부분집합이라 소프트 포크로 구현할 수 있고 이전에 유효했던 일부 거래를 무효로 만들 뿐이어서 보안상 단점이 없는 순수한 보안 강화입니다. 이 EIP는 Final 상태로 확정됐습니다.

EIP 원문 · ← EIPs