Blockchain 들여다 보기 5

in #kr7 years ago (edited)

13. Coinbase Tx의 Inputs

Coinbase Tx은 각Node가 스스로 작성하여 첫Tx으로써 끼워넣는 것이라는 점에서,일반User들이 Node에 제출하는 통상적인 Tx과는 이점에서 기본적으로 차이가 있고,
또 한가지 특징은 Bitcoin을 창출(創出)하는 거래인 만큼, 거래서중 Inputs 부분은 아무 의미가 없으므로,그 내용을 어느정도
임의로 작성할 수 있다는 점이다. 단, 정상적 Tx과 똑같이 형식은 맞춰 주어야 한다.

13.1 Genesis Block의 경우

Genesis Block의 Coinbase Tx의 내용을 Hex로 받은 내용을, 크게 4부분으로 구분하여, 다음에 보였다.

================ Block #0 Coinbase Tx ===============
01000000: Version No

01: Inputs Count
0000000000000000000000000000000000000000000000000000000000000000: Previous Txid
ffffffff: output index
4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73: InputScript
ffffffff: Sequence (End of input)

01:Outputs Count
00f2052a01000000: Satoshis Value
434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac:OutputScript

00000000:Locktime
=================== End ==========================

창시자들은 Previous Txid를 0000. . . 0000으로 하고, Output index는 ffffffff로 Set하였다. 아주 최근에 채굴된 Block의 Coinbase Tx을 Hex로 받아 비교해 보면 알게 되는데, 이 "전통"은 그대로 지켜지고 있는 것 같다. 이값들은 의미가 없으므로, 어떤 것을 넣어도 무방하겠지만,하나의 불문률로써 "전통"을 유지하고 있는 것이 아닌가 여겨진다.

Input Script도 그점은 마찬가지다. 다만,보다 의미있게 이 저장 공간을 활용하기 위하여, InputScript에 어떤 Message를 포함시킬 수도 있다. Genesis Block의 Coinbase Tx Inputs부분에는 어떤 Message가 담겨 있었을까?

선두의 "4d"는 InputScript의 Byte Count이므로, InputScript 의 본내용은,
04ffff001d01044554686520. . . . .722062616e6b73
이다. 무슨 Message가 있었을까?
여기서 잠깐! 앞으로, 우리가 "0x54"라고 쓰면, 이것은 "0x"뒤에 따르는 것들은 16진수(Hexadecimal)이며, 10진수가 아님을 확실히 하기 위한 것이다. 숫자 0에 영문 소문자 x를 사용한다. 아주 잘 알려진 관행이다.
이러한 표시법을 써서 설명을 계속 한다.
위 Script내용에서, 중간 쯤의 . . . . .54686520 부분을 보자.
0x54는 영문 대문자 "T"의 ASCII Code이고, 0x68,0x52 는 각각 "h"와 "e"의 ASCII Code이다.
ASCII Code의 표는,이 링크 ASCII Table를 참조하면 볼 수있다.
즉 "The"라는 단어이다. 이를 계속하면,

The Times 03/Jan/2009 Chancellor on brink of second bailout for banks

라는 문장임을 알 수 있을 것이다. 이는 2009년 1월3일자 영국 Financial Times지의 Tittle이었던 것이다.
Genesis Block을 채굴할 당시의 시대 배경과, 자기들이 무엇에 반기를 들고자 했는지가 확실히 들어난다.
Nakamoto Satoshi라는 필명으로 알려진 이들 창시자 Group은 아직 그 정체가 밝혀지지 않고 있다.
금년에든가,영국 케임브리지 대학원의 연구에 의하면,초기에 채굴된 Block Reward중 상당부분이,아직까지 한번도 Spend되지 않은채로 그대로 그 주소에서 잠자고 있다고 한다. 총 채굴량의 약 70%에 이른다고 한다. 자신들의 정체를 계속 감추기 위해서 일까?

필명으로 보아, 창시자Group에는 ,일본인이 포함되어 있었음은 분명해 보이고, 2009년 당시 Financial Times지가 아직 영국회사였던 것으로 보아서, 약간의 영국인들도 포함되지 않았을까? ( FT지는 그후 2015년 무렵, 일본의 한 회사에 인수 당했다) 그들이 정체를 밝히지 않고 있는 것은 현명한 처사로 보인다. 정체가 밝혀지면, 아마도,온갖 사람들로 부터,각종 구설수에 시달리게 될 것이니까. 혹자는,그 즉시 CIA가 그들을 덥칠 것이라고도 말한다. 떠도는 소문에는, 외계인들이 지구문명의 참상(?)을 보다 못해, Satoshi들에게 "영감(inspiration)" 을 불어넣은 것이라고 한다.

13.2 Coinbase Inputs의 또다른 용도

채굴에 성공하기 위해서, 채굴자가 직접 변경할 수 있는 것은 Block Header중 4Byte(32bit)밖에 안되는 Nonce 밖에 없다.
Bits에 의해서 채굴 Diffculty가 극히 높아지면, 이 Nonce 32bit의 모든 경우의 수를 다 시도해도 실패할 확율이 많아 질것이다. 특히 최근의 Diffculty는 최초보다 8600억배나 높아졌기 때문에 더욱 그렇다.

