블록체인

거 그래서 블록체인이 뭐란 말이오? (1)

그냥 요즘 삘 받아서 글을 막 쓰게 되는데, 이럴 때 열심히 글을 써 두는게 제일 좋지 않나 싶다. 일단 블록체인 기술에 대해서 이야기를 해야하나 싶은게, 실제로 다들 블록체인 기술이 뭔지에 대해서 이야기를 하는 사람이 없기 때문이다. 아니 솔직히, 블록체인 관련 글들은 쓰는데 회사 솔루션을 끼워서 이야기를 하거나, 아님 얕은 지식의 이야기를 하거나, 너무 암호학 위주로 이야기를 하거나, 아님 뭐 내 마음에 안 들게 글을 써서 그냥 블록체인에 대한 이야기를 처음부터 하려고 한다. 하지만, 이 글은 언제라도 사라질 수 있으며, 그 후 회사 블로그에 올라갈 (...) 수 있다는 부분은 양해 부탁드리는 부분이며, 솔직히 저희 회사도 먹고 살아야한다는 점을 이야기 하고 싶다. 저희 회사 기술력 보고 시리즈A 투자 좀 해 주세요. 제발.

뭐, 여튼 블록체인을 언제나 쉽게 이야기를 하면,

1. 공인인증서(비대칭키)로 거래 내역을 사이닝해서
2. 그 트랜젝션(거래 내역)을 전파를 하고,
3. 전파 받은 기록들을 해쉬 링크드 리스트에 기록을 해서
4. 그 최신 블록(혹은 노드)을 P2P로 토렌트 비슷하게 공유를 하면,

기초적인 블록체인이 나온다.

5. 거기에 PDA 같은 녀석을 추가로 넣고 스택 기반으로 VM을 만들면 비트코인이 되고
6. 인스트럭션 셋을 만들어서 인스트럭션 단위로 Gas라는 사용료를 물면 이더리움이 된다
7. 그리고 블록을 생성할 때마다 보상을 줘야한다. (경제학적 이유)
8. 블록 생성 방식에 대한 합의가 필요하다.

좀 더 복잡한 이야기를 하자면,
9. 이런 VM에 박히는 스크립트의 용량을 최소화하는 것이 목표인 상황,
10. 블록 생성 방식을 바꾸어 최소한의 시간으로 빠르게 컨펌하는 것이 목표인 상황
11. 블록체인 네트워크가 갖고 있는 한계 및 해결 방식
12. Fee를 해결하기 위한 방법
13. 기타 등등의 각종 이슈들
이 있으며, 이 부분에 대해서는 추가적인 포스팅을 하도록 할 것 같다.

라고 말을 한다. 사실 공인인증서라고는 말하지만 사실은 사설인증서이며, 개인이 직접 생성하는 비대칭키에 의존한다. (그러니 막 지갑 주소가 여러개 생성 될 수 있는 것이다!)

사실 많은 질문들, 특히 블록체인 노드와 월렛에 대한 구분을 못 하거나, 콜드 월렛과 핫 월렛이라는 요상한 단어를 쓰는 친구들을 볼 때마다 복장이 터지는 이유는 콜드와 핫은 의미도 없을 뿐더러, 콜드나 핫이나 둘 다 실제로 작동되는 원리는 비슷하기 때문이다. 아니 비슷하다고? 비슷하다. 이제 그 이야기를 길고 길게 이야기를 할 것이다.

일단, 큰 꼭지는 1번과 3번은 인터넷 없이도 처리가 되고, 2번과 4번은 네트워크랑 관계가 있다는 것을 쉽게 눈치를 챌 수 있을 것이다. 5번과 6번은 이제 심플한 컴퓨터구조론 혹은 오토마타 이야기라는 걸 이해를 바로 하면 컴퓨터 공학 정규 수업을 열심히 들었다는 것이다. 뭐 일단 이야기를 진행해보자. 1번 부터 이야기를 해보자.

1번 : 비대칭키로 거래내역의 사이닝을 한다.

