Develop with pleasure!

福岡でCloudとかBlockchainとか。

秘密鍵が対応するBitcoinアドレスの種類を指定する拡張WIFフォーマットを定義したBIP-178

Bitcoinアドレスは秘密鍵から計算した公開鍵を使って生成されるが、そのアドレスの種類は複数(P2PKH、P2WPKH、P2SHでネストしたP2WPKH)ある。いずれも同じ秘密鍵から生成可能なアドレスだが、実際にウォレットで使ってるアドレスはそのうちのどれか1つ。ただ、現在のWIF(Wallet Import Format)形式の秘密鍵では、どの種類のアドレスに関連付けられた秘密鍵なのか示すデータが存在しないので、それをわかるようにWIFフォーマットを拡張しようとBIP-178が提案された。

https://github.com/bitcoin/bips/blob/master/bip-0178.mediawiki

ただほとんどのユーザーはHDウォレットを使っており、どのアドレスを導出するかはその導出仕様(BIP-44、BIP-49、BIP-84)で定義されているため、ユーザーが個別の秘密鍵を管理するようなことは無いので、実際のユーザーが利用することはないと思うが、まぁ開発やテストなんかで秘密鍵単位でインポート・エクスポートする際には管理しやすくなるといったところか。

参照実装のプルリクがBitcoin Coreに投げられているけど、マージはされないままクローズされているので、今後どうなるか様子見かな。

以下、BIPの定義内容。

動機

1つの秘密鍵に対して、(1から始まるレガシーな)P2PKH、(P2WPKHのP2SHネスト版)P2SH-P2WPKH、P2WPKHなど対応するBitcoinアドレスは複数ある。

秘密鍵には対応する公開鍵が圧縮されているか(0x01)、非圧縮か(suffixなし)を示す1バイトのsuffixがあるが、秘密鍵に関連付けられているアドレスの種類を知る方法はない。その結果、秘密鍵をインポートする際に、ウォレットは全種類のアドレスを想定し、それぞれのアドレスを追跡する必要がある。

siffixを拡張することで、秘密鍵にどの種類のアドレスが関連付けられているのか指定できるようになる。

仕様

現在、秘密鍵はunit256の秘密鍵のデータの後にオプションでuint8のcompressed flagが付与される形で保存されている。この後者のフラグをアドレスタイプを指定できるよう拡張する。

タイプ 圧縮 定義
suffixなし P2PKH_UNCOMPRESSED No 非圧縮のレガシーな公開鍵。公開鍵フォーマットは不明
0x01 P2PKH_COMPRESSED Yes 圧縮されたレガシーな公開鍵。公開鍵フォーマットは不明
0x10 P2PKH Yes 圧縮されたレガシーな公開鍵。1から始まるレガシーな公開鍵フォーマットを使用。
0x11 P2WPKH Yes Bech32フォーマット(ネイティブSegwit)
0x12 P2WPKH_P2SH Yes 3から始まるP2SHでネストされたSegwitアドレス

ウォレットが秘密鍵をインポートすると、以下の2つの事がわかる。

  • 鍵はレガシータイプの1つを使っており、この場合すべてのタイプを考慮する必要がある。
  • 鍵は拡張タイプを使っており、この場合ウォレットは特定の対応するアドレスのみを追跡すればいい。

0x010x10の違いは、前者は上記いずれのタイプにも対応でき、後者は(従来の非Segwitの)P2PKHのみに対応していること。

互換性

この提案には後方互換性はなく、新しいタイプを認識しないソフトウェアはcompressed flagを理解できない。ただ、少しの変更で対応が可能で、uncompressedは(suffixがない)現在のまま、compressedを0以外のなんらかの値として解釈すればいい。

この提案は、新しいウォレットソフトウェアが古いWIFフォーマットを常に理解するという点で後方互換性がある。しかしそのフォーマットの秘密鍵をインポートした場合、そのアドレスの候補は複数あるためその全てを追跡する必要がある。

謝辞

このBIPはBitcoin DevメーリングリストのThomas Voegtlinの最初の提案と、Electrum 3.0の実装に基づいている。

参照実装

github.com