作者:marathon-gary

来源:https://delvingbitcoin.org/t/silent-payments-coinbase/2833

我一直好奇,如何能让矿池在 coinbase 交易中直接给矿工(不同的地址)支付(以及广义上来说可以用 coinbase 交易做的 “有趣” 事情)。当前,Ocean 矿池会在 coinbase 交易中给矿工支付 1,只不过都是发给一个用作 startum 用户名的静态地址。

经过一番实验(使用 miniscript 脚本来轮换矿池的 coinbase 地址,我初步认为,让矿工给矿池分享一个 xpub(或者类似的东西),就可以了。但是,一旦这个矿池的数据库被攻破,那么与这个 xpub 有关的所有交易都会曝光。如果你想要隐私性,这是很不好的方案。

最近我突然想到,可以使用 BIP352 静默支付(SP),因为一个收款方(在这里就是矿工)可以使用一个静态的、公开的 SP 地址。本文剩下的部分是列举我想到的,可以如何在一笔 coinbase 交易中给矿工支付。我将这套方案称为 “静默支付 coinbase(SPc)”。

对于 SP 收款方来说,一个静默支付地址包含了两个公钥:其一为 “扫描公钥”,其二为 “花费公钥”。SPc 也保持相同设定。收款方将在与一个矿池开设一条挖矿协议信道时,通过 Stratum v2 协议 2 分享自己的 SP 地址。矿池会在自己的记账数据库中登记,然后开始给这个 SP 地址增记哈希率。

矿池的记账方法与此无关,但我认为,矿池应该在记账日志失去意义后主动删掉它们。矿池要追踪 SP 地址与其应得的数额之间的关联,这是无可避免的。但从用户隐私性角度看,还是有一个威胁因素,就是矿池的数据库被攻破;所以,任何矿池实现都应该只保留为准确支付而必要的记账数据。我认为,这跟 VPN 的 隐私性-信任 取舍是一样的。VPN 的服务商(矿池)是你的隐私性的受信任第三方,这意味着,用户应该要求操作层面的最佳做法,因为删除是无法证明的。

现在,就到有趣的部分了。

在一个普通的 SP 发送者创建交易时,需要揭晓一个公钥和 nonce 。这让收款方可以运行 DHKE(DH 密钥交换)数据 ,从而发现哪个地址是属于自己的、能够花费它。这或多或少也是过度简化,我推荐读者们自行浏览 BIP352 的 “发送者” 一节

在静默支付最本的规范中,公钥/nonce 的组合是从输入(们)的确定性数据中派生出来的,其中包括发送者的花费公钥。但是 coinbase 交易没有输入 3,所以无法使用标准的 SP 。在 SPc 中,nonce 定义为区块高度,并被用在一个带有矿池公钥的承诺(hash(block_height ‖ A_send))中。通过承诺 A_send 和区块高度,就能防止矿池研磨出一个恶意的 a_send(详见 BIP352 的脚注 3)。

发送者的公钥要发布在 coinbase 交易的矿池标签(也就是矿池签名)中。coinbase 交易的脚本签名字段有 100 个字节(的空间),它要包含一些必要的字节(见 BIP34),但 A_send 只有 34 字节,要替换 ASCII 编码的矿池标签还是有余量的,不会跟挖矿时可以滚动的 extranonce 重叠(由矿池在 Sv2 中定义)。矿池使用的 A_send 公钥只用于 DHKE,最好是一次性的,这样即使这个密钥被劫持,也不会泄露太多关于支付的机密数据。在普通的 SP 协议中,这个密钥是发送者的花费密钥,所以永远无法丢弃。而在 SPc 中,它完全不控制资金,在考虑劫持情形时,姿态完全不同。

这些对 coinbase 支付的规范的重新思考,带来了一些动态要求,是谋求使用 SPc 的矿池需要考虑的。幸运的是,在 Stratum v2 中,我们已经有了充分定义、良好规范的挖矿协议,所以 定义/编程 这些动态要求都是容易的(政客发言!)。

作为一个 SPc 矿池,收到矿池协议信道并得到一个来自工况的 SP 地址时,在数据库中就要使用这个 SP 地址作为记账的公钥。随着矿池统计和更新其 coinbase 交易支付分布,它要同步运行必要的数学来创建 SPc 交易,给所有连接的矿工支付。给定挖矿的 在线/交互式 要求,这不会给矿工增加多少复杂性,因为矿池可以承担这部分计算成本,这本身就是矿池的作用。使用一个合适的实现,矿工可以直接更新自己的用户名为一个 SP 地址,然后将自己的哈希率指引到一个启用了 SPc 的网络端点。

与普通的 SP 一样,收款方使用公开(在矿池标签中的)A_send 以及他们的扫描公钥来找出哪个地址是给他们的支付。幸运的是,因为 SPc 交易总是每个 SPc 区块的第 0 笔交易,扫描的负担大大缩小。这是一个微不足道的胜利,但值得一提,因为我认为它解决了 BIP352 轻客户端所面临的一个开放问题

还有一些 考虑/威胁:

  • SPc 并不能缓解数额痕迹。一个矿池的 稳定的/持续的 哈希率供应者,可以在这个矿池所发现的区块中识别出来。可能会有缓解措施,但我决定留给评论和未来的设想。
  • 攻破这样的矿池的收据库是矿工隐私性的最大威胁。理想情况下,矿池仅保留为计算和清账而必要的份额统计数据,然后就会闪电,可以帮助保护过往区块(挖矿矿工)的隐私性。
  • 如 Ocean 已经证明的那样,为避免粉尘数额,一笔 coinbase 交易的支付数量是有限的。一个 SPc 矿池可能会采用 Ocean 类型的 BOLT12 闪电支付,从而允许体量较小的矿工可以匿名退出。对 SPc 来说,由于这种局限性,我们假设并非所有的矿工都会在在一笔 coinbase 交易中得到清账。
  • 已经有了一个 Sv2 规范的插件,是为非托管支付而提议的;SPc 需要先适配它,才能支持 “工作声明(JobDeclaration)” 特性,也就是矿工自己构造区块模板,但让矿池来决定 coinbase 交易的内容。这份规范没有决定矿池标签的要求,不过其它方面似乎都是有用的。

如果你愿意看看(我提示) AI(Claude)生成的网页来研究这个想法,我做了一个放在 GitHub 上。它所在的代码库包含了 SPc 的测试向量以及 AI 帮我创建的这个想法的迭代。

欢迎 评论/提问/批评,也欢迎各位优化这个想法,使之能称为一个 BIP/规范。这个提议肯定需要更多的尽职调查以及完胜,但我希望分享出了能够加速这个过程。请分享给可能被触动和启发的人。我坚信,Stratum v2 的成熟会带来一个健壮而繁荣的软件生态系统,我希望我在这里提出的想法能吸引更多人汇集到这个生态系统。

感谢。

- - -

1. 哈希率超过一个阈值的矿工就能在 coinbase 交易中得到支付。

2. Stratum v1 有意留下这个空白,因为规范本身缺乏原生的加密方法,也没有正式的定义。Sv2 将 BIP324 类型的 Noise 协议用于连接协议,我认为对于矿工和矿池之间的机密通信是必要的。偏见披露:我贡献于 Sv2 参考实现和嫌疑。

3. 技术上来说,coinbase 交易有一个输入,我们也会用上,但使用方式不同;这个输入也没有公钥(无法为普通的 SP 协议所用)。

- - -

Seldenthuis:

有一个数值值得再次确认:BIP34 的高度记录并不是一个微不足道的固定成本。

我最近一直在实现 coinbase 交易脚本签名构造(BIP34 高度编码、2 ~ 100 字节的共识限制),在当前的真实世界的区块高度上(包括主网和 testnet4,都超过了 2^16,小于 2^24)。也就是它已经需要 4 个字节:1 个字节的数据推入(PUSH)操作码,加上 3 个字节的数据。

在某些情况下,最小编码可能也需要第五个填充字节,当高度的小端序编码的最高字节恰好设置了其最高比特时(避免将它误读为一个信号比特)。

所以,实际的空间预算很接近于 100 - 4(BIP34)- 34(A_send)= 62 字节,用于 extranonce,而不是 “100 减去 4 字节,还有很多弓箭”。今天当然还有不少空间,但 BIP34 的开销只增不减(从高度 16,777,215 开始,就是 5 字节),并且,我还没搞懂,这到底是对 extranonce 长度的真正限制,还是只是噪音。

marathon-gary:

我不确定 extranonce 的约束会不会成为很大的问题,即使编码区块高度需要更多的字节,尤其是有 BIP323