Bitcoin::Scriptを実行する

P2SH宛てのトランザクションを作ろうとしたとき、スクリプトはちゃんと動いているかな？とデバッグしてみたくなります。

BitcoinのRuby実装は、スクリプトをScriptクラスで扱っていて、そのメソッドの一つにrunがあるので、それを使いながら動きを見てみましょう。

特に、スクリプト実行中のスタックの状態が見れるdebugという配列はなかなか便利です。（後述）

# P2PKHのスクリプト

まずは、シンプルなP2PKHのとき。

こんなvoutがあったとする。

```json
  "vout": [
    {
      "value": 0.99900000,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 687eb2c06a660cdbab88e9ea6b0ce45a1fddb99e OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a914687eb2c06a660cdbab88e9ea6b0ce45a1fddb99e88ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "mq3UM9q26id4iJaguoST1RaHEJAtZuZCLK"
        ]
      }
    }
  ]
```

これを、新しいトランザクションのvinに組み込むときに、署名の検証と署名をつけるわけですが、

stringで表現すると、「OP_DUP ...」。hexで表現すると「76a...」

# Scriptオブジェクトを作る

```rb
script_hex = '76a914687eb2c06a660cdbab88e9ea6b0ce45a1fddb99e88ac'
script = Bitcoin::Script.new(script_hex.htb)

 => #<Bitcoin::Script:0x007ff8fb8876f0 @raw_byte_sizes=[25, 0], @previous_output_script=nil, @input_script="v\xA9\x14h~\xB2\xC0jf\f\xDB\xAB\x88\xE9\xEAk\f\xE4Z\x1F\xDD\xB9\x9E\x88\xAC", @raw="v\xA9\x14h~\xB2\xC0jf\f\xDB\xAB\x88\xE9\xEAk\f\xE4Z\x1F\xDD\xB9\x9E\x88\xAC", @chunks=[118, 169, "h~\xB2\xC0jf\f\xDB\xAB\x88\xE9\xEAk\f\xE4Z\x1F\xDD\xB9\x9E", 136, 172], @exec_stack=[], @stack_alt=[], @stack=[], @last_codeseparator_index=0, @do_exec=true> 

# 想定したスクリプトが作れたか確認。jsonのasmと同じ値であればOK
script.to_string
 => "OP_DUP OP_HASH160 687eb2c06a660cdbab88e9ea6b0ce45a1fddb99e OP_EQUALVERIFY OP_CHECKSIG" 

# アドレスに変換してみる
hash160_to_address('687eb2c06a660cdbab88e9ea6b0ce45a1fddb99e')
 => "mq3UM9q26id4iJaguoST1RaHEJAtZuZCLK" 
```

# 実行する

実行といえば、run。

```rb
script.run
 => false 
```

うん。

scriptPubKey単体では実行できない。scriptSigと合わせて初めて正常に動作する。（後述）

# 引数を渡す

引数を渡して使うらしい。do〜endは、runの中でコールバックされる。

```rb
block_timestamp = 200 # 適当
opts = {} # 適当
tx = （省略） # Scriptで検証するためのtx。（つまり、UTXOを指定するvin）
sig_valid = script.run(block_timestamp, opts) do
    |pubkey,sig,hash_type,subscript|
  hash = tx.signature_hash_for_input(in_idx, subscript, hash_type)
  Bitcoin.verify_signature( hash, sig, pubkey.unpack("H*")[0] )
end
 => false 
```

なるほど、、、わからん

do〜end句は、validate用のためのコールバック。このコールバックを定義していないと、OP_CHECKSIGが何でもtrueを返してしまう。（末尾参考）


# 自力でrun

runの中身を逐次実行してみる。コールバックはその場で呼ぶ。

## P2PKH

公式サイト（参考）によると、P2PKHのトランザクションにつけるスクリプトの実行（検証）には、次のようにおこなう

> <script_sig> <script_pub_key>

というわけで、vinの"scriptSig"とUTXOの"scriptPubKey"を組み合わせて、Script
を作る

