Bitcoin Coreでは、User-space Statically Defined Tracing(USDT、※Tetherではない)ベースのトレースポイントが提供されており、Linux環境で動作するBitcoin Coreでは、このトレースポイントを使って、内部のデータにアクセスできるようになっている。
Bitcoin Coreのトレースポイント
Bitcoin Coreには、v23.0の時点で以下のトレースポイントが組み込まれている。
参考:https://github.com/bitcoin/bitcoin/blob/master/doc/tracing.md
トレースポイント | 内容 |
---|---|
net:inbound_message |
P2Pネットワーク上のピアからメッセージを受信した際に呼び出される |
net:outbound_message |
P2Pネットワーク上でピアにメッセージを送信する際に呼び出される |
validation:block_connected |
ブロックがチェーンに接続された後に呼び出される |
utxocache:flush |
インメモリのUTXOキャッシュがフラッシュされた後に呼び出される |
utxocache:add |
UTXOキャッシュにコインが追加された際に呼び出される |
utxocache:spent |
UTXOキャッシュからコインが使用された際に呼び出される |
utxocache:uncache |
UTXOキャッシュから意図的にアンロードされ際に呼び出される |
coin_selection:selected_coins |
SelectCoins が完了すると呼び出される |
coin_selection:normal_create_tx_internal |
最初のCreateTransactionInternal が完了した際に呼び出される |
coin_selection:attempting_aps_create_tx |
CreateTransactionInternal が楽観的なAvoid Partial Spendsの選択試行のために2回目に呼び出された際に呼び出される |
coin_selection:aps_create_tx_internal |
Avoid Partial Spend が有効になっている2回目のCreateTransactionInternal が完了すると呼び出される |
各トレースポイントで取得可能なデータについては↑のドキュメント参照。
トーレス
実際に、上記のトレースポイントに対してトレースしてみる。Bitcoin Coreではリポジトリのcontrib/tracingにトレースのサンプルが用意されてる。
bpftraceを使ったトレース
最初は、bpftraceを使ったトレース。
bpftraceをまだインストールしていない場合はインストールから↓(Ubuntu)
$ sudo apt-get install bpftrace
P2Pのネットワークメッセージの情報を出力するbpftraceのスクリプトが用意されてるので実行してみる。リポジトリのルートから以下のコマンドを実行↓
$ sudo bpftrace contrib/tracing/log_p2p_traffic.bt Attaching 3 probes... Logging P2P traffic outbound 'inv' msg to peer 0 (outbound-full-relay, 73.166.84.222:8333) with 2 bytes inbound 'inv' msg from peer 0 (outbound-full-relay, 159.100.255.18:8333) with 1 bytes outbound 'getdata' msg to peer 0 (outbound-full-relay, 159.100.255.18:8333) with 2 bytes inbound 'inv' msg from peer 0 (outbound-full-relay, 94.231.253.18:8333) with 1 bytes outbound 'addrv2' msg to peer 0 (outbound-full-relay, 104.36.175.37:8333) with 2 bytes inbound 'tx' msg from peer 0 (outbound-full-relay, 159.100.255.18:8333) with 1 bytes inbound 'inv' msg from peer 0 (outbound-full-relay, 65.21.122.162:8333) with 1 bytes inbound 'inv' msg from peer 0 (outbound-full-relay, 128.0.51.17:8333) with 1 bytes ...
と、net:inbound_message
とnet:outbound_message
の2つのトレースポイントをフックして、データを出力できる。
※ log_p2p_traffic.bt
に実行中のbitcoind
のパスを記載する必要があり、ローカルでビルドしたものではない場合、適宜パスを修正する必要がある。
pythonでのトレース
サンプルとして、Pythonのスクリプトもある。こちらは、事前に↓のインストールが必要
$ sudo apt-get install python3-bpfcc
そして、p2p_monitor.py
を実行すると、
$ sudo python3 contrib/tracing/p2p_monitor.py <実行中のbitcoindのパス>
ターミナルにP2Pメッセージのやりとりが表示される↓
Pythonの方は、BCC(BPF Compiler Collection)を使ってeBPF用のバイトコードをコンパイルしていて、eBPFのコードはPythonのコード内にCで書く必要がある。bpftraceの方は、独自のDSLを記述する形なので、DSLの仕様さえ学習すればこっちの方がカジュアルに使えそう。