作者: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 ,则交易构造的方式将有些不同:

  1. Alice 初始化一笔交易,发送 0.1 BTC 给 Bob,并表明自己可以使用 PayJoin 特性。
  2. Bob 的钱包会提供自己的一个 UTXO 作为额外的一个输入:0.07341 BTC ,这是来自前一笔交易的非整数面额。
  3. 输出相应调整,以保持原来的支付数量:Bob 收到 0.17341 BTC(也就是 0.1 BTC 支付加上他自己的 0.07341 BTC),Alice 支付 1000 聪的确认手续费,收到 0.08999 BTC 的找零。
  4. 双方都签名交易,并正常广播。

从区块链上看,这笔交易就是普普通通的两输入、两输出交易。没有一个输出是整数面额,也没有哪个的面额是 0.1 BTC(真正的支付额)。看到这个 0.17341 BTC 的输出和 0.08999 BTC 的输出的分析者,没有可靠的依据能够识别出哪个是支付、哪个是找零。

所以,对区块链交易的启发式分析在两种维度上都失败了。CIOH 会错误地以为两个输入来自同一个钱包,而找零输出侦测也会失败,因为不管假设哪个输出是找零,都符合 “输出是一个支付加一个找零” 的模式。

PayJoin vs. CoinJoin

PayJoin 和 CoinJoin 解决的是链上隐私性问题的不同方面。

CoinJoin 通过混淆打破了 UTXO 的历史性关联:通过将许多输入结合在一起、产生相同面额的输出,它创建了一个巨大的匿名集,从中识别出身份的概率会随着参与者数量增加而下降。一个 CoinJoin 回合,如果有 10 个人参与,则每个输出只有 1/10 的概率被识别出真实的身份。

PayJoin 则总是恰好两方参与,所以没有那么大的匿名集。它的隐私性收益是结构性的,而不是概率性的:标准的启发式分析完全无法产生出可靠的结论。

这两种技术在支付流程的不同位置上发挥作用。

  1. CoinJoin 应用在你已经持有的 UTXO 上。
  2. PayJoin 则在支付的时刻发生,没有额外的步骤,也没有协调员。

因为 PayJoin 交易与普通的多输入支付无法区分,其广泛采用可以降低区块链分析在整个 UTXO 集中的数据质量,甚至非 PayJoin 交易也能受益。当两者结合使用时,CoinJoin 可以解决历史上的 UTXO 暴露,而 PayJoin 可以防止新的支付历史被识别出来。

PayJoinCoinJoin
匿名集2 方(发送方 + 接收方)多方
可在链上侦测吗?不能,看起来就像普通支付。可以,根据交易结构来识别。
需要协调员吗?不需要需要(可使用去中心化的市场)
何时能用?支付的时刻专门参与混淆
打败 CIOH?
打败找零侦测?部分(找零输出是剩余部分)

BIP-78 协议是什么?

BIP-78 是定义两方如何无需协调者而构造一笔 PayJoin 交易的技术标准。

核心挑战在于,两方需要向同一笔交易贡献输入,但他们不能同时共享一个 PSBT 。支付的接收者需要先看到发送者的 PSBT,然后添加自己的输入。BIP-78 通过用 HTTPS 协议交换一种结构化的、交互式的 PSBT 来解决这个问题。

收款方运行一个 “支付端点”,就是一个 HTTP URL,作为协调的网络端点。发送者的钱包知道要联系这个端点,因为发送者在一个标准的 BIP-21 支付 URI 中包含它作为 pj= 的参数 —— 这也是普通的比特币支付所用的 URI 格式。

这让 PayJoin 变成后向兼容的:如果发送者的钱包不支持 PayJoin 特性,那么会忽略掉这个 pj= 参数,按普通模式支付,无需用户介入。

这套协议的工作流程如下:

  1. 支付的接收方先发布一个 BIP-21 支付 URI,其中包含一个 pj= 参数,指向自己的 PayJoin 网络端点。这也是收款方表示己方支持且愿意参与 PayJoin 的信号。
  2. 发送者的钱包发现这个 pj= 参数,如果本身兼容 PayJoin 特性,则会构造一个标准的 PSBT,表达支付的数额并通过 HTTPS 发送给接收方的网络端点。
  3. 接收方的软件收到 PSBT,会添加一个自己持有的 UTXO 作为额外的输入、调整输出的数额以反映原本的支付额,然后返回修改后的 PSBT 。
  4. 发送者的钱包软件验证最初的支付数额没有改变,并且未添加没有授权的输出,就签名并广播最终的交易。

支付发送者无法被诱骗支付超出预期的数额,因为钱包软件会在签名之前检查输出的总额。接收方无法盗窃发送者的资金,因为需要发送者签名交易才有效,而只有钱包软件确认数额正确之后才会签名。要求使用 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 的配置。

  1. 取得支付 URI 。收款方提供一个带有 pj= 参数的 BIP-21 URI,参数指向自己的端点(通常是一个BTCPay Server 支付页面)。这可能是一个可以点击的链接,也可能是一个 QR 码或粘贴过来的字符串。
  2. 在 Sparrow 中初始化支付。在 Sparrow 粘贴 URI 或扫描 QR 码。Sparrow 会侦测到 pj= 参数,然后自动准备运行 PayJoin 协议。
  3. Sparrow 与收款方的端点协调。Sparrow 发送初始化的 PSBT 给端点。收款方的软件添加自己的输入,调整输出数额,然后返回修改后的 PSBT 。Sparrow 验证最初的支付额没有被更改、没有添加未经授权的输出。
  4. 使用 Coldcard 签名器来签名。导出修改后的 PSBT,通过你喜欢的空气隔离信道(BBQr QR 码、MicroSD 卡、NFC)交给 Coldcard 签名器。这个 PSBT 包含多个输入(也包括收款方的)。在 Coldcard 签名器屏幕上,验证支付数额可以目标地址是正确的,然后许可并签名。
  5. 在 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 的基础。