汇总我们每周系列文章的所有已发布部分,内容涉及在区块高度 709,632 激活 Taproot 的准备工作。

  1. Bech32m 发送支持
  2. Taproot 对单签名是否有意义?
  3. Taproot 描述符
  4. 从 P2WPKH 到单签 P2TR
  5. 我们为什么要等待?
  6. 通过使用学习 Taproot
  7. 多签
    1. 使用多签
    2. 阈值签名
  8. 多签随机数
  9. 签名适配器
    1. 适配器签名的魔法
    2. 多签适配器
  10. PTLCs
    1. HTLC 的隐私问题
    2. PTLC 解决方案
  11. 使用 Taproot 的闪电网络
    1. 闪电网络上的 PTLCs
    2. P2TR 通道
    3. 时间预估
  12. 使用 Taproot 的保险库
  13. 备份与安全方案
  14. 在 Signet 上测试
  15. 仍然需要 Signmessage 协议
  16. 输出关联
  17. 合作始终是一个选项吗?
  18. 趣闻
  19. 未来的共识变化
  20. 激活时会发生什么?
  21. 感谢!

Bech32m 发送支持

最初发表于 Newsletter #154

从预计在 11 月到来的区块高度 709,632 开始,比特币用户将能够安全地接收发送到 taproot 地址的付款。考虑到用户对 taproot 的期待,以及钱包开发者有 5 个月的时间来实现对 taproot 的支持,Optech 预计到时会有数个流行的钱包允许用户在第一时间生成 taproot 地址。

这意味着任何会向用户提供的地址发送比特币的钱包或服务,都需要在区块高度 709,632 前支持发送至 taproot 地址,否则可能会让用户感到困惑并失望。Pay to TapRoot(P2TR)地址使用了 bech32m(参见 BIP350),它与 BIP173 用于 segwit v0 P2WPKH 和 P2WSH 地址的 bech32 算法略有不同。bech32m 在校验和函数中使用 0x2bc830a3 常量,而传统 bech32 则使用 0x01

只需改变这一常量即可为校验 bech32m 校验和提供支持,但在处理现有 P2WPKH 和 P2WSH 地址时仍要使用原始常量。也就是说,代码需要先在不验证校验和的情况下解析地址,判断它是 v0 segwit(bech32)还是 v1+ segwit(bech32m),然后再使用对应的常量来验证校验和。更多示例可参考 bech32#56,它更新了 C、C++、JS 和 Python 的 bech32 参考实现。如果代码已经使用了参考库,可以更新至该仓库的最新版本,但要注意其中部分 API 发生了小幅更改。BIP350 和参考实现提供的测试向量,所有 bech32m 实现都应当进行使用以验证正确性。

虽然在区块高度 709,632 之前向 taproot 地址接收付款并不安全,但向这些地址发送付款对于付款方而言并不会造成任何问题。自 Bitcoin Core 0.19(2019 年 11 月发布)起,Bitcoin Core 就开始支持传播和挖矿包含 taproot 输出的交易。Optech 鼓励各钱包和服务的开发者现在就着手实现对 bech32m taproot 地址付款的支持,而不要等到 taproot 激活后再做准备。

Taproot 对单签名是否有意义?

最初发表于 Newsletter #155

使用 Optech 的 交易大小计算器,我们可以比较不同类型单签名交易的大小。正如预期,使用 P2WPKH 输入和输出的交易远小于使用 P2PKH 输入和输出的交易——但或许令人惊讶的是,P2TR 交易比同等的 P2WPKH 交易略大。

  P2PKH (legacy) P2WPKH (segwit v0) P2TR (taproot/segwit v1)
Output 34 31 43
Input 148 68 57.5
2-in, 2-out tx 374 208.5 211.5

