Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ankarrr/3abdcc310955ae78aa9a324e9fa2dd43 to your computer and use it in GitHub Desktop.
Save Ankarrr/3abdcc310955ae78aa9a324e9fa2dd43 to your computer and use it in GitHub Desktop.
隔離驗證錢包開發指南 Part I(基本篇)

本文翻譯自 Segregated Witness Wallet Development Guide

Key Terms(文中可能以英文表示):

  • Segregated Witness = SegWit = segwit
  • BIP = Bitcoin Improvement Proposals
  • address = bitcoin address
  • txin = bitcoin transaction input
  • UTXO = Unspent Transaction Output
  • P2PKH = Pay To PubKey Hash
  • P2SH = Pay to script hash
  • P2WPKH = Pay to Witness Public Key Hash
  • scriptPubKey = the locking script of an output
  • scriptSig = the unlocking script to resolve an scriptPubKey
  • redeemScript = A script similar in function to a scriptPubKey. One copy of it is hashed to create a P2SH address and another copy is placed in the spending signature script to enforce its conditions.
  • Other terms:
    • multi-signature, keyhash, Sighash, air-gapped, light-weight wallet, orphaned block, retarget cycle

隔離驗證錢包開發指南 Part I(基本篇)

本篇文章大部分內容可在 BIP141, BIP143, BIP144, BIP145 中找到。請將本篇文章視為閱讀其他相關文章前的首要參考,及作為一需要完成及應避免事項的清單。

基本隔離驗證支持

為了達到基本的隔離驗證相容,錢包必須實作所有本章所描述功能:

送到 P2SH

  • 一個隔離驗證相容錢包必須支持 P2SH(BIP16) 及其 address 格式。
  • 就付款來說,錢包必須能轉換一 P2SH address 成 scriptPubKey,並建立交易。
  • 對收款來說,錢包必須能建立一基於 P2WPKH 腳本(本文稍後會描述)的 P2SH address,並能識別出送到該 address 的交易。
  • 以上是必須的要求,即使錢包只接受單簽章的收付款。

建立 P2SH-P2WPKH Address

  • 一個 P2SH-P2WPKH address 可比擬比特幣原本的單簽章 P2PKH address (address 其 prefix 為 1)。
  • 像是任何 P2SH address, P2SH-P2WPKH address 其 prefix 為 3。
  • 直到有 P2SH-P2WPKH UTXO 被花費並揭露 redeemScript,才得以分辨一個 P2SH-P2WPKH address 和 non-segwit P2SH address(例如一個 non-segwit multi-signature address)。
  • 當收款只需要一個公鑰時(像 P2PKH),應使用 P2SH-P2WPKH address。
  • P2SH-P2WPKH 使用和 P2PKH 相同的公鑰,但有一個重要的例外:公鑰使用在 P2SH-P2WPKH 必須被壓縮,i.e. 大小 33 bytes,以 0x020x03 開頭。使用不同格式像是沒有壓縮過的公鑰可能導致不可回溯的資金遺失。
  • 創建一個 P2SH-P2WPKH address:
    1. 計算公鑰經 SHA256 在經 RIPEMD160 的值(keyhash)。雖然計算 keyhash 的公式和 P2PKH 相同,為了隱私和預防不小心用到沒有壓縮過的公鑰,應避免重複使用 keyhash
    2. P2SH redeemScript 都是 22 bytes。它是以 OP_0 為開始,接著 keyhash (i.e. 0x0014{20-byte keyhash})。
    3. 和所有 P2SH 相同,scriptPubKey 是 OP_HASH160 hash160(redeemScript) OP_EQUAL, 然後 address 是相對應的 P2SH address 其 prefix 為 3。

交易序列化

  • 一個隔離驗證相容的錢包必須支援原本的交易格式,像是 nVersion|txins|txouts|nLockTime
  • 一個隔離驗證相容的錢包必須支援新的序列化格式,像是 nVersion|marker|flag|txins|txouts|witness|nLockTime
    • nVersion, txins, txouts, 及 nLockTime 的格式和原本格式相同
    • marker 必須0x00
    • flag 必須0x01
    • witness 是所有交易的 witness data 的序列化結果:
      • 所有 txin 都連結到一個 witness 欄位。所以,並沒有數字指出有多少個 witness 欄位,因為有多少 txin 就代表有多少 witness 欄位。
      • 每個 witness 欄位都會始於一個 compactSize integer 指出有多少個項目在 stack 中。如果 stack 中有 witness 項目的話,會接再 compactSize integer 之後。
      • 每個 witness 項目都始於一個 compactSize integer 表示該項目的 bytes 數。
      • 如果該 txin 沒有連結任何 witness data,它對應的 witness 欄位就是 0x00,表示 stack 中的項目數為零。
  • 如果所有 txin 都沒有連結到任何 witness data,該交易必須序列化成原本的交易格式,沒有 marker, flagwitness。例如,如果沒有 txin 是來自 segwit UTXO,該交易就必須序列化成原本的交易格式。(例外:coinbase 交易)
  • 交易的範例可以在 BIP143 中的範例找到。錢包開發者可以用該範例測試他們的實作是否正確抓取交易資料以符合新的序列化格式。

