
はじめに
本ページは設計文書シリーズのL1 #8 — ウォレット設計である。Bitcoin Coreのアプリケーション層を扱う: ソフトウェアが鍵をどう管理し、アドレスをどう導出し、コインをどう選択し、トランザクションをどう構築・署名し、手数料をどう推定し、外部呼び出し元にどう機能を公開するか。トランザクション設計ページのUTXOモデルとスクリプトタイプ、および暗号設計ページの鍵導出と署名の基本要素に依存する。
ウォレットはビットコインにおいて秘密鍵に触れる唯一のサブシステムである。他のコンポーネント(検証、中継、ストレージ、合意形成)はすべて公開データのみで動作する。この非対称性が、ウォレットをノードバイナリー内の密結合モジュールから論理的に(そして次第に物理的にも)分離されたプロセスへと進化させる原動力となった。
サトシ時代の実装(v0.1、2009年1月。Forensicxsによる2024年のコードウォークスルーが行単位で調査済み)と現代のBitcoin Core(v27以降を基準)で挙動が異なる箇所は、双方を記載する。
1. ウォレットアーキテクチャの概要
以下の図はウォレットのBitcoin Coreプロセス内での位置と、通信するインターフェースを示す。実験的なマルチプロセスのビルドでは、ウォレットはIPC経由でノードに接続する別プロセスとして動作できる。
サトシ時代のアーキテクチャ
v0.1ではウォレットはインターフェース境界なしにノードバイナリーに組み込まれていた。GUI、鍵ストア、マイナー、検証エンジンがすべて単一のプロセスと単一のBerkeley DBファイル(wallet.dat)を共有していた。初回リリース時にはRPCサーバーは存在しなかった。JSON-RPCが加わったのはリリースから約13か月後、v0.2.6(2010年2月)のことで、その年の7月のv0.3リリースで初めて主要機能に格上げされた。
2. 鍵管理
鍵管理はウォレットの最も重要な責務である。秘密鍵を失うことは、それが管理する資金を永久に失うことを意味する。訴える先の復旧機関は存在しない。この永久性が実際にどう現れるかは、アーカイブのビットコイン象徴的損失概観が、ステファン・トーマスのIronKeyロックアウトやジェームズ・ハウエルズの埋立地行きハードドライブを含めてまとめている。ウォレットデータベース (wallet.dat、Berkeley DBまたはSQLite) は、合意データ (ブロックファイルとUTXO集合) とは別のストレージパスであり、ストレージ設計ページに記録されている。一方を失っても、もう一方には影響しない。
レガシー鍵プール(v0.3.14〜v0.20)
サトシのウォレットは当初、鍵を独立に生成していた: 各秘密鍵はwallet.datに保存される新規乱数で、先読みはなく、最後のバックアップ以降に作成された鍵は、ウォレットファイルが破壊されると失われた。このwallet.datは、トランメルにバックアップ対象を尋ねられたサトシ自身が名指ししたファイルであり、トランザクション対応のデータベースDBM(Berkeley DB)に保存されていた。この欠落はv0.3.12(2010年9月)まで続いており、同リリースが持つバックアップ手段は手動でファイルをコピーする新しいbackupwallet RPCコマンドのみだった。サトシが実際にこの欠落を解消したのは翌月のv0.3.14(2010年10月)で、100鍵の事前生成プール(「鍵プール」)により、今日取得したバックアップが近い将来に生成されるアドレスもカバーできるようになった。この欠落は理論上の懸念にとどまらなかった。実際、ダスティン・トランメルは2009年1月の時点で、まさにこのリスクをサトシに指摘していた。鍵プールがその欠落を解消する2年近く前のことである。
記述子ウォレット(v0.21以降、v23以降で既定)
現代のBitcoin Coreはレガシー鍵モデルを出力記述子(BIP 380〜386)で置き換える: ウォレットがアドレスをどう導出し、自身の出力をどう認識するかを完全に指定する合成可能な式。
| 特性 | レガシーウォレット | 記述子ウォレット(v27以降) |
|---|---|---|
| 鍵の出所 | 独立した乱数鍵 | 記述子からの決定性導出 |
| バックアップモデル | 新しい鍵のたびにwallet.datをエクスポート | 1回のシードバックアップで将来のすべての鍵をカバー |
| スクリプトタイプ認識 | ウォレットが鍵のコンテキストからタイプを推測 | 記述子がスクリプトタイプを明示的に宣言 |
| 監視専用サポート | 別の監視専用ウォレットをインポート | xpubのみ(秘密鍵なし)の任意の記述子が監視専用になる |
| マルチスクリプト対応 | 暗黙的(BIP 44/49/84/86規約) | 明示的 — 各記述子が個別の導出規則 |
| ストレージバックエンド | Berkeley DB(wallet.dat) | SQLite(新形式のwallet.dat) |
| 移行パス | — | migratewallet RPCでレガシー → 記述子に変換 |
3. アドレス生成
ビットコインアドレスはロックスクリプトのペイロードをユーザー向けにエンコードしたものである。ウォレットはアクティブな記述子からアドレスを生成し、アドレスが払い出されるたびに鍵プールを循環させる。具体的には、BIP 32子鍵導出により次の未使用インデックスで新しい鍵を導出し、得られた鍵素材(Taprootではさらに調整を加える)を以下のようにエンコードする。
ウォレットはギャップリミット(最後に使用されたアドレスの先に導出する連続未使用アドレスの数)を維持する。インデックスnのアドレスを使用するトランザクションが検出されると、ウォレットは常に未使用アドレスが利用可能になるよう鍵プールを拡張する。これにより、シードフレーズからの復元時に、トランザクションが見つからなくなるまでギャップリミット分を前方走査することで、資金の入ったアドレスをすべて再発見できる。
鍵導出の暗号学的詳細(BIP 32 HMAC-SHA512、強化導出と通常導出、secp256k1スカラー乗算)およびエンコード形式(Base58Check、Bech32、Bech32m)は暗号設計ページで扱う。
支払者ごとに新規アドレスを割り当てるという発想の根拠は、この仕組みそのものより古くから存在する。サトシは2009年1月にダスティン・トランメルへ宛てたメールで、支払者ごとに固有の受信アドレスを生成するという発想には「現実世界にあまり似たものがない」と述べている。これはまさに、上述のギャップリミットに支えられた鍵プールが解決しようとしている使い勝手の課題である。
4. コイン選択
ウォレットがトランザクションを構築する際、どのUTXOを入力として使用するかを選択しなければならない。コイン選択の問題は手数料最適化、プライバシー、UTXOプールの健全性の交差点に位置する。トランザクション設計ページで戦略を紹介した。本節では現代の選択パイプラインを詳述する。
選択パイプライン(v27以降)
無駄指標
無駄指標は、選択されたコインを今使う場合のコストと、仮想的な長期手数料率で使う場合のコストを比較して各候補選択を採点する。不必要なお釣り出力にはペナルティを与え、完全一致(お釣りなし)の解には報酬を与える。計算式は3つの要素のバランスをとる:
| 要素 | 計測対象 | 効果 |
|---|---|---|
| 入力コスト | 選択された入力のウェイト × (現在の手数料率 − 長期手数料率) | 長期レートに対して過払いの場合に正; 現在の手数料が低い場合に負(統合の好機) |
| お釣りコスト | お釣り出力の作成と後の使用にかかるコスト | 常に正 — お釣りは今の追加出力と後の追加入力 |
| 超過分 | お釣りなしトランザクションで手数料として失われる目標超過額 | 分枝限定法のわずかな超過分を手数料に充てる解にのみ適用 |
無駄スコアが低いほど良い。ウォレットは異なる戦略からのすべての候補選択を評価し、最も低い無駄の選択を採用する。
5. PSBTワークフロー
部分署名ビットコイントランザクション(BIP 174 / BIP 370)はトランザクション構築と署名を分離する。PSBTはUTXOデータ、導出パス、償還スクリプトなど署名者が必要とするすべてのメタデータを持ち運び、ブロックチェーンへのアクセスがないデバイスでも署名できるようにする。
ハードウェアデバイス(署名者2)は署名する前に自身の画面で出力を検証する。完了者が最終的なscriptSig/witnessを組み立てた後、抽出者がノードの検証・中継に使える完成したトランザクションを取り出す。
PSBTの役割
| 役割 | 処理内容 | 通常の担当者 |
|---|---|---|
| 作成者 | 入力と出力を定義; 未署名PSBTを生成 | ウォレットソフトウェア、createpsbt RPC |
| 更新者 | UTXO詳細、導出情報、スクリプトを添付 | 同じウォレットまたはコーディネーター; walletprocesspsbt RPC |
| 署名者 | 管理する入力に部分署名を追加 | ハードウェアウォレット、エアギャップマシン、またはwalletprocesspsbt |
| 結合者 | 複数署名者からの部分署名を1つのPSBTに統合 | combinepsbt RPC |
| 完了者 | すべての署名から最終的なscriptSig / witnessを組み立て | finalizepsbt RPC |
| 抽出者 | 完了済みPSBTから完成したネットワーク送信可能なトランザクションを取り出す | finalizepsbt(PSBTと生の16進数の両方を返す) |
PSBTが重要な理由。BIP 174以前は、マルチデバイス署名にはアドホックな形式やベンダー固有のプロトコルが必要だった。PSBTは、準拠するどのウォレットでも生成、更新、署名、完了できる単一のポータブルで自己記述的なコンテナーを提供する。ハードウェアウォレット統合、マルチシグワークフロー、CoinJoin調整、トランザクションを構築するデバイスが鍵を保持するデバイスではないあらゆるシナリオの基盤である。
6. 手数料推定
ビットコインのトランザクションは限られたブロック空間を競う。ウォレットは目標ブロック数以内でトランザクションが承認される可能性の高い手数料率(仮想バイトあたりのサトシ数)を推定しなければならない。
推定メカニズム
Bitcoin Coreのestimatesmartfeeはトランザクションがメモリープールに入った時の手数料率を追跡し、各トランザクションが承認までに何ブロック待ったかを記録する。トランザクションは手数料率でバケットに分類され、各バケットについて推定器は成功率(その手数料率のトランザクションのうちnブロック以内に承認された割合)を維持する。指定された承認目標に対する推定値は、成功率が閾値(経済的モードで85%、保守的モードで95%)を超える最低手数料率バケットである。
| モード | 閾値 | 挙動 | 典型的な用途 |
|---|---|---|---|
| 経済的 | 85% 成功率 | 低手数料、承認がやや遅れるリスク | 緊急でない支払い |
| 保守的 | 95% 成功率 | 高手数料、より確実な承認 | 時間に敏感な支払い |
手数料推定の進化
| 側面 | サトシ時代(v0.1) | 現代のBitcoin Core、v27以降基準 |
|---|---|---|
| 手数料の要件 | GetMinFee: ウォレットは10,000バイト未満なら手数料を付けなかった。マイナーが10,000バイト未満の取引の手数料を免じたのは、ブロックの取引が100件未満のあいだだけだった。それ以外は0.01 BTC ×(1 + バイト数 ÷ 1,000の切り捨て) | 必須; 手数料なしのトランザクションはメモリープールポリシーで拒否 |
| 推定 | なし — 手数料市場が存在しなかった | バケットベースのメモリープール追跡(estimatesmartfee) |
| 手数料引き上げ | 利用不可 | RBF(bumpfee RPC)、CPFP(低手数料出力を高手数料の子で使用) |
| 最低中継手数料 | なし: メモリープールに入れるときのConnectInputsの最低手数料は0で、中継では手数料を確かめず、規則はウォレットが取引を作るときとマイナーがブロックを作るときにかかった | 1 sat/vB既定(minrelaytxfee) |
7. RPC・REST・ZMQインターフェース
Bitcoin Coreは外部呼び出し元に3つのインターフェースを公開する。それぞれ異なるアクセスパターンに対応する。
RPCコマンドカテゴリー
| カテゴリー | コマンド例 | 処理内容 |
|---|---|---|
| ブロックチェーン | getblockchaininfo、getblock、gettxoutsetinfo | チェーン状態、ブロックデータ、UTXOセット統計の問い合わせ |
| ウォレット | getnewaddress、sendtoaddress、listunspent、walletprocesspsbt | 鍵管理、トランザクション構築、コイン選択 |
| トランザクション | getrawtransaction、decoderawtransaction、sendrawtransaction | 生のトランザクションの検査、作成、ブロードキャスト |
| マイニング | getblocktemplate、submitblock、getmininginfo | ブロックテンプレート構築と提出(プール運営者向け) |
| ネットワーク | getpeerinfo、addnode、getnetworkinfo | ピア管理、接続状態、帯域幅統計 |
| 制御 | stop、uptime、logging、getmemoryinfo | ノードのライフサイクルと診断 |
| 手数料 | estimatesmartfee | 目標承認ウィンドウに対する手数料率推定 |
| PSBT | createpsbt、walletprocesspsbt、combinepsbt、finalizepsbt | 秘密鍵に直接触れない完全なPSBTワークフロー |
インターフェース比較
| 特性 | JSON-RPC | REST | ZMQ |
|---|---|---|---|
| プロトコル | HTTP POST(JSON本文) | HTTP GET(URLパス) | TCPプッシュ(パブ/サブ) |
| 認証 | クッキーまたはユーザー名/パスワード(rpcauth) | なし(設計上読み取り専用) | なし(ローカルネットワーク前提) |
| 方向 | 要求 → 応答 | 要求 → 応答 | サーバーがサブスクライバーにプッシュ |
| 書き込みアクセス | あり(トランザクション送信、ウォレット管理) | なし | なし(通知のみ) |
| データ形式 | JSON | JSON、バイナリー、または16進数(呼び出し元の選択) | 生のバイナリー(ブロックハッシュ、トランザクションハッシュ、または完全なシリアライズされたブロック/トランザクション) |
| 典型的な呼び出し元 | bitcoin-cli、ウォレットアプリ、取引所バックエンド | ブロックエクスプローラー、軽量モニター | インデクサー、リアルタイムダッシュボード、Lightningノード |
| ZMQトピック | — | — | hashblock、hashtx、rawblock、rawtx、sequence |
8. ノードからのウォレット分離
サトシのv0.1はウォレット、マイナー、GUI、検証エンジンを単一のバイナリーにコンパイルしていた。現代のBitcoin Coreはウォレットをノードから漸進的に分離してきた。
| マイルストーン | バージョン | 変更内容 |
|---|---|---|
| ウォレットインターフェース定義 | v0.17(2018年) | 内部のinterfaces::Wallet抽象化がウォレットロジックをノードロジックから分離 |
-disablewalletオプション | v0.8(2013年) | ウォレットを読み込まずにノードを実行可能 |
| マルチウォレット対応 | v0.15(2017年) | 単一のノードが複数のウォレットファイルを同時に読み込み管理。実行中の読み込みと解除はv0.17から |
| 記述子ウォレット | v0.21(2021年) | 新しいウォレット形式; v23以降で新規ウォレットの既定 |
| Berkeley DB非推奨 | v26(2023年) | レガシーBDBウォレットの作成には非推奨の旗が要る; 新規ウォレットはSQLite |
| レガシーウォレットの撤去 | v30(2025年) | BDBのレガシーウォレットは作成も読み込みもできなくなった; migratewalletでディスクリプターウォレットに変換する |
| マルチプロセス化(実験的) | v27以降(2024年) | 実験的なbitcoin-node / bitcoin-walletプロセス分離(IPCはCap’n Proto)。bitcoin-wallet CLIツールはオフラインウォレット操作を処理; 完全なIPCベースの実行時分離は進行中で既定ではない |
分離が重要な理由。ウォレットが扱う秘密鍵は、システム内で最も機密性の高いデータである。論理的分離(既に達成済み)と最終的な物理的プロセス分離により、鍵を保持するコンポーネントを制限された環境で動作させ、ノードは公開的に検証可能なチェーンデータを処理する。
9. 二つの時代の比較
| 機能 | サトシ時代(v0.1、2009年1月) | 現代のBitcoin Core、v27以降基準 |
|---|---|---|
| アーキテクチャ | ウォレットが単一バイナリーノードに組み込み | 論理的に分離済み; 実験的マルチプロセス分離が進行中 |
| 鍵生成 | リリース時は独立乱数鍵; 100鍵の先読みプールはv0.3.14(2010年10月)で追加 | 記述子ウォレット: マスターシードからの決定性導出 |
| バックアップモデル | 新しい鍵のたびにファイルをエクスポート; バックアップ後の新しい鍵は復元不能 | 記述子バックアップがすべての導出鍵をカバー(BIP 39ではなく生のBIP 32シード) |
| アドレスタイプ | P2PK、P2PKHのみ | P2PKH、P2SH、P2WPKH、P2WSH、P2TR |
| アドレスエンコード | Base58Check | Base58Check(レガシー)、Bech32、Bech32m |
| コイン選択 | ちょうどの額、なければ無作為の部分和1,000回か目標額を上回る最小の硬貨(ナップサックの祖先) | 分枝限定法 + ナップサック + 単一ランダム抽出 + CoinGrinder; 無駄指標による採点 |
| トランザクション署名 | 内部、同一プロセス | 内部、PSBT(BIP 174/370)、またはハードウェアウォレット(HWI経由) |
| マルチデバイス署名 | 未対応 | PSBTワークフロー: 作成 → 更新 → 署名 → 結合 → 完了 |
| 手数料推定 | なし(大半のトランザクションが無料) | バケットベースのメモリープール追跡; 経済的モードと保守的モード |
| 手数料引き上げ | 利用不可 | 手数料置換(bumpfee)、CPFP |
| インターフェース | リリース時はなし; JSON-RPCはv0.2.6(2010年2月、リリースから13か月後)に追加 | JSON-RPC(完全)、REST(読み取り専用)、ZMQ(プッシュ通知) |
| マルチウォレット | ノードあたり1ウォレット | 複数ウォレットを同時に読み込み; loadwallet / unloadwallet |
| 暗号化 | 利用不可 | encryptwallet — 保存時の秘密鍵をAES-256-CBCで暗号化 |
| 監視専用 | 未対応 | xpubのみ(秘密鍵なし)の任意の記述子 |
| プロセスモデル | 一体型(ウォレット + ノード + マイナー + GUI) | モジュール型: bitcoind(ノード)、bitcoin-wallet(ウォレット)、bitcoin-qt(GUI) |
10. 本ページの範囲
本ページはBitcoin Coreのウォレットとインターフェース層を扱う。以下のトピックは範囲外であり、設計文書シリーズ内のそれぞれのページで扱う:
- トランザクション構造とスクリプト: 入力、出力、ロックスクリプトがプロトコルレベルでどう機能するか。トランザクション設計ページで扱う。
- 暗号学的基本要素: 楕円曲線数学、ハッシュ関数、HD導出の内部(BIP 32 HMAC-SHA512)、署名アルゴリズム。暗号設計ページで扱う。
- メモリープールポリシー: 中継規則、手数料率の下限、パッケージリレー、手数料置換の適用。ネットワーク設計ページで扱う。
- マイニングとブロックテンプレート: マイナーがメモリープールからトランザクションを選択し候補ブロックをどう構築するか。合意形成設計ページで扱う。
- サードパーティーウォレット: Electrum、Sparrow、ハードウェアウォレット、モバイルウォレットはBitcoin Coreリファレンス実装の外部のアプリケーション層ソフトウェア。
- Lightning Network: ここで記述したトランザクションとPSBTの基本要素の上に構築されるが、別のプロトコルで動作するレイヤー2決済チャネル。
トランザクション設計は、ここが終わるところから始まる。ウォレットが組み立てて署名したものが、トランザクション層の運ぶものである。




















