Chapter 11. 단순 지급 검증

Kyle Lee
Programming Bitcoin
9 min readMay 31, 2020

아래 글에서는 <밑바닥부터 시작하는 비트코인(Programming Bitcoin)> — Jimmy Song, 한빛미디어(2019)의 Chapter 11 단순 지급 검증에 대한 내용을 일부 다룬다. 단순 지급 검증(SPV, Simplified payment verification)이란 특정 트랜잭션의 블록 포함 여부를 알아내는 과정(proof of inclusion)이며, 비트코인 네트워크의 확장을 위해 중요한 요소이다.

Writer. Kyle Lee

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. 세그윗

Contents

  1. 비트코인 네트워크와 SPV
  2. 머클트리를 이용한 포함증명 방법

SPV는비트코인 백서의 8번째 섹션에 아래와 같이 간략히 기술되어 있다. 이 때문인지 SPV의 중요성은 지금까지도 많이 간과되어 왔다.

Bitcoin: A Peer-to-Peer Electronic Cash System, Section 8

SPV의 중요성을 이해하기 위해서는 비트코인 네트워크에 대한 이해가 필요하다.

1. 비트코인 네트워크와 SPV

사실, 비트코인 네트워크의 초기에는 대부분의 사용자들이 풀 네드워크 노드(full network node)를 운영했었기 때문에 SPV의 중요성은 간과되었고, 지금도 그 중요성은 크게 알려져 있지 않다. 그러나 사토시는 네트워크가 특정 시점을 넘어서면, 채굴을 하는 풀 네드워크 노드(full network node)의 운영은 오직 전문화된 서버 팜(Server Farm)에서 이루어지게 될 것이기 때문이라 언급했다. 그리고 실제 지금의 비트코인 채굴은 일반 사용자가 아닌 대부분 전문화된 채굴 풀(Mining Pool)에서 이뤄지고 있다.

다시 말하자면, 현재 full network node를 운영하지 않는 대부분의 일반 사용자들은 SPV 를 이용함으로써 중개인에 대한 신뢰 없이도 트랜잭션을 주고 받을 수 있다. 비트코인 네트워크가 커질 수록 블록체인에 담기는 데이터의 양은 기하 급수적으로 확장하지만, 블록헤더의 양은 선형적(연간 4MB)으로 늘어날 뿐이다. 따라서 SPV는 블록전체의 데이터가 필요 없이 자신의 PubKey, PrvKey, 자신의 UTXOs, Merkle paths, 그리고 블록헤더(optional)만 유지함으로써 제 기능을 할 수 있다. 일반 사용자가 SPV를 사용하지 않는다면, 수백기가 바이트의 데이터를 저장해야 한다. 이 때문에 SPV는 비트코인 네트워크의 확장에 중요한 것이다.

비트코인 네트워크의 확장과 관련한 설명을 위해 Mandala Networks를 소개한다.

Mandala Networks

비크코인 네트워크는 위와 유사한 Mandala Networks를 이룬다. 아래는 이를 조금 더 구체화한 그림이다.

네트워크의 가장 안쪽 노드들(Layer1)은 채굴을 하는 마이닝 풀들이다. 마이닝 풀들은 그들끼리 각자의 인센티브를 위해 완전 그래프(Complete Graph)에 가까운 네트워크를 형성한다. 그러한 이유는, 우선 블록을 채굴한 마이너는 최대한 빠르게 다른 마이너에게 해당 블록을 전송하는 것이 유리하다. 그래야 자신이 채굴한 블록이 고아블록이 될 가능성을 낮출 수 있기 때문이다. 그리고 다른 누군가 새로운 블록을 채굴하였을 때, 각 마이너들은 그 블록의 정보를 최대한 빠르게 전달 받고자 한다. 그래야 다음 블록을 빠르게 생성하는 데 유리하기 때문이다.

이러한 인센티브 구조 덕분에 마이너들은 더욱 촘촘히 연결되며, 대규모 거래 및 대용량의 블록이 비트코인 네트워크에 빠르고 정확하게 전파되어 질 수 있다. 동시에 블록보상 및 수수료를 얻기 위한 마이너들간의 경쟁은 더욱 네트워크를 견고하고 빠르게 유지시켜 준다. 이것이 전문화된 채굴 풀의 등장으로 비트코인의 “확장성” 문제가 해결되는 방식이다.

Layer2는 채굴은 하지는 않지만, 블록 및 트랜잭션 데이터를 전문적으로 처리하는 기업(블록데이터 전문기업)들이 위치한다. 비트코인을 사용하는 특정 서비스 회사가 직접 노드를 운영하며 블록 데이터를 처리하고, 트랜잭션을 실시간으로 다루는 것에는 꽤 비싼 비용이 발생한다. 지금도 비트코인 네트워크에서는 50~100MB에 이르는 블록은 하루에도 수차례 발견되며, 하루 전송되는 트랜잭션의 양은 이제 100만 건을 훌쩍 뛰어넘는 상황이다. 최근에는 300MB, 100만 트랜잭션이 훨씬 넘는 블록들이 채굴되기도 했다. 이 모든 데이터를 모니터링하고 저장하기엔 상당한 비용이 들 수 밖에 없으며, 비트코인 네트워크가 확장될 수록 그 비용은 증가한다. 즉, 비트코인 데이터만을 전문적으로 처리해주는 기업이 자연스레 필요해진다.

