hiro99ma blog

何か技術的なこと

btc: btcdebを使う (2)

2025/01/20

はじめに

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

bitcoin-core/btcdeb: Bitcoin Script Debugger

前回はドキュメントに書いてあるように使っただけなので、今回は P2TR script path の確認をしていたときのデータを使ってやってみる。

script path の例

こちらの例を使う。

input tx=d1c40446c65456a9b11a9dddede31ee34b8d3df83788d98f690225d2958bfe3c でスクリプトはこういう形だ(“leaf script”)。

 20 6d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0
 OP_CHECKSIG

P2TR 以外であれば pubkey は 33バイトなので 0x21 で始まるが、P2TR の tapscript という時点でシュノア署名になるので 0x20 だ。 いつも「データ長」と書いているが、正しくはスタックにデータを積む OPコードだ。
OPコードの 0x01-0x4b までは同じ値の長さをその次のデータからスタックに積む、という命令になっている。
つまりここに出てくる「0x20」は、その次のデータから 0x20 バイト(32 バイト)をスタックに積むのである。

<<tx:d1c40446c65456a9b11a9dddede31ee34b8d3df83788d98f690225d2958bfe3c>>
02000000
0001

<vin_cnt>
01

<vin#0>
3cfe8b95d22502698fd98837f83d8d4be31ee3eddd9d1ab1a95654c64604c4d1 00000000
00
ffffffff

<vout_cnt>
01

<vout#0>
983a000000000000
1600140de745dc58d8e62e6f47bde30cd5804a82016f9e

<vin#0 witness_cnt>
03
<vin#0 witness#0>
4101769105cbcbdcaaee5e58cd201ba3152477fda31410df8b91b4aee2c4864c7700615efb425e002f146a39ca0a4f2924566762d9213bd33f825fad83977fba7f01
<vin#0 witness#1>
22206d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0ac
<vin#0 witness#2>
21c0924c163b385af7093440184af6fd6244936d1288cbb41cc3812286d3f83a3329

<locktime>
00000000

--txin を使う

既に展開済みになっているデータもあるので --txin を使ってみよう。 797505b104b5fb840931c115ea35d445eb1f64c9279bf23aa5bb4c3d779da0c2のデータである。

<<txin:797505b104b5fb840931c115ea35d445eb1f64c9279bf23aa5bb4c3d779da0c2>>

02000000
0001

<vin_cnt>
<vin#0>
関係ないので省略

<vout_cnt>
02

<vout#0> ※こちら
204e000000000000
225120f3778defe5173a9bf7169575116224f961c03c725c0e98b8da8f15df29194b80

<vout#1>
7472000000000000
1600149524b39436fd4abe0d48b156ebfb5d9c0d48850c

<witness>
関係ないので省略

<locktime>
052d0d00

実行。

$ btcdeb --tx=020000000001013cfe8b95d22502698fd98837f83d8d4be31ee3eddd9d1ab1a95654c64604c4d10000000000ffffffff01983a0000000000001600140de745dc58d8e62e6f47bde30cd5804a82016f9e034101769105cbcbdcaaee5e58cd201ba3152477fda31410df8b91b4aee2c4864c7700615efb425e002f146a39ca0a4f2924566762d9213bd33f825fad83977fba7f0122206d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0ac21c0924c163b385af7093440184af6fd6244936d1288cbb41cc3812286d3f83a332900000000 --txin=02000000000101289c4d2de39f53acc69da3d641810545c1b9b198a0c6b521456e2e12c2b7c6680000000000fdffffff02204e000000000000225120f3778defe5173a9bf7169575116224f961c03c725c0e98b8da8f15df29194b8074720000000000001600149524b39436fd4abe0d48b156ebfb5d9c0d48850c02473044022030b384e51521b2031cf8bab2a8a0f52dbec70cf199a6139b7ed81fbcdd382b48022038df47f71d4c5cf601366e52c3d808fa724e2deb207f5d3408f0577d5dc2f7aa0121037daba156158ed0d92c6acc34c3061af3b1a788b4f33772e27be1fdb569015d0a052d0d00
btcdeb 5.0.24 -- type `btcdeb -h` for start up options
LOG: signing segwit taproot
notice: btcdeb has gotten quieter; use --verbose if necessary (this message is temporary)
input tx index = 0; tx input vout = 0; value = 20000
got witness stack of size 3
34 bytes (v0=P2WSH, v1=taproot/tapscript)
Taproot commitment:
- control  = c0924c163b385af7093440184af6fd6244936d1288cbb41cc3812286d3f83a3329
- program  = f3778defe5173a9bf7169575116224f961c03c725c0e98b8da8f15df29194b80
- script   = 206d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0ac
- path len = 0
- p        = 924c163b385af7093440184af6fd6244936d1288cbb41cc3812286d3f83a3329
- q        = f3778defe5173a9bf7169575116224f961c03c725c0e98b8da8f15df29194b80
- k        = 16ef34a5bc45e95857f751fc3511a6f6ad0a1f631deefcc1a248dda326fe8d85          (tap leaf hash)
  (TapLeaf(0xc0 || 206d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0ac))
