目标
- 理解什么是隔离见证
- 交易地址类型
- 编程实践:生成隔离见证地址
一、什么是隔离见证
隔离见证的英文叫做SegWit,是Segregated Witness的简称,隔离见证是对比特币提出的一种升级方案,用于解决比特币面临的一系列严重问题,由Pieter Wuille(比特币核心开发人员、Blockstream联合创始人)在2015年12月首次提出。主要由BIP-141定义。我们可以这样来理解隔离见证:
见证:在比特币里指的是对交易合法性的验证,用于证明自己拥有某些交易的输出的见证数据。
隔离:就是把见证数据从交易信息里抽离出来,单独存放。
SegWit解决的问题
SegWit是由Bitcoin Core的拟议更新,Bitcoin Core是当前最受欢迎的比特币标准客户端,大多数企业使用。最初,该更新旨在解决交易的可扩展性,这也是比特币软件中众所周知的弱点。虽然这种攻击向量对用户来说并不是最具破坏性的,但目前为止已经在多个攻击案例中被利用,因此也就凸显了修补这一漏洞的必要性。目前,比特币可扩展性问题主要源自区块容量不足,这里的问题就在于当前区块的硬编码限制为1兆字节,而这并不足以承担用户每分钟尝试发送的数百笔交易。因此,很多用户必须排队等候,直到他们的交易得到确认,这个等待的时间可能是几个小时,甚或是几天。随着网络规模的扩大,交易强度也随之增加,但区块容量限制则保持不变,这就意味着问题会不断恶化。
SegWit的解决方案由两部分组成的:
- 第一,它可以立即将区块容量限制增加到4兆字节。这里就有一点需要注意:4 MB是绝对最大值,而实际区块容量将取决于网络条件。SegWit激活后,专家预测区块容量将在2到2.1兆的范围内。
- 第二,解决交易的可扩展性,将大量交易移出区块链使用雷电网络(Lightning Network)进行快速处理,预计将大大增加网络容量。
segwit的优点
- 增加块可以执行的事务数。
- 降低交易费用。
- 减少每笔交易的规模。
- 现在可以更快地确认交易,因为等待时间将减少。
- 有助于比特币的可扩展性。
- 由于每个区块的交易数量将增加,因此可能会增加矿工可能收取的总费用。
- 消除交易延展性。
- 有助于激活雷电协议。
二、交易地址类型
地址是使用Base58check格式化的20字节哈希值,去生成P2PKH或P2SH比特币地址。目前最常用的方式是用户交换支付信息。普通的比特币交易地址有两种类型:
- P2PKH(Pay-to-Public-Key-Hash):支付给公钥哈希。是最常用的模板,它被中本聪定义,允许简单的支付给一个单一的公钥。
- P2SH(Pay-to-Script-Hash):支付到脚本,这是多重签名交易输出。在BIP16定义,它允许付款到任意复杂的脚本。
- P2WPKH(Pay-to-Witness-Public-Key-Hash):支付到隔离见证公钥哈希,类似P2PKH,在BIP141新定义的。它嵌入在P2SH脚本中,所以它可以被不知道segwit的钱包使用。
- P2WSH(Pay-to-Witness-Script-Hash):支付到多重签名隔离见证脚本哈希,类似P2SH,是BIP141定义的另一个新的脚本格式。它可以嵌入到P2SH脚本和地址中,使得任何钱包都可以进行与segwit兼容的支付。
举个例子,假设有两个人:lixu、zhangsan,lixu的钱包没有升级到segwit,但是zhangsan的钱包已经升级,可以处理segwit交易。lixu和zhangsan都可以使用正常地址交易,但是zhangsan很可能会使用segwit来降低交易费用。在这种情况下,zhangsan的钱包就需要构建一个包含一个segwit脚本的P2SH地址。lixu的钱包认为这是一个正常的P2SH地址,并可以在没有任何segwit的知识的情况下付款。然后,zhangsan的钱包可以通过隔离交易来支付这笔款项,充分利用隔离交易并降低交易费用。
因此我们需要构建segwit地址兼容普通地址。
三、编程实践:生成隔离见证地址
代码
var bitcoin = require('bitcoinjs-lib');
var bip39 = require("bip39")
var bip32 = require("bip32")const myNetwork = bitcoin.networks.bitcoin
const mnemonic = 'eternal list thank chaos trick paper sniff ridge make govern invest abandon'
// const mnemonic = bip39.generateMnemonic()
const seed = bip39.mnemonicToSeed(mnemonic, "lixu1234qwer")
const root = bip32.fromSeed(seed, myNetwork)
for(var i = 0; i < 3; i++) {
const path = "m/44'/0'/0'/0/"+i
console.log("路径:", path)
const keyPair = root.derivePath(path)
const privateKey = keyPair.toWIF()
console.log("私钥:", privateKey)
const publicKey = keyPair.publicKey.toString("hex")
console.log("公钥:", publicKey)
let address = getAddress(keyPair, myNetwork)
console.log("普通地址:", address)
let segWitAddress = getSegWitAddress(keyPair, myNetwork)
console.log("隔离见证:", segWitAddress, "\n")
}
function getAddress(keyPair, network) {
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey , network:network})
return address
}
function getSegWitAddress(keyPair,myNetwork) {
const { address } = bitcoin.payments.p2sh({
redeem: bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey, network: myNetwork}),
network: myNetwork
})
return address
}
输出

验证

代码解析
这里只解getSegWitAddress方法的实现,其它代码解析请查看上一章“从生成助记词到扩展子地址”的内容。const { address } = bitcoin.payments.p2sh({
redeem: bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey, network: myNetwork}),
network: myNetwork
})
这是将p2wpkh地址嵌套在p2sh地址中,作为它的redeem字段。同时需要注意,在两种地址类型中都需要指定网络类型。上面的代码是在比特币正式网络中运行的,即指定了const myNetwork = bitcoin.networks.bitcoin
。版权声明:博客中的文章版权归博主所有,未经授权禁止转载,转载请联系作者取得同意并注明出处。
未经授权禁止转载、改编,转载请注明出处!
本文链接:https://www.8btc.com/article/319189
转载请注明文章出处