비대칭키는 무엇인가? 일반적으로 프로그래머라면, 알 수 있는 부분은 "공인인증서에서 사용된다." 혹은 "SSL 같은 곳에서 사용된다." 정도일 것이다. 좀 더 궁금증을 갖고 있다면, RSA 정도를 알 것이고, 일반적으로 ssh 통신을 할 때 pem 키라고 부르는 녀석이 RSA (혹은 딴 비대칭키) 비밀키 및 공개키를 박아놓은 녀석이라는 것을 알 수 있다. 이걸 이용해서 비밀키로 사이닝을 하고, 공개키로 그것을 확인하는 (사실 반대도 가능하다) 작업을 할 수 있다. 이는 중간에 공격자가 공개키로 암호화된 메세지를 가로채도 비밀키가 없다면 해독을 못하는 상황을 만들어 낼 수 있다는 것을 의미한다. 또한 비밀키로 사이닝한 메세지를 공개키와 같이 공개를 하여, 비밀키를 갖고 있는 사람이 공개키로 이러한 메세지를 썼다는 것을 해독 시킬 수 있을 것이다. 암호화폐에서 이것이 쓰이는 이유는 명료하다. 사이닝을 통해서 주인을 식별할 수 있다는 것 때문이고, 이를 암호화폐의 전송에 사용하게 된다.

제일 간단하게 생각 할 수 있는 예는 다음과 같을 것이다. 일단 Alice는 10 Bengi 코인을 갖고 있고, 나머지는 모두 0 Bengi 코인을 갖고 있다고 가정하자. 그리고 Alice는 다음과 같은 메세지를 써서 서명을 한다.

{
    msg : "Alice는 Bob에게 10 Bengi Coin을 보낸다.",
    signature : msg의 서명 (Alice의 비밀키로 서명함)
}

 

이 메세지를 받은 사람은 Alice가 비밀키를 사용하여 Bob에게 10 Bengi Coin을 보냈다는 것을 증명할 수 있다. msg를 signature(서명)을 Alice의 공개키로 해독해 msg가 나오면, Alice가 보낸 것이 맞기 때문이다. 그렇다면, 이제 Bob은 10 Bengi 코인이 있는 것이고, 5 Bengi Coin을 Carol에게 보내고 싶다. 그러면 이제 위의 모델에서, Bob은 Carol에게 5 Bengi 코인을 보내고 싶다는 메세지를 작성해 서명해서 넘겨주면 된다! 그러면 Bob이 주인인게 확실하니! 그러면 이제 Bob은 5 Bengi 코인을 갖고 있고, Carol은 5 Bengi 코인을 갖고 있고, Alice는 0 Bengi 코인을 갖고 있을 것이다.

하지만, 여기서 드는 의문은 이제 이것이다. msg 내용이 좀 그시기하다는 것이다. 다음과 같이 바꿔보자

{
    from : "Alice",
    to : "Bob",
    amount : 10,
    signature : msg의 서명 (Alice의 비밀키로 서명함),
}

그 다음으로 드는 생각은 Alice의 Signature를 어떻게 검증하냐는 것이다. Alice의 공개키가 등록된 장부가 있거나 그에 준하는 무언가가 있어야한다. 이럴바에는 그냥 from에 Alice의 공개키를 넣는것이 어떤가? 그러면 좀 더 쉽게 전송을 할 수 있을 것이다.

{
    from : "Alice's Publickey",
    to : "Bob",
    amount : 10,
    signature : msg의 서명 (Alice의 비밀키로 서명함),
}

이제 메세지는 자가 증명을 할 수 있다. form에서 Alice의 공개키를 찾아서 signature가 맞는지 알 수 있다. 근데, 이러면 Bob의 공개키와 Bob이 어떻게 연결되어있는지를 증명할 수 없다. 즉, to에도 Bob의 공개키를 넣으면 편해질 것이다. Bob은 여기서 비밀키를 이용할 일이 없지만, Bob의 신원증명에는 사용되니 공개키를 넣는게 좋을 것이다.

{
    form : "Alice's Public key",
    to : "Bob's Public key",
    amount : 10,
    signature : msg의 서명 (Alice의 비밀키로 서명함),
}

(별로 알 필요는 없음) 비대칭키 암호화를 좀만 안다면 msg 길이 만큼 signature의 길이가 길어진다는 점이 문제라는 걸 알 수 있다. 위의 메세지를 해슁을 하고, 해슁된 데이터 값 (해식값)에 서명을 해도 동일한 효력이 나올 것이다. 그렇게 바꿔보자.

{
    form : "Alice's Public key",
    to : "Bob's Public key",
    amount : 10,
    tx_hash : msg의 hash 값,
    signature : tx_hash의 서명 (Alice의 비밀키로 서명함),
}