Layer3와 Layer4는 비트코인을 활용하는 서비스회사와 사용자들이 위치한다. 바로 이들이 위에서 언급한 SPV를 사용하게 된다. full network node가 아닌 이상, 블록의 헤더정보 이외의 다른 데이터들을 보관 및 처리하는 것은 비용이 꽤 드는 일이라 비효율적이기 때문이다. 그리고 SPV를 사용하면, Layer1(마이너) 또는 Layer2(블록데이터 전문기업)을 신뢰하지 않고도(trustless) 안전하게 비트코인을 전송하거나, 혹은 필요한 데이터를 읽고 쓸 수 있게 된다.

이와 관련한 좀 더 자세한 설명은 이곳을 참조하기 바란다.

2. 머클트리를 이용한 포함증명 방법

비트코인 백서 섹션8에서는 SPV 기능을 위해 머클트리를 사용함을 언급한다. 머클트리는 데이터의 유효성을 검사하는데 사용되는 구조이다. 이를 통해 모든 블록 데이터가 없는 상태에서도 특정 TX의 존재여부를 확인 할 수 있다.

참고로, 머클트리에서 머클은 아직 생존해 계신 유명한 컴퓨터 과학자의 이름이다.

Ralph C. Merkle

머클트리는 랄프 머클이 발명했고, 이에 대한 특허를 1979년 취득했다.

An example of a binary hash tree

비트코인 블록헤더에는 Merkle Root가 포함된다. Merkle Root는 해당 블록에 포함되는 각 트랜잭션(단말 노드)으로 구성한 해시트리의 최상위 해시값(Top Hash)이다.

SPV는 특정 트랜잭션이 블록에 포함됐는지 확인하기 위해서 머클트리를 활용한다.

예를 들어, 위 그림에서의 H(K)로 표시된 특정 트랜잭션이 어떤 블록에 포함되어 있는지를 확인하는 방법은 다음과 같다.

  1. H(K), H(L), H(IJ), H(MNOP), H(ABCDEFGH)를 이용해 최상위 해시값인 H(ABCDEFGHIJKLMNOP)를 계산한다. 이것이 Merkle Root이다.
  2. 실제 블록헤더에 포함되어 있는 Merkle Root와 비교한다.
  3. 두 Merkle Root의 값이 같다면, H(K)는 해당 블록에 포함되어 있음이 증명된다. 이를 머클증명(Merkle Proof)이라고 한다.

SPV는 머클패스(Merkle Path)인 H(L), H(IJ), H(MNOP), H(ABCDEFGH)의 값을 자신과 연결되어 있는 full network node로부터 받아온다. 이 경우, 관심을 두고 있는 트랜잭션이 H(K)임이 너무 쉽게 드러나기 때문에, 실제로는 프라이버시 보호를 위해 좀 더 많은 정보를 요청해 받아온다.(12장 블룸 필터 참고)

머클블록(Merkle Block)은 full network node가 SPV가 요청하면 SPV에게 전달하는 정보이다. 여기에는 머클트리의 구조에 대한 정보와 각 해시값의 위치정보가 포함되어 있다. 머클블록 데이터는 다음과 같다.

  • version : 4bytes
  • previous block id : 32bytes
  • merkle root : 32bytes
  • timestamp : 4bytes
  • bits : 4bytes
  • nonce : 4bytes
  • number of total transactions : 4bytes
  • number of hashes : varint(The number of hashes to follow)
  • hashes : 32bytes * number or hashes
  • flag bytes : varint(The size of flags (in bytes) to follow)
  • flag bits : Merkle Path Data

version부터 nonce까지는 블록헤더에 있는 값 그대로 이며, 아래 5개 항목(number of total transactions ~ flag bits)의 데이터를 이용해 머클트리를 재구성한다. 그리고 이를 통해 특정 트랜잭션의 블록 포함여부를 확인한다. 이에 대한 알고리즘은 책에 상세히 설명되어 있으니 참고 바란다.

  • 이 글에서의 비트코인(Bitcoin)은 기술적으로 original protocol에 가장 가까운 것을 지칭한다.
  • 머클루트 관련 보안 취약점은 CVE-2012–2459에 잘 정리되어 있다.
  • varint : 가변정수 표현로 Chapter 5. 트랜잭션에 설명되어 있다. 여기에도 잘 정리되어 있다.
  • flag bytes : 책에서는 생략되어 있다. 자세한 내용은 Bitcoin Wiki를 참고바란다.

--

--