EIP-1344 체인 ID 옵코드 (ChainID opcode)
최종 확정 · EVM·실행 · 원문 상태 Final · 2018-08-22 작성
스마트 컨트랙트가 자신이 실행 중인 네트워크의 체인 ID를 직접 읽을 수 있는 새 EVM 명령어 CHAINID를 추가합니다.
왜 필요한가
이더리움에서 서명된 트랜잭션은 EIP-155가 정한 체인 ID(chain ID)를 함께 담아 한 네트워크에서 쓴 서명을 다른 네트워크에서 다시 쓰는 리플레이 공격(replay attack)을 막습니다. 그런데 정작 스마트 컨트랙트 안에서는 지금 어느 체인에서 실행되고 있는지 알 방법이 없었습니다. 그래서 EIP-712 같은 오프체인 서명 방식은 체인 ID를 컨트랙트를 컴파일할 때 고정값으로 박아 넣어야 했습니다. 이 방식은 하드포크로 체인이 갈라지거나 사람이 값을 잘못 넣는 실수가 생기면 자금 손실이나 서명 재사용 공격이 일어날 수 있습니다. 이 EIP는 현재 체인 ID를 읽는 명령어 하나를 EVM에 추가해 컨트랙트가 실행 시점의 실제 체인 ID로 서명을 검증할 수 있게 합니다.
무엇이 바뀌나
지금
- 컨트랙트가 자신이 실행되는 체인의 ID를 알 방법이 없습니다
- EIP-712 서명 검증에 쓰는 체인 ID를 컴파일 때 고정값으로 넣어야 합니다
- 하드포크 뒤에는 고정해 둔 체인 ID가 실제 체인과 어긋날 수 있습니다
EIP-1344 이후
- CHAINID 옵코드 하나로 실행 시점의 체인 ID를 바로 읽습니다
- 서명 검증에 현재 체인 ID를 써서 다른 체인에서 재사용되는 것을 막습니다
- 체인 ID가 바뀌어도 컨트랙트를 다시 배포하지 않고 새 값을 따라갑니다
누구에게 영향이 있나
- 스마트 컨트랙트 개발자: EIP-712 서명 검증에서 체인 ID를 하드코딩하지 않고 CHAINID로 읽을 수 있습니다
- 레이어 2·메타트랜잭션 서비스: 오프체인 서명의 체인 간 재사용 방지에 체인 ID를 안전하게 쓸 수 있습니다
- 클라이언트 팀: 0x46 자리에 새 옵코드를 구현해야 합니다
- 일반 사용자: 체인이 갈라져도 서명해 둔 메시지가 다른 체인에서 재사용될 위험이 줄어듭니다
심층 설명
옵코드 명세: 0x46 CHAINID
새 옵코드 CHAINID를 0x46에 추가합니다. 스택 인자를 받지 않으며 실행하면 현재 체인 ID를 스택에 올립니다. 체인 ID는 256비트 값으로 취급합니다. 실행 비용은 G_base입니다. 컨트랙트 입장에서는 블록 번호나 호출자 주소를 읽듯이 명령어 하나로 자신이 실행 중인 네트워크의 식별자를 얻는 셈이어서 별도의 저장소 접근이나 외부 호출이 필요 없습니다.
반환값은 클라이언트의 체인 ID 설정에서 옵니다
옵코드가 돌려주는 값은 클라이언트의 체인 ID 구성에서 가져오며 이 값은 클라이언트가 들어오는 트랜잭션에서 받아들이는 EIP-155 고유 식별자와 일치해야 합니다. EIP-155에서는 트랜잭션이 반드시 EIP-155 식별자를 포함할 필요는 없지만 그런 트랜잭션 안에서 실행되더라도 이 옵코드는 기본값이 아니라 설정된 체인 ID를 그대로 돌려줍니다. 즉 결과는 개별 트랜잭션의 서명 방식과 상관없이 네트워크 설정을 따릅니다.
왜 필요한가: EIP-712의 컴파일 타임 체인 ID 문제
기존 EIP-712 접근은 체인 ID를 컴파일 시점에 지정합니다. 이 방식은 하드포크 이후 문제를 일으키고 사람의 실수로 자금 손실이나 서명 메시지 리플레이 공격이 생길 수 있습니다. 제안된 옵코드를 추가하면 컨트랙트가 현재 체인 ID에 접근해 그 값을 기준으로 서명을 검증할 수 있습니다.
분쟁성 분기 시나리오와 개발자의 책임
체인 ID가 특정 네트워크에 어떻게 정해지는지에 대한 명세는 없고 클라이언트 구현자와 커뮤니티의 수동 선택에 의존합니다. 분쟁성 분기(contentious split)가 일어나면 두 체인이 같은 체인 ID를 유지하는 것은 안전하지 않으므로, 한쪽 또는 양쪽이 값을 바꾸게 됩니다. 그래서 원문은 CHAINID 사용자가 체인 ID 값이 바뀌는 상황을 애플리케이션이 처리할 수 있게 반드시 대비해야 한다고 명시합니다. 체인 ID 변경 시점을 기록하는 무신뢰 오라클(Trustless Oracle)을 앱 내부 기능으로 구현하거나 전역 표준 컨트랙트로 참조하는 방식이 제시됩니다. 대비가 없으면 이미 서명된 오프체인 메시지의 정당성이 갑자기 사라질 수 있고 정산 기간처럼 긴 검증 구간에서 문제가 됩니다. 모든 애플리케이션에 완화책이 필요하지는 않으며 개발자가 사례별로 판단 근거를 제시해야 합니다.
왜 프리컴파일이 아니라 단순 옵코드인가: Plasma 사례
원문은 전역 오라클이 맞지 않는 예로 Plasma L2를 듭니다. Plasma에서는 운영자가 L2 트랜잭션을 요약한 블록을 베이스 체인에 제출하는데, 이 제출 시점이 체인 ID 변경 같은 메인체인의 큰 사건과 정확히 맞물리지 않을 수 있습니다. 운영자가 체인 ID 갱신 시점을 통제할 수 없으면 블록 제출과 갱신을 완벽히 동기화할 수 없고 과거 트랜잭션 일부가 갱신 시점과 어긋나 거부될 수 있습니다. 분기 상황의 동작을 프로토콜이 과하게 규정하면 이런 의도치 않은 부작용이 생기므로, 복잡한 프리컴파일이나 컨트랙트보다 단순한 접근용 옵코드가 최적이라는 것이 원문의 결론입니다. 전역이든 지역이든 체인 ID 변경 처리 방식은 개발자가 유연하게 구현하도록 남겨 둡니다.
상태와 호환성, 구현 자료
이 EIP는 상태가 Final로 이미 확정된 명세입니다. EIP-155 체인 ID 도메인 분리자를 트랜잭션 서명에 구현한 모든 체인과 완전히 하위 호환됩니다. 이 기능은 과거 EIP-901에서 일부로 제안된 적이 있습니다. 테스트 케이스는 ethereum/tests 저장소에 추가되었고 Trinity 파이썬 클라이언트용 참조 구현과 무신뢰 체인 ID 오라클 예제 구현(ChainIdOracle.vy)이 공개되어 있습니다.