Segregated witness
- BIP 141: Segregated Witness (Consensus layer)
- BIP 143: Transaction Signature Verification for Version 0 Witness Program
- BIP 144: Segregated Witness (Peer Services)
Segregated Witness (SegWit) 是 2017 年激活的比特币软件的一次重大升级(区块 481,824)。
主要变化是新的交易结构、区块大小的增加以及新增的地址格式。
本页列出了 Segregated Witness 升级中引入的技术变化。 有关该升级发生的原因和过程的介绍,请查看 SegWit 初学者指南。
动机¶
为什么要引入 Segregated Witness?
引入 Segregated Witness 的首要原因是为了修复交易延展性 (transaction malleability)。
在 Segregated Witness 之前,旧版交易的 txid 是从整个交易数据(包括签名)中创建的。
然而,可以调整交易内部的签名并使它们保持有效,这会对 txid 产生连锁反应。这意味着有人可以在你将交易发送到网络后更改你交易的 txid。
这带来的问题是,任何依赖于此 txid 的交易(即在交易仍在内存池中时花费其输出的交易)都将变得无效。换句话说,矿工可以“取消”内存池交易的后代并阻止它们被开采到区块中。
因此,Segregated Witness 升级中的主要变化是对交易数据结构的修改,使得签名不再包含在 txid 计算中,从而使 txid 变得可靠,并允许你在交易仍处于内存池中时自信地花费它们的输出。
这种新的交易数据同时允许区块大小的增加,这就是为什么 Segregated Witness 在一次重大软件升级中作为一系列变更引入的原因。
技术变化¶
比特币发生了哪些变化?
以下是随着 Segregated Witness 升级在比特币中发生的所有变化列表。
我将从最重大的变化开始(开发者最可能遇到的变化),然后逐渐介绍较小的变化。
1. 交易结构¶
主要变化是增加了新的 SegWit 交易结构。
这些新的 SegWit 交易包含一个新的 witness 部分,该部分保存用于解锁升级中引入的新锁定脚本的解锁代码(即签名)。
因此,虽然旧版交易使用 ScriptSig 字段来解锁输入,但 SegWit 交易现在使用新的 witness 部分来代替。
- 旧版锁定脚本(例如 P2PKH, P2SH)仍然需要使用 ScriptSig 字段进行解锁。只有新的锁定脚本(例如 P2WPKH, P2WSH)才使用新的 witness 字段进行解锁。
- 因此,不使用 witness 部分解锁输入的旧版交易仍然容易受到交易延展性的影响。
交易拆分器
随机示例
交易数据
0 bytes0 vbytes
结果
0 secs
2. 交易大小计算¶
随着新 witness 字段的增加,交易还获得了一种名为重量 (weight) 的新大小计算方法。
不同于纯粹根据字节数衡量交易大小,交易数据的不同部分被赋予了特定的乘数,从而使交易的某些部分比其他部分“重量更轻”:
| 旧版数据 (Legacy Data) | 字节数 x 4 |
| SegWit 数据 (Segwit Data) | 字节数 x 1 |
结果,SegWit 交易中的解锁代码比旧版交易中的解锁代码重量更轻,有效地为使用新 SegWit 交易的任何人提供了大小折扣(并降低了手续费成本)。
虚拟字节 (vbytes)¶
虚拟字节测量相当于重量测量,但使用不同的乘数:
| 旧版数据 (Legacy Data) | 字节数 x 1 |
| SegWit 数据 (Segwit Data) | 字节数 x 0.25 |
使用虚拟字节,旧版交易保持相同的大小计量,而新 SegWit 交易可以在“虚拟字节”方面与旧版交易的大小进行对比。
你通常会在区块链浏览器上看到虚拟字节测量,但在内部,比特币使用重量来确定一个区块中可以容纳多少交易。
交易拆分器
随机示例
交易数据
0 bytes0 vbytes
结果
0 secs
3. 区块大小增加¶
为交易使用新的重量计算方法后,区块大小限制从 1,000,000 字节 更改为 4,000,000 重量单位。
这导致区块大小增加,平均比旧的区块大小限制大 4 倍。
鉴于交易数据中总是包含一些旧版数据以及新的 SegWit 数据,实际的区块大小增加在平均水平上约为 1,700,000 至 2,000,000 字节(具体取决于区块中包含 of 交易组成)。
4. 锁定脚本¶
引入了两种新的锁定脚本模式,以利用新的 witness 字段解锁特定类型的输出:
它们在功能上与旧版 P2PKH 和 P2SH 锁定脚本相同。
主要区别在于 P2WPKH 和 P2WSH 是使用交易的 witness 区域而不是 ScriptSig 解锁的。
新的 P2WPKH 和 P2WSH 锁定脚本不使用传统的 Script 语言进行锁定和解锁。 它们使用固定的字节结构,并有自己的硬编码执行方法。但尽管如此,它们在功能上仍与 P2PKH 和 P2SH 相同。
脚本
随机 ScriptPubKey 随机 ScriptSig
十六进制
0 bytes
ASM 类型
非标准 P2PK (Pay To Pubkey) P2PKH (Pay To Pubkey Hash) P2MS (Multisig) P2SH (Pay To Script Hash) P2WPKH (Pay To Witness Pubkey Hash) P2WSH (Pay To Witness Script Hash) P2TR (Pay To Taproot) OP_RETURN (Data)
地址0 characters
0 secs
5. 地址格式¶
新的 P2WPKH 和 P2WSH 锁定脚本使用新的 Bech32 地址格式。
这些 Bech32 地址允许更好的错误检测,且更易于抄写。
地址 (Bech32)
随机生成
ScriptPubKey
Version
OP_0 (P2WPKH or P2WSH)
OP_1 (P2TR)
Data
(public key hash or script hash)
0 bytes
Hex
0 bytes
Type:
Network Mainnet Testnet Regtest
Address
Bech32 encoding of the ScriptPubKey
0 characters
0 secs
因此,旧版 P2PKH 和 P2SH 锁定脚本继续使用 Base58 地址,而新的 P2WPKH 和 P2WSH 锁定脚本使用 Bech32 地址来代替。
6. 签名算法¶
新的 P2WPKH 和 P2WSH 锁定脚本还使用了一种新的签名算法。
这种新的“SegWit 签名算法”旨在比旧版签名算法更高效。
所以现在,创建签名来解锁 P2WPKH 和 P2WSH 锁定脚本的过程与为旧版锁定脚本(例如 P2PKH 和 P2SH)创建签名的过程是不同的。
旧版签名算法和新 SegWit 签名算法都仍然使用 ECDSA。 只是当你想解锁 P2WPKH 和 P2WSH 锁定脚本时,准备用于签名的交易数据的方法是不同的。
7. wTXID 承诺¶
由于新的 SegWit 交易包含不再属于 txid 一部分的数据,因此需要通过 wTXID 承诺将此新见证数据提交到区块。
所以,除了 txid(不包括 SegWit 交易中的新字段)之外,每个交易还具有一个 wtxid,该 id 是通过对 SegWit 交易中的所有数据(包括 SegWit 交易中的新字段)进行哈希运算计算得出的。
TXID
随机示例
交易数据
0 bytes
显示详情
TXID (自然字节顺序)
内部在原始交易数据中使用
0 bytes
TXID (反向字节顺序)
在区块浏览器上搜索交易时外部使用
0 bytes
0 secs
wTXID
随机示例
交易数据
0 bytes
wTXID (自然字节顺序)
0 bytes
wTXID (反向字节顺序)
使用 bitcoin-cli 命令时也称为交易“哈希”
0 bytes
0 secs
所以当构建区块时,矿工现在还将为区块中的所有 wtxid 计算一个 merkle root,并通过 Coinbase 交易中的 wTXID 承诺将该根哈希包含在区块中。
结果,这个 wTXID 承诺防止任何人修改见证数据用于区块中包含的交易。
8. 网络消息¶
当与网络上的其他节点通信时,你现在必须专门请求节点发送 SegWit 交易的完整交易数据(即包括新见证数据)。
所以,在 getdata 消息中,type 字段本来是以下之一:
01000000 = MSG_TX02000000 = MSG_BLOCK
要请求包括新见证数据在内的交易或区块,你需要使用以下 type 字段来代替:
01000040 = MSG_WITNESS_TX02000040 = MSG_WITNESS_BLOCK
9. 其他¶
- 除了在新交易大小计算期间旧版字节数乘以 4 外,旧版交易中的所有签名操作(例如
OP_CHECKSIG,OP_CHECKMULTISIG,OP_CHECKSIGVERIFY,OP_CHECKMULTISIGVERIFY)也会乘以 4。这在计算区块中包含多少个签名操作时很重要,因为一个区块具有 80,000 个签名操作的限制 (sigops)。
总结¶
正如你所看到的,Segregated Witness 一次性为比特币引入了多项技术变革。
其中的许多改变起初似乎有些不必要地复杂,但那是因为需要技术性权衡才能将这些变化作为软分叉而不是硬分叉引入。
然而,根据你所从事的项目,你可能不需要在你的软件中实现所有的变化;你可以仅实现与你的工具相关的改变(例如,如果你在开发钱包,你可能不需要担心新的网络消息)。
不过,了解已发生的所有变化以及它们如何结合在一起构成比特币自发布以来最大的一次升级,还是非常有用的。
最初实现对 SegWit 的支持可能看起来是一项艰巨的技术挑战,但如果你按步骤逐步引入每一项更改,你最终会实现的。一步一步来。






