btc: bitcoinjs-lib を使う (1)
2025/01/22
はじめに
P2TR を扱うのに node.js で使える bitcoinjs-lib を使ってみよう。
私は bitcoinjs-lib をまったく使ったことが無いというと嘘になるが、どこかからサンプルを持ってきていじる程度しか扱ったことが無い。
そういう点では JavaScript/TypeScript もそんなに慣れていないのだが、今みたいにいじりながら確認するときには向いていると思ったのだ。
それ以外の言語でやるならこんなところだろうか。
私は libwally-core をちょっとと btcd くらいしか使ったことが無いが。
- C: ElementsProject/libwally-core
- C++: libbitcoin/libbitcoin-system: Bitcoin Cross-Platform C++ Development Toolkit
- Go: btcsuite/btcd: An alternative full node bitcoin implementation written in Go (golang)
- Rust: bitcoindevkit/bdk: A modern, lightweight, descriptor-based wallet library written in Rust!
Rust は全然わからんのだが、Bitcoin 界隈では新しく作るプロジェクトで使われることが多くなってきた。
組み込みの Rust もあるようだし C言語から呼び出すこともできるので置き換えながら勉強していくのもありなのかも?
長いこと C言語で組み込み開発をしていた影響かもしれないけど、言語についての知識が中途半端になるのが怖いのよね。。。
bitcoinjs-lib を少しだけ動かす
key path のテストコードを試そうと思ったが、テストコードだけだって長い。。。
サンプルコードじゃないからね。
こちらのサイトのサンプルを使うことにした。
testnet を使っていて、展開などは blockstream.info の API を使っている。
key path spend
“1. Key Path Spend” のデータを使うようにした。
- https://github.com/hirokuma/taproot-with-bitcoinjs/commit/5a7cefb325d5d94887a505c101721e5be8081043
- blockstream.info の API は使わない
- internal private key を固定値にする
SIGHASH_ALL
に変更しようとしたがダメだったので raw data は一致しない- が TXID は witness を含まないので一致する
Running "Pay to Pubkey with taproot example"
sent address: bc1ppuxgmd6n4j73wdp688p08a8rte97dkn5n70r2ym6kgsw0v3c5ensrytduf
Using UTXO a7115c7267dbb4aab62b37818d431b784fe731f4d2f9fa0939a9980d581690ec:0
Spent Transaction Hex: 02000000000101ec9016580d98a93909faf9d2f431e74f781b438d81372bb6aab4db67725c11a70000000000ffffffff0110270000000000001600144e44ca792ce545acba99d41304460dd1f53be3840140dcb5efe9455d2ad2e2a12f1463901259dc716e21d36d65974f1ab4a418b9fe2e512e72508ece41454f696b639bb8af087aefc5a1f77654b6ac0103a520e25c6000000000
Txid: 091d2aaadc409298fd8353a4cd94c319481a0b4623fb00872fe240448e93fcbe
sighash type が指定できないので署名の一致が確認できないのが残念だ。
改造しても署名が 64バイトになるようにできてしまう。
ちゃんとできたのかは regtest に展開するなどで確認するしかないか。
署名に乱数要素を外部から与えていないので元々あわないのか。
乱数生成をどうやっているかは確認できなかった。
script path spend
“3. Script Path Spend (Signature)” のデータを使う。
SIGHASH_ALL
にできないので完全な一致は確認できない。
- https://github.com/hirokuma/taproot-with-bitcoinjs/commit/9bf33b017d881bd983e11c6f27ce0cf343adb7de
- スクリプトが 1つなので
scriptTree
の型がTapleaf
になった toXOnly()
は API にあったので置き換え- TypeScript の設定で
noImplicitAny
をtrue
にするといくつか指摘されるのだが解消できないのであきらめた
- スクリプトが 1つなので
Running "Taptree example"
sent address: bc1p7dmcmml9zuafhackj463zc3yl9suq0rjts8f3wx63u2a72gefwqqku46c7
The script path with UTXO d1c40446c65456a9b11a9dddede31ee34b8d3df83788d98f690225d2958bfe3c:0
Spent Transaction Hex: 020000000001013cfe8b95d22502698fd98837f83d8d4be31ee3eddd9d1ab1a95654c64604c4d10000000000ffffffff01983a0000000000001600140de745dc58d8e62e6f47bde30cd5804a82016f9e0340b0a357496f15f21327576f2205fdbe4643928ca8c67d8ddaa1ea5150e28fad446a956644987586028e4c2d16e8076e3f4a4885b4e58a052ddb214ab0a91f7b2822206d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0ac21c0924c163b385af7093440184af6fd6244936d1288cbb41cc3812286d3f83a332900000000
Txid: 797505b104b5fb840931c115ea35d445eb1f64c9279bf23aa5bb4c3d779da0c2
SIGHASH_DEFAULT
になるので署名サイズが違うだろうし、署名の乱数要素を指定できないので毎回値が変わると思う。
それはともかく、やっぱりかなり面倒だ。
これを一から作れといわれてもちょっと無理だな。。。
といっても、ライブラリ無しで作ることを考えるとわかりやすいのは間違いなかろう。
おわりに
サンプルのデータを与えて署名以外は計算が一致した。 しかしそれではよくわからんので regtest で試したい。