이제 좀 이쁜 모습이 되었다. 이제 이것을 이용하여 전송 Alice는 Bob에게 전송을 할 수 있다. Bob의 공개키는 이 트랜젝션이 블록체인 상에 허가가 나면 10 Bengi Coin을 소유하게 되는 것이고, 이에 따라서 10 Bengi Coin 이하의 값을 전송할 수 있을 것이다. 기본적인 전송 시스템을 구축할 수 있는 것이다. Bob에게 수신된 총량과 발신한 총량을 빼면 Bob의 잔고가 나올 것이다. 즉, 이걸 주기적으로 기록만 한다면 블록체인 상에서 거래를 할 수 있다! 그러니, 이런 전송이 발생할 때마다 Alice의 잔고에서 금액을 깍고, Bob의 잔고에 그 만큼의 금액을 추가하면 된다. 만약 Alice가 잔고가 없는 상황에서 돈을 보내려고 한다면 블록체인 네트워크 상에서 거부를 할 것이다. (잔고 금액을 추적하고 있으니, 하지만 동시에 각각 Bob과 Carol에게 7 Coin씩 보낸다는 트랜젝션을 생성하는 공격 같은 걸 하거나 0 Bengi Coin을 무한히 보내는 공격을 한다면 어떨까? 이후에 후술한다.)

사실, 암호화폐에서 대표적인 모델은 2가지가 있는데, UTXO 모델과 Account 모델이다. UTXO는 비트코인이 사용하는 모델이고, Account는 이더리움이 사용하는 모델이다. Account 모델의 기초를 위에서 이미 설명을 했으니 넘어가도록 하고, UTXO 모델은 복식 부기를 사용하는 모델이다. 상당히 복잡하다고 할 수 있는데 상당히 직관적이니 이야기를 한 번 하긴 해야할 부분이다. 이 이야기는 나중에 공격에 대한 저항성 이야기에 대해서 아주 중요하게 다룰 것이다.

Account 모델의 단점은 공개키-잔고 쌍을 어딘가에 기록하고 계속 추적해야한다는 점이다. 이 방식은 어쨌든 공개키 쌍이 늘어날 수록 데이터베이스 크기가 늘어난다는 점이다. 이 방법 대신에 UTXO는 복식 부기를 사용하여 이 부분을 해결한다. 복식부기 자체가 잔고 증명이 되고, 복식부기를 연속적으로 만들어냄으로써 잔고의 흐름을 추적하는 방식을 사용한다.

간단하게 1 Input, 2 Output 트랜젝션을 보자.

{
    from : [
    	tx1_hash, // to Alice 12
        ],
    to : { 
    	Alice Publick Key : 2,
        Bob Public Key : 10
        },
    tx_hash : tx_new_hash,
    signature : alice signature of tx1_hash,
}

Alice의 12 Bengi Coin을 받는 트랜젝션을 찾아서, Alice에게 2를 보내고, Bob에게 10을 보내는 새로운 트랜젝션을 만든다. 이렇게 되면 Alice는 tx1 더 이상 사용 될 수 없어지고, tx_new가 이제 Alice와 Bob의 새로운 잔고 증명 Tx가 된다. Alice와 Bob은 이 트랜젝션 해쉬를 갖고 새로운 거래를 열 수 있다. 여튼 여러개의 Alice에게 Bengi Coin을 보내는 tx들을 모아서, from에 넣고, to에 받을 사람을 적어서 트랜젝션을 생성하면 되는 구조이며, 이를 통해서 검증자는 전체 잔고의 추적을 할 필요가 없어졌다. 그냥, tx1_hash의 시그니처와 Alice의 공개키와 tx1_hash 세 개를 대조하여 맞는 사용자인지 확인을 하는 과정이 있는 것 뿐이다. 이를 P2PK 방식이라고도 불리는데, 바로 공개키를 사용하지는 않고 Address를 사용하나 전체적인 기조는 같다. 그렇다면 2개의 인풋과 3개의 아웃풋이 있을 경우 어떻게 하는가? 아웃풋은 쉽겠는데, 2개의 인풋이 Alice의 서로 다른 공개키로 보내는 것이라면 약간 골이 아플 것이다. 그래서 실제로 signature는 다음과 같은 형태를 띄고 있다.

{
    from : {
    	tx1_hash: alice signature of tx1_hash, // to Alice 10
        tx2_hash: alice signature of tx2_hash, // to Alice 5
        },
    to : { 
    	Alice Publick Key : 2,
        Bob Public Key : 10,
        Carol Public Key : 3
        },
    tx_hash : tx_new_hash,
}

 

