> For the complete documentation index, see [llms.txt](https://books-and-cows.gitbook.io/bitcoin-developer-guide-in-korean/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://books-and-cows.gitbook.io/bitcoin-developer-guide-in-korean/block-chain.md).

# Block Chain

블록체인은 비트코인의 공공 장부(public ledger)를 제공한다. 이 공공 장부는 시간기록(timestamp)을 포함하고 시간순서로 정렬된 트랜잭션들의 기록 그 자체다. 이 시스템은 이중 지불(double spending)과 이전에 발생했던 트랜잭션 기록(transaction records)에 대한 수정(modification)을 방지하는데 사용된다.

비트코인 네트워크 내의 각 풀 노드(full node)는 풀 노드들로부터 검증된 블럭들을 포함하고 있는 블록체인을 저장하고 있다. 개별 노드들이 모두 같은 블록들로 이루어진 블록체인을 가지고 있다면, 합의(consensus)를 이루고 있다고 여겨진다. 이러한 노드들이 합의(consensus)를 이루기 위해 유지하는 일종의 검증 규칙(validation rules)들을 합의 규칙(consensus rules)이라 한다. 이번 섹션에서는 비트코인 코어에 사용되는 많은 합의 규칙(consensus rules)에 대해 서술한다.

> Note: 트랜잭션이란 거래라고 해석할 수 있다. 하지만 앞으로 이루어지는 번역에서는 좀 더 정확한 의미를 담고자 거래 대신 트랜잭션이라는 용어를 계속해서 사용한다.

## Block Chain Overview (블록 체인 개요)

![](https://2895310081-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-L9heHiETfq_9kxk2Qnu%2F-L9heQ85fDiVcp9UMbdd%2F-L9heUYn_mVYFHQLvqCb%2Fen-blockchain-overview.svg?generation=1523332025860218\&alt=media)

위 그림은 간소화된 버전의 블록체인을 보여준다. 새로운 트랜잭션을 하나 혹은 여러 개 포함하고 있는 하나의 블록은 블록 내에 존재하는 트랜잭션 데이터 파트에 수집된다. 각 트랜잭션의 복사본들은 해시되고(hashed), 그 해시들은 서로 쌍을 이루어 해시되고, 또 해시된 결과들 끼리 해시되는 과정을 반복한다. 단 하나의 해시가 남게될 때까지 과정을 반복하고, 단 하나의 해시가 남게되면 해당 값을 머클 트리(merkle tree)의 머틀 루트(merkle root)라고 한다.

머클 루트는 블록 헤더(block header) 내에 저장된다. 각 블록은 이전 블록의 헤더에 대한 해시를 저장하고, 각 블록들이 서로 묶일 때는(chaining) 블록의 헤더 값으로 묶이게 된다. 이렇게 엮게 되면, 하나의 블럭을 수정했을 경우 해시로 연계된 모든 블럭의 해시값이 바뀌게 되므로 임의 블럭에 대한 수정을 사전 방지할 수 있다.

> 만약 블록 내용을 바꾸고 싶다면, 그 블록 뒤로 연결되는 모든 블록의 해쉬값을 그에 맞게 수정해야 해야 하는데, 이는 현실적으로 매우 힘들다. 엄청난 컴퓨팅 자원, 즉 자본이 소요되고 그렇게 해서 블록 내용을 수정한다해도 전체 네트워크의 신뢰도가 떨어지므로 비트코인 생태계의 가치 또한 하락할 것이다. 결국 공격을 감행하는 공격자는 엄청난 경제적 손실을 감수해야만 한다.

트랜잭션들 또한 서로 엮여 있다. 비트코인 지갑 소프트웨어는 한 지갑에서 다른 지갑으로 사토시(satoshis)를 전송할 때, 트랜잭션들 끼리의 이동을 통해 전송을 수행한다; 즉 지갑과 지갑 사이의 교환이 아닌 트랜잭션에서 다른 트랜잭션으로 옮겨가는 것뿐이다. 각 트랜잭션은 이전에 발생했던 트랜잭션의 아웃풋에 있는 사토시를 소비한다. 즉, 한 트랜잭션의 인풋(input)은 다른 트랜잭션의 아웃풋(output)으로 이루어진다.

> 사토시(satoshi)는 비트코인의 통화 단위이다. 1억분의 1비트코인이 1사토시다.
>
> 한 트랜잭션의 인풋이 다른 트랜잭션의 아웃풋이라는 의미는, 만약 당신이 1000사토시를 누군가에게 전송하고 싶다면, 당신에게는 1000사토시보다 더 많은 사토시를 가져야만 해당 트랜잭션을 생성할 수 있다는 뜻이다. 즉 없는 돈을 누군가에게 전송한다거나 하는 행위는 사전에 차단된다. 내 주소로 들어오는 인풋(input)이 없다면, 새로운 아웃풋(output)은 생성할 수 없다.

![](https://2895310081-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-L9heHiETfq_9kxk2Qnu%2F-L9heQ85fDiVcp9UMbdd%2F-L9heUZNIsRI5OuX_DX1%2Fen-transaction-propagation.svg?generation=1523332025889806\&alt=media)

하나의 트랜잭션은 여러 개의 아웃풋을 만들 수 있다; 내가 가진 비트코인이 10개가 존재한다면, 코인을 2개씩 서로다른 다섯 명에게 전송하는 아웃풋을 만들어내는 것이 가능하다는 의미다. 하지만 해당 트랜잭션의 각 아웃풋은 블록체인 내에 하나의 인풋으로만 사용될 수 있다.

> 나로부터 2비트코인을 받은 사람은 2비트코인에 해당하는 인풋을 가진다는 말이다. 어찌보면 당연한 말이다.

아웃풋들은 TXIDs(transaction identifiers)로 묶인다. TXIDs는 서명된 트랜잭션들(signed transactions)의 해시들(hashes)이다; 서명된 트랜잭션들을 식별(구분)하기 위해 사용되는 값이고, 확실하게 식별하기 위해서 해시를 거친다.

특정 트랜잭션의 아웃풋은 한 번만 사용될 수 있기 때문에 블록체인 내에 존재하는 트랜잭션들의 아웃풋은 UTXOs (Unspent Transaction Outputs) 또는 spent transaction outputs로 분류될 수 있다; 즉, 아직 사용되지 않은 아웃풋들의 집합(UTXOs)과 이미 사용된 아웃풋들의 집합(spent transaction outputs)으로 구분된다는 당연한 말이다. 지불과정이 유효하려면, 해당 지불은 반드시 UTXOs를 인풋으로 사용해야 한다; 이미 사용된 아웃풋을 인풋으로 사용할 수는 없다.

코인베이스 트랜잭션(coinbase transaction)을 제외하면, 트랜잭션의 아웃풋이 해당 트랜잭션의 인풋을 초과했다면, 트랜잭션은 거부된다. 반대로 인풋이 사용하려는 아웃풋 보다 높다면, 그 차이는 트랜잭션들을 포함한 블록을 생성하는 비트코인 마이너들(miners)에게 수수료로서 청구될 수 있다; 비트코인 생태계에서 마이너들은 비트코인 네트워크가 정상작동할 수 있게 블록을 생성하는 작업을 수행하기 때문에 우리는 마이너들에게 서비스 이용료로서 일정 수수료를 지불하게 되어 있다. 예를 들면, 위 그림에서 각 트랜잭션은 10,000 사토시를 제외한 나머지 금액을 소비한다. 10,000 사토시는 마이너들에게 수수료로 지불된다는 것을 알 수 있다. 100K의 사토시를 다른 사람에게 각각 40K, 50K 씩 보낸 것을 볼 수 있다. 즉 100K 중 나머지 10K는 마이너에게 수수료로 지불 되었다는 의미이다.

> 코인베이스 트랜잭션은 마이너(miner)가 블록을 생성할 때 가장 첫번째로 포함하는 특별한 트랜잭션으로, 이 트랜잭션은 블록을 생성한 보상을 마이너 개인 비트코인 주소로 전송하는 트랜잭션이다. 마이너는 프로토콜상에 기재된 (현재 12.5비트코인) 갯수만큼의 비트코인을 보상으로 얻을 수 있다.
>
> 또한 코인베이스 트랜잭션을 제외한 다른 트랜잭션들도 포함할 수 있고 이로써 마이너는 블록 생성 보상과 더불어 트랜잭션 수수료를 취할 수 있다.

## Proof Of Work (작업 증명)

블록체인은 네트워크 안에 존재하는 익명의 피어들(anonymous peers)의 협력으로 유지된다. 그래서 비트코인은 각 블록을 생성할 때 일종의 중요한 작업을 요구한다. 이 작업은 컴퓨팅 파워, 자원이 많이 소요되는 작업으로 네트워크 안에 존재하는 비협력적 혹은 불순한 피어(untrustworthy peers)들이 블록 내용을 함부로 바꿀 수 없게끔 한다. 불순한 피어들이 과거에 생성된 블럭의 내용을 바꾸려면 성실히 일하는 (새로 생긴 블럭을 블록 체인에 추가하는 작업만 하는) 피어들(honest peers) 보다 더 많은 컴퓨팅 연산을 해야 한다; 물론 이러한 작업을 하려면 막대한 비용을 감수해야 하고, 심지어 바꾼다 해도 크게 이득볼 수 있는 요소는 존재하지 않는다.

각 블록을 엮는 것은 특정 블록 내의 트랜잭션을 바꿀 수 없게 만든다. 한 블록 내의 트랜잭션을 바꾸는 행위는 결국, 그 블록 이후에 엮인 모든 블럭들을 수정하지 않으면 불가능하기 때문이다. 결과적으로 특정 블럭을 수정하는 작업의 비용 (컴퓨팅 파워, 자원)은 새로운 블럭이 생겨날수록 기하급수적으로 늘어난다. 이것이 바로 작업증명(POW)의 효과다.

비트코인에 사용되는 작업 증명(Proof Of Work) 과정은 난수적인 특징을 갖는 암호 해쉬(the apparently random nature of cryptographic hashes)를 이용하고 있다. 좋은 암호 해쉬 알고리즘은 임의의 데이터를 (겉으로 볼 때) 랜덤한 숫자로 바꿔준다; 완벽한 난수 생성이라는 개념은 컴퓨터에서 구현될 수 없으므로, 겉으로 볼 때라는 표현이 들어갔다. 만약 데이터가 수정된다면, 해쉬가 재동작하여 (겉으로 볼 때) 랜덤한 숫자가 다시 생성된다. 해쉬 넘버를 예측 가능하게 데이터를 수정하는 방법은 존재하지 않는다.

블록을 생성하기 위해 추가 작업을 했다는 것을 증명하기 위해서는, 특정 값(a certain value)을 초과하지 않는 블록 헤더의 해쉬(a hash of the block header)를 생성해야만 한다. 예를 들어, 해쉬가 가질 수 있는 최대값이  라고 가정한다면,  보다 작은 값을 생성함으로써 최대 두 조합을 실행했다는 것을 증명할 수 있다.

> 위 설명에 대한 자세한 예시를 들자면, 2의 256승 -1이라는 값을 이진수로 풀어쓰면 111 ... 110으로 표현할 수 있고 2의 255승은 011 ... 111으로 표현할 수 있다. 즉 앞에 0이 하나만 들어가는 256글자의 이진수를 찾으면 2의 256승 - 1이라는 값을 초과하지 않는 조건을 만족할 수 있으므로 2가지 경우의 수(1 또는 0)를 시도하면 되는 것이다. 그래서 두 번의 조합만으로 조건을 만족시키는 것이 가능한 것이다.

위에서 든 예시로는, 평균적으로 2번의 해쉬 생성을 시도하면 조건을 만족하는 성공적인 해쉬를 생성할 수 있을 것이다. 그렇다면, 주어진 해쉬 생성 시도(a given hash attempt)가 타겟 값(target threshold)보다 작은 해쉬를 성공적으로 생성할 확률을 측정할 수도 있을 것이다. 비트코인은 선형 확률 모델(a linear probability)을 가정하는데, 이 모델에서는 타겟 값(target threshold)이 더 낮아질수록 더 많은 해쉬연산(the more hash attempts)이 요구된다.

새로운 블록은 적어도 블록의 해쉬가 합의 규칙(consensus protocol)에서 기대하는 난이도 값(a difficulty value expected)에 충분히 도전적일 경우에만 블록체인에 추가된다; 타겟 값을 넘지 않는 해쉬를 성공적으로 생성했을 때만 추가된다는 말과 동일하다. 2,016개의 블록마다, 네트워크는 각 블록 헤더에 저장되어 있는 시간기록(timestamps)를 이용하여 2,016개의 블록 중 첫 블록의 생성 시간과 마지막 블록의 생성 시간 사이의 시간차(number of seconds elapsed between generation of the first and last of those last 2,016 blocks)를 계산한다. 가장 이상적인 차이값은 1,209,600 초라고 한다 (2주에 해당하는 값).

* 만약 2,016개의 블록을 생성하는데 2주 보다 적은 시간이 걸렸다면, 기대되는 난이도 값(the expected difficulty value)은 비율에 맞게 증가한다 (최대 300%까지). 때문에 해시를 체크하는 속도가 동일하다면, 다음 2,016개 블록은 정확히 2주라는 시간 동안 만들어지게 된다.
* 만약 2주 이상의 시간이 걸렸다면, 기대되는 난이도 값은 비율에 맞게 감소한다 (최대 75%까지).

(Note: 비트코인 구현에 있어서 off-by-one error(하나의 사소한 문제로 발생하는 오류)는 블록의 난이도가 2,016개의 블록마다 조정되는 것을 어렵게 할 수 있다. 본래 2,016개 블록의 타임스탬프 값을 근거로 난이도를 조정해야 하는데, off-by-one error가 발생할 경우 2,015개의 블록 타임스탬프 값만을 근거로 난이도가 재조정될 수 있다.)

각 블록헤더는 반드시 타겟 값(target threshold)보다 작은 해쉬를 가져야 하고, 각 블록은 이전에 생성된 블록과 연결되어(linked to the block that preceded it) 있다. 이 때문에 수정된 블록(a modified block)을 전파하는 행위는 많은 해시 파워(hashing power)를 요구한다. 원본 블록이 생성된 시간과 현재 사이에 전체 비트코인 네트워크가 이미 소모되었기 때문이다. 트랜잭션 기록(transaction history)에 손을 대는 행위, 그리고 이를 다시 전체 네트워크에 전파하는 건, 전체 네트워크 해시 파워(hashing power)의 51%를 가지고 있지 않으면 불가능하다 (물론 50% 보다 적은 해시 파워를 가지고도 충분히 이와 같은 행위를 하는 것이 가능하긴 하다).

블록헤더는 설정하기 쉬운 몇개의 항목들(easy-to-modify fields)을 제공한다. 예로 dedicated nonce field가 존재하고, 이 항목(field) 덕분에 새로 생기는 트랜잭션을 기다릴 필요 없이 새로운 해시들을 얻을 수 있다. 오직 80바이트 크기의 블록헤더만이 작업증명(proof-of-work)에 의해 해시된다. 따라서 많은 양의 트랜잭션 데이터를 한 블록에 포함시키는 작업이 추가적인 입출력(I/O)으로 인해 해시 연산속도를 낮추거나 하진 않는다. 트랜잭션을 추가하는 건 단지 머클 트리에 존재하는 조상들의 해시를 재계산(recalculation of the ancestor hashes in the merkle tree) 하기만 하면 된다.

## Block Height And Forking (블록의 높이와 포킹)

블록헤더를 타겟 값(target threshold)보다 낮은 값으로 성공적으로 해쉬한 마이너는 해당 블록을 블록체인에 추가할 수 있다 (블록이 검증되었다는 가정 하에). 이러한 블록들은 블록 높이(block height)로 설명이 되어질 수 있다. 블록 높이란, 최초에 생겨난 제네시스 블록(genesis block)부터 지금까지 생겨난 블록의 갯수를 의미한다. 예를 들어, 블록 2,016은 비트코인 역사상 최초의 난이도 조정 과정이 이루어진 곳이라고 생각할 수 있다; 2,016개마다 난이도 재조정이 된다는 것을 작업증명 파트에서 이미 다뤘다.

![](https://2895310081-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-L9heHiETfq_9kxk2Qnu%2F-L9heQ85fDiVcp9UMbdd%2F-L9heU_rbqD5aPwbIkW9%2Fen-blockchain-fork.svg?generation=1523332026043951\&alt=media)

두 개 이상의 블록(Multiple blocks)은 같은 높이를 가질 수 있는데, 이는 두 명 이상의 마이너들이 거의 동시에(roughly at the same time) 블록을 생성했을 경우 그렇다. 이러한 경우 위 그림에서 보듯 블록체인 내에 포크(fork)를 생성하게 된다; 포크라는 이름이 붙은 이유는 갈라지는 것을 시각적으로 연상시키기 위해 붙었다.

마이너가 가장 최신에 위치하게 될 블록(block at the end of the block chain)을 동시에(simultaneous) 생성할 때, 네트워크를 구성하는 각 노드들은 어떤 블록을 인정(accept)할 것인지 선택하게 된다. 아래에서 더 자세히 다루겠지만, 노드들은 보통 첫 번째로 발견한 블록(the first block they see)을 선택한다.

결국 마이너는 또 다른 블록을 생성할 것이고, 동시에 생성된 두 블록 중 하나의 블록에 자신이 생성한 블록을 더해 갈 것이다. 그러다 보면 결국 포크가 된 두개의 블록체인 중, 더 긴 블록체인(side of the fork stronger than the other side)이 생기게 마련이다. 두 개의 포크 모두 검증된 블록만을 가지고 있다고 했을 때, 보통 피어들은 만드는 데 더 많은 연산이 소모된 블록체인(the most difficult chain to recreate)을 선택하게 되어 있다. 이 과정에서 선택되지 못하여 효력이 상실된 실효블록들(stale blocks)은 버려지게 된다. (선택되지 못한, 즉 효력을 잃은 실효블록(stale block)들은 고아 블록(orphans or orphan block)이라 불리기도 한다. 고아 블록의 경우 알려진 부모 블록이 없지만 검증된 블록(true orphan blocks without a known parent block)을 뜻하기도 한다.)

갈라진 포크체인들이 지속적으로 각자의 길을 갈 수도 있다. 하나만 선택되지 않고 두 개 모두 고르게 계속 블록이 붙으면서 성장할 수 있는데, 이는 마이너들에게 달려 있다. 어떤 마이너들은 더 긴 블록체인에 성실하게 블록을 더해가는 반면, 51% 공격을 노리고 (기존 거래 기록들을 엎어버리는 행위) 포크된 블록에 블록을 계속 추가해가는 마이너도 있을 수 있다.

블록체인 포크 중에는 다수의 블록이 같은 높이를 가질 수 있다. 따라서 블록 높이는 고유한 식별자로 사용될 수 없다. 그래서 블록은 주로 고유한 식별자로 블록헤더의 해쉬(the hash of their header)을 사용한다(종종 바이트 순서를 거꾸로 한 16진수(the byte order reversed, and in hexadecimal)로 표시된다).

## Transaction Data (트랜잭션 데이터)

모든 블록은 적어도 하나 이상의 트랜잭션을 포함하고 있다. 포함하고 있는 트랜잭션 중 첫 번째 트랜잭션은 반드시 코인베이스 트랜잭션(coinbase transaction)으로 구성된다; 생성 트랜잭션(generation transaction)이라 불리기도 한다. 이 특별한 트랜잭션은 블록 보상을 취합하고 소비(collect and spend the block reward)할 수 있다(블록 생성 보상으로 주어지는 비트코인(block subsidy)과 블록 내에 포함하고 있는 트랜잭션으로부터 발생한 수수료들).

코인베이스 트랜잭션의 UTXO는 특별한 조건을 가지고 있다. 이 UTXO는 적어도 100번의 컨펌을 받아야 한다는 조건이다. 즉 100개의 블록이 추가로 더 생성되기 전에는 코인베이스 트랜잭션의 UTXO는 소비될 수 없다. 이 조건은 일시적으로 마이너가 트랜잭션 수수료(transaction fees)와 블록 생성 보상(block reward)을 소비할 수 없게끔 만든다. 이렇게 하는 건, 코인베이스 트랜잭션이 포함되어 있는 블록이 후에 블록체인 포크(block chain fork)로 인하여 실효블록이 될 수도 있기 때문(may later be determined to be stale)이다.

블록에는 코인베이스가 아닌 트랜잭션이 포함될 필요는 없지만, 마이너는 트랜잭션 수수료를 징수하기 위해 거의 항상 추가적으로 트랜잭션들을 포함한다; 이렇게 하면 블록 생성 보상(block subsidy, reward)과 트랜잭션 수수료를 둘 다 챙길 수 있으므로 마이너에게 이득이 된다.

코인베이스 트랜잭션을 비롯하여 모든 트랜잭션은 이진 rawtransaction 형식으로 블록에 인코딩 된다.\
이진 rawtransaction 형식은 해시되어 트랜잭션 식별자(txid)가 된다. 이러한 트랜잭션 식별자들(txids)로부터, 머클 트리(merkle tree)가 생성된다. 머클 트리를 생성하는 건 각 txid가 두 개씩 짝지어져 해시되는 과정으로 이루어진다. 만약 txid가 홀수개로 존재한다면, 짝이 없는 txid는 자신의 복사(a copy of itself)본과 함께 해시된다.

그렇게 해시된 것들끼리 다시 짝을 이루어 해시가 되는 과정을 반복한다. 마찬가지로 짝이 없는 해시는 스스로의 복사본과 해시한다. 단 하나의 해시가 남을 때까지 이 과정은 반복된다. 마지막까지 남은 단 하나의 해는 머클 루트(merkle root)라고 부른다.

예를 들어, 아래의 텍스트로 이루어진 그림(text diagram)과 같이 5개의 트랜잭션으로 이루어진 머클 트리(merkle tree)를 살펴보자.

```
       ABCDEEEE .......Merkle root
      /        \
   ABCD        EEEE
  /    \      /
 AB    CD    EE .......E is paired with itself
/  \  /  \  /
A  B  C  D  E .........Transactions
```

[Simplified Payment Verification](https://bitcoin.org/en/glossary/simplified-payment-verification) (SPV) 하위섹션에 설명했듯이, 머클 트리는 클라이언트가 스스로 트랜잭션을 검증할 수 있게 해준다. 검증이라는 건, 블록 헤더에 속한 머클 루트와 풀 노드(full peer)로부터 얻은 중간 해시들(intermediate hashes)을 통해 해당 트랜잭션이 블록에 포함되어 있는지 확인하는 것을 말한다. 풀 노드(full peer) 자체를 신뢰할지 말지를 고민할 필요는 없다: 블록 헤더를 위조하는 데에는 많은 비용이 발생하며, 중간 해시들은 결코 위조될 수 없으며 위조됐을 경우 검증과정에서 걸러지게 되기 때문이다.

> Simplified Payment Verification (SPV): 모든 블록을 다운로드 하지 않고 특정 거래가 블록에 포함이 되어 있는지 확인하는 방법으로서, 가볍게 비트코인을 사용하는 고객들이 많이 사용하는 방법이다.

예를 들어, 블록에 추가된 D트랜잭션을 검증하기 위해서 SPV 클라이언트가 필요한 건 단지 머클 루트(merkle root)와 C, AB, 그리고 EEEE 해쉬의 복사본이다; 먼저 C의 해쉬와 D의 해쉬를 붙여 CD를 만들고 AB와 CD를 해쉬하여 ABCD를 얻은 후 EEEE와 마지막으로 해쉬하여 머클 루트와 동일한지 확인하면 된다. 여기서 언급한 정보 외에 더 필요한 정보는 없다. 만약 위 그림에 표시된 다섯 개의 트랜잭션이 모두 최대 사이즈의 트랜잭션이었다면, 전체 블록을 다운로드 받는데 필요한 용량은 500,000 bytes이다 - 하지만 단지 세 개의 해쉬와 블록 헤더를 다운받는 건 140 bytes만을 요구한다; 따라서 위와 같은 검증과정을 거치는 것은 매우 효율적이다.

주의: 만약 같은 txids가 같은 블록 내에 발견되면, 머클 트리가 불균형하게 구현되는 방법(짝이 없는 해쉬를 복제하는 행위)으로 인해 머클 트리가 일부 또는 모든 중복이 제거된 블록과 충돌할 가능성이 있다. 사실 다른 트랜잭션이 동일한 txid를 같는건 실제로 일어날 수 없기 때문에, 정직하게 활동하는 소프트웨어에 그다지 큰 장애물이 되진 않는다. 그러나 유효하지 않은 블록의 상태가 캐쉬(cached)되었는지는 반드시 체크해야 한다; 그렇지 않으면, 중복이 제거된 유효한 블록이 같은 블록 해시와 머클 루트를 가질 수 있지만 캐시된 잘못된 결과로 거부되어 CVE-2012-245와 같은 보안 버그가 발생한다.

## Consensus Rule Changes (합의 규칙의 변경)

합의를 유지하기 위해서 모든 풀 노드들(all full nodes)은 블록들이 같은 합의 규칙(the same consensus rules)을 사용하는지 검증해야 한다. 하지만 때때로 새로운 기능을 도입하거나 네트워크 남용(network abuse)을 방지(prevent)하기 위해 합의 규칙은 변경된다. 새로운 합의 규칙이 구현되면, 업그레이드 하지 않은 노드가 이전 규칙(old rules)을 따르고 업그레이드한 노드는 새로운 규칙을 따르는 일정 기간이 있을 수 있고, 이것은 합의가 깨질 수 있는 두 가지 가능한 시나리오를 발생시킨다.

1. 새로운 룰을 따르는 블록은 업그레이드된 노드들(upgraded nodes)에게 인정되는 반면 업그레이드를 하지 않은 노드(non-upgraded nodes)에겐 거절당한다. 예를 들어, 새로운 트랜잭션의 기능(a new transaction feature)이 블록 내에서 사용되었다고 가정해보면: 업그레이드한 노드는 새로운 기능을 이해하고 인정(accept)하겠지만, 업그레이드를 하지 않은 노드는 해당 기능이 합의 규칙을 어기고 있다고 가정하여 거부(reject)할 것이다.
2. 새로운 합의 규칙을 위반하는 블록은 업그레이드된 노드들에게 거절당하는 반면 업그레이드를 하지 않은 노드들에게는 인정받을 것이다. 예를 들어, 공격적인 트랜잭션의 기능이 블록 내에 사용되었다고 가정해보면: 업그레이드한 노드는 이 기능을 새로운 룰을 위반하고 있다는 이유로 거절할 것이고, 업그레이드 하지 않은 노드는 해당 기능을 이전 규칙을 준수한다는 이유로 인정할 것이다.

업그레이드 하지 않은 노드가 새로운 규칙을 받아들이지 않는 첫번째 상황에서, 업그레이드 하지 않은 노드들(non-upgraded nodes)로부터 정보를 얻는 구식 채굴 프로그램(mining software)은 업그레이드 된 채굴 프로그램과 함께 동일한 블록 체인에 블록을 더해가는 작업을 거절하게 된다. 이러한 현상은 결국 영구적으로 분리된 체인을 만들게 되고 - 하나는 구식 노드(non-upgraded nodes)들이 사용하는 체인, 또 하나는 신형 노드(upgraded nodes)들이 사용하는 체인 - 이러한 현상을 우리는 하드포크(hard fork)라고 부른다.

![](https://2895310081-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-L9heHiETfq_9kxk2Qnu%2F-L9heQ85fDiVcp9UMbdd%2F-L9heUcXxvJ-JY6E8wgM%2Fen-hard-fork.svg?generation=1523332027017508\&alt=media)

두번째 케이스는 업그레이드 된 노드들로부터 거절되는 상황이다. 만약 업그레이드된 노드들이 다수의 해쉬율을 점유하고 있다면, 영구적으로 분기(fork)되는 상황을 막을 수 있다. 왜냐하면 구식노드들은 여전히 업그레이드된 노드들과 동일한 블록을 유효한 블록으로 받아들일 것이고, 이로 인해 업그레이드된 노드들은 계속해서 블록체인을 더 견고하게 만들어갈 수 있다. 이러한 상황을 소프트포크(soft fork)라고 한다.

> 아래그림을 보면 구식노드는 여전히 오래된 규칙을 따르는 블록만을 생성하겠지만, 오래된 규칙과 새로운 규칙을 함께 따르는 신형노드의 해시율(연산속도)이 더 높으므로 더 긴 블록체인을 형성할 것이고, 결국 가장 긴 체인이 됨으로써 구식 노드도 결국 이 블록체인을 유효하다고 판단하고 따를 것이다. 새로운 규칙만 따르는 블록이었다면 구식 노드가 받아들이지 않았겠지만 여전히 오래된 규칙 또한 포함하고 있으므로 구식 노드 또한 유효한 블록체인에 편승할 수 있다.

![](https://2895310081-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-L9heHiETfq_9kxk2Qnu%2F-L9heQ85fDiVcp9UMbdd%2F-L9heUclgwouDRtDHxdf%2Fen-soft-fork.svg?generation=1523332027035566\&alt=media)

포크는 블록체인에서 일어나는 실제적인 분리(an actual divergence in block chain)지만, 합의 규칙에 대한 변경은 종종 하드포크 혹은 소프트포크를 만들 가능성으로 설명된다. 예를 들어, "1MB를 초과하게끔 블록 크기를 늘리는 건 하드 포크를 필요로 한다." 이 예에서는 실제 블록체인 포크가 꼭 요구되는 건 아니지만 가능한 시나리오인 건 맞다.

합의 규칙의 변경은 다양한 방법으로 이루어질 수 있다. 비트코인의 첫 2년 동안은 사토시 나카모토가 몇몇 소프트 포크를 진행했다. 소프트포크의 진행은 새로운 규칙을 바로 적용하기 시작한 클라이언트에서 이전 버전과 호환되는(backwards-compatible change) 변경 사항을 배포함(releasing)으로써 이뤄졌다. BIP30과 같은 여러 개의 소프트포크는 새로운 규칙이 미리 설정된 시간 또는 블록 높이에서 시행되기 시작할 디데이(flag day)를 통해 활성화되었다; 즉, 바로 적용하면 부작용이 있을 수 있으니 미리 시간과 블록 높이에 대해 공지를 주는 것이다. 이러한 포크들은 User Activated Soft Forks (UASF)로 알려져 있는 디데이(flag day)를 통해 활성화되고, 포크의 성공 여부는 새로운 규칙을 디데이 이후 적용할 충분한 유저가 있는지에 달려있다.

그 후 소프트포크는 새로운 합의 규칙을 시행할 준비가 되었음을 알리기 위해 대다수 (75% 또는 95%)의 해시 비율(a majority of hash rate)을 기다렸다가 신호 임계값(signal threshold)이 전달되면, 모든 노드(all nodes)가 새 규칙을 시행하기 시작한다. 이러한 포크들은 Miner Activated Soft Forks (MASF)로 알려져 있으며 성공 여부는 마이너들에게 달려 있다.

참고 자료들: [BIP16](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki), [BIP30](https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki), 그리고 [BIP34](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki)는 소프트 포크로 실행된 변경내용들이다. [BIP50](https://github.com/bitcoin/bips/blob/master/bip-0050.mediawiki)은 업그레이드된 노드들의 기능을 임시로 다운그레이드하여 문제를 해결한 우발적인 하드포크(an accidental hard fork)와 임시적인 다운 그레이드가 철회되었을 때의 계획된 하드포크(an intentional hard fork)에 대해 설명한다. Gavin Andresen이 만든 [이 문서](https://gist.github.com/gavinandresen/2355445)는 미래의 규칙 변경이 어떻게 이루어질 것인가에 대한 개요를 다룬다.

## Detecting Forks (포크 탐지)

하드포크와 소프트포크가 일어나는 동안 구식 노드들은(non-upgraded nodes) 옳지 않은 정보를 사용하고 퍼뜨릴 수 있다. 그리고 이러한 과정은 경제적 손실을 야기할 수도 있다. 특히, 구식노드는 신형노드(upgraded nodes)에게 유효하지 않다고 간주되어 최상의 블록체인(universally-recognized best block chain)에 속할 수 없는 트랜잭션들을 중계하고 수락(relay and accept)할 수 있다. 구식 노드들은 또한 최상의 블록 체인에 추가되거나 곧 추가될 유효한 트랜재션들을 전파하는 과정을 거부할 것이고, 결국 불완전한 정보를 생산해낼 것이다.

비트코인 코어(Bitcoin Core)는 블록 체인의 작업 증명을 살펴봄으로써 하드포크를 탐지할 수 있는 코드를 포함하고 있다. 만약 구식노드가 유효한 체인으로 여겨지는 최적의 블록체인보다 6개이상의 블록에 대한 작업 증명을 보여주는 블록 체인 헤더를 수신하는 경우, 노드는 getnetworkinfo RPC 결과안에 있는 경고메시지를 보고하고 -alertnotify 명령을 실행한다(설정이 되어 있는 경우만). 이 과정은 프로그램을 작동하는 주체에게 구식 노드가 최적의 블록체인으로 전환할 수 없음을 경고한다.

> 최상의 블록체인(best blockchain)보다 6개이상의 블록을 가졌다는 것은 이미 분기(fork)가 일어난 상황이다. 따라서 지금 바로잡지 않으면 더이상 유효한 비트코인 블록체인시스템을 이용할 수 없는 것과 마찬가지다. 따라서 경고를 통해 현재의 분기(fork)를 바로잡고 다시 최상의 블록체인으로 편승할 수 있도록 도와준다.
>
> 최상의 블록체인보다 6개 이상의 작업증명이 이루어졌다는것은 최상의 블록체인이 따르는 합의규칙에 나와있는 블록생성 시간이 더 길어다는 뜻으로 해석할 수 있다. 따라서 위와 같은 상황은 업그레이드된 노드들의 프로토콜이 업그레이드 전의 블록생성시간보다 더 긴 생성시간으로 수정한 상황을 가정한 것으로 해석할 수 있다. 분기된 노드들이 소수의 해쉬파워를 갖고있는 상태에서 다수의 해쉬파워를 가지고 있는 최신 노드들이 만들어내는 블록체인보다 6개의 작업증명을 더 만들어내는 일은 상식적으로 있을 수 없다.

풀노드들(Full nodes)은 또한 블록과 트랜잭션의 버전 번호(version numbers)를 확인할 수 있다. 만약 몇몇 최신 블록들의 블록과 트랜잭션의 버전 번호(the block or transaction version numbers)가 자신(non-upgraded node)이 사용하는 버전 번호보다 크다면, 자신이 현재의 합의규칙(current consensus rules)을 따르고 있지 않다고 유추할 수 있다. 비트코인 코어는 이 상황을 getnetworkinfo RPC과 -alertnotify 명령을 통해 노드에게 보고한다(설정이 되어 있을 경우만).

> getnetwrokinfo RPC를 호출하면 현재 사용중인 네트워크와 관련된 여러가지 정보를 얻을 수 있는데, 그 중 warning이라는 string 자료형으로 된 field에 경고 내용이 기록되어 있다.

위의 두 경우 모두, 현재의 합의 규칙을 사용하지 않는 노드(non-upgraded nodes)에서 오는 경우 블록 및 트랜잭션 데이터를 신뢰해서는 안된다.

풀노드에 연결하는 방식으로 동작하는 SPV 클라이언트는 몇몇 풀노드들에게 연결함으로써 하드포크를 탐지할 수 있다. 또한 풀노드들이 같은 체인에 존재하고 같은 블록 높이를 가지고 있는지도 확인할 수 있으며, 몇몇 블록들을 임의로 더하거나 뺌으로써 전송지연(transmission delays)과 실효블록들(stale blocks)을 알아낼 수도 있다.

> SPV클라이언트는 모든 블록기록들을 가지고 있지 않기 때문에 풀노드들에게 의존할 수밖에 없다.

또한 SPV 클라이언트는 블록 및 트랜잭션 버전 번호 증가를 모니터링하여 수신 트랜잭션을 처리하고 현재 합의 규칙을 사용하여 새 트랜잭션을 생성하도록해야한다.
