Blockchain 들여다 보기 2
3. Genesis Block을 Hex형식으로 받기
chainblock.info를 사용해서 Genesis Block을 연 상태에서, 브라우져의 윗쪽은 다음과 같을 것이다.
즉, 주소창이 https://blockchain.info/ko/block/000000000019d. . . .26f 과 같이 되어 있을 것이다.
무슨 말인가 하면,Block Height인 0을 검색하더라도, 실제로는 Block #0의 Block id인
000000000019d668. . . . . e26f
를 써서 검색이 이루어 지고 있었다는 것이다.
이 주소의 끝에,다음에 보인 것 처럼, "?format=hex"를 끝에 추가한 후 ,Return Key를 쳐보라.
그러면, 다음 처럼, Block #0의 전체내용을, 16진수(Hexadecimal)로 표현된 형식으로, Browser가 받게된다.
이 내용을 mouse로 긁어서 복사한 후, Text file(Notepad를 열어서)을 하나 만든후, 그 속에 복사해 넣는다. 한 행에 40Byte(16진수 80개)가 보이도록 화면의 폭을 조정해 두는 것이 편리할 것이다. 첫행의 끝이 3ba3edfd로 되면 40Byte가 맞다.
결국, 다음 처럼 되면 한행당 40Byte가 되어 OK다.
그런데,Block Header는 Block의 선두 80Byte 고정된 크기이다. 그러므로 윗 그림에서 첫 2행의 내용이 Block Header인 것이다.
그래서, 다음 처럼 Header와 나머지 부분을 분리 시키자.
4. Block Header의 Format
Block Header는 선두 80Byte로써, 6개의 Entry가 포함되어 있다.
둘째와 셋째 Entry들은 각각 32Byte이고,나머지Entry는 전부4Byte로 되어 있다.
다음 그림은 Header를 Entry별로 나누어 본 것이다.
4.1 Version
우선 Protocol Version을 보자. 점으로써 Byte경계를 표시하기로 하면,
01.00.00.00 으로 되어 있는데,
이것이 실제로 나타 내고자 하는 정보는 Byte역순인
00.00.00.01 이다.
즉, Version Number는 1인 것이다.
이렇게, Byte순서가 정반대로 되어 있는 것을 "Little Endian"이라고들 한다.
Header의 모든 Entry들은 "Little Endian"방식으로 써 있다는 점에 주의하기 바란다.
다음은 경주 불국사의 현판인데 우측에서 좌측으로 써있는 것을 아는가?
이처럼,Header의 모든 Entry들은 Byte순서가 역전된 "Little Endian"으로 기술되어 있다.
4.2 Previous Block의 id
Genesis Block에서는 전Block이 없으므로, Nakamoto들은 임의로 000. . . . 00으로 Set한 것이다.
4.3 Merkle Root
이 Block은 Coinbase Tx한개만 포함하고 있으므로, 그 거래의 Txid인,
(Block #0 의 page에서, 아랫쪽 Coinbase Tx에 파란색으로 표시되어 있음),
4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
가 되어야 하나,
역시 불국사 현판처럼 , "Little Endian"방식으로,
3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a
로 써 있음을 알수 있다.
4.3 Time Stamp
이Entry는 Unix Epoch time을 넣도록 되어 있다.
이것은 Unix OS가 세상에 나온 것을 기념하여, 그 시점을 기준으로 하는 Time이다.
Little Endian에 이젠 익숙해 졌을 것이다. 495fab29 라는 의미로 받아들여야 한다.
이를 10진수로 변환하는 데는 2가지 방법이 있다.
(1)16진법방식
16진수란 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f 총 16개의 기호로써 수(數)를 세는데 사용하는 체계이다. 따라서, 여기서는 a,b,c,d,e,f 는 문자(文字)가 아니라 숫자(數字)인 것이다. 각 16진수 한개는 4bit에 해당한다.
10진수에서,
12506=1x(10^4)+2x(10^3)+5x(10^2)+6 이듯이,16진법도 이런 논리는 마찬가지다.
그러므로 16진수
495fab29 = 4x(16^7)+9x(16^6)+5x(16^5)+15x(16^4)+10x(16^3)+11x(16^2)+2x(16^1)+9
=1,231,006,505
(2)256진법으로 보는 방식
이것은 1Byte(8bit),즉 16진수 2개, 를 하나의 숫자로 파악하는 개념이다.
즉, 16진수 495fab29는 원래,
. . . . . .0000. . .0000495fab29 으로 쓸 수 있는데,
맨 우측 부터,2개씩을 묶어,그것을 한개의 수처럼 파악하자는 것이다. 한개의 수처럼 파악한 것을 [ ]로 묶어서 표시하겠다.
즉, . . . [00][00]. . .[00][00][49][5f][ab][29]
로 보자는 것이다. 그런데,선두의 무한히 많은 [00]들은 생략하는 것이므로,결국,
[49][5f][ab][29]
가 되는데,256진수 숫자 4개로 파악하는 것이다.
[ ]는, [00],[01],[02]. . .[0f],[10]. . .[2f],[30]. . .[ef],[f0]. . .[ff]까지 총 16x16=256개의 숫자를 표현할 수 있으므로,
256진법인 것이다.
그러므로,
[49][5f][ab][29]
=[49]x(256^3)+[5f]x(256^2)+[ab]x(256^1)+[29]
=(4x16+9)x(256^3)+(5x16+15)x(256^2)+(10x16+11)x(256^1)+(2x16+9)
=1,231,006,505
이 Unix Time을 우리가 일반적으로 쓰는 시간으로 변환하기 위하여, 다음 Site를 열어서
우측 아랫쪽 칸에 1231006505를 넣어서 "Convert"를 해보라.
Unix Epoch Time
01/03/2009 @ 6:15pm (UTC) 가 나올 것이다.
4.4 Bits
이 항목을 사람에 따라서는 nBits라고 표현하기도 하고,Target이라고 말하기도 하는데,
채굴에 성공하자면,Nonce를 잘 정해서,Block Header의 Hash값이
이 Bits가 "제시하는" 숫자와 같거나 적으면 되는 것이다!
그런데,이 Bits에서는 지수(Exponent)와 가수(Mantissa)를 이용하는 표현이 사용되는 점이 좀 다르다.
수학에서 아주 큰 수나 작은 수를 표시할 때는(10진수에서),
가령 0.314x10^9 이라든지, 0.314x10^(-8)과 같은 방식으로 나타낸다.
전자는 314000000이고,후자는 0.00000000314 이다. 이 때,0.314를 가수라 하고, 9나 -8은 지수라 하는 것이다.
우리의 예에서 Bits는 ffff001d 지만,이것은 Little Endian식 표기이므로,
Big Endian으로 바꾸어서, 1d00ffff 의 뜻으로 이해해야 한다.
앞서 설명 한바 있지만,이것을
4개의 숫자(256진법 숫자) [1d],[00],[ff],[ff]가 나열된 것, 즉
[1d][00][ff][ff]로 파악하는 것 까지는 위 4.3의 (2)에서와 같다.
그런데 Bits의 경우는, 첫수 [1d]를 지수로 보고(256을 base로한), [00][ff][ff]는 소수점이 [00]의 바로 왼쪽에
있는 가수로 보라는 것이다.
다시 말해서 가수를 [00].[00][ff][ff] 로 보고,
[1d]는 지수로 보라는 뜻이다.
그러므로 Bits가 "제시하는" 숫자는,
[00].[00][ff][ff]x{256^([1d])}= 0.00ffff x {(256)^[1d]} 인 것이다.
만약,지수가 [1d]가 아니고,[00]이었다면,{256^([00])}=1이 되어,
그냥, [00].[00][ff][ff]= 0.00ffff가 되었을 것이고,
지수가 [01]이었다면, 위의 소수점이 우측으로 1칸 움직여서,
[00].[ff][ff] = 0.ffff 가 되었을 것이며,
[03]이었다면,우측으로 3칸을 움직여서
[ff][ff] =ffff 가 되었을 것이다.
그런데,[1d]= 16+13=29이므로,
결국 Bits가 제시하는 숫자는,
[ff][ff]뒤에 [00]이 26번 되풀이 되는 수이다. 결국,[ff][ff]로 시작하는,256진수 28개로 이루어진 수란 뜻이다.
한편,우리는 32Byte의 범위(256진수 32자리)에서 생각을 하고 있는 고로, 결국은 앞쪽에 [00]을 4개 더 붙친
[00][00][00][00][ff][ff][00][00][00]. . . .[00] (Total 32Byte)
로 봐야 하는 것이다. 다시 말해서 Bits가 제시한 숫자는,
00000000ffff000000. . . . 00 (Total 32Byte)
이었다.
4.5 Nonce
이것도 7c2bac1d 로 이해 해야 하며,
굳이 10진수로 변환해 본다면, 2083236893 이 나오지만, 숫자로써의 이값 자체는 별로 의미가 없다.
요컨데,4Byte(32bit)인 이곳에 이런 저런 Bit Pattern을 넣어가며,그 때 마다 Header의 Hash를 얻어, 위의 Bits가 제시하는 수를 넘지않는 결과가 나오는지 여부를 계속 반복하는 것이 "채굴"한다는 것의 내용인 것이다.
Nakamoto들은 Nonce에 0부터 1씩 증가해 가며,Header를 Hash하여, 그 때 마다,
Hash결과가 위의 Bits가 제시한 값과 대조하는 것을 반복하다가,
Nonce가 7c2bac1d가 되었을 때,Bits의 조건에 합치함을,즉 채굴에 성공했음을, 알았을 것이다.
Nonce를 ffffffff 부터 시작하여 1씩 줄여 나가든, Random하게 마구잡이로 하든, 어떤 것이 더 좋다고 말할 수도 없다.
Hash함수의 특징(엄청난 불연속 함수다)상, 한Bit만 달라져도 그 결과는 "상전벽해",완전히 달라지기 때문이다.
이제는, Block Header의 Hash결과 값이 Bits의 Target에 합치함을 확인해야 하고 싶다.
그런데, 그전에 좀 주의할 사항이 있으므로,다음 5절에서 Text file과 Binary file의
차이점을 강조한 다음 6절에서 Block Header의 Hash를 실제로 해보기로 한다.
5. Text 과 Binary 의 차이
다음 링크를 "새탭에서 링크열기"를 해보아라.
sha256 Calculator-text-input
data로써 "1a3f"를 입력한 다음,sha256 Hash 를 실행해 보면,다음처럼,
655191b8b2ead2c6854a6ff04104cf11d53beaea49736c14ef8ed6ff573d2d0f
가 출력 될 것이다.
한편, 다음 링크를, 역시 "새로운 탭"에서 열어보라.
Sha256-Hex-input
그리고 나서,"Enter as Hex"의 왼쪽을 클릭하고, 입력난에 "1a3f"를 써넣은 후,그 아래에서 Hash함수중 sha256을 선택한 다음 "Caculate"를 클릭해 보아라.
다음 처럼,
4b8b2006c56bc2be7a9333022d98a3a6711327b31d50759c2a0fe9df534ac5dd
의 출력을 얻을 것이다.
같은 입력을 했는데도,Sha256의 결과가 다른 이유를 아는가?
앞의 것(Text input)은 , 1a3f 를 문자 4개 1,a,3,f로 보아, 그 4개 문자에 대응하는 ASCII Code인
[31],[61],[33],[66] (이것은 Hex이며,10진수로는 49,97,51,102에 해당)로 파악하는 것이다.
다시말해서,binary인
00110001 01100001 00110011 01100110
를 Hash하게 되는 것이다. (또,위의 binary형태가 바로,Notepad로 메모장을 열어, 1a3f를 입력하여 file로 저장했을 때의,file의 실제 내용이기도 하다.)
참고로 ASCII code를 보고자 한다면 이 링크를 눌러 보기 바란다.
따라서 가령,Hex input방식인 후자에서 입력난에 33613366을 넣어서 Hash하면,
전자인 Text input방식에서 "1a3f"를 입력하여 Hash했을 때의 출력과 동일한
655191b8b2ead2c6854a6ff04104cf11d53beaea49736c14ef8ed6ff573d2d0f
를 얻게 될 것이다. 다음을 보라.
이제 필자가 무엇을 말하고자 하는지 알게 되었을 것이다.
Block #0의 Header를 Hash하자면 , Hex input을 받는 방식인 2번째 Web Site를 이용해야 한다.
6. Block Header의 Hash
이제 Genesis Block의 Block id를 계산할 모든 준비가 되었다.
그런데,한가지,여기서 고백할 것이 하나 있다.
지금까지 "Hash를 한다"는 설명을 여러번 했었으나,실제로는 "Double Hash"를 하는 것이었다.
무슨 말인고 하니, X가 Hash할 대상이라고 할때, Sha256(X)를 하는게 아니라
Sha256(sha256(X))를 해야 한다는 말이다.
이것을 앞으로는 DSha256이라고 표시하겠다.
3절에서 받아둔 Block #0의 Block Header(선두 80Byte)를 입력하여 Sha256을 1차 시행 하면,다음과 같이 나올 것이다.
Sha256출력을 마우스로 복사하여 입력난에 "붙여넣기"를 하여 2차로 Sha256을 시행하면
다음 처럼 될 것이다.
결국,DSha256 한 결과는
6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000
가 되는데, 이것을 Little Endian Format이라 간주하여,Byte역순으로 바꿔보면,
000000000019d6689c085ae1. . . . . .0a8ce26f
이 되는데,과연 이것은 Block #0의 page에서 우측의 "Hash"난에 나오는 그 값과 같음을 확인할 수 있을 것이다.
또,이것이 Block #0의 Block id 이기도 하다.
한편,이 값은 4.4에서 설명한 Bits의 Target 숫자인
00000000ffff000000. . . . 00 (Total 32Byte)
보다 분명히 적어서,아주 여유 있게(0이 2개나 여유가 있다) "채굴합격"을 Pass한 것이었다.
7. Merkle Root의 계산
Block #0는 Coinbase Tx 1개 밖에 없으므로, Coinbase Tx의 Txid가 그대로 Merkle Root가 된다. 따라서, Merkle Root를 구하는 문제는 Coinbase Tx의 내용을 DSha256하는 것으로 귀착된다.
다만, 주의 할것은 Transaction부분의 제일 첫 Byte는
이 Transaction부분에 몇개의 Tx이 포함 되었는가를 보이기 위한 Tx Counter이므로,
이 첫Byte를 제외한 나머지 부분이 Coinbase Tx의 본 내용이 된다는 점이다.
그러므로, 다음 처럼 Coinbase Tx내용을 복사한후 DSha256을 실행하면 된다.
Block #0 page의 우측에서 표시되는 Merkle Root는
4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
이지만,Coinbase Tx내용을 DSha256을 실행한 결과는 위의 Byte역순이 될 것이다.
다음 8절에서는 Block #1을 살펴보고,Block #1과 어떻게 연계가 되는지를 볼것이다.
좋아요!
감사합니다
보았습니다
와 대단하십니다. 북마크해놓고 집에 가서 정독해야겠습니다 팔로합니다
팔로우 감사! 감사! 힘이 좀 나는군요. 우리나라의 젊은 Programer들이 Blockchain tech에 관심을 갖고 배우면,창창한 길이 열릴텐데. . .
중국 아이들 무섭습니다. Bitcoin채굴도 일찍부터 주도하는 나라입니다. 정신 바짝차려야!
창창한 길 제가 한번 걸어보겠습니다 ㅎㅎ
많은 도움되었습니다. 감사합니다.