본문 바로가기
학교공부/[블록체인]

[블록체인] - 비트코인_채굴

by 윈디개 2025. 12. 11.

1. Node Behavior

 비트코인의 채굴에 대해서 본격적으로 정리하기 전에, 비트코인 시스템 내에서 Node들이 어떤 행동을 취하는지 먼저 짚고 넘어가려고 한다.

 

 비트코인 시스템 내에서 노드들은 다음과 같은 특징을 지닌다.

  • 모든 노드들은 동등하다. 즉, 마스터 노드가 존재하거나 계층 구조가 존재하지 않는다. 
  • P2P 방식의 TCP 위에서 동작하고, random하게 P2P가 매칭된다.
  • 새로운 노드는 언제든 네트워크에 들어올 수 있고 떠날 수 있다.
  • 들어오고 싶다면, 간단한 메시지를 seed node에 보내는 것으로 시작할 수 있다.
    • seed node는 DNS에 등록되어 있다.(seed.bitcoinstats.com 또는 dnsseed.bitcoin.dashjr.org)

예를 들어, 트랜잭션을 publish하기 위해서는 비트코인 전체 네트워크에 flooded되어야 한다. 즉, 전체 네트워크에 broadcast해야 된다는 것이다. 다음과 같은 상황을 예를 들어 보자.

  • Alice는 Bob에게 돈을 지불하고 이 트랜잭션을 그녀의 peer에게 전달하려고 한다.
  • 해당 트랜잭션을 받은 peer들은 트랜잭션을 검증하고 accept하고 트랜잭션을 이어서 전달할지 결정한다.
    • 트랜잭션이 현재 블록체인에 유효한 트랜잭션인지 검증해야 한다.
    • 끌어오는 output이 UTXO인지 검증한다.
    • 진짜로 새로운 트랜잭션인지 검증한다.
    • 트랜잭션의 스크립트가 유효한지 검증한다.(recursive하게 사용되지 않았는지, 다른 script를 호출하지는 않았는지 등등)
  • 노드들은 위 검증을 마쳤으면, 그들의 트랜잭션 pool에 해당 트랜잭션을 넣는다. 만약, 이때, 다른 어떤 노드로부터 그 트랜잭션이 이미 pool에 존재한다고 듣게 된다면, 그 트랜잭션은 broadcast하지 않는다.

 

그런데, 이런 트랜잭션들은 트랜잭션이 발생한 지점에서 가까운 노드들에 당연하게도 더 빨리 도달한다. 비트코인 시스템에서는 트랜잭션이 어디서든 발생할 수 있기 때문에 트랜잭션이 발생한 지점에서 얼마나 가까운지에 따라서도 트랜잭션 pool에 들어오는 순서가 다를 수 있다. 이런 경우를 이용해 다음 상황이 일어날 수 있다.

  • Alice가 동일한 UTXO로 Bob과 Charlie에게 동시에 지불하려고 한다. 즉, Double spend를 하려고 한다.
  • 어떤 노드들은 Alice가 Bob에게 지불하는 트랜잭션을 먼저 받고, 어떤 노드들은 Alice가 Charlie에게 지불하는 트랜잭션을 먼저 받는다.
  • 한 노드가 전자의 트랜잭션을 먼저 받고 검증을 마친 뒤, 트랜잭션 풀에 전자의 트랜잭션을 저장한다.
  • 그 후에 후자의 트랜잭션이 들어와도 이 트랜잭션은 drop한다.(double-spend로 의심하기 때문에)
  • 노드들은 일시적으로 트랜잭션에 대해 불일치가 생길 수 있다.

그러나 이 상황은 일시적인 현상일 뿐이다. 이 트랜잭션(Alice > Bob 또는 Alice > Charile 둘 중 하나 어느 것이든)이 포함된 블록이 채굴되어 네트워크에 broadcast되면, 이 블록에 포함된 트랜잭션이 유효하다고 인정되며, 이 블록을 전달받은 노드들은 해당 트랜잭션을 본인의 pool에서 제거한다. 결국 모든 노드의 트랜잭션 풀은 다시 일치하게 된다.

 

