노드 : p2p 네트워크를 구성하는 하나의 소프트웨어 (호스트) 를 말한다. 모든 노드는 동등하다.
비트코인의 정신이 탈 중앙화이기 때문에 특정 노드에게 더 권한을 준다거나 하는 것이 없다.
p2p 네트워크는 TCP를 기반으로 만들어진다.
그리고 이 네트워크에는 새로운 노드가 언제든 참여하고 떠날 수 있다.
노드로 참여할 때는 특정 사이트에서 비트코인을 돌리고 싶은 데 내 이웃 노드가 되어달라고 요청하고, 요청이 수락되면 연결을 짓는 식으로 네트워크에 참여하게 된다. (요청 보내는 대상 노드를 가리켜 시드 노드라고 한다.)
노드의 행동
각 노드의 행동 방식을 보기에 앞서 앨리스가 밥에게 비트코인을 보내는 트랜잭션을 만들었다고 해보자.
그러면 이 트랜잭션은 전체 비트코인 네트워크에 퍼져야만 한다.
앨리스는 월렛 프로그램의 도움으로 밥에게 비트코인을 보내고, 남은 잔액을 자신의 계좌로 보내고, 적절한 수수료를 책정하는 트랜잭션을 생성한 뒤, 비트코인 네트워크 전체에 뿌린다.
그러면 이 트랜잭션을 수신한 노드는 이 트랜잭션이 유효한지 (UTXO에서 끌어다 쓴 게 맞는지, lock time 은 잘 지켰는지, 스크립트가 실행 가능한지 = 비트코인에서 사용하는 방식의 스크립트인지 등) 검증한다.
또 이 트랜잭션이 내가 이미 본 트랜잭션인지도 확인한다. P2P 네트워크라서 내가 이미 본 트랜잭션을 다른 경로를 통해 또 받을 수 있다.
이럴 때는 중복으로 받은 트랜잭션을 무시한다.
그리고 이런 검증이 모두 끝났다면 이 트랜잭션을 풀에 넣는다.
트랜잭션 풀에는 블록에 들어갈 수 있는 대상 트랜잭션들이 저장되어 있다.
만약 내가 받은 트랜잭션이 이미 나의 풀에 들어있는 트랜잭션이라면 그 트랜잭션은 브로드캐스트 하지 않는다.
반면 나의 풀에 없는 트랜잭션이라면 풀에 추가하고 브로드캐스트까지 한다.
그런데 각각의 노드마다 트랜잭션을 수신하는 타이밍도 종류도 다를 수 있기 때문에
어떤 특정 시점에서 스냅샷을 찍으면 각 노드의 pool 은 조금씩 다를 수 있다.
이때 경쟁 상태가 발생할 수도 있다.
앨리스가 자신이 가진 같은 코인을 찰리에게 지불하는 트랜잭션과 밥에게 지불하는 트랜잭션을 생성해서 둘 다 뿌렸다고 해보자.
이때 블록 안에는 둘 중 하나의 트랜잭션만 유효한 것으로 간주되어 들어갈 수 있다.
그래서 각 노드마다 어떤 트랜잭션이 유효한지 서로 다르게 판단할 수 있다.
1. 트랜잭션의 도착 시점이 서로 달라서 내가 포함시킨 트랜잭션이 다른 노드의 블록에는 포함되지 않았을 수 있고
2. 하나의 주소에서 서로 다른 곳으로 나가는 트랜잭션 2개에 대해 맞다고 인정하는 트랜잭션이 다를 수 있다.
그래서 블록에 들어가는 트랜잭션은 다를 수 있고, 경쟁 상태에 대해서는 둘 다 서로 다른 블록으로 채굴이 되었다고 해도 두 트랜잭션이 모두 승인될 수는 없기 때문에 둘 중에 한가지 브랜치 블락이 길게 늘어나는 순간 그 블록에 있는 트랜잭션이 유효한 것으로 판정된다.
따라서 단기간에는 의견 불일치가 발생하더라도 장기적으로 보면 의견이 일치할 것이다.
그리고 만약 노드의 pool 에 들어있는 트랜잭션이 채굴이 되었다면 그 트랜잭션을 pool 에서 제거하고,
내가 찰리를 밀고 있었는데, 밥으로 보내는 트랜잭션이 채굴되어 길게 이어진다면, 찰리 역시 pool 에서 제거할 것이다.
블록을 생성할 때도 비슷한 상황이 발생한다.
내가 이미 하나의 100번 블록에 이어붙이는 101번 블록을 만들고 있었는데, 다른 100번 블록이 만들어졌다고 소식이 들려오면, 나는 굳이 그 블록 뒤에 다시 이어서 붙일 필요가 없다. 이미 기존 블록에 대해 이어붙이려고 해시 퍼즐을 풀고 있었는데, 새로운 블록으로 넘어가서 지금까지 연산했던 시간을 버릴 필요는 없기 때문이다.
또한 채굴하는 과정에서는 이전 블록을 검증하는 과정도 거친다.
먼저 블록 헤더를 보고 그 헤더의 값이 채굴 당시 타겟 넘버보다 작은지 검증하고, 그 블록에 포함된 트랜잭션들이 유효한지도 검증한다.
그림으로 보면 위와 같이 블록이 구성되어있다.
위 그림은 블록의 구조와 블록 헤더의 구조를 나타낸다.
블록에는 블록 크기, 블록 헤더, 트랜잭션 수, 각 트랜잭션 정보가 들어있고
블록 헤더에는 버전, 이전 블록 해시, 머클 트리 루트, 블록 생성 시간, 채굴 당시 난이도, 채굴에 성공했던 난스값이 들어있다.
블록을 특정할 때는 해시를 이용해서 특정하거나, 높이를 이용해서 특정할 수 있다.
블록 해시는 블록 헤더를 sha 256 알고리즘으로 두 번 해싱한 결과이다.
머클 트리 역시 2번 해시해서 구한다.
리프 노드에서부터 해시값을 차례대로 올려서 합치고 해시하는 과정을 반복하여 구한다.
만약 특정 트랜잭션이 이 머클트리에 제대로 들어있는지 확인하고 싶을 때는 다음과 같이 확인할 수 있다.
Hk를 확인한다면 파란색으로 칠해진 이미 계산된 해시값들을 이용해서 점선으로 표시한 블록의 해시값을 계산한다.
최종적으로 root 노드의 해시값이 내가 계산한 값과 같다면 Hk 가 들어있음을 확인할 수 있다.
(그러면 머클 트리 중간에 있는 계산값도 다 저장을 하는건가?)
Mining
채굴은 한마디로 비트코인 네트워크에서 일어나는 모든 거래 (트랜잭션) 에 대한 검증과정 (정산) 과 같다.
채굴 난이도의 결정 (Determining the difficulty)
너무 여러번 정리했지만, 강의록에 반복해서 나와서 또 정리한다..ㅎㅎ
채굴 난도는 2016 블록이 채굴될 때마다 조정된다.
난이도를 결정하는 수식은 다음과 같다.
하나의 블록의 채굴 기준 시간은 10분이다. 따라서 2016 블록을 채굴하는 시간은 2016 * 10 이다.
이 값을 지난 2016 블록이 채굴되는 데 걸린 시간으로 나누면, 기준 시간 대비 어느 정도의 채굴 시간이 소요되었는지 알 수 있다.
예를 들어 하나의 블록을 채굴하는데 걸린 실제 시간이 평균 9분이었다고 하면, 2016 * 9 분의 시간이 실제로 소요되었을 테니,
10/9 라는 값이 나올 것이고, 이 값이 next_difficulty 가 된다.
이 값은 1보다 크므로, 이전보다 채굴 난이도를 올리도록 설정한다.
이때 이 식을 구할 때 앞에 previous_difficulty 가 곱해진다.
최초에는 기준이 10분이므로 1을 곱했다고 가정하고, 이후에 평균 9분이 걸렸다고 해보자.
만약 previous_difficulty 를 적용하지 않은 상태에서 똑같이 2016 * 10 을 2016 * 9 로 나누면 똑같이 10/9 로 같은 난이도가 되어버린다. (난이도를 10/9로 높였는데도 여전히 평균 9분에 하나씩 채굴된다면 난이도를 더 올려야 하는 상황인데 말이다.)
따라서 previous_difficulty 를 곱해주어 기존의 난이도에 대비하여 조절하도록 한다.
만약 기존의 난이도인 10/9 가 곱해져있다면 (10/9 * 2016 * 10) / (2016 * 9) = 100/81 로 이전보다 난이도가 조금 더 상승하게 된다.
만약 난이도를 올렸더니 11분에 하나씩 채굴되었다면,
(10/9 * 2016 * 10) / (2016 * 11) = 100 / 99 로 10/9 와 비교하여 난이도가 1에 가까워지도록 줄어든다.
difficulty 는 직접적으로 다음과 같이 해석할 수 있다.
만약 difficulty = 24조 라면, 하나의 유효한 블록을 채굴하는데 24조 번의 해시 계산이 필요하다는 뜻이다.
(난이도가 해시 계산 횟수라고 한다면 위에서 내가 이해한 예시는 10분동안 해시 계산을 1번한다는 뜻인가...?
=> 근데 맞는 것 같다. 1개 블록 채굴에 24조 번의 해시 연산이 필요하다 = 1개 블록 채굴에 10분이 걸린다. = 10분동안 24조 번의 해시 계산을 한다.)
이 값도 매우 큰 것 같지만, 요즘은 하나의 블록을 채굴할 때 대략 70조 번의 해시 계산이 필요하다고 한다..
각각의 채굴자는 독립적으로 difficulty 를 계산하고, 다른 채굴자가 채굴한 블록을 검증할 때, 내가 계산한 difficulty 와 일치하는지 확인한다. (그럼 우연히 한번에 들어맞아서 10분도 안 걸려서 채굴에 성공해봤자 다른 노드들이 인정을 안해주는 건가?)
다음 그림은 비트코인의 채굴 난이도 변경을 보여주는 그래프이다.
초록색 선이 지난 2016 블록의 평균 해시 연산 비율을 보여준다.
이 값에 맞춰서 2주마다 빨간색 선이 변동하는 것을 알 수 있다.
이 그래프는 블록 하나가 채굴되는데 걸리는 시간을 나타낸 그래프이다.
이 그래프에서는 녹색 선이 다음의 난이도를 나타내고, 파란색 선이 2016 블록의 평균 채굴 시간을 나타낸다.
점점 2주가 되어갈 때마다 평균 채굴 시간이 줄어들고, 난이도를 나타내는 빨간색 그래프가 높아지면, 평균 채굴 시간도 다시 증가했다가 점점 줄어드는 과정이 계속 반복되는 것을 볼 수 있다.
채굴 장비 역시 비트코인이 점점 유명해지면서 위와 같이 발달하였다.
처음에는 CPU를 사용해서 집에 있는 컴퓨터만으로도 채굴이 가능했으나, 나중에는 단순 연산이 많은 해시 연산의 특성상 CPU대신 GPU가 더 효율적이라 GPU를 사용하여 채굴하도록 발전했다.
나중에는 해시 계산 자체에 효율성을 높이는 전용 하드웨어를 FPGA로 만들어서 채굴했다.
FPGA는 하드웨어 회사가 만들어 둔 제품을 조립해서 해시 계산에 유리하게 조립해서 만드는 방식이었다면,
ASIC은 아예 해시 계산에 맞는 전용 하드웨어를 만들어서 채굴하는 수준에까지 다다르게 되었다.
그래서 24시간 이런 전용 기계를 계속 돌리는 채굴 공장 (마이너 풀) 이 등장하게 되었다.
위 그래프는 2022년의 마이너 풀 분포 현황을 나타낸 그래프이다.
이 풀에 속한 집단은 서로 nonce 바운더리를 나눠서 해시 계산을 병렬적으로 하고, 채굴 보상은 공평하게 나눠갖는 시스템으로 동작한다.
거의 절반에 가까운 Unknown 풀이 개인 채굴자를 말하고 AntPool, F2Pool 이 꽤 유명하다.
만약 이 두 pool 이 힘을 합쳐서 비트코인 시스템을 흔들고자 한다면 흔들 수도 있겠지만, 실제로 그런 일이 일어난 적은 없었다.
(자기들이 연합해서 채굴 보상을 먹고 있는데, 자신이 이익을 보고 있는 시스템을 흔들 이유가 없기 때문이다.)
'CS > 블록체인' 카테고리의 다른 글
[블록체인] 15. Lightning Network (1) : 개요 (0) | 2024.12.01 |
---|---|
[블록체인] 14. 비트코인 Consensus (2) | 2024.11.30 |
[블록체인] 12. 비트코인 script (2) (3) | 2024.10.25 |
[블록체인] 12. 비트코인 script (1) (0) | 2024.10.25 |
[블록체인] 11. 비트코인 트랜잭션 (1) | 2024.10.25 |