概述
隔离见证 (Segwit) 即将发布。本文提供了一些背景信息,详细介绍了 Segwit 的测试方法,以及升级预计如何进行的信息,并描述了 Segwit 使实施更容易的一些未来功能。
背景
Segwit 是一种提案,允许生成交易的软件将交易签名(见证)与交易中的其余数据分离(隔离),并允许矿工将这些见证置于传统的区块结构之外。这提供了两个直接的好处
-
消除可塑性:隔离见证允许接收交易的现有软件和升级后的软件在不引用见证的情况下计算使用 Segwit 的交易的交易标识符 (txid)。这解决了所有已知的第三方非预期交易可塑性问题,这是一个使比特币钱包软件编程更加困难并严重复杂化比特币智能合约设计的问题。
-
容量增加:将见证数据移出传统的区块结构(但仍在新的区块结构内)意味着新型区块可以容纳比旧型区块更多的数据,从而使区块中可以容纳的交易数据量适度增加。
Segwit 还简化了向比特币添加新功能的能力,并提高了完整节点的效率,这提供了将在本文后面更详细描述的长期益处。
有关 Segwit 的更多信息,请参阅 我们的常见问题解答 或 BIP 141、143 和 144。
Segwit 的测试方法
Segwit 改变了比特币系统的几个部分,最值得注意的是完整验证节点用来就比特币分类账状态达成一致的共识规则。如果节点停止就分类账的状态达成一致,那么接收新的比特币交易将变得不安全,因此比特币开发人员应该谨慎地进行任何此类更改,并对任何此类建议的更改进行广泛的测试。
同样重要的是对用于中继区块和交易的点对点网络代码的更改。由于 Segwit 交易和区块的组织方式与早期交易和区块版本不同,因此务必确保网络实现既可以将 Segwit 数据中继到 Segwit 节点,也可以将旧式数据中继到旧节点。
对共识规则和 P2P 网络代码的这些综合更改包括 1,486 行添加或修改的代码。Segwit 修补程序还包括在单元和集成测试中额外添加或修改的 3,338 行代码,这些代码有助于确保 Segwit 在比特币核心程序的每个完整版本中都能按预期工作。
除了 3,000 多行添加的自动化测试代码外,Segwit 还得到了比特币开发人员的广泛测试。本节仅描述他们在过去一年中对 Segwit 的不同版本进行的一些严格测试。
-
Segwit 最初由 Pieter Wuille 和其他几位 Blockstream 开发人员于 2015 年 4 月至 6 月在 Elements 项目 侧链上实施,作为“从头开始”的版本,该版本不打算与以前的比特币软件兼容。此版本已用于基于 Elements 的侧链上的每笔交易。
-
2015 年 10 月下旬,Luke Dashjr 描述了一种允许 Segwit 以软分叉方式在比特币中实施的方法,而 Wuille 利用他在 Elements 版本方面的经验开始着手开发这种新的实现,该实现与所有现有的比特币软件向后兼容(尽管程序确实需要升级才能完全理解 Segwit)。
-
该代码于 2015 年 12 月下旬在一个专门的 Segwit 测试网上 (称为 Segnet) 上全面投入使用,该测试网允许实施者和测试人员在多用户环境中运行代码,并允许钱包作者测试其生成 Segwit 交易的代码。随着问题的发现和修复,以及改进的发现和实施,Segnet 经历了多次迭代。
-
2016 年 4 月,经过四个月的积极开发和测试,Wuille 提交了 拉取请求 供比特币核心项目审查。
-
2016 年 5 月,Segwit 在比特币的常规测试网上启用,在那里它不仅针对预期与 Segwit 交互的其他软件进行了测试,还针对比特币测试网上定期测试的所有其他程序进行了测试,而这些程序尚未针对 Segwit 进行升级。
-
同样在 2016 年 5 月,二十位比特币核心开发人员 在瑞士会面,(除其他事项外)对 Segwit 代码进行面对面审查,并确保测试覆盖范围足够。
-
2016 年 6 月,在对原始拉取请求进行了近两个月的非常积极的审查以及在 Segnet 和测试网上进行了扩展操作之后,Wuille 创建了 第二个拉取请求,其中包含对原始拉取请求进行的所有改进,并重新基于比特币核心开发分支的最新版本,并且专门格式化以方便最终审查并确保对原始拉取请求进行的所有审查仍然有效。
随着 Segwit 的原始侧链实施在过去一年中被许多审阅者使用,以及比特币软分叉实施在六个月内接受了严格的测试和审查,比特币核心开发人员认为它现在已准备好投入生产。
紧凑区块
Segwit 将允许比特币矿工在其创建的区块中包含比现在更多的交易数据。这将增加中继所有这些数据的比特币完整节点的带宽需求,并增加发布新区块与节点接收新区块之间的时间延迟(因为大量数据通常需要更长的时间才能传播)。为了帮助减少这些负面影响,比特币核心开发人员计划使 紧凑区块中继 可用于比特币核心 0.13 及更高版本。
比特币完整节点目前下载许多交易两次:一次是在单独接收交易时,另一次是在将交易作为区块的一部分接收时。紧凑区块中继可以通过仅向节点发送他们需要的信息来消除大部分(有时是全部)此重复,以便使用节点已接收的交易重建区块。
在乐观的情况下,这将使节点使用的带宽减少近一半。由于预计 Segwit 将使最大容量增加到大约两倍,因此这两项改进大致相互抵消,使节点带宽使用量保持在与现在大致相同的水平。
更重要的是,紧凑区块中继有助于降低峰值带宽负载。目前,必须立即下载大约 1 MB 的新接收的区块;当部署 Segwit 时,这将意味着可能需要下载 2 MB 或更大的区块。在除最快的连接之外的所有连接上,这些带宽峰值都会损害用户同时运行的其他服务的性能,例如游戏或视频流。使用紧凑区块,用户可以以稳定的流接收交易,然后使用对区块的简短描述重建每个区块,从而消除给许多用户带来不便的带宽峰值。
最后,通过减少宣布新区块时需要发送的数据量,紧凑区块中继还实现了更好的区块传播速度。紧凑区块中继通过支持两种操作模式充分利用了这一点,一种是针对减少带宽进行了优化的低带宽模式(尽管它在大多数情况下也提高了速度),另一种是显着提高速度的高带宽模式,并且仍然通过仅需要比低带宽模式平均多 20 KB 来大幅减少峰值带宽使用量。
高带宽模式被用作进一步开发点对点区块中继优化的基础。它尤其适合矿工使用,矿工需要尽快接收区块(尤其是在其他非点对点区块中继方法失败时),但具有额外带宽的用户也可以启用此模式以帮助更快地向矿工中继区块,并帮助阻止拒绝服务攻击,方法是使其不太明显哪些高带宽节点由矿工运行,哪些由普通对等节点运行。
部署计划
以下计划描述了 Segwit 预计将如何部署。
合并到主分支(不带主网激活代码):在比特币核心开发人员“ACK”(批准)最终的 Segwit 拉取请求后,它将合并到比特币核心主 Git 存储库分支中。正在合并的代码将包括 Segwit 中的所有内容,除了激活代码。这将使开发人员能够轻松地在 Segwit 之上测试其他功能,例如紧凑区块。测试网上的激活已经发生,因此用户和开发人员可以在测试网上试验和测试 Segwit。
回传到 0.12 分支:未激活的代码将回传到 0.12 维护分支,并且回传将接受自己的测试。
选择 BIP9 参数:BIP9 是一种软分叉部署机制,允许矿工发出信号表示他们已准备好执行新的共识规则。每个使用 BIP9 进行的软分叉都会选择矿工何时可以开始发出软分叉信号,如果没有足够的矿工发出软分叉信号,何时将软分叉视为不成功,以及矿工将使用区块头版本字段中的哪个位来发出他们已准备好的信号。这些参数将在此时选择,并在主分支和 0.12 分支上与激活 Segwit 的代码一起实施。
发布候选阶段:在所有开发人员测试成功结束之后,将向任何愿意测试代码的人员公开提供发布候选版本(可能命名为 0.12.2RC1)。尤其鼓励矿工、商家和钱包供应商进行测试。如果发现任何问题,将对其进行修复并发布新的发布候选版本。这将根据需要重复,直到找到没有已知问题的发布候选版本。
二进制发布:最终的发布候选版本将将其版本更改为最终发布版本(预计为 0.12.2),并将发布供所有用户下载并在空闲时开始运行(Segwit 是一个软分叉,因此只有在他们计划使用 Segwit 功能时才需要升级)。
矿工升级:选择升级到 0.12.2 的矿工一旦达到定义为 Segwit 的 BIP9 开始日期的日期,就可以开始生成发出信号表示已准备好执行 Segwit 的区块。
锁定:一旦 2,016 个区块长的重新定位周期中的 95% 的区块发出信号表明他们的矿工已准备好执行 Segwit,Segwit 将锁定——这意味着除非在此时回滚区块链,否则 Segwit 将变为活动状态(请参阅下一条)。
激活:Segwit 锁定后 2,016 个区块(大约两周),它将被激活。这意味着所有运行 Segwit 感知代码的完整节点将开始要求矿工执行新的 Segwit 共识规则。
钱包升级:类似于 2012 年的 P2SH 软分叉,在 SegWit 激活后,钱包升级以支持 SegWit 并不会立即安全。这是因为 SegWit 交易的支出在旧节点看来像是未经安全保护的交易,所以如果在 SegWit 激活后不久区块链发生分叉,这些支出可能会被放置在不受 SegWit 规则约束的早期区块中。因此,建议钱包在 SegWit 激活后的几周内避免升级。允许这段额外的时间可以为钱包用户提供额外的安全性,尽管任何想要用少量可以承受损失的钱进行测试的人,可以在 SegWit 激活后立即开始支出。用户也可以立即使用测试网络或 regtest 以及建议的 SegWit 代码或(在可用时)任何包含 SegWit 的版本开始测试。
Segwit 将如何影响你
-
选择运行 SegWit 的矿工将有责任确保他们已准备好通过将他们的完整验证节点升级到执行 SegWit 的代码来执行 SegWit。完成此操作并执行他们认为谨慎的任何测试后,他们可以开始发出对 SegWit 的支持信号。
-
完整节点运营商可以继续使用其现有节点,但建议他们升级到执行 SegWit 的版本。如果任何矿工最终在 SegWit 激活后产生了根据 SegWit 规则无效的区块,升级后的完整节点将自动拒绝这些区块,确保这些升级后的完整节点用户看到准确的确认计数。
此升级对于任何接受确认次数较少的交易的人(例如企业)尤其重要。
-
Bitcoin Core 钱包用户可以继续使用其现有节点。即使您升级,除了上面描述的内容之外,您也不会看到任何变化。预计在 0.12.2 中发布的代码默认情况下不会开始生成 SegWit 接收地址。
-
其他钱包的用户可以继续使用其现有钱包。建议轻量级钱包用户在收到大量资金时始终等待几次确认,因此此处预计不需要额外等待。
当您有机会升级到支持 SegWit 的钱包版本时,您可能会发现,当您花费升级到 SegWit 后收到的比特币时,您需要支付的交易费用略低,因为见证数据是外部的,因此交易大小被计算为更小。
Segwit 使未来的升级更容易
SegWit 是朝着改进比特币系统运行迈出的重要一步。除了上面描述的针对第三方可塑性和容量增加的修复之外,它还提供了一种机制,允许更容易地升级比特币的脚本语言。
从 Bitcoin 0.3.6 开始,脚本语言支持十个特殊的 NOP 操作码,这些操作码的行为可以在更高版本中以某些方式重新定义。这十个特殊的 NOP 操作码中的两个已被用于向系统添加新功能:NOP2 根据BIP65更改为OP_CHECKLOCKTIMEVERIFY
(CLTV),NOP3 根据BIP112更改为OP_CHECKSEQUENCEVERIFY
(CSV)。
此类操作需要非常小心地实现,以保留旧节点使用的 NOP 语义,这限制了软分叉可以执行的操作,并可能使以这种方式添加功能变得有些混乱。例如,由于 CLTV 和 CSV 都接受参数,因此每次使用它们时,还必须使用OP_DROP
操作码以保持与其原始 NOP 行为的兼容性。这使得使用它们编写和读取脚本都变得更加困难。
SegWit 通过允许 SegWit 用户指定要使用哪个版本的比特币脚本语言来消除所有这些问题。每个版本都可以是对早期版本的小幅改进或全新的语言——并且多个版本可以共存,允许单个用户指定他们希望用来保护其交易的版本。
例如,SegWit 附带了对OP_CHECKSIG
、OP_CHECKMULTISIG
以及相关签名检查操作码的改进,这些改进消除了可以通过这些操作码利用的已知的拒绝服务漏洞向量。这不是该问题的完整解决方案,因为以前版本的 CHECKSIG 操作码仍然可用于非 SegWit 交易,但它确实有助于使 SegWit 交易比非 SegWit 交易更难以滥用。
下面描述了一些使用此机制进行未来升级的想法。
Schnorr 签名
比特币使用椭圆曲线数字签名算法 (ECDSA)。还有一种更简单的数字签名算法也使用椭圆曲线,但在比特币最初发布前不久才获得专利。此算法称为Schnorr,它支持比特币使用的 ECDSA 中的所有功能,包括创建安全签名以及创建 HD 钱包的能力。
Schnorr 签名已在比特币之外使用。例如,著名的Ed25519 签名方案基于 Schnorr。
Schnorr 签名的验证速度略快于 ECDSA 签名(这使得运行完整节点更加方便),并且签名可以更小,因为当前用于 ECDSA 签名的 DER 编码不需要用于 Schnorr(提供适度的容量增加)。
Schnorr 还允许在所有参与者都需要签名(例如 2-of-2、3-of-3 或任何 n-of-n)的情况下进行“原生多重签名”,这允许将所有n个公钥组合成一个整体公钥,并将所有n个签名组合成一个整体签名。整体公钥和签名与原始公钥和签名中的单个公钥和签名大小相同,因此可以创建一个 100-of-100 多重签名交易,其大小与 1-of-1 交易相同。这将非常有用,因为预计网络将看到 n-of-n 多重签名交易的使用增加(例如,2-of-2 用于许多支付通道交易)。
Bitcoin Core 用于创建和验证签名的libsecp256k1库中已经提供了 Schnorr 支持,尽管比特币目前没有以任何方式使用 Schnorr,并且开发人员希望在开始使用它之前对库的 Schnorr 部分进行一些更改。这与 SegWit 对比特币脚本版本的支持相结合,应该使添加上面描述的功能变得相当容易。
一个更难添加的功能是 Schnorr 支持的签名聚合。这将改变签名验证的工作方式,并允许需要 1-of-2、2-of-3 或任何 m-of-n 签名的多重签名交易仅为每个交易创建一个签名,前提是所有签名者同时在线。这还允许为每个交易创建一个签名,无论它有多少输入(同样,如果所有签名者同时在线)。
由于签名通常是交易中最大的单个部分,并且许多交易有两个或多个输入,每个输入都需要至少一个签名,因此这将显着减少许多交易的大小,并且还会加快验证速度(因为只需要验证一个签名,而不是每个输入一个签名)。
一旦实施,签名聚合可以与 coinjoin 隐私增强技术相结合,为使用 coinjoin 支出您的比特币创造重大的经济激励。目前,使用 coinjoin 存在轻微的经济激励,因为组合不同人多个单独交易的 coinjoin 交易略小于所有这些单独交易的总大小。使用签名聚合,组合交易将显着缩小,因为它只需要一个签名而不是多个签名。
虽然签名聚合仍在设计中,但使用 SegWit 对不同版本的比特币脚本评估语言的支持,可以轻松地向协议添加对其的支持。
MAST
Merkelized Abstract Syntax Trees (MAST) 允许创建具有许多不同条件的比特币脚本,但可能只允许将相对少量的数据放入交易中。
它们的工作原理是获取一个程序并将其每个条件部分拆分为一个单独的片段,然后将每个片段放入一个默克尔树中。比特币被花费(受约束)到默克尔树的根。
需要用于最终验证的最小条件集可以向所有完整验证节点公开,但未执行的代码可以用作部分默克尔分支的一部分的简单哈希替换,允许脚本的所有部分连接到约束中使用的默克尔根,以便完成验证。
这不仅节省了空间,而且可能有助于提高隐私。例如,如果 Alice 想要每天都能正常花费她的比特币,但又希望她的遗产律师 Bob 在她的比特币不活跃一年后能够花费她的比特币,她可以将这两个条件分别放在不同的分支中。当 Alice 进行正常支出时,没有人可以通过查看交易来查看第二个条件是什么。
可以使用 SegWit 启用的比特币脚本版本控制来启用 MAST。