ビットコインセキュリティ中級

受け取る側もコインを出す

ブロックチェーン分析は、一つの取引の入力はすべて一人のものだと仮定する。ペイジョイン(Payjoin)は、支払いを受け取る側が自分のコインを入力に加えることでこの仮定を誤らせる。数字の例で支払額がどう消えるかを見て、送る側と受け取る側が互いを信頼せずに取引を作るための仕組み、普通に見えることがなぜ難しいのか、そして受信サーバーという壁を BIP-77 がどう取り除いたのかを整理する。

·14分

ビットコインのホワイトペーパー第 10 節「プライバシー」は、一つの限界を自ら認めて終わる。

Some linking is still unavoidable with multi-input transactions, which necessarily reveal that their inputs were owned by the same owner.

入力が複数ある取引では、ある程度の結びつきは避けられない。そうした取引は、入力が同じ持ち主のものであることを必然的に明かしてしまうからだ。ブロックチェーン分析業界はこの一文を規則にした。一つの取引の入力はすべて一人のものだと仮定し、その仮定でアドレスを一人分の束にまとめていく。共通入力所有ヒューリスティックと呼ばれる。

ペイジョイン(Payjoin)はこの一文の「necessarily」を狙う。支払いを受け取る側が、自分のコインを一つその支払い取引の入力に加える。すると入力は複数あるのに持ち主は二人になる。外から見れば普通の支払い一件で、分析者の仮定は静かに外れる。

普通の支払いが残すもの

UTXO のウォレットでは、支払いはたいていこういう形をしている。アリスがボブに 0.05 BTC を送り、アリスのウォレットには 0.08 BTC のコインがある。取引は入力一つ(0.08)と出力二つを持つ。ボブへの 0.05 と、アリスに戻るお釣りの 0.03 だ。この記事の数字は、計算を簡単にするため手数料を省いている。

この取引を見る分析者はいくつかのことを推測できる。BIP-78 はそのうち三つに名前を付けて書き留めた。一つ目は先ほどの共通入力所有。二つ目はアドレスの形式だ。入力がすべてある形式のアドレスから来ているなら、同じ形式の出力がお釣りである可能性が高い。三つ目は切りのいい金額だ。0.05 のようにきれいに割り切れる出力は支払いで、残りがお釣りである可能性が高い。上の取引は、三つ目の推測だけで支払いとお釣りが分かれてしまう。

受け取る側が入力を一つ加える

同じ支払いをペイジョインで行うと、ボブが自分のウォレットの 0.04 BTC のコインを入力に加える。取引はこう変わる。

  • 入力: アリスの 0.08、ボブの 0.04
  • 出力: ボブへ 0.09、アリスへ 0.03

ボブは 0.05 を受け取り、自分の 0.04 と合わせて 0.09 のコインを一つ新しく持つことになった。アリスは 0.03 をお釣りとして受け取った。実際に起きたことは最初とまったく同じだ。

分析者にはまったく違って見える。共通入力所有を当てはめれば、0.12 BTC を持つ一人が支払った取引だ。お釣りを探そうとすると、ウォレットは必要以上のコインを選ばないという推測が働く。支払いが 0.03 だったなら 0.08 一つで足りたので、0.04 を足す理由がない。だから支払いは 0.09 で、0.03 がお釣りだという結論になる。結論はどちらも誤りだ。入力は二人のもので、実際の支払額 0.05 はブロックチェーンのどこにも書かれていない。

ボブが別のコインを選んでいたら事情は変わる。0.01 BTC のコインを加えていたなら、出力はボブ 0.06、アリス 0.03 になる。今度はどちらが支払いでも、アリスの 0.08 一つで足りていた。0.01 という入力は理由もなく入ったように見え、普通のウォレットはそういう選び方をしない。この取引はかえって「誰かがコインを加えた」という印になる。この点は後でもう一度扱う。

