이번에는 블럭을 '채굴'한다는 것이 무엇인지, 구체적으로 어떻게 이루어지는지 알아보자.
개인적으로 이 파트를 공부하면서 코드로 구현하는것도 중요하겠지만
우선 각 용어의 정의를 명확하게 인지하고 가는 것이 다른 부분에 비해 매우 비중이 높다고 생각했다.
그래서 개념에 대한 정리를 먼저하고, 이를 코드로 구현하는 것은 나중에 할 것이다.
블럭을 아무나 쉽게 만들어서 가져다 붙일 수 있게 하면 안된다.
그래서 블럭 체인 네트워크에서는 특정 작업을 완료한 사람만이 블럭체인에 블럭을 추가할 수 있는 자격을 부여한다.
작업을 완료한 후, 이를 다른 네트워크 참여자들에게 검증을 거친 후 (증명), 블럭체인에 새로운 블럭을 추가하는 것을
채굴이라고 하며 이 채굴 방식은 작업의 증명, 작업증명(Proof of Work, POW) 라고 한다.
그럼 그 작업이라는 것이 구체적으로 무엇인가?
일반적으로 이 작업은 컴퓨터의 연산을 통해 특정한 조건을 만족하는 값을 찾아내는 것 으로 정의한다.
조건이 까다로울수록 난이도는 상승하며, 조건이 느슨해질수록 난이도는 하락한다.
만약 블럭의 채굴 속도가 너무 빠르다면 조건을 어렵게 만들어 연산에 소요되는 시간을 늘려 채굴 속도를 낮추고,
반대로 너무 느리면 조건을 느슨하게 만들어 연산에 소요되는 시간을 줄여 채굴 속도를 높힌다.
이런 방식으로 블럭이 체인에 추가되는 속도를 어느 정도 범위에서 움직이도록 조절할 수 있다.
우리가 새로운 블럭을 만들 때 반드시 만들어서 넣어줘야 하는 요소가 hash였다.
이 때까지는 편의상 hash를 만드는데 version, timestamp, height, merkleRoot, previousHash 5가지의 값만을 사용했지만
앞으로는 hash를 만들 때 2가지 요소(difficulty, nonce)를 더 개입시킬 것이다.
const values = `${version}${timestamp}${height}${previousHash}${merkleRoot}${difficulty}${nonce}`
const hash = SHA256(values).toString()
이제 hash를 생성하는데에는 (merkleRoot를 제외하고) 4개의 상수에 더해 1개의 상수(difficulty)와
1개의 변수(nonce)가 추가적으로 개입하게 된다.
(수학적인 상수, 변수와는 약간 결이 다르다. 채굴자 입장에서 difficulty는 정해져 있지만,
nonce는 채굴자가 바꿀 수 있다는 의미)
1. 난이도 (difficulty)
채굴을 하는데 난이도가 높다는 것의 구체적인 정의에 대해 알아보자.
이를 위해서 우선 hash의 데이터 타입에 대해 다시 한 번 짚고 넘어가야 한다.
hash는 64자리를 가지는 16진수인데, 이는 SHA256 암호화 알고리즘을 거쳐 생성된다.
SHA256 알고리즘은 문자열의 길이에 관계없이 무조건 결과물을 64자리의 16진수로 준다.
여기서 주목할 점은 이게 16진수라는 점인데, 16진수를 2진수로 바꾸면 16이 2의 4제곱이기 때문에
그 자릿수는 4배가 된다.
hash는 16진수의 64자리 수이므로 이를 2진수로 바꾸면 256자리가 나온다.
예를 들어 16진수 4a44dc15364204a80fe80e9039455cc1608281820fe2b24f1e5233ade6af1dd5 를 2진수로 바꾸면
01001010010001001101110000010101001101100100001000000100101010000000111111101000000011101001000000
111001010001010101110011000001011000001000001010000001100000100000111111100010101100100100111100011
11001010010001100111010110111100110101011110001110111010101
를 얻을 수 있다.
가장 큰 자리부터 읽어보면 처음에 0이 1개 나온다.
이 '처음에 오는 0의 수' 가 난이도의 핵심이다.
2진수로 변환했을 때 그 결과물의 처음에 오는 0의 수가 n개가 되는 hash값을 찾아달라고 요구를 하는 것이
'문제를 낸다'는 것의 정의이고,
이 조건을 만족하는 hash값을 구하는 것이 '문제를 푼다'는 것이다.
문제를 낼 때 요구하는 '처음에 오는 0의 갯수'가 많아지면 많아질수록
그 조건을 만족하는 hash값을 찾는 것은 더욱 어려워진다.
이것이 '난이도가 높다'는 것의 의미가 된다.
difficulty라는 '숫자'는 2진수 변환 결과물의 첫자리부터 연속되는 0의 갯수가 된다.
한 블록 체인의 난이도가 10이라면
이 블록체인은 채굴자에게 2진수로 변환했을 때, 결과값이 첫 10개 자릿수가 0인 hash값을 답으로 요구하는 것이다.
2. 넌스 (nonce)
hash를 만드는데 필요한 모든 데이터는 상수이다. 채굴자는 주어진 값만을 조합해 hash값을 만들어야 하는데,
이렇게 만들어진 hash값은 당연히 조건을 만족하는지 알 수 없다.
문제는 이렇게 hash값 자체가 상수인 경우, 그 hash값이 조건을 만족하지 못하면 새로운 블럭을 추가하는 것이
아예 영영 불가능해진다는 것이다.
그래서 추가되는 것이 nonce 값이다. hash값을 만들 때 채굴자가 변화시킬 수 있는 변수를 하나 추가해줌으로써
여러 개의 hash값을 만들 기회를 가지게 되는 것이다.
채굴자는 nonce값을 1에서 시작해 계속 1씩 증가시켜가며 hash를 만들고, 그 hash값이 조건을 만족하는지 확인한다.
nonce값에 1을 주고 > hash값을 만들고 > 2진수로 변환한 후 > 주어진 조건을 만족하는지 확인 >
i) 조건을 만족하는 경우 > 채굴 성공. 네트워크의 다른 노드에게로 전달해 검증 과정을 거친다.
ii) 조건을 만족하지 못하는 경우 > 채굴 실패, nonce값을 1 증가시킨 후, hash값을 만드는 것부터 반복한다.
난이도가 높을수록 조건을 만족할 가능성이 낮아지므로 연산의 반복 횟수도 늘어나고, 이에 따라 블럭 난이도에 따라
nonce값도 증가하는 경향성을 가진다.
다음 글에서는 이 nonce와 difficulty 값이 어떤식으로 코드에 담겨서 사용되는지 알아보자.
'Blockchain' 카테고리의 다른 글
#9 체인 최신화 (0) | 2022.06.17 |
---|---|
#8 mining ch.2 - 활용 (0) | 2022.06.17 |
#6 chain (0) | 2022.06.12 |
#5 block 검증 (0) | 2022.06.12 |
#4 block 생성 (0) | 2022.06.12 |