- Cheating

 이런 상황을 한 번 가정해보자. 위의 상황과 동일하게, Alice라는 사용자가 Bob에게 보낸 트랜잭션이 블록에 포함되어 채굴되었다. 그리고, 블록체인의 longest-chain에 등록되었다. 그런데, 만약, Alice가 Bob에게 보낸 트랜잭션을 취소하고 이를 Charlie에게 보낸 트랜잭션으로 바꿔치기를 시도한다고 가정해보자. 이 행위 자체를 cheating이라고 한다.

 

그런데, 다음 그림을 참고해서 블록체인의 블록 구조를 한 번 다시 떠올려보자.

블록은 다음과 같이 구성된다.

  • 이전 블록 헤더의 해시값
  • Timestamp
  • Difficulty
  • Nonce
  • Merkle Root
  • Transactions

이때, 이전 블록 헤더의 해시값 ~ Merkle Root까지 한 블록의 header가 되며, 이전 블록 헤더의 해시값을 통해 이전 블록을 가리키는 해시 포인터가 된다. 근데, 이 헤더 값 중, Merkle Root 해시값은 트랜잭션들이 데이터로 들어와 계산되는 root값을 해시시킨 것으로, 트랜잭션의 순서에 따라서도 해시값이 변하게 된다.

 

 따라서, 위에서 가정한 상황처럼 트랜잭션을 바꾼다는 것은, 결국 블록 해시값이 바뀌게 되는 것이고, 이전 블록이 가리키고 있는 해시 포인터가 끊기게 되어 체인 구조가 깨지게 된다.

 

 그렇기에, 트랜잭션만을 바꾸는 것은 불가능하고, 해당 cheating을 성공시키기 위해서는 바꾸려는 트랜잭션을 포함한 블록에서 분기를 일으켜서 그 블록부터 현재 채굴된 블록까지의 블록의 해시값을 다 계산해서 longest-chain으로 만드는 방법 밖에 존재하지 않는다. 이는 엄청난 자원 낭비 및 투자 대비 효율성이 나오지 않기 때문에 대부분의 채굴자는 정직하게 채굴하는 것이 경제적으로 합리적이다.

 

- Block Structure

위의 표는 블록의 전체 구조와 블록 헤더의 구조를 정리한 것이다. 블록 구조는 계속해서 다뤄왔지만, 특징들에 대해서 다시 정리해보면 다음과 같다.

  • 블록 헤더 해시값: Digital Fingerprint, 두 번의 SHA256 알고리즘을 적용시킨 값(결과: 32byte 크기의 블록 해시값)
  • 첫 번째 블록(gensis 블록): height 0이며, 이후 채굴된 블록들은 차례대로 이전 블록의 top 위에 쌓이며, height는 1씩 커지게 된다.
    • 순간적으로 블록에 분기가 생길 수 있으며, 이 이유 때문에 height에 한 블록만 존재한다는 정의는 하지 않는다.

실제 블록체인의 모습을 나타내면 아래 그림과 같다.

+) 추가로, Merkle tree에서 left-most의 leaf에는 항상 coinbase transaction이 들어간다. 즉, 채굴 보상을 생성하는 트랜잭션이 항상 첫 번째 위치에 존재한다.

 

++) 만약, 트랜잭션을 검증한다고 했을 때, 다음 그림과 같은 과정을 거치게 된다.

  • Hk에 속하는 트랜잭션을 검증하려고 할 때, 위 그림처럼 tree를 차례대로 따라가면 된다.
  • 파란색으로 칠해져 있는 노드들은 해시값만 가져다 쓰면 된다는 것이고, Hk+Hl, Hkl+Hij, Hijkl+Hmnop, Habcdefgh+Hijklmnop를 차례대로 계산해 root의 해시값과 일치하면 유효한 트랜잭션이다.

2. Mining

이제 본격적으로 채굴에 대해서 정리해 보려고 한다. 오늘날 채굴은 많은 사람들이 보상(reward)을 얻기 위한 과정으로 인식하지만, 사실 채굴의 근본적인 목적은 새로운 코인을 만드는 것이 아니다.

 