어려운가? 그렇다면 쉽게 설명하면, 잔돈 모델로 생각하면 편하다. Alice가 1000원짜리 지폐랑 500원짜리 동전 합쳐서 1500원을 넘겨주고, 200원을 거슬러 받고, 1000원을 BoB에게 주고, 300원을 Carol에게 준  모양새가 된다.이런식으로 잔돈들을 합쳐서 큰 돈을 만들고, 큰 돈을 다시 쪼개서 분배를 하는 과정을 거치게 된다. 그래서 비트코인 트랜젝션을 보면 일반적으로 1~3개의 인풋에 2개 정도의 아웃풋이 기본적으로 있는 것이다.

2번 트랜젝션의 내역을 전파한다.

이렇게 만들어진 트랜젝션을 이쁘게 팩킹하여, 연결된 노드나 자기 자신의 노드나 여튼 블록체인 데이터를 받을 수 있는 무언가에 전송을 해 주면, 노드들끼리 이 신규 트랜젝션을 공유를 하여 네트워크에 동기화를 시켜준다. 그리고, 블록 생성자가 이 트랜젝션 데이터를 받아서 블록에 산입을 하도록 한다. 그냥 토렌트나 P2P 서비스를 생각하면 편하다. 데이터를 동기화하는 과정인 것이다. 여기서 콜드월렛 핫 월렛이 결정되는데, 블록체인 노드에 바로 연결되어서 쏘면 핫 월렛, 연결이 되어있지 않고 중간 전달자가 대신 전달해주면 콜드월렛이나, 실제로 콜드나 핫이나 트랜젝션 생성을 하는 건 변함이 없다는 것을 알 수 있다. 솔직히 네트워크에 안 붙고도 트랜젝션 생성할 방법 많은 관계로 핫이나 콜드나 별 의미가 없다. 특히 같은 비밀키를 여러군데에 저장해서 쓰는 경우라면 더더욱.

3번 해쉬드 링크드 리스트에 기록을 한다

블록체인이라는 게 여기서부터 중요해지는데, 해쉬드 링크드 리스트를 사용한다는 점과, 사실은 링크드 리스트가 아니라 DAG라는 점이다. 링크드 리스트는 트리나 그래프 형태로 만들어지면 안 되는데, 블록체인은 그렇게 되는 경우가 종종 있기에 엄밀히 말하면 링크드 리스트의 속성을 충족하지는 않는다. 그래서 더 느슨한 자료구조인 DAG의 특징을 충족하는 것인데, 이 부분에 대해서 이야기를 해보자.

이제 두번째 장벽인 해쉬 함수에 대해서 이야기를 하려고 한다. 해쉬란 무엇인가? 비가역적인 형태로 무언가를 생성시키는 함수이다. 해쉬 함수의 특징은, 같은 값이 들어가면 같은 값이 나와야하고, 두 다른 값의 결과는 같지 않아야하며, 비슷한 값의 결과는 충분히 달라야한다, 그리고 제일 중요한것은 원본의 값을 유추할 수 없어야한다는 점이다. 간단히 설명한 것이지만, 상당히 구현 난이도는 높은 편이고, 실제로 해쉬 함수가 깨진다 (취약점이 나온다) 라는 부분들이 저 전제를 못 지키기 때문이다. 두 다른 값에서 같은 결과값이 나오는 경우를 해시 콜리전 (충돌)이라고 불리고, 유추 가능성에 대해서는 제1역상 공격이라고 한다(제2는 해쉬 콜리전이다) 이를 실제로 염두를 해야하는 점은 무엇인가? 블록체인은 데이터의 위변조를 검증하는데 해쉬를 쓰고, 이 덕분에 해쉬가 덕지덕지 발라져 있다는 점이다.

해쉬 링크드 리스트는 다음과 같은 특징을 갖고 있다. 트랜젝션들을 넣은 블록을 만들고, 해쉬를 만든다. 아니... 정확히는 앞선 블록에 대한 정보를 담게 된다. 다음과 같은 구조를 띄게 되는데 일단 확인해 보자.

current_block = {
    previous_block_hash : previous_block_hash,
    tx_data : [tx1_data, tx2_data, tx3_data, tx4_data, ... ],
    txs_hash : SHA3(tx_data),
}

