Go로 블록체인 만들기 #2

Min Seo Park
CAU_CLink
Published in
11 min readAug 17, 2020

Go 로 블록체인 만들기 시리즈 2번째

#2 PoW 구현하기

이번 Go로 블록체인 만들기 2편은 다음과 같이 구성되어있다.

  • Introduction
  • Proof - of - Work
  • Hashing
  • 해시캐시
  • 구현
  • 결론

서론

1편에서는 매우 간단한 블록체인 데이터 베이스의 핵심이 되는 자료 구조를 구현해보았다. 그리고 블록을 추가할 때 체인 형태로 서로 연결될 수 있게 구현했다. 문제는 이전에 구현한 블록체인은 쉽고 바로 블록이 생성된다는 것이다.

비트코인을 포함한 많은 실제 블록체인에서는 블록 생성하는데 있어서 일정 시간이 걸리며 많은 에너지가 요구된다. 바로 PoW 라는 합의 알고리즘이 있기 때문이다. 이번 단계에서는 그 PoW를 구현해보려고 한다.

<Part 2 에서 구현할 5가지 파일들>

작업증명(Proof-of-Work, PoW)

블록체인의 핵심 특징 중 하나는 합의 알고리즘이다. 불특정 다수가 권한이 동등한 탈중앙화된 상태의 네트워크에 포함되어 있어, 어떤 정보가 옳은 정보인지 정할 필요가 있다. 이때, 사용되는 바로 과정이 바로 합의 알고리즘이다.

다수의 블록체인은 PoW 방식을 택하였다. PoW 알고리즘을 간단하게 설명하면 누군가가 힘들게 작업을 하여 결과물을 내는 것이다. 그리고 그 힘든 일에 대한 대가로 보상을 지급받는 것이다. (채굴의 결과로 코인을 보상으로 얻는 인센티브 구조)

이 메커니즘은 현실세계과 매우 비슷하다 : 일을 하여 보상을 얻고 삶을 영위해나가는 것처럼 말이다. 블록체인에서는 채굴자들이 채굴이라는 과정을 통해 힘들게 새로운 블록을 만들고 그에 대한 보상을 받는다. 그리고 이러한 행동이 네트워크를 유지시킨다. 작업 결과물로, 새로운 블록은 블록체인에 안전한 방법으로 더해지고 블록체인 데이터베이스 전체의 안정성을 보장한다.

작업증명(POW)의 개념은 “열심히 일하고 그 결과물을 증명하라” 이다. 작업증명 과정이 쉽지는 않다. 그 이유는 많은 컴퓨팅 파워를 필요로 하기 때문이다 : 고성능 컴퓨터를 이용한다고 해도 작업이 빨리 완료되지는 않는다. 설사, 특정 블록이 빨리 생성되었다고 하여도 6개 블록 생성시간은 1시간으로 맞춰져있기 때문에 시간이 지남에 따라 그 난이도도 같이 변화한다.

비트코인에서는, 블록의 해시값을 찾는 “작업”을 하고 특정 조건에 부합함을 “증명”한다.

마지막 알아야 할 점은 PoW는 작업은 어렵지만, 작업의 결과물을 검증(옳은 것인지 증명)하는 것은 쉽다는 것이다. 결과물이 옳은 것인지를 증명하는 것은 네트워크에 참가하는 모든 사람들이 할 수 있는데, 그 과정이 오래 걸려서는 안된다.

해싱 (Hashing)

해싱에 대해서 한번 설명해보려고 한다. 해싱의 개념과 과정에 대해서 이미 알고있는 독자들은 해당 단원은 그냥 넘겨도 된다.

해싱은 특정 데이터에 대한 해시값을 얻어가는 과정이다. 해시 함수는 임의의 크기의 데이터를 입력값으로 받아서 정해진 크기의 데이터를 출력값으로 낸다. 아래에 해시 함수 특징 몇가지가 쓰여 있다.

  1. 기존의 데이터는 해시값으로 복구될 수 없다. 그렇기에, 해싱과정은 암호화 과정과 다르다.
  2. 특정 데이터는 오직 하나의 해시값만을 가지고 그 값은 유일하다.
  3. 1 바이트라도 변화가 일어나면 완벽하게 다른 해시 결과값이 나오게 된다.

블록체인에서 해시는 블록의 일관성을 보증한다. 해싱을 하는데 있어서 이전 블록의 해시값도 포함이 되기 때문에, (사실상) 체인 안에 있는 블록을 변형시키는 것은 불가능하다 : 변형시키기 위해서는 해당 블록을 포함한 그 이후에 있는 모든 블록의 해시값을 다시 계산해야 한다.

