Mastering Bitcoinの2章でカフェのレジでBitcoinを使った支払いをする際に生成されていたQRコードがBIP-21の仕様で作られているみたいなので、BIP-21の内容を見てみる。
bips/bip-0021.mediawiki at master · bitcoin/bips · GitHub
BIP-21は、Webサイト上のリンクやQRコードを使って簡単にBitcoinの支払いをするためのURIスキームを定義したBIPになる。
仕様
支払いをハンドリングする際の重要なルール
Bitcoin Clientはユーザの許可なくURIの内容に基づいて勝手に支払いを行ってはいけない。
Clientは支払い毎にユーザに支払いの承認を求めるべきである。
OSとの連携
GUIクライアントはデフォルトで自分自身を"bitcoin:" URIスキームのハンドラとして登録すべきで、もし既に別のハンドラが登録されている場合は、ハンドラを変更するようユーザに提案する。
共通フォーマット
Bitcoin URIもRFC 3986で定義された一般的なURIスキームの形式に従う。RFC 3986のpathコンポーネントの部分がBitcoinアドレスで構成され、queryコンポーネントで追加の支払オプションを提供する。
queryコンポーネントの要素は最初にUTF-8でエンコードし、さらにURLエンコードする必要がある。
ABNF(Augmented バッカス・ナウア記法)文法
ABNFで定義したこのBIPのURIスキームが↓
bitcoinurn = "bitcoin:" bitcoinaddress [ "?" bitcoinparams ] bitcoinaddress = *base58 bitcoinparams = bitcoinparam [ "&" bitcoinparams ] bitcoinparam = [ amountparam / labelparam / messageparam / otherparam / reqparam ] amountparam = "amount=" *digit [ "." *digit ] labelparam = "label=" *qchar messageparam = "message=" *qchar otherparam = qchar *qchar [ "=" *qchar ] reqparam = "req-" qchar *qchar [ "=" *qchar ]
↑の"qchar"は、RFC 3986のURI quesryコンポーネントの有効な文字列が利用可能。ただ"="と"&" については、このBIPでセパレータとして使うので利用不可。
スキームコンポーネント("bitcoin:")は、大文字・小文字を区別せず、大文字・小文字が混在していても受け付ける必要がある。スキームコンポーネント以外の残りのURIの部分は、queryパラメータのキー含めて大文字・小文字を区別する。
Queryキー
- label
支払いを受け取るアドレスのラベル - address
支払いを受け取るBitcoinアドレス - message
支払いを行うユーザへの取引に関する説明 - amount
Bitcoinの量(オリジナルのBIP上はキーはsizeと記載されているけどamoutが正と思われる) - (others)
将来の拡張のためのオプション
送付するBitcoinの量
Queryにamountが含まれている場合、そこで指定するBitcoinの量の単位はBTCで指定する。その際カンマは使えず、小数点を表すピリオド(.)は使える。例えば50BTCを送る際は、 amount=50.00や amount=50と記載できるが、amount=50,000.00というのは無効。
Bitcoinクライアントは任意のフォーマットでamountをユーザに表示しても良いが、ユーザが馴染みのあるフォーマットを選択すべき。例えば大半のユーザがBTC単位で動作しているのであればBTCで表示すべきだし、mBTCやTBCが適切な場合もあるかもしれない。
論理的根拠
支払いの識別と個人の識別
現在のベストプラクティスは、各取引ごとに個別のアドレスを使用するべきである。そのためURIスキームはワンタイムの支払いをするだけで、個人情報の交換を意味してはならない。
Accessibility
外部からこのようなURIにアクセスされた際、クイックサーチにより支払いをするのに必要なリソースを案内する必要がある。
上位互換
プレフィックスとして”req-”が付いている変数は支払い処理になんらか必要な変数で、クライアントがそのプレフィックスが付いた変数を実装していない場合は、そのURI全て無効と判断する必要がある。他の変数で実装されていないものがあっても、プレフィックスとして"req-"が付いていない変数であればそのURIは有効で、その変数だけ無視することができる。
後方互換
既にいくつかのクライアントはこのBIPに記載された内容に類似したbitcoin:URIスキームを実装しているが、追加の"req-"プレフィックス要件は含まれていない。従って、このBIPの確定から6ヶ月間は"req-"プレフィックスを付加した追加の変数を使わないことを推奨する。
付録
簡単な構文
このセキュションの内容は参考レベルで全ての構文をサポートしていない。規範文法については、上記BNFを参照。
bitcoin:<address>[?amount=<amount>][?label=<label>][?message=<message>]
サンプル
アドレスのみであれば↓
bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W
アドレスとラベルの場合↓
bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Luke-Jr
"Luke-Jr"への20.30 BTCの支払いだと↓
bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=20.3&label=Luke-Jr
50 BTCとメッセージを付加するケースだと↓
bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=50&label=Luke-Jr&message=Donation%20for%20project%20xyz
将来のバージョンで有効で現在はサポートしてなく無効なケース↓
bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-somethingyoudontunderstand=50&req-somethingelseyoudontget=999
将来のバージョンで有効で現在はサポートしてなく有効なケース↓
bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?somethingyoudontunderstand=50&somethingelseyoudontget=999
最後の2つの有効・無効の違いは”req-”プレフィックスの有無。
このBIPが出来て結構経ってるので、既に”req-”プレフィックスは一般的にサポートされている?
参照実装
Bitcoin Client
- Bitcoin-QtはWindowsとKDE版で、”req-”プレフィックスの無い旧バージョンのBitcoin URIをサポートしている。(70f55355e29c8e45b607e782c5d76609d23cc858 のコミットから)
ライブラリ
- JavaScript - https://github.com/bitcoinjs/bip21
- Java - https://github.com/SandroMachado/BitcoinPaymentURI
- Swift - https://github.com/SandroMachado/BitcoinPaymentURISwift
実際に作ってみた
自分のアドレス使って実際に支払い用のQRコードを作ってみた。
対応しているクライアントでQRコードを読み込むと↓のようにあとは送金ボタン押すだけの状態になる。
(↓のアプリはMycelium)