채굴은 트랜잭션이 검증되었는지, 그리고 유효한지를 확인하기 위한 탈중앙화된 합의(consensus) 메커니즘이다. 이 채굴 과정을 통해 비트코인은 중앙 기관 없이도 신뢰할 수 있는 거래 기록을 유지할 수 있고, 네트워크 전체가 하나의 합의에 도달할 수 있게 된다.

 

채굴 과정은 다음과 같이 이루어진다.

  • 블록에 포함된 트랜잭션들은 confirmed(확정)되었다고 여겨진다.
  • 채굴자들은 새로운 블록을 채굴하면 두 가지 형태의 보상을 받는다.
    • coinbase reward(=block reward): 새로운 블록이 생성될 때 발행되는 새로운 비트코인
    • transaction fees: 블록에 포함된 트랜잭션들의 수수료
  • 채굴자들은 위와 같은 보상들을 얻기 위해 암호학 해시 알고리즘 수학 문제를 풀기 위해 경쟁한다.
    • 위 과정을 Proof-of-Work(PoW)라고 한다.
  • 이러한 과정들이 비트코인 시스템의 보안과 무결성을 유지하는 데 중요한 역할을 한다.

 이때, 모든 트랜잭션은 transaction fee가 있는 것이 좋다. 채굴자들은 보통 수수료가 높은 트랜잭션을 우선적으로 블록에 포함시키기 때문에, 수수료가 없는 트랜잭션은 블록에 포함되지 못할 가능성이 높다.

 

 물론, 오늘날은 채굴보상 중 coinbase reward가 존재해 transaction fee가 없는 트랜잭션도 포함시키도 한다. 그렇지만, 비트코인 총 발행량은 한정되어 있기 때문에 시간이 지남에 따라 블록 보상은 주기적으로 반감된다. 그 결과 채굴자들은 점차 transaction fee만으로 보상을 얻는 구조로 변하게 될 것이다.

 

+) 현재 coinbase reward가 3.125BTC로 transaction fee에 비해 월등히 높지만, 장기적으로 비트코인의 희소성이 높아지고 가치가 상승하게 되면 transaction fee 자체만으로도 충분한 보상이 될 것으로 예측된다.

 

- 채굴자들이 하는 일

그럼 채굴자들이 채굴을 위해 해야될 일은 무엇이 있을까? 간단하게 정리해보면 다음과 같다.

  • listen for the transactions
  • maintain blockchain listen for new blocks
  • assemble a candidate block
  • 채굴하려는 블록이 유효하게 만들기 위해 nonce값 찾기
  • 채굴한 블록이 accept되기를 기다리기
  • 다른 채굴자들이 블록을 accept하면 보상 받기

즉, 위 일들을 두 가지 카테고리로 분류하면 다음과 같다.

  • 트랜잭션과 블록이 유효한지 확인하기: healthy 비트코인 네트워크를 유지하기 위해 필수
  • 유효한 블록 찾기 경쟁

- Finding Valid Blocks

 위의 두 가지 일 중, 채굴자들이 핵심적으로 해야 할 일은 바로 유효한 블록을 찾는 것이다. 그럼 이 유효한 블록을 찾는 일은 어떻게 이루어질까? 다음과 같은 과정으로 이루어진다.

  1. 유효한 트랜잭션의 set을 Merkle tree로 컴파일을 한다.
  2. 이전 블록의 해시값을 헤더에 포함시켜 해시 포인터를 가리키고, 블록을 생성한다.
  3. target number보다 작은 값을 만들기 위한 hash-puzzle를 풀기 위해서 적절한 nonce값을 찾는다. 즉, 블록 헤더 전체의 SHA256 output이 difficulty가 나타내는 target 보다 작아야 유효한 블록으로 인정된다.
  4. 채굴 난이도는 비트코인에서 16진수 target 값으로 표현된다. 유효한 블록을 채굴하려면, SHA256 결과가 이 target 보다 작은 값이어야 한다.

