灵活交易(Flexible Transactions)与隔离见证(Segregated Witness)
时间:2016-09-27 来源:巴比特 作者:黄世亮@闪电HSL
最近不断有人问我一个问题,而且越来越频繁。这个问题是关于隔离见证(Segregated Witness)方案,特别是以硬分叉为基础的版本将会怎样。 隔离见证(或简称为“SegWit”)非常复杂。它试图解决相当多的、完全不同的和不相关的问题,并试图以向后兼容的方式这样做。这不是一件小事! 那么,SegWit究竟视图解决什么问题呢 我们可以在效益文件中找到这些信息: 1.延展性修复 2.对签名中哈希运算操作的线性扩容(也即一倍的哈希运算导致一倍的CPU消耗,10倍的运算则对应10倍的消耗)(译者注:这一句的原文是Linear scaling of sighash operationssighash) 3.输入值签名 4.通过“支付给脚本哈希(P2SH)”交易标准,增加多重签名(Multisig)的安全性 5.脚本版本 6.降低UTXO增长 7.Compact fraud proofs (紧凑的欺诈证明) 如上所述,SegWit试图以一种向后兼容的方式解决这些问题。这种要求只是因为SegWit作者设置了这一要求。这样设置是因为他们希望用软分叉推动这个协议升级。本文将试图回答这个问题:这是否是解决这些问题的最好办法。 从延展性开始,问题是,一笔交易从资金所有者和挖区块的矿工构建开始,因为延展性问题,延展性改变都会被认为是有效的交易,但交易标识符(TX-id)已经改变了。在我们深入探讨之前,让我们先看看交易数据结构。 如果我们看一下现在的交易数据结构,我们会注意到一些问题。 最初的交易格式是由中本聪设计,它是包含一个4字节的版本号。这种设计方法在行业中是很常见的,采用的方式是当数据结构中的任何字段需要更改时,则定义一个新版本。就比特币而言,我们还没有做到这一点,我们仍然处于版本1。 比特币取而代之的是做出更小的、半向后兼容的变化。比如,CHECKSEQUENCEVERIFY特点是将repurposes序列字段作为一种添加数据的方式(译者注:CHECKSEQUENCEVERIFY重定义了sequence 字段以便在不破坏兼容性的前提下增加数据),而不破坏旧客户端的数据。顺便说一句,在主要客户端中,这个特定的改变(详见 BIP68)不向后兼容,因为它依赖于一个大于1的交易版本号,他们都检查标准交易,并说只有版本1是标准的。 一个版本号的设计意味着,设计师想使用硬分叉来处理变化。一个新的客户端需要知道如何解析一个新设计的数据结构,这应该是显而易见的。因此,一个主意是要改变版本号,所以老客户会知道他们无法解析这个新的交易版本。为了保持操作,每个人都必须升级到支持这个新交易版本的客户端。 让我们看看为什么我们会想改变版本,我用红色标记了着一些项目,它们易使人混淆。最特别的是,在交易中,这些数字分别是以3个不同的、不兼容的格式存储。这不见得是大的和确定的程序错误。 交易是由比特币的所有者签名加密,以便其他人可以验证,他实际上可以转移该地址的比特币。签名保存在 TX-in-script中。 密码极客们可能已经注意到一些奇怪的东西,它们违背任何课本知识。即数字签名必须放置在它标志的事物外面。这是因为数字签名可以保护自己,防止被更改。但一个签名本身会引起这种变化。所以您必须在您签署的事物外储存签名。(译者注:即数字签名必须放置在它签署的数据之外。这是因为数字签名可以保护被签署的数据不被更改,但签名的本身则会引起数据的变化。因此你必须把签名放在被签署的数据之外) 就如何实际进行签署交易,比特币的创造者做了一些“聪明”的设计,所以签名实际上不必在交易之外。大多数情况下,它确实起作用了。但我们希望它能完美无瑕地的发挥作用,因为目前这些设计太过“聪明”,会导致可怕的延展性问题,人们已经就此而赔钱了。 SegWit (隔离见证)怎么样? SegWit(隔离见证)实际上只解决这些项目中的一个问题。它将签名从交易中移出来。SegWit(隔离见证)未解决比特币交易中的任何其他问题,在做出交易后,它也没有改变版本,这意味着老客户基本上无法理解其本质意义。 老版本客户端将不再能够检查交易的SegWit(隔离见证)类型,因为当真正的数据移动到“拖车”上时,SegWit(隔离见证)的作者只是使SegWit(隔离见证)交易打上“一切OK”的标签,而明知道老客户会忽略“拖车”。(译者注:隔离见证的作者把其设计的类似于一辆车上贴上一个“一切都OK”标签,但却把真实的数据移到车后面的拖车上,知道旧客户端不会去检查拖车) SegWit(隔离见证)想要保持交易的数据结构不变,并试图修复交易的数据结构。这将导致相互矛盾,因为您不能同时进行,于是就有了非理想的情况,随之而来的黑客攻击也在预料之中。 然后的问题是,SegWit(隔离见证)引进了更多的“技术债务”,它是一个软件术语,指的是开发团队在设计或架构选型时从短期效应的角度选择了一个易于实现的方案,但从长远来看,这种方案会带来更消极的影响,亦即开发团队所欠的债务。“债务”一词在这里比喻地十分准确,随着时间的推移,使用交易的每个人都必须了解这种缺陷,从而正确地操作。这与支付利息非常相似。 使用软分叉是指老客户将无法验证交易,甚至无法完全解析它们。但这些老客户自己认为他们正在做充分的验证。 我们能对此进行改进吗 我想建议一种方法来一次性改变交易的数据结构,使它变得更加面向未来,并随着时间的推移,修复它遇到的问题,包括延展性问题。事实证明,这种新的数据结构,可使SegWit(隔离见证)能修复并解决所有的、相当琐碎的其他问题。 我打算提出一个升级方案我称之为: Flexible Transactions (灵活交易) 上个周末,我写了一个小应用程序(源代码请点击这里),读取一个交易,然后按照我为比特币设计的一个新格式写出来。它基于我已经在其他项目上使用了一段时间的主意,但这是第一个开源版本。 基本的想法是改变交易,使其更像现代系统,如JSON, HTML and XML。它是一个以“标签”为基础的格式,比封闭式的“binary-blob”(二进制-blob)格式要有更多各种优点。 例如,如果您添加一个新的field(字段),就像HTML中的标签,您的旧浏览器将只是忽略它,使它向后兼容,并且适用于未来的升级。 更多的优点; 解决延展性问题,它将变得微不足道。 以“标签”为基础的系统可以使您跳过未使用或默认值的writing(写入)。 因为我们正在做出改变,在交易中,我们可以只使用var-int(可变整数)编码数据来替代3个不同的类型。 添加新的标签后(例如ScriptVersion(脚本版本)),不需要进一步修改交易数据结构。所有老客户仍然可以解析所有已知的数据。 实际的交易时间比平均值缩短约3%(超过200K的交易计算) SegWit(隔离见证)增加了大量的技术债务,而我的“Flexible Transactions(灵活交易)”方案不会造成大量的技术债务摊销。 “Flexible Transactions(灵活交易)”方案一般看起来如下: Flexible Transaction (灵活的交易)建议使用一个标签列表,如JSON; ”Name:” “Value”.,使内容变得非常灵活且可扩展。仅仅只取代了文本, Flexible Transaction(灵活的交易)使用一个二进制格式。注意如何跳过未使用的标签。NLockTime 和 Sequence 没有使用,所以它们在交易中被跳过。 最大的变化是, TX-in-script (又名witness(见证)数据)被移动到交易末端。当一个钱包产生这种新的交易类型时,他们将在最后追加witness(见证)数据,但是,通过哈希算法计算witness(见证)数据之前结束的数据来获得交易标识。 Witness(见证)数据通常包含一个公钥以及签名。在Flexible Transactions(灵活交易)方案中,签名由完全相同的数据集签署完成,采用哈希算法生成TX-input。解决延展性的问题。如果有人改变交易,这将使签名无效。 我使用测试应用程序进行测试,我测试了187000个最近的交易,并检查了这个改变会对交易的大小有什么影响。 交易从平均1712字节下降到1660字节,平均值从333个字节下降到318个字节。 在它们已被确认后,交易可以进一步精简(去除签名)。精简后,大小平均下降450个字节,或中位数平均下降101个字节 与SegWit(隔离见证)相反,所有客户端进行此升级后,得到交易体积都更小。 在签名被移除后,交易和区块,可以期望高达75%的体积大小减少。 Broken OP_CHECKSIG脚本指令 实际上为了从源头解决延展性问题,我们需要修复这个指令。但是,我们不能改变原来的脚本,直到我们决定制作一个版本2的脚本语言。 这种变化并不是制作版本2的一个很好的时机,这将是疯狂的,因为在同一时间,我们还推出了交易本身得一个新格式。(同一时间有太多的变化必然会引起问题)。 这意味着,为了使Flexible Transaction(灵活交易)方案实际发挥作用,我们现在需要在脚本中使用一个从未使用过的NOP码,并且让它的作用基本上与OP_CHECKSIG相同,但是,在决定它如何签署方面,不使用过于复杂的方式,我们只是定义它来签署完全相同的交易区域,我们也用它来创建TX-ID。(参见上面表格最右列)。 这个新的opcode(操作码)应该是比较容易的代码,它将使我们非常容易地解决在未来版本的脚本中引入脚本的问题。 那么,与SegWit(隔离见证)相比如何 首先,引入一个新版本的交易并不意味着我们停止支持当前版本。因此,所有这一切都是完美的向后兼容,客户可以继续在旧版本上使用旧的交易格式进行交易。当然会存在一些问题,但没有人最终会被卡住。 对于一个交易,使用一个标记的格式,是一次性硬分叉升级协议,这允许更多的变化,并且对未来系统的影响要小得多。也与SegWit(隔离见证)有相似之处,毕竟争取的是同样的目标。但是,SegWit(隔离见证)试图通过重新利用现有的fields(字段)来调整静态存储格式,而Flexible transactions(灵活交易)方案提出了一个连贯的简单的设计,消除了大量相互冲突的概念。 最重要的是,在Flexible transactions(灵活交易)方案已经引入多年后,,我们可以继续受益于标签系统,从而扩展和修复我们今天还没有想到和发现的问题,使用相同的和一致的概念。 类似于SegWit(隔离见证),我们可以在同一(区块)空间容纳更多的交易,签名(witness部分)可以通过全节点精简,而不造成任何安全问题,这些两个解决方案来是一样的。SegWit(隔离见证)未实现的是,未使用的功能不占空间。因此,如果一个交易不使用NLockTime(它们当中近100%使用),在SegWit中,它们依然将占据空间,而本建议的方案不会。预期您的交易尺寸会较小,因此费用会较低! 在体积大小上, SegWit(隔离见证)目标是增加60%的空间。通过移除签名来减少开销。在我的测试中,Flexible transactions(灵活交易)显示了增加了75%的空间。 SegWit(隔离见证)还描述了如何将存储在区块中的数据进行更改。它在Merkle进程树上创建了一个额外的分支。Flexible transactions(灵活交易)在本质是和SegWit(隔离见证)使用相同的办法解决了相同的区块应用问题。这意味着我们也可以采用Merkle进程树的方案。没有发生变化。 在本文上述提到的优势列表中,包括SegWit(隔离见证)作者所述的优势。事实证明,这些优势彼此本身是完全不相关的,他们每个都有一个非常独立的解决他们问题的方案。棘手的部分来自于老客户的要求,他们被迫把他们都推到一个“修复”的问题上。 让我们来逐一回顾一下: 延展性修复 使用这个新版本的交易数据结构解决了所有已知的延展性问题。 对签名中哈希运算操作的线性扩容(Linearscaling of sighash operations) 这试图解决的问题在bitcointalk里的这个帖子(https://bitcointalk.org/ topic=140078)有描述。 在这个讨论结果显示,SigOps变量被引入,不久就被证明这不是最优解。在BIP109中有一个更好的解决办法叫sig-hash-bytes(运算总节点数)。它是基于这样的事实,哈希是验证过程最昂贵的部分(需要注意的是哈希也是签名验证的一部分)。 在这个解决方案中,给出了一个明确的结论,1M区块最多只允许计算650MB的哈希数量,相应的就只需要5秒钟的验证时间,这样是对验证区块时间的一个保护,不至于特别长。 这是一个很好的平衡,每MB的区块650MB的哈希运算可以保证最极端的交易发生时保证区块验证。 这看起来像是一个不需要去解决的问题。修改协议,可能带来意想不到的后果,这是矫枉过正。 输入值的签名 包括在本建议方案中。 通过 pay-to-script-hash (P2SH) 交易标准,增加多重签名的安全性 在本文中列出的Flexible transactions(灵活交易)方案的建议中,使SegWit(隔离见证)中许多额外的变化在以后很容易添加。这种变化是其中之一。 底线是,对于SegWit(隔离见证),使用更大的哈希来对SegWit(隔离见证)安全更改,仅仅只对SegWit(隔离见证)有效,因为SegWit(隔离见证)没有解决交易的版本问题,使得单独处理它变得平凡而价值很小。 通过Flexible transactions(灵活交易)方案,这种变化可以在未来任何时间进行,且影响最小。 脚本版本 注意,这只是介绍了版本控制字节。它实际上并没有引入一个新版本的脚本。 这是一个很好的例子,Flexible transactions(灵活交易)方案的标签格式比SegWit(隔离见证)采用的静态存储格式更具优势,因为添加这样的版本标签会更清洁、更便捷、更低侵入。只添加一个新的标签,默认为版本1,所以能与没有标签的旧版本交易保持一致。 试想一下,在每一个HTML页都必须包含“body background=white”,因为它不允许被丢弃。这就是SegWit现在所做的。尽管实际上目前并没有支持改变它。 降低 UTXO 增长 我建议您为自己而仔细阅读这点,这是相当有趣的技术,我相信许多人都不会完全掌握、理解这个想法。底线是,他们声称UTXO数据库将避免增长,因为SegWit(隔离见证)不允许为更多的客户提供服务。 我甚至不知道该如何回应这样的解决方案。这是典型的把婴儿和洗澡水一起倒掉。 在过去的20年里,数据库技术已经非常成熟,相比于自由和开源数据库今天所能做的事请,这个数据库根本微不足道。当然,UTXO数据库稍微不适合正常的SQL数据库,但从长远来看,告诉客户到别的地方去的做法,没有哪个长远的项目会做这样的事。 Compact fraud proofs (紧凑的欺诈证明) 再次地,这个并不包括在SegWit(隔离见证)中,而是只提供了一个基础。Flexible transactions(灵活交易)也提供了相同的基础,在这里两个方案是一样的。 我们提供了哪些 SegWit (隔离见证)没有提供的? 交易变得可扩展。未来的改进是方便的。 交易体积更小。使用较少的功能,需要更少的空间。 我们只使用一个整数类型而不是3个来编码。 我们移除了技术债务并实现了简化。SegWit(隔离见证)则相反。 总结 SegWit(隔离见证)具有一些好的想法和一些必要的修正。取其精华去其糟粕是可以的,但是需要硬分叉。这篇文章表明,这些优势是相当重要的,而且是值得的。 我们介绍了一种标签数据结构。从概念上讲,它像JSON和XML一样灵活,但本建议的方案是一个紧凑和快速的二进制格式。采用Flexible transactions(灵活交易)数据格式可以让未来许多的改进和创新保持一致和干净,在随后的阶段,即使更长的时间里,其向后兼容的方式比SegWit(隔离见证)更优秀。我们可以看到SegWit(隔离见证)试图分开来修复的基础事项是可以被一次性全做完的,对比特币来说,作为一个系统,这样做风险更低。 在SegWit(隔离见证)已经开始设计了一年后,我们仍然发现各种问题,并且延迟了软件释放时间,我认为,放弃保持向后兼容的要求应摆到台面上来来讨论。 引入Flexible transactions(灵活交易)升级有很大的好处,因为交易设计变得具有可扩展性。进行一次性的硬分叉让我们在未来可以进行软升级。 Flexible transactions(灵活交易)方案降低了整个系统所需的变化量。不仅仅对完整节点来说是这样,而且特别考虑到许多工具和钱包是通过共享库来创建和解析交易。 任何关心协议稳定性的人应考虑本文建议的Flexible transactions(灵活交易)升级方案,因为在升级之后,失败风险低于SegWit(隔离见证)几个数量级。它没有技术债务,这将使我们能够在未来更好地进行创新。 Flexible transactions(灵活交易)的交易体积更小,能比SegWit(隔离见证)提供更显著的空间节约。 (感谢币圈才子@vatten的校核) |