이때 채굴자Node는,가령 Tx을 더 추가하여 Merkle Root를 새로운 값으로 바꾼다거나, 아니면 Tx들은 그냥 둔채 Coinbase의 Input부분에 변화를 줌으로써 결과적으로 Merkle Root값을 바꾸거나 해야 할 것이다.
주로 후자의 방법이 동원되는 것 같다. 아주 최근에 채굴된 Block들의 Coinbase Input들을 보면,가끔 Inputs중의 Sequence가 ffffffff가 아니라 00000000으로 되어 있는 것을 보게 될 것이다.
즉, Sequence 4Byte에 변화를 주어 결과적으로 Merkle Root를 새것으로 바꾼 경우이다. 다시 말해서, Nonce 4Byte로도 부족하면, 이 Sequence 4Byte도 동원하여,도합 8Byte를 조정함으로써 채굴에 도전하는 셈이다.

만일, 향후 더욱 더 Diffculty가 올라가면, InputScript부분 까지도 조정할 대상에 포함해야 할지 모른다. 하여튼, Diffculty가 아무리 더 올라가더라도 이에 대처할 여유는 얼마든지 있으므로 이점은 걱정할 필요가 없다.

14. Private Key, Publick Key

이쯤에서, Private Key,Public Key그리고 Address에 대해서 간략히 정리해 두고 넘어 가고자 한다.
너무 Detail한 것 같다 생각되면 이절을 건너 뛰어도 좋다.

(1)Private Key

Private Key는 32Byte의 정수(integer)이다. 1 ~ (p-1) 사이의 정수 중에서 Random하게 하나를 고른 것이다.
여기서 p는 32Byte를 거의 다 "ffff. . . .fff..." 로 채울듯할 정도로 아주 큰 소수(Prime number)이다. 32Byte란 엄청난 경우의 수를 갖는다. 맞는 말인지는 모르나, 우주의 모든 원자들의 숫자에 가깝다고도 한다. Bitcoin의 보안 및 Backup의 목적은 결국 이 Private Key를 어찌 비밀유지 할 것인가와 ,어떻게 그 내용을 안전한곳에 Backup해둘 것인가의 문제이다.

(2)Publick Key

우선 Public Key는 어떤 점(Point)의 (x,y) 좌표이다. 보조 설명을 하겠다.
Bitcoin 체계에서는 Secp256k1이라는 규격에 의한 암호체계를 사용한다. 2차원 평면이지만, x좌표 및 y좌표가 0~(p-1)의 정수(integer)로 제한된,평면을 생각하자.
이 2차원 평면상에 띄엄 띄엄하게 존재하는 모든 점들 중에서,
소위 Elliptical Curve 방정식이라고 하는,

y^2= x^3+7 (단, mod p )
(y^2은 y의 제곱, x^3은 x의 세제곱의 뜻이다. 노파심에서. . .)

을 만족하는 점들이 무수히 많이 있다. 그들의 수효 또한 거의 p에 필적할 정도로 많다.
온 우주의 원자의 수 만큼 많은 점들이 있지만,이들 모두에게 고유한 일련번호를 부여하는 알고리즘이 확립되어 있다.

Public Key란 이 점들 중 제d번째 점의 (x,y)좌표이다. (가령, d가 Private Key일때.)
따라서 Public key는 2x32Byte=64Byte만 필요하지만, 선두에
이것이 Full Format이란 것을 표시하기 위하여 "04"라는 16진수 고정내용, 1Byte를 선두에 달기로 하였다.
그래서, Full Pubkey는 65Byte 길이다. 그러나, 이것은 과거에 쓰던 Format이고, 현재는 압축된 짧은 형식을 권장하고 있다.

사실은, Curve상의 점이므로,x좌표만 알아도 "거의" y를 구할 수 있다. Curve의 식의 특징상, (x,y)가 해(解)이면 (x,-y)도 해이기 때문에, 둘중 어느 것인지만 그 정보만 더 알려주면 된다.
단, 여기서 -y란 " y+(-y) = 0 : mod p " 의 뜻인바,실은 y+(-y)=p 라는 뜻이기도 하다. p는 소수이므로 홀수이다.
따라서, y가 짝수면 -y가 홀수 여야하고 , 홀수면 짝수여야 한다.
그래서 Pubkey의 Compressed format는 다음 처럼 정했다.
x좌표만 적되, y가 짝수면 16진수로 "02"를 선두에 두고,홀수면 "03"을 선두에 두기로. . . .
따라서, 현재 권장하는 Compressed Format으로는,Pubkey는 33Byte의 길이를 갖는다.

각점(Point)들에 일련번호가 부여 되었다고 했는데, 일련번호 1번인 점을 G(1)점이라 하면, Private Key d에 대응하는 Publick Key는 G(d)라는 이야기다.
G(1),G(2),G(3),. . . . .,G(d),. . . . . .
G(1)을 특히 Base Point라 부르는데, 보통 G로 표시하는데, 그 좌표값은 여러 자료들에 나와 있다.
d를 알고,그로부터 일련의 알고리즘에 따라, G(1)을 시작점으로 하여,G(d)점을 구해내는 것은 매우 쉬운데,
역으로 점G(d)에서 d를 알아내기는 참으로 불가능에 가깝게 어렵다는 것이다.

(3) Pubkey hash

보안을 더 강화하기 위하여 Pubkey를 hash하여 20Byte로 줄인것이 Pubkey hash이다.
정확히 말하면,두번의 Hash과정, RIPEMD160(Sha256(Pubkey)),을 거쳐서 얻은 것이다. Hash함수 특성상 역방향 계산은 불가능하다. Output Script에 Bitcoin을 보내는 곳을 지정할 때 이 Pubkey hash를 사용한다. Wallet sotware들에 있어서는 이것이 Address인 셈이다. Tx작성에서도 이것을 쓴다. Software의 사용자인 인간과의 정보 소통시에만 Bitcoin Address로 바꾸어 소통을 하고 있는 것이다.

