本文翻译自 Segregated Witness Wallet Development Guide 。
Key Terms(文中可能以英文表示):
- Segregated Witness = SegWit = segwit
- BIP = Bitcoin Improvement Proposals
- address = bitcoin address
- txin = bitcoin transaction input
- UTXO = Unspent Transaction Output
- P2PKH = Pay To PubKey Hash
- P2SH = Pay to script hash
- P2WPKH = Pay to Witness Public Key Hash
- scriptPubKey = the locking script of an output
- scriptSig = the unlocking script to resolve an scriptPubKey
- redeemScript = A script similar in function to a scriptPubKey. One copy of it is hashed to create a P2SH address and another copy is placed in the spending signature script to enforce its conditions.
- Other terms:
- multi-signature, keyhash, Sighash, air-gapped, light-weight wallet, orphaned block, retarget cycle
隔离验证钱包开发指南 Part I(基本篇)
本篇文章大部分内容可在 BIP141, BIP143, BIP144, BIP145 中找到。请将本篇文章视为阅读其他相关文章前的首要参考,及作为一需要完成及应避免事项的清单。
基本隔离验证支持
为了达到基本的隔离验证相容,钱包必须实作所有本章所描述功能:
送到 P2SH
- 一个隔离验证相容钱包必须支持 P2SH(BIP16) 及其 address 格式。
- 就付款来说,钱包必须能转换一 P2SH address 成
scriptPubKey
,并建立交易。 - 对收款来说,钱包必须能建立一基于 P2WPKH 脚本(本文稍后会描述)的 P2SH address,并能识别出送到该 address 的交易。
- 以上是必须的要求,即使钱包只接受单签章的收付款。
建立 P2SH-P2WPKH Address
- 一个 P2SH-P2WPKH address 可比拟比特币原本的单签章 P2PKH address (address 其 prefix 为 1)。
- 像是任何 P2SH address, P2SH-P2WPKH address 其 prefix 为 3。
- 直到有 P2SH-P2WPKH UTXO 被花费并揭露
redeemScript
,才得以分辨一个 P2SH-P2WPKH address 和 non-segwit P2SH address(例如一个 non-segwit multi-signature address)。 - 当收款只需要一个公钥时(像 P2PKH),应使用 P2SH-P2WPKH address。
- P2SH-P2WPKH 使用和 P2PKH 相同的公钥,但有一个重要的例外:公钥使用在 P2SH-P2WPKH 必须被压缩,i.e. 大小 33 bytes,以
0x02
或0x03
开头。使用不同格式像是没有压缩过的公钥可能导致不可回溯的资金遗失。 - 创建一个 P2SH-P2WPKH address:
- 计算公钥经 SHA256 在经 RIPEMD160 的值(
keyhash
)。虽然计算keyhash
的公式和 P2PKH 相同,为了隐私和预防不小心用到没有压缩过的公钥,应避免重复使用keyhash
。 - P2SH
redeemScript
都是 22 bytes。它是以OP_0
为开始,接著keyhash
(i.e.0x0014{20-byte keyhash}
)。 - 和所有 P2SH 相同,scriptPubKey 是
OP_HASH160 hash160(redeemScript) OP_EQUAL
, 然后 address 是相对应的 P2SH address 其 prefix 为 3。
- 计算公钥经 SHA256 在经 RIPEMD160 的值(
交易序列化
- 一个隔离验证相容的钱包必须支援原本的交易格式,像是
nVersion|txins|txouts|nLockTime
。 - 一个隔离验证相容的钱包必须支援新的序列化格式,像是
nVersion|marker|flag|txins|txouts|witness|nLockTime
:nVersion
,txins
,txouts
, 及nLockTime
的格式和原本格式相同marker
必须是0x00
flag
必须是0x01
witness
是所有交易的 witness data 的序列化结果:- 所有 txin 都连结到一个 witness 栏位。所以,并没有数字指出有多少个 witness 栏位,因为有多少 txin 就代表有多少 witness 栏位。
- 每个 witness 栏位都会始于一个
compactSize
integer 指出有多少个项目在 stack 中。如果 stack 中有 witness 项目的话,会接再compactSize
integer 之后。 - 每个 witness 项目都始于一个
compactSize
integer 表示该项目的 bytes 数。 - 如果该 txin 没有连结任何 witness data,它对应的 witness 栏位就是 0x00,表示 stack 中的项目数为零。
- 如果所有 txin 都没有连结到任何 witness data,该交易必须序列化成原本的交易格式,没有
marker
,flag
及witness
。例如,如果没有 txin 是来自 segwit UTXO,该交易就必须序列化成原本的交易格式。(例外:coinbase 交易) - 交易的范例可以在 BIP143 中的范例找到。钱包开发者可以用该范例测试他们的实作是否正确抓取交易资料以符合新的序列化格式。
交易 ID
- 在隔离验证中,每一个交易会有 2 个 ID。
txid
的定义保持不变:原本交易的序列化格式经过两次 SHA256。- 一个新的
wtxid
被定义为新的序列化格式加上 witnes data 经过两次 SHA256。 - 如果一个交易没有任何 witness data,它的
txid
和wtxid
是一样的。 txid
还是一个交易主要的识别符:txid
必须用在 txin 中,用以指到上一个 output- 如果一个钱包或服务目前使用
txid
来识别交易,预期更新后也是用相同方式。
P2SH-P2WPKH 签章生成和验证
- 对花费 non-segwit UTXO 来说,产生签章的演算法没变。
- 对花费 P2SH-P2WPKH 来说:
- scriptSig 必须只有包含一个项目,就是
redeemScript
。 - 对应的 witness 栏位 必须 包含刚好两个项目,一个签章和公钥。
- 有一个新的签章生成演算法被描述在 BIP143。开发者必须谨慎的根据指示,并使用 BIP143 中的范例以确保他们可以重新制作
sighash
。 - BIP143 中的签章生成演算法包含了所有被花费的 input,简化了 air-gapped 轻量钱包和硬体钱包的设计。
- 请注意对 P2SH-P2WPKH,
scriptCode
都是 26 bytes 其中包含一开始的 size byte,像是0x1976a914{20-byte keyhash}88ac
,而不是redeemScript
或scriptPubKey
。 - Example
- scriptSig 必须只有包含一个项目,就是
网路服务(可选的)
- 如果钱包会透过比特币 P2P 网路收送交易,那网路服务是必须的。
- 隔离验证相容的节点会透过 message 中的 service 栏位:
NODE_WITNESS = (1 << 3)
公布他是支援隔离验证。(可参考 Protocol documentation) - 交易不包含验证资料(因此被序列化为原本的格式),可被送到支援或不支援
NODE_WITNESS
的节点。 - 交易如花费 segwit UTXOs(因此被序列化为新的格式),必须被送到支援
NODE_WITNESS
的节点。 - 交易花费 segwit UTXOs 但其验证资料被剥夺(因此被序列化为原本的格式),应被送到节点不支援
NODE_WITNESS
。然而在激活隔离验证之后这种交易是不合法且不会被接受到区块中。 - 网路服务的细节可以在 BIP144 中找到。
使用者隐私
- 在隔离验证刚开始被激活的时候,比特币网路可能会有隔离验证的交易数量限制。
- 使用隔离验证交易当它还不普遍时,可能使比特币较容易被追踪。
- 使用 P2SH-P2WPKH 作为预设的找钱 output 也可能有隐私上的影响。
交易手续费估计
- 一个新的测量标准被定义以取代交易大小,叫"virtual size"(
vsize
)。 - 交易的
vsize
等于 3 倍于原本序列化结果的大小,再加上新的序列化结果大小,再除 4 并进位成整数。例如,如果一个交易新的序列化结果是 200 bytes,再移除掉marker
,flag
, 和witness
栏位后是 99 bytes,vsize
进位后是 (99 * 3 + 200) / 4 = 125。 - 非隔离验证交易的
vsize
就是原本的 size。 - 交易手续费的估计应是透过比较交易的
vsize
而不是 size。 - 开发者们应注意在估计手续费时不要犯差四倍错误(忘记除 4)。
升级的安全性
- 绝对不可以让一般使用者在隔离验证完全被激活之前,产生任何 P2SH-P2WPKH 或其他隔离验证的 address。在激活前,使用 P2SH-P2WPKH 或其他隔离验证的 address 可能导致永久的资金遗失。
- 同样地,绝对不可以找钱至隔离验证的 output 在激活之前。
- 隔离验证激活被定义在 BIP9。在 2016/11/15 之后和 2017/11/15 之前,如果在一个 retarget cycle 的 2016 个 block 之中有 1916 个 blocks 示意为预备好的,隔离验证会在下一个 retarget cycle 被激活。
- 如果一个钱包没有支援 BIP9,升级版不应该被释出直到被激活时。
- 如果担心有些矿工不遵守新的规则,升级的钱包应该延迟直到证据显示大多数的矿工遵守新的规则。违反规则是很明显的,透过不合法的的 orphaned blocks 显示出来。
向后兼容
- 应维持支援使用 P2PKH(address 其 prefix 为 1)进行交易。