隔离见证
随着早在2011年,协议开发者就知道如何解决循环依赖、第三方篡改和第二方篡改等问题。这个想法是避免将输入脚本包含在生成交易 txid 的计算中。回想一下,输入脚本中保存的数据的抽象名称是见证。将交易的其余数据与其见证分开,以便生成 txid 的想法称为隔离见证(Segregated Witness,简称 SegWit)。
明显的实现 SegWit 的方法需要对比特币的共识规则进行更改,这将与旧的全节点不兼容,也称为硬分叉。硬分叉带来了很多挑战,我们将在第 291 页的“硬分叉”中进一步讨论。
另一种实现 SegWit 的方法是在2015年底提出的。这将使用向后兼容的方式更改共识规则,称为软分叉。向后兼容意味着实现更改的全节点不得接受旧节点认为无效的任何区块。只要它们遵守这个规则,较新的全节点就可以拒绝旧全节点会接受的区块,从而使它们有能力执行新的共识规则(但前提是较新的全节点代表比特币用户之间的经济共识——我们将在第 12 章中探讨更新比特币的共识规则的细节)。
软分叉 SegWit 方法基于任何人可支配的输出脚本。以数字 0 到 16 中的任何一个数字开头,后跟 2 到 40 字节的数据的脚本被定义为隔离见证输出脚本模板。数字表示其版本(例如,0 是隔离见证版本 0,或者 SegWit v0)。数据称为见证程序。还可以将 SegWit 模板包装在 P2SH 承诺中,但我们在本章中不处理这个。
从旧节点的角度来看,这些输出脚本模板可以使用空的输入脚本进行支出。从了解新 SegWit 规则的新节点的角度来看,对隔离见证输出脚本模板的任何支付必须仅使用空的输入脚本进行支出。请注意这里的区别:旧节点允许空的输入脚本;新节点要求空的输入脚本。
空的输入脚本使得见证不会影响 txid,消除了循环依赖、第三方交易篡改和第二方交易篡改。但是,由于不能在输入脚本中放置数据,使用隔离见证输出脚本模板的用户需要一个新的字段。该字段称为见证结构(Witness Structure)。
引入见证程序和见证结构使比特币变得更加复杂,但它遵循了增加抽象的现有趋势。回想一下第 4 章,最初的比特币白皮书描述了一个系统,比特币被接收到公钥(pubkeys)并使用签名(sigs)进行支出。公钥定义了谁有权花费比特币(控制相应私钥的人),而签名提供了验证,即支出交易来自控制私钥的人。为了使该系统更加灵活,比特币的初始版本引入了脚本,允许比特币被接收到输出脚本并使用输入脚本进行支出。后来对合同协议的经验启发了允许比特币被接收到见证程序并使用见证结构进行支出。不同版本比特币中使用的术语和字段如表 6-1 所示。
表6-1. 比特币中不同部分用于授权和认证数据的术语
Whitepaper
Publick key
Signature
Original(Legacy)
Output script
Input script
Segwit
Witness program
Witness structure
Last updated