hiro99ma blog

何か技術的なこと

btc: btcdebを使う (3)

2025/01/21

はじめに

btcdeb を使ってスクリプトのデバッグをしてみよう。

bitcoin-core/btcdeb: Bitcoin Script Debugger

前回から P2TR script path での使い方を模索している。

どういうときに使いたいか

そもそもスクリプトのデバッグをしたいというのはどういうときだろうか?
デバッグしたいのは失敗する場合がほとんどだろう。
私がやるときは、アプリを作って regtest で試すのが最初だ。 何かが間違って失敗する。

いろいろだ、いろいろあるのだ。

スクリプトは間違えにくいものではあるのだが、例えば私は 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 に与えた方が簡単かもしれない。

次回は一般的なライブラリでトランザクションを作っていこう。

< Top page