EIP-2481 eth/66 요청 식별자 (eth/66 request identifier)

최종 확정 · 네트워크·노드 · 원문 상태 Final · 2020-01-17 작성

이더리움 노드끼리 데이터를 주고받는 eth 프로토콜의 모든 요청·응답 메시지에 요청 번호(request_id)를 붙입니다. 이 변경으로 프로토콜 버전이 eth/65에서 eth/66으로 올라갑니다.

왜 필요한가

이더리움 노드는 다른 노드(피어)에게 블록 헤더, 블록 본문, 영수증 같은 데이터를 요청하고 응답을 받으며 동작합니다. 그런데 기존 eth 프로토콜에는 요청과 응답을 짝지어 주는 번호가 없었습니다. 한 노드가 같은 피어에게 여러 요청을 동시에 보내면 응답이 보낸 순서대로 돌아온다는 보장이 없어서 노드는 도착한 응답의 내용을 보고 대기 중인 모든 요청을 하나씩 뒤져 가며 어느 요청의 답인지 추측해야 했습니다. 특히 빈 응답처럼 내용만으로는 구분이 안 되는 응답은 짝을 찾기가 더 까다로웠습니다. 이런 방식은 모든 이더리움 클라이언트에 불필요하게 복잡한 코드를 강요하고 통신 효율도 떨어뜨립니다. 이 EIP는 요청을 보낼 때 번호를 붙이고 응답에 같은 번호를 그대로 돌려주게 해서 응답을 요청에 바로 연결할 수 있게 합니다.

무엇이 바뀌나

지금

EIP-2481 이후

누구에게 영향이 있나

심층 설명

메시지 구조를 바꾸는 방식

기존 메시지를 두 단계로 감쌉니다. 첫째, request_id를 첫 번째 원소로 하는 리스트를 만듭니다. 둘째, 기존 방식에서 명령 전체를 정의하던 리스트를 두 번째 원소로 넣습니다. 예를 들어 GetBlockHeaders(0x03)는 eth/65의 [block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]에서 eth/66의 [request_id: P, [block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]]로 바뀝니다. 응답인 BlockHeaders(0x04)도 같은 방식으로 [request_id: P, [blockHeader_0, blockHeader_1, ...]]가 됩니다.

바뀌는 메시지 열 가지

요청·응답 다섯 쌍이 모두 바뀝니다. GetBlockHeaders(0x03)와 BlockHeaders(0x04), GetBlockBodies(0x05)와 BlockBodies(0x06), GetPooledTransactions(0x09)와 PooledTransactions(0x0a), GetNodeData(0x0d)와 NodeData(0x0e), GetReceipts(0x0f)와 Receipts(0x10)입니다. 모두 request_id가 첫 원소, 기존 명령 리스트가 둘째 원소인 구조로 통일됩니다.

request_id의 세 가지 특성

request_id는 64비트 정수이고 순차적일 필요가 없으며(무작위 가능), 중복을 허용합니다. 순차성을 강제하지 않는 이유는, 연결이 끊긴 뒤 재접속한 클라이언트가 0부터 다시 세기 시작하면 이전 세션에서 쓰던 번호와 겹쳐 혼란이 생기기 때문입니다. 중복을 허용하는 이유는 구현의 유연성과 단순성입니다. 요청 종류가 다르면 자연히 구분되므로 같은 번호를 여러 요청 타입에 공유할 수 있고, 아예 request_id에 의존하지 않고 모든 요청에 같은 상수를 쓰는 구현도 가능합니다. 64비트를 고른 것은 les 프로토콜과의 호환성 때문입니다.

les 프로토콜과의 관계

라이트 클라이언트용 les 프로토콜은 이미 모든 요청·응답 쌍에 요청 식별자를 정의하고 있습니다. 이 EIP는 eth 프로토콜을 les와 더 비슷하게 맞추는 효과가 있습니다. 그렇다면 les를 그냥 쓰면 되지 않느냐는 물음에 원문은, 실제 네트워크에서 les를 서비스하는 피어를 찾기가 훨씬 어렵다고 답합니다. 클라이언트 기본 설정, 미성숙한 구현, 인센티브 부재 등이 이유로 꼽힙니다. 또 정수 하나를 더하는 것이 군더더기 아니냐는 물음에는, 메시지당 정수 하나를 추가하는 대신 코드 복잡성을 줄이고 네트워킹 효율을 높이므로 정당하다고 답합니다.

하위 호환성: 하드포크 없이 배포

이 변경은 eth 프로토콜을 하위 호환되지 않게 확장하므로 새 버전인 eth/66을 배포해야 합니다. 다만 devp2p는 같은 와이어 프로토콜의 여러 버전을 나란히 운영할 수 있어서 업데이트하지 않은 클라이언트는 eth/65를 계속 쓰면 됩니다. 따라서 클라이언트 간 일정 조율 없이 배포할 수 있습니다. 합의 엔진을 건드리지 않으므로 하드포크도 필요 없습니다. 이 EIP는 eth/65를 정의한 EIP-2464를 전제로 합니다.

테스트 케이스와 RLP 인코딩

원문은 재정의된 모든 메시지 타입의 RLP 인코딩 테스트 케이스를 제공합니다. 각 테스트는 data 부분에 정의된 메시지와 그것을 rlp로 인코딩한 결과를 짝지어 보여 줍니다. 예를 들어 GetBlockHeadersPacket66 테스트는 RequestId 1111, Amount 5, Skip 5, Reverse false 같은 필드를 담은 요청이 0xe8820457e4a0...0580으로 인코딩됨을 보여 줍니다. BlockHeaders, BlockBodies, NodeData, Receipts, PooledTransactions 등 열 가지 메시지 전부에 대해 같은 형식의 검증 데이터가 있어 클라이언트 구현을 대조할 수 있습니다. 이 EIP의 상태는 Final로, 명세가 확정되었습니다.

EIP 원문 · ← EIPs