Develop with pleasure!

福岡でCloudとかBlockchainとか。

送信者−受信者間で簡単なコインジョインを行うBustapayプロトコルを定義したBIP-79

Bitcoinトランザクションはインプットに送信者のUTXOが、アウトプットに受信者のアドレスと送信者のお釣りがセットされる構成が一般的。ブロックチェーンの分析をする企業でよく採られるアプローチでは、こういうトランザクションの場合、インプットのUTXOは全て同じユーザーのものであるという仮定に基づいていて、その仮定の元、ブロックチェーン上のトランザクショングラフを解析し、ユーザーや企業の動向を分析しようとしている。

今回新しく提案されたBustapayプロトコルは、コインジョインといっても大量のインプット/アウトプットを集めてコインを撹拌しようという目的ではなく、トランザクションのインプットは全て同じユーザーのものという上記ブロックチェーンの分析の仮定を崩すための送信者−受信者間の簡単なコインジョインプロトコルを定義したもの↓

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

同様の目的で以前BlockstreamがPay to EndPoint(P2EP)というプロトコルを提案していた↓

techmedia-think.hatenablog.com

ただBlockstreamのP2EPの場合、受信者が所有するUTXOの情報に関するプライバシーを守るため、フルノードにアクセスしてダミーのUTXOををセットしたダミートランザクションを多数用意し、送信者との間で署名のやりとりをするなど、単一の決済プロトコルとしては重かった部分をBustapayでは削ぎ落としてシンプルになっている↓

Abstract

Bitcoinトランザクションを普通に作成すると、望ましくない情報が漏れることが多い。結果として、効果的なブロックチェーン分析技術により、有用な通貨に期待される重要な特性が危険にさらされる。

Bustapayは、支払いの送信者と受信者が、両者の直接的な利益を守るためいくつかの分析の仮定を破壊する方法で、両者がBitcoinトランザクションに協力して署名するための簡単で実用的なプロトコルだ。さらに、Bitcoin決済をする事業者にとって一定の問題であるUTXOセットのサイズを管理するのを手助けするため、受信者に重要な量の制御を与える方法を取る。

動機

最も強力なブロックチェーン分析のヒューリスティクスの1つは、トランザクションのインプットの全てが、(伝統的なコインジョイン独自の構造やマルチシグの使用など)別で知られている場合を除いて、単一のユーザーによって制御されているという仮定だ。他の手法(特にお釣り用のアウトプットの推測)と組み合わせることで、予想以上に正確な追跡が行われ、Bitcoinの参加者は容認できない個人的に、ビジネス上および財務上のリスクにされされ、Bitcoinの利便性と代替性を損ない、最終的に有用な通貨として機能する能力を損なうことになる。

しかし我々は、送信者と受信者のコインジョインでこれらの仮定を壊すことができる。コストのかからないスパイ/DoS攻撃を防ぐため、プロセスを開始する際に送信者に完全に有効な伝播準備のできたトランザクションの提供を求め、送信者がコインジョインを完了しない場合に受信者がそのトランザクションをブロードキャストできるようになっている。最も有望なことに、Bustapayのトランザクションは識別可能な構造を持たないため、任意のネットワーク分析は与えられたトランザクションがBustapayのトランザクションかどうか分からないため、分析のモデル全体の信頼性が損なわれ、Bitcoinのエコシステム全体に肯定的な外部性がもたらされる。

Bustapayのトランザクションは、受信者のUTXOの数を増やすことなく、実際に受信者に自分のUTXOセットを良いように管理する機会を与え、それは通常の支払い時の取引でのみ行われる。大規模なUTXOセットは、よく問題になり高価で、頻繁にプライバシーを破壊する統合を必要とする。Bustapayは、クラスタ化の仮定を破壊する以外に、送信量の難読化レイヤーも提供する。

この仕様では、導入を促進するにあたってシンプルさが1番重要であるとの前提で、複雑さと潜在的に有用な拡張を避けてきたことが注目に値する。

概要

Bustapayの支払いは送信者から受信者に対して行われる。

手順1:送信者は受信者に支払うBitcoinトランザクションを作成する