new_block = {
    previous_block_hash : SHA3(current_block),
    tx_data : [tx5_data, tx6_data, tx7_data, ... ],
    txs_hash : SHA3(tx_data),
}

간단해 보이지 않는가? 사실 이 데이터는 좀 말이 안 된다는 걸 나중에 이야기를 하겠지만, 이런식으로 데이터를 박아넣는다. 정확히는 tx_data는 머클트리를 사용하여 저장을 하고, 블록과 블록 헤더가 분리가 되어있는 형태이지만, 일단 간단한 형태로 설명을 하기 위해서는 이것이 편하리라 생각하여 이렇게 적는다. new_block은 current_block의 hash 값을 가리킨다. 이를 이용하여, 블록체인은 자신의 이전 블록 데이터를 찾아 넣을 수 있는데, 이 때문에 해시드 링크드 리스트라고 하는 것이다. 포인터 대신에 해시값을 사용하는 링크드 리스트인 것이다.

그리고 블록체인 클라이언트는 tx_data를 순회하면서 값들을 최신으로 업데이트를 하게 되는데, 이를 통하여 앞의 트랜젝션을 통한 전송 관련된 부분을 처리하게 된다.

4번 최신 블록을 P2P로 토렌트 비슷하게 공유를 한다.

자 이제 블록체인은 트랜젝션을 전파하듯이 전파를 하면.... 되나....? 될 것이다. 옆 사람이 새로운 블록을 만들어냈다는 걸 알기 전까지는 말이다. 실제로 블록의 경우 예측 가능한 정도로 생성되어야하며, 동시에 한 블록을 참조하는 여러 블록들이 생성되는 일은 지양해야한다. (그렇기에 DAG라는 표현을 한 것이다. 실제로는 일어나니) 이를 위해서, 블록체인 클라이언트들은 규칙을 공유한다.

첫째, PoW 방식의 생산. HashCow 같은 문제를 풀어서 해결하는 방식. Nonce 필드를 추가하고, 해쉬 값에 대해서 제약 조건을 걸어 특정 조건을 달성한 해쉬 값을 인정하는 방식이다. 일반적으로 해쉬 값에 앞에 0이 몇 자리 이상 붙어 있느냐로 제한을 두는 경우가 많다. 해쉬의 특성상 특정한 해쉬를 도출해 내는 건 상당히 힘든 일인데, 이를 이용한 트릭이다.

new_block = {
    previous_block_hash : SHA3(current_block),
    tx_data : [tx5_data, tx6_data, tx7_data, ... ],
    txs_hash : SHA3(tx_data),
    nonce : some_number
}

적절한 some_number를 넣게 된다면, 00000deadbeef..... 같은 해쉬를 얻을 수 있다. 각각 컴퓨터는 이 some_nubmer를 무작위 (혹은 순서대로) 대입하여 00000으로 시작하는 해쉬 값을 찾으면 되는 것이다. 이를 통해서 제일 먼저 0이 5개 (상황따라 난이도가 올라갈 수록 0의 갯수가 증가한다)인 some_number인 블록을 찾았다면, 이를 적합한 블록으로 인식하고 모두가 받아들이는 것이다.

아니, 이게 어떻게 보안을 유지시키냐고? 비트코인은 30분마다 블록이 생성되도록 해쉬 난이도를 조절(0의 갯수 조절)을 하는데, 총 컴퓨팅 파워로 30분 즈음에 적합한 블록을 찾아내도록 셋팅을 하는 것이다. 그것을 이용해서, 다른 유저가 (위변조한) 블록을 마구 생성하거나, 블록체인이 2개로 쪼개지거나 했을 때를 조절할 수 있다.

둘째, 제일 긴 체인을 선택한다. 제일 많은 컴퓨팅 파워가 소모된 체인이 제일 올바른 체인이라고 가정을 하는 것이다. 별다른 의미는 없지만 제일 효율적인 방식이긴 하다. 특히, 공격자가 다른 체인을 만드려고 해도, 전체 컴퓨팅 파워의 51% 이상을 장악하고 있지 않는 이상 제일 긴 체인을 택할 것이므로 공격자의 공격은 수포로 돌아가게 된다.

셋째, 깊이가 6 이상이 된 스플릿이 발견될 경우 롤백하지 않는다. 30분 단위의 블록 생성 시간을 감안하면 3시간 이상이 된 블록들은 적합한 것으로 간주하고, 신규 체인 (7번 전 블록부터 다른 해쉬 값을 갖는 더 적합한 블록들의 연속)을 받아들이지 않는다. 이렇게 함으로써 외부의 공격을 막는다.

이 두 가지를 지키는 블록들을 외부 노드로부터 받아들이면서, 블록체인의 전체 크기는 증가한다. 뭐 하지만 저런 시스템이 돌아가지만 실제로 블록 스플릿이 거하게 일어난 적도 있고 (6개 이상의 블록이 각각 생긴 두 체인으로 쪼개진 적이 있다.), 포크라는 방식으로 블록을 양분하는 방식이 있는 등 (비트코인 캐쉬, 비트코인 골드 등) 을 생각한다면, 실제로 완벽하게 안정적인 방식은 아니라는 것을 알 수 있다. 다만, 이러한 규칙을 통해서 주기적으로 블록을 생성하고, 확률적으로 동시에 블록을 생성하는 것을 막고, 충분히 네트워크에 전파될 시간을 잡아 블록체인의 신뢰성을 보장 시킬 수 있다.

자 그렇다면, 이제 노드는 어떻게 찾는 것인가? 일반적으로 P2P 클라이언트와 비슷하게 작동되나, 자기 자신이 Seeder이기도 하고, Tracker이기도 하다. 일반적으로 비트코인 클라이언트가 처음 시작된다면, 하드 코딩 된 DNS 주소에 쿼리를 날려 주변 노드들 정보를 얻고, 그것이 안 될 경우 하드 코딩 된 노드 주소에 연결을 시도한다 (참고로 최신 클라이언트에서는 폐기된 방법이다), 최종적으로 아무것도 없을 경우 UDP 브로드캐스팅을 쓰는 것으로 알고 있는데, 여기까지 가보지는 않아서 정확히 설명을 할 수는 없을 것이다. 여튼, 천하의 블록체인이 중앙화된 클라언트에 하드코딩된 주소를 의지한다니 재미있지 않은가? 이더리움도 비슷하게 bootstrap node 리스트를 따로 제공한다. 이에 대한 문제는 Tor 네트워크나 Tails가 갖고 있는 문제와 비슷한데, 일단 초반에 Tor나 Tails를 깔기 위해서 사이트에 접속하는 과정 자체가 그 사람의 신원을 노출 시킨다는데 있다. 즉, 아무리 익명성 클라이언트라고 하더라도 초반에 접속하게 되는 곳은 다 같으니 그 곳만 주기적으로 감시를 하면 된다는 문제점이 있는 것이다. 이 부분에 대한 해결 방법은 나중에 이야기하도록 하고, 이제 이렇게 접속을 하면 어떻게 되나 이야기를 하자.

이제 접속을 하게 되면, 제네시스 블록, 그리고 그 다음 블록, 그 다음 블록의 다음 블록을 쭉쭉 받아오게 된다. 블록 하나하나의 해쉬를 검증하고, 시그니처를 검증하면서 옳은 블록인지를 검증을 하면서 주변 노드들로부터 데이터를 받아오는 것이다. 그리고 어느 정도 동기화가 끝나면 Tip이라고 하는 끝 부분 (혹은 최신 블록을 받아와야하는 시점)에 도달하게 되고 이제 사용할 수 있는 상태가 된다. 왜냐하면, 모든 트랜젝션 데이터들을 다 받아서, 내 트랜젝션 데이터들의 집합을 다 찾아냈기 때문이다.

으악 너무 불편하고 시간이 걸린다고?!

그렇다면 SPV나 Light 모드로 빠르게 싱킹하는 방법이 있다. 이는 블록 전체 데이터를 받아오지 않거나, 거꾸로 (...) 받아오거나, 미리 몇 십 기가바이트 정도 되는 데이터를 P2P로 압축해서 받거나 하는 방식으로 진행된다. 이 방법에 대해서는 11장에서 이야기를 하도록 하자. 추가적인 꼭지들에 대해서 이제 이야기를 할 수 있을 정도로 내용이 진척된 거 같아서 기쁘다.

일단 1/2/3/4 장에서 진짜 기초적인 블록체인 클라이언트에 대해서 설명을 하였다. 설명이 충분하지 않다는 생각이 들지만, 일단 이 정도면 블록체인에 접목되는 암호학 기술에 대해서 약간이나마 이해를 할 수 있을 것이다. 여기까지 읽어줘서 감사하다.