本文深入探讨了比特币CoinJoin面临的一种主动攻击——侦测攻击(probing attack)。
作者: m0wer
来源: https://joinmarket-ng.github.io/coinjoin-simulator/
模拟结果生成于 2026 年 4 月 12 日
“ CoinJoin” 是一种合作式的比特币交易,多个参与者将他们的输入和输出合并在一笔交易中。只要处理得当,外部观察者将无法确定哪个输入(的资金)流入了哪个输出,这就提供了 “ 交易隐私性”。
在 JoinMarket 式的 CoinJoin 中,有两个角色:
挂单人(maker) 是永远在线的机器人,在一个公开的订单簿上广告自己的要价(offer)。每一个挂单人都有一个钱包,切分成多条 “ 混淆路径 ”(就是独立的账户,通常是 5 个)。他们在这些混淆路径上分散资金,通过参与 CoinJoin 来赚取手续费。根据他们的 “ 忠诚保证金 ” 数量,挂单人会被赋予一定的权重 —— 这是带有时间锁的比特币存款,用来证明他们的投入,并让分身攻击(Sybil attacks)成本更高。
吃单人(taker) 是发起 CoinJoin 交易的人。他们从订单簿中挑选挂单人、对 CoinJoin 的数额达成一致,然后合作构造交易。吃单人的目标是获得隐私性:在 CoinJoin 之后,他们的输出将跟挂单人的输出无法区分。
一笔有 N 个挂单人的 CoinJoin 交易的 匿名性集合 的大小是 *(N+1)*:观察者将无法辨别出这 N+1 个等面值的输出中,哪一个才属于吃担任。一笔 8 个挂单人参与的 CoinJoin 交易的匿名性集合大小是 9 。
这对于被动的观察者来说,显然成立。但如果是 主动的攻击者 呢?
“侦测攻击(probing attack)”利用了 CoinJoin 的协商协议。在一笔 CoinJoin 交易得到签名和广播之前,挂单人必须将自己的输入 UTXO 暴露给吃单人。通常来说,这没什么问题,因为吃单人是诚实的,只是想完成交易。但是 恶意的吃单人 可以利用这个机制:
JoinMarket 已经安排了一种针对打探的保护措施: PoDLE(离散对数相等证据)。为了发起一个 CoinJoin 回合,吃单人必须先承诺自己有一个真实的 UTXO ,其价值要大于所请求的 CoinJoin 金额的 20% 。每一个 UTXO 只能用在最多 3 个 PoDLE 承诺中(以允许诚实参与者犯错)。挂单人会将用过的承诺广播给所有人,作为一种黑名单机制。
问题是:PoDLE 只能对付偶然的滥用,但一个资源丰富的攻击者可以 —— 在黑名单传播开来之前 —— 同时打探所有挂单人。每一个挂单人都将因为自己承诺可以提供的最大金额而揭晓尽可能多的 UTXO 。攻击者确实用掉了一些 PoDLE 承诺,但回报是,他们得到了每一个挂单人的最大混淆路径的完整快照。我们要模拟的就是这种攻击情形。
如果没有 PoDLE 以外的对抗措施,CoinJoin 协议在侦测攻击面前是非常脆弱的。我们模拟了有 100 个挂单人的网络,并根据 JoinMarket 订单簿地实时采样来假设他们地钱包结构。
哪怕攻击者发起的 CoinJoin 回合只占少许比例,也会有大量吃单人被完全消除匿名。如果攻击者的提议占 20%(每 5 个 CoinJoin 回合中就有 1 个是侦测攻击),那么大约 20% 的吃单人会失去所有隐私性。如果侦测攻击占到了 40%,就会有 32% 的吃单人失去隐私性。

而且情况会逐渐恶化。因为每一次识别都会揭晓更多 UTXO(雪崩效应),攻击者的数据在每一笔诚实的 CoinJoin 交易完成后也会增长。如果 CoinJoin 回合数量超过 5,000 个,哪怕只有 10% 是侦测攻击,也会产生 45% 的消除匿名效果(如果 CoinJoin 回个只有 1,000 个,那么消除匿名效果只有 4%)。这是长期存在的稳态风险。

