EIP-3675 합의를 지분증명으로 전환 (Upgrade consensus to Proof-of-Stake)

최종 확정 · 합의·스테이킹 · 원문 상태 Final · 2021-07-22 작성

작업증명(PoW) 채굴을 끝내고 비콘 체인이 이끄는 지분증명(PoS)으로 이더리움 메인넷의 합의 방식을 교체합니다. 이를 위한 블록 구조, 유효성 검사, 포크 초이스 규칙, 네트워크 동작의 변경을 명세합니다.

왜 필요한가

이더리움은 그동안 작업증명(Proof-of-Work), 즉 컴퓨터 연산 경쟁으로 블록을 만들고 체인을 지켜 왔습니다. 한편 지분증명(Proof-of-Stake)을 실행하는 비콘 체인(beacon chain)은 2020년 12월부터 따로 가동되어 왔고 그 기간 동안 안전성(safety)이나 활성(liveness) 문제가 한 번도 발견되지 않았습니다. 원문은 이 무사고 운영 기록을 근거로 비콘 체인이 이더리움 메인넷의 보안을 책임질 준비가 되었다고 밝힙니다. 다만 살아 움직이는 네트워크의 합의 장치를 통째로 바꾸는 일이므로, 이 EIP는 바꿔야 할 것만 최소한으로 바꿔 작업의 안전성과 적용 시점을 모두 챙기는 방향으로 설계되었습니다. 특히 블록 형식을 그대로 유지한 덕분에 대부분의 스마트 컨트랙트와 서비스는 전환 중에도, 전환 뒤에도 거의 손대지 않고 그대로 동작합니다.

무엇이 바뀌나

지금

EIP-3675 이후

누구에게 영향이 있나

심층 설명

전환 트리거: 터미널 PoW 블록과 총 난이도

터미널 PoW 블록은 자신의 total_difficulty가 TERMINAL_TOTAL_DIFFICULTY 이상이고 부모의 total_difficulty는 그 미만인 PoW 블록입니다. 메인넷 값은 58750000000000000000000입니다. 같은 부모의 자식 여러 개가 조건을 동시에 만족할 수 있어 터미널 PoW 블록은 하나가 아닐 수 있습니다. 블록 번호 대신 총 난이도를 쓰는 이유는 공격 방지입니다. 높이 조건이라면 공격자가 소수 해시파워로 높이만 맞춘 악성 포크를 만들고 그 위에 첫 PoS 블록을 제안해 전환의 보안을 흔들 수 있습니다. 또 일시적 네트워크 분단으로 소수가 다른 터미널 PoW 블록을 보더라도, FIRST_FINALIZED_BLOCK 수신 전까지는 터미널 블록 조건을 만족하는 포크 사이의 재구성(re-org)이 허용되어 복구 불가능한 분열을 막습니다.

블록 구조: PoW 필드를 상수로 고정

TRANSITION_BLOCK부터 ommersHash는 Keccak256(RLP([])) 값인 0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347, difficulty는 0, mixHash는 0x0000000000000000000000000000000000000000000000000000000000000000, nonce는 0x0000000000000000, ommers는 빈 리스트 []로 고정됩니다. extraData 길이는 MAX_EXTRA_DATA_BYTES(32바이트) 이하여야 합니다. 필드를 삭제하지 않고 상수로 바꾼 이유는 블록 형식의 하위 호환을 지키기 위해서입니다. 외부에서 받은 블록 헤더의 해시를 BLOCKHASH 결과와 맞춰 보며 트랜잭션·영수증·상태의 머클 증명을 검증하는 컨트랙트가 전환 뒤에도 그대로 동작합니다. 이후 EIP가 이 상수 값을 재정의해 새 기능을 줄 수 있으며 EIP-4399가 그 예입니다.

유효성 규칙 변경과 보상 폐지

TRANSITION_BLOCK부터 difficulty 공식 검증, Ethash 함수에 따른 nonce·mixHash 검증, 엉클(ommer) 목록과 그 구성원에 대한 모든 검증 규칙이 제거됩니다. 대신 위의 상수 필드 검증이 추가되며, 새 규칙 중 하나라도 어긋나면 블록은 무효입니다. TRANSITION_BLOCK은 반드시 터미널 PoW 블록의 자식이어야 합니다. 보상도 바뀝니다. 블록 보상으로 beneficiary 계정 잔액을 늘리는 것, 엉클 포함 보상, 엉클 블록의 beneficiary에게 주는 엉클 보상이 모두 제거됩니다. 다만 트랜잭션 수수료가 beneficiary 계정에 들어가는 동작은 그대로 유지됩니다. 블록을 봉인하고 보상을 발행하는 책임은 PoS 합의가 맡습니다.

