作者:Coldcard
来源:https://coldcard.com/learn/bitcoin-privacy/what-is-payjoin
原文出版于 2026 年 6 月。
PayJoin 是一种两方交易,有意支付的一方和收取支付都一方都为一笔交易提供输入。这种结构可以同时抵御两种区块链启发式分析,并且形成的交易与标准的多输入支付,在链上形态上没有区别。
PayJoin 是 CoinJoin 的补充,而非替代:Coinjoin 通过混合来打破 UTXO 的历史关联,PayJoin 则是在支付的时候防止跟踪,并且无需协调员和第三方。
什么是 “PayJoin”?
在普通的比特币支付中,发送者挑选自己拥有的一个或多个 UTXO 作为输入,从而制作出一笔交易。一般来说,这样的交易会产生两个输出:一个用于支付,将一定数额的资金发送到收款方的地址;另一个则是找零输出,将没有花完的钱返回到发送者自己控制的地址。
这种结构极为通用,所以区块链分析者将它视作一条公理。应用 “输入所有权同一性(CIOH)” 假设,他们会把一笔交易的所有输入都视作属于同一个钱包。然后,通过侦测找零输出,识别出那个输出是支付、哪个输出是找零,分析者就能进一步跟踪进入双方地址的资金。对比特币区块链上的全部历史交易应用这些假设,就成了一种大规模的金融监控。
PayJoin 摧毁了这种模式,因为它让收款方也给这笔交易提供一个输入。结果是,这笔支付交易并不符合常见的模式,但从外观上,看不出它使用了任何隐私保护技术。
- 上述两种启发式分析会同时失效。CIOH 假设一笔交易的所有输入都属于同一个人,那么当收款方也提供输入时,这种假设就被打破了:它的输入来自两个不同的人,所以应用 CIOH 的分析者会错误地将两个钱包集群合并(归类为同一个身份)。找零输出侦测也会失败,原因也是一样的,因为额外的输入,使得输入的价值不会恰好比支付输出高出一点点,所以分析者也无法可靠地识别出哪个输出是什么目的。
- 交易从外部看无法区分。如果分析者熟知两个参与者的请快乐,他们可以猜测这两人一起构造了这笔 PayJoin 交易,但依然无法确定哪个输出属于谁。如果对双方都没有了解,那么这笔交易看起来跟任何携带两个输入的支付都没有什么区别。
- 收款方也能得到好处。一个运行 BTCPay Server 的商家,在将要收取付款时为交易贡献一个输入,最终形成的交易既能保护收款方的隐私,也能保护发送者的隐私,因为分析者无法断定哪个输出是真正的支付、哪个输出属于顾客。
- 无需协调员。PayJoin 发生在支付的时候,没有资金混淆池、不需要等待其他参与者,也无需第三方协调员。所以,它对于网络层面的监控来说,不会被视为独特的混淆事件。
PayJoin 的工作原理
以一笔普通的比特币支付为例。Alice 希望给 Bob 支付 0.1 BTC ,而她持有一个价值 0.19 BTC 的 UTXO 。她创建一笔交易,使用一个输入(0.19 BTC),产生一个支付输出(0.1 BTC)到 Bob 的地址,以及一个找零输出(0.08999 BTC)给自己(其中 1000 聪的差额是为了支付区块确认手续费)。
任何看到这笔交易的分析者,都能看出这个 0.1 BTC 的输出是用来支付的(因为数额是整数,而且使用新的地址),而这个 0.08999 BTC 的输出是找零(因为这是剩下的,很可能返回给了 Alice 自己)。他们可以进一步跟踪 Bob(支付接收方)的地址,以及 Alice 的找零地址,观察后续的花费行为。
而如果双方使用 PayJoin ,则交易构造的方式将有些不同:
- Alice 初始化一笔交易,发送 0.1 BTC 给 Bob,并表明自己可以使用 PayJoin 特性。
- Bob 的钱包会提供自己的一个 UTXO 作为额外的一个输入:0.07341 BTC ,这是来自前一笔交易的非整数面额。
- 输出相应调整,以保持原来的支付数量:Bob 收到 0.17341 BTC(也就是 0.1 BTC 支付加上他自己的 0.07341 BTC),Alice 支付 1000 聪的确认手续费,收到 0.08999 BTC 的找零。
- 双方都签名交易,并正常广播。
从区块链上看,这笔交易就是普普通通的两输入、两输出交易。没有一个输出是整数面额,也没有哪个的面额是 0.1 BTC(真正的支付额)。看到这个 0.17341 BTC 的输出和 0.08999 BTC 的输出的分析者,没有可靠的依据能够识别出哪个是支付、哪个是找零。
所以,对区块链交易的启发式分析在两种维度上都失败了。CIOH 会错误地以为两个输入来自同一个钱包,而找零输出侦测也会失败,因为不管假设哪个输出是找零,都符合 “输出是一个支付加一个找零” 的模式。
PayJoin vs. CoinJoin
PayJoin 和 CoinJoin 解决的是链上隐私性问题的不同方面。
CoinJoin 通过混淆打破了 UTXO 的历史性关联:通过将许多输入结合在一起、产生相同面额的输出,它创建了一个巨大的匿名集,从中识别出身份的概率会随着参与者数量增加而下降。一个 CoinJoin 回合,如果有 10 个人参与,则每个输出只有 1/10 的概率被识别出真实的身份。
PayJoin 则总是恰好两方参与,所以没有那么大的匿名集。它的隐私性收益是结构性的,而不是概率性的:标准的启发式分析完全无法产生出可靠的结论。
这两种技术在支付流程的不同位置上发挥作用。
- CoinJoin 应用在你已经持有的 UTXO 上。
- PayJoin 则在支付的时刻发生,没有额外的步骤,也没有协调员。
因为 PayJoin 交易与普通的多输入支付无法区分,其广泛采用可以降低区块链分析在整个 UTXO 集中的数据质量,甚至非 PayJoin 交易也能受益。当两者结合使用时,CoinJoin 可以解决历史上的 UTXO 暴露,而 PayJoin 可以防止新的支付历史被识别出来。
| PayJoin | CoinJoin | |
|---|---|---|
| 匿名集 | 2 方(发送方 + 接收方) | 多方 |
| 可在链上侦测吗? | 不能,看起来就像普通支付。 | 可以,根据交易结构来识别。 |
| 需要协调员吗? | 不需要 | 需要(可使用去中心化的市场) |
| 何时能用? | 支付的时刻 | 专门参与混淆 |
| 打败 CIOH? | 是 | 是 |
| 打败找零侦测? | 是 | 部分(找零输出是剩余部分) |
BIP-78 协议是什么?
BIP-78 是定义两方如何无需协调者而构造一笔 PayJoin 交易的技术标准。
核心挑战在于,两方需要向同一笔交易贡献输入,但他们不能同时共享一个 PSBT 。支付的接收者需要先看到发送者的 PSBT,然后添加自己的输入。BIP-78 通过用 HTTPS 协议交换一种结构化的、交互式的 PSBT 来解决这个问题。
收款方运行一个 “支付端点”,就是一个 HTTP URL,作为协调的网络端点。发送者的钱包知道要联系这个端点,因为发送者在一个标准的 BIP-21 支付 URI 中包含它作为 pj= 的参数 —— 这也是普通的比特币支付所用的 URI 格式。
这让 PayJoin 变成后向兼容的:如果发送者的钱包不支持 PayJoin 特性,那么会忽略掉这个 pj= 参数,按普通模式支付,无需用户介入。
这套协议的工作流程如下:
- 支付的接收方先发布一个 BIP-21 支付 URI,其中包含一个
pj=参数,指向自己的 PayJoin 网络端点。这也是收款方表示己方支持且愿意参与 PayJoin 的信号。 - 发送者的钱包发现这个
pj=参数,如果本身兼容 PayJoin 特性,则会构造一个标准的 PSBT,表达支付的数额并通过 HTTPS 发送给接收方的网络端点。 - 接收方的软件收到 PSBT,会添加一个自己持有的 UTXO 作为额外的输入、调整输出的数额以反映原本的支付额,然后返回修改后的 PSBT 。
- 发送者的钱包软件验证最初的支付数额没有改变,并且未添加没有授权的输出,就签名并广播最终的交易。
支付发送者无法被诱骗支付超出预期的数额,因为钱包软件会在签名之前检查输出的总额。接收方无法盗窃发送者的资金,因为需要发送者签名交易才有效,而只有钱包软件确认数额正确之后才会签名。要求使用 HTTPS 协议,是为了防止中间人修改传输中的 PSBT 。
BIP-78 真正的局限性在于它要求收款方运行一个服务端。运营一个 HTTPS 端点,对于运行 BTCPay Server 的商家来说当然没什么大不了,但对于大部分个人来说可能都有些麻烦。BIP-77(无服务端的 PayJoin)让中继基础设施来路由通信内容,从而任何一方都无需运营基础设施,解决了这个问题,也让 PayJoin 对没有服务端的点对点应用场景可用。
什么工具支持 PayJoin?
PayJoin 要求发送者的钱包和接收者的支付基础设施都支持这套协议。Sparrow Wallet 支持发送 PayJoin,而 BTCPay Server 支持接收 PayJoin 。
- Sparrow Wallet(发送者)自动在 BIP-21 支付 URI 中侦测
pj=参数。当出现这个参数时,Sparrow 运行一个交互式协议,无需用户手动配置。如果无法访问对方的端点,Sparrow 将回退为广播一笔普通交易。Coldcard 签名器会正常签名得到的 PSBT。从 Coldcard 签名器的角度看,只不过是签名一笔多输入的 PSBT,跟处理别的交易没有什么不同。 - BTCPay Server(接收方)原生支持 BIP-78 。PayJoin 特性是自动启用的,让发送者可以支付一个 BTCPay 发票。这意味着,无论在什么地方部署了 BTCPay ,商家的支付基础设施已经支持了 PayJoin 收款,无需额外的配置。
在现实中,PayJoin 在商家这一边已经基本普及,一个基于 BTCPay 的支付页面可以收取来自任何兼容钱包的 PayJoin 。点对点的用法需要双方都使用兼容的软件,而收款方需要运行一个 BTCPay 实例或相同效用的程序。
使用 Sparrow 和 Coldcard 签名 PayJoin 交易
当遇到包含了 pj= 参数的支付 URI 时,Sparoow 会自动处理 PayJoin 协议。Coldcard 签名器可以签名最终的多输入 PSBT ,不需要任何专用于 PayJoin 的配置。
- 取得支付 URI 。收款方提供一个带有
pj=参数的 BIP-21 URI,参数指向自己的端点(通常是一个BTCPay Server 支付页面)。这可能是一个可以点击的链接,也可能是一个 QR 码或粘贴过来的字符串。 - 在 Sparrow 中初始化支付。在 Sparrow 粘贴 URI 或扫描 QR 码。Sparrow 会侦测到
pj=参数,然后自动准备运行 PayJoin 协议。 - Sparrow 与收款方的端点协调。Sparrow 发送初始化的 PSBT 给端点。收款方的软件添加自己的输入,调整输出数额,然后返回修改后的 PSBT 。Sparrow 验证最初的支付额没有被更改、没有添加未经授权的输出。
- 使用 Coldcard 签名器来签名。导出修改后的 PSBT,通过你喜欢的空气隔离信道(BBQr QR 码、MicroSD 卡、NFC)交给 Coldcard 签名器。这个 PSBT 包含多个输入(也包括收款方的)。在 Coldcard 签名器屏幕上,验证支付数额可以目标地址是正确的,然后许可并签名。
- 在 Sparrow 中广播交易。将签好名的 PSBT 交给 Sparrow 并广播。这笔交易会得到区块确认,就像普通的多输入支付一样,不会留下使用了 PayJoin 的痕迹。
如果收款方的端点离线了,或者在第 3 步无响应,那么 Sparrow 会回退为广播一笔普通交易,这都是自动的。无论如何,支付会完成。
什么是 “无服务端的 PayJoin”(BIP-77)?
BIP-77 提出通过基于中继的通信来消除服务端门槛,如此则双方都无需运行服务端。
BIP-77 使用了 “Oblivious HTTPS”(OHTTP)中继节点。发送方和接收方通过中继来通信,但中继无法阅读内容,因为通信是端到端加密的。中继只知道两个人在交换数据,但无法看到 PSBT 内容,也无法识别参与者e身份。
这套协议也是异步的。在 BIP-78 下,发送者必须等待接收者在线并响应。而在 BIP-77 下,发送者可以将 PSBT 发到中继,接收者可以稍后再取回,从而 PayJoin 双方甚至无需同时在线。
在撰写本文之时,BIP-77 只是草案,未得到钱包软件广泛采用。
《比特币地址复用和管理》一文介绍了使用新地址的互补性隐私习惯,可以防止收款关联,也正是 PayJoin 的基础。