ボブにも得るものがある。店のように支払いを多く受け取る側には、小さなコインが数百、数千とたまる。いつかそれらをまとめる統合取引を別に行う必要があり、その取引は手数料を払ったうえで自分のアドレスを一人のものとして結びつけてしまう。ペイジョインで受け取れば、支払いを受けるたびにコインを一つずつまとめておくことになり、その費用の大半はどのみち出ていく支払い取引に乗る。BIP-78 が提案の動機として最初に挙げたのが、この統合の機会だ。

元の取引という担保

二人で一つの取引を作るには、互いに情報をやり取りしなければならない。BIP-78 の流れは四段階だ。

  1. ボブが支払い要求(BIP-21 URI)に pj= パラメータでペイジョインの受付先を付けて示す。
  2. アリスはいつも通りボブへの取引を作り、署名まで済ませる。これをオリジナル(Original)PSBT と呼び、受付先に送る。
  3. ボブはオリジナルに自分の入力を入れ、自分の出力を直し、自分の入力にだけ署名して返す。これがプロポーザル(Proposal)PSBT だ。
  4. アリスはプロポーザルを検査し、自分の入力に改めて署名してブロードキャストする。

ここで重要な仕組みは第 2 段階だ。アリスが最初に送るオリジナルは、そのままネットワークに流してもよい完成した取引でなければならない。ボブが店なら、オリジナルを受け取った時点で支払いは確保されている。アリスが第 3 段階のあとで姿を消しても、ボブはオリジナルをそのまま流せばいい。オリジナルと最終取引は同じコインを使うので、ブロックに入るのはどちらか一方だけだ。

この担保はボブ側の別のリスクも防ぐ。店の受付先は誰にでも開かれている。悪意のある者がオリジナルを送っておいて最後の署名をしなければ、ボブはプロポーザルを作るたびに自分のコインを一つ見せることになる。これを繰り返せば、店のウォレットの中身を一つずつ探り出せる。BIP-78 はこれを UTXO 探査攻撃と呼ぶ。オリジナルが実際に有効な取引であれば、攻撃者は探査のたびに本物の支払いを一つずつ賭けることになり、ボブはそれを流して代金を受け取る。そのため BIP-78 は、自動で支払いを受ける受信者に、オリジナルが実際に流せる取引かどうかを確かめ、以前に見たことのある入力が含まれていれば拒否するよう求める。一度見せたコインは次のペイジョインで優先して使い回すことも勧めている。この仕組みの源は、2018 年にライアン・ハヴァー(Ryan Havar)が書いたバスタペイ(Bustapay、BIP-79)だ。その文書は「コストのかからない偵察とサービス妨害を防ぐため」、送る側にすぐ伝播できる有効な取引を先に求めた。

アリス側の検査も長い。ボブが返したプロポーザルで、アリスは自分の入力がすべて残っているか、自分の出力の金額が減っていないか、手数料の総額がオリジナルより減っていないか、取引のバージョンと nLockTime、自分の入力の sequence 値がそのままかを確かめる。そして、オリジナルにあった自分の入力にだけ署名する。逆にボブは自分の分の出力を自由に変えてよい。金額を減らすことも、アドレスを替えることも許される(出力の置き換え)。アリスのアドレスがネイティブ SegWit で、ボブの要求アドレスが古い形式なら、ボブが同じ形式に替えて二つ目の推測までぼかせるようにするためだ。受付サーバーを決済サーバーより信頼の低い場所に置いているなら、ボブは pjos=0 を付けて置き換えを禁じる。そうすればサーバーが乗っ取られても支払いを横取りされない。

BIP-78 が自ら書き留めた弱点もある。ハードウェアウォレットは、オリジナルと最終取引が同じ支払いの二つの版なのかを判断できない。接続したコンピューターのウォレットソフトが汚染されていれば、ハードウェアウォレットは別々の二つの取引に署名することになる。ペイジョインでなければ、汚染されたソフトが抜き取れる最大額は支払い一件分だが、ペイジョインでは二件分になる。

普通に見えることがいちばん難しい

