ビットコインで寄付を受け付けたいとき、ウェブサイトなどにビットコインアドレスを公開することが一般的です。この方法のメリットはどのウォレットでも必ず使えること、送金する際に相手との通信等が不要なこと(新しいアドレスを発行してもらう必要がない)、アドレスを生成して貼り付けるだけというシンプルさです。また、場合によっては集まった金額を見てもらいたいという場合もあるでしょう。

一方で、集まった金額の透明性はそのアドレスに対する送金がすべて見れてしまうことの裏返しです。このため、特定の団体に寄付したユーザーのトランザクションを辿って本人を特定したり、逆にその団体の資金の流れを追って取引所等の口座を凍結することができてしまいます。

この問題の解決方法はBIP47、寄付の両側でのミキシング等いくつかありますが、今日はそれらと比較してシンプルさが際立つ"Silent Payments"という新しいものを解説します。

仕組み

送金を受け付けたい者は32バイトの公開鍵X = x*Gを「サイレントアドレス」として公開します。

送金したい者はサイレントアドレスを見て、自身の持つUTXOから送金に使うものを1つ以上選びます。このうち1つの公開鍵をI = i*Gとします。

送金したい者はサイレントアドレスを、Iに対応した秘密鍵を使って改変します。送金先のビットコインアドレスX' = hash(i*X)*G + Xが求まるので、入力に先程選んだUTXOを含めてこのアドレスに送金します。

i*X == x*Iが成り立つので(Diffie-Hellman鍵交換)、送金を受け付ける者はブロックチェーンを監視し、すべてのトランザクションの入力をIと仮定して同じトランザクション内にhash(x*I)*G + Xに対応するアドレスがあるかを確認します。

長所、短所

このスキームを使うことで、たとえ第三者がサイレントアドレスを監視していても、そのサイレントアドレスに紐づくトランザクションがあるのかを判別できません。

一方で、トランザクションの受け取りを確認するには最低でもUTXOセットをすべて調べる必要があり、過去に遡って受け取りを確認するにはブロックチェーンから該当するトランザクションを検出する必要があります。UTXOセットには8000万件のUTXOが存在するため、全部をチェックするにはシングルコアで少なくとも4時間はかかってしまうようです。(もちろん、一部のUTXOを除外することで効率化する方法はあるでしょう)

トランザクションの受け取りにはこの処理を通した検出が必要なため、フルノードがなければ使用は難しいです。したがって、実は固定のビットコインアドレスを公開する程度の気軽さがあるとは言い難いかもしれません。

改善案

Silent Paymentsの提案者であるRuben Somsen氏はいくつか改善案も提案しています。

検出用と送金用の鍵の分離

送金を受け取ったか確認するための鍵がホットウォレットである必要はありません。アドレスの導出をX' = hash(i*X_scan)*G + X_spendとすることで、送金検出用の鍵x_scanをフルノードで扱いながら、受け取った資金の送金時にのみコールド保管している送金用鍵x_spendを使用することができます。

もしx_scanが流出しても資金は失わず、プライバシーを失うにとどまります。

アドレス再使用の防止

上記のプロトコルでは、再使用されたアドレスを入力とした場合、同じサイレントアドレスに対する送金はすべて同じビットコインアドレスに向けて送金されてしまいます。(宛先も再使用されてしまう)

これを防ぐために宛先アドレスの導出にtxid, input indexを含めることを提案しています。X' = hash(i*X,txid,index)*G + X

欠点として、フルノードを持たずに支払いを検出することがさらに難しくなります。

まとめ

Silent Paymentsは宛先が「サイレントアドレス」という静的な公開鍵を公開し、送金者がトランザクションの入力値となるアドレスの公開鍵を使って新しいアドレスを導出してくれるプロトコルです。宛先はフルノードでチェーンを監視、あるいはUTXOセットなどから事後的に送金を検出する必要があります。固定のビットコインアドレスを公開することが多い団体等への寄付の匿名性を送金側、受け取り側の両方で高める最もシンプルなアイデアかもしれません。

ビットコインを使った送金のプライバシーの重要性は増していくと考えられるので、寄付をするシチュエーションがあればぜひ使いたいです。ただしウォレットの対応が必要になってくるので、使えるようになるとしてもまだ先だと思います。