Contact

【CTO Tech Blog】Bitcoinの支払いURIスキームをアップデートするBIP-321

  • CTO Tech blog

Bitcoinで支払先の情報を記述するURIスキームとしては、古くからBIP-21が使用されてきた↓

techmedia-think.hatenablog.com

ただ、BIP-21はアドレス仕様として正式にサポートしているのがBase58checkエンコーディング(P2PKH、P2SH)のみであったり*1、新しい支払い方法に対するクエリパラメーターを標準化する要望も出てきたため、以下をサポートする形でBIP-21を改変したものがBIP-321。

  • アドレスのエンコーディングにbech32bech32mをサポート
  • BOLT11インボイス、BOLT12オファー、サイレントペイメント、プライベートペイメント用のクエリパラメーターを定義
  • 支払いの証明(Proof of Payment)を提供するオプション機能のサポート

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

BIP-321

BIP-321 URIをABNF記法で定義すると↓*2

bitcoinurn     = "bitcoin:" [ bitcoinaddress ] [ "?" bitcoinparams ]
bitcoinaddress = *base58 / *bech32 / *bech32m
bitcoinparams  = bitcoinparam [ "&" bitcoinparams ]
bitcoinparam   = [ amountparam / labelparam / messageparam / responseparam / otherparam / reqparam ]
amountparam    = "amount=" *digit [ "." *digit ]
labelparam     = "label=" *qchar
messageparam   = "message=" *qchar
responseparam  = [ "req-" ] "pop=" *qchar
otherparam     = qchar *qchar [ "=" *qchar ]
reqparam       = "req-" qchar *qchar [ "=" *qchar ]

BIP-21との定義上の違いは、

  • bitcoinaddressで新たにbech32bech32mをサポート
  • responseparamの追加(支払い証明に使用)

の2点。

クエリパラメーターの値とBitcoinアドレスフィールドは場合によって大文字/小文字が区別される可能性があるけど、他の部分は基本的に大文字/小文字を区別しない。

クエリキー

以下のクエリパラメーターのキーは、支払手段に関係なく任意のURIに適用可能なキーとして定義されている(最後のpopは今回新たに定義)。

  • label:受信者のラベル
  • message:トランザクションの説明をするメッセージ
  • pop:支払いを開始したアプリに支払いが完了したことの証明を提供するためにウォレットが返すURI

支払金額のキーamountに対応する値は、BIP-21と同様BTC建ての金額を設定(後方互換的に単位は変えなかったのかな?)。

これらのパラメーターは基本的にURI内に1つだけ設定可能。

また、支払い方法によって以下のキーが定義されている:

  • lightning:BOLT11インボイス
  • lno:BOLT12オファー
  • payBIP-351のプライベートペイメントアドレス
  • spBIP-352のサイレントペイメントアドレス

これらのパラメーターは、URI内に複数設定することが可能。

アドレス部分は空にすることもできるし、アドレスと両方指定してBOLT11インボイスで支払いができない場合のフォールバック手段としてオンチェーンアドレスでの支払いも許可するといった使い方も可能。また、たとえばBOLT12オファーとサイレントペイメントアドレスを両方指定してどちらかで支払うようにリクエストするといったことも可能。

また、BIP-21と同様req-プレフィックスがつくパラメーターは必須パラメーター。もしウォレットがそのパラメーターを解釈できない場合は無効なURIとして処理する必要がある。

URIの再利用

基本的にアドレスの再利用は避けるべきで、BIP-21でもURIの再利用は避けるべきとしている。BIP-321も同様だけど、アドレスを再利用しない再利用可能なURIについては再利用を認めるとしている。つまり、サイレントペイメントやBOLT12オファーを指定するURIについては、アドレスの再利用が行われないので、そのURIについては再利用してもいいと。

支払いの証明

支払いの証明(Proof of Payment)は実際に支払いが行われたことを証明するデータで、

  • オンチェーン支払いであれば、支払いを行ったトランザクションデータ
  • LN支払いであれば、ペイメントプリイメージ

で、それぞれ16進エンコードされる。上記以外の支払いスキームの場合は、独自のフォーマットを定義することになる。

BIP-321 URIでは、popパラメーターを含めることで、支払い完了後に支払いの証明を提供するためのURIを構築する機能をオプションで定義している。

popパラメーターで設定するのは任意のURIプレフィックスで、支払い完了後に支払いの証明データと共にURIを構築する。

たとえば、以下のURIの場合

bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?pop=initiatingapp%3a

popパラメーターをURLデコードすると、initiatingapp:となるので、構築するURIは、

 initiatingapp:onchain=HEXエンコードしたトランザクション

となる。上記のように支払先がURIの本体で指定されている場合は、キーonchainを指定する。

以下のURIでライトニング支払いした場合は、

bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?lightning=lnbc420bogusinvoice&pop=app%3a%3f

構築するURIは、

 app:?lightning=HEXエンコードしたペイメントプリイメージ

となる。

上記のURIを実行することで支払いの証明を提供できる。

ただ、支払人のIPなどの情報が受信者に公開されるのを防ぐため、httphttpsfilejavascriptmailtoおよびWebブラウザで開けるスキームでないことを検証する必要がある。ウォレットが開けないスキームでかつ、popが必須パラメーターになっている場合(つまり、req-popになってる)、支払い自体を行ってはならない。

といったように、最近の支払い方法に合わせてURIの仕様を更新したのがBIP-321。

*1:慣行としてほとんどのウォレットでは他のSegwitアドレスも利用可能にしている

*2:qcharはRFC 3986 URIクエリコンポーネントの有効な文字に対応

ブログ元記事へのリンク

ブログの元記事はこちらから

https://techmedia-think.hatenablog.com/entry/2025/05/07/181410

Chaintopeでブロックチェーンの未来を共に創りませんか?

Chaintopeは、独自のブロックチェーン「Tapyrus」と、開発プラットフォーム「Tapyrus Platform」を活用し、デジタル社会の信頼基盤を構築しています。
私たちは、ブロックチェーン技術の可能性を最大限に引き出し、社会に新しい価値を提供することを目指しています。

募集職種:

ブロックチェーンエンジニア
アプリケーションエンジニア
インフラ・保守エンジニア
プロジェクトマネージャー
フィールドセールス

Chaintopeで働く魅力:

最先端のブロックチェーン技術に触れる機会
リモートワークやフレックスタイム制による柔軟な働き方
専門性の高いチームとの協働
ブロックチェーン技術に情熱を持つあなたのスキルを、私たちのチームで活かしませんか?
詳細は、採用情報をご覧ください。

https://www.chaintope.com/recruit/

 

話題のキーワード