Skip to content

feat: Add Bitcoin SegWit Documentation #1293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
331 changes: 331 additions & 0 deletions BTC/Basic/SegWit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,331 @@
# 隔离见证 (SegWit)

## 什么是隔离见证?

隔离见证(Segregated Witness,简称SegWit)是比特币协议的一项重大升级,于2017年8月通过软分叉方式激活。这项技术通过将交易的签名数据(见证数据)与交易数据分离,解决了比特币网络中的一些关键问题,并为未来的扩展性改进奠定了基础。

隔离见证的名称直接反映了其核心概念:将交易的"见证"(witness,即签名数据)从交易的主要部分"隔离"(segregate)出来。这种结构上的变化不仅解决了技术问题,还为比特币网络带来了显著的性能和安全性提升。

## 隔离见证的工作原理

### 传统交易结构的问题

在SegWit之前,比特币交易的结构将交易数据和签名数据(见证数据)存储在同一区块内。这种设计存在几个问题:

1. **交易延展性**:交易ID(txid)是根据整个交易数据(包括签名)计算的。由于签名数据可以在不改变交易有效性的情况下被修改,这就导致了交易ID可能在交易被确认前发生变化,称为"交易延展性"问题。

2. **区块空间效率低**:签名数据通常占据交易大小的很大一部分,但对于验证交易历史并不总是必需的。

### SegWit的解决方案

SegWit通过以下方式解决这些问题:

1. **分离见证数据**:将签名数据(见证数据)从交易的主要部分移出,存储在交易结构的单独部分。

2. **新的交易ID计算方式**:引入了一个新的交易ID计算方式(wtxid),同时保留了向后兼容的txid计算方式。新的txid不包含签名数据,因此消除了交易延展性问题。

3. **区块权重计算**:引入了一个新的"区块权重"概念,使得见证数据在计算区块大小时的权重较低,从而有效增加了每个区块可以包含的交易数量。

## SegWit的主要优势

### 1. 解决交易延展性

通过将签名数据从交易ID计算中分离出来,SegWit彻底解决了交易延展性问题。这对于构建依赖于未确认交易的复杂交易链(如闪电网络)至关重要。

### 2. 增加区块容量

SegWit通过引入区块权重概念,使得每个区块可以包含更多的交易。理论上,SegWit可以将区块容量提高到约2.1MB到4MB,而不需要增加传统的1MB区块大小限制。

### 3. 降低交易费用

由于每个区块可以包含更多交易,网络拥堵情况得到缓解,从而降低了交易费用。使用SegWit地址的交易通常比传统地址的交易费用更低。

### 4. 为二层解决方案铺平道路

SegWit的实施为闪电网络等二层扩展解决方案的开发和部署创造了条件,这些解决方案可以显著提高比特币的交易吞吐量和用户体验。

### 5. 脚本版本控制

SegWit引入了脚本版本控制机制,使得未来可以更容易地引入新的脚本功能,如Taproot等高级功能。

## SegWit地址类型

SegWit引入了两种主要的地址类型:

### 1. P2SH-P2WPKH(兼容地址)

这种地址以"3"开头,与传统的P2SH地址外观相同。它是一种过渡性解决方案,允许旧钱包向SegWit地址发送交易,同时享受SegWit的部分好处。

### 2. P2WPKH(原生SegWit地址)

这种地址以"bc1q"开头,使用Bech32编码格式。原生SegWit地址提供了SegWit的全部好处,包括更低的交易费用和更好的安全性。

## SegWit的采用情况

自2017年激活以来,SegWit的采用率稳步增长。截至2023年,超过80%的比特币交易使用了SegWit,这显著提高了网络的整体效率和容量。

### 采用率数据

| 年份 | 采用率 |
|------|--------|
| 2017 | ~10% |
| 2018 | ~30% |
| 2019 | ~50% |
| 2020 | ~65% |
| 2021 | ~75% |
| 2022 | ~80% |
| 2023 | ~85% |

### 按地址类型分布

当前比特币网络中的地址类型分布大致如下:

- 原生SegWit地址 (P2WPKH/P2WSH): ~45%
- 兼容SegWit地址 (P2SH-P2WPKH): ~15%
- Taproot地址 (P2TR): ~25%
- 传统地址 (P2PKH/P2SH): ~15%

这一趋势表明,比特币生态系统正在逐步迁移到更高效的地址类型,特别是随着Taproot的激活,更多用户开始采用这一基于SegWit v1的新技术。