```rb

# 前のTxのscriptPubKeyを取る
# 注意：もし、それがP2SHであれば、scriptPunKeyがないので、エラーになる。
script_pubkey = prev_tx.out[prev_tx_out_index].pk_script

tx.in[1].script
=> "H0E\x02!\x00\xB6=\xE7\xD8\x11;\x80\x10X\xCDL3+L{,\xA1~\x8Dr\xCC\xC7\x13\xBA\xC7\xEF\x14+\xCF\xD0}\xAA\x02 V\x92\x9Dt}\xC29\xC9\xC8]\x7F\xBC\xAF\xD4\x15\xEC\r9\x19\x81&\xC2\x9F\xAAf3q{\x04d\x1D\v\x01!\x02r\xE3=\xAB\x1Eo(\x170\xC4\xA7\xAA\xE5\xEE\x85\xE1\xCD\xE6\x10+\x06\xC6\x1E\xE7\xA3TO\xD0\xA1\x8D,\xEC" 

script_pubkey.to_string
=> "v\xA9\x14h~\xB2\xC0jf\f\xDB\xAB\x88\xE9\xEAk\f\xE4Z\x1F\xDD\xB9\x9E\x88\xAC" 

# scriptを作る
script = Bitcoin::Script.new(tx.in[1].script + script_pubkey)

# scriptを見る
script.to_string
 => "3045022100b63de7d8113b801058cd4c332b4c7b2ca17e8d72ccc713bac7ef142bcfd07daa022056929d747dc239c9c85d7fbcafd415ec0d39198126c29faa6633717b04641d0b01 0272e33dab1e6f281730c4a7aae5ee85e1cde6102b06c61ee7a3544fd0a18d2cec OP_DUP OP_HASH160 687eb2c06a660cdbab88e9ea6b0ce45a1fddb99e OP_EQUALVERIFY OP_CHECKSIG" 

# 1: sig (encrypted payload with privkey)
# 2: pubkey (no-hash)
# -- 上 scriptSig || 下 scriptPubKey
# 3: OP_DUP
# 4: OP_HASH160 (in order to derive hash160 of pubkey in 3 which is equal to 2)
# 5: hash160 of pubkey
# 6: OP_EQUALVERIFY
# 7: OP_CHECKSIG

# 実行する
script.run
 => true
```

おお！

## P2SH

P2PKHと同じようにやってみる。ただし、前のトランザクションにはscriptPubKeyがないので、代わりにredeem script（何らかの手段で事前に共有）を元に使うことに注意。

このとき、redeem_script（P2PKHのscriptPubKey（前のTxのvout中に記載）に相当）に合わせて、scriptSigも書き換えなければならない。便宜上、ここでは、spend_scriptと呼ぶ。
仮に、P2PKHのように、単に"scriptSig + redeem_script"でスクリプトを作成すると、プログラム実行のスタックがうまく処理されずに、falseとなる。

繰り返しになるが、redeem_scriptからspend_scriptを作り、それとscriptSigと合体させたスクリプトを実行する。

```rb
redeem_script_hex     =
'0175b1752102057820710677d967d13b6be404a2622498ce0f84cbb107b9003f83337a6d011bac'
 => "0175b1752102057820710677d967d13b6be404a2622498ce0f84cbb107b9003f83337a6d011bac" 

# redeem_scriptをScriptオブジェクトにする
redeem_script = Bitcoin::Script.new(redeem_script_hex.htb)
 => #<Bitcoin::Script:0x007ff8face0c70 @raw_byte_sizes=[39, 0], @previous_output_script=nil, @input_script="\x01u\xB1u!\x02\x05x q\x06w\xD9g\xD1;k\xE4\x04\xA2b$\x98\xCE\x0F\x84\xCB\xB1\a\xB9\x00?\x833zm\x01\e\xAC", @raw="\x01u\xB1u!\x02\x05x q\x06w\xD9g\xD1;k\xE4\x04\xA2b$\x98\xCE\x0F\x84\xCB\xB1\a\xB9\x00?\x833zm\x01\e\xAC", @chunks=["u", 177, 117, "\x02\x05x q\x06w\xD9g\xD1;k\xE4\x04\xA2b$\x98\xCE\x0F\x84\xCB\xB1\a\xB9\x00?\x833zm\x01\e", 172], @exec_stack=[], @stack_alt=[], @stack=[], @last_codeseparator_index=0, @do_exec=true> 

# Scriptを作成
script = Bitcoin::Script.new(tx.in[0].script + spend_script)

# scriptを見てみよう
script.to_string
 => "304402200d1568e4762531c08a9b81520162c1f8d8927dc54dd792d7942d969e438c917e022063c38a7f3177e0f18b90cf5ffe011388d4bc3aa46d2e59ae53cac008a170d0f601 0175b1752102057820710677d967d13b6be404a2622498ce0f84cbb107b9003f83337a6d011bac 75 OP_NOP2 OP_DROP 02057820710677d967d13b6be404a2622498ce0f84cbb107b9003f83337a6d011b OP_CHECKSIG"

# 1: sig (encrypted payload with privkey)
# 2: pubkey (no-hash)
# -- 上 scriptSig || 下 scriptPubKey
# 3: 75 (locktime in little endian of 117)
# 4: OP_NOP2 (operation of check locktime)
# 5: OP_DROP (drop the top of stack that is 2)
# 6: pubkey (no in hash)
# 7: OP_CHECKSIG

# 念のため、本当にキーはあっているか確認
pubkey_to_address('02057820710677d967d13b6be404a2622498ce0f84cbb107b9003f83337a6d011b')
 => "n4ZjDj9GArupgYd5fnCgHbQJYzw6W7EXsg" 

pubkey_to_address('0175b1752102057820710677d967d13b6be404a2622498ce0f84cbb107b9003f83337a6d011bac')
 => "n1zMx3XjbE45vewnSTou4WzrEfXoxe19Ux" 

# あれ？？
```