valid script
- generating prevout hash from 1 ins
[+] COutPoint(d1c40446c6, 0)
4 op script loaded. type `help` for usage information
script                                                             |                                                             stack
-------------------------------------------------------------------+-------------------------------------------------------------------
<<< taproot commitment >>>                                         |                                                               i: 0
Tweak: 924c163b385af7093440184af6fd6244936d1288cbb41cc3812286d3... | k: 858dfe26a3dd48a2c1fcee1d631f0aadf6a61135fc51f75758e945bca534...
CheckTapTweak                                                      |
<<< committed script >>>                                           |
6d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0   |
OP_CHECKSIG                                                        |
#0000 Tweak: 924c163b385af7093440184af6fd6244936d1288cbb41cc3812286d3f83a3329

btcdeb の k が不明だ。
スタックの方にも k が出ているが、また違う値だしこちらの値も不明だ。

スクリプトで必要になるのは OP_CHECKSIG のための署名だけなので、--tx<vin#0 witness#0> は署名である。
それ以降は script path のルールに従ってスクリプトを次の <vin#0 witness#1> に、最後は control block を vin#0 witness#2> に置いてある。

ステップ実行

以下、step でステップ実行していく。

btcdeb> step
- looping over path (0..-1)
- q.CheckTapTweak(p, k, 0) == success
script                                                             |                                                             stack
-------------------------------------------------------------------+-------------------------------------------------------------------
6d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0   | 01769105cbcbdcaaee5e58cd201ba3152477fda31410df8b91b4aee2c4864c7...
OP_CHECKSIG                                                        |
#0001 CheckTapTweak
btcdeb> step
                <> PUSH stack 6d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0
script                                                             |                                                             stack
-------------------------------------------------------------------+-------------------------------------------------------------------
OP_CHECKSIG                                                        |   6d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0
                                                                   | 01769105cbcbdcaaee5e58cd201ba3152477fda31410df8b91b4aee2c4864c7...
#0002 6d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0
btcdeb> step
EvalChecksig() sigversion=3
Eval Checksig Tapscript
- sig must not be empty: ok
- validation weight - 50 -> 136
- 32 byte pubkey (new type); schnorr sig check
GenericTransactionSignatureChecker::CheckSchnorrSignature(65 len sig, 32 len pubkey, sigversion=3)
  sig         = 01769105cbcbdcaaee5e58cd201ba3152477fda31410df8b91b4aee2c4864c7700615efb425e002f146a39ca0a4f2924566762d9213bd33f825fad83977fba7f01
  pub key     = 6d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0
SignatureHashSchnorr(in_pos=0, hash_type=01)
- tapscript sighash
- schnorr sighash = c980a90108fc424b92ab0ed0d9d889ebe59fd664d69720daa011e573d4532475
  pubkey.VerifySchnorrSignature(sig=01769105cbcbdcaaee5e58cd201ba3152477fda31410df8b91b4aee2c4864c7700615efb425e002f146a39ca0a4f2924566762d9213bd33f825fad83977fba7f, sighash=c980a90108fc424b92ab0ed0d9d889ebe59fd664d69720daa011e573d4532475):
  result: success
                <> POP  stack
                <> POP  stack
                <> PUSH stack 01
script                                                             |                                                             stack
-------------------------------------------------------------------+-------------------------------------------------------------------
                                                                   |                                                                 01
#0003 OP_CHECKSIG
btcdeb> step
script                                                             |                                                             stack
-------------------------------------------------------------------+-------------------------------------------------------------------
                                                                   |                                                                 01
#0003 OP_CHECKSIG
btcdeb>

出力がずれているだけなら、まあ大丈夫なのかな・・・?

btcdeb の issue を見ていると新しくしないと発生している問題(issue#154)もあるようだ。
ただ仕事が忙しいと書いてあるのでなかなか手が回らないのだろう。

おわりに

今回は --txin だけだったので、もう少しスクリプトをデバッグしているような感じで試してみねば。

< Top page