BIP-0352 Silent Payments
概要
サイレントペイメントは、受信者が再利用可能な(オフチェーン)アドレスを支出者に提供したにもかかわらず、支払いのたびに一意のオンチェーンアドレスに対して行うことができるタイプの支払いである。
従来、支払いを受けるユーザーは、支払いのたびに新しいビットコインアドレスを生成する必要があった。 同じアドレスに複数の支払いを受けると、たとえその出力が後に別々の取引で使われたとしても、同じユーザーがそれらの支払いを受けたことが明らかになるからだ。 これはアドレスの再利用として知られている。
新しいアドレスを使用するには、送信者と受信者の間で安全なやりとりを行い、受信者が毎回新しいアドレスを提供できるようにする必要がある場合が多い。
サイレントペイメントでは、受信者は1つのサイレントペイメントアドレスを生成して公開できるため、やり取りが不要になる。 送信者は、選択した1つまたは複数の入力を選択し、その秘密鍵をサイレントペイメントアドレスの公開鍵と一緒に使用して、宛先を生成するために使用される共有秘密を導出する。
受取人は、ブロックチェーン上のトランザクションをスキャンし、トランザクションの入力公開鍵の合計と自分のアドレスからのスキャン鍵でECDH計算を実行することで、支払いを検出する。 主な欠点は、BIP32 スタイルのウォレットのように scriptPubKey の UTXO セットを単純にスキャンするよりも計算コストがかかることである。 さらに、コインジョイニングのような共同作業でサイレントペイメントを使用することは、今後の課題である。
---------------------------------------------------------------------------------------------------------------------
はじめに
本文書は、支払いのオンチェーンリンク可能性やオンチェーン通知を必要としない、ビットコインにおける静的支払いアドレスのためのプロトコルを規定する。 著作権 本BIPはBSD 2-clauseライセンスの下でライセンスされる。
動機
各ビットコイン取引に新しいアドレスを使用することは、プライバシーを維持する上で極めて重要である。 そのためには、送信者と受信者の間で安全なやりとりを行い、受信者が新しいアドレス、新しいアドレスのバッチ、またはxpubのような送信者がオンデマンドでアドレスを生成する方法が必要になることが多い。
しかし、やりとりは多くの場合実行不可能であり、望ましくない。 これを解決するために、静的な支払いアドレスとブロックチェーン経由で送信される通知を使用する様々なプロトコルが提案されている。 これらのプロトコルは相互作用の必要性を排除するが、1回限りの支払いのためのコスト増とブロックチェーンにおける顕著な足跡を犠牲にし、送信者と受信者に関するメタデータを明らかにする可能性がある。 また、通知スキームでは、受信者は同じ送信者からのすべての支払いをリンクすることができ、送信者のプライバシーが損なわれる。
この提案は、対話の必要性をなくし、通知の必要性をなくし、送信者と受信者の両方のプライバシーを保護するソリューションを提示することによって、これらの現在のアプローチの限界に対処することを目指している。 これらの利点は、支払いを検出するためにウォレットがブロックチェーンをスキャンする必要があるという代償を伴う。 この追加要件はフルノードでは一般的に実現可能ですが、ライトクライアントでは課題となります。 今日、帯域幅の増加という代償を払ってプライバシーを保護するライトクライアントを実装することは可能であるが、ライトクライアントのサポートは未解決の研究分野であると考えられている(付録A:ライトクライアントのサポート参照)。 設計では、CoinJoinsのような協調トランザクションやMuSigおよびFROST鍵による入力を念頭に置いているが、プロトコルが協調設定において安全であるという正式な証明がないため、トランザクションのすべての入力の鍵は同じエンティティに属することが推奨される。
目標
以下の特性を満たすプロトコルの提示を目指す:
トランザクションのサイズやコストを増加させない
結果、トランザクションは他のビットコイン・トランザクションに紛れ込み、区別できない
トランザクションは外部のオブザーバーによってサイレント・ペイメント・アドレスにリンクされない
送信者と受信者の相互作用が不要
複数の支払いを同じ送信者にリンクさせない
各サイレント・ペイメントは一意のアドレスに送られる、 偶発的なアドレスの再利用を回避
支払いのラベリングをサポート
バックアップとリカバリのために既存のシードフレーズまたは記述子メソッドを使用
スキャンと支出の責任を分離
CoinJoinライトクライアント/SPVウォレットのサポートなど、他の支出プロトコルとの互換性 プロトコルはアップグレード可能
概要
最初にプロトコルの概略を述べる。
以下では、大文字は公開鍵、小文字は秘密鍵、|| はバイト連結、·は楕円曲線スカラー倍算、Gはsecp256k1の生成点、nはsecp256k1の曲線次数を表す。
概要の各セクションはそれ自体では不完全であり、プロトコルの各側面を紹介し簡潔に説明するために、前のセクションの上に構築することを意図している。 プロトコルの完全な仕様については、仕様を参照のこと。
簡単なケース
Bobは公開鍵Bをサイレントペイメントアドレスとして公開する。 AliceはBobのサイレント・ペイメント・アドレスを発見し、秘密鍵a、公開鍵Aを持つUTXOを選択し、以下の方法でBobの宛先出力Pを作成する:
Let P = B + hash(a·B)·G
Encode P as a BIP341 taproot output
a·B == b·A (Elliptic-curve Diffie-Hellman)であるため、Bobは自分の秘密鍵bを用いて、少なくとも1つの未使用のタップルート出力を持つ各トランザクションの入力公開鍵を収集し、Pが見つかるまでECDH計算を実行する (すなわち、P = B + hash(b-A)·Gを計算し、Pがトランザクション出力に存在することを確認する)。
複数の出力の作成
アリスがボブのために複数の出力を作成できるように、以下の方法で整数を含めます:
Let k = 0
Let P0 = B + hash(a·B || k)·G
For additional outputs:
Increment k by one (k++)
Let Pi = B + hash(a·B || k)·G
ボブは、P0 = B + hash(b·A || 0)·Gを検索することで、前と同じようにこの出力を検出する:
Check for P1 = B + hash(b·A || 1)·G
If P1 is not found, stop
If P1 is found, continue to check for P2 and so on until an additional output is not found
Bobは、少なくとも1つの出力が自分に支払われるトランザクションが見つかった後にのみ、これらの後続チェックを行うので、全体的なスキャン要件の増加は無視できる。 また、これらの出力が取引に現れる順番は結果に影響しないことに注意すべきである。
アドレスの再利用を防ぐ
もしAliceが、同じ公開鍵Aから別のUTXOをBobへのその後の支払いに使おうと すると、結局同じ宛先Piを導き出すことになる。 これを防ぐために、Aliceは以下の方法で入力ハッシュを含めるべきである:
Let input_hash = hash(outpoint || A)
Let P0 = B + hash(input_hash·a·B || 0)·G
ボブはスキャン時に同じinput_hashを計算しなければならない。
すべての入力を使用する
単純化した例では、アリスのトランザクションには入力 A が 1 つしかないとしたが、実際にはビットコインのトランザクショ ンには多くの入力があり得る。 アリスに特定の入力を選択させ、ボブに各入力を個別にチェックさせる代わりに、アリスに入力公開鍵の合計で微調整を実行させることができる。 これにより、Bobのスキャン要件が大幅に削減され、ライトクライアントのサポートがより実現可能になり、CoinJoinのような協調的トランザクションプロトコルにおいてAliceのプライバシーが保護される。 Aliceは以下の方法で、入力された秘密鍵の合計でTweakを実行する:
Let a = a1 + a2 + ... + an
Let input_hash = hash(outpointL || (a·G)), where outpointL is the smallest outpoint lexicographically
Let P0 = B + hash(input_hash·a·B || 0)·G
Spend and Scan Key
Bobは入金を確認するために秘密鍵bを必要とするため、bをオンラインデバイスに公開する必要がある。 リスクを最小限に抑えるため、Bobは代わりに(Bscan, Bspend)という形式のアドレスを公開することができる。 これにより、Bobはbspendをオフラインのコールドストレージに保持し、公開鍵Bspendと秘密鍵bscanでスキャンを実行することができる。 AliceはBobの公開鍵の両方を使用して、以下の手順でTweakを実行する:
Let P0 = Bspend + hash(input_hash·a·Bscan || 0)·G
Bobはオンライン・デバイスでP0 = Bspend + hash(input_hash·bscan·A || 0)·G を計算することでこの支払いを検知し、秘密鍵として(bspend + hash(input_hash·bscan·A || 0)) mod nを使用してコールドストレージ署名デバイスから支出することができる。
ラベル
(Bscan, Bspend)形式の単一のサイレントペイメントアドレスに対して、Bobは着信ペイメントを区別したい場合がある。 単純に考えれば、Bobは複数のサイレントペイメントアドレスを公開することもできるが、その場合、それぞれのサイレントペイメントアドレスをスキャンする必要があり、法外なコストがかかる。 その代わりに、Bobは自分のspend公開鍵Bspendに以下のように整数mのラベルを付けることができる:
Let Bm = Bspend + hash(bscan || m)·G where m is an incrementable integer starting from 1
Publish (Bscan, B1), (Bscan, B2) etc.
Aliceは、公開されている(Bscan, Bm)のペアの1つを使用して、前と同じようにTweakを実行する。 Bobは以下の方法でラベル付き支払いを検出する:
Let P0 = Bspend + hash(input_hash·bscan·A || 0)·G
Subtract P0 from each of the transaction outputs and check if the remainder matches any of the labels (hash(bscan || 1)·G, hash(bscan || 2)·G etc.) that the wallet has previously used
外部のオブザーバーは、各公開アドレスがBscanを共通に持つことから、各公開 (Bscan, Bm)ペアが同じエンティティによって所有されていることを容易に推測で きることに注意することが重要である。 そのため、ラベルはボブが別個のIDを管理するためのものではなく、ボブが着信の支払い元を判断するためのものである。
変更のためのラベル
ボブは自分の変更出力を管理するためにラベルを使うこともできる。 この使用例では、m = 0を予約する。 これにより、BobはBIP32を使用して小銭を管理する代わりに、マスターキーからウォレットを復元する際に、自分の未使用の出力のどれが小銭であったかを知ることができる。 ラベルの使用は任意であるが、すべてのサイレントペイメントを受け取るウォレットは、最大限の相互互換性を確保するために、バックアップからリカバリする際に、少なくともchangeラベルをスキャンすべきである。