Mastering Bitcoin Script
2年ほど前に書いた記事を発掘したので今更公開する。
詳しくは参考文献である「ブロックチェーン・プログラミング 仮想通貨入門」を読んでみるのがいい。
https://www.amazon.co.jp/dp/B078G94JNT/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1
前提
ScriptSig(unlocking script) + ScriptPubkey(locking script)
新しくTransactionを作成する際、UTXOのTransaxtionをTxと解除用スクリプトと共に指定、アウトプットをロックするスクリプトを指定。
検証の順序はScriptSig実行してからScriptPubkeyを実行。
ScriptSig
Transactionのインプットに置かれている署名用スクリプト。
ScriptPubkey
Transactionのアウトプットに置かれている解除条件スクリプト。
bitcoindコードリーディング
/src/script/interpreter.cpp EvalScript関数
C++スタンダードライブラリのvectorを使いstackの操作を処理。
コードリーディングした時のメモ:
https://hackmd.io/@Tokashi/SJx9rLXVv
OP_codeの特徴
- チューリング不完全でステートレスな言語。
- スタックベースで左から右へ処理。
OP_codeの要件
- スクリプトが終了したときにスタックの先頭の項目がTrue(ゼロではない)であれば、トランザクションは有効。0が残った場合、複数のスタックが残った場合、スタックがからの場合は検証に失敗する。
-> Transactionの検証をし、失敗させるOP_codeを使う。 - スタック上のバイトベクトルの長さの上限は520バイト。
- 整数やブールをスタックから取り出すオペコードは4 バイト以下。
- 加算や減算はオーバーフローして 5 バイトの整数がスタックに置かれることもある。
例
2 3 OP_ADD 5 OP_EQUAL
IDE
一度自分で触ってみて欲しい。
-
Bitcoin IDE
https://siminchen.github.io/bitcoinIDE/build/editor.html -
Bitauth IDE
https://ide.bitauth.com/
よく使うOP_code
OP_ADD
スタックの上から2番目と先頭を足す。
(例)
1 2 OP_ADD => 0x3
OP_SUB
スタックの上から2番目から先頭を引く。
2 1 OP_SUB => 0x1
OP_DUP
先頭スタックを複製。
2 OP_DUP => 0x2 0x2
OP_EQUAL
上から2番目スタックと先頭のスタックが同じなら1を返す。違うなら0を返す。
2 OP_DUP OP_EQUAL => 0x1
OP_VERIFY
先頭のスタックがTrueでない場合、Transactionの検証に失敗する。
先頭スタックは削除される。
2 1 OP_EQUAL op_verify => Execution unsuccessful
OP_EQUALVERIFY
OP_EQUAL実行後、OP_VERIFYを実行。
0P_HASH160
先頭スタックをSHA-256 -> RIPEMD-160する。
<Pubkey> OP_HASH160 => <Pubkey Hash>
OP_CHECKSIG
スタックを全てハッシュ化する。スタックが署名と署名に対応した公開鍵だった場合1を返す。違う場合0を返す。
OP_CHECKMULTISIG
OP_IF・OP_ELSE・OP_ENDIF
先頭のスタックがTrue(0でない値)だった場合、OP_IFのスクリプトを実行。先頭スタックは削除される。
1 2 OP_EQUAL // false
OP_IF
<PUBKEY> OP_HASH160 OP_EQUAL // 実行されない
OP_ELSE
<PUBKEY> OP_HASH160 OP_DUP OP_EQUAL // 実行される
OP_ENDIF
OP_CHECKMULTISIGVERIFY
OP_CHECKMULTISIG実行後、OP_VERIFYを実行。
OP_DROP
先頭のスタックを削除する。
OP_RETURN
関係のないデータをブロックチェーン上に残すためのOP_code。拡張によく使われる。
検証時OP_RETURNがあった場合即座にtransactionの検証を無効にする。
OP_RETURNアウトプットはunlocking scriptが無く永久に使えない。
dataの上限サイズは80byte。
OP_RETURN <data>
OP_CHECKSEQUENCEVERIFY
入力の相対ロック時間が先頭スタックの値と同じかそれより短い場合Transactionの検証に失敗する。
まだまだ色々ある。詳しくはBitcoin Wikiに載っている。
一般的なTransactionに使われるOP_code
P2PKH(Pay to Public Key Hash)
一番シンプルな送金トランザクション。
ScriptPubkey
OP_DUP OP_HASH160 <pubkey Hash> OP_EQUALVERYFY OP_CHECKSIG
ScriptSig
<signature A> <pubkey A>
P2SH(Pay to Script Hash)
マルチシグトランザクション。
P2SHはスクリプトが長くなってしまうため、scriptPubkeyにreedem scriptのハッシュを入れておき、sicriptSigでreedem scriptを提示する。
ScriptPubkey
OP_HASH160 <redeem script hash> OP_EQUAL
ScriptSig
OP_0 <signature A> <signature B> <reedem script>
redeem script
2 <pubkey A> <pubkey B> <pubkey C> 3 OP_CHECKMULTISIG
Segwit Transactionに使われるOP_code
segwit(segregate witness)
今までのTransactionはscriptSigの改ざんができた(malleability問題)ため、トランザクションのインプットから署名を分離し、witnessの領域に移動させた。(一番上の図を参照。)
これにより、TXIDを作成するために必要だったトランザクションの領域が未署名な状態でも確定するため、未署名のトランザクションをInputに指定することができるようになった。
P2WPKH(Pay to Witness Public Key Hash)
Segwitバージョンの送金トランザクション。
ScriptPubkey
0 <20-byte pubkey hash>
ScriptSig
(空)
witness
<signature A> <pubkey A>
P2WSH(Pay to Public Key Hash)
Segwitバージョンの送金トランザクション。
ScriptPubkey
0 <32-byte redeem script hash>
ScriptSig
(空)
witness
<A value that meets redeem's unlocking criteria> <redeem script>
2-of-2マルチシグスクリプトの場合
ScriptPubkey
0 <32-byte redeem script hash>
ScriptSig
(空)
witness
0 <signature A> <signature B> <redeem script>
redeem script
2 <Pubkey A> <Pubkey B> 2 OP_CHECKMULTISIG
発展的なBitcoin Script
複雑なBitcoin Scriptを書くことでBitcoinを拡張して使うことができる。
拡張にはロックタイムをよく用いる。まずは、ロックタイム関連のOP_codeを説明する。
また、一般的なトランザクションではあまり用いられないため、上では紹介しなかったOP_SWAP、OP_SIZEも説明する。
OP_CHECKLOCKTIMEVERIFY
2016年6月にBIP-69として提案された。
先頭スタックがトランザクションのnLockTimeフィールドよりも大きい場合、トランザクションの検証に失敗する。
以下の場合にも検証に失敗する。
- 先頭スタックが空、0または負の値
- インプットのnSequenceの値が0xffffffff
- 先頭スタックが500000000以上でnLockTimeが500000000未満の時。間やその逆の場合。
OP_CHECKLOCKTIMEVERIFYの実行後引数はスタックに残るのでOP_DROPの使用を推奨。
OP_CHECKSEQUENCEVERIFY
2015年8月にBIP-112として提案された。
指定した相対時間(使用するトランザクションがブロックに取り込まれてからの経過時間)までトランザクションをロックする。
ビットが設定されている場合512秒単位の時間で、そうで無い場合ブロック高として解釈。unlockする際はトランザクションのnSequenceに解除期間を指定。
OP_SWAP
先頭から2このスタックの順序を逆転させる。
OP_SIZE
参考文献
*「ブロックチェーン・プログラミング 仮想通貨入門」, 講談社, 著:山崎重一郎, 安土茂亨, 田中俊太郎, 2017年08月22日
https://www.amazon.co.jp/dp/B078G94JNT/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1
*「Mastering Bitcoin 」
https://github.com/bitcoinbook/bitcoinbook/blob/develop/preface.asciidoc
-
Script - Bitcoin Wiki :
https://en.bitcoin.it/wiki/Script -
Transaction - Bitcoin Wiki :
https://en.bitcoin.it/wiki/Script