ペイジョインの価値は、すべて「普通に見える」ことにかかっている。普通の支払いと見分けがつかないからこそ、分析者はすべての複数入力取引を疑わなければならなくなる。ところが、普通に見えることは思ったより難しい。

先ほどの 0.01 の例が典型だ。2021 年、シミン・ゲスマティ(Simin Ghesmati)らは、不要に見える入力を含む取引を拾い出す不要入力ヒューリスティック(Unnecessary Input Heuristic)によってペイジョインが露見しうることを示した。受け取る側が適当なコインを入れると、ペイジョインがかえって目印になるということだ。広く使われている実装の rust-payjoin は、これを避ける選択関数を持っている。出力が二つの取引で、加えたあとに最小の入力が最小の出力より大きくなるコインを選ぶ。すると最小の出力が普通のお釣りに見える。先ほどの 0.04 がまさにこの条件を満たす選び方だった。

手数料率も痕跡になる。ウォレットはたいてい 2 sat/vB のような切りのいい手数料率を使う。受け取る側が入力を加えて手数料をそのままにすると、取引が大きくなった分だけ手数料率が 1.87 のような中途半端な値に下がる。入力を一つ外して計算し直したときに切りのいい値が出れば、疑いは確信に変わる。BIP-78 は、増えた手数料をいくらまで負担するかを送る側があらかじめ伝えるパラメータを設け、受け取る側が手数料率を元の値に合わせられるようにした。

実装どうしの小さな違いも指紋になる。2025 年 9 月、Sparrow の利用者が Cake Wallet 宛てにペイジョインを送ろうとして「The proposal PSBT changed the nLocktime」というエラーを受けたという報告が上がった。Sparrow は BIP-78 の検査項目どおり、nLockTime が変わったプロポーザルを拒否したのだ。一方の Cake Wallet は、すべてのビットコイン取引の nLockTime を 0 にしていた。Bitcoin Core や Electrum は現在のブロック高に近い値を入れるので、0 という値はそれだけで、どのウォレットで作った取引かを教える痕跡だった。Cake Wallet は 2026 年 8 月にこれを Core の方式に改めた。同じウォレットの受信側は、しばらくのあいだ候補コインの先頭を無条件に加えていて上の選択関数を飛ばしていたが、これも 2026 年 6 月に直された。

ペイジョインは普通の取引をまねる技術だ。だから、その「普通」の基準は結局、ほかのウォレットが実際に作っている取引になる。

阻んでいたのはサーバーだった

ペイジョインという考えは古い。2018 年 8 月、ブロックストリームのブログでマシュー・ヘイウッド(Matthew Haywood)が、あるコミュニティのワークショップの結論を P2EP(Pay-to-EndPoint)という名前でまとめ、10 月にバスタペイが BIP-79 の番号を受けた。2019 年 5 月には BTCPay Server のニコラ・ドリエ(Nicolas Dorier)が書いた BIP-78 が番号を受け、バスタペイに取って代わった。BIP-78 は、バスタペイが PSBT を使わないため、手数料を上げるには受け取る側が UTXO 集合全体を知っている必要があったことなどを理由に挙げた。2020 年 4 月 16 日、BTCPay Server 1.0.4.0 が店舗でのペイジョイン受信と内蔵ウォレットからの送信を入れた。BIP-78 の状態は現在「Deployed」だ。

それでもペイジョインは広まらなかった。理由は数学ではなくサーバーだった。BIP-78 の受け取る側は、認証付き暗号(TLS または .onion)で守られた公開 HTTP の受付先を運用しなければならず、送る側と同時にオンラインでなければならない。店のサーバーには難しくないが、スマートフォンのウォレットには事実上不可能だ。2020 年 6 月、Bitcoin Core に「ペイジョインを実装しよう」というイシューが立ったとき、提案者自身が、サーバーとの通信に OpenSSL が必要になるかもしれず BIP-70 と同じ反対に遭うだろうと書いた。Core は決済プロトコル BIP-70 を、TLS への依存などの問題からすでに取り除いていた。

