자바로 블록체인 만들기 Part 1

김성재
CAU_CLink
Published in
9 min readAug 12, 2018

원문 : https://medium.com/programmers-blockchain/create-simple-blockchain-java-tutorial-from-scratch-6eeed3cb03fa

원저자 : Kass, kassCrypto@gmail.com

블록체인에 관심을 가지고 이것저것 찾아보면 블록체인의 기본 원리에 대해 이해하는 데에는 크게 어렵지도 않고, 시간이 많이 걸리지도 않을 것이다. 하지만 뭔가 찝찝하다. 필자는 컴퓨터 공학과를 재학중이고, 개발자를 목표로 하다보니까 이 블록체인이라는 것이 실제로 어떻게 작동되나 궁금했다.

비트코인이나 이더리움 같은 블록체인 플랫폼은 깃허브에 오픈소스로 공개되어 있다. 하지만 그 양과 내용이 너무나도 많고 기본 개념을 안다고해도 코드를 이해하기란 쉽지 않다. 그래서 블록체인을 간단하게 구현하면서 차근차근 이해해가면 어떨까라는 생각을 하였고 때마침 미디엄(Medium)에 올라온 좋은 글이 있어서 소개하고자 한다.

이 글은 JAVA 언어로 블록체인을 구현했고, 블록체인을 처음 접하는 개발자로서 블록체인 코어를 공부하기에 앞서 한번쯤 읽고, 구현해보면 도움이 될 만한 글이라고 생각된다. 이 글은 세 가지 part로 나뉘어져 있고 세 번째 part는 아직 작성 중이라고 한다. 아래는 part별로 다루어질 내용이다.

Part 1

- 기본적인 블록체인 만들기

- PoW(Proof of Work) 시스템 구현하기

Part 2

- 지갑 만들기

- 트랜잭션 구현하기

Part 3

- Peer2peer Network 구현하기

- Consensus algorithm

- 블록 저장소와 DB

Part 1

블록체인 만들기

블록체인은 말 그대로 블록이 체인(chain)으로 연결되어 있는 구조이다. 기본적으로 각각의 블록은 자신만의 해쉬 값, 이 전 블록의 해쉬 값, 그리고 데이터(ex> 트랜잭션)를 가지고 있다. 각각의 블록에서 해쉬값을 도출할 때엔 데이터와 이 전 블록의 해쉬값을 사용한다.

이 대목에서 블록체인의 보안성을 확인할 수 있다. 만약 이 전 블록의 데이터가 조금이라도 변한다면 해쉬값도 변하게 되고, 그렇다면 그 이후의 블록에도 영향을 미치게 되어서 올바르게 체인을 이어나갈수 없다. 또한 이 체인은 블록체인을 사용하는 모든 사용자(노드)들이 같은 체인을 가지게 되고, 각자의 체인이 같은 체인인지 비교하게 된다.

즉, 데이터 위, 변조가 쉽지 않다는 것을 확인 할 수 있다. 결론적으로는 해시 계산 및 비교를 통해 블록체인의 유효여부를 확인할 수 있다.

Blockchain의 구조

위의 그림에서 확인해 볼 수 있듯이 블록은 이 전 블록의 해쉬값을 가지고 있는 것을 볼 수 있다. 이러한 해쉬값을 가지고 블록을 연결시킨다는 의미에서 체인이라는 단어를 쓰는 것이다. 일단 첫 번째로 이것을 코드로 구현해 보자. 원저자는 이 프로젝트(이 블록체인)을 NoobChain이라고 지었다.

위의 코드에서 변수 hash는 블록을 식별할 수 있는 데이터들의 집합을 해싱한 결과값을 담을 것이고, previousHash는 이 전 블록의 hash 값을, data는 블록의 데이터를 담는 변수이다.

다음으로, 블록의 해쉬값을 만드는 방법이다. 많은 암호 알고리즘이 있지만 이 예제에서는 SHA256을 쓸 것이다. 실제로 비트코인에서도 SHA256을 쓴다. 이 알고리즘을 쓰기 위해 java.security.MessageDigest를 import 해주자. 그리고 이 알고리즘을 이용해서 hash값을 만들어내는 메서드를 만들어 준다.

코드 출처 : http://www.baeldung.com/sha-256-hashing-java

MessageDigest나 SHA256 알고리즘 작동방식을 이해 못한다고 걱정할 필요는 없다. 이글의 목적은 블록체인의 원리를 이해하기 위한 글이기 때문이다.

다음으로 블록의 고유 식별자가 될 hash 값을 얻기 위해 블록을 hashing하는 메서드를 만들어주자. 블록 안의 데이터 값과 이 전 블록의 hash값을 이용해서 hash값을 도출해 내는 메서드이다. hashing 될 data 값에는 previousHash, data, timestamp가 들어간다.

우리가 데이터를 해쉬화 하는 과정을 간단히 도식화 한 것이다. SHA256 해쉬화 과정을 거치고 나면 데이터가 일정한 길이의 문자열로 암호화된다.

또한 생성자에 이 메서드를 넣어주자.

중간 점검 차원에서, 이것들이 어떤 의미를 갖는지 확인해 보자. Main Class인 NoobChain Class에서 블록을 만들고, 제대로 작동하는지 출력해 보자.

여기서 주의할 점은, 첫 번째 블록은 이 전 블록이 없다는 점이다. 그래서 이 전 hash 값을 넣는 자리에 “0”을 넣어 준다. 블록체인 상에서 이러한 블록은 genesis block 이라고 칭한다.

