9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Mastering Bitcoin Script

Last updated at Posted at 2022-06-14

Mastering Bitcoin Script

2年ほど前に書いた記事を発掘したので今更公開する。
詳しくは参考文献である「ブロックチェーン・プログラミング 仮想通貨入門」を読んでみるのがいい。
https://www.amazon.co.jp/dp/B078G94JNT/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

前提


(出典) Segwitに関して調べた記録2

 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

一度自分で触ってみて欲しい。

よく使う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

9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?