Chapter 10. 네트워킹

Hank Park
Programming Bitcoin
7 min readMay 31, 2020

아래 글에서는 “밑바닥부터 시작하는 비트코인(Programming Bitcoin) -한빛미디어(2019)”의 Chapter 10. 네트워킹에 대한 내용을 다룬다. 비트코인 노드가 실행된 후 다른 노드로부터 블록을 다운로드 받기까지의 플로우를 이해하는 것을 목적으로 한다. 주고 받는 데이터 형식과 같은 자세한 내용은 책을 참조하도록 한다.

Reviewed by. Nobody

Programming Bitcoin Series

Chapter 1. 유한체
Chapter 2. 타원곡선
Chapter 3. 타원곡선 암호
Chapter 4. 직렬화
Chapter 5. 트랜잭션
Chapter 6. 스크립트
Chapter 7. 트랜잭션 검증과 생성
Chapter 8. p2sh 스크립트
Chapter 9. 블록
Chapter 10. 네트워킹
Chapter 11. 단순 지급 검증
Chapter 12. 블룸 필터
Chapter 13. 세그윗

P2P 네트워크

비트코인 네트워크는 peer-to-peer(이하 P2P) 네트워크이다. 모든 노드들은 이 P2P 네트워크 위에서 블록과 트랜잭션을 주고받는다.

이 글은 비트코인 노드가 실행된 후 블록을 다운로드 받기까지의 다음과 같은 3 가지 단계을 설명한다.

  1. 탐색. 다른 노드의 IP를 수집한다.
  2. 연결. 특정 노드와 연결한다.
  3. 동기화. 다른 노드와 블록 데이터를 동기화한다.

블록체인과 P2P Network

P2P 네트워크는 물리적인 네트워크 토플로지 위에 가상의 오버레이 네트워크를 구성한다. P2P 노드들은 실제 물리적인 네트워크와 상관없이 가상의 오버레이 네트워크 상에서 1:1로 직접 연결된다. 오버레이 네트워크 내에서 노드들이 연결되는 방식과 P2P 네트워크 자원들이 인덱싱되고 검색되는 방법에 따라서, P2P 네트워크를 Unstructured 방식과 Structured 방식, 그리고 Hybrid 방식으로 구분할 수 있다.

비트코인 네트워크는 Unstructured 네트워크 방식이다. 이에 따라, 다음과 같이 Unstructured 네트워크의 장점을 그대로 가진다.

  • 노드의 구성이 랜덤하게 이루어진다.
  • 빈번한 노드의 네트워크 참여와 이탈을 감당하기 쉽다.

반면, 라우팅 공격 같이 Unstructured 네트워크가 가지는 보안 문제도 그대로 가진다.

참조: Peer-to-peer

탐색

노드가 실행되면 네트워크에 참여하기 위해서 가장 먼저 다른 노드들의 IP를 수집한다.

DNS Seeds

비트코인 노드 내에는 DNS Seeds 가 하드코딩 되어 있다. DNS 서버에 이 DNS Seeds의 IP를 조회하면 비트코인 노드의 IP를 리턴한다.

여기에서 하드코딩된 DNS Seeds를 확인할 수 있으며, “bitcoin.sipa.be”가 대표적인 DNS Seed이다. 아래는 DNS 서버에 조회하여 노드의 IP 어드레스 “144.217.240.89”를 응답받은 예이다.

> dig bitcoin.sipa.be; <<>> DiG 9.10.6 <<>> bitcoin.sipa.be
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45462
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;bitcoin.sipa.be. IN A
;; ANSWER SECTION:
bitcoin.sipa.be. 21599 IN CNAME zps.sipa.be.
zps.sipa.be. 21599 IN A 144.217.240.89
;; Query time: 349 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Wed May 13 00:53:41 KST 2020
;; MSG SIZE rcvd: 78

커스텀한 DNS Seeds를 사용하고 싶다면 비트코인 노드를 실행할 때, 커맨드 라인 파라메터 “— seednode”를 사용해서 DNS Seeds를 지정할 수도 있다.

이곳에서 ‘탐색’과 관련된 전체 플로우를 확인할 수 있다.

연결

상대 노드의 IP를 알아냈다면, 그 다음은 상대 노드와 연결한다. 노드 A가 노드 B에 연결하려는 경우 version, verack 메시지를 주고 받는다.

노드 간의 연결 시퀀스
출처: Mastering Bitcoin

위의 과정을 통해 연결이 완료되면 각 노드는 version 메시지에 담긴 상대방 노드의 정보를 알게 된다. version 메시지는 다음과 같은 필드를 포함한다.

  • protocol version: 비트코인 프로토콜 버전. 예: 70002
  • network services: 노드가 지원하는 서비스 목록
  • timestamp: 노드의 현재 시간
  • network address of receiver: 상대 노드의 퍼블릭 IP
  • network address of sender: 본인의 IP
  • user agent: 노드에서 실행중인 소프트웨어의 서브 버전. 예: “/Satoshi:0.9.2.1/”
  • height: 노드의 블록 높이
  • optional flag for relay: BIP37에 사용됨. 12장 블룸 필터 참조

verack 메시지는 헤더만 있고, 별도의 페이로드는 없다.

version과 verack 메시지 전체 구조는 이곳이곳에서 확인할 수 있다.

추가 발견

연결이 완료된 후에는, 각 노드가 알고 있는 추가 노드의 정보를 교환한다. getaddr 및 addr 메시지를 이용해서 추가 피어의 정보를 수집할 수 있다.

출처: Mastering Bitcoin

addr, getaddr 메시지에 대한 구조는 이곳이곳에서 확인할 수 있다.

블록 다운로드

연결이 완료되면, 다음은 다른 노드와 블록체인을 동기화하는 것이다. 만일 노드 A가 처음 실행되는 것이라면, 오직 Genesis 블록이라 불리우는 첫 번째 블록의 데이터만 소스 코드에 하드코딩된 형태로 가지고 있다.

연결 과정에서 받은 version 메시지의 height 필드를 통해 다른 노드와의 블록 높이를 비교할 수 있다. 상대 노드의 블록 높이가 더 높은 경우에, 다음과 같은 과정을 통해 블록을 다운로드한다.

출처: Mastering Bitcoin

연결된 두 노드는 각자 최상위 블록의 해시를 포함하고 있는 getblocks 메시지를 주고 받는다. 둘 중에 더 긴 블록을 가진 노드는 상대 노드에게 inv 메시지를 보내는데, 이 메시지에는 짧은 블록은 가진 노드가 추가해야 할 최초 500개 블록의 해시를 포함하고 있다. inv 메시지를 받은 노드는 getdata 메시지를 보내 블록 데이터를 요청하고, block 메시지를 통해 블록 데이터를 응답받는다.

각 메시지의 구조는 아래의 링크를 참조한다.

--

--