跳至主要內容
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 能夠作為軟分叉部署, 不需要所有節點同時升級。

已複製連結
已複製到剪貼簿