進階
Transaction Weight
了解 SegWit 引入的交易權重計算方式,以及對手續費和區塊空間的影響。
10 分鐘
交易權重(Transaction Weight)是 SegWit 引入的新計量單位, 取代了傳統的字節大小。見證數據按 1/4 的權重計算, 這為 SegWit 交易提供了手續費優惠。
權重計算公式
交易權重計算:
weight = (base_size × 4) + witness_size
= (非見證數據 × 4) + 見證數據
或等效地:
weight = (total_size × 3) + (base_size × 1)
其中:
- base_size: 交易序列化大小(不含見證)
- witness_size: 見證數據大小
- total_size: 完整序列化大小(含見證)
單位:
- Weight Units (WU)
- 1 vByte = 4 WU
區塊限制:
MAX_BLOCK_WEIGHT = 4,000,000 WU
= 1,000,000 vBytes 計算示例
範例 1: 傳統 P2PKH 交易(無 SegWit)
結構:
- 版本: 4 bytes
- 輸入數量: 1 byte
- 輸入 (1個):
- prevout: 36 bytes
- scriptSig: ~107 bytes
- sequence: 4 bytes
- 輸出數量: 1 byte
- 輸出 (2個): ~68 bytes
- locktime: 4 bytes
總大小: ~225 bytes
見證: 0 bytes
weight = 225 × 4 + 0 = 900 WU
vsize = 900 / 4 = 225 vB
// 傳統交易: vsize = size 範例 2: Native SegWit P2WPKH 交易
結構:
- 版本: 4 bytes
- marker: 1 byte (0x00)
- flag: 1 byte (0x01)
- 輸入數量: 1 byte
- 輸入 (1個):
- prevout: 36 bytes
- scriptSig: 1 byte (空)
- sequence: 4 bytes
- 輸出數量: 1 byte
- 輸出 (2個): ~62 bytes
- 見證:
- 簽名: ~72 bytes
- 公鑰: 33 bytes
- locktime: 4 bytes
base_size = 110 bytes (不含 marker, flag, 見證)
witness_size = 107 bytes
total_size = 219 bytes
weight = 110 × 4 + 107 = 547 WU
vsize = ceil(547 / 4) = 137 vB
// SegWit 交易更小: 137 vB vs 225 vB
// 節省約 39% 不同交易類型比較
| 交易類型 | 典型大小 | 權重 (WU) | vBytes |
|---|---|---|---|
| P2PKH (1-in, 2-out) | 225 B | 900 | 225 |
| P2SH-P2WPKH | ~166 B | ~561 | ~141 |
| P2WPKH (native) | ~141 B | ~437 | ~110 |
| P2TR (key path) | ~153 B | ~445 | ~112 |
| 2-of-3 P2WSH | ~265 B | ~574 | ~144 |
為什麼見證數據有折扣?
見證折扣的理由:
1. UTXO 集合影響
- 非見證數據影響 UTXO 集合
- UTXO 集合是長期存儲
- 見證數據只需驗證一次
2. 驗證成本
- 見證數據主要是簽名
- 驗證後可以丟棄
- 對節點存儲負擔較小
3. 經濟激勵
- 鼓勵使用 SegWit
- 減少 UTXO 膨脹
- 更高效的區塊空間使用
4. 向後兼容
- 舊節點看到較小的「區塊」
- 維持 1 MB 非見證限制
- 新節點可處理更多交易 手續費計算
手續費基於 vBytes 計算:
fee = fee_rate × vsize
= fee_rate × ceil(weight / 4)
範例:
fee_rate = 10 sat/vB
weight = 547 WU
vsize = ceil(547 / 4) = 137 vB
fee = 10 × 137 = 1370 satoshis
比較同樣費率下的費用:
P2PKH: 10 × 225 = 2250 sat
P2WPKH: 10 × 110 = 1100 sat
// SegWit 節省約 51% 手續費
估算費用:
bitcoin-cli estimatesmartfee 6
# 返回 BTC/kvB,乘以 vsize 得到費用 查詢交易權重
# RPC 命令
# 解碼交易查看權重
bitcoin-cli decoderawtransaction <hex>
{
...
"size": 219, # 總大小(含見證)
"vsize": 137, # 虛擬大小
"weight": 546, # 權重單位
...
}
# 或從已確認交易
bitcoin-cli getrawtransaction <txid> true
{
...
"size": 219,
"vsize": 137,
"weight": 546,
...
}
# 計算交易權重
bitcoin-cli testmempoolaccept '["<hex>"]'
# 返回 vsize 和 fees 程式計算
// Python 計算交易權重
def calculate_weight(tx_hex):
tx_bytes = bytes.fromhex(tx_hex)
# 檢查是否有見證標記
has_witness = (tx_bytes[4] == 0x00 and tx_bytes[5] == 0x01)
if not has_witness:
# 傳統交易
base_size = len(tx_bytes)
witness_size = 0
else:
# SegWit 交易
# 需要解析交易結構
base_size = get_base_size(tx_bytes)
witness_size = len(tx_bytes) - base_size - 2 # 減去 marker 和 flag
weight = base_size * 4 + witness_size
vsize = (weight + 3) // 4 # 向上取整
return {
'size': len(tx_bytes),
'base_size': base_size,
'witness_size': witness_size,
'weight': weight,
'vsize': vsize
}
# 使用
result = calculate_weight("0200000001...")
print(f"Weight: {result['weight']} WU")
print(f"vSize: {result['vsize']} vB") 區塊權重分析
# 查看區塊權重使用
bitcoin-cli getblock <hash>
{
...
"size": 1500000, # 總大小
"weight": 3998000, # 總權重
"strippedsize": 998000 # 剝離見證的大小
...
}
# 計算 SegWit 使用率
segwit_ratio = 1 - (strippedsize / size)
# 分析區塊空間使用
bitcoin-cli getblockstats <height>
{
"total_weight": 3998456,
"total_size": 1456789,
"avgfeerate": 25,
"medianfee": 3500,
...
}
# 區塊已使用容量
used_percent = (total_weight / 4000000) × 100 優化建議
- 使用 SegWit:P2WPKH 或 P2TR 最節省費用
- 合併 UTXO:多輸入增加權重,選擇性合併
- 減少輸出:每個輸出約 31-43 字節
- 使用 Taproot:複雜腳本用 key path 更省
- 批量發送:一次多輸出比多次單輸出省
相關概念
- Virtual Bytes:虛擬字節詳解
- Block Weight:區塊權重限制
- SegWit:隔離見證
- Transaction Fees:手續費計算
- Fee Estimation:費用估算
已複製連結