Develop with pleasure!

福岡でCloudとかBlockchainとか。

BIP-32の鍵導出と組み合わせてPay-to-Contractのアドレス導出方法を定義したBIP-175

以前ブログでも記事書いたPay-to-Contractのホワイトペーパー

techmedia-think.hatenablog.com

プロトコルがBIPになった↓

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

動機

Bitcoinトランザクションは、二者間で価値を移転する現実世界の契約を表す。現実の取引では、請求書や領収書で支払いを追跡している。支払人が請求明細の支払いに同意し、受取人が領収書にサインすると受取人により商品が発送される。GerhardtとHankeは準同型の支払アドレスとマルチパーティのpay-to-contract protocolを使ってBitcoinプロトコル内でこの相互作用を定式化した。

このプロトコルは、誰が何に支払うのかについて暗号的な証拠を全ての当事者が保持するよう構成されている。このBIPで説明されている技術を使うと、契約の条件と受取人の公開鍵からアドレスを導出できる。この導出スキームは、UTXOを増大させることなくネットワークの参加者から隠すことができる。導出されるアドレスはP2(W)PKHやP2(W)SHアドレスのように見える。資金を償還する際は契約と受取人の秘密鍵の知識が必要になる。

このスキームではBIP-32の基盤を利用して、既存のウォレット開発者が仕様を実装するための一貫性のある方法を提供する。

仕様

この鍵導出スキームには、支払人(顧客)と受取人(マーチャント)という2人の当事者が登場する。顧客は購入したい商品/サービスを指定して、購入リクエストをマーチャントに送る。購入リクエストを受け取ったマーチャントは請求明細と総支払額を指定して請求書(コントラクト)を作成する。マーチャントはこのコントラクトと一緒にpayment baseと呼ばれる拡張公開鍵を顧客に提供する。この情報が与えられると顧客は、コントラクト及びpayment baseに関連する支払アドレスの公開鍵を生成し、そこに送金することで契約を履行する。

以下のBIP-32のパスを定義する:

m / purpose' / coin_type' / contract_hash

contract_hashは複数のレベルで構成される。