포크 초이스: LMD-GHOST와 낙관적 갱신 금지

첫 POS_FORKCHOICE_UPDATED 이벤트부터 PoW의 가장 무거운 체인 규칙을 제거하고 PoS의 LMD-GHOST 규칙을 따릅니다. 이벤트가 발생할 때마다 제네시스부터 이벤트가 지목한 헤드까지를 정본 체인으로 삼고 FIRST_FINALIZED_BLOCK부터는 최근 완결 블록도 이벤트가 지목한 대로 설정합니다. 첫 완결 전에는 이벤트의 완결 블록 해시가 0x00...00 스텁입니다. 블록 트리 저장소 변경은 원자적으로 적용해야 하며 새 블록을 현재 헤드 위에서 처리했더라도 이벤트 없이는 헤드로 올리면 안 됩니다(낙관적 갱신 금지). 초안에 있던 POS_CONSENSUS_VALIDATED 이벤트는 불필요한 최적화였고 같은 블록이 상충하는 두 PoS 브랜치에서 서로 다른 판정을 받을 수 있어 위험하므로 제거되었습니다.

네트워크: 블록 가십의 단계적 폐기와 포크 식별자

터미널 PoW 블록의 후손을 알리는 NewBlockHashes(0x01), NewBlock(0x07) 메시지는 보내지 않아야 합니다(SHOULD NOT). FIRST_FINALIZED_BLOCK을 받은 뒤부터는 들어오는 해당 메시지를 버려야 하고(MUST), 그다음 완결 블록부터는 메시지 핸들러 자체를 제거해야 하며, 그 뒤에도 계속 보내는 피어는 연결을 끊는 것이 권고됩니다. 전환 뒤에는 비콘 체인 네트워크에만 블록을 검증할 정보가 있으므로 eth 프로토콜의 블록 가십은 안전하지 않게 되어 폐기됩니다. 한편 EIP-2124 포크 식별자의 FORK_NEXT는 다음 포크의 블록 번호를 써야 하는데, 전환 조건이 동적이라 TRANSITION_BLOCK 번호를 미리 알 수 없으므로 명시적으로 정한 FORK_NEXT_VALUE를 대신 사용합니다.

비상 가속 장치: TERMINAL_BLOCK_HASH 재정의

전환을 앞당겨야 하는 비상 상황 두 가지를 고려합니다. 해시레이트가 급락해 전환이 크게 늦어지는 경우에는 TERMINAL_TOTAL_DIFFICULTY를 더 이른 시점의 값으로 낮추고 FORK_NEXT_VALUE를 맞춰 조정하면 됩니다. 전환 전 PoW 네트워크가 공격받는 더 심각한 경우에는 TERMINAL_BLOCK_HASH를 특정 블록 해시로, TERMINAL_BLOCK_NUMBER를 그 블록 번호로 설정해 터미널 PoW 블록을 지정합니다. 이때 정본 체인은 해당 높이에 해당 해시의 블록을 반드시 포함해야 하며 이는 기존 클라이언트의 블록 해시 화이트리스트 기능과 비슷합니다. 다만 이 방식은 메인넷에 상당한 활성 실패를 일으키므로 가장 극단적인 시나리오에서만 고려됩니다. TERMINAL_BLOCK_HASH가 스텁(0x00...00)이면 두 파라미터는 효력이 없습니다.

기존 컨트랙트와 노드 운영에 미치는 영향

EVM을 직접 바꾸지는 않지만 두 곳에 영향이 있습니다. DIFFICULTY 명령은 difficulty 필드가 0으로 고정되므로 항상 0을 반환합니다. 이 명령이 비콘 체인의 난수를 반환하도록 바꾸는 방안은 별도 EIP로 검토됩니다. BLOCKHASH 출력으로 얻던 의사난수는 블록 해시의 가변성을 줄이던 PoW가 사라지면서 더 불안전해집니다. 노드 운영 측면에서는 PoW와 달리 체인 전체 역사의 검증이 필요 없어집니다. PoS의 동기화는 피어들이 공유하는 과거 스냅샷인 약한 주관성 체크포인트(weak subjectivity checkpoint)에 의존하므로, 그 이전의 오래된 블록은 정본 체인 판단에 필수가 아닙니다. 이 EIP는 Final 상태로 확정되었고 메인넷에 적용되었습니다.

EIP 원문 · ← EIPs