このトランザクションは全てのインプットに対してsegwitを使用し、完全に有効で署名済みである必要がある。トランザクションはネットワークに伝播できる状態であること(ただしこの段階ではブロードキャストされない)。

手順2:送信者は受信者にテンプレートトランザクションを送る

これはbustapay urlに対して、HTTPのPOSTリクエストで行われる。

手順3:受信者はトランザクションを処理し、部分的に署名されたコインジョインを返す

受信者はトランザクションを検証し、自身に支払うようにする。受信者は1つ以上のインプットを追加し(contributed inputs)、(オプションで)受信者自身に支払うアウトプットを増額する(一般的にcontributed inputsの合計分増額する)。こうして受信者が送信者に返す、部分的なトランザクションが作成される。これは送信者に自身のインプットに再署名してもらう際などに呼ばれる。

手順4:受信者は検証、再署名、Bitcoinネットワークへの伝播をする

受信者は部分的なトランザクションが正しくかつ悪意なく変更されていることを検証し(潜在的に信頼できない通信シャネルも使用できるため)、元の自分のインプットに最署名し最終的なトランザクションBitcoinネットワークにブロードキャストする。

手順5:受信者はBitcoinネットワーク上で最終トランザクションを確認する

受信者がネットワーク上で最終トランザクションを確認し(そして十分な承認数あるか)、送信された金額は通常の支払いのように見える(ネットワーク上で確認する金額と実際の送金額は異なるが)。タイムアウト後に受信者が最終トランザクションを確認できない場合は、支払いが確実に行われるように元のテンプレートトランザクションをブロードキャストし、強力なアンチDoSの仕組みを機能させる。

仕様

送信者にBustapayトランザクション送信先を知らせる標準的な方法は、BIP-21エンコードされたアドレスを使用する方法だ。この時パラメータとしてキー:bpu(BustaPayUrlの短縮表記)を使用する。アドレスの例は以下のようになる。

bitcoin:2NABbUr9yeRCp1oUCtVmgJF8HGRCo3ifpTT?bpu=https://bp.bustabit.com/submit

URLは短くしておくことを強く推奨する。

送信者がテンプレートトランザクションを作成するにあたっては、segwitインプットだけが使用できるという点を除いて、通常の送金トランザクションを作成するのと変わらない。送信者はBIP125(オプトインのFullRBFのシグナリング)と同様、通常よりやや積極的な手数料レートの使用を勧められるが、どちらも厳密には要求されない。

テンプレートトランザクションは、Bustapay URLにHTTP POSTでバイナリエンコードされたBODYとして受信者に送信する必要がある。

受信者はテンプレートトランザクションの検証で応答する。トランザクションに問題がある場合、もしくはトランザクションに不満がある場合(手数料が低すぎるなど)、HTTPレスポンスコード422を使って、拒否理由をユーザーに伝えるため人が読める形式の文字列と一緒にレスポンスを返す。

受信者がトランザクションを拒否した場合、それをネットワーク上に伝播してはならない。しかし、送信者は(どのエラーが出たかに関わらず)受信者がいつでもテンプレートトランザクションをブロードキャストできることを認識することが重要だ。クライアントはそのため受信者の意思に応じて行動する必要がある(再調整するか、トランザクションを伝播だけするか)。

Contributed Inputの選択

受信者はすくなくとも1つのインプット(=contributed input)をトランザクションに追加しなければならない。受信者のインプットがない場合、500 Internal Server Errorを使用する必要があり、クライアントは通常通りトランザクションを送信できる(もしくは後でやり直す)。一般的には、1つのcontributed inputのみを追加することを推奨するが、複数のインプットを追加するのが便利なケースもある。

受信者のUTXOセットを列挙させるために同じトランザクションのバリエーションを継続的に送信される攻撃を防ぐために、トランザクションに同じインプットがあった場合は、常に同じcontributed inputを返すのが重要だ。

可能であれば、できるだけ多くの他のトランザクションインプットと同じタイプのcontributed inputを選択する努力を受信者がすることが強く望まれる。

アウトプットの調整