我们检验了六种对抗措施。每一种都针对侦测攻击的不同方面:限制信息泄露、打破链上身份识别,或者提高攻击者的成本。
措施:限制一个挂单人在回应一个 CoinJoin 请求时揭晓的 UTXO 数量。因此,挂单人不会再揭晓自己的最大混淆路径中的全部 UTXO(可能有 5 到 10 个,甚至更多),只会揭晓价值最大的 N 个。
对抗性:攻击者从每次打探中知道的 UTXO 更少。当最大限量是 3 时,挂单人绝大部分的 UTXO 将保持隐秘,从而让未来的 CoinJoin 交易识别更难命中。
措施:在失败的 CoinJoin 回合(可能是侦测)中已经披露过的 UTXO 会被打上 标记。 当一个带有标记的 UTXO 作为输入出现在后续的 CoinJoin 交易中时,其主人 不会 以挂单人身份参与这笔交易。这个标记也会传播到从该输入 UTXO 产生的找零输出中。
对抗性:它从根本上打破了链上身份识别。即使攻击者知道一个 UTXO 属于某个挂单人,只要这种知识是从打探中知道的,那它就被污染了,无法用于身份识别。只有从别的渠道(比如通过别的方法识别出挂单人)知晓的 UTXO 才有用。
措施:在一次打探(失败的 CoinJoin 回合)之后,挂单人要记住哪个 UTXO 公开过了。在后续的 CoinJoin 回合(可能是打探)中,挂单人要重新挂单 同样的 UTXO,而不是揭晓新的 UTXO 。这个粘性集合要在这些 UTXO 在成功的 CoinJoin 回合中花费之后才情况。
对抗性:重复打探同一个挂单人不会得到新的信息。攻击者无法通过多次打探同一个挂单人获得更多信息。
措施:在一次 CoinJoin 回合开始时,每个挂单人都收取一份手续费(数额在聪级别),不论交易能否完成都要支付。诚实和恶意的吃单人都会承担这种费用。
对抗性:这让打探变得更昂贵。如果每个挂单人收取 500 聪,有 100 个挂单人,那么一次打探就要花费 50,000 聪。一天打探 10 轮,就要花掉 0.005 BTC 了。不过,这是纯粹从经济上劝阻,不会 减少信息泄露。
措施:控制挂单人在参与 CoinJoin 时如何挑选输入。这种 渐进式 算法会选出满足数额的最少数量的 UTXO,然后加入一个小额的 UTXO 以逐渐归集钱包中的 UTXO 。默认的算法使用贪婪的大额优先逻辑,没有额外属性。
对抗性:更少输入意味着更少信息被泄露给任何观察者(也包括攻击者),即使一个挂单人被其它手段识别出来。
措施:挂单人跟踪自己的已经披露的 UTXO(可能已被攻击者看过)。这种 适应式 策略会根据积压率动态决定花费已经曝光的 UTXO 还是还未曝光的 UTXO 。当许多 UTXO 都已曝光,这个挂单人会更加激进地参与 CoinJoin,以产生新的输出。
对抗性:这将加速已经曝光的 UTXO 的流转,同时保留干净的 UTXO 用于正常用途。
下图展示了每一项对抗措施单独对抗侦测攻击的影响,测试环境为每个 CoinJoin 8 个 挂单人,运行 1,000 回合:

| 对抗措施 | 对去匿名化的影响 | 机制 |
|---|---|---|
| 每次要价最多披露 3 个 UTXO | 消灭了去匿名化 | 限制每轮打探得到的信息 |
| 隔离带有标记的 UTXO | 消灭了去匿名化 | 阻碍来自侦测的身份识别 |
| 粘性披露 UTXO | 几乎消除了去匿名化(在打探占比达 80% 时,去匿名化成功率小于 0.5% ) | 防止重复打探获得增益 |
| 诚意金(500 聪) | 没有减少去匿名化 | 经济成本 |
| 诚意金(1000 聪) | 没有减少去匿名化 | 经济成本 |
三种对抗措施各自都消灭或几乎消灭了去匿名化:限制披露 UTXO 的数量、隔离带有标记的 UTXO,以及粘性披露 UTXO 。诚意金是重要的经济阻遏措施,但自身不足以减少去匿名化。
与其依赖于某一个单项措施,不如合并起来产生深度防御。推荐的配置如下:
| 参数 | 数值 | 目的 |
|---|---|---|
每次要价最多披露 UTXO 个数 |
3 |
限制每轮打探得到的信息 |
粘性披露 UTXO |
true |
防止重复打探获得增益 |
隔离带有标记的 UTXO |
true |
阻碍来自侦测的身份识别 |
诚意金 |
500 |
经济劝阻 |
合并算法 |
gradual |
尽可能减少每轮 CoinJoin 的输入曝光 |
披露输入的策略 |
adaptive |
高效循环已经曝光的 UTXO |
每轮 CoinJoin 的挂单人数量 |
8 |
更大的匿名集 |
混淆深度数量 |
5 |
钱包分层 |
我们在最严酷的条件下测试了上述策略的效果:5,000 回合的 CoinJoin,有一个预先打探过的攻击者(每个挂单人在第一次诚实的 CoinJoin 之前都被打探过,以模拟前述的同步快照攻击)。结果是,不论打探占据了多少比重(从 10% 到 60%),都 没有打破吃单人匿名。

基准测试时,侦测攻击占比 40% 就可以将 79.2% 的吃单人去匿名化;而在推荐的策略下,去匿名化效果为 0.0% 。
即便攻击者愿意为打探花费比特币,诚意金和限制信息泄露的组合,让攻击者颗粒无收。下图展示了在为期14 天的时间里,攻击的强度对去匿名化和攻击者成本的影响:

在基准测试中,哪怕每天只打探一次,也能实现 70% 的去匿名化。将频率提高到每天 50 次,效果将是 97%,成本为 0.025 BTC 每天。而在推荐的策略下,攻击者不论花费了多少钱,都 无法实现去匿名化效果。
光靠诚意金本身是不够的。即便每个挂单人收取 1,000 聪,攻击者依然可以在侦测攻击占比 80% 时,实现大约 56% 的去匿名化效果。成本会增加,但无法解决基本的信息泄露问题。真正的防御还是要限制攻击者获得信息。
攻击结束之后,会怎么样?随着诚实 CoinJoin 出现, 挂单人会生成攻击者所不知道的新的 UTXO 。攻击者的数据库将变得过时、身份识别率也会下降。

在为期 14 天、每天 20 次侦测的攻击之后,基准情形要在一周之后才能复原(去匿名化率下降到 5%)。而推荐的策略则从未受到影响:去匿名化率一直都是 0% 。
模拟的原始数据: github.com/m0wer/coinjoin-simulator
收集的数据集: publish_summary.json
生成于 2026-04-12
- 本文转载自: btcstudy.org/2026/05/21/... , 如有侵权请联系管理员删除。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!
作者暂未设置收款二维码