— JavaScript — 2 min read
자바스크립트로 블록체인을 구현해보자
블록체인에 대한 막연한 호기심을 가지고 있다가, 대략의 원리라도 알아야겠다 싶어 공부를 했습니다. 분산형 장부, 암호화 기술로 만들어지는 경제와 그곳에서 통용되는 화폐인 암호 화폐에 대한 이야기를 조금씩 공부했습니다. 책도 읽어보고 영상도 찾아봤습니다. 띄엄띄엄 이해가 되지만 역시 코드로 구현해보지 않고서는 제대로 이해할 수가 없었습니다. 그래서 검색했습니다. 'JavaScript', 'BlockChain' 등의 키워드로 검색했더니 아니나다를까 이미 자바스크립트로 블록체인을 구현한 자료가 많았습니다.
저는 그 중에 Savjee라는 분이 유튜브에 올려둔 영상과 코드를 참고했습니다. 객체 지향으로 구현한 방식을 제 방식으로 풀어서 정리해보려고 합니다. 이전에 소개해드린 함수들도 사용하면서 다소 정신 없이 코드를 써내려가볼까 합니다. 몇차례 쓰게 될지 모르지만 일단 시작합니다.
앞으로의 글은 아주 대략적으로 제가 이해하고 있는 수준에서만 설명하겠습니다. 이하 모든 내용은 정확한 설명이 아닐 수 있음을 미리 밝힙니다.
블록체인에서 말하는 블록은 거래내역을 모아둔 데이터 구조 단위입니다. 여기에 블록이 체인이 되기 위해 다른 블록의 주소값을 가지고 있죠. 그리고 블록이 생성된 시간과 자신의 주소값을 가지고 있습니다. 그래서 아래와 같은 데이터 구조를 갖습니다. (구현을 위한 간략한 구조입니다.)
1let Block = {2 previousHash: '',3 timestamp: '2018-06-22T07:29:19.198Z',4 transactions: [ { a: 10, b: -10 }, { a: -10, b: 20, c: -10 } ],5 nonce: 79431,6 hash: '0000c067110339dd0f6d844112fa3a7a02142ccb133aad2dc6ebb4709c7651c7'7};
이전 블록의 해시값입니다. 예제의 경우 previousHash
가 빈 문자열이 담겨있는데, 이는 해당 블록이 최초의 블록이기 때문입니다. 블록체인에서는 최초의 블록을 Genesis Block이라고 부릅니다. 두번째로 생기는 블록은 이 블록의 해시값을 previousHash
로 갖게 됩니다.
블록이 생성된 시간 데이터입니다. 이 부분에 대해서도 제대로 다룰려면 글 하나를 써야할 것 같습니다. 참고한 글에 따르면 블록체인에서의 타임스탬프는 기존의 그것과 다른 점이 많다고 합니다. 우선은 블록이 생성된 시간이라고 알아두죠.
발생한 거래의 내역(리스트)입니다. 실제로는 머클트리(Merkle Tree)라는 구조로 거래 내역을 담아두고 이를 저장합니다. 저는 간단하게 배열의 형태로 거래 내역을 담아두겠습니다. 거래는 객체 형태로 담아두는데 { a: 10, b: -10 }
이렇게 적어둔건 그냥 'a의 잔고가 10만큼 늘었고, b의 잔고는 10만큼 줄었다.'는 뜻이라고 해두겠습니다.
해시값을 얻기 위해 찾아야하는 값입니다. 미리 설명하지 않은 이 값은 채굴(mining)이라고 일컫는 작업을 통해 구해지는 값 중 하나입니다. 여기서 채굴에 대해 잠시 언급하고 지나가면, 아시다시피 노드(참가자)들은 채굴을 통해 보상(화폐)을 얻습니다. 여기서 말하는 채굴은 hash
라는 값을 구하는 활동입니다. 원하는 hash
값을 얻기 위해서 nonce
라는 값을 계속 바꿔보면서 결과 값을 맞춰봐야 합니다. 결과적으로 우리가 원하는 형태의 hash
가 생성되면 그때 사용된 nonce
가 블록에 기록되는 것입니다. (이렇게 만들어진 값을 가지고 다른 노드들이 제대로 hash
가 만들어진 것인지 확인하는 작업이 바로 작업증명(PoW: Proof of Work)인 것이죠.)
해당 블록의 주소 값입니다. 채굴을 통해 얻어진 값인 hash
는 예제와 같이 아주 길고 복잡한 문자열로 구성되어 있습니다. 16진수(Hexadecimal)로 표기되는 값으로 암호화 알고리즘인 SHA256으로 만들어진 해시함수가 생성한 값입니다. 이때 해시함수에 인자로 주어지는 값들은 previousHash
, timestamp
, transactions
, nonce
입니다. 이 값들의 조합은 유니크합니다. 때문에 이 값을 해시함수에 통과시키면 본 블록만의 유니크한 hash
값을 만들 수 있습니다.
아마 이쯤에서 의문이 생기거나 뭔가 아다리(?)가 맞지 않는다고 느껴지실 겁니다. 도대체 hash
값이 어떻게 생겨먹어야하길래 보상을 줄만큼 구하기 어렵다는 것이냐, 그냥 nonce
에 아무 숫자나 때려 넣으면 되는 것 아니냐 하는 생각이 드실 겁니다. 당연한 생각입니다. 블록체인에서는 원하는 hash
값에 제약 조건을 겁니다. 이 조건은 특정 숫자보다 hash
값이 작아야한다는 조건입니다. 특정 숫자를 구하는 방식은 여길 참고하시면 됩니다.
예제의 데이터 구조에는 포함하지 않았지만, 제약 조건이 얼마나 어려운 제약인지를 설명하는 것을 난이도(Difficulty)라고 부릅니다. 조금 쉽게 구현하기 위해 저는 난이도만큼의 0을 hash
가 앞자리로 가져야한다는 조건으로 제약을 두고 구현할 예정입니다. 예제의 경우는 hash
값의 시작 지점에 0이 4개(0000c067...
)임으로 난이도가 4입니다.