这可能会让人觉得,为了迎接在区块 709,632 激活的 taproot 而在单签名钱包中实现 taproot 花费是得不偿失的,但当我们进一步研究时会发现,对于钱包用户和整个网络而言,使用 P2TR 进行单签名仍然有许多好处。

  • 花费更便宜: 与花费 P2WPKH UTXO 相比,花费单签名 P2TR UTXO 在输入层面上节约了大约 15% 的成本。上表这样过于简单的分析掩盖了一个细节,即花费者无法选择他们被要求支付的地址,所以如果你还停留在 P2WPKH,而其他人都升级到了 P2TR,那么你的 2 入、2 出交易的实际常见大小将会达到 232.5 vbytes——而全部使用 P2TR 的交易仍然只有 211.5 vbytes。

  • 隐私: 虽然当早期采用者切换到新的脚本格式时会失去一些隐私,但用户切换到 taproot 也能立刻获得隐私增强。你的交易在链上可能与正在使用新 LN 通道、更高效的 DLCs、安全的多签、各种巧妙的钱包备份恢复方案或其他上百种全新发展场景的人看起来毫无区别。

    现在就对单签名采用 P2TR 还能让你的钱包在之后升级到多签名、tapscript、LN 支持或其他功能时,不会影响你的现有用户的隐私。UTXO 是在你旧版或新版软件中接收的都无关紧要——这两种 UTXO 在链上看起来没有差别。

  • 更方便硬件签名设备: 自从重新发现了手续费超额支付攻击以来,一些硬件签名设备在没有为该交易输入的每个 UTXO 提供元数据(包含创建该 UTXO 的完整交易中重要部分的副本)的情况下,拒绝为交易签名。这样会极大增加硬件签名器需要执行的最糟糕情况处理量,对主要通过尺寸有限的二维码进行交互的硬件签名器来说尤其棘手。taproot 消除了导致手续费超额支付攻击的漏洞,从而能够显著提高硬件签名器的性能。

  • 更可预测的费率: 适用于 P2PKH 和 P2WPKH UTXO 的 ECDSA 签名大小具有灵活性(参见 Newsletter #3)。由于钱包需要在创建签名前先决定交易的费率,大多数钱包只是默认假设最糟糕的签名大小,并接受在实际生成更小签名时稍微超额支付费率。对于 P2TR,则可以预先明确签名的确切大小,钱包就能可靠地选择精准的费率。

  • 帮助全节点: 比特币系统的整体安全性依赖于有相当比例的比特币用户使用自己的节点验证所有已确认的交易,包括验证你的钱包所创建的交易。taproot 的 schnorr 签名可以被高效地批量验证,在节点赶上之前区块的过程中,CPU 耗时大约可以减少一半。即使你对上面提到的其他优势都不感兴趣,也可以考虑为了那些运行全节点的人而做好使用 taproot 的准备。

Taproot 描述符

最初发表于 Newsletter #156

输出脚本描述符 为钱包提供了一种通用方式,用来存储生成地址所需的信息、有效扫描付款给这些地址的输出,以及之后从这些地址花费。此外,描述符相对紧凑且包含一个基础校验和,这使其在备份地址信息、在不同钱包之间复制或在合作提供多签的多个钱包之间共享时都非常方便。

尽管当前只有少数项目在使用描述符,但它们和相关的 miniscript 项目有潜力显著提升不同钱包和工具之间的互操作性。随着越来越多的用户利用 taproot 带来的好处,通过多签来加强安全性,以及通过备份花费条件来提高恢复能力,这一点将变得愈加重要。

在此之前,需要先对描述符进行更新以适配 taproot。最近合并的 Bitcoin Core #22051 拉取请求正是针对这一需求。该语法设计允许使用单一描述符模板,同时提供使用 P2TR 密钥路径花费和脚本路径花费所需的全部信息。对于简单的单签名,以下描述符就足够了:

tr(<key>)

相同的语法也适用于多签和阈值签名。例如,Alice、Bob 和 Carol 使用 MuSig 聚合它们的密钥,然后支付给 tr(<combined_key>)

出人意料的是,“tr(<key>) 中的 key” 并不会直接是地址中所编码的那个密钥。tr() 描述符遵循了 BIP341 中的安全性建议,使用一个承诺于不可花费脚本树的内部密钥,这就消除了对简单密钥聚合方案(像 MuSig 和 MuSig2 这类更先进的方案不受影响)的一个攻击。

对于脚本路径花费,新增了一种可指定二叉树内容的语法。例如,{ {B,C} , {D,E} } 描述了这样一棵树:

Internal key
    / \
   /   \
  / \ / \
  B C D E

可以将这棵树作为可选的第二个参数传入之前使用的描述符模板。例如,如果 Alice 希望能够通过密钥路径花费,但也允许 Bob、Carol、Dan 和 Edmond 以能够为她生成审计轨迹的脚本路径花费(但不对第三方链上监控暴露),她可以使用如下描述符:

tr( <a_key> , { {pk(<b_key>),pk(<c_key>)} , {pk(<d_key>),pk(<e_key>)} )

上述功能足以让描述符用于 taproot,但拉取请求 #22051 中提到仍有一些可能被添加的功能,用于让描述符更好地完整描述预期的策略:

  • *无效化密钥路径: 某些用户可能希望禁止通过密钥路径花费,从而强制使用脚本路径花费。现在可以在 tr() 第一个参数中使用不可花费的密钥来实现,但能够在描述符本身中记录这一偏好并让它计算出一个保护隐私的不可花费密钥路径将更好。

  • *Tapscript 多签: 对于传统和 v0 segwit,multi()sortedmulti() 描述符支持 OP_CHECKMULTISIG 操作码。为了在 taproot 中实现批量验证,基于脚本的多签在 tapscript 中的处理方式有所不同,因此 tr() 描述符目前需要通过 raw() 脚本来指定任何必需的多签操作码。对 tapscript 版本的 multi()sortedmulti() 进行更新将非常有用。

  • *基于 MuSig 的多签: 在本文前面,我们描述了 Alice、Bob 和 Carol 手动聚合它们的密钥,以使用一个 tr() 描述符。理想情况下,应当能有一个函数允许像 tr(musig(<a_key>, <b_key>, <c_key>)) 这样指定,这样他们就能保留全部初始密钥信息并用它来填充它们协同签名所用 PSBT 中的各字段。

  • *时间锁、哈希锁和点锁: 这些在闪电网络、DLCscoinswaps 以及许多其他协议中使用的强大结构,目前只能通过 raw() 函数来描述。可将它们直接加入描述符是可行的,但也可能会在描述符的姊妹项目 miniscript 中添加对它们的支持。miniscript 整合到 Bitcoin Core 仍在进行中,但我们预期它的创新将和 PSBT、描述符等工具一样,推广到其他钱包中。

钱包并不需要实现描述符就能开始使用 taproot,但那些实现了描述符的,将为自己使用更高级的 taproot 功能奠定更好的基础。

从 P2WPKH 到单签 P2TR

最初发表于 Newsletter #157

对于已经支持接收和使用 v0 segwit P2WPKH 输出的钱包来说,将其升级到用于单签的 v1 segwit P2TR 应该相对容易。以下是主要步骤:

  • 使用新的 BIP32 密钥推导路径: 你不需要修改你的 BIP32 分层确定性 (HD) 代码,并且你的用户也不需要更换种子。1 然而,我们强烈建议你为你的 P2TR 公钥使用新的推导路径(例如由 BIP86 定义);如果你不这样做,当你在 ECDSA 和 schnorr 签名两者中都使用相同密钥时,可能会导致潜在攻击

  • 通过其哈希值调整你的公钥: 尽管在单签场景中技术上并非必须,尤其当你的所有密钥都来自随机选定的 BIP32 种子时,BIP341 建议让你的密钥承诺到一个不可花费的脚本哈希树中。其操作很简单,只需要使用椭圆曲线加法操作,将你的公钥与该公钥哈希得到的曲线点相加即可。遵循这一建议的好处在于,如果你日后添加无脚本的多签支持,或者为 tr() 描述符添加支持,你也可以使用相同的代码。

  • 创建你的地址并进行监控: 使用 bech32m 来创建你的地址。付款将发送到脚本 OP_1 <tweaked_pubkey>。你可以使用与扫描 v0 segwit 地址(如 P2WPKH)相同的方法来扫描支付到该脚本的交易。

  • 创建支出交易: 对于 taproot 来说,所有的非见证字段都与 P2WPKH 相同,因此你无需担心交易序列化的改变。

  • 创建签名消息: 这是对支出交易数据的承诺。大部分数据与为 P2WPKH 交易所签名的内容相同,但字段的顺序已改变,并且有一些额外内容需要签名。实现这一点只需要对各种数据进行序列化和哈希处理,所以编写这部分代码应该相对容易。

  • 对签名消息的哈希进行签名: 生成 schnorr 签名有多种方法。最好的方式是不“自己动手写加密”而是使用你信任的、经过充分审阅的库提供的函数。但如果因某些原因你无法这样做,BIP340 提供了一种算法,如果你已经有可用于制作 ECDSA 签名的原语,那么实现它应该相当简单。当你获得签名后,将其放入输入的见证数据中,然后发送你的支出交易。

即使在 taproot 于区块 709,632 激活之前,你也可以使用 testnet、公用默认 signet 或者 Bitcoin Core 的私有 regtest 模式来测试你的代码。如果你为开源钱包添加了 taproot 支持,我们鼓励你将实现它的拉取请求链接添加到 Bitcoin Wiki 上的 taproot 用法bech32m 采用页面,以便其他开发者可以从你的代码中学习。

我们为什么要等待?

最初发表于 Newsletter #158

本系列之前的文章鼓励钱包和服务开发者立即开始实施 Taproot 升级,以便在 Taproot 激活时准备就绪。但我们也警告不要在区块 709,632 前生成任何 P2TR 地址,否则可能导致服务或用户资金损失。

不建议提前生成地址的原因是,在区块 709,632 之前,任何发送至 P2TR 式输出的资金均可被任何人花费。这些资金将完全无安全保障。但从该区块开始,数千个全节点将开始强制执行 BIP341BIP342(以及关联的 BIP340)的规则。

如果区块链重组能被完全排除,那么在看到最后一个 Taproot 前区块(区块 709,631)后立即生成 P2TR 地址是安全的。但存在对区块链重组的担忧——不仅是意外重组,还包括蓄意制造以窃取早期 P2TR 支付的资金。

设想大量用户希望成为首批接收 P2TR 支付的人。他们在看到区块 709,631 后立即天真地向自己发送资金。2 这些资金在区块 709,632 中是安全的,但可能被创建替代 709,631 区块的矿工窃取。如果发送至 P2TR 输出的资金价值足够大,尝试挖两个区块而非一个可能变得更为有利可图(详见手续费狙击主题)。

因此,在重组风险有效消除前,我们不建议软件或服务生成 P2TR 地址。我们认为等待激活后 144 个区块(约一天)是较为保守的安全边际,可在最小化风险的同时避免显著延迟用户享受 Taproot 优势。

简言之:

  • 709,631: 最后一个允许任何人花费 P2TR 式输出资金的区块
  • 709,632: 首个要求 P2TR 输出必须满足 BIP341BIP342 规则才能被花费的区块
  • 709,776: 钱包可开始为用户提供 P2TR 输出的 Bech32m 接收地址的合理区块

以上均不影响本系列首篇文章的建议——应尽快支持向 Bech32m 地址付款。若有人在您认为安全前请求向 P2TR 地址付款,风险由其自行承担。

通过使用学习 Taproot

最初发表于 Newsletter #159

将近两年前,James Chiang 和 Elichai Turkel 创建了一个开源仓库,其中包含一系列 Jupyter 笔记本,旨在为 Optech 组织的开发者培训提供 Taproot 技术相关内容。在旧金山、纽约和伦敦举办的研讨会收到了积极的反馈,但由于旅行限制,后续的线下研讨会未能如期进行。

自 Jupyter 笔记本发布以来,Taproot 发生了多项变更。然而,Taproot 支持已合并到 Bitcoin Core,这使得这些笔记本可以不再依赖于 Bitcoin Core 的自定义分支。开发者 Elle Mouton 友善地更新了这些笔记本,使其适应所有的更改,使其再次成为快速掌握 Taproot 算法和数据类型的绝佳实践工具。

这些笔记本分为四个部分:

  • 第 0 部分 包含一个帮助您设置环境的笔记本,涵盖椭圆曲线密码学的基础知识,并介绍 BIPs 340341342 中广泛使用的标签哈希。

  • 第 1 部分 指导您创建 Schnorr 签名。掌握这些知识后,您将学习如何使用 MuSig 协议创建多重签名

  • 第 2 部分 带您全面了解 Taproot。首先回顾 Segwit v0 交易的基本原理,然后帮助您创建和发送 Segwit v1(Taproot)交易。在掌握第 1 部分知识后,您将学习如何使用 MuSig 创建并花费 Taproot 输出。随后,您将接触密钥调整(key tweaking)概念,并学习如何利用 Taproot 公钥承载数据承诺。掌握承诺创建后,您将了解 Tapscript——其与传统及 Segwit v0 脚本的区别,以及如何创建 Tapscript 树的承诺。最后,一个简短的笔记本将介绍如何使用 Huffman 编码来创建最优的脚本树。

  • 第 3 部分 提供了一个可选练习,内容是创建一个 Taproot 输出,该输出会随着未花费时间的增加而改变所需的签名数量——在正常情况下提供高效的花费方式,同时在出现问题时提供强大的备份方案。

这些笔记本包含众多相对简单的编程练习,确保您真正掌握所学内容。本专栏作者并非优秀的程序员,但能够在六小时内完成所有笔记本练习,并遗憾没有更早学习这些内容。

多签

最初发表于 Newsletter #160

在撰写本文之前的 1,000 个区块中,11% 的交易输入包含了多签操作码。如果许多创建这些交易的用户和服务将多签操作码切换为无脚本的多签,Taproot 的两个最大和最直接的好处将会显现。

第一个主要好处是交易大小的减少。基于脚本的多签随着更多密钥和签名的需求而增大,但多签则保持为一个恒定的小尺寸。最小的有效多签策略(1-对-2)所需的空间比一个可以涉及成千上万签署者的多签策略还要大。尺寸的减少直接导致了多签用户的手续费减少,同时也间接减少了所有用户的手续费,因为相同数量的已确认交易需求可以通过更小的区块空间得到满足。

展示多签与多签操作码节省的图表

第二个主要好处是隐私的提高。每次使用多签的交易都会在区块链上有明显的记录,观察者可以通过这些记录推测出个别用户的钱包历史和当前余额。例如,在区块 692,039 中,我们不仅可以区分多签交易和单签名交易,还可以区分不同的签名集合大小和多签的阈值。

展示当前区块中见证不可替代性的插图

相比之下,第三方仅查看区块链数据时,无法知道支出者是否使用了多签。当多签用于密钥路径支出时,它与单签名支出无法区分。如果上述区块中的所有单签名和多签都切换为 P2TR 密钥路径支出,只有少数特殊的支出会因其脚本而被区分出来(即便是这些支出,也可能在最好的情况下使用密钥路径支出)。

展示理想情况下可替代的见证如何呈现的插图

使用多签

我们知道有三种专为比特币设计的基于 Schnorr 的多签方案,它们都是 MuSig 系列的一部分:

  • MuSig(也称为 MuSig1),实现起来相对简单,但在签名过程中需要三轮通信。

  • MuSig2,同样实现起来较为简单。它消除了一个通信轮次,并将另一个通信轮次与密钥交换结合。这样可以使用与当前基于脚本的多签类似的签名过程。这确实需要存储额外数据,并且非常小心,确保你的签名软件或硬件不会被误导重复进行某部分签名会话。我们将在下周的 为 Taproot 做准备 栏目中更详细地探讨这种权衡。

  • MuSig-DN(确定性随机数),实现起来复杂得多。参与者之间的通信无法与密钥交换结合,但它的优势在于不会受到重复会话攻击的影响。

所有签名者必须就使用哪种协议达成一致,因此可能会出现网络效应,许多实现选择使用相同的协议。MuSig 提案的作者 建议 由于其相对简单性和高效性,MuSig2 将成为大多数实现的选择。

目前有一个开放的并正在积极开发的 PR,用于向 libsecp256k1-zkp 项目添加 MuSig2 支持。我们预计大多数软件的基本多签工作流将如下所示:

  1. 每个参与者的钱包生成一个 BIP32 xpub,并通过输出脚本描述符或其他方式与所有其他参与者共享(这与当前多签使用的方式相同)。

  2. 任何一个钱包都可以通过将其在某个 BIP32 深度上的公钥与所有其他钱包在同一深度的公钥相结合,生成一个聚合公钥。这个聚合公钥可以用于接收 P2TR 支付。

  3. 当其中一个钱包想要支出资金时,它使用基于 PSBT 的工作流,类似于当前使用基于脚本的多签的流程,但现在需要签署者之间进行两轮通信。在第一轮中,提议者创建未签名交易并包含一对随机生成的随机数。必须确保随机数的生成不是完全确定性的,以避免为不同的签名使用相同的随机数。提议者将包含随机数的 PSBT 发送给其他钱包。

  4. 其他钱包接收 PSBT 并更新其中的随机数,然后将更新后的 PSBT 发送给其他钱包,或发送给为钱包提供信任的协调员。

  5. 当所有钱包都获得所有随机数对后,它们将它们合并为一个单一的随机数。协调员也可以为它们执行此操作。然后,所有钱包更新它们的 PSBT 版本并添加各自的部分签名,将 PSBT 发送给其他钱包或协调员。最后,所有部分签名将合并生成最终签名,并将交易广播。

阈值签名

仅凭 MuSig 系列的多签方案,你只能实现 n 对 n 的签名——每个贡献密钥的参与者必须也贡献一个部分签名以形成最终签名。这在一些当前使用的基于脚本的多签用例中运行良好,例如支出 2-对-2 的闪电网络资金输出,但它与其他流行的策略有所不同,例如许多交易所使用的 2-对-3 多签脚本。

目前,几位开发者正在研究阈值签名方案,它将为 k-对-n 场景带来与多签相同的效率和隐私好处,但在这些方案可用之前,有一个简单的技巧可以使用。

在许多阈值情况下,事先知道哪些参与者最有可能签名。例如,在一个 2-对-3 的场景中,可能已经知道通常 Alice 和 Bob 会共同签名,而 Carol 只有在其他两人都无法签名时才会签名。对于这种情况,主密钥可以使用多签进行 Taproot 密钥路径支出(例如 Alice 和 Bob 之间),而额外的结果(如 Alice 和 Carol,或 Bob 和 Carol)可以使用 OP_CHECKSIG 操作码在 tapscripts 的树状结构中单独分支。

在正常情况下,以上方案与单签名或多签交易具有相同的效率和隐私。在异常情况下,支出仍然按预期工作,并且比在链上发布多签参数更高效和隐私。

尽管希望最小化费用并实现最大隐私的用户最终可能会切换到纯阈值签名方案,但上述方案可能仍会继续使用,因为它为审计员(如果他们知道所有参与者的公钥)提供了关于哪些相应的私钥被用来签名的链上证明。

编辑:关于 MuSig2 的部分文字已更新,以澄清在预共享随机数时需要格外小心,因此预计大多数使用 MuSig2 的常规钱包将在需要时生成新的随机数。我们感谢 #secp256k1 IRC 频道成员分享他们的担忧。

多签随机数

最初发表于 Newsletter #161

在上周的专栏中,我们讨论了多签并通过 MuSig2 举例进行说明。我们所做的描述在技术上是正确的,但有几位参与 MuSig2 的密码学家担心我们建议的使用方法是危险的。我们更新了我们的描述,以解决他们的直接担忧,并开始更深入地研究这一问题。在本文中,我们将探讨我们所学到的,可能是安全实施多重签名的最大挑战:避免重用 nonce。

为了验证比特币中的签名,您需要通过签名、签名的消息(例如交易)、您的公钥和公有 nonce 来填充一个公开已知的方程式。只有在您知道私钥和私有nonce的情况下,才能平衡这个方程式。因此,任何看到该方程式的人都可以认为这个消息和公钥的签名是有效的。

将签名和消息包括在方程式中的动机是显而易见的。公钥是私钥的代替,那么公有 nonce 的作用是什么呢?如果它不存在,方程式中除了您的私钥以外的所有值都是已知的,这意味着我们可以使用基础代数来求解唯一的未知值。但代数无法求解两个未知数,因此 nonce 的私有形式能够保持您的私钥的秘密。正如公钥在签名方程式中是私钥的代替一样,nonce 的公有形式则代替其私有形式。

在这个背景下,nonce 不仅是一次性使用的数字,而且必须仅使用一次。如果您使用相同的 nonce 进行两次不同的签名,那么这两个签名方程式可以合并,nonce 可以被消除,从而有人可以解决唯一剩下的未知数——您的私钥。如果您使用BIP32 标准派生(非硬化派生),这可能是几乎所有多重签名钱包都会使用的方式,那么一旦暴露一个私钥,就意味着该BIP32路径下的所有其他私钥都会被暴露(甚至可能在其他路径中也是如此)。这意味着一个已经收到了比特币的多重签名钱包,如果其中一个签名者重用了一个 nonce,那么该签名者在这个钱包下的所有地址都会被泄露。

单签名钱包,或者使用基于脚本的多重签名的钱包,可以通过一个简单的技巧来避免重用 nonce:他们使得 nonce 依赖于他们签署的消息。如果消息发生任何变化,nonce 也会变化,因此它们不会重用 nonce。

但多重签名不能使用这个技巧。它们要求每个共同签名者不仅贡献一个部分签名,还要贡献一个部分公有 nonce。多个部分公有 nonce 被组合起来生成一个聚合公有 nonce,该 nonce 将与签名的消息一起使用。

这意味着,即使交易保持不变,也不应该多次使用相同的部分 nonce。如果第二次签署时,某个共同签名者改变了他们的部分 nonce(改变了聚合 nonce),您的第二个部分签名实际上就是为一个不同的消息签署的,这会暴露您的私钥。由于对于每个参与方来说,让他们的私有 nonce 依赖于所有其他方的部分公有 nonce 是完全不可能的,因此在多重签名中没有简单的方法来避免nonce重用。

乍一看,这似乎不是一个大问题。只需要让签名者每次签署时生成一个新的随机 nonce。实现起来比听起来要难得多——自 2012 年以来,人们一直在发现依赖生成随机 nonce 的钱包中的比特币丢失漏洞。

但即便钱包能够生成高质量的随机 nonce,它仍然需要确保每个 nonce 只使用一次。这是一个真正的挑战。在我们上周专栏的原始版本中,我们描述了一个MuSig2兼容的冷钱包或硬件签名设备,它会在首次运行时生成大量的 nonce。然后,钱包或设备需要确保每个nonce 从未与多个部分签名一起使用。虽然这听起来简单——每次使用 nonce 时递增计数器——但当软件和硬件可能因偶然原因出现故障,或者受到外部甚至恶意干预时,这可能会变得非常复杂。

也许钱包减少 nonce 重用风险的最简单方法是尽可能缩短 nonce 的存储时间。我们上周的示例建议将 nonce 存储几个月或几年,这不仅为出错提供了大量机会,而且还需要将 nonce 记录到持久化存储介质中,这些介质可能会被备份并恢复,或以其他方式被置于意外状态。使用MuSig2的另一种替代方式是仅在需要时创建 nonce ,例如在接收到 PSBT 时。 nonce 可以存储在易失性内存中,仅在需要时使用,因此在发生意外情况(例如软件崩溃或断电)时,它们会被自动销毁(使其无法重用)。

然而,致力于解决这个问题的密码学家们似乎对原始 MuSig 协议(MuSig1)和 MuSig2 中缺乏万无一失的方法来防止 nonce 重用感到非常担忧。MuSig-DN(确定性 nonce )确实提供了解决方案,但它复杂且速度较慢(一个 alpha 版本在 2.9 GHz 的 Intel i7 处理器上生成 nonce 证明几乎需要一秒钟;我们不知道在16 MHz硬件签名设备上,使用一个处理器不那么先进的设备需要多长时间)。

我们给所有实施多重签名签署的人提供的建议是,在进行任何重大时间或资源投入之前,考虑前往 #secp256k1 IRC 聊天室或比特币密码学家聚集的其他地方,描述您的计划。

签名适配器

最初发表于 Newsletter #162

想象有人提出,如果有人能猜出他最喜欢的一个非常大的数字,他将向某个特定的慈善机构捐赠 1,000 BTC。捐赠者可以通过以下简单的方法实现这一目标:创建一笔支付 1,000 BTC 的未签名交易,然后发布该交易的签名的加密版本,其中最喜欢的数字作为解密密钥。

理论上,任何人只要猜对了这个数字,就可以解密签名并广播交易,从而支付给慈善机构。然而,如果捐赠者使用 AES 等标准加密方案,在解密之前,第三方无法轻松验证该签名是否对该交易有效。因此,任何想投入精力猜测数字的人都必须信任捐赠者的诚意,而不是一个恶作剧者。

让我们把这个问题再扩展一点。第三方 Alice 和 Bob 想要就签名是否会被公布进行下注。他们或许可以要求签名者提供签名的哈希值,并将其用作 HTLC 的哈希值,但这仍然要求信任捐赠者的诚实行为。即使签名最终被公布,捐赠者仍可以通过提供错误的哈希值来破坏 Alice 和 Bob 的合约。

适配器签名的魔法

适配器签名(也常被称为 adaptor signatures一次性可验证加密签名)可以解决这些问题——事实上,它还能解决当今比特币系统中许多实际遇到的问题。虽然适配器签名可以与比特币当前的 ECDSA 签名方案一起使用,但在 BIP340 定义的 Schnorr 签名(用于 Taproot)的实现中,适配器签名的使用会更加私密且无需额外成本。让我们看看,如果使用适配器签名,上述示例会发生怎样的变化。

与之前一样,捐赠者准备了一笔 1,000 BTC 的交易。他们的签名过程与通常方式几乎相同,唯一的不同点是,他们会以两部分生成随机数(nonce):一个真正的随机数(将永远保密),以及他们最喜欢的数字(起初也是保密的,但其他人发现它是安全的)。捐赠者使用这两个值生成一个完整的有效签名,将它们相加作为单个随机数。

BIP340 签名承诺使用随机数的两种形式:一个数值表示(称为 标量),通常只有签名者知道;以及一个椭圆曲线(EC)上的 ,用于公示以支持验证。

捐赠者从其有效签名的承诺部分中减去隐藏的标量。这使得签名变得不完整(因此无效),但允许捐赠者共享(无效的)签名承诺、(有效的)完整随机数的椭圆曲线点,以及(有效的)隐藏数字的椭圆曲线点。这三部分信息共同构成了一个适配器签名

使用 BIP340 签名验证算法的一个小变种,任何人都可以验证该适配器签名是否能通过简单地将隐藏的标量加回当前无效的签名承诺来提供一个有效签名。即使不知道隐藏的数字是什么,这也是可以验证的。简而言之,现在用户可以无需信任地开始猜测隐藏标量的值,确保他们只要猜对,就能获得签名并发送交易。

像所有收到捐赠者适配器签名的人一样,Alice 和 Bob 现在也得到了隐藏数字的椭圆曲线点。同样,他们不知道实际的标量。但请记住,捐赠者只是通过从签名承诺中减去隐藏数字来使签名变得无效,同时仍然让签名承诺包含隐藏数字的椭圆曲线点。Alice 也可以通过类似的方式创建一个无效签名:她可以创建自己的随机数对,在生成(无效的)签名时使用其私有部分,但在签名中承诺使用她的公有随机数与捐赠者适配器签名中的椭圆曲线点的聚合。这将生成一个支付给 Bob 的适配器签名。如果 Bob 知道隐藏的标量,他可以将该适配器签名转换为有效签名,并发送交易,从而赢得赌注。

那么,Bob 如何得知中奖数字?他是否必须等待某个猜对的人发布新闻稿?不需要。请再次回忆,捐赠者发布的适配器签名是他们的实际签名减去标量。当隐藏数字被发现,有人发送 1,000 BTC 交易时,他们必须发布原始(有效的)签名承诺。Bob 可以取该(有效的)签名承诺,并从中减去原始适配器签名中的(无效)签名承诺,以得出标量。然后,他可以使用该标量将 Alice 的适配器签名转换为有效签名。

多签适配器

前一节展示了个体用户如何调整其签名方式以生成适配器签名。此外,多方多签也可以使用相同的技巧。这一点极为重要,因为许多使用适配器签名的场景都需要两方的协作。

例如,在 Alice 和 Bob 进行上述赌注时,他们可以首先将资金存入一个只能由他们两人联合签名的脚本地址。然后,Alice 可以以适配器签名的形式生成她的部分签名;如果 Bob 发现隐藏的数字,他可以将 Alice 的适配器转换为她的有效部分签名,并再提供他的部分签名,以生成完整的签名来花费这些资金。

这使得适配器签名继承了多签的所有优势:它们看起来与单个签名相同,占用的空间也相同,从而最小化手续费并最大化隐私性和可替代性。

在下周的 为 Taproot 做准备 专栏中,我们将探讨适配器签名的一种主要应用场景:点时间锁合约(PTLCs),这是一种对广泛用于闪电网络、币交换以及其他协议中的哈希时间锁合约(HTLCs)的升级改进。

PTLCs

最初发表于 Newsletter #163

上周的专栏中,我们探讨了签名适配器,以及 TaprootSchnorr 签名的激活将如何使适配器的使用更加私密和高效。签名适配器可以在比特币上以多种方式应用,其中最直接受益的用例之一是点时间锁定合约(Point Time Locked Contracts,简称 PTLCs),它可以替代多年来使用的哈希时间锁定合约(HTLCs)。这将带来多个优势,但也伴随着一些挑战。为了理解两者,我们首先从一个简化的 HTLC 示例开始,该示例适用于链下 LN 支付、链上 CoinSwap,或像 Lightning Loop 这样结合链上和链下的混合系统——正是这种灵活性,使得 HTLC 被广泛使用。

Alice 想通过 Bob 向 Carol 支付,但 Alice 和 Carol 都不想信任 Bob。Carol 生成一个随机的前镜像(preimage),并使用 SHA256 算法对其进行哈希。然后,Carol 将哈希值提供给 Alice,并保留前镜像的秘密。Alice 发起支付给 Bob,Bob 可以使用自己的公钥签名加上前镜像来领取资金;或者,在 10 个区块后,Alice 可以使用自己的公钥签名将交易退还给自己。以下是用 Minsc 语言描述的该 HTLC 逻辑

(pk($bob) && sha256($preimage)) || (pk($alice) && older(10))

随后,Bob 可以使用几乎相同的脚本向 Carol 发起支付(可能扣除一些费用),但角色相应调整,并且退款超时更短:

(pk($carol) && sha256($preimage)) || (pk($bob) && older(5))

现在,Carol 可以在 5 个区块内使用前镜像领取来自 Bob 的付款,这会将前镜像暴露给 Bob,使得 Bob 也能在 5 个区块内使用它向 Alice 领取付款。

HTLC 的隐私问题

如果上述脚本在链上发布,由于相同的哈希和前镜像被重复使用,观察者可以立即看出 A 通过 B 向 C 付款。这对于同链和跨链的 CoinSwap 可能是个重大问题。不那么明显的是,这对 LN 等链下路由协议也是个问题。如果一个路径较长的支付中,有人控制多个跳数,他们可以通过检测相同的哈希和前镜像的重复使用来识别哪些节点是路由节点,从而推测出其余节点很可能是支付方或接收方。这是 可链接性问题(linkability problem)的一个组成部分,而这可能是 LN 目前最大的隐私弱点。

HTLC 可链接性问题示意图

虽然多路径支付(MPP)在一定程度上缓解了 LN 付款金额的可链接性问题,但它可能会加剧哈希可链接性问题,因为它给了监听节点更多机会来关联哈希值。

HTLC 的另一个问题是,任何需要链上执行的脚本都会与普通的支付脚本明显不同。这使得监测者更容易识别使用模式,并可能有效推测特定用户的信息。

PTLC 解决方案

在前面的 Minsc 脚本中,我们使用了一个函数,只有在传入一个预先选择的特定值(前镜像)时,该函数才会返回 true。而签名适配器(signature adaptors) 也有类似的特性——它们只有在传入一个特定值(标量)时,才能转换成有效签名。如果暂时忽略多重签名,我们可以将 HTLC 脚本转换为以下 PTLC 形式:

(pk($bob) && pk($alice_adaptor)) || (pk($alice) && older(10))
(pk($carol) && pk($bob_adaptor)) || (pk($bob) && older(5))

简单来说,Carol 给 Alice 一个椭圆曲线(EC)点,它对应一个隐藏的标量。Alice 使用该点和她选择的公钥创建一个签名适配器并交给 Bob;Bob 再使用相同的点和自己选择的公钥创建另一个适配器交给 Carol。Carol 通过转换 Bob 的适配器为有效签名来揭示标量,从而领取 Bob 的资金。随后,Bob 从 Carol 的有效签名中恢复该标量,并使用它转换 Alice 的适配器为有效签名,以领取 Alice 的资金。

这解决了链上监测的可链接性问题,因为区块链上展示的只是不同公钥对应的有效签名。第三方无法知道是否使用了适配器签名,更无法得知适配器的标量值。

然而,上述流程并不能防止参与路由的监听节点关联支付。如果所有支付都基于相同的标量,它们的可链接性就与使用哈希锁和前镜像一样高。为了解决这个问题,每个路由节点可以选择自己的标量,并在支付通过该节点时移除相应的点。我们修改示例如下:

和之前一样,Carol 给 Alice 一个点,但这次 Alice 还向 Bob 请求一个点。Alice 构造的适配器包含 Carol 的点和 Bob 的点的聚合。Bob 知道自己的点,因此可以从 Alice 传来的适配器中移除它。这样,Bob 得到的结果(他不知道的是,这实际上只是 Alice 从 Carol 那里获得的点),用于创建他给 Carol 的适配器。Carol 知道最终的标量,所以可以转换 Bob 的适配器为有效签名。Bob 从 Carol 的签名中恢复 Carol 的标量,并结合自己的标量转换 Alice 的适配器为有效签名。

在 Alice→Bob 和 Bob→Carol 这两个跳数中,使用了不同的 EC 点和标量,消除了可链接性。扩展到更长的路径后,我们可以看到隐私性的改进:

PTLC 取消可链接性示意图

正如上周提到的,Schnorr 签名使得将适配器签名与多重签名结合变得简单。对于一般的 PTLC,这使得链上的脚本可以进一步简化为:

pk($bob_with_alice_adaptor) || (pk($alice) && older(10))
pk($carol_with_bob_adaptor) || (pk($bob)   && older(5) )

在 Taproot 方案下,左分支可以成为密钥路径(keypath),右分支可以成为 Tapleaf。如果支付成功路由,Bob 和 Carol 可以在链上结算,而无需对手方进一步配合,从而使此类路由支付与单签支付、普通多重签名支付和合作解决的合约难以区分,同时还能最大化节省区块空间。如果需要执行退款条件,这种方式仍然相当高效,并具有良好的隐私性——pk(x) && older(n) 代码与降级多签强制持币等多种可能的脚本难以区分。

在下周的专栏中,我们将邀请一位我们最喜爱的 LN 开发者撰写客座文章,讨论 LN 采用密钥路径支付、多重签名、PTLCs 以及 Taproot 启用的其他特性的必要变更。

使用 Taproot 的闪电网络

最初发表于 Newsletter #164

ZmnSCPxj,闪电网络协议开发者

本文将探讨 Taproot 为闪电网络带来的两大隐私特性:

  • 闪电网络上的 PTLCs
  • P2TR 通道

闪电网络上的 PTLCs

PTLC 可实现多项功能,其中对闪电网络而言,最大优势在于无需路径随机化即可实现支付解关联3在单路径或多路径支付中,每个节点均可获得用于调整转发 PTLC 的特定参数,实现支付解关联,此举可消除各转发节点通过唯一哈希值关联具体支付的可能性。

需明确,PTLC 并非隐私万能解。若监控节点观察到特定时间锁和金额的支付转发后,短期内发现另一节点转发具有更短时间锁稍小金额的支付,这些事件极可能为同一支付路径的组成部分(即便无法通过哈希值唯一标识进行关联)。然而,变更带来以下优势:

  • 分析难度提升:监控节点依据的关联概率降低,其信息价值相应减少。
  • 多路径支付的解关联增强:不同路径间的时间锁与金额关联性大幅减弱,且若闪电网络持续发展,海量支付将削弱时序关联的有效性。
  • 成本未增加:相较于 HTLC,PTLC 无需额外开销(甚至可能因多签效率优化稍有节约)。

理论而言,无需关闭现有通道即可通过链下交易将预-Taproot 通道升级至支持 PTLC。现有通道可通过将非 Taproot 资金输出转移至含 PTLC 的 Taproot 输出实现兼容。因此,用户无需承担额外成本,仅需节点及其通道对端升级软件即可支持 PTLC。

但 PTLC 的实际使用需支付路径中所有节点均支持该协议。这意味着需足够多节点完成升级后方可广泛采用。这些节点未必需支持同一 PTLC 协议(允许存在多个协议),但均须至少支持一种。协议多样化将增加维护负担,开发者期望尽量减少协议数量(理想状态为单一协议)。

P2TR 通道

提升基础层与闪电网络层解关联的方案之一是未公开通道——此类通道不在闪电网络的 gossip 协议中广播。

但当前预-Taproot 的比特币网络中,所有 2-2 多签脚本均需明示编写。闪电网络作为 2-2 多签的最大用户,其通道的关闭交易极易被区块浏览器识别为闪电网络的链上活动,进而被追溯资金流向。任何新生成的 P2WSH 输出极可能为另一未公开通道。因此,未公开通道一旦关闭,仍存在链上识别的可能(伴随误判率)。

Taproot 借助 schnorr 签名使 n-of-n 多签交易与 1-of-1 单签交易在链上表现无异。经技术优化后,k-of-n 多签交易亦可实现等价匿名性。因此,我们可采用 Taproot 地址(即 P2TR 通道)作为闪电通道的链上基础,提升未公开通道的链上隐私4

此(微小)隐私提升同样惠及公开通道。公开通道仅在存续期广播,监控者无法获取历史通道信息。若需追踪所有公开通道,需自行存储全部数据,无法依赖”归档”节点。

此外,Taproot 密钥路径交易比现有闪电网络 P2WSH 交易体积减少 38.5 vbytes(40%)。但需注意,现有 pre-taproot 通道无法升级至 P2TR 通道,因现有通道采用 P2WSH 2-2 模式,必须关闭后重新开启 P2TR 通道。

理论上,资金输出形式仅关乎通道双方节点。其他节点无需关心通道保证金的技术细节。但公开通道需通过 gossip 网络广播。节点收到通道信息后,将查询其信任的比特币全节点验证资金 UTXO 的存在性及地址正确性。地址验证机制可抵御垃圾通道的传播——需真实资金支撑才能发布通道信息。因此实践中,P2TR 通道仍需一定程度的远程兼容性,否则发送方将因无法验证存在性而忽略此类通道。

时间预估

在去中心化开源项目中,最佳时间预测法为参考历史类似功能的开发周期。近期重大特性中,与闪电网络 PTLC 复杂度相当的是 dual funding 协议。Lisa Neigut 在 BOLTs #524 中提出初始方案后,历时两年半完成首个主网 dual funding 通道。鉴于 PTLC 需全网路径节点兼容(包括接收方),预估在具体协议提案后需三年零九个月实现广泛采用。

P2TR 通道虽仅需两节点支持,但其收益较低,故开发优先级受限。多数开发者将优先实现 PTLC 支持,预计 P2TR 通道的开发将在 SIGHASH_ANYPREVOUT 或 Decker-Russell-Osuntokun(Eltoo)方案落地后展开。

使用 Taproot 的保险库

最初发表于 Newsletter #165

Antoine PoinsotRevault 开发者

比特币保险库是一种需要两笔连续交易才能使用户从钱包中支出资金的合约。已经提出了许多此类协议(单方或多方,有或没有契约),因此我们将重点讨论它们的共同点。

与通过单一链上交易执行多次支付的批量支付相反,保险库使用多笔交易来执行一次支付。第一笔交易,即 unvault,支付给:

  1. 在相对时间锁后的一组公钥,或
  2. 没有任何时间锁的单个公钥。

第一种支出路径是主路径,预计将与“热”密钥一起使用。第二种支出路径允许进行取消交易(有时称为回收恢复重新保险库化交易)。

因此,比特币保险库与 Taproot 的洞察相反,后者认为大多数合约都有一个合作签名的“顺利路径”(争议路径通常包含时间锁)。比特币保险库恰恰相反。支出 交易必须使用 Taproot 脚本发送路径,因为它受到相对时间锁的限制5,而 取消 交易理论上可以使用密钥支出路径。

由于多方保险库在实践中已经需要大量交互,它们理论上可以受益于通过 BIP340 实现的交互式多签名门限签名方案,例如 Musig2。然而,这些方案也带来了新的安全挑战。由于保险库协议旨在用于冷存储,设计选择更为保守,因此保险库可能会是最后一个使用这些新技术的协议。

通过切换到 Taproot,保险库还可以受益于隐私和效率的轻微改进,得益于使用梅尔克分支和更短的 BIP340 签名(尤其是对于多方签名)。例如,在一个包含 6 个“冷”密钥和 3 个“活跃”密钥(门限为 2)的多方设置中,unvault 输出脚本可以表示为深度为 2 的 Taproot,叶子如下:

  • <X> CSV DROP <active key 1> CHECKSIG <active key 2> CHECKSIGADD 2 EQUAL
  • <X> CSV DROP <active key 2> CHECKSIG <active key 3> CHECKSIGADD 2 EQUAL
  • <X> CSV DROP <active key 3> CHECKSIG <active key 1> CHECKSIGADD 2 EQUAL
  • <cold key 1> CHECKSIG <cold key 2> CHECKSIGADD <cold key 3> CHECKSIGADD <cold key 4> CHECKSIGADD <cold key 5> CHECKSIGADD <cold key 6> CHECKSIGADD 6 EQUAL

在 Taproot 中,只需要揭示用于支出输出的叶子,因此交易的重量显著小于等效的 P2WSH 脚本:

IF
  6 <cold key 1> <cold key 2> <cold key 3> <cold key 4> <cold key 5> <cold key 6> 6 CHECKMULTISIG
ELSE
  <X> CSV DROP
  2 <active key 1> <active key 2> <active key 3> 3 CHECKMULTISIG
ENDIF

尽管在成功支出时撤销分支可以被隐藏(如果使用多签门限,它的存在和参与者的数量也会被模糊化),但隐私提升是有限的,因为保险库的使用模式在链上将是显而易见的。

最后,像大多数预签名交易协议一样,保险库协议将极大受益于基于 Taproot 的进一步比特币升级,例如 BIP118SIGHASH_ANYPREVOUT。尽管这需要进一步的谨慎和协议调整,ANYPREVOUTANYPREVOUTANYSCRIPT将使取消签名可重新绑定,这将大大减少交互性并允许 0(1) 的签名存储。这对 Revault 协议 中的紧急签名尤为有趣,因为它将大大减少 DoS 攻击面。通过在输出中使用ANYPREVOUTANYSCRIPT签名,您实际上是在创建一个契约,通过限制该交易支出此币时如何创建其输出。未来更具可定制性的签名哈希将允许更灵活的限制。

备份与安全方案

最初发表于 Newsletter #166

In last week’s column, Antoine Poinsot described how taproot can make vault-style coin backup and security schemes more private and fee efficient. In this week’s column, we’ll look at several other backup and security schemes that are improved by converting to taproot.

  • Simple 2-of-3: as mentioned in a previous week, it’s easy to use a combination of multisignatures and scriptpath spends to create a 2-of-3 spending policy that’s normally just as efficient onchain as a single-sig spend and which is much more private than current P2SH and P2WSH multisigs. It’s still fairly efficient and private in the abnormal cases as well. This makes taproot great for upgrading your security from a single-signer wallet to a multi-signer policy.

    We expect future techniques for threshold signatures to further improve 2-of-3 and other k-of-n cases.

  • Degrading multisignatures: one of the exercises in the Optech Taproot Workshop allows you to experiment with creating a taproot script that can be spent at any time by three keys, or after three days with two of the original keys, or after ten days with only one of the original keys. (That exercise also uses backup keys, but we’ll cover that separately in the next point.) Tweaking the time parameters and the key settings provides you with a flexible and powerful backup construct.

    For example, imagine you can normally spend using a combination of your laptop, mobile phone, and a hardware signing device. If one of those becomes unavailable, you can wait a month to be able to spend with the remaining two devices. If two devices become unavailable, you can spend using just one after six months.

    In the normal case of using all three devices, your onchain script is maximally efficient and private. In the other cases, it’s a bit less efficient but may still be reasonably private (your script and its tree depth will look similar to the scripts and depths used in many other contracts).

  • Social recovery for backups and security: the example above is great at protecting you if one of your devices gets stolen by an attacker, but what happens if two of your devices are stolen? Also, if you frequently use your wallet, do you really want to wait even a month before you can start spending again after losing a device?

    Taproot makes it easy, cheap, and private to add a social element to your backups. In addition to the scripts in the previous example, you can also allow immediate spending of your bitcoins with two of your devices plus signatures from two of your friends or family members. Or immediate spending with only a single one of your keys plus signatures from five people you trust. (A similar non-social version of this would simply be using extra devices or seed phrases you have stored in secure locations.)

  • Combining time and social thresholds for inheritance: combining the techniques above, you can allow someone or a group of people to recover your funds in case you suddenly die or become incapacitated. For example, if you haven’t moved your bitcoins for six months, you can allow your lawyer and any three of your five most trusted relatives to spend your coins. If you normally move your bitcoins every six months anyway, this inheritance preparation has no added onchain cost for as long as you live and is completely private from outside observers. You can even keep the transactions you make private from your lawyer and family as long as you have a reliable way for them to learn your wallet’s extended public key (xpub) after your death.

    Please note that making it possible for your heirs’ to spend your bitcoins doesn’t mean that they’ll be able to spend those coins legally. We recommend that anyone planning to pass on Bitcoins read Cryptoasset Inheritance Planning by Pamela Morgan (physical book and DRM’d ebook or DRM-free ebook) and use its information to discuss details with a local expert in estate planning.

  • Compromise detection: an idea proposed prior to the invention of taproot is to put a key controlling some amount of bitcoin on all of the devices you care about as a way of detecting when the device has been compromised. If the amount of bitcoin is large enough, the attacker will probably spend it to themselves for the immediate gain rather than wait to use their illicit access in a long-term attack that might cause you more overall harm.

    A problem with this approach is that you want to make the amount of bitcoin offered large enough to entice the attacker but you don’t want to put large amounts of bitcoin on every one of your devices—you’d prefer to offer only one large bounty. However, if you were to put the same key on every device, the attacker transaction spending the bitcoin wouldn’t reveal which device was compromised. Taproot makes it easy to put a different key with a different scriptpath on every device. Any one of those keys will be able to spend all the funds controlled by that address, but it can also uniquely identify to you which device was compromised.

在 Signet 上测试

最初发表于 Newsletter #167

Although you can’t safely use taproot before block 709,632 on mainnet, you can use taproot today with either testnet or signet. Compared to creating a local test network with Bitcoin Core’s regtest mode, as done in the Optech taproot workbooks, using testnet or signet makes it easier to test how your wallet interacts with other people’s wallets.

In this post, we’ll receive and spend a taproot transaction using Bitcoin Core’s built-in wallet on signet. You should be able to adapt these instructions for testing receives and spends between your own wallet and Bitcoin Core.

Although it’s technically possible to receive and spend taproot transactions using the built-in wallet in Bitcoin Core 22.0, we recommend that you instead build Bitcoin Core pull request #22364, which makes taproot the default for descriptor wallets. Once built, start signet:

$ bitcoind -signet -daemon

If this is your first time using signet, you’ll need to sync its block chain. That currently includes less than 200 MB of data and can finish syncing in as little as a minute. You can monitor sync progress using the getblockchaininfo RPC. After syncing, create a descriptor wallet:

$ bitcoin-cli -signet -named createwallet wallet_name=p4tr descriptors=true load_on_startup=true
{
  "name": "p4tr",
  "warning": "Wallet is an experimental descriptor wallet"
}

Now you can create a bech32m address:

$ bitcoin-cli -named -signet getnewaddress address_type=bech32m
tb1p6h5fuzmnvpdthf5shf0qqjzwy7wsqc5rhmgq2ks9xrak4ry6mtrscsqvzp

With this address, you can request funds from the signet faucet. You’ll then need to wait for a confirmation, which will take the same variable amount of time you’d expect on mainnet (typically up to 30 minutes, but sometimes longer). If you look at the transaction, you’ll notice the P2TR script you created.

$ bitcoin-cli -signet getrawtransaction 688f8c792a7b3d9cb46b95bfa5b10fe458617b758fe4100c5a1b9536bedae4cd true | jq .vout[0]
{
  "value": 0.001,
  "n": 0,
  "scriptPubKey": {
    "asm": "1 d5e89e0b73605abba690ba5e00484e279d006283bed0055a0530fb6a8c9adac7",
    "hex": "5120d5e89e0b73605abba690ba5e00484e279d006283bed0055a0530fb6a8c9adac7",
    "address": "tb1p6h5fuzmnvpdthf5shf0qqjzwy7wsqc5rhmgq2ks9xrak4ry6mtrscsqvzp",
    "type": "witness_v1_taproot"
  }
}

You can then create a second bech32m address and send the funds there to test spending.

$ bitcoin-cli -named -signet getnewaddress address_type=bech32m
tb1p53qvqxja52ge4a7dlcng6qsqggdd85fydxs4f5s3s4ndd2yrn6ns0r6uhx
$ bitcoin-cli -named -signet sendtoaddress address=tb1p53qvqxja52ge4a7dlcng6qsqggdd85fydxs4f5s3s4ndd2yrn6ns0r6uhx amount=0.00099
24083fdac05edc9dbe0bb836272601c8893e705a2b046f97193550a30d880a0c

For this spend, we can look at one of the inputs and see that its witness contains nothing but a single 64-byte signature. That’s smaller in vbytes than the witness which would’ve been required if this was a P2WPKH spend or any other type of older Bitcoin spend.

$ bitcoin-cli -signet getrawtransaction 24083fdac05edc9dbe0bb836272601c8893e705a2b046f97193550a30d880a0c true | jq .vin[0]
{
  "txid": "bd6dbd2271a95bce8a806288a751a33fc4cf2c336e52a5b98a5ded432229b6f8",
  "vout": 0,
  "scriptSig": {
    "asm": "",
    "hex": ""
  },
  "txinwitness": [
    "2a926abbc29fba46e0ba9bca45e1e747486dec748df1e07ee8d887e2532eb48e0b0bff511005eeccfe770c0c1bf880d0d06cb42861212832c5f01f7e6c40c3ce"
  ],
  "sequence": 4294967294
}

By playing around with the above commands, you should find it easy to receive and spend money using taproot with any wallet that supports signet.

仍然需要 Signmessage 协议

最初发表于 Newsletter #168

Since the activation of segwit over four years ago, there’s been no widely accepted way to create signed text messages for bech32 or bech32m addresses. Arguably, that means we can now assume that widespread message signing support must not be very important to users or developers, otherwise more work would’ve been dedicated to it. But it still feels like Bitcoin wallet software has regressed since the days when everyone used legacy addresses and could easily trade signed messages.

The generic signmessage solution we wrote about two years ago in our bech32 spending support series has floundered, not even being adopted by Bitcoin Core despite occasional updates of its protocol documentation, BIP322 (see Newsletters #118 and #130). Despite that, we’re unaware of any better alternative, and so BIP322 should still be the preferred choice of any developer who wants to add signmessage support to their P2TR wallet.

If implemented, generic signmessage will allow signing messages for P2TR outputs that are truly single-sig, which use multisignatures, or which use any tapscript. It will also provide backwards compatibility with all legacy and bech32 addresses as well as forward compatibility with the types of changes currently envisioned for the near future (some of which we’ll preview in a future preparing for taproot column). Applications with access to the full UTXO set (e.g. via a full node) can also use BIP322 to generate and validate reserve proofs, providing evidence that the signer controlled a certain amount of bitcoin at a certain time.

It should be very easy to implement support for creating generic signed messages. BIP322 uses a technique called virtual transactions. A first virtual transaction is created to be deliberately invalid by attempting to spend from a non-existent previous transaction (one whose txid is all zeroes). This first transaction pays the address (script) the user wants to sign for and contains a hash commitment to the desired message. A second transaction spends the output of the first transaction—if the signatures and other data for that spend could be a valid transaction, then the message is considered signed (although the second virtual transaction still can’t be included onchain because it spends from an invalid previous transaction).

Verifying generic signed messages is harder for many wallets. To be able to fully verify any BIP322 message requires implementing essentially all of Bitcoin’s consensus rules. Most wallets don’t do that, so BIP322 allows them to return an “inconclusive” state when they can’t fully verify a script. In practice, and especially with taproot’s encouragement of keypath spends, that may be rare. Any wallet that implements just a few of the most popular script types will be able to verify signed messages for over 99% of all UTXOs.

Generic signmessage support would be a useful addition to Bitcoin. Although we can’t ignore the lack of attention paid to it in the past several years, we do encourage wallet developers reading this to consider adding experimental support for it to your programs. It’s an easy way to give users back a feature they’ve been missing for several years now. If you are either a developer working on BIP322 or related reserve proof implementation or a service provider that would find such features useful, feel free to reach out to info@bitcoinops.org to coordinate efforts.

输出关联

最初发表于 Newsletter #169

After taproot activates, users will begin receiving payments to P2TR outputs. Later, they’ll spend those outputs. In some cases, they’ll make payments to non-P2TR outputs but will still return their change to themselves using a P2TR change output.

Example transaction P2TR -> {P2WPKH, P2TR}

It’s easy for an expert or an algorithm observing such a transaction to reasonably infer that the P2TR output is the user’s own change output, making the other output the payment output. This isn’t guaranteed to be true, but it is the most likely explanation.

Some have argued that the many privacy benefits of taproot should be ignored because of this possible temporary decrease in privacy during the transition of wallets to P2TR. Many experts have called that an unwarranted overreaction. We agree and can also offer a few additional counterpoints to consider:

  • Other metadata: transactions may contain other metadata that reveals which outputs are change and which are payments. One of the most concerning is the large percentage of outputs that currently reuse addresses, significantly reducing privacy for both the spenders and receivers involved in those transactions. For as long as those problems persist, it seems foolish not to proceed with significant privacy upgrades for users of wallets and services that implement best practices.

  • Output script matching: Bitcoin Core’s built in wallet defaults to using a segwit change output if any of the payment output types are also segwit. Otherwise, it uses the default change address type. For example, when paying a P2PKH output, a P2PKH change output might be used; for a P2WPKH output, P2WPKH change is used. As described in Newsletter #155, after taproot activation Bitcoin Core will begin to opportunistically use P2TR change outputs when any other output in the same transaction is P2TR. This can minimize any increase in change identifiability during the transitional period.

  • Request upgrades: with P2TR, we have an opportunity for the first time in Bitcoin’s history to get everyone using the same type of output script no matter their security requirements, and also to frequently use indistinguishable inputs, which significantly improves privacy. If you want to see a meaningful increase in Bitcoin privacy, you can ask the users and services you pay to provide taproot support (and also to stop reusing addresses, if applicable). If both you and they upgrade, then change outputs become harder to identify and we also get all of taproot’s other amazing privacy benefits.

合作始终是一个选项吗?

最初发表于 Newsletter #170

The original taproot proposal by Gregory Maxwell suggested an interesting principle for contract design:

“It is almost always the case that interesting scripts have a logical top level branch which allows satisfaction of the contract with nothing other than a signature by all parties. Other branches would only be used where some participant is failing to cooperate. More strongly stated, I believe that any contract with a fixed finite participant set upfront can be, and should be, represented as an OR between an N-of-N and whatever more complex contract you might want to represent.” (emphasis in original)

Since then, experts have debated the universality of this principle, with two possible exceptions we’re aware of being focused on timelocks:

  • Consensus augmented self-control: some people have used timelocks to prevent themselves from spending their own bitcoins for a period of time. The timelock requirement seems to suggest that more than a signature is required, but a few criticisms have been raised:

    • Someone truly desperate to spend their timelocked bitcoins can take out a loan, perhaps secured by some other asset. This undermines the utility of this self contract.

    • In addition to the consensus-enforced scriptpath timelock, the user can allow keypath spending between their key and the key of a third party who only signs when the timelock has expired. This is not only more efficient, but it also allows implementing a more flexible spending policy such as providing the user the ability to sell any forkcoins they receive or to work with a third party who will allow them to spend early in case of major life changes or price appreciations.

  • Vaults: as mentioned in Antoine Poinsot’s column here a few weeks ago, vaults also use timelocks extensively to help protect funds, which seems “contrary to the insight of taproot that most contracts have a happy path where all participants collaborate with a signature.” Others have argued that there’s no case where the vault user wouldn’t want an option to escape the vault’s conditions through a keypath spend, and that because it costs nothing to add a keypath option to a contract created for scriptpaths, it would be strictly superior to enable a keypath.

The argument against always providing a keypath option seems to be that there are cases even when all the signers acting together don’t trust themselves. They instead trust other people—the operators of economic full nodes who enforce Bitcoin’s consensus rules—to enforce restrictions on the signers spending ability which the signers are unwilling to enforce themselves.

The counterpoint is that, at least purely in theory, you can create a keypath spend between the regular signers and all those economic full node operators to obtain the same security. More practically, there’s probably some subset or alternative set of those node operators who can be added to your keypath multisig set who will enforce the policy you want, if they’re available (and, if they aren’t, you’ve lost nothing since you can still use the scriptpath spend).

Theory aside, we recommend taking some extra time to consider whether there’s an opportunity to use a keypath spend in a taproot-based contract even when it doesn’t seem like an option.

趣闻

最初发表于 Newsletter #171

  • What is a taproot? Wikipedia says, “A taproot is a large, central, and dominant root from which other roots sprout laterally. Typically a taproot is somewhat straight and very thick, is tapering in shape, and grows directly downward. In some plants, such as the carrot, the taproot is a storage organ so well developed that it has been cultivated as a vegetable.”

    How does this apply to Bitcoin?

    • “I always assumed the origin of the name was ‘taps into the Merkle root’, but I don’t actually know what Gregory Maxwell’s thinking was.” —Pieter Wuille (source)

    • “I originally had to look the word up; but I took it as the key path being the ‘taproot’ because that’s the tasty one that you make carrot soup out of, and the merklized scripts would be the other lesser roots that you hope to ignore.” —Anthony Towns (source)

    • “The name originated in a visualization of a tree with a thick central truck like a dandelion taproot—the technique is mostly useful because of the assumption that there is one high probability path and the rest is fuzzy stragglers, and I thought it was a good one because of the punny fact that it verifies script-path spends by tapping into the hidden commitment in the root.

      […] Alas, calling the hash tree with the sorted interior nodes a ‘myrtle tree’ didn’t catch on. (Myrtle tree because the set of policies with an equal hash root are ones whos ordering differs by a permutation which can be defined by a t-function, and Myrtle is the family which includes melaleuca, the tea-tree, and it sounds like ‘merkle’. :p )” —Gregory Maxwell (source)

  • Schnorr signatures predate ECDSA: we talk about schnorr signatures as an upgrade on Bitcoin’s original ECDSA signatures because they make it easier to implement various cryptographic tricks, but the schnorr signature algorithm predates the DSA algorithm that ECDSA is based upon. Indeed, DSA was created in part to circumvent Claus Peter Schnorr’s patent on schnorr signatures but Schnorr still claimed “[my] patents apply to various implementations of discrete log signatures of that sorts and hence covers the use of Nyberg-Rueppel and DSA signatures in these instances.” No court is known to have supported Schnorr’s claim and his patent expired by 2011.

  • Unsure what name to use: although it didn’t work out, there was a suggestion early in the development of adapting schnorr signatures for Bitcoin that Claus Peter Schnorr’s name shouldn’t be used in association with them because his patent on them prevented the widespread use of a valuable cryptographic technique for over 20 years. Pieter Wuille writes, “we did consider calling BIP340 ‘DLS’ for ‘Discrete Logarithm Signatures’, but I think we eventually didn’t go through with that because the name Schnorr was already so much talked about.”

  • Schnorr signatures for twisted Edwards curves: an application of schnorr signatures using elliptic curves was published in 2011. The scheme, EdDSA, is now the basis of several standards. Although not used in Bitcoin consensus, references to it in the context of other systems can be found in many of the Bitcoin repositories tracked by Optech.

  • Pay to contract: Ilja Gerhardt and Timo Hanke created a protocol, presented by Hanke at the 2013 San Jose Bitcoin conference, for allowing a payment to commit to the hash of its contract. Anyone with a copy of the contract, and the nonce used to avoid certain attacks, can verify the commitment—but to anyone else the payment looks like any other Bitcoin payment.

    A slight improvement to this pay-to-contract (P2C) protocol was included in the 2014 paper about sidechains, where the commitment also includes the original public key to pay. Taproot uses this same construction but, instead of committing to the terms of an offchain contract, the output creator commits to consensus-enforced terms chosen by the receiver for how they can spend the received bitcoins onchain.

  • A Good Morning: the idea to use P2C so that payments to scripts can look identical onchain to paying public keys was invented in Los Altos, California, at the diner “A Good Morning” on 22 January 2018. Pieter Wuille writes that the idea was developed by Andrew Poelstra and Gregory Maxwell “while I briefly left the table… !$%@” [sic].

  • 2.5 years in 1.5 days: choosing the optimal constant for bech32m required about 2.5 years of CPU time, which was performed in just 1.5 days mostly using a CPU cluster belonging to Gregory Maxwell.

We thank Anthony Towns, Gregory Maxwell, Jonas Nick, Pieter Wuille, and Tim Ruffing for enjoyable conversations related to this column. Any errors are the author’s.

未来的共识变化

最初发表于 Newsletter #172

As taproot nears activation at block 709,632, we can start to look forward to some of the consensus changes that developers have previously expressed the desire to build on top of taproot.

  • Cross-input signature aggregation: schnorr signatures make it easy for owners of several distinct public and private key pairs to create a single signature that proves all of the key owners cooperated in creating the signature. With a future consensus change, this may allow a transaction to contain a single signature which proves the owners of all the UTXOs being spent in that transaction authorized the spend. This will save about 16 vbytes per keypath spend after the first input, providing significant savings for consolidation and coinjoins. It could even make coinjoin-based spending cheaper than spending by yourself, providing a mild incentive to use more private spending.

  • SIGHASH_ANYPREVOUT: every normal Bitcoin transaction includes one or more inputs, and each of those inputs references the output of a previous transaction, using its txid. That reference tells full verification nodes like Bitcoin Core how much money the transaction can spend and what conditions need to be fulfilled to prove the spend was authorized. All ways of generating signatures for Bitcoin transactions, both with and without taproot, either commit to the txids in the prevouts or don’t commit to the prevouts at all.

    That’s a problem for multiuser protocols that don’t want to use a precise pre-arranged series of transactions. If any user can skip a particular transaction, or change any detail of any transaction besides its witness data, that will change any later transaction’s txid. Changing the txid invalidates any signatures previously created for later transactions. This forces offchain protocols to implement mechanisms (such as LN-penalty) that penalize any user who submits an older transaction.

    SIGHASH_ANYPREVOUT can eliminate this problem by allowing a signature to skip committing to the prevout txid. Depending on other flags used, it will still commit to other details about the prevout and the transaction (such as amount and script), but it will no longer matter what txid is used for the previous transaction. This will make it possible to implement both the eltoo layer for LN and improvements in vaults and other contract protocols.

  • Delegation and generalization: after you create a script (taproot or otherwise), there’s almost no way for you to delegate to additional people the ability to spend from that script short of giving them your private key (which can be extremely dangerous when using BIP32 wallets). Additionally, taproot could be made more affordable for users who want to use a keypath spend plus just a small number of script-based conditions. Several methods for enhancing taproot by generalizing it and providing signer delegation have been proposed:

    • Graftroot: proposed shortly after the introduction of the idea for taproot, graftroot would give an extra feature to anyone capable of making a taproot keypath spend. Instead of directly spending their funds, the keypath signers could instead sign a script that described new conditions under which the funds could be spent, delegating spending authority to anyone capable of satisfying the script. The signature, the script, and whatever data was needed to satisfy the script would be provided in the spending transaction. The keypath signers could delegate to an unlimited number of scripts in this way without creating any onchain data until an actual spend occurred.

    • Generalized taproot (g’root): a few months later, Anthony Towns suggested a way to use public key points to commit to multiple different spending conditions without necessarily using a MAST-like construction. This generalized taproot (g’root) construction is “potentially more efficient for cases where the taproot assumption doesn’t hold”. It also “offers an easy way to construct a softfork-safe cross-input aggregation system”.

    • Entroot: a more recent synthesis of graftroot and g’root that simplifies many cases and makes them more bandwidth efficient. It can support signer delegation from anyone able to satisfy any of the entroot branches, not just those able to create a top-level keypath spend.

  • New and old opcodes: the taproot soft fork includes support for tapscript which provides an improved way to add new opcodes to Bitcoin, OP_SUCCESSx opcodes. Similar to the OP_NOPx (no operation) opcodes added early in Bitcoin’s history, the OP_SUCCESSx opcodes are designed to be replaced with opcodes that don’t always return success. Some proposed new opcodes include:

    • Restore old opcodes: a number of opcodes for math and string operations were disabled in 2010 due to concerns about security vulnerabilities. Many developers would like to see these opcodes re-enabled after a security review, and (in some cases) perhaps extended to handle larger numbers.

    • OP_CAT: one of the previously-disabled opcodes that deserves special mention is OP_CAT, which researchers have since discovered can enable all sorts of interesting behavior on Bitcoin by itself, or which can be combined with other new opcodes in interesting ways.

    • OP_TAPLEAF_UPDATE_VERIFY: as described in Newsletter #166, an OP_TLUV opcode can enable covenants in a way that’s particularly efficient and powerful when used with taproot’s keypath and scriptpath capabilities. This can be used to implement joinpools, vaults, and other security and privacy improvements. It may also combine well with OP_CHECKTEMPLATEVERIFY.

All of the ideas above are still only proposals. None is guaranteed to be successful. It’ll be up to researchers and developers to bring each proposal to maturity and then for users to decide whether adding each feature to Bitcoin is worth the effort of changing Bitcoin’s consensus rules.

激活时会发生什么?

最初发表于 Newsletter #173

Less than two weeks after the publication of this post, taproot is expected to activate at block 709,632. We know what we expect to happen, and we also know about a few possible failure modes.

The best and most likely outcome is that everything goes fine. Nothing that happens should be visible to normal users. Only those carefully monitoring their nodes or trying to create taproot transactions should notice anything. At block 709,631 nearly all full nodes we’re aware of will be enforcing the same consensus rules. One block later, nodes running Bitcoin Core 0.21.1, 22.0, or related releases will be enforcing the additional taproot rules not enforced by earlier software releases.

This carries a risk that earlier and later versions of node software will accept different blocks. This happened during the activation of the BIP66 soft fork in 2015, resulting in a six-block chain split and several shorter chain splits. Significant engineering effort has been invested in preventing a repeat of that problem. A similar problem should only happen with taproot if a miner either deliberately mines a taproot-invalid block or has disabled safety measures hardcoded into Bitcoin Core and related node software.

Specifically, to create a chain split, a miner would need to create or accept a transaction that spends from a taproot output (segwit v1 output) without following taproot’s rules. If a miner did that, they would lose at least 6.25 BTC (about $400,000 USD at the time of writing) if the economic consensus of Bitcoin node operators rejects the taproot-invalid blocks.

We can’t know for sure without creating an invalid block what those node operators will do—nodes can be run entirely privately—but proxy measures indicate that perhaps more than 50% of node operators are running taproot-enforcing versions of Bitcoin Core. That’s probably more than sufficient to ensure any miner who creates a taproot-invalid block will see it rejected by the network.

Although very unlikely, a temporary chain split is theoretically possible. It should be possible to monitor for it using services such as ForkMonitor.info or using the getchaintips RPC in Bitcoin Core. If it does happen, lightweight clients may receive false confirmations. Although it is theoretically possible to get 6 confirmations, like in the 2015 chain split, that would imply miners had lost almost $2.5 million in value (compared to losses of about $50,000 in 2015). We can hope with values that large at stake, miners will actually enforce the taproot rules they signaled preparedness for six months ago.

In almost any failure circumstance we can imagine, a simple but effective temporary response is to raise your confirmation limit. If you normally wait for 6 confirmations before accepting a payment, you can quickly raise that 30 confirmations for a few hours until the problem has been resolved or it becomes clear that an even higher confirmation limit is required.

For users and services that are convinced the economic consensus of full node operators will enforce taproot’s rules, an even simpler solution is to only get information about which transactions are confirmed from Bitcoin Core 0.21.1 or later (or a compatible alternative node implementation).

Optech expects taproot activation to proceed smoothly, but we do encourage exchanges and anyone accepting large values around block 709,632 to either upgrade their node or be prepared to temporarily raise their confirmation limit if there are any indications of problems.

感谢!

最初发表于 Newsletter #174

Taproot will activate at block 709,632, which is anticipated a few days after the publication of this column. As the final entry in this series, we would like to thank some of the many people who helped develop and activate taproot—and who will soon begin enforcing it. Many others not mentioned below are also deserving of thanks—we apologize for all such omissions.

Bitcoin-dev mailing list discussions

The key idea behind taproot originated on the morning of 22 January 2019 at a meeting between several cryptographers. It was posted to the Bitcoin-Dev mailing list later the same day. Each of the people named below contributed to a thread with “taproot” in its name.

Adam Back, Andrea Barontini, Andreas Schildbach, Andrew Chow, Andrew Poelstra, Anthony Towns, Antoine Riard, Ariel Lorenzo-Luaces, Aymeric Vitte, Ben Carman, Ben Woosley, Billy Tetrud, BitcoinMechanic, Bryan Bishop, Carlo Spiller, Chris Belcher, Christopher Allen, Clark Moody, Claus Ehrenberg, Craig Raw, Damian Mee, Daniel Edgecumbe, David A. Harding, DA Williamson, Elichai Turkel, Emil Pfeffer, Eoin McQuinn, Eric Voskuil, Erik Aronesty, Felipe Micaroni Lalli, Giacomo Caironi, Gregory Maxwell, Greg Sanders, Jay Berg, Jeremy Rubin, John Newbery, Johnson Lau, Jonas Nick, Karl-Johan Alm, Keagan McClelland, Lloyd Fournier, Luke Dashjr, Luke Kenneth Casson Leighton, Mark Friedenbach, Martin Schwarz, Matt Corallo, Matt Hill, Michael Folkson, Natanael, Oleg Andreev, Pavol Rusnak, Pieter Wuille, Prayank, R E Broadley, Riccardo Casatta, Robert Spigler, Ruben Somsen, Russell O’Connor, Rusty Russell, Ryan Grant, Salvatore Ingala, Samson Mow, Sjors Provoost, Steve Lee, Tamas Blummer, Thomas Hartman, Tim Ruffing, Vincent Truong, vjudeu, yancy, yanmaani—, and ZmnSCPxj.

However, many of the ideas included in taproot, such as schnorr signatures and MAST, predate taproot by years or even decades. It’s beyond our capacity to list the many contributors to those ideas, but we owe them our thanks nonetheless.

Taproot BIP review

Starting in November 2019, a large number of users and developers participated in an organized review of taproot and related developments.

achow101, afk11, aj, alec, amiti, _andrewtoth, andytoshi, ariard, arik, b10c, belcher, bjarnem, BlueMatt, bsm1175321, cdecker, chm-diederichs, Chris_Stewart_5, cle1408, CubicEarth, Day, ddustin, devrandom, digi_james, dr-orlovsky, dustinwinski, elichai2, evoskuil, fanquake, felixweis, fjahr, ghost43, ghosthell, gmaxwell, harding, hebasto, instagibbs, jeremyrubin, jnewbery, jonatack, justinmoon, kabaum, kanzure, luke-jr, maaku, mattleon, michaelfolkson, midnight, mol, Moller40, moneyball, murch, nickler, nothingmuch, orfeas, pinheadmz, pizzafrank13, potatoe_face, pyskell, pyskl, queip, r251d, raj_149, real_or_random, robert_spigler, roconnor, sanket1729, schmidty, sipa, soju, sosthene, stortz, taky, t-bast, theStack, Tibo, waxwing, xoyi-, and ZmnSCPxj.

GitHub pull requests

The main implementation of taproot in Bitcoin Core was submitted for review starting in January 2020 in two pull requests. The following people left a GitHub review on those PRs.

Andrew Chow (achow101), Anthony Towns (ajtowns), Antoine Riard (ariard), Ben Carman (benthecarman), Ben Woosley (Empact), Bram (brmdbr), Cory Fields (theuni), Dmitry Petukhov (dgpv), Elichai Turkel (elichai), Fabian Jahr (fjahr), Andreas Flack (flack), Gregory Maxwell (gmaxwell), Gregory Sanders (instagibbs), James O’Beirne (jamesob), Janus Troelsen (ysangkok), Jeremy Rubin (JeremyRubin), João Barbosa (promag), John Newbery (jnewbery), Jon Atack (jonatack), Jonathan Underwood (junderw), Kalle Alm (kallewoof), Kanon (decryp2kanon), kiminuo, Luke Dashjr (luke-jr), Marco Falke (MarcoFalke), Martin Habovštiak (Kixunil), Matthew Zipkin (pinheadmz), Max Hillebrand (MaxHillebrand), Michael Folkson (michaelfolkson), Michael Ford (fanquake), Adam Ficsor (nopara73), Pieter Wuille (sipa) Sjors Provoost (Sjors), Steve Huguenin-Elie (StEvUgnIn), Tim Ruffing (real-or-random), and Yan Pritzker (skwp).

This doesn’t count several other related PRs to Bitcoin Core as well as the work of implementing taproot in other software, including schnorr support in libsecp256k1 (used by Bitcoin Core) or alternative node software.

Taproot activation discussion

As the taproot implementation was merged into Bitcoin Core, it fell on the community to decide how it would be activated. This led to several months of discussion, with the most active conversations on the taproot activation IRC channel between the following users, developers, and miners:

6102bitcoin, AaronvanW, achow101, aj, alec, Alexandre_Chery, Alistair_Mann, amiti, andrewtoth, andytoshi, AnthonyRonning, ariel25, arturogoosnargh, AsILayHodling, averagepleb, bcman, belcher, benthecarman, Billy, bitcoinaire, bitentrepreneur, bitsharp, bjarnem, blk014, BlueMatt, bobazY, brg444, btcactivator, btcbb, cato, catwith1hat, cguida, CodeShark__, conman, copumpkin, Crash78, criley, CriptoLuis, CubicEarth, darbsllim, darosior, Day, DeanGuss, DeanWeen, debit, Decentralizedb, devrandom, DigDug, dome, dr_orlovsky, duringo, dustinwinski, eeb77f71f26eee, eidnrf, elector, elichai2, Emcy, emzy, entropy5000, eoin, epson121, erijon, eris, evankaloudis, faketoshi, fanquake, fedorafan, felixweis, fiach_dubh, fjahr, friendly_arthrop, GeraldineG, gevs, gg34, ghost43, ghosthell, giaki3003, gloved, gmaxwell, graeme1, GreenmanPGI, gr-g, GVac, gwillen, gwj, gz12, gz77, h4shcash, harding, hebasto, hiro8, Hotmetal, hsjoberg, huesal, instagibbs, Ironhelix, IT4Crypto, ja, jaenu, JanB, jeremyrubin, jimmy53, jnewbery, jonatack, jonny100051, jtimon, kallewoof, kanon, kanzure, Kappa, keblek, ksedgwic, landeau, lucasmoten, luke-jr, maaku, Majes, maybehuman, mblackmblack, mcm-mike, Memesan, michaelfolkson, midnight, MikeMarzig, mips, mol, molz, moneyball, mrb07r0, MrHodl, murch, naribia, newNickName, nickler, nikitis, NoDeal, norisgOG, nothingmuch, occupier, OP_NOP, OtahMachi, p0x, pinheadmz, PinkElephant, pox, prayank, prepaid, proofofkeags, provoostenator, prusnak, qubenix, queip, r251d, rabidus, Raincloud, raj, RamiDz94, real_or_random, rgrant, riclas, roasbeef, robert_spigler, rocket_fuel, roconnor, rovdi, rubikputer, RusAlex, rusty, sanket1729, satosaurian, schmidty, sdaftuar, setpill, shesek, shinobiusmonk, snash779, solairis, somethinsomethin, stortz, sturles, sugarpuff, taPrOOteD, TechMiX, TheDiktator, thomasb06, tiagocs, tomados, tonysanak, TristanLamonica, UltrA1, V1Technology, vanity, viaj3ro, Victorsueca, virtu, walletscrutiny, wangchun, warren, waxwing, Whatisthis, whuha, willcl_ark, WilliamSantiago, windsok, wumpus, xxxxbtcking, yanmaani, yevaud, ygrtiugf, Yoghurt11411, zmnscpxj, and zndtoshi.

Miner signaling

We also thank all of the miners since block 681,408 that have signaled their readiness to enforce taproot’s rules.

Side projects

Activation of taproot is only the start. It will now be up to developers and users to begin using the new features made available. Some have been preparing for this for years, working on projects such as MuSig and others. There’s no convenient way to get a list of such developers, but we thank all of them any way.

Node operators

Most importantly, we all owe thanks to the thousands of operators of Bitcoin full verification nodes that have upgraded to Bitcoin Core 0.21.1 or later (or compatible software) and who use their nodes for receiving payments, ensuring that they will only accept transactions in blocks that obey taproot’s rules starting with block 709,632. This provides an economic incentive for every other Bitcoin user to also only accept taproot-compliant blocks, making it safe for everyone to use taproot’s features.

脚注

  1. 当 Electrum 升级到 segwit v0 时,要求任何希望使用 bech32 地址接收资金的用户都生成新的种子。虽然这在技术上并非必要,但它使 Electrum 的作者能够在其自定义种子推导方法中引入一些新的功能。其中一个功能是允许通过种子版本号来指定一个种子应当使用的脚本。这使得旧脚本可以被安全地逐步弃用(例如,未来某个版本的 Electrum 可能会发布,它将不再支持接收到传统的 P2PKH 地址)。

    大约在 Electrum 开发者部署其版本化种子同期,Bitcoin Core 的开发者开始使用 输出脚本描述符 来解决相同的问题——允许逐步弃用脚本(同时也解决了其他问题)。下表对比了 Electrum 的版本化种子和 Bitcoin Core 的描述符与此前两者都使用的 隐式脚本 方法(目前在大多数其他钱包中仍普遍使用)。

    脚本管理 初始备份 引入新脚本 扫描(带宽/CPU 成本) 弃用脚本
    隐式脚本(例如 BIP44 种子词 自动(无需用户操作) 必须扫描所有受支持的脚本,O(n) 无法警告用户他们使用了不受支持的脚本
    显式脚本(版本化种子) 种子词(包含版本位) 用户必须备份新的种子;资金要么被拆分到两个独立钱包中,要么需要用户将旧钱包的资金转移到新钱包 只扫描单一脚本模板,O(1) 警告用户有关不受支持的脚本
    显式脚本(描述符 种子词和描述符 用户必须备份新的描述符 仅扫描实际使用过的脚本模板,O(n);对于新钱包而言 n=1 警告用户有关不受支持的脚本

  2. 若用户希望在首个 Taproot 区块接收 P2TR 支付,应生成一个不与他人共享的地址,并创建 nLockTime 设为 709,631 的交易。该交易可在收到区块 709,631 后立即广播。nLockTime 将确保交易无法在 Taproot 规则生效的 709,632 前被包含。若未充分理解新脚本类型和自定义锁定时间,此类操作可能存在风险,请谨慎处理。 

  3. 付款方可选择复杂路径(路径随机化)弱化 HTLC 关联分析,然存在弊端:

    • 复杂路径不仅成本更高且可靠性下降(需要支付更多转发节点费用,同时依赖更多节点成功完成转发)。
    • 路径延伸导致支付信息被暴露于更多节点,大幅增加遭遇监控节点的可能性。 因此路径随机化非完美隐私解决方案。

  4. 在考虑未公开通道时,记住需要“二人共舞”,如果一个未公开通道被关闭,那么其中一个参与者(例如,一个闪电网络服务提供商)将剩余的资金用于一个公开通道,区块链浏览器可以推测这些资金的来源有一定概率是曾经关闭的未公开通道。 

  5. 如果已知,您可以预签 支出 交易并指定 nSequence,但这样您就不再需要“活跃”密钥的备用支出路径。而且,通常您在收到比特币时并不知道如何花费它们。