Standards Track Final
BIP-144: SegWit 序列化
定義隔離見證交易的網路傳輸和序列化格式,包含 marker、flag 和見證資料。
Eric Lombrozo, Pieter Wuille 2016年1月8日
BIP 編號
144
類型
Standards Track
狀態
Final
創建日期
2016-01-08
摘要
BIP-144 定義了隔離見證(SegWit)交易在 P2P 網路中的序列化格式。 它引入了新的交易格式,將見證資料(簽章等)從交易主體中分離, 同時保持與舊節點的向後相容性。
動機
BIP-141 定義了 SegWit 的共識規則,但沒有說明如何在網路中傳輸交易。 BIP-144 解決了以下問題:
- • 如何編碼包含見證資料的交易
- • 如何讓舊節點仍能轉發(但不驗證)SegWit 交易
- • 如何讓新節點識別 SegWit 交易
交易序列化格式
傳統格式
傳統交易格式(非 SegWit): ┌──────────────────────────────────────┐ │ version │ 4 bytes │ │ tx_in_count │ varint │ │ tx_in[] │ 輸入列表 │ │ tx_out_count │ varint │ │ tx_out[] │ 輸出列表 │ │ lock_time │ 4 bytes │ └──────────────────────────────────────┘
SegWit 格式
SegWit 交易格式: ┌──────────────────────────────────────┐ │ version │ 4 bytes │ │ marker │ 0x00(1 byte) │ ← 新增 │ flag │ 0x01(1 byte) │ ← 新增 │ tx_in_count │ varint │ │ tx_in[] │ 輸入列表 │ │ tx_out_count │ varint │ │ tx_out[] │ 輸出列表 │ │ witness[] │ 見證資料列表 │ ← 新增 │ lock_time │ 4 bytes │ └──────────────────────────────────────┘
Marker 和 Flag
為什麼用 0x00 作為 marker?
傳統交易中,version 後面緊接著 tx_in_count(輸入數量)。 由於交易必須至少有一個輸入,tx_in_count 不可能是 0x00。 因此 0x00 可以明確標識這是 SegWit 交易。
見證資料結構
witness[] 結構: 每個輸入對應一個 witness: witness_i = [ witness_count, // 見證項目數量(varint) witness_item_1, // 第一個見證項目 witness_item_2, // 第二個見證項目 ... ] witness_item = [ length, // 項目長度(varint) data // 項目資料(如簽章、公鑰) ] 範例(P2WPKH): witness = [ 02, // 2 個項目 47, <signature>, // 71 bytes 簽章 21, <pubkey> // 33 bytes 壓縮公鑰 ]
網路協議
服務位元
節點通過 NODE_WITNESS 服務位元宣告支援
SegWit:
NODE_WITNESS = (1 << 3) = 0x08 version 訊息中設置此位元表示: • 節點理解 SegWit 交易格式 • 節點可以提供見證資料 • 節點驗證見證資料
Inventory 訊息
| 類型 | 值 | 說明 |
|---|---|---|
| MSG_TX | 1 | 傳統交易格式(無見證) |
| MSG_WITNESS_TX | 0x40000001 | SegWit 交易格式(含見證) |
| MSG_BLOCK | 2 | 傳統區塊格式 |
| MSG_WITNESS_BLOCK | 0x40000002 | SegWit 區塊格式(含見證) |
交易 ID
txid vs wtxid
txid(傳統 ID)
不包含見證資料的序列化交易的雙重 SHA256 哈希。 用於 UTXO 引用和交易鏈接。
txid = SHA256(SHA256( version || inputs || outputs || locktime ))
wtxid(見證 ID)
包含見證資料的完整序列化交易的雙重 SHA256 哈希。 用於區塊的 witness commitment。
wtxid = SHA256(SHA256( version || marker || flag || inputs || outputs || witness || locktime ))
向後相容性
BIP-144 設計確保舊節點可以:
接收精簡格式 — 舊節點請求 MSG_TX 獲得無見證的交易
轉發交易 — 舊節點可以轉發它不完全理解的 SegWit 交易
不驗證見證 — 舊節點將 SegWit 輸出視為「anyone-can-spend」
範例
P2WPKH 交易序列化
01000000 // version (1) 00 // marker 01 // flag 01 // 1 個輸入 [prevout txid] // 32 bytes [prevout index] // 4 bytes 00 // 空 scriptSig(P2WPKH) ffffffff // sequence 01 // 1 個輸出 [value] // 8 bytes [scriptPubKey] // 輸出腳本 02 // 見證:2 個項目 47 [signature] // 簽章 21 [pubkey] // 公鑰 00000000 // locktime
總結
BIP-144 定義了 SegWit 交易在網路中的傳輸格式,巧妙地利用 marker 和 flag 欄位 區分新舊格式,同時保持向後相容性。這種設計讓 SegWit 能夠作為軟分叉部署, 不需要所有節點同時升級。
延伸閱讀: 查看 GitHub 上的完整 BIP-144 文件
已複製連結