### 性能数据对比

不同地址类型的交易大小和费用对比(假设费率为10聪/字节):

| 交易类型 | 传统地址 (P2PKH) | 兼容SegWit (P2SH-P2WPKH) | 原生SegWit (P2WPKH) | Taproot (P2TR) |
|---------|-----------------|------------------------|-------------------|----------------|
| 1输入1输出 | 192字节 / 1,920聪 | 132字节 / 1,320聪 | 109字节 / 1,090聪 | 98字节 / 980聪 |
| 2输入2输出 | 374字节 / 3,740聪 | 254字节 / 2,540聪 | 208字节 / 2,080聪 | 186字节 / 1,860聪 |

这些数据显示,与传统地址相比:
- 原生SegWit地址可节省约45%的交易费用
- 兼容SegWit地址可节省约30%的交易费用
- Taproot地址可节省约50%的交易费用

### 区块容量提升

- 传统区块:最大1MB,约容纳2,000笔交易
- SegWit区块:最大可达4MB,约容纳4,000-8,000笔交易

这种容量提升使得比特币网络的吞吐量从传统的3-7 TPS (每秒交易数) 提高到了7-14 TPS。

## SegWit的技术实现细节

### 交易序列化格式

SegWit引入了一种新的交易序列化格式,这是理解其工作原理的关键。下面比较传统交易和SegWit交易的序列化格式:

#### 传统交易格式
```
[4字节] 版本
[变长] 输入数量
[输入列表] 每个输入包含:
[32字节] 上一笔交易ID
[4字节] 输出索引
[变长] 脚本长度
[变长] 脚本(包含签名数据)
[4字节] 序列号
[变长] 输出数量
[输出列表] 每个输出包含:
[8字节] 金额
[变长] 脚本长度
[变长] 脚本
[4字节] 锁定时间
```

#### SegWit交易格式
```
[4字节] 版本
[1字节] 标记 (0x00)
[1字节] 标志 (0x01)
[变长] 输入数量
[输入列表] 每个输入包含:
[32字节] 上一笔交易ID
[4字节] 输出索引
[变长] 脚本长度
[变长] 脚本(不包含签名数据)
[4字节] 序列号
[变长] 输出数量
[输出列表] 每个输出包含:
[8字节] 金额
[变长] 脚本长度
[变长] 脚本
[见证数据] 每个输入的见证数据:
[变长] 见证数据项数量
[变长] 见证数据(签名、公钥等)
[4字节] 锁定时间
```

关键区别:
1. SegWit交易添加了标记(0x00)和标志(0x01)字节
2. 签名数据从输入脚本移到了交易末尾的见证数据部分
3. 交易ID计算不包括见证数据,解决了交易延展性问题

### 区块权重计算

SegWit引入了"区块权重

3. **HTLC实现**:闪电网络中的哈希时间锁定合约(HTLC)依赖于SegWit提供的脚本版本控制功能,使得复杂的条件支付成为可能。

4. **通道关闭效率**:当闪电网络通道关闭时,最终结算交易会广播到比特币区块链。使用SegWit可以降低这些交易的费用,提高结算效率。

### 实际应用示例

本示例代码中的`createLightningChannelFundingTx`函数展示了如何创建一个与闪电网络兼容的通道资金交易,这是建立闪电网络通道的第一步。

## 代码示例:创建SegWit地址和交易

代码示例文件:[example.js](./example.js) 和 [example-extended.js](./example-extended.js)

这些示例文件包含以下功能:

### 基础功能

1. **创建不同类型的SegWit地址**:
- P2WPKH(原生SegWit)地址 - 以bc1q开头
- P2SH-P2WPKH(兼容SegWit)地址 - 以3开头
- P2WSH(原生SegWit脚本哈希)地址

2. **构建SegWit交易**:
- 支持原生SegWit和兼容SegWit交易
- 处理输入、输出和找零

3. **计算SegWit交易ID**:
- 计算传统txid(不包含见证数据)
- 计算wtxid(包含见证数据)

4. **估算SegWit交易的大小和费用**:
- 根据输入输出数量和地址类型估算交易大小
- 计算建议的交易费用

5. **验证SegWit地址**:
- 检查地址是否为有效的SegWit地址
- 识别地址类型(原生SegWit、兼容SegWit或传统地址)

### 高级功能

6. **批量生成SegWit地址**:
- 一次性生成多个SegWit地址
- 支持不同类型的SegWit地址批量生成