うーん、検証中


# デバッグ

trueとfalseにたどり着くまでの過程が見たいとき。

```rb
script = Bitcoin::Script.from_string("1112223330 123456 OP_CHECKSIG")

script.debug
 => [[], "PUSH DATA 1112223330", [["1112223330"]], "PUSH DATA 123456", [["1112223330"], ["123456"]], "OP_CHECKSIG", [1], "RESULT"] 

# 初期状態
script.debug[0]
 => [] 

# 第一段階
script.debug[1]
 => "PUSH DATA 1112223330" 

# 第二段階
script.debug[2]
 => [["1112223330"]] 

# 以降、各段階ごとに配列に入っている

script.debug[4]
 => [["1112223330"], ["123456"]] 

script.debug[5]
 => "OP_CHECKSIG" 

script.debug[6]
 => [1]  # ??!?!?!?!!?!

script.debug[7]
 => "RESULT" 

```

true(=1)になっている原因は、OP_CHECKSIG実行時にコールされるコールバックメソッドが未定義のため。

```rb
  # run the script. +check_callback+ is called for OP_CHECKSIG operations
  def run(block_timestamp=Time.now.to_i, opts={}, &check_callback)
    # 省略
    m.call(check_callback)
```


# OP
## OP_DROP

> Removes the top stack item.

スタックの最上位の項目を削除する。OPCODE = 117(0x75)

## OP_CHECKSIG
OPCODE = 172 (0xAC)
引数1 = sig, 引数2 = pubkey
戻り値 True / false

> The entire transaction's outputs, inputs, and script (from the most recently-executed OP_CODESEPARATOR to the end) are hashed. The signature used by OP_CHECKSIG must be a valid signature for this hash and public key. If it is, 1 is returned, 0 otherwise.

ハッシュ（トランザクションのoutput, input, scriot）と、pubkeyが妥当か検討する。
（どういうこと？）

## OP_NOP2

そのうち、OP_CHECKLOCKTIMEVERIFYという名前に変わる
OPCODE = 177 (0xb1)
引数 = なし、戻り値 = なし（またはfail）
> Marks transaction as invalid if the top stack item is greater than the transaction's nLockTime field, otherwise script evaluation continues as though an OP_NOP was executed. Transaction is also invalid if 1. the stack is empty; or 2. the top stack item is negative; or 3. the top stack item is greater than or equal to 500000000 while the transaction's nLockTime field is less than 500000000, or vice versa; or 4. the input's nSequence field is equal to 0xffffffff. The precise semantics are described in BIP 0065

トランザクションのnLockTimeが、スタック最上位の数**よりも（greater than）大きい**ときに無効になる。（すなわち、nLockTimeが、スタック最上位の数（redeem_scriptで指定）**以下**のときに有効になる。

その他の無効条件
4. inputのnSequence fieldが0xffffffffのときも、無効になる。


#　参考
https://en.bitcoin.it/wiki/Transaction