BIP-77(Async Payjoin)はこの壁を狙う。2023 年 8 月に番号を受け、著者はダン・グールド(Dan Gould)とユヴァル・コグマン(Yuval Kogman)だ。受け取る側がサーバーを運用する代わりに、信頼する必要のない第三者のディレクトリサーバーに一時的な郵便受けを開く。送る側はオリジナルをその郵便受けに入れ、受け取る側はあとで来て取り出し、プロポーザルを別の郵便受けに入れる。二人が同時にオンラインである必要はない。中身は両端で暗号化されていて、ディレクトリは取引を読めない。リクエストはオブリビアス HTTP(OHTTP、RFC 9458)の中継を通り、ディレクトリにはどの IP からのリクエストかも分からないようにする。暗号の材料は secp256k1 の鍵交換と ChaCha20-Poly1305 で、Core が BIP-324 の暗号化通信のためにすでに持っているものだ。TLS は要らない。

2020 年の Core のイシューは 2025 年 10 月 22 日に閉じられた。同じ日、PSBT の仕様 BIP-174 の著者エイヴァ・チョウ(Ava Chow)が、BIP-77 を Core のウォレットに入れるための追跡イシューを新たに開いた。2026 年 10 月現在、そのイシューは開いたままで、Core のウォレットにはまだペイジョインがない。BIP-77 の状態もまだ「Draft」だ。ウォレットの側では、Bull Bitcoin のモバイルウォレットが 2024 年 12 月 27 日の 0.4.0 で BIP-77 の送受信を入れ、Cake Wallet が 2025 年 5 月 15 日の 4.28.0 で続いた。Sparrow は BIP-78 の送信に対応しており、BIP-77 対応の要望は 2026 年 3 月から開いている。

使わない人にも

ペイジョインが狙う効果は、使う人だけにとどまらない。BIP-78 は、この提案が存在すること自体が共通入力所有ヒューリスティックをネットワーク全体で当てにならないものにし、使わない人のプライバシーも高めると書いた。複数入力取引の一部が二人のものかもしれないと分析者が疑わなければならなくなった瞬間、複数入力取引から作られたすべての束が揺らぐ。

ただし、この効果には条件がある。ペイジョインがまれなら、分析者はその可能性を無視してもたいてい正しい。そして先に見たように、実装が痕跡を残せば、ペイジョインは隠れられずに拾い出される。コインジョインは同じ金額の出力が並んでいて誰が見てもコインジョインだが、その代わり多くの人が混ざる。ペイジョインは二人しか混ざらないが、見た目が普通だ。前者の力は隠れる群衆の大きさにあり、後者の力は疑わせる取引の数にある。

BIP-77 はプライバシー以外の使い道も掲げる。取引所への入金が同じ取引の中でほかの顧客の出金を満たすように、受け取ってすぐ送り出すお金を一つの取引で処理すれば、ブロックスペースと手数料が減る。取引所がすでに行っている出力のまとめに、入力のまとめを加える形だ。

いま試せること

受け取る側が BTCPay Server を使う店なら、ペイジョインの受信を有効にできる。支払い要求の URI に pj= が見えれば、その店はペイジョインを受け付けている。送る側は、Sparrow のように BIP-78 の送信に対応したウォレットにその URI をそのまま貼り付ければいい。個人どうしでやり取りするなら、双方に BIP-77 対応のウォレット(Bull Bitcoin、Cake Wallet)が必要だ。ペイジョインを知らないウォレットは pj パラメータを無視して普通の送金をするので、受け取る側がペイジョインを有効にしておいて損をすることはない。

ハードウェアウォレットから送るなら、先に述べた二件分の署名のリスクを覚えておく。受け取る側なら、加えるコインをウォレットがどう選ぶかも見ておく。適当なコインを加えるウォレットは、ペイジョインを隠すどころか明かしてしまう。

ホワイトペーパーは、複数入力取引は入力の持ち主が同じであることを「必然的に」明かすと書いた。ペイジョインの取引では、その一文は外れる。そして、その記録が事実と違うことを知っているのは、取引をした二人だけだ。

関連記事