本文件的大部分内容可以在与隔离认证相关的BIP中找到,包括BIP141,BIP143,BIP144和BIP145。请将此视为阅读其他相关文件的第一个参考点,并作为那些应该做和那些不应该做的检查清单。
### 基本的隔离认证支持
钱包必须实现本节中的所有功能,以便在基本级别被视为segwit兼容:
#### 发送到P2SH
- 兼容segwit的钱包必须支持`pay-to-script-hash`([BIP16](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki))及其地址格式([BIP13](https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki))。
- 对于付款,钱包必须能够正确地将给定的P2SH地址转换为`scriptPubKey`,并创建一个交易。
- 为了接收付款,钱包必须能够基于P2WPKH脚本(在下文中定义)创建P2SH地址,并且能够识别对这些地址的支付。
- 这是强制性要求,即使钱包仅接受单签名付款。
#### 创建P2SH-P2WPKH地址
- P2SH-P2WPKH地址与比特币的原始单签名P2PKH地址(前缀为1的地址)相当。
- 与任何其他P2SH地址一样,P2SH-P2WPKH地址的前缀为3。
- 在使用P2SH-P2WPKH UTXO并暴露`redeemScript`之前,P2SH-P2WPKH地址与非segwit P2SH地址无法区分(例如非segwit多签名地址)。
- 当只有1个公钥用于接收付款时(如P2PKH),应使用P2SH-P2WPKH地址。
- P2SH-P2WPKH使用与P2PKH相同的公钥格式,但有一个非常重要的例外:P2SH-P2WPKH中使用的公钥必须被压缩,即大小为33字节,并以`0x02`或`0x03`开头。使用任何其他格式(如未压缩的公钥)可能会导致不可撤销的资金损失。
- 创建P2SH-P2WPKH地址:
- 1.计算公钥(`keyhash`)的SHA256的RIPEMD160。尽管`keyhash`公式与P2PKH相同,但应避免重用`keyhash`以获得更好的隐私并防止意外使用未压缩密钥。
- 2.P2SH `redeemScript`始终为22个字节。它以`OP_0`开头,然后是`keyhash`的规范推送(如`0x0014{20-byte keyhash}`)。
- 3.与其他P2SH相同,`scriptPubKey`是`OP_HASH160 hash160(redeemScript)OP_EQUAL`,地址是对应的P2SH地址,前缀为3。
#### 交易序列化
- 兼容segwit的钱包必须支持原始的交易格式,如`nVersion|txins|txouts|nLockTime`。
- 兼容segwit的钱包也必须支持新的序列化格式,如`nVersion|marker|flag|txins|txouts|witness|nLockTime`。
- `nVersion`,`txins`,`txouts`和`nLockTime`的格式与原始格式相同。
- `marker`必须是`0x00`。
- `flag`必须是`0x01`。
- `witness`是交易的所有见证数据的序列化。
- 每个txin都与见证字段相关联。作为结果,没有表示显示证据字段的数量,因为它是由`txins`的数量默认的。
- 每个见证字段以[compactSize integer](https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers)开始,以指示相应txin的堆栈项目数。然后是相应txin的见证堆栈项目数(如果有的话)。
- 每个见证堆栈项都以`compactSize integer`开头,以指示该项的字节数。
- 如果`txin`未与任何见证数据相关联,则其对应的见证字段精确为`0x00`,表示见证堆栈项的数量为零。
- 如果交易中的所有`txins`都没有与任何见证数据相关联,则交易必须以原始交易格式序列化,不包括`marker`, `flag`, `witness`。例如,如果没有`txins`来自segwit UTXO,它必须以原始交易格式序列化。(coinbase交易例外)
- 可以在BIP143的示例部分找到交易序列化的示例。钱包开发人员可以使用这些示例来测试他们的实现是否正确解析了新的序列化格式。
#### 交易ID
- 在segwit下,每个交易将有2个ID。
- `txid`的定义保持不变:原始序列化格式的double SHA256。
- 定义了一个新的`wtxid`,它是具有见证数据的新序列化格式的double SHA256。
- 如果交易没有任何见证数据,则其`wtxid`与`txid`相同。
- `txid`仍然是交易的主要标识符:
- 当引用先前的输出时,它必须在`txin`中使用。
- 如果钱包或服务当前正在使用`txid`来识别交易,则预示着它将继续使用segwit。
#### P2SH-P2WPKH的签名生成和验证
- 对于非segwit UTXO的消费,签名生成算法不变。
- 对于P2SH-P2WPKH的消费:
-`scriptSig`必须只包含一个`redeemScript`。
- 相应的见证字段必须包含2个项目,签名后跟公钥。
- BIP143(见文末)中描述了一种用于segwit脚本的新签名生成算法。开发人员应仔细遵循说明,并使用BIP143中的P2SH-P2WPKH示例,以确保它们能够重现`sighash`。
- BIP143签名生成算法涵盖了所花费的输入值,简化了air-gapped轻量钱包和硬件钱包的设计。
- 请注意,对于P2SH-P2WPKH,`scriptCode`总是26个字节,包括前导大小字节,如`0x1976a914{20-byte keyhash}88ac`,不是`redeemScript`,也不是`scriptPubKey`。
- [示例](http://n.bitcoin.ninja/checktx?txid=8139979112e894a14f8370438a471d23984061ff83a9eba0bc7a34433327ec21)。
#### 网络服务(可选)
- 如果钱包通过对等网络发送和接收交易,则需要网络服务。
- 支持Segwit的节点将表示他们可以通过服务位提供见证:`NODE_WITNESS=(1<<3)`。
- 没有任何见证数据的交易(因此以原始格式序列化)可以发送到有或没有`NODE_WITNESS`支持的节点。
- 花费segwit UTXO(因此以新格式序列化)的交易必须仅发送到具有`NODE_WITNESS`支持的节点。
- 花费segwit UTXO但剥离见证数据(因此以原始格式序列化)的交易可以发送到没有NODE_WITNESS支持的节点。但是,这些交易在激活segwit后无效,并且在块中不会被接受。
- 有关网络服务的详细信息,请参阅BIP144(见文末)。
#### 用户隐私
- 在segwit交易很普遍之前,这种交易类型可以使比特币跟踪更容易。
- 使用P2SH-P2WPKH作为默认变化时的输出也可能会对隐私产生影响。
#### 交易费用估算
- 替代交易大小,定义了一个新的度量,称为“virtual size”(`vsize`)。
- 交易的`vsize`等于原始序列化大小的3倍,加上新格式序列化的大小,将结果除以4并向上舍入到下一个整数。例如,如果一个交易是200字节的新格式序列化,并且变为99字节,删除了`marker`,`flag`,`witness`,则`vsize`为(99*3+200)/4=125并向上舍入。
- 非segwit交易的`vsize`只是它本身的大小。
- 交易费应通过比较`vsize`与其他交易而不是大小来估算。
- 开发人员应注意不要在费用估算中犯off-by-4-times错误。
#### 激活
- 从块高度481824开始,所有SegWit就绪节点都开始执行新的SegWit共识规则。
### 向后兼容性
- 应继续支持发送和接收传统的P2PKH支付(前缀为1的地址)。
### 复杂的脚本支持
如果钱包支持除单一签名之外的脚本类型,例如多重签名,则必须满足以下基本要求:
#### 创建P2SH-P2WSH地址
- P2SH-P2WSH地址与比特币的原始P2SH地址相当,后者允许表示具有固定大小地址的任意复杂脚本。
- 与任何其他P2SH和P2SH-P2WPKH地址一样,P2SH-P2WSH地址具有前缀3.在UTXO用完之前,它们无法区分。
- 要创建P2SH-P2WSH地址:
- 1.定义一个名为`witnessScript`的脚本。
- 2.计算`witnessScript`(`scripthash`)的SHA256。请注意使用单个SHA256,而不是双SHA256和RIPEMD160(SHA256)。
- 3.P2SH `redeemScript`总是34个字节。它以`OP_0`开头,然后是`scripthash`的规范推送(即`0x0020{32-byte scripthash}`)。
- 4.与任何其他P2SH相同,`scriptPubKey`是`OP_HASH160 hash160(redeemScript) OP_EQUAL`,地址是对应的P2SH地址,前缀为3。
#### 对脚本的限制
- 脚本评测不能失败,并且必须在评测后留下一个且只有一个TRUE堆栈项。否则,评估失败。
- P2SH-P2WSH脚本中的任何公钥必须是压缩密钥,否则资金可能永久丢失。
- 如果使用`OP_IF`或`OP_NOTIF`,则其参数必须是空向量(对于false)或`0x01`(对于true)。使用其他值可能导致永久性资金损失。(BIP草案)。
- 如果`OP_CHECKSIG`或`OP_CHECKMULTISIG`返回失败,则所有签名必须为空向量。否则,资金可能会永久丢失。(BIP146)。
- `witnessScript`的默认策略限制为3600字节。除了`witnessScript`,最多可以有100个见证堆栈项,每个最多80个字节。超出这些限制的交易不得转发或包含在一个区块中。
- 许多原始脚本的共识限制,例如10000字节脚本大小,201 `nOpCount`,仍然适用于P2SH-P2WSH。
- P2SH的520字节脚本大小限制不适用于P2SH-P2WSH。它被3600字节的策略限制和10000字节的共识限制所取代。
#### P2SH-P2WSH的签名生成和验证
- 对于P2SH-P2WSH的消费:
- `scriptSig`必须只包含一个`redeemScript`。
- 相应见证字段的最后一个见证项必须是`witnessScript`。
- 新的BIP143签名生成算法适用于:
- 在不使用任何`OP_CODESEPARATOR`的情况下,`scriptCode`是`witnessScript`,前面是一个`compactSize integer`,用于`witnessScript`的大小。例如,如果脚本是`OP_1`(`0x51`),则序列化的`scriptCode`是(`0x0151`)。
- 对于包含`OP_CODESEPARATOR`的任何异常脚本,请参阅BIP143以获取确切的语义。
- 在`witnessScript`之前的任何见证堆栈项目都用作脚本评测的输入堆栈。输入堆栈不会被解释为脚本。例如,不需要使用`0x4c`(OP_PUSHDATA1)来“push”大项。
- 要验证签名生成和堆栈序列化的正确性,请始终根据BIP143中的示例进行测试。
- [示例](http://n.bitcoin.ninja/checktx?txid=954f43dbb30ad8024981c07d1f5eb6c9fd461e2cf1760dd1283f052af746fc88)。
### Segwit本机地址(可选)
初始segwit支持不需要以下功能。
#### 本地Pay-to-Witness-Public-Key-Hash(P2WPKH)
- Native P2WPKH是一个22字节的`scriptPubKey`。它以`OP_0`开头,然后是`keyhash`的规范推送(即`0x0014{20-byte keyhash}`)。
- 与P2SH-P2WPKH相同,`keyhash`是压缩公钥的RIPEMD160(SHA256)。
- 当使用原生P2WPKH时,`scriptSig`必须为空,见证堆栈格式和签名生成规则与P2SH-P2WPKH相同(包括使用压缩公钥的要求)。
- [示例](http://n.bitcoin.ninja/checktx?txid=d869f854e1f8788bcff294cc83b280942a8c728de71eb709a2c29d10bfe21b7c)。
#### 本地Pay-to-Witness-Script-Hash(P2WSH)
- 原生P2WSH是一个34字节的`scriptPubKey`。它以`OP_0`开头,然后是`scripthash`的规范推送(即`0x0020{32-byte scripthash}`)。
- 与P2SH-P2WSH相同,`scripthash`是`witnessScript`的SHA256。
- 当使用原生P2WSH时,`scriptSig`必须为空,见证堆栈格式和签名生成规则与P2SH-P2WSH相同(包括使用压缩公钥的要求)。
- [示例](http://n.bitcoin.ninja/checktx?txid=78457666f82c28aa37b74b506745a7c7684dc7842a52a457b09f09446721e11c)。
#### 为什么以及如何使用Native(Bech32)P2WPKH和P2WSH?
- BIP173为本机P2WPKH和P2WSH地址提出校验和base32格式(Bech32)。
- 比特币核心v0.16.0中包含对Bech32地址的支持。
- 与P2SH版本相比,在大多数情况下,本机版本的交易`vsize`较小,因此可能需要较少的费用。
- 原生P2WPKH和P2WSH可以与原始`scriptPubKey`协议一起使用,例如支付协议(BIP70)。但是,它可能会影响付款人和收件人的隐私(见下文)。
- 原生P2WPKH和P2WSH可用作默认更改地址,但这可能允许其他人轻松识别更改(参见下文)。
- 在广泛使用原生P2WPKH和P2WSH之前,这些地址类型可能会引起用户之间的隐私问题。
### 脚本和事务示例
- [不同见证交易类型和交易有效性检查工具的示例](http://n.bitcoin.ninja/checktx)
- [BIP141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki)
- [BIP143](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki)
- [BIP144](https://github.com/bitcoin/bips/blob/master/bip-0144.mediawiki)
- [BIP145](https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki)
- [BIP173](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki)
- [脚本测试](https://github.com/bitcoin/bitcoin/blob/master/src/test/data/script_tests.json)
- [有效的交易测试](https://github.com/bitcoin/bitcoin/blob/master/src/test/data/tx_valid.json)
- [无效的交易测试](https://github.com/bitcoin/bitcoin/blob/master/src/test/data/tx_invalid.json)
======================================================================
分享一些以太坊、EOS、比特币等区块链相关的交互式在线编程实战教程:
> - [java比特币开发教程](http://xc.hubwiz.com/course/5bb35c90c02e6b6a59171df0?affid=1102studygolang),本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。
> - [php比特币开发教程](http://xc.hubwiz.com/course/5b9e779ac02e6b6a59171def?affid=1102studygolang),本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。
> - [java以太坊开发教程](http://xc.hubwiz.com/course/5b2b6e82c02e6b6a59171de2?affid=1102studygolang),主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
> - [python以太坊](http://xc.hubwiz.com/course/5b40462cc02e6b6a59171de4?affid=1102studygolang),主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。
> - [php以太坊](http://xc.hubwiz.com/course/5b36629bc02e6b6a59171de3?affid=1102studygolang),主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。
> - [以太坊入门教程](http://xc.hubwiz.com/course/5a952991adb3847553d205d1?affid=1102studygolang),主要介绍智能合约与dapp应用开发,适合入门。
> - [以太坊开发进阶教程](http://xc.hubwiz.com/course/5abbb7acc02e6b6a59171dd6?affid=1102studygolang),主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
> - [C#以太坊](http://xc.hubwiz.com/course/5b6048c3c02e6b6a59171dee?affid=1102studygolang),主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。
> - [EOS教程](http://xc.hubwiz.com/course/5b52c0a2c02e6b6a59171ded?affid=1102studygolang),本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。
汇智网原创翻译,转载请标明出处。这里是原文[比特币隔离认证钱包开发指南](http://blog.hubwiz.com/2018/11/01/bitcoin-SegWit-Wallet/)
有疑问加站长微信联系(非本文作者)