BTC ; 사토시의 의지

SungJunEun·2021년 9월 25일
1

Case Studies

목록 보기
1/6
post-thumbnail

본 글은 비트코인 백서을 기반으로 저만의 방식으로 이해하기 쉽게 정리한 글입니다. 하지만, 해당 내용 전체를 다루지 않을뿐만 아니라 포함되어 있지 않은 내용들도 설명을 위해 포함되어 있으므로 주의를 바랍니다. 저 또한 블록체인을 막 공부하기 시작한 사람으로써 오류와 보완할 점 및 피드백 주시면 큰 도움될 것 같습니다!🐶


해결하고자 하는 문제는

처음 비트코인을 제안한 사토시 나카모토는 기존 금융권이 가지고 있는 문제들을 해결하려고 하였다. 대부분의 문제들은 제 3자가 신뢰의 주체가 되어 거래의 중개를 돕기 때문에 일어나는 문제들이다.

예를 들어,

  • 높은 거래 수수료
  • 최소 거래 사이즈의 존재
  • 불가피한 소수의 사기 거래 용인
  • 거래자들에 대한 과도한 정보 수집

등이 있다.


비트코인은 transaction의 연속이다.

transaction, not balance

은행과 달리 비트코인에서는 각자의 잔고라는 것이 엄밀히 따지자면 없다. 비트코인은 현재까지 일어난 모든 합법적 transaction들을 블록체인 상에 기록한다. 그래서 비트코인 지갑에서의 잔고라는 것은 모든 기록된 transaction들 중 나의 주소로 전송되었지만 아직 사용되지 않은 비트코인의 합을 계산해서 보여주는 것이다. 이러한 사용되지 않은 거래들을 unspent transaction output, UTXO라고 한다.

input, output & amount

transaction에 사용되는 UTXO를 transaction input이라하고, transaction으로 생성되는 UTXO를 transaction output이라고 한다. 예를 들어 내가 과거에 Alice에게 1btc를 받았고, 현재 Ben에게 1btc를 보내려고 한다고 하자. 나와 Ben의 transaction에서 input은 내가 보낼려고 하는 btc를 받은 곳이다. 위의 예에서는 나와 Alice 사이에 이뤄진 transaction이 input이다. output은 내가 보낼려는 곳, Ben의 주소이다. amount는 보낼려고 하는 btc의 양이다.

input&output과 관련된 특징은 하나의 비트코인 transaction에 여러개의 input과 output이 가능하다는 점이다. input의 갯수는 하나에서부터 수십개, 수만개까지 이론적으로 가능하다. 예를 들어 내가 Charlie에게 2btc를 보내려 할 때 나는 Alice에게 1.5btc를 받은 UTXO와 Ben에게 0.5btc를 받은 UTXO, 이 2개를 input으로 사용 가능하다. Output의 경우에는 일반적으로는 2개인 경우가 대부분이다. 하나는 내가 보내려는 사람, 그리고 하나는 다시 나에게로 돌아오는 잔돈이다.


돈의 소유권은 어떻게 증명하는가

모든 transaction에는 digital signature이 필요하다. 나의 digital signature은 나의 private key를 이용하여 만들 수 있고, 나의 public key를 이용하여서 나의 것이 맞는지 확인할 수 있다.

내가 Alice에게 1btc를 보낼 떄 개념적으로 transaction이 이뤄지는 과정은 다음과 같다.

  1. 나는 Alice에게 보내는 transaction에 Alice만 풀 수 있는 자물쇠를 건다.
  2. transaction이 이뤄지는 순간부터 이 거래는 UTXO 상태가 된다.
  3. 이후 시간이 지나 Alice가 나에게 받은 1btc를 transaction input으로 사용하여서 transaction을 진행시키기 위해서는 내가 건 자물쇠를 풀어야 한다.
  4. 이 자물쇠를 풀기 위해서 Alice 자신의 digital signature와 public key를 열쇠로 사용한다.
  5. 해당 UTXO를 사용하려는 사람이 Alice인 것이 증명되었으므로 정상적으로 Alice는 이후 거래를 실행할 수 있게 된다.

    실제로 transaction을 확인할 때는 script라는 프로그래밍 언어를 실행시켜서 확인한다. 위 예제에서 자물쇠 역할을 하는 것이 scriptPubKey이고 열쇠 역할을 하는 것이 scriptSig이다. 더 심화된 내용은 아래 링크를 참고하길 바란다.

Mastering Bitcoin - 5.Transactions

double-spend 문제 해결하기

Digital signature은 btc의 소유권 문제는 해결해주지만, double-spend 문제는 해결하지 못한다.

double-spend 문제는 다음과 같다.
나의 총 balance(나에게 해당하는 UTXO의 합)에 1btc가 있는 상황에서 나는 Alice에게 1btc를 보내는 transaction를 한 후 Ben에게도 1btc를 보내는 transaction를 할 수 있다. 그 이유는 Alice와 Ben은 내가 자신말고도 다른 사람에게도 btc를 보냈는지 알 수 없기 때문이다.

이 문제를 해결하기 위해서 비트코인은 2가지 규칙을 정한다.

  • 모든 transaction들은 공개적으로 발표된다.
  • 모든 참여자(노드)들이 하나의 기록으로 합의할 수 있는 시스템이 필요하다.

위 규칙들이 만족된다면 위의 예제에서 내가 Ben에게 1btc를 보내는 transaction을 진행시키려 할 때, Ben은 내가 이미 가지고 있는 1btc를 Alice에게 보냈다는 transaction을 확인 후 나의 transaction이 잘못되었다는 것을 알 수 있다.

Proof-of-Work

위 예제에서 Ben은 나의 transaction을 수락하기 전에 대부분의 노드들이 그 transaction이 유효하다는 증명이 필요하다. 그리고 그 증명방식이 proof-of-work, POW이다. POW는 말 그대로 직접 자원과 시간을 투자해서 일을 하여 증명하는 방식이다. 여기서 일이란, 특정 값 nonce를 찾는 행위를 말한다. nonce란 해당 block header의 hash 값이 주어진 갯수의 0들로 시작하도록 만드는 값을 말한다.

Block의 구성

Block Header

Block이란 유효한 transaction의 모음집이다. 위의 block에서는 a~z까지의 유효한 transaction이 포함되어 있다. Proof-of-Work에서는 Block의 header부분에 주목해야 한다.

  • Version
    위의 그림에서는 나와있지 않지만, block을 만든 비트코인의 버전이 header에 포함되어 있다.

  • Hash of previous header block
    비트코인은 위변조를 막기 위하여 각각의 block들이 자신의 이전 block header의 hash 값을 참고하고, 이와 같은 형태를 blockchain이라고 부른다.

  • Timestamp
    블록이 생성된 시간이다. timestamp를 통하여 우리는 block들이 시간 순서대로 문제 없이 생성되었는지 알 수 있다.

  • Difficulty target
    비트코인은 하나의 block을 생성하기 까지 약 10분이 걸리도록 설계되어 있다. 이를 만족하기 위해서 더 많은 시간과 자원이 투자되어서 POW를 하게 되면 difficulty target이 올라가서 10분을 맞춘다.

  • Nonce
    Block header에서 유일하게 가변적인 값이다. Header는 총 80byte의 데이터로 POW에서 우리는 이 header의 hash 값이 특정 갯수의 0으로 시작하게 만들면 성공이다. 그렇기 때문에 노드들은 이 nonce값을 계속 1씩 키워가면서 계속 시도한다. Hash 함수의 특징은 input 값이 조금만 변해도 output이 완전히 다르게 나온다는 것이다. 고로 노드들은 시간과 자원을 투자하여서 일일히 nonce값을 변경시켜보는 방법을 선택할 수 밖에 없다.

  • Merkle root
    Merkle root는 transactions들의 Merkle tree의 root 값으로 해당 block에 포함된 transactions들의 요약본이다.

    Mastering Bitcoin - 7.The Blockchain

    Merkle tree는 이진트리로 비트코인에서는 block안에 포함된 transaction의 hash 값을 2개씩 묶어서 block header에는 최종적인 root 값만 저장한다. Merkle root의 장점은 2가지이다.
    • 특정 거래의 확인이 빨라진다.
      위의 Merkle tree에서 Merkle root로 부터 transaction D의 hash 값을 찾는데는 2번의 과정이 필요하다. n개의 tx들이 있을 때에는 ** 만에 데이터 값을 빠르게 찾을 수 있다.

    • 저장 공간의 효율성이 증가한다.
      Merkle root가 Block header에 없다면 우리는 transaction에 대한 정보를 얻기 위해서는 block 안에서 transaction 데이터 매번 다운로드하고 찾아야 하는 번거로움 및 저장공간의 문제가 생긴다. 2021년 9월 13일 기준으로 전체 비트코인 블록의 데이터는 약 355GB이다. Merkle root가 없었더라면 우리는 비트코인 네트워크에 참여하기 위해서는 이 전체 데이터를 다운로드하여야 할 것이지만, Merkle root 덕분에 Simple Payment Verification, SPV가 가능해진다.

      • Simple Payment Verification, SPV
        SPV는 경량 노드(Lightweight node)들이 block header의 정보만으로도 특정 transaction이 유효성이 검증되었는지 확인할 수 있는 방법이다.

        방법은 먼저 경량 노드는 확인 하고 싶은 transaction의 block을 풀 노드에게 요청하고, 풀 노드는 해당하는 transaction의 hash, merkle root hash, 그리고 merkle path을 제공한다. 이 정보를 가지고 경량 노드는 특정 transaction의 hash값을 제공받은 merkle path를 따라 계산한 뒤 기존의 merkle root hash와 비교해서 같을 경우, 이 transaction에 위변조가 일어나지 않은 것을 알 수 있다.

        SPV의 단점은 필요한 정보를 다른 노드들에게 요청하기 때문에 악의적인 노드들이 우세한 네트워크에서는 올바르게 이뤄질 수 없다.

요약...

위의 내용을 예를 통해 다시 정리해 보자. 나는 Alice에게 받은 1btc를 Ben에게 보낼려고 한다. 나는 Alice와 생성된 UTXO를 input으로 Ben과 새로운 transaction을 형성하였고, Ben의 digital signature를 통하여 Ben은 내가 1btc를 보낼려는 대상이 Ben이고 자신이 Ben이라는 사실을 증명한다.

이렇게 유효함이 증명된 transaction들을 모아서 노드들은 새로운 Block을 형성하려고 한다. 이를 위해서는 Proof-of-Work을 통과하여하고, 그 과정은 특정 조건을 만족하는 nonce값을 찾는 것이다. Charlie라는 노드가 나의 transaction이 포함된 새로운 Block의 POW를 찾았다고 하자. 이제 어떤 일이 벌어질까?

transaction → POW → ?

사실 Charlie가 새로운 Block을 생성할 동안 비트코인 네트워크의 다른 노드들도 각자 유효한 transaction들을 모아서 각자의 Block을 만들고 있었다. 하지만, 결과적으로 Charlie가 가장 먼저 새로운 Block을 찾았고, 찾은 즉시 Charlie는 다른 노드들에게 자기가 찾은 Block을 전파한다. 그 이후 노드들은 해당 Block의 transactions들이 유효한지 검증하고 만약 유효하다면 그 block을 수락한다. Block을 수락한 이후에는 그 Block의 hash를 앞서 설명한 Hash of previous header block으로 설정한 뒤 새로운 Block을 찾는다.

두 노드가 거의 비슷하게 자신의 Block을 전파한 경우

두 노드가 거의 비슷하게 자신의 Block을 전파한 경우는 약간 모호하다. 앞서 double-spend problem을 해결하기 위해선 모든 노드들이 하나의 기록으로 합의할 수 있는 시스템이 필요한데, 누구는 Block A를 기반으로 다음 Block을 찾고, 다른 누군가는 Block B를 기반으로 이어나간다면 결국 2가지 기록으로 나뉘어질 것이다. 이를 해결하기 위하여서 생긴 규칙이 longest chain rule이다. Longest chain rule은 말 그대로 2가지 기록이 생길 위험이 있을 때는 더 긴 chain이 맞다고 하는 것이다.

위 상황에 적용시켜보자. 노드 Echo는 Charlie가 전파한 Block A, 그리고 바로 뒤이어서 Daisy가 전파한 Block B를 받았다고 하자. 이런 경우에 일단 Echo는 살짝이라도 더 빨리 전파받은 Block A를 기반으로 새로운 Block을 생성하기 위해 노력한다. 시간이 흐른 뒤 다음 POW가 찾아지고 새로운 Block이 찾아지면 longest chain rule에 의하여 하나의 기록으로 모든 노드들은 합의하게 된다. 예를 들어 Block A를 기반으로 먼저 Block이 찾아진다면 그 chain으로, Block B를 기반으로 먼저 찾아진다면 B를 포함한 chain이 유효한 chain으로 합의된다.

왜 Block을 생성하는 걸까

아무런 보상이 없다면 비트코인 네트워크에서 노드들은 Block을 생성할 이유가 없다. Block을 생성하고 transaction의 유효성을 검증하는데는 자원과 시간이 들기 때문이다. Block을 생성한 노드가 받을 수 있는 보상의 종류는 2가지가 있다.

먼저 Block 생성에 대한 보상이다. 모든 block에 포함된 첫번째 transaction은 특이하게 input이 없고 output은 그 block을 생성한 사람이다. 태초에는 이 보상은 블럭 당 50btc였지만, 21만개의 블록이 형성될 때마다 이 보상은 반으로 줄어들어 현재는 블럭 당 12.5btc이다. 또 주목해야할 점은 이 block 생성에 대한 보상을 받은 btc는 100개의 블록이 생성된 이후부터 사용할 수 있다.

다음은 transaction fee이다. transaction에서 input에서 output을 뺀 값이 바로 transaction fee이다. 2032년이 되면 Block 생성에 대한 보상이 0에 이르게 되고 유일한 보상은 이 transaction fee가 된다.

이러한 인센티브는 노드들이 투명하고 비트코인 네트워크에 이익이 되는 방향으로 행동하도록 유도한다. 만약 악의적인 노드가 비트코인 네트워크에 과반수에 해당하는 CPU를 갖게 되더라도 해당 노드는 자신의 악의적 행동을 통해 얻을 수 있는 이득과 올바른 행동을 통해 얻을 수 있는 보상을 비교해 봐야 할 것이다. 또한 애초에 과반수의 CPU 파워를 가진 노드가 악의적인 행동을 하게 되면 비트코인 네트워크에 대한 신뢰가 떨어져 자신이 가지고 있는 많은 양의 비트코인의 가치가 떨어질 것이므로 이러한 점 역시 올바른 행동을 하도록 유도한다.

profile
블록체인 개발자(진)

0개의 댓글