トランザクションにインプットを加えた後、受信者はcontributed inputの合計量分、自身宛のアウトプットの合計(手数料を追加したい場合はその分を差し引いて)を追加するよう調整したい。しかし唯一の厳しい要件が、受信者は決してインプットを追加or削除してはならず、アウトプットの量を減らしてはならないという点だ。

部分的なトランザクションの返却

受信者は部分的なトランザクションの全てのcontributed inputに署名する必要がある。部分的なトランザクションはこの時点で有効なトランザクションではなく、送信者により再署名される必要があるため、元のテンプレートトランザクションから全てのwitnessを削除する。受信者は部分的なトランザクションをバイナリエンコードしたHTTPレスポンスとしてレスポンスコード200で返す。

送信者の検証

送信者は部分的なトランザクションについて重要な検証をしなければならない。送信者は以下を検証しなければならない。

最終トランザクションの作成

部分的なトランザクションの検証後、送信者は全てのトランザクションに署名し、最終トランザクションを作成する。送信者は受信者が送信者の別のインプットに署名するよう騙そうとしていないか慎重に注意することが重要だ。送信者はテンプレートトランザクションに存在するインプットにのみ署名する必要がある。送信者が慎重でない場合、受信者は送信者が実際に所有しているUTXOをcontribute inputに入れ、送信者が盲目的に全てに署名するという希望を持っているケースが考えられる。

トランザクションの公開

最終トランザクションが作成されると、送信者はそれを直接Bitcoinネットワークに送信する必要がある。送信者が妥当な時間内(例えば1分間)にトランザクションを送信しない場合、受信者は重要なアンチスパイ/アンチDoS戦略としてテンプレートトランザクションを公開すべきである。送信者はまた、受信者が不当にトランザクションの手数料を下げた(例:トランザクションサイズは増えたけど、手数料が十分でない)と判断した場合、最終トランザクションでなくテンプレートトランザクションを公開することもできる。最終トランザクションをネットワークに公開した後でも、最終トランザクションが承認されずテンプレートトランザクションの方が手数料が高い場合、(RBFのアドバンテージを取り)テンプレートトランザクションの公開を検討することができる。

実装の注意点

Bustapayの支払いを実装したいと思っている人のために、ここに受信者のためのいくつかの注意がある:

  • トランザクションがmempoolに適しているかどうかは、bitcoin core 0.17+でtestmempoolacceptを使うことで簡単にチェックできる。
  • TXIDによりトランザクションの追跡は不確か。正気を保つために全てのインプットが確実にsegwitであること。しかしトランザクションを検証しない限り、segwitはTXIDのmalleabilityを防げない。そのため、少なくともtestmempoolacceptを使っていることを確認すること。
  • Bustapayはあなたが入金アドレスを持っているかどうかを照会するのに悪意あるユーザーによって悪用される可能性がある。既に使用済みの入金アドレス宛に支払うBustapayトランザクションを受け入れないこと。
  • どのUTXOのユーザー、あなたのどのUTXOを明らかにしたのかマッピングを保持する必要がある。同じUTXOで照会があった場合、以前明らかにしたのと同じUTXOを返す必要がある。
  • BIP-69に基づいてトランザクションが既にソートされているかどうかチェックし、ソートされているのであればそのままにする。ソートされていない場合インプット/アウトプットをシャッフルする。
  • 参照実装はhttps://github.com/rhavar/bustapayで公開されており、bitcoin coreウォレットのRPC呼び出しのラッパーとして機能する。
  • 送信者は、受信者が送信者のコントロール下にあるインプットを追加し送信者が盲目的にそれに署名することを期待する攻撃に対して注意しなければならない。

後方互換

Bustapayはオプションのペイメントプロトコルで、後方互換性の問題はない。実際に、通常のトランザクション処理に加えてサポートできる。これは通常のBitcoinトランザクションに戻す必要があるため。

所感

P2EPでもBustapayでも上記仮定を崩すウォレットが1つでも利用可能になっているというのが重要で、実際にこれらのプロトコルが使われていないとしても(使われているかどうかはトランザクション見ても分からないので)、これらのプロトコルが使われている可能性があるということだけで上記の仮定を崩すことに繋がると思われる。

あと(P2PEも一緒だけど)副次的な効果として受信者のUTXOセットを減らせるというのも良いね。