(4)Bitcoin Address

이것은 Wallet software등이,인간들의 편이를 위해서, 인간들과의 정보교환시, Pubkey hash를 대신하여 사용하도록 고안된 대용물이다. 문자와 숫자를 사용하는 형태로 변환한 것 뿐이다. 약 34개 정도의 문자/숫자의 나열로 되어있다.
이 변환 규격을 Base58check 이라 부른다. 영문자 52개(26x2)와 숫자10개 를 합하면, 총 62개의 character들이 되는데,그중에서 0,O,l,I 이 4개는 혼동/착각이 우려되므로 제외하여,58개의 Character만을 사용하기에 부쳐진 이름이다.
이를 WIF(Wallet Import Format)이라고도 말한다.
물론 Bitcoin Address를 알면 Pubkey hash로 변환 할수있다. Pubkey hash로부터 변환한 Address는 "1"자로 부터 시작한다.
한편, 20Byte의 길이인 것은 같지만 Pubkey hash가 아니고 Script hash(후술)로부터 변환한 것은 "3"자로 시작한다.
"5"자로 시작하며, 40자 정도로,약간 더긴,언뜻 Address처럼 보이는 것도 있는데, 이것은
Private key를 위한 대용물이다.

15. Payment의 여러가지 형태

앞서 12절에서 설명한 OutputScript는 "Pay to Pubkey"라고 하여 ,간략히 P2PK방식이라 부르는 Payment방식인데,
이제는 거의 않 쓰게 된 옛방식이다.
요즈음 가장 흔하게 많이 쓰는 방식은 "Pay to Address"방식인데,그런 표현보다는 "Pay to Pubkey Hash"라는 용어를 주로 사용하고,줄여서 "P2PKH"방식이라 한다. 그외에 간혹 "Pay to Script Hash"(P2SH)라는 것이 쓰인다.
이절에서는 Blockchain에 있는 실례를 통해서 Payment의 여러 방식을 훝어보기로 한다.

15.1 P2PKH의 실례

Blockchain.info 에서 다음 Txid,
a9b2a444eda4d21aa66d026d4f00b4bfd3078c3908d65d9501a26f74bed17cc2
를 검색어로 해서 연 다음, 주소난 끝에
?format=json을 추가해서 json format으로 이 Tx의 내용을 보면, 다음과 같다.


