用語集 / 開発者向けリファレンス
PaymentDetails
- PaymentDetailsとは?
- PaymentDetailsは、実際に支払いの内容を記述していたBIP70の内部メッセージで、どの出力に支払うか、いくら支払うか、リクエストがいつ失効するか、署名済みのトランザクションをどこへ送るかを定めていました。
BIP-70で規定されています。
PaymentDetailsは加盟店が実際に署名した部分であり、外側の封筒はそれを証明する証明書を運んでいるだけでした。このメッセージには7つのフィールドがありました。既定値がmainのネットワーク名、出力のリスト、必須のタイムスタンプ、任意の有効期限、メモ、コールバックURL、そして内容を解釈しないmerchant_dataのバイト列です。現在ではBIP21のURIと決済ページが、署名もサーバーもなしで同じ役割を果たしています。
仕組み
状態:歴史的な仕様です。Bitcoin Coreは2020年6月3日にバージョン0.20.0でBIP70を削除し、PaymentDetailsに稼働中の実装はありません。当サイトでこれを解説しているのは、フィールド名が古い統合ガイドやbitcoin.orgの開発者リファレンスに今も登場するためです。
構造を運んだのはJSONではなくProtocol Buffersでした。この選択が重要だったのには、少し立ち止まって考える価値のある理由があります。加盟店はPaymentDetailsをバイト列にシリアライズし、その正確なバイト列を、入れ子のメッセージとしてではなく不透明なフィールドとして外側のPaymentRequestの中に置きました。署名はそのバイト列を対象としたため、同じフィールドを別の順序で再エンコードするライブラリが、有効な署名を無効にしてしまうことはありませんでした。
7つのフィールドは、指示と記録に分かれていました。
network、既定値が"main"の文字列で、定義されている他の値は"test"だけでした。outputs、繰り返しのリストで、各項目はサトシ単位の金額とスクリプトを組にしています。出力を複数持つことも許されており、加盟店はこれを利用して、顧客に2回送金を求めずに、1回の顧客の支払いをホットウォレットとコールドストレージに分けていました。time、リクエストが作成された時刻を記録する必須のUnixタイムスタンプです。expires、この時刻を過ぎたらウォレットはリクエストを拒否することになっていた、任意のUnixタイムスタンプです。このフィールドのおかげでBIP70はカード端末のように感じられました。加盟店が法定通貨での価格を示し、一定の期間その価格を保証できたからです。memo、支払者に表示されるUTF-8のメモです。payment_url、ウォレットがブロードキャスト後にPaymentメッセージを送信した先です。merchant_data、加盟店が支払いをショッピングカートと照合できるよう、そのままの形で返される不透明なバイト列です。
必須だったのはtimeと出力のスクリプトだけでした。それ以外は加盟店が省略でき、ほとんどの加盟店は省略していました。
どこで見られるか
PaymentDetailsの背後にある考え方はメッセージより長く生き残っており、そこが注目すべき点です。
価格の有効期限は現在、ウォレットではなく取引所で扱われます。即時購入の画面から購入すると、表示価格の横にカウントダウンが付きます。カウントダウンが終われば、価格は新しいレートで作り直されます。これはexpiresをWebアプリで再実装したものであり、まったく同じ形で売り手をボラティリティから守ります。取引所の板での注文の突き合わせは、固定価格を一切提示しないという別の方法で同じ役割を果たします。
メッセージ全体に相当する加盟店側の仕組みは、決済ソフトウェアの請求記録です。BTCPay ServerなどのツールはBIP21のURIを生成し、設定した分数の間それを有効に保ち、入ってきたトランザクションを内部の注文識別子と照合します。これはまさにmerchant_dataが担っていたことです。
PaymentDetails vs領収書
PaymentDetailsはリクエストであり、BIP70における領収書は、加盟店が後から返したPaymentACKでした。一方は何が起こるべきかを記述し、もう一方は加盟店がそれが起きたことを見たと確認しました。どちらもブロックチェーンの事実ではなく、人々が過小評価していた制約はそこにあります。加盟店からの署名済みの確認応答が証明するのは、加盟店のサーバーが何かを述べたということであり、トランザクションが確認されたということではありません。ビットコインの支払いを決済するのは、領収書ではなく確認です。