해시캐시

비트코인에서 사용되는 PoW는 이메일 스팸을 막기 위해서 사용되었던 해시캐시와 상당히 유사하다, 그 과정은 다음과 같이 진행된다 :

  1. 공개적으로 알려진 데이터를 취한다. (이메일의 경우에는, 수신자의 이메일 주소 ; 비트코인의 경우에는, 이는 블록 헤더이다.)
  2. 카운터는 0에서 시작하고 1을 더한다.
  3. data + counter 조합의 해시값을 얻어야 한다.
  4. 해시값이 특정 조건을 만족하였는지 확인하라.
  • 만약 그렇다면, 일을 멈추어라.
  • 만약 그렇지 않다면, 카운터를 올리고 3,4 단계를 반복한다.

그러므로 원하는 값을 얻기 위해서는 무작위로 input 값을 바꿔야 한다 : counter를 올리고, 새 해시값을 계산하고, counter 를 올리고, 해시값을 계산하고 . 바로 이래서 많은 컴퓨터 연산과 비용이 투입된다는 것이다.

자 그렇다면, 이제는 해시값이 만족해야 하는 조건에 한번 초점을 맞추어 설명을 해보겠다. 원래 Hashcash 에서는, “해시값의 처음 20 비트는 반드시 0이어야 한다.” 라는 규칙이 있었다. 비트코인에서는, 컴퓨팅 파워가 발전하고 시간이 지날 수록 더 많은 사람들이 생기는 것과 상관없이 , 무조건 10분에 1개씩 블록이 생성되도록 설계 되어있다.

직접 예시를 보면서 해당 알고리즘이 어떻게 작동하는지 알아보자. 예를 들어 “I like donuts”라는 문구를 넣어서 결과를 받아보자. 결과에서 보면 알 수 있듯이 3개의 0 바이트로 시작한다:

뒤에 붙은 ca07ca counter의 16진수 값이다.

구현

지금까지는 이론이었고, 이제는 직접 구현해보겠다! 먼저, 채굴의 난이도를 정의해보자 :

<code 2_1 : 채굴의 난이도 설정>

비트코인에서 “target bits”는 해당 블록이 채굴되었을 때의 난이도에 대한 정보를 담고 있는 값이다. 사실 난이도는 블록이 생성되는 시간에 따라 조정되어야 하는데, 조정되는 알고리즘을 지금 단계에서는 구현하지 않을 것이다.

24는 임의로 정한 숫자이고 우리의 목표는 메모리에서 256비트 보다 작은 용량을 차지하는 타겟값을 찾는 것이다.

<code 2_2 : 블록체인 구조>

위에서 생성한 ProofOfWork 구조는 block에 대한 포인터 값 그리고 타겟값에 대한 포인터 값을 포함하고 있다. “target”은 이전 문단에서 설명한 그 목표값이다. big integer를 이용하려고 한다: 해시를 big integer로 변환한 후에, 타겟값보다 작은지를 비교하고자 한다.

NewProofOfWork 함수에는, big.Int 값을 1로 초기화하고 with the value of 1 and shift it left by 256 — targetBits bits. 256은 SHA-256 해시 결과값의 길이를 비트 단위로 센 것이다. target 을 16진수로 나타내면 아래와 같다:

0x10000000000000000000000000000000000000000000000000000000000

이 부분은 메모리에서 29 바이트를 차지한다. 그리고 아래에는 이전의 예시에서 부터 나온 해시값이다 :

0fac49161af82ed938add1d8725835cc123a1a87b1b196488360e58d4bfb51e300000100000000000000000000000000000000000000000000000000000000000000008b0f41ec78bab747864db66bcb9fb89920ee75f43fdaaeb5544f7f76ca

첫번째 해시값은 타겟값보다 크다,(“I like donuts” 를 기반으로 만들어진 해시값) 그러므로 이는 유효한 작업 증명은 아니다. 두번째 해시값은 타겟값보다 작다(“I like donutsca07ca” 를 기반으로 계산됨), 이는 유효한 작업 증명이라고 할 수 있다.

타겟값을 특정 범위의 상한선이라고 생각하는 것이 가장 쉬울 것이다: 만약 숫자(해시값)가 경계보다 작다면, 이는 유효한 것이다. 그 경계를 낮추는 것은 유효한 숫자의 개수를 줄이는 것이고, 유효한 것을 찾는데 있어서 더 많은 작업량을 필요로 한다.

자, 이제는 해싱을 할 데이터 값이 필요하다.

<code 2_3 : 해싱과정>

복잡해보이지만, 상당히 간단합니다. 단지 블록 필드에 타겟값과 논스값을 더한 것입니다. 여기서 nonce 는 위의 Hashcash에서 언급한 counter 이다, 암호학에서 주로 사용되는 용어이기에 어색한 독자들이 있을 수도 있다.

자, 이제 모든 사전 작업은 마무리가 되었고 지금부터는 PoW 알고리즘의 핵심을 구현해보자 :

<code 2_4 : PoW 알고리즘의 핵심>

일단, 변수들을 초기화하자 : hashInt는 hash의 수치 값이다. nonce 는 counter 값이다. 다음으로, 무한 루프를 돌려본다 : 사실 완벽한 무한은 아니고, math.MaxInt64의 값까지만 지원한다. 논스값 찾는데에 있어서 과도한 오버플로우를 방지하기 위함이다. 비록 현재 구현되고 있는 PoW 의 난이도는 오버플로우를 일으키기에는 많이 낮지만, 만일의 사태를 대비하여 확인하는 것은 좋을 것이다.

과정은 다음과 같다:

  1. 데이터를 준비한다.
  2. SHA-256 으로 해싱한다.
  3. 해시값을 big integer 으로 변환한다.
  4. inter을 target 과 비교한다.

이전에 설명했던 것처럼 상당히 간단하다. 이제, Block에서 SetHash를 없애고 NewBlock 함수를 수정하면 된다 :

<code 2_5 : 새로운 블록 생성 재구현>

이제 nonce 값도 block 내부 인자로 들어가 있다. nonce 값은 작업의 결과물을 검증하는데 있어서 필수적인 요소이다. block 의 구조는 이제 아래와 같다 :

<code 2_6 : 블록의 구조 재구현>

이제 잘 작동하는지 확인하기 위해 프로그램을 한번 실행시켜보겠다.

Mining the block containing “Genesis Block”00000041662c5fc2883535dc19ba8a33ac993b535da9899e593ff98e1eda56a1Mining the block containing “Send 1 BTC to Ivan”00000077a856e697c69833d9effb6bdad54c730a98d674f73c0b30020cc82804Mining the block containing “Send 2 more BTC to Ivan”000000b33185e927c9a989cc7d5aaaed739c56dad9fd9361dea558b9bfaf5fbePrev. hash:Data: Genesis BlockHash: 00000041662c5fc2883535dc19ba8a33ac993b535da9899e593ff98e1eda56a1Prev. hash: 0000004

결과에서 보이는 것처럼 Hash 값 앞 부분이 3개의 0바이트로 시작함을 알 수 있다.

한가지 해야할 일이 더 남아있다 : 작업 증명의 결과를 검증할 수 있게 하자.

<code 2_7 : PoW의 결과물을 구현>

바로 이 지점에서 논스 값을 저장해야 한다. 구현상 문제가 없는지 한번 더 확인해보자 :

<code 2_8 : main 함수 재구현>

아래와 같은 결과를 볼 수 있을 것이다.

...Prev. hash:Data: Genesis BlockHash: 00000093253acb814afb942e652a84a8f245069a67b5eaa709df8ac612075038PoW: truePrev. hash: 00000093253acb814afb942e652a84a8f245069a67b5eaa709df8ac612075038Data: Send 1 BTC to IvanHash: 0000003eeb3743ee42020e4a15262fd110a72823d804ce8e49643b5fd9d1062bPoW: truePrev. hash: 0000003eeb3743ee42020e4a15262fd110a72823d804ce8e49643b5fd9d1062bData: Send 2 more BTC to IvanHash: 000000e42afddf57a3daa11b43b2e0923f23e894f96d1f24bfd9b8d2d494c57aPoW: true

결론

이번에 구현한 결과물은 이제 실제 구조와 더 가까워졌다 : 새로운 블록을 더하는 것은 많은 어려운 작업을 필요로 한다. 그러나 아직 몇가지 중요한 핵심 기능이 빠져있다 : 지갑, 주소, 거래 그리고 합의 알고리즘 등은 아직 구현되지 않았다. 이 부분들은 앞으로 계속 구현해 나갈 것이다.

Links:

  1. Full source codes
  2. Blockchain hashing algorithm
  3. Proof of work
  4. Hashcash

--

--

Min Seo Park
CAU_CLink

Interested in Blockchain, Project Financing and Smart city and Love DJing and EDM