{
"ver":1,
"inputs":[
{
"sequence":4294967295,
"prev_out":{
"spent":true,
"tx_index":264429133,
"type":0,
"addr":"1Fzpm9KD8aTKYrWWiDKgGKobBKYti6wC69",
"value":1000000,
"n":1,
"script":"76a914a48156f9a588fd9d8c5c3f9f61a56cffeaf515bc88ac"
},
"script":"4730440220137248f9c7fca3e2aee70d2a7b99012c1de098061add231dd2f2b802523f3dbb0220516205adc13d67aecff92b3315c9936bbb2154fd5763f61c06f53eca9581ab87012102b1cb94ceb345ad1a195e6d8513a1f2cf5fadd764e23cdaba2187b1d8f48400fc"
}
],
(이하 생략)


"Inputs"내의 "Prev_out"은 자금의 근거인 Previous Txid와 그 index를 보여주는 대신에,친절하게도,아예 그 Previous Tx의 Output index 1의 내용을 조사하여,
1000000 Satoshi의 Value와, 거기에 걸려있는 Encumbrance(관문),Output Script, 의 내용을 보여 주고 있다.
즉,1000000 Satoshi에 걸려있는 OutputScript의 내용은,
"76a914a48156f9a588fd9d8c5c3f9f61a56cffeaf515bc88ac"
이었었던 것이다.

그리고,그 바로 밑에는 이에 대응하여 제출되는 inputScript가,
"4730440220137248f9c7fca3e2aee70d2a7b99012c1de098061add231dd2f2b802523f3dbb0220516205adc13d67aecff92b3315c9936bbb2154fd5763f61c06f53eca9581ab8701;2102b1cb94ceb345ad1a195e6d8513a1f2cf5fadd764e23cdaba2187b1d8f48400fc"
임를 보여 주고 있다.

이제,Tx의 검증을 위하여 준비되는, 검증Program을 구성해 보자. 12절에서 설명했듯이,그냥 inputScript에, Previous Tx /index 의, OuputScript를 이어 붙치면 된다.
우선 inputScript를 Opcode와 data로 구분해서 좀 알기 쉬운 형태로 써보자.
첫Byte인 0x47은 뒤따르는 0x47(71개)의 Byte를 data로써 Stack에 넣으라는 명령이다. 0x01~0x4b는 전부 동종의 Opcode인데,이런 종류의 Opcode는 총칭하여 Constant라고 부른다.(아예 명령어 명칭조차 없다!)
따라서 뒤따르는 Byte의 수를 세어보아, data는,
< 304402. . . .ab8701 >임을 알 수 있다. 그러므로,바로 그 뒤를 잇는 0x21(십진33)은 Opcode로 파악해야 하며,이것 역시 Constant에 속하는 Opcode이다.
결국,inputScript는
[47]< 304402. . .ab8701 >[21]< 02b1. . . 00fc >
가 된다. 그런데,우리의 편이상, Constant류의 Opcode는 아예 생략하기로 하자. 즉, 그냥
< 304402. . .ab8701 > < 02b1. . .00fc >
로 쓰기로 하고, 그대신 data를 뜻하는 < . . .. >의 앞에는 그에 맞는 적절한 Constant가 있었지만 생략했었다는 사실만 잊지 않으면 되는 것이다.

< 304402. . .ab8701 >은 Signature이다. < sig >로 줄여 쓰자. 무엇을 대상으로 하여 Sign을 한 결과인가 하는 것은 12절에서 대략 설명한바 있다. 보통 70Byte근방의 길이를 갖는다.
한편, < 02b1. . .00fc >는 Pubkey이다. 33Byte길이 임을 알 수있다.
따라서, InputScript는 결국,
< sig > < pubkey >
로 간략히 표시할 수 있다.
(참고사항: 이처럼 InputScript에는 늘 < sig >가 포함되기 때문에,사람들은 InputScript라고 말하는 대신 "ScriptSig"라는 용어를 주로 사용한다.)

한편,이 InputScript에 대응하는 OutputScrypt를 보자.
0x76은 OP_DUP라는 명령어(Opcode), 0xa9은 OP_HASH160 이라는 명령어이며,0x14는 다시 Constant류의 Opcode이므로
편의상 역시 생략하기로 한다. 결국은, 다음 처럼 쓸 수 있다.

OP_DUP OP_HASH160 < a481. . . .15bc >OP_EQUALVERIFY OP_CHECKSIG
(필자의 이Post는, Script에서 사용되는 Opcode들을 세세히 설명하는 것은 목표로 하지 않았다. 다만, "맛보기"정도를 의도한 것이다. 그러니,독자들은 그저 "아! 대략 이해는 된다!"는 정도의 감이 오면 되겠다. )

한편, data < a481. . . .15bc >의 내용은 Pubkey hash 이므로 < pubkey hash >로 쓰기로 하자. 그 앞의 constant로 알 수 있듯이 20Byte의 길이이다.
(참고사항: 이처럼, OutputScript에는 보통, Pubkey 또는 Pubkey hash등이 늘 포함되므로, OutputScript라는 용어 대신 "ScriptPubkey"라는 용어를 주로 쓴다.)

자,이제 둘을 이어 붙처서, 검증을 위한 Script Language Program을 모두 써보면,
< sig > < pubkey > OP_DUP OP_HASH160 < Pubkey hash > OP_EQUALVERIFY OP_CHECKSIG
가 된다.

실행을 해보자. 먼저 < sig >가 Stack에 push되고,이어서 < pubkey >가 push된다.
Stack의 top에는 < pubkey >가 있고,그 아래에 < sig >가 있다. 이것을,
< pubkey > / < sig >
로 나타내자.
다음. OP_DUP란 Opcode는 Stack top의 내용과 동일한 복사본을 만들어,Stack에 push한다. 따라서 Stack은,
< pubkey>/< pubkey >/< sig >
가 될 것이다. 즉,Stack의 맨위에 < pubkey >가 있고 그 밑에 < pubkey >, < sig >가 차례로 쌓여 있는 것이다.

다음. OP_HASH160은 Stack top을 뽑아(pop)낸후,그것을 Hash160이라 불리우는 Hash처리를 하고, 그결과를 Stack에 push한다. 따라서,이제 Stack은,
< Pubkey hash > / < Pubkey >/< Sig >
가 되었을 것이다. Hash160은 다름아닌 ,14에서 언급한 , RIPEMD160(Sha256( ) ) 그것이다.

다음. < pubkey hash >가 Push될 것이다. < pubkey hash > 바로 직전에, 적절한 Constant가 있었지만 생략했던 사실을 잊지말라. 따라서,Stack의 상태는 이제,
< pubkey hash > / < pubkey hash >/ < pubkey >/ < sig >
가 되었을 것이다.

다음. OP_EQUALVERIFY는,
Stack의 top에서 부터 2개를 차례로 뽑아(pop),이 둘이 같은지 아닌지를 검사하고 나서,
만일 다를 경우엔 이 Tx을 "불합격"으로 지정하고,Program은 종료된다.
같을 경우엔 다음 Opcode로 계속 진행된다. 결국,이 과정은 이 Tx의 ScriptSig에 포함된 < Pubkey >가 ScriptPubkey에서 제시된 < Pubkey hash >와 합치하는 것인가를 대조하는 과정이다. Pubkey에서 Pubkey hash를 얻는 과정은 일방향성이라는 것에 유의하라. 즉,Pubkey Hash로부터 역으로 Pubkey를 알아낼 수는 없다. 자. 그러나,이것만으로는 검증이 완벽하지 않다. 왜냐하면, Pubkey가 한번이라도 Blcokchain상에서 노출되면, 다른 사람들도 그 정보를 알게 되므로,이 검사만으로는 불충분하다. 이 Tx을 작성한 사람이 과연 이 Pubkey에 대응하는 Private Key로 < Sig >를 생성할 수 있었는가를 반드시 검사해야 한다.

이제,Stack의 상태는,
< pubkey >/< sig >
일 것이다.

다음. OP_CHECKSIG는 Stack에서 < pubkey >와 < sig >를 뽑아, < pubkey >로써 < sig >의 합치여부를 Check한다. 실제의 OP_CHECKSIG의 작업 내용은 좀 복잡하나,요컨데 이 < sig >가 < pubkey >에 대응하는 Private Key로써 만든 Signature가 맞는지를 검사하는 것이다. 보다 정확한 것을 알고자 원하는 수준 높는 독자들은 다음 링크를 참조하면 될 것이다.
OP_Checksig

이러한 모든 과정을 거쳐야 그 Tx은 검증이 Pass된 것으로 인정되어,Block채굴에 포함되는 Tx의 일원이 되는 것이다. 그렇지 못할 경우 그 Tx은 거부(reject)되어 버려진다.

우리가 다룬 실례에서 < Pubkey hash >는
a48156f9a588fd9d8c5c3f9f61a56cffeaf515bc (20Byte)
이었는데, Blockchain.info가 Script속의 이 Pubkey hash를 보고,이것을 1Fzpm9KD8aTKYrWWiDKgGKobBKYti6wC69 라는 Address로 변환하여 Web page등에 표시하고 있는 것이다. 위에서 Json format으로 받아 보았던 내용을 다시 보아 확인 바란다.

15.2 P2SH방식(Pay to Script Hash)

먼저 실례를 보자. Blockchain.info를 열어서 다음 Txid를 검색해 보자.
40eee3ae1760e3a8532263678cdf64569e6ad06abc133af64f735e52562bccc8
이 Tx의 page을 보면, 0.0099BTC를 Bitcoin Address
3P14159f73E4gFr7JterCCQh9QjiTjiZrG
로 보낸 것으로 되어 있다.
아랫쪽의 "Output 스크립트"난을 보면,이 0.0099BTC에, 다음 같은 Script를 걸어 놓았음을 알 수 있다.
OP_HASH160 e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a OP_EQUAL

이것은 다음 처럼 쓸 수 있는데,
OP_HASH160 < e9c3dd. . . . 6c160a > OP_EQUAL
이것은 확실히, 앞에서 다룬 P2PKH와는 약간 다른 Opcode들을 쓰고 있다.
유사한 점은, data인 < e9c3dd. . . . 6c160a >가 20Byte인 점 인데,Byte갯수로 판단해 보면, 마치 < Pubkey Hash > 인 것 처럼 보인다. 그러나 실제로는, 이 20Byte의 data는 어떤 Pubkey를 Hash한 것은 아니고, 어떤 "Script"의 내용을 Hash한 것이다.
"Script"가 어떤 내용에 어떤 길이든 간에, RipEMD160(Sha256())처리의 결과는 20Byte가 나오므로. . .
지금은 이 "Script"가 무슨 말인지, 아마 잘 이해가 안될지 모르나,일단 그냥 넘어가자.

Blockchain.info 의 Server는 그러한 사실을 알고 있기 때문에,20Byte의 data < e9c3dd. . . . 6c160a >를 Address로 Encode를 할 때, "이 Address는 Pubkey hash가 아니라,Script hash의 내용을 Encode한 것이다" 라는 사실을 알리기 위해서, Address의 첫글자(Address의 종류를 표시)를 3으로 한 것이다. (Pubkey hash로 부터 Encode한 Address는 1을 첫문자로 한다.)
우리의 실예에서,Address는
3P14159f73E4gFr7JterCCQh9QjiTjiZrG 이었다. (위의 json format의 inputs 내용을 보라)

한편, 이 0.0099BTC에 Access하여 이를 소비한 Txid는,
7edb32d4ffd7a385b763c7a8e56b6358bcd729e747290624e18acdbe6209fc45
이다. 이 Tx의 page를 열어서,그것의 "Input 스크립트"난을 보면,

OP_FALSE
3045022100ad0851c69dd756
b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001
라고 나오는데,이것은 Blockchain.info가 약간 잘못 파악한 것이고,제대로 파악하면 다음 처럼 되어야 한다.
(이 Tx을 Hex로 받아서 분석해 보면,알 수 있다)

OP_FALSE < 3045. . . .b79001 > < 514104. . . .df51ae >

여기서, < 3045. . . .b79001 >부분은 < sig >로, < 514104. . . df51ae >는 < script > 표시하면,
OP_FALSE < sig > < script >가 된다. 이제, 검증 Program을 만들어 보면,

OP_FALSE < sig > < script > OP_HASH160 < e9c3dd. . . . 6c160a > OP_EQUAL

가 되는데, 어떻게 하여 관문을 통과할 수 있었는지를 보자.

우선,OP_FALSE 는 Stack에 0x00을 Push하는 Opcode이다.
그이후 차례로 < sig >와 < script >가 Push된다. 즉, Stack의 상태는 < script > 를 top으로,다음 같은 상태일 것이다.
< script > / < sig > / 0x00

다음. OP_HASH160은 Stack의 top의 내용을 복사한후, 그것에 HASH160이라는 Hash처리를 하고, 그 결과를 Stack에 Push한다. 따라서, OP_HASH160을 수행한 후의 Stack상태는 다음과 같다.
< script hash > / < script >/ < sig >/ 0x00

다음. < e9c3dd. . . . 6c160a >를 만나게 되는데, 그앞에 Constant류의 Opcode를 우리가 생략했었다는 것을 잊지 말자.
따라서, < e9c3dd. . . . 6c160a >가 Stack에 Push된다. 따라서,이제 Stack은, 다음과 같다.
< e9c3dd. . . . 6c160a > / < script hash > / < script >/ < sig >/ 0x00

다음. OP_EQUAL은 Stack의 top부터, 2개를 뽑아내어(pop),그 2개가 서로 같은지를 대조한다.
물론 다르면 검증은 실패한 것으로 된다.
여기서,< script hash >가 어떤 값이었을지를 실제로 계산해 보기로 하자.
앞서 말한 OP_HASH160이란 Sha256으로 1차 Hash를 한후에 그 결과를 다시 RIPEMD160 이라는 Hash로 또한번 Hash하는 것을 말한다. 즉,
< script hash > = RIPEMD160(Sha256( < script >) )인 것이다.
다음 링크는 hex로 input하여,여러가지 Hash함수의 결과를 얻을 수 있는 Site이다.
Various Hash-Online

이 Web site를 이용해서, < 514104. . . df51ae >를 Sha256으로 1차 Hash하면,
a1b2676332a6fcdd21363dbd456e20aed83d703404696036f42913353b000838
를 얻을 것이다. 이를 다시 RIPEMD160으로 처리하면,
e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a
를 얻는다. 한편, 원래 Output Script에 있던 data와 비교해 보면,과연 똑같다!
즉, OP_EQUAL은 무난히 Pass할 것이다!
그런데, 중요한 사실은, 이 때 Stack에는 아직도,

< script >/ < sig >/0x00

이 남아 있다. 이런 경우,즉 Program이 종료할 그 시점인데 아직도 Stack에 무언가가 남아 있다면, Stack의 top을 뽑아내어(pop),그것을 data가 아니라 ,자기가 수행해야 할 Script로 보고, 검증을 계속한다.
사실은 지금부터, 정말로 중요한 진짜 검증이 시작된 것이다.
"아하! "하고 감이 왔기를 바란다.

< script >의 내용은 다음과 같았었다.
5141042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424b0d79122a653ad0c7ec9896bdf51ae

한편, Stack의 상태는,
< sig > / 0x00
이다.

Script를 Opcode와 data들로 구분해 보면,다음 처럼 된다.
OP_1 < 042f. . . .6bdf> OP_1 OP_CHECKMULTISIG

OP_1 이란 Opcode는 Stack에 0x01을 Push하는 명령이다.
OP_CHECKMULTISIG 바로 전까지를 수행하면 Stack은 다음 처럼 된다.
0x01 / <042f. . . .6bdf> / 0x01 / < sig > / 0x00

여기서, < 042f. . . .6bdf>는 65Byte길이로써, 실은 Full Pubkey이다(0x04로 시작하고 있다). 이 Tx은 2013년 무렵의 거래였으며, 아직 Full Pubkey가 사용되고 있을 때였다. 요즈음 이라면,33Byte의 짧은 길이의 Pubkey를 사용했을 것이다.
이 거래는 Multisig를 이용한 거래지만 실례로 들기에는 좀 싱거운 거래( 1 of 1 )가 되고 말았다.
보다 좋은 실례였다면, Stack의 내용은,가령, 다음과 같았을 것이다. 그래서,아예 이것을 예로써 바꿔서 설명을 계속하기로 하겠다.

0x03 / < pubkey1 > / < pubkey2 >/< pubkey3 >/ 0x02 / < sig1 > / < sig2 > / 0x00

Stack이 이와 같을때, OP_CHECKMULTISIG 라는 명령은,이것을 "2 of 3"의 Multisig로 판단하여,
( 3사람중 임의의 2명의 Signature가 있으면,관문을 Pass하는 것이 "2 of 3"방식이다.)
Pubkey 3개와 < sig >2개를 전부 pop한 후에,
3개의 Pubkey중 < sig1 >과 합치하는 것이 있는지 조사한다. 없으면 불합격이고, 합치하는 Pubkey가 있으면, 그 Pubkey는
제거하고 나서,이번에는 < sig2 >에 대해서 조사한다. 여기서도 남은 Pubkey중 < sig2 >와 합치하는 것이 있어야 한다.

이상으로 P2SH방식을 설명하였는데,주된 용도는 "N of M"방식의 Multisig 이지만, 이 "script"를 어떻게 작성하느냐에 따라 다양하고 복잡한 관문(Encumbrance)를 걸어줄 수가 있을 뿐만아니라,이렇게 하여, 3으로 시작되는 Address가 부여되므로,signer 당사자들 뿐만아니라 제3자가 자금을 그 Address로 보내는 과정이 간단해 진다는 이점이 있다.
이 이점은 다음 소절에서 명확해 질 것이다.

15.3 옛날의 MultiSig 방식

Blockchain.info에서 다음 Txid를 열어보라.
09dd94f2c85262173da87a745a459007bb1eed6eeb6bfa238a0cd91a16cf7790
Outputs은 4곳인데, 3번째(index 2) 출력에는 "출력주소를 디코딩 할 수 없읍니다"라고 나온다.
아래에서 "출력 스크립트"를 보면,(여기도 약간의 Miss가 있다),제대로 해석 했다면 다음 처럼 되어야 하는 것이었다.

OP_1 < 0324. . . .3016 > < 0230. . . . 685a > OP_2 OP_CHECKMULTISIG

여기서 <0324. . . .3016>과 <0230. . . .685a>는 각각 33 Byte길이의 data인데, 이것들은 짧게 줄인 Pubkey 인 것이다.
그러므로, 0.0001086BTC에 걸린 관문은,

OP_1 < pubkey1 > < pubkey2 > OP_2 OP_CHECKMULTISIG

이었던 것이다. 이것은 P2PK 나,P2PKH,또는 P2SH 그 어느 방식도 아니기에, 이 0.0001086BTC를 어디로 보낸 것인지 Blockchain.info로써는 표현할 길이 없는 것이다.

P2SH방식이 나오기전에는 Multisig방식을 이와 같은 방식으로 했었다.
이 실례는 "1 of 2"의 Multisig방식이므로, 이 금액을 Spend하려면, InputScript를

OP_FALSE < sig >

와 같이 하면 될 것이다. 물론,이 < sig >는 Pubkey1또는 Pubkey2에 대응하는 Private Key를 사용하여 만든 Signature면 된다.
검증을 위한 Program은,

OP_FALSE < sig > OP_1 < pubkey 2> < pubkey1 > OP_2 OP_CHECKMULTISIG

가 되어, OP_2까지 수행을 하고 난후의 Stack상태는 ,
0x02 / < pubkey1 > / < pubkey2 > / 0x01 / < sig > /0x00
가 되고,
OP_CHECKMULTISIG 의 수행 내용은 이미 앞의 소절에서 설명한바 있다.
이 것이 과거에 행해왔던 Multisig방식이다.
요즈음은 이를 P2SH방식으로 처리를 하는데, 그 장점은 다음과 같다.

가령, 2사람이 Online Shop을 운영하는데, 손님으로 부터 입금된 금액을 지출 할때는,2사람중 임의의 한명의 < sig >만으로도 출금이 가능하기를 원한다고 할 때,(또는 두사람 모두의 sig를 필요로 한다든가 등등 ),
손님들에게, 위와 같이 특별한 관문(OutputScript)을 걸어서 금액을 지불해 달라고 요청하는 것은 대단히 거북스러운 이야기 이다. 뿐만아니라,손님들이 이용하는단순한 Wallet들은 그러한 다양한 기능은 갖고 있지도 않다. 게다가 입금된 총 금액을 Blockchain.info에서 확인코자 할 때도 대단히 불편하다. 도대체 검색할 Address조차 없으니. . . .

그래서,요즈음의 대부분의 Multisig기능은 P2SH로써 처리한다. 이 방식으로는 3으로 시작되는 Address가 부여되기 때문에, 제3자인 손님에게 그 Address만 알려주면,손님들도 간단히 그 Address로 Send를 할 수 있다는 큰 장점을 갖는다. 손님의
Wallet Software는, 정상적인 Address이었을 때와 동일한 방법으로, Address로 부터 Pubkey hash(실제로는 Script hash지만)를 계산한 다음,OutputScript를 만든다. 이때,Adress가 숫자 3 으로 시작했다는 사실로부터, 이 hash는 < script hash >라는 것을 알므로, 그에 걸맞는 Opcode를 전후에 달아주는 것이다. 다음 처럼.
OP_HASH160 < script hash > OP_EQUAL

15.4 그 밖에 특이한 OutputScrip들

Puzzle 풀기

다음 Txid를 열어보라.
a4bfa8ab6435ae5f25dae9d89e4eb67dfa94283ca751f393c1ddc5a837bbc31b

이것도 "출력주소를 Decode할수 없다"라고 나온다. "출력 스크립트"가 어쨋길레 그렇게 되었는지 보자.
아랫쪽의 "출력 스크립트"난을 보면,
OP_HASH256 < 6fe28c. . . .d6190000000000 > OP_EQUAL
으로 되어있다. 본적이 없는 기이한 형식이다. 그러니 Blockchain.info가 "Decode할수 없다"는 출력을 보이는 것이다.

data인 < 6fe28c. . . .d6190000000000> 를 세어보면 32Byte(256bit)이다.
잘 머리를 써보면, 이것은 어떤 Puzzle에 대한 답을 제출하면 관문을 열어주겠다는 뜻임을 알 수 있다.
그 puzzle이란. . . .
Sha256(Sha256())을 했을 때,그 결과가 < 6fe28c. . . .d6190000000000>로 나오게 될 입력data를 알아 낸다면, 걸려있는 BTC를 가져갈 수 있다는 이야기다.
이 Hash값의 끝이 00000000으로 되어 있는 것이 무언가를 기억나게 하지는 않는가?
그렇다!
채굴을 할때, Block Header의 Hash가 Bits가 제시하는 조건내에 들어야 채굴이 되는 것이었고,그 Hash를 Big Endian표현으로 한 것이 Block id가 된다는 것을 상기하자.
따라서,Block id가 < 000000.. . .8ce26f >인 Block의 Header부의 내용(Raw Hex)를 제출하면,이 1BTC를 받을 수 있을 것 같다.
그런데, 이 Puzzle은 이미 누군가가 1BTC를 받아 갔다.

어쨋거나,
< 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f > Block id를 검색해 보자.
과연 그런 것이 있었다. 다름아닌 Genesis Block이었다!

이 Puzzle을 풀어 상금을 타간 Tx는,
09f691b2263260e71f363d1db51ff3100d285956a40cc0e4f8c8c2c4a80559b1
이었다. 이 Tx을 열어보고, 그 "입력 스크립트"를 보면,

  1. . . . .1d1dac2b7c (80Byte)
    로 나오는데,이는 다름 아닌 Genesis Block의 Header 80Byte 그것임을 확인 할 수 있을 것이다.

기묘한 Address들

다음 링크를 클릭해 보라.
Strange Address 1
이 Page는 Address가 1BitcoinEaterAddressDontSendf59kuE 인 주소를 검색어로 연 것이다.
여기서 이상한 점은 Address자체이다. 원래 Address는 Pubkey hash(20Byte)의 대용물로써,이 20Byte를 Base58방식으로 Encode하여(양방향으로 변환가능)얻어 지는 것인데, 정상적인 과정에 따라, Pubkey hash로부터 얻어진 Address가 이렇게 우연한 문자열을 가질 수가 없다! 따라서,이 Address는 역으로 Address를 먼저 만든후 그로부터 20Byte의 Pubkey hash를 얻은 것이다. (사실 Pubkey hash라는 용어를 쓰기 어렵지만. . .)
따라서,이 Address로 보내진 BTC는 결코 Spend할 수 없다. 그대로 잠겨버리는 돈이 된다. 대응하는 Pubkey는 물론 그 Private Key를 어찌 알아낼 수 있겠는가?
이는 누군가가 Blockchain에 Joke를 하나 올려 놓은 셈인데,그럼에도 불구하고, 아는지 모르는지, 많은 사람이 이리로 BTC를 보낸 기록이 남아 있는 것이다. 유사한 Address가 더 있는데, 다음이 그것이다.
1111111111111111111114oLvT2
1CounterpartyXXXXXXXXXXXXXXXUWLpVr

특히 1Counter. . . . .LpVr에는 무려, 2130BTC가 영원히 잠겨있다.
CounterParty.PNG

도대체 왜?
필자는 이같은 기이한 정보들을 다음 Site에서 얻었었다.
Strange Transactions
필자의 생각으로는,아마도 많은 정보기관들이,(Terrorist들도?),Bitcoin Blockchain을 은밀한 연락수단으로 활용하고 있을 가능성이 매우 높다.

OP_RETURN의 용도

Script에서, 0x6a 는 OP_RETURN 이란 이름을 갖는 Opcode인데, Tx을 무조건 불합격으로 하고,검증을 종료하는 명령이다.
이 명령 뒤에 다른 Script들이 있더라도 그것들은 아예 무시된다.
따라서, 이 명령어를 OutputScript의 첫 Opcode로 하면, 그 관문은 여하한 InputScript로도 Pass하지 못하는 것이 된다.
따라서, 그 관문이 설치된 Value (Satoshi) 는 영영 찾을 수 없는 것이 된다.

이러한 Opcode를 왜 만들어 두었을까 하고 이상스럽게 생각하겠지만, 이 Opcode는 꽤 중요한 역할을 하고 있다.
OutputScript에 첫Code로써 0x6a를 두면,그 이후는 임의의 Byte열을 부담없이 달아 놓을 수가 있다는 이야기므로,
Blockchain에 어떤 Message나 증거를 영원히 기록하고 싶다면, 이 OP_RETURN을 활용할 수 있는 것이다. 그런 경우 Value는 zero로 해두는게 좋다. 영영 못 찾을 BTC니까.

필자가 올린 또다른 Post인 "비트코인 따라잡기 4"의 17절에서, Proof of Existence를 설명한 바가 있는데,
그 때,수취인 Address난에, File을 Sha256처리한 결과(32Byte)를 복사해 넣은 다음,제일 선두에 "6a"를 추가하라는 요령을 말했었는데, 그 때의 그 0x6a가 바로 Opcode OP_RETURN이었던 것이다.

사실, OP_RETURN을 굳이 쓰지 않아도 어떤 data를 Blockchain에 기록해 둘 방법은 많다.
앞서, "기묘한 Address들"에서 Hint를 얻었을 것이다. 마치 P2PKH 방식으로 Bitcoin을 보내는 것처럼 하여,
OutputScript를 작성하되 < Pubkey hash >의 위치에,자기가 원하는 20Byte길이의 data를,다음 처럼 대치해 넣어도 될 것이다.

OP_DUP OP_HASH160 < 20Byte data >OP_EQUALVERIFY OP_CHECKSIG

다만 이경우,그 Script와 쌍을 이루는 Value(Satoshi)는 영원히 되찾을 가망은 없게 된다.
가령,다음 Tx의 page를 열어서, "출력 스크립트"의 내용을 조사해 보아라.
그곳의 20Byte data는 Pubkey hash가 아니라, 그냥 임의로 자기가 기록으로 남기기를 원하는,어떤 Message를 차례로 집어 넣은 것이다.
930a2114cdaa86e1fac46d15c74e81c09eee1d4150ff9d48e76cb0697d8e1d72

"Proof of Existence"로써 어떤 File의 "존재 증명"을 Blockchain에 남기고자 한다면, 또다른 방법이 있다. File을 Sha256으로 Hash한 다음,선두 20Byte만 짤라서 그것을 가짜 Pubkey hash로 삼아, 약간의 BTC를 보내는 것이다. 그 때, 두번째 Output 은 Value를 0BTC로 하고, Output Script선두에 0x6a를 넣은후, 이후에 ASCIII code로 어떤 Message를 같이 남기는 것이다. 물론 이같은 작업은 좀더 융통성 있는 Coinb.in 같은 것을 써서, 수작업을 좀 해야 할 것이다.
Coinb.in을 사용하면, Tx이 어떻게 작성되는지 Signature를 넣기 전후의 변화 등등을 잘 알수 았게 될 것이다. 아울러, 작성한 Tx에 수작업으로 이런 저런 편집을 한후 Verify를 이용하여 내용의 Check도 할 수있고, 마음에 들면 최종적으로 Sign을 마치고 Broadcast도 할 수 있다.

이상으로 Block채굴이라든가, Blockchain의 여러가지 측면, 그리고 Script가 무엇인지 대략 감을 잡았으리라
본다. Script라든가 Programming에 흥미가 생긴 독자들은 다음 링크를 뿌리로 하여 조사를 해나가면 좋으리라 생각한다.

Bitcoin Script
Developer Guide

다음 절에서는 Fork가 무엇인지와 Soft Fork,Hard Fork에 대해서 설명 할 것이다.

Sort:  

주소가 이렇게 만들어지는거였군요...ㅎ,.ㅎ
15프로정도 이해했나?..몇번 더 들어와서 다시 읽어봐야 겠어요
감사합니다

Coin Marketplace

STEEM 0.19
TRX 0.13
JST 0.029
BTC 60932.34
ETH 3380.87
USDT 1.00
SBD 2.50