Genesis블록(최초블록) : 블록체인에서 최초의 블록을 가리킨다.

결과값

hash 값에 timestamp도 들어가므로 결과값이 위와 다를 것이고 실행할 때 마다 달라진다.

이제 각각의 블록은 자신만의 해쉬값을 갖는다. 그런데 이렇게 블록을 만드는데 변수 명도 지어줘야 하고 굉장히 어색해 보인다. 그래서 우리는 ArrayList라는 자료 구조를 이용할 것이다. 그리고 Json을 이용하기 위해 Gson 라이브러리를 사용한다.

Gson : Json 형식의 데이터를 객체에 자동으로 담아주는 기능을 제공하는 라이브러리

이제 우리 블록체인의 무결성(integrity)을 확인해 보자.

블록체인에서 무결성이란 체인으로 연결되어 있는 블록들의 hash값이 같은 지. 즉, 데이터의 위변조가 있는지 확인하는 것을 뜻한다. ArrayList로 연결시켜 준 블록들의 무결성을 확인해 보기 위해 NoobChain Class에서 Boolean 타입의 isChainVaild 메서드를 만들어 주자.

이 전 블록과 현재 블록의 hash 값을 비교하면서 같은 지 판단하는 간단한 코드다. 만약에 블록체인 안의 블록에 위변조가 일어나면 false를 반환하게 된다.

간단한 PoW 시스템 구현하기

비트코인 네트워크에서 노드들은 네트워크상의 블록체인을 서로 공유한다. 그럼 블록체인 상에서 악의적인 노드가 데이터를 위변조 하거나 네트워크를 위협 할 때 어떻게 대처할까?

모든 노드가 올바른 블록체인을 공유하고 있다는 것을 입증하기 위해서 합의 알고리즘을 사용한다. 다양한 합의 알고리즘이 있는데 비트코인에서는 PoW(Proof of Work)라는 합의 알고리즘을 사용한다. PoW란 컴퓨팅 파워를 이용해 블록의 hash값을 추적하여 블록체인 네트워크에 새로운 블록을 추가하는 방식인 합의 알고리즘이다.

이 과정을 채굴(Mining)이라고 부르는데 PoW 방식의 알고리즘은 다량의 컴퓨팅 파워를 요구하고 시간 또한 오래 걸린다. 그래서 공격자는 그만큼 많은 컴퓨팅 파워를 요구하게 된다.

hash값의 추적은 hash값 첫 부분의 0 개수를 추적하는 과정이며 이를 위해서는 계속해서 다른 변수값을 블록에 넣으면서 조건을 만족할 때 까지 hashing하는 것이다. 0의 개수가 많아질수록 추적은 어려워지며 ‘난이도(difficulty)가 높다’고 말한다.

위에서 말한 ‘다른 변수값’이란 비트코인에서 nonce라고 불리며 우리 코드에도 적용시켜 보자.

hash를 계산할 때, nonce값을 추가하여 hash값을 만들어 준다. 이 nonce 값은 블록을 채굴하기 위해 사용되는 값이다. 이 코드에서는 nonce 값을 0에서부터 1씩 증가시키며, 특정 조건을 만족시킬 때 까지 hashing과정을 거치게 된다.

mineBlock이라는 메서드와 파라미터로 difficulty(난이도) 라는 것이 추가되었다. 이 메서드는 difficulty를 이용해 hashing된 값의 앞 자리에서 부터 나타나는 0의 개수를 정한다. difficulty 값이 높아지면 그만큼 0의 개수도 많아지고, 조건(0의 개수)에 맞는 값을 찾아가는 데에는 더욱 오랜 시간이 걸리게 된다.

앞 자리의0의 개수가 많아져야 할 수록 그에 맞는 조건을 맞추기는 어렵다. 위의 예제에서는 timestamp, nonce, previousHash 등의 집합으로 hashing이 이루어진다. 쉽게 설명하기 위해, 주사위 예시를 들 수 있다(마스터링 비트코인 참고). 주사위 두 개를 던져서 나올 값의 합이 특정 목표값 보다 낮은 숫자가 나올 확률을 생각해보자. 만약 목표값이 12이면 (6, 6) 을 던지지 않는 이상 성공한다. 거의 100%에 가깝다. 하지만 목표값이 11, 10, 9… 점점 떨어지면 확률 또한 기하급수적으로 떨어진다. 만약 목표값이 2라면 주사위를 던져 (1, 1)이 나와야 하므로 확률은 1/36, 약 2%이다. 이런식으로, hashing 과정에서 0의 개수가 늘어난다는 것은, 목표값에 만족할 수 있는 확률 또한 기하급수적으로 낮아진다는 것이다.

이제 채굴과 검증 과정을 한 번 확인해 보도록 하자.

difficulty를 5로 설정하고 3개의 블록을 채굴하는 데에 필자의 노트북으로 6초 정도가 걸렸다. difficulty가 높아질 때 마다 채굴하는 데에 시간이 오래 걸리고, cpu 팬이 팽팽 도는 소리를 들을 수 있을 것이다.

만약 악의적인 노드가 데이터를 위변조 하려고 한다면

  • 위변조된 블록은 유효하지 않을 것이다.(Invalid)
  • 기존의 체인에 붙지 않을 것이고 악의적인 노드가 자체적인 체인을 만들려고 한다해도,
  • 이것은 기존의 체인보다 긴 체인을 만들 수 없다.

이로서 part1이 끝났다.

part2에서는 블록체인 안에서 거래를 일으키고, 지갑을 구현할 것이다.

--

--