‘Mastering Bitcoin 2nd’ 세미나 13, 9장. The Blockchain
이번 장에서는 블록체인에 대해서 설명합니다. 먼저 책 내용을 읽은 후, 아래 정리한 내용을 다시 한 번 읽어봅니다.
Chapter 9. The Blockchain
Introduction
트랜잭션들은 블록으로 묶이고, 블록은 순서적으로 연결되어 블록체인이 됩니다. 블록들은 이전 블록을 다음 블록이 참조하는 방식으로 일방향으로 연결됩니다. 비트코인 코어 클라이언트는 구글 LevelDB 데이터베이스를 사용해서 블록체인 데이터를 저장합니다.
블록체인의 첫 번째 블록을 제네시스 블록이라고 합니다. 블록체인은 높이(height)가 있는데 제네시스 블록을 1로해서 블록이 추가될 때 마다 1씩 커집니다. 높이 값을 보면 지금까지 몇 개의 블록이 생성되었는지를 알 수 있습니다.
블록은 해시로 식별됩니다. 블록 해시는 블록 헤더 데이터에 SHA256 해시 알고리즘을 적용한 결과입니다. 해시로 블록을 식별하기 때문에 이전 블록에 대한 참조(previous block hash)도 해시로 블록 헤더 데이터로 작성됩니다. 이런 방식으로 연결되기 때문에 하나의 블록이 변경되면 해당 블록의 해시가 변경되고, 블록의 해시가 변경되면 이것을 참조하는 블록의 헤더가 변경되고 결과적으로 해시가 변경됩니다. 변경된 해시를 참조하는 블록이 있다면 이것의 해시도 변경되고, 이러한 변경의 연쇄는 계속됩니다.
This cascade effect ensures that once a block has many generations following it, it cannot be changed without forcing a recalculation of all subsequent blocks. Because such a recalculation would require enormous computation (and therefore energy consumption), the existence of a long chain of blocks makes the blockchain’s deep history immutable, which is a key feature of bitcoin’s security.
이러한 구조를 갖기 때문에 블록체인에서 하나의 블록 데이터를 바꾸면 변경된 블록 이후의 모든 블록들의 데이터도 바뀌게 됩니다. 블록체인 내의 특정 블록 하나의 데이터만 바꿀 수는 없습니다.
블록체인은 높이 말고 깊이라는 개념도 있는데, 깊이는 해당 블록을 1로 하고 블록 뒤에 추가된 블록 개수를 더한 값입니다. 깊이가 깊어진다는 것은 해당 블록 데이터를 바꾸었을 때 연쇄적으로 바꾸어야 할 블록들이 많다는 것을 의미합니다. 블록 깊이가 깊다는 것은 그 만큼 해당 블록 데이터를 바꾸기 어렵다는 것을 의미합니다.
Although a block has just one parent, it can temporarily have multiple children. Each of the children refers to the same block as its parent and contains the same (parent) hash in the “previous block hash” field. Multiple children arise during a blockchain “fork,” a temporary situation that occurs when different blocks are discovered almost simultaneously by different miners (see [forks]). Eventually, only one child block becomes part of the blockchain and the “fork” is resolved. Even though a block may have more than one child, each block can have only one parent. This is because a block has one single “previous block hash” field referencing its single parent.
블록들 사이의 연결에서 참조된 이전 블록을 부모라고 하고, 참조하는 다음 블록을 자식이라고도 합니다. 부모는 하나만 가질 수 있지만 자식은 여러 개 가질 수 있는데 이럴 경우 포크(fork)가 발생했다라고 합니다.
포크가 발생하는 근본적인 이유는 차이가 발생할 수 밖에 없는 P2P 네트워크의 고유한 특성 때문입니다.
비트코인 네트워크에서 포크를 발생하는 상황은 두 가지로 구분할 수 있습니다. 첫 번째는 POW라는 경쟁 방식의 합의 알고리즘에 의한 것이고, 두 번째는 소프트웨어 업그레이드에 의한 것입니다. 이에 대해서는 10장에서 상세하게 다룹니다.
아래 인용한 본문 내용은 저자의 탁월한 비유 능력을 보여줍니다.
One way to think about the blockchain is like layers in a geological formation, or glacier core sample. The surface layers might change with the seasons, or even be blown away before they have time to settle. But once you go a few inches deep, geological layers become more and more stable. By the time you look a few hundred feet down, you are looking at a snapshot of the past that has remained undisturbed for millions of years. In the blockchain, the most recent few blocks might be revised if there is a chain recalculation due to a fork. The top six blocks are like a few inches of topsoil. But once you go more deeply into the blockchain, beyond six blocks, blocks are less and less likely to change. After 100 blocks back, there is so much stability that the coinbase transaction—the transaction containing newly mined bitcoin—can be spent. A few thousand blocks back (a month) and the blockchain is settled history, for all practical purposes. While the protocol always allows a chain to be undone by a longer chain and while the possibility of any block being reversed always exists, the probability of such an event decreases as time passes until it becomes infinitesimal.
Structure of a Block
핵심은 거래 즉 트랜잭션을 다루는 것입니다. 블록체인은 트랜잭션들을 블록 단위로 묶어 다루고, 블록들을 시간 순서대로 서로 연결해서 전체 트랜잭션들을 관리하는 것입니다.
블록은 헤더에 해당하는 메타데이터와 바디에 해당하는 트랜잭션들로 구성됩니다.
The block header is 80 bytes, whereas the average transaction is at least 400 bytes and the average block contains more than 1900 transactions. A complete block, with all transactions, is therefore 10,000 times larger than the block header.
블록 헤더는 80바이트이고, 블록은 평균적으로 1900개 이상의 트랜잭션을 포함하고, 하나의 트랜잭션은 평균적으로 400바이트 이상입니다. 블록은 블록 헤더에 비해 10,000배 정도 큽니다.
표 1은 블록 구조를 설명합니다.
- 블록 크기(Block Size)를 나타내는 4바이트
- 블록 헤더(Block Header) 80바이트
- 트랜잭션 갯수(Transaction Counter)를 나타내는 가변형 정수 1~9바이트
- 트랜잭션들(Transactions)
Block Header
표 2는 블록 헤더 구조를 설명합니다.
- 소프트웨어/프로토콜 업그레이드를 추적하기 위한 버전(Version) 4바이트
- 이전 블록 해시(Previous Block Hash) 32바이트
- 머클 루트(Merkle Root) 32바이트
- 머클 트리의 루트 해시
- 머클 트리 – 블록에 포함된 모든 트랜잭션들을 효율적으로 요약할 수 있도록 하는 데이터 구조(트리)
- 머클 트리의 루트 해시
- 블록 생성 시간을 나타내는 타임스탬프(Timestamp) 4바이트
- 10장에서 상세하게 다룸
- 블록 생성의 난이도(Difficulty Target) 4바이트
- 10장에서 상세하게 다룸
- 논스(Nonce) 4바이트
- 10장에서 상세하게 다룸
Block Identifiers: Block Header Hash and Block Height
블록은 블록 헤더 해시와 블록 높이를 식별자로 사용할 수 있습니다.
블록 헤더 해시는 블록체인 내에서 고유한 값이지만 블록 높이는 그렇지 않습니다. 일시적이지만 포크가 발생할 수 있기 때문입니다. 비트코인 시스템의 합의 메커니즘은 “가장 긴 체인(가장 노력이 많이 들어간 체인)을 단일 진실로 선택” 합니다. 따라서 어느 정도 시간이 지나고 나면(블록이 여러 개 추가적으로 생성되고 나면) 블록 높이도 블록체인 내에서 고유한 값으로 인정받게 되고 식별자로 사용할 수 있게 되는 것입니다.
블록 해시와 블록 높이는 블록 데이터 구조에 포함되지 않음을 주의해야 합니다. 이 값들은 필요 시 계산해서 구합니다. 블록 탐색기와 같은 서비스 제공자들은 빠른 블록 탐색을 위해 블록 데이터 외에 이들 값을 추가적으로 저장하기도 합니다.
The Genesis Block
비트코인 네트워크에 참여하는 노드들은 모두가 같은 블록체인을 가지고 있어야 합니다. 노드가 네트워크와 같은 블록체인을 갖도록 자신의 블록체인을 구성하는 과정을 동기화라고 합니다.
블록체인의 개별 블록들은 이전 블록을 참조하는 방식으로 모두를 순차적으로 연결합니다. 따라서 연결을 시작하려면 첫 번째 블록이 어떤 것인지를 알아야 합니다. 블록체인의 첫 번째 블록을 제네시스 블록이라고 합니다.
비트코인 시스템은 제네시스 블록을 비트코인 클라이언트 소프트웨어 내에 고정된 값으로 포함하는 방법으로 비트코인 네트워크에 참여하는 모든 노드가 동일한 제네시스 블록을 갖도록 합니다.
Merkle Trees
그림 2와 그림 3이설명하는 것과 같이, 머클 트리를 사용해서 블록에 포함된 모든 트랜잭션들에 대한 요약을 만들 수가 있습니다.
트랜잭션들을 나열하고 각각의 트랜잭션에 대해 SHA256을 두 번 적용해서 해시를 구하고, 둘 씩 짝을 지어 루트에 이르기까지 계층을 따라 올라가면서 같은 방법으로 SHA256을 두 번 적용해서 해시를 구합니다. 둘 씩 짝을 지어야 하기 때문에 트랜잭션 수가 홀수 인 경우 마지막 트랜잭션을 중복해서 짝수가 되게 합니다. 머클 트리의 루트 해시를 머클 루트라고 합니다.
최종적으로 블록에 포함된 모든 트랜잭션들은 머클 루트로 요약되어, 블록 헤더 항목으로 작성됩니다.
트랜잭션 데이터로 트랜잭션 해시가 계산되고, 트랜잭션 해시들로 머클 루트가 계산되고, 머클 루트를 포함한 블록 헤더로 블록 해시를 계산합니다. 이런 방법을 사용함으로서 트랜잭션 데이터들을 모두 사용해서 블록 해시를 계산하지 않고도 머클 루트 만을 사용해서 효율적으로 블록 해시를 계산할 수 있습니다.
SPV 노드에서 설명할 때 SPV 노드는 포함 증명(특정 트랜잭션이 특정 블록에 포함되어 있는지를 증명)으로 트랜잭션의 유효성을 검증한다고 했습니다. 머클 트리는 여기에서도 사용할 수 있습니다.
포함 증명에는 머클 트리 전체 노드의 해시를 요구하지 않습니다. 포함되었는지를 알고자 하는 트랜잭션으로 시작해서 루트까지 올라가는 경로(머클 패스)에 필요한 노드만 해시를 가지고 있으면 됩니다. 예를 들어 그림 5에서 HK의 포함 증명을 위해서는 HL, HIJ, HMNOP, HABCDEFGH만 있으면 됩니다. 이것들을 사용해서 계층적으로 구한 해시 값이 머클 루트와 같으면 블록에 트랜잭션이 포함되어 있음이 증명됩니다.
단순 지급 검증(SPV) 노드는 블록 헤더들만 다운로드 받고, 풀 노드로 부터 머클 패스를 받아 트랜잭션이 블록에 포함되어 있는지를 검증할 수 있습니다. 풀노드는 불룸 필터에 매칭되는 트랜잭션이 있을 때 merkleblock 메시지를 사용해서 블록 헤더와 머클 패스를 전달합니다.
Bitcoin’s Test Blockchains
비트코인 시스템은 메인 체인 외에도 테스트 목적의 체인(testnet, segnet, regtest)을 운영합니다.
테스트넷은 이름 그대로 개발자들에게 테스트 용으로 제공되는 체인입니다. 메인넷에 비해 채굴이 상대적으로 쉽다는 점을 제외하고 같은 기능을 갖고 운영되는 독립된 네트워크 입니다. 현재 테스트넷은 testnet3이라고 불립니다.
테스트넷으로 비트코인 코어를 실행하려면 다음과 같은 옵션을 사용해서 실행해야 합니다.
- bitcoind -testnet
segnet은 세그윗에 대한 테스트를 위한 체인으로, testnet3에서 세그윗이 가능하기 때문에 segnet은 지금은 필요 없습니다.
regtest는 테스트 목적으로 사용한다는 점에서는 testnet과 같지만, testnet은 공개된 네트워크이고 regtest는 비공개 네트워크라는 점에서 다릅니다. regtest는 내부에서만 사용하는 로컬 체인 네트워크 입니다. 대부분 하나의 노드를 가지고 실행되지만 다수의 노드들로 구성할 수도 있습니다.
다음과 같은 옵션을 사용해서 실행합니다.
- bitcoind -regtest
Using Test Blockchains for Development
regtest에서 테스트를 마친 후, 테스트넷에서 테스트하고, 최종적으로 메인넷으로 제품을 배포합니다.