交易 ID

  • 在隔離驗證中,每一個交易會有 2 個 ID。
  • txid 的定義保持不變:原本交易的序列化格式經過兩次 SHA256。
  • 一個新的 wtxid 被定義為新的序列化格式加上 witnes data 經過兩次 SHA256。
  • 如果一個交易沒有任何 witness data,它的 txidwtxid 是一樣的。
  • txid 還是一個交易主要的識別符:
    • txid 必須用在 txin 中,用以指到上一個 output
    • 如果一個錢包或服務目前使用 txid 來識別交易,預期更新後也是用相同方式。

P2SH-P2WPKH 簽章生成和驗證

  • 對花費 non-segwit UTXO 來說,產生簽章的演算法沒變。
  • 對花費 P2SH-P2WPKH 來說:
    • scriptSig 必須只有包含一個項目,就是 redeemScript
    • 對應的 witness 欄位 必須 包含剛好兩個項目,一個簽章和公鑰。
    • 有一個新的簽章生成演算法被描述在 BIP143。開發者必須謹慎的根據指示,並使用 BIP143 中的範例以確保他們可以重新製作 sighash
    • BIP143 中的簽章生成演算法包含了所有被花費的 input,簡化了 air-gapped 輕量錢包和硬體錢包的設計。
    • 請注意對 P2SH-P2WPKH,scriptCode 都是 26 bytes 其中包含一開始的 size byte,像是 0x1976a914{20-byte keyhash}88ac,而不是 redeemScriptscriptPubKey
    • Example

網路服務(可選的)

  • 如果錢包會透過比特幣 P2P 網路收送交易,那網路服務是必須的。
  • 隔離驗證相容的節點會透過 message 中的 service 欄位: NODE_WITNESS = (1 << 3) 公布他是支援隔離驗證。(可參考 Protocol documentation
  • 交易不包含驗證資料(因此被序列化為原本的格式),可被送到支援或不支援 NODE_WITNESS 的節點。
  • 交易如花費 segwit UTXOs(因此被序列化為新的格式),必須被送到支援 NODE_WITNESS 的節點。
  • 交易花費 segwit UTXOs 但其驗證資料被剝奪(因此被序列化為原本的格式),應被送到節點不支援 NODE_WITNESS。然而在激活隔離驗證之後這種交易是不合法且不會被接受到區塊中。
  • 網路服務的細節可以在 BIP144 中找到。

使用者隱私

  • 在隔離驗證剛開始被激活的時候,比特幣網路可能會有隔離驗證的交易數量限制。
  • 使用隔離驗證交易當它還不普遍時,可能使比特幣較容易被追蹤。
  • 使用 P2SH-P2WPKH 作為預設的找錢 output 也可能有隱私上的影響。

交易手續費估計

  • 一個新的測量標準被定義以取代交易大小,叫"virtual size"(vsize)。
  • 交易的 vsize 等於 3 倍於原本序列化結果的大小,再加上新的序列化結果大小,再除 4 並進位成整數。例如,如果一個交易新的序列化結果是 200 bytes,再移除掉 marker, flag, 和 witness 欄位後是 99 bytes,vsize 進位後是 (99 * 3 + 200) / 4 = 125。
  • 非隔離驗證交易的 vsize 就是原本的 size。
  • 交易手續費的估計應是透過比較交易的 vsize 而不是 size。
  • 開發者們應注意在估計手續費時不要犯差四倍錯誤(忘記除 4)。

升級的安全性

  • 絕對不可以讓一般使用者在隔離驗證完全被激活之前,產生任何 P2SH-P2WPKH 或其他隔離驗證的 address。在激活前,使用 P2SH-P2WPKH 或其他隔離驗證的 address 可能導致永久的資金遺失。
  • 同樣地,絕對不可以找錢至隔離驗證的 output 在激活之前。
  • 隔離驗證激活被定義在 BIP9。在 2016/11/15 之後和 2017/11/15 之前,如果在一個 retarget cycle 的 2016 個 block 之中有 1916 個 blocks 示意為預備好的,隔離驗證會在下一個 retarget cycle 被激活。
  • 如果一個錢包沒有支援 BIP9,升級版不應該被釋出直到被激活時。
  • 如果擔心有些礦工不遵守新的規則,升級的錢包應該延遲直到證據顯示大多數的礦工遵守新的規則。違反規則是很明顯的,透過不合法的的 orphaned blocks 顯示出來。

向後兼容

  • 應維持支援使用 P2PKH(address 其 prefix 為 1)進行交易。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment