블록은 거래에 대한 증거이다. 이 증거의 모음집이 블록체인이다.
블록체인은 블록과 체인이 합쳐진 구조이다. 우리는 여기서 블록과 체인을 나눠서 살펴보기로 하자.
블록의 구조는 위의 사진을 참고하자. 여담으로 나카모토 사토시의 비트코인 백서에는 블록체인이라는 단어가 나오지 않는단다.
블록은 블록 헤더와 블록 바디로 이루어져 있다. 블록 헤더에는 블록의 요약 정보, 즉 메타데이터가 담긴다. 블록 바디에는 트랜잭션, 즉 거래 정보가 담긴다.
아래에서 더 자세히 다루겠지만 이 트랜잭션을 모두 묶어 하나의 머클 트리로 해시해서 블록 헤더에 담는다. 쉽게 말해 거래의 요약본을 헤더에 포함시킨다는 것이다.
체인은 이 블록들을 하나로 연결시켜 놓은 것이다. 블록과 블록을 연결하기 위해 블록 헤더의 모든 내용을 한 번 더 해시해서 이전 블록의 해시값과 비교하여 블록을 체인으로써 연결한다. 해시함수가 곧 체인의 역할을 한다고 볼 수 있다.
블록의 정보를 요약한 메타데이터가 담기는 곳
블록 헤더에 담기는 블록의 용량은 위와 같다. 현재 블록 하나당 크기는 1MB라고 한다. 블록 헤더에 담기는 각각의 정보를 자세히 살펴보자.
블록체인의 버전 상태를 표시
비트코인은 처음 나왔을 때부터 지금까지 모든 거래 내역을 다 갖고 있다.
때문에 버전 업그레이드가 될 때마다 과거 버전의 블록에 영향을 미치게 되는데, 이 때 하위 호환이 가능하게 하기 위해서 버전을 기록한다. 단, 하위 호환을 진행하기 떄문에 프로그래밍 코드가 복잡해지는 단점이 발생한다.
블록이 생성된 시간
좀 더 정확히는 헤더를 해싱하기 시작한 시간이다. Unix-epoch time 포맷을 사용한다.
타임스탬프 상 시간 차이가 존재할 수 있지만 심각하게 벗어나지 않는다면 허용한다. 비트코인은 2시간 정도를 허용한다. 타임 스탬프는 난이도를 결정할 때 사용된다.
이전 블록의 헤더를 해싱한 결과값
블록과 블록을 연결하기 위해 이전 블록의 블록 헤더를 해시 함수로 돌려서 다음 블록의 블록 헤더에 기록한다.
이전 블록 해시는 블록을 체이닝하기 위한 연결고리로써의 역할을 한다. 이전 블록 해시 값과 이전 블록의 데이터 값을 비교해서 검증이 가능하다.
모든 거래를 해시해서 얻은 마지막 요약본
머클루트의 더 자세한 구조는 아래 그림을 참고하자.
거래가 수 십 개가 되도 마지막에 최종으로 나오는 머클루트는 32byte(4bit = 1byte)로 항상 같다. 이런 식으로 모든 거래를 머클 루트로 요약하면 거래량이 늘어나도 특정 거래를 찾는 경로는 단순해진다.
이진트리 구조이기 때문에 log2N의 시간 복잡도를 갖는다. 이진트리에 대해서는 아래의 블록 바디에서 더 자세히 다룬다.
블록체인의 용량은 데이터가 쌓일 수록 늘어나기 때문에 풀노드만이 모든 블록체인을 가질 수 있다. 그런데 2023년 9월 5일 기준 비트코인 전체 체인 사이즈가 508G 밖에 안하네요.. 노드 하겠다고 맘먹은 사람한테 과연 크다고 할 수 있는 용량인지.....?
하여튼 머클트리를 이용하면 헤더만, 즉 블록체인의 일부만 받을 수 있는 라이트 노드처럼, 누구나 모바일로도 쉽고 빠르게 특정 거래를 찾을 수 있게 된다.
하나의 데이터만 바뀌어도 모든 해시값이 다 바뀌기 때문에 머클루트가 변하는 것은 헤더가 바뀐다는 의미이다. 때문에 데이터 위변조가 불가능하다.
머클 증명을 통해 원하는 데이터를 검증할 수 있다. 머클 루트와 머클 경로로 검증을 한다. 위 사진에서 data2의 데이터를 머클 증명하기 위해서는 세 개의 해시값만 있으면 가능하다.
난이도(비츠)는 채굴에서 사용되는 값으로, 난이도를 통해 목표값(Target Value)을 선정하게 된다. 논스는 난이도를 통해 선정된 목표값보다 낮은 해시값을 생성하기 위해 채굴자가 반복적으로 변경하는 임의의 숫자이다.
난이도 = 문제
에 비유할 수 있고 논스 = 답
에 비유할 수 있다. 답을 맞추기 위해 채굴자들은 논스값을 계속 바꿔가면서 목표값을 맞춰 채굴에 성공한다.
논스와 난이도는 채굴과 연관이 있기 때문에 블록체인 채굴에 대해서는 후에 다른 포스트에서 더 자세히 다루기로 한다.
실질적인 거래의 내역이 들어간다.
순서가 있는(Linked List) 트랜잭션 목록이 담긴다. 바디의 정보들을 기반으로 Header의 Merkle Root가 생성된다. 순서가 지켜지지 않으면 채굴자가 부당 이익을 챙길 여지가 존재한다. 이를 MEV(Miner Extractable Value) 라고 한다. 채굴자들이 순서를 재배치하게 되면 차등 이익을 발생 시킬 수 있는 여지가 생길 수 있기 때문에 순서가 중요하다.
가령 비트코인을 대량판매하는 TX1이 존재하고 비트코인을 구매하겠다는 TX2와 판매하겠다는 TX3이 있다고 가정하자. 트랜잭션 순서를 바꿀 수 있다면 TX3을 TX1로 바꿀 수 있게 된다. 이러한 부당 행위를 피하기 위해 순서를 조작할 수 없게 해놓은 것이다.
바디에 있는 거래 내역들은 이진 트리를 형성하고 루트값을 생성한다. 이진 트리는 각 노드가 꼭 2개씩 자식을 노드로 둔 형태의 트리를 의미한다. 하나의 정보가 변경되면 상위의 정보들이 모두 변경이 되어야 하는 구조이기 때문에 정보의 변화가 쉽지 않다.
트리의 가장 상위의 노드를 루트 노드라고 부른다. 이진트리에서 모든 부모는 자식을 둘만 갖는다.
자식 노드의 거래 내역을 해시한 해시값을 합친 형태가 부모에게 올라가고 부모가 받은 해시값을 또 해시한 값이 루트 노드에게 올라가고 그 해시값이 또 해시된 값이 Merkle Root에 들어가는 것이다.
자식 노드들은 꼭 2의 n승이어야 한다. 만약 6개밖에 안 된다면 남은 노드들을 2의 제곱수로 만들어서 이진트리를 형성한다. 만약 7개라면, 남은 한 개를 복사해서 8개로 만든다.
트랜잭션에 대한 자세한 내용은 다음 포스트에서 다루기로 한다.
고정길이의 단방향, 무규칙성 암호
Hash는 으깨다, 라는 의미를 지닌다. 평문을 으깨서 알아볼 수 없게 만드는 것이 특징이다.
평문을 넣어서 나온 암호문으로 평문을 다시 복호화할 수 없기 때문에 단방향이다.
블록체인은 SHA256(256bit)을 통해 어떤 길이의 값을 입력하더라도 256비트의 고정된 64자리 암호문을 출력한다.
복호화가 되지 않는다는 것은 규칙없이 생성되기 때문에 유추할 수 없다는 것을 의미함. 암호문의 원본을 갖고 있다면 돌려서 평문을 얻어낼 수 있긴 하다. 그러나 맨눈으로 봐서는 규칙이 일절 보이지 않는 특징을 두고 무규칙성이라고 하는 것.
아주 작은 확률로 입력값이 다름에도 불구하고 출력값이 같은 경우가 발생하는데 이것을 충돌이라고 한다.