btc: btcdebを使う (3)
2025/01/21
はじめに
btcdeb を使ってスクリプトのデバッグをしてみよう。
bitcoin-core/btcdeb: Bitcoin Script Debugger
前回から P2TR script path での使い方を模索している。
- 01/20 btc: btcdebを使う (2)
- 01/19 btc: btcdebを使う
どういうときに使いたいか
そもそもスクリプトのデバッグをしたいというのはどういうときだろうか?
デバッグしたいのは失敗する場合がほとんどだろう。
私がやるときは、アプリを作って regtest で試すのが最初だ。
何かが間違って失敗する。
- スクリプトが間違えている
- scriptPubKey の作り方を間違えている
- witness の構成が間違っている
- 署名が間違えている
- sigMsg が間違えている
- control block が間違えている
- ↑の認識はあっているが関数の使い方を間違えている
いろいろだ、いろいろあるのだ。
スクリプトは間違えにくいものではあるのだが、例えば私は OP_CSV
の引数を 10, 100, 200 にしたことで失敗したことがある。
10(0x0a) という数値をスタックに載せたかったら OP_10(0x5a)
だが、100(0x64) だと 0164
、200(0xc8) だと 02c800
になる。
こういうのは btcc
コマンドを使うとわかるので助かる。
$ btcc 10
warning: ambiguous input 10 is interpreted as a numeric value; use 0x10 to force into hexadecimal interpretation
warning: ambiguous input 10 is interpreted as a numeric value; use OP_10 to force into opcode
5a
$ btcc 100
0164
$ btcc 200
02c800
ではなく。デバッガの話だった。
オフラインで確認するのでブロックチェーンに展開する必要がないのがよいところだろうか。
しかし doc/tapscript-example.md などでは regtest に展開して --txin
のデータを作っている。
--tx
については createrawtransaction
したデータを segwit V1 っぽくするためか、marker, flag、witness は 1 つだけ 64byte の 0x00-0x0f を 4回繰り返したデータを載せていた。
どうせ OP_CHECKSIG
で失敗するならと witness stack を ‘0100’ にすると、最後は署名サイズがおかしいとなった。
--tx
は rawdata を取るからスペースで適当に区切っていても影響ないんだな。連結すると ''
で囲む必要もなかったがスペースで区切った場合はいるだろう。
では OP_CSV
などで待たずに検証できるとか?
しかし Tapscript spend では、
(since we don’t wanna wait a day, we will go with the latter one, Bob’s)
とかいっている。
ブロックチェーンを見るわけでもないから関係ないのでは?
試しに、雑に control block とその手前のスクリプトのスタック、sequence をいじって alice のルートを通してみた(locktime も変更してみたがブロックチェーンの高さがないので意味が無い)。
$ btcdeb --verbose --txin=$txin --tx='020000000001 015ad21d61d78dc29dd7a243d3e07d4b4a4652ae47f12d09d84f23d15aa4283d30000000000090000000 012823000000000000160014976a249d6f98141981dc54c536fe19ec92b9975b 02 27 029000b275209997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803beac 41 c1 5bf08d58a430f8c222bffaf9127249c5cdff70a2d68b2b45637eb662b6b88eb5 632c8632b4f29c6291416e23135cf78ecb82e525788ea5ed6483e3c6ce943b42 5a010000'
...
...
8 op script loaded. type `help` for usage information
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
<<< taproot commitment >>> | i: 0
Branch: 632c8632b4f29c6291416e23135cf78ecb82e525788ea5ed6483e3c... | k: c81451874bd9ebd4b6fd4bba1f84cdfb533c532365d22a0a702205ff658b...
Tweak: 5bf08d58a430f8c222bffaf9127249c5cdff70a2d68b2b45637eb662... |
CheckTapTweak |
<<< committed script >>> |
9000 |
OP_CHECKSEQUENCEVERIFY |
OP_DROP |
9997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803be |
OP_CHECKSIG |
#0000 Branch: 632c8632b4f29c6291416e23135cf78ecb82e525788ea5ed6483e3c6ce943b42
btcdeb> step
- looping over path (0..0)
- 0: node = 63...; taproot control node mismatch -> k second
(TapBranch(Span<33,32>=632c8632b4f29c6291416e23135cf78ecb82e525788ea5ed6483e3c6ce943b42 || TapLeaf(0xc0 || 029000b275209997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803beac)))
- 0: k -> 6b9f0cd659a5c64f4f5ac4f84e7998dae7fec41b47f5d7da6da9e21f8c6f6441
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
<<< taproot commitment >>> | i: 1
Branch: 632c8632b4f29c6291416e23135cf78ecb82e525788ea5ed6483e3c... | k: 41646f8c1fe2a96ddad7f5471bc4fee7da98794ef8c45a4f4fc6a559d60c...
Tweak: 5bf08d58a430f8c222bffaf9127249c5cdff70a2d68b2b45637eb662... |
CheckTapTweak |
<<< committed script >>> |
9000 |
OP_CHECKSEQUENCEVERIFY |
OP_DROP |
9997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803be |
OP_CHECKSIG |
#0001 Tweak: 5bf08d58a430f8c222bffaf9127249c5cdff70a2d68b2b45637eb662b6b88eb5
btcdeb> step
- looping over path (0..0)
- q.CheckTapTweak(p, k, 1) == success
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
9000 |
OP_CHECKSEQUENCEVERIFY |
OP_DROP |
9997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803be |
OP_CHECKSIG |
#0002 CheckTapTweak
btcdeb> step
<> PUSH stack 9000
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
OP_CHECKSEQUENCEVERIFY | 9000
OP_DROP |
9997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803be |
OP_CHECKSIG |
#0003 9000
btcdeb> step
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
OP_DROP | 9000
9997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803be |
OP_CHECKSIG |
#0004 OP_CHECKSEQUENCEVERIFY
btcdeb> step
<> POP stack
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
9997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803be |
OP_CHECKSIG |
#0005 OP_DROP
btcdeb> step
<> PUSH stack 9997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803be
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
OP_CHECKSIG | 9997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803be
#0006 9997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803be
btcdeb> step
error: Operation not valid with the current stack size
元が bob 側のルートになるデータだから OP_SHA256
用のデータがスタックにあるのが邪魔なのか変な終わり方になった。
ちなみに sequence を 0x8f (< 144) にするとエラーになる。OP_CSV
より前にエラーになるのはやっぱり出力がずれているからだろうか。
#0003 9000
btcdeb> step
error: Locktime requirement not satisfied
おわりに
デバッグはできるし、自分でコードをほとんど書かずに確かめられそうなのだけど、なかなか手間がかかる。
ここまで理解していてデバッグするなら、動くと分かっているライブラリでトランザクションデータを作り、そのデータを btcdeb に与えた方が簡単かもしれない。
次回は一般的なライブラリでトランザクションを作っていこう。