パスのアポストロフィ(')は、BIP-32強化導出が適用されていることを意味する。

また以下の拡張公開鍵を定義する。

payment_base :

m / purpose' / coin_type'

payment_address :

m / purpose' / coin_type' / contract_hash
もしくは
m / payment_base / contract_hash

各レベルには以下で説明する特別な意味がある。

Purpose

BIP-42の勧告に従いpurposeフィールドの定数は175'(or 0x800000AF)になる。このノードサブツリーはこの仕様に従うことを意味する。

m / 175' / *

このレベルでは強化導出が使われる。

Coin Type

coin typeフィールドは、BIP-44と同じ。

このレベルでも強化導出が使われる。

支払先アドレスの生成

コントラクトドキュメント c1,...cn、拡張公開鍵payment_base、暗号学的ハッシュ関数hが与えられたとして、以下のステップで支払先のアドレスを計算する。

  1. コントラクトドキュメントについてハッシュ関数を適用し、ハッシュ値を計算する。
    h(c1),...,h(cn)
  2. 全てのハッシュを辞書順にソートする。
    hash_1,...,hash_n
  3. ソートしたハッシュを結合し、さらにハッシュ関数を適用してハッシュ値を計算する。
    h(hash_1+...+hash_n)
  4. ステップ3で結合したハッシュから後述するPartial Derivation Path Mappingで定義されている部分的なBIP-32導出パスを計算する。
    contract_hash
  5. contract_hash導出パスの前にpayment_baseを追加する。
    payment_base / contract_hash
  6. ステップ5の導出パスから拡張公開鍵を計算する。
  7. ステップ6の拡張公開鍵のアドレス(P2PKH)を計算する。

支払先アドレスの検証

与えられたBitcoinアドレスと、payment_base 拡張公開鍵、 c1,...cnで表されるコントラクトドキュメント、及びhで表される暗号学的ハッシュ関数から、次のステップでアドレスの完全性を検証することができる。

  1. 支払先アドレスの生成セクションの入力から、コントラクトアドレスを計算する。
  2. ステップ1で計算したアドレスと与えられたアドレスを検証する。

償還

マーチャントは、支払先アドレスの生成セクションで記載されている方法を使って、オフラインで秘密鍵を構成することができる。マーチャントは支払先アドレス宛ての送金をブロックチェーン上で監視する。アドレスはpayment baseとコントラクトから生成されるため、ロックされた資金を使用するためには暗黙的にコントラクトの条件に同意する必要がある。そのアドレスへの支払いは、顧客にとっては領収書になる。

ハッシュからPartial Derivation Path Mapping

このセクションでは、任意の16進数の数値からBIP-32の導出パスを部分的に生成するマッピング手順について説明する。

与えられた16進数の数値について以下の操作をする。

  1. 16進数の値を4文字毎に分割する。
  2. 分割した各パートを10進数の整数に変換する。
  3. 全ての数値を/で連結する。

サンプル

以下のデータが与えられた場合

master private extended key:
xprv9s21ZrQH143K2JF8RafpqtKiTbsbaxEeUaMnNHsm5o6wCW3z8ySyH4UxFVSfZ8n7ESu7fgir8imbZKLYVBxFPND1pniTZ81vKfd45EHKX73
coin type:
0

以下のようにpayment baseを計算することができる

payment base derivation path:
m/175'/0'
contract base public extended key:
xpub6B3JSEWjqm5GgfzcjPwBixxLPzi15pFM3jq4E4yCzXXUFS5MFdXiSdw7b5dbdPGHuc7c1V4zXbbFRtc9G1njMUt9ZvMdGVGYQSQsurD6HAW

以下の例では、SHA256を暗号学的ハッシュ関数として使用し、上記のコントラクトベース公開鍵を使用している。

支払先アドレスの生成 :

入力として、2つのドキュメントで構成されるコントラクトがあり、その内容が以下の場合

document 1:
bar
document 2:
foo

1.それぞれのハッシュ値を計算する。

document 1:
fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9
document 2:
2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae

2.生成したハッシュを辞書順にソートする

2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae
fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9

3.ハッシュを連結し、そのハッシュ値を計算する。

concatenated hash:
2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7aefcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9
combined hash:
ec321de56af3b66fb49e89cfe346562388af387db689165d6f662a3950286a57

4.計算したハッシュから部分的なBIP-32導出パスを計算する。

60466/7653/27379/46703/46238/35279/58182/22051/34991/14461/46729/5725/28518/10809/20520/27223

5.contract_hash導出パスの前にpayment_baseを付与する。

contract_base_pub/60466/7653/27379/46703/46238/35279/58182/22051/34991/14461/46729/5725/28518/10809/20520/27223
or
m/175'/0'/60466/7653/27379/46703/46238/35279/58182/22051/34991/14461/46729/5725/28518/10809/20520/27223

6.公開拡張鍵を計算する。

xpub6hML7vSU2Hwww9ctwrwt4ijnhJr4n6XaMRox1nnF3PvZKuF1SZoTymnKQHrF9fp2nWJSqv5ZjJSxJJQ8A3PKcBUWhGvTFmuRKpycSCr5coz

7.公開拡張鍵からアドレス(P2PKH)を計算する。

1HYjhPTtMmpBJBd5tVepZDAVdvPA7o8KHJ

検証例1(失敗パターン) :

上記の入力を使って、今度は以下の内容の1つのドキュメントで構成されるコントラクトを使って検証する。

document 1:
baz

1.ハッシュを計算する。

baa5a0964d3320fbc0c6a922140453c8513ea24ab8fd0577034804a967248096

2.要素は1つだけだが、2回めのハッシュ計算をする。

3a08605829413ce0bf551b08d21e4a28dbda6e407f90eff1c448e839050c73a1

3.部分導出パスを計算する。

14856/24664/10561/15584/48981/6920/53790/18984/56282/28224/32656/61425/50248/59449/1292/29601

4.contract_hash導出パスの前にcontract_basepubを付与する。

contract_base_pub/14856/24664/10561/15584/48981/6920/53790/18984/56282/28224/32656/61425/50248/59449/1292/29601
or
m/175'/0'/14856/24664/10561/15584/48981/6920/53790/18984/56282/28224/32656/61425/50248/59449/1292/29601

5.拡張公開鍵を計算する。

xpub6gujKWRhegHXKZBkrprW55oSL6UxYhStxF5FtoUNa4KShLxLPDLQTS39XAwRhdCSvuAv2wogwukmfk3fS7CM6pT6QWwJHiCTw7RkwXMgThy

6.拡張公開鍵からアドレス(P2PKH)を計算する。

162KDdRXa3KPgYkH3d1DDKfddacH1gn1n8

7.予想通り生成したアドレスは、前に計算した値162KDdRXa3KPgYkH3d1DDKfddacH1gn1n8とは異なる。

検証は、コントラクトアドレス生成の際に使用したドキュメントと同じドキュメントを使用した場合のみ成功する。

互換性

この仕様はBIP-32の仕様と後方互換性はなく、このBIPの導出スキームはBIP-32に準拠している。支払人と受取人の間の通信は、コントラクトのハッシュ化やパスの生成と同様、ウォレットを大きく変更する必要がある。

参照実装

所感

  • Pay-to-contractの何をBIPで定義するのかと思ったけど、BIP-32の鍵導出の仕組みと組み合わせて決定論的に導出する仕様を定義してるのか。
  • ホワイトペーパーでは単純にコントラクトのハッシュをベースとなる鍵に直接加算して支払先のアドレスを生成してるのに対して、このBIPではコントラクトのハッシュを分割してBIP-32のパスの一部を生成し、そこからBIP-32で鍵導出してる。