+) 추가로, Nonce 값만을 조정하며 2^32번의 시도를 한다고 했을 때도 해시 퍼즐을 못 푸는 경우도 많다. 이럴 때는 다음과 같은 방법으로 해시값을 다시 조정할 수 있다.

  1. coinbase transaction을 바꾼다. coinbase transaction은 채굴자가 임의로 정할 수 있는 트랜잭션이기 때문에 이를 변경하면 된다.
    • coinbase transaction을 변경하면, 블록 헤더에 있는 merkle root의 해시값도 변경된다.
    • merkle tree root의 해시값이 변경되면, 블록 헤더의 해시값도 변경된다.
    • 이 변경된 해시값으로 다시 Nonce값을 조정하며 2^32번의 시도를 하며 적절한 해시값을 찾으면 된다.
    • 이때, coinbase transaction script는 2 ~ 100 바이트의 데이터를 포함할 수 있으며, 채굴자들은 이 공간의 데이터를 변경시키며 시도한다.
      • 따라서 이론적으로 최대 2^800 * 2^32번 시도를 할 수 있다.
  2. 헤더에는 timestamp가 존재하는데, timestamp는 초 단위로 변경된다. 이때, 계산을 시도하다가 timestamp가 바뀌면, 바뀐 timestamp를 헤더에 포함시키고 다시 Nonce를 시도해도 된다.
    • 과거에는 hash poewr가 충분히 세지 않았기 때문에 timestamp를 변경시키는 방법도 사용하긴 했다.
    • 그러나, 현재는 2^32(약 40억 번)을 시도하는 데 1초도 걸리지 않을 정도로 hash power가 매우 커졌기 때문에, 이러한 timestamp를 변경시키는 시도는 사용할 필요가 거의 없다.

그럼 채굴에 대해서 다음과 같은 의문증이 생길 수도 있다.

  • 모든 채굴자들이 똑같은 해시 퍼즐을 푸는 것 아닌가?
  • nonce값을 증가시키며 똑같은 해시 퍼즐을 푸는 것이라면, 해시 파워가 가장 쎈(빠른) 채굴자가 항상 이기는 것이 아닌가?

이러한 의문증의 답은 No이다. 그 이유는 다음과 같다.

  1. 채굴자들은 서로 다른 transaction set들을 서로 다른 순서로 포함시켜 결국은 서로 다른 해시 퍼즐을 푸는 것과 같다.
    • 각 노드는 자신이 보유한 pending transaction pool이 약간씩은 차이가 나기 때문에, 블록에 넣는 트랜잭션의 구성과 순서는 동일할 가능성은 매우 낮다.
  2. 만약 두 채굴자가 동일한 transaction set에, 동일한 순서로 해시 퍼즐을 푼다고 해도, 블록은 아마 다를 가능성이 크다.
    • 그 이유는 각자의 coinbase transaction 때문이다. coinbase transaction에 output에는 채굴자 각자의 주소가 있을 것이고, 이 주소가 merkle root를 계산할 때 포함되기 때문에 두 채굴자의 Mekrle root는 다를 수 밖에 없다. 따라서 결국 다른 블록에 대해 해시 퍼즐을 푸는 것이다.

- Dtermining the difficulty

 그럼, 이 해시 퍼즐의 난이도는 어떻게 정할까? 지난 글에서도 정리했지만, 매 2,016 블록마다 난이도를 조정하게 되어있다. 공식은 다음과 같다.

  • next_difficulty = (previous_difficulty * 2016 * 10 minutes) / (time to mine last 2016 blocks)

식을 해석해보면, 10분마다 채굴하는 것이 이상적이기 때문에,

  • (현재 난이도로 2016블록을 채굴할 때 이상적인 시간)을
  • (최근 2016 블록을 채굴하는데 걸린 시간)으로 나눈 비율만큼

다음 난이도를 조정하게 된다.

 

이렇게 난이도를 조정함으로써 해시 파워가 갑자기 증가하거나 감소하더라도, 평균 블록 생성 시간을 다시 10분에 가깝게 유지할 수 있다.