7. **批量处理SegWit交易**:
- 处理多个输入和输出
- 自动计算交易费用和找零

8. **创建SegWit多签名地址**:
- 支持m-of-n多签名方案
- 支持原生P2WSH和兼容P2SH-P2WSH多签名地址

9. **创建闪电网络通道资金交易**:
- 创建与闪电网络兼容的2-of-2多签名SegWit地址
- 构建通道资金交易

要使用这些示例,您需要安装bitcoinjs-lib库:

```bash
npm install bitcoinjs-lib
```

## SegWit的最佳实践

### 地址选择

1. **优先使用原生SegWit地址(bc1开头)**:
- 提供最低的交易费用
- 最佳的安全性和性能
- 适用于支持Bech32地址格式的现代钱包和交易所

2. **兼容性考虑**:
- 如果需要与旧钱包或服务兼容,可以使用P2SH-P2WPKH地址(3开头)
- 虽然费用优势略低于原生SegWit,但仍优于传统地址

3. **多签名场景**:
- 对于多签名钱包,P2WSH(原生)或P2SH-P2WSH(兼容)提供了更高的安全性和更低的费用
- 复杂脚本应优先考虑SegWit版本,以获得费用优势

### 交易构建

1. **费用估算**:
- 使用`estimateSegWitTransactionFee`函数准确估算交易费用
- SegWit交易的费用计算与传统交易不同,正确估算可避免支付过高费用

2. **批量处理**:
- 当需要处理多个交易时,使用`batchSegWitTransaction`函数可以更有效地管理UTXO
- 批量处理可以优化交易费用和UTXO集合管理

3. **与闪电网络集成**:
- 使用`createLightningChannelFundingTx`函数创建与闪电网络兼容的通道资金交易
- 确保通道资金交易使用正确的多签名脚本格式

## 实际应用场景

### 1. 交易所集成

交易所可以通过实现SegWit来显著降低提款交易的费用,同时提高交易处理速度:

```javascript
// 交易所批量处理提款示例
const withdrawals = [
{ address: 'bc1q...', amount: 1000000 }, // 用户A提款
{ address: 'bc1q...', amount: 2500000 }, // 用户B提款
// 更多提款...
];

const tx = batchSegWitTransaction(availableUTXOs, withdrawals, exchangeKeyPair, exchangeChangeAddress, 'p2wpkh');
// 广播交易...
```

### 2. 钱包应用

钱包应用可以提供多种地址类型选择,并解释每种类型的优缺点:

```javascript
// 为用户生成不同类型的地址
const addressOptions = {
legacy: bitcoin.payments.p2pkh({ pubkey: userKeyPair.publicKey, network }).address,
segwitCompatible: bitcoin.payments.p2sh({
redeem: bitcoin.payments.p2wpkh({ pubkey: userKeyPair.publicKey, network }),
network
}).address,
segwitNative: bitcoin.payments.p2wpkh({ pubkey: userKeyPair.publicKey, network }).address
};
```

### 3. 多签名钱包

企业和组织可以使用SegWit多签名地址来增强资金安全性:

```javascript
// 创建3-of-5多签名企业钱包
const corporateWallet = createSegWitMultisigAddress(3, 5, 'p2wsh');
// 保存地址和赎回脚本信息...
```

### 4. 闪电网络节点

运行闪电网络节点的用户可以使用SegWit来创建通道资金交易:

```javascript
// 开设新的闪电网络通道
const channelFunding = createLightningChannelFundingTx(
selectedUTXO,
localNodePubkey,
remoteNodePubkey,
myChannelAmount,
theirChannelAmount,
myKeyPair,
estimatedFee
);
// 广播资金交易并等待确认...
```

## 结论

隔离见证是比特币历史上最重要的技术升级之一,它不仅解决了交易延展性等关键问题,还提高了网络的交易容量和效率,同时为闪电网络等创新解决方案铺平了道路。随着越来越多的用户和服务采用SegWit,比特币网络的性能和可用性将继续提高。

通过本示例代码,开发者可以轻松实现SegWit的各种功能,从基本的地址生成到复杂的多签名和闪电网络集成。这些工具为构建现代、高效的比特币应用提供了坚实的基础。

## 参考资料

1. [BIP 141: Segregated Witness](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki)
2. [BIP 143: Transaction Signature Verification for Version 0 Witness Program](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki)
3. [BIP 173: Base32 address format for native v0-16 witness outputs](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki)
Loading
Loading