綜述
本提案定義了一個新結構“witness”送出到區塊中,與交易的merkle tree不同。該結構包含檢查交易有效性所需的資料。此外,腳本和簽名移動到了這個新結構。
為了確定BIP軟分叉的相容性,該結構通過coinbase交易嵌套在區塊已存在的merkle root。未來的硬分叉可以給該樹配置設定一個自己的分支。
動機
整個交易的效果由引用的交易輸出和新建立的交易輸出決定。其他的交易資料,尤其是簽名,僅僅隻在驗證塊鍊的狀态的時候需要,其他的時候并不需要它。
通過從交易結構中移除這些資料,送出給交易merkle tree,幾個問題得到修正:
- 無意導緻的交易延展性變的不可能 : 因為簽名資料不再是組成交易哈希資料的一部分,是以交易簽名的變化将不再影響到對應交易的确定。作為一個交易延展性的解決方案,它比經典的簽名編碼解決方案更好(BIP62)。
- 對于所有類型的腳本,該方案阻止了無意導緻的簽名延展性,隻要所有的交易輸入被簽名(使用至少一個CHECKSIG或CHECKMULTISIG操作碼)。
- 在m-of-n的CHECKMULTISIG的多重簽名腳本中,隻有得到所有私鑰所有者的同意,該交易才可能被延展(而不是BIP62中僅一個私鑰的持有者).
- 防止未知的ECDSA簽名延展性造成的交易延展。
- 允許沒有風險的建立未确認的交易依賴鍊,這是對于offchain協定一個重要的功能(例如:閃電網絡)
- 傳輸簽名資料變得可選擇 : 簽名資料隻有當一個對等節點準備驗證該交易有效性是才需要,對于隻檢查該交易是否存在,并不需要該交易的簽名資料。這将減少SPV 節點證明的位元組大小,提升SPV節點的隐私性,因為SPV節點可以使用相同的帶寬下載下傳更多的交易,
- 一些限制可以通過軟分叉繞過 : 通過轉移交易的部分資料到目前協定未知的資料結構中,例如:
- 當計算區塊位元組大小時,witness的位元組可以被忽略或減少,一定程度上增大了區塊的位元組。
- 寫死常量,例如最大的push位元組數或操作碼個數的限制可以被移除或重新評估。
- 新的腳本系統可以不受現有腳本語義的限制被引入。例如:對于交易的簽名驗證,一個新的交易摘要算法被引入(BIP143)
規範
交易ID
一個新的資料結構:witness被定義。每個交易有兩個ID。
txid的定義未變;
[nVersion] [txins] [txouts] [nLockTime]
新的wtxid被定義:
[nVersion] [marker] [flag] [txins] [txouts] [witness] [nLockTime]
nVersion, txins, txouts, and nLockTime格式與傳統的序列化相同。
marker 必須是一個值為0的位元組,0x00.
flag 必須是一個非0的位元組:目前,必須是0x01。
witness是每個交易所有witness資料的序列化。每個txin關聯一個witness字段。一個witness字段以var_int開始,辨別txin棧中item的數量,後面緊跟棧上的items,每個item以var_int開始,辨別長度。witness資料不是腳本。
一個非witness程式的txin必須關聯一個空的witness字段,由0x00表示。如果所有的txins都是非witness程式,則交易的wtxid等于它的txid。
承諾結構
一個新的區塊規則被添加,該規則要求wtxid的承諾結構。coinbase交易的承諾結構被假設為0x00...000.
witness root hash
由所有
wtxid
做為葉子來計算,與塊頭的
hashMerkleRoot
相同的方式。
該承諾結構被記錄在coinbase交易的
scriptPubKey
字段。它必須含有至少38個位元組,前6個位元組是:
0x6a24aa21a9ed
,
1-byte - OP_RETURN (0x6a)
1-byte - Push the following 36 bytes (0x24)
4-byte - Commitment header (0xaa21a9ed)
32-byte - Commitment hash: Double-SHA256(witness root hash|witness reserved value)
39th byte onwards: Optional data with no consensus meaning
複制
并且coinbase的交易輸入必須含有一個32位元組的數組,做為
witness reserved value
.
如果有多個
scriptPubKey
比對這個格式,則索引最大的輸出被認定為承諾結構。
如果區塊的所有交易都不含witness資料,此時這個承諾結構就可有可無。
witness program
一個
scriptPubKey
(或定義在BIP16/P2SH中的
redeemScript
)由一個位元組的push 操作碼,後緊跟一個2-40位元組的資料獲得一個新的特殊含義。第一個push的值叫做
version byte
,接下來的push位元組向量叫做
witness program
.
有兩種情況下,witness的驗證邏輯被觸發。每種情況都決定了witness version位元組和程式的位置,以及
scriptSig
的格式。
- 由一個版本位元組和witness program組成的scriptPubKey觸發。則
必須恰好是空或驗證失敗("native witness program")。scriptSig
- 被一個P2SH腳本的
觸發,并且pushscriptPubKey
到scriptSig
正好是一個版本位元組加一個witness program。這個redeemScript
必須恰好是一個push到BIP16的scriptSig
或驗證失敗("P2SH witness program")redeemScript
如果版本位元組是0,并且witness program是20位元組
- 解釋為一個 pay-to-witness-public-key-hash (P2WPKH)程式。
- 這個witness必須正好包含兩個item,且每個item小于等于520位元組。第一個是簽名,第二個是公鑰。
- 公鑰的hash160必須比對20個位元組的witness program。
- 正常腳本評估後,簽名和公鑰通過CHECKSIG操作驗證通過。驗證必須在棧上chanTRUE的輸出。
如果版本位元組是0,并且witness program是32位元組:
- 解釋為一個pay-to-witness-script-hash(P2SH)程式。
- witness必須包含一個輸入棧以供給腳本,然後是一個腳本的序列化(witnessScript).
-
被反序列,并在正常的腳本評估後使用剩餘的witness棧繼續執行(每個堆棧項小于等于520位元組).witnessScript
-
腳本一定不能執行失敗,并在棧上産生一個TRUE。
如果版本位元組是0,但是witness program既不是20位元組,也不是32位元組,這個腳本必須失敗1。
如果版本位元組是1到16,且witness program 或witness 堆棧沒有進一步的解釋,并且對于witness 堆棧沒有位元組限制。這些版本号保留給未來的拓展2。
其他的共識規則限制
Block Size
區塊目前被限制在1,000,000(1M)位元組。如下這樣改變限制:
Block wight = Base size * 3 + Total size; 3.
Base size是不帶witness資料的交易序列化後的位元組大小,具體方式檢視未更新節點。
Total Size 是BIP144中描述的交易序列化方式後的位元組大小,包含基礎資料和witness資料。
新的規則是:block wight <= 4,000,000(4M)
Sigops
目前每個塊的操作碼被限制在20,000。如下這樣改變限制:
在目前鎖定腳本,簽名腳本,P2SH檢查腳本,操作碼被計數為先前值的4倍。操作碼的限制同樣翻了一番 <= 80,000.
每個P2WPKH的交易輸入被記為1個操作碼。另外,在P2WSH
witnessScript
中的操作碼被記為與以前P2SH
redeemScript
中相同的個數。也就是說,CHECKSIG被記為一個操作碼,CHECKMULTISIG根據參數被記為1到20個操作碼。這個規則适用于标準的witness program和P2SH witness program。
額外的定義
接下來的定義沒有用于共識限制,但建議符合上述術語。
Transaction size calculations(交易位元組計算)
Transaction weight = Base transaction size * 3 + Total
transaction size。(例如:相同的方法計算block weight)
Virtual transaction size = Transaction weight / 4. (四舍五入至下一個整型)
Base transaction size = 不帶witness 資料的交易序列化後的大小。
Total transaction size = BIP144中描述的交易序列化後的位元組大小,包含基礎資料和witness資料。
新的腳本語義
盡管P2WPKH和P2WSH腳本看起來非常類似于預先隔離驗證腳本,但還是有一些顯著的不同。使用者不得假設在預先隔離見證中可花費的腳本在P2WPKH或P2WSH也可以花費。再生産網絡大規模部署之前,開發者應該在測試網絡上使用預設的中繼政策測試腳本,并且在BIP141在主網絡被激活後,使用較少的金額去測試。
共識級别的主要不同在BIP143中描述,在0号版本的witness program 為簽名驗證定義了一個新的交易摘要算法。
在參考實作版本0.13.1中,三個中繼政策和挖礦政策也被包含在第一版的隔離見證中。基于這些政策的軟分叉很可能在不久的将來提出。為了在軟分叉中造成避免無限期的延遲交易确認或永久性的資金丢失,使用者必須仔細檢視新的腳本語義。
- 在P2WPKH和P2WSH中隻接受壓縮公鑰.BIP143
- 在P2WSH中OP_IF/NOTIF的參數必須是最小的.
- 如果OP_CHECKSIG或OP_CHECKMULTISIG失敗,簽名必須是空的位元組向量.(目前的segregated witness腳本和P2WSH,請看BIP146)
示例
P2WPKH
接下來的例子是0号版本的P2WPKH
witness: <signature> <pubkey>
scriptSig: (empty)
scriptPubKey: 0 <20-byte-key-hash>
(0x0014{20-byte-key-hash})
複制
'0'在鎖定腳本中辨別接下來的push資料是一個版本位0的witness program。witness program的長度辨別腳本是一個P2WPKH類型。witness必須恰好包含2項,在witness中公鑰的hash160必須比對witness program。
簽名被如此驗證:
<signature> <pubkey> CHECKSIG
與傳統的P2PKH輸出相比,P2WPKH在scriptPubKey中占據少3個位元組,并且從簽名腳本中轉移簽名和公鑰至witness字段。
P2WPKH 嵌套在 BIP16 P2SH中
witness: <signature> <pubkey>
scriptSig: <0 <20-byte-key-hash>>
(0x160014{20-byte-key-hash})
scriptPubKey: HASH160 <20-byte-script-hash> EQUAL
(0xA914{20-byte-script-hash}87)
複制
在簽名腳本中僅包含Hash160,與鎖定腳本中的20位元組的腳本哈希進行比較,并被解釋為:
0 <20-byte-key-hash>
.
與以前的例子比較,scriptPubKey 大1位元組,并且簽名腳本大23位元組。盡管一個嵌套的witness program是不太高效,但它的支付位址是完全透明的,并且向後相容比特币0.6.0以後的所有版本。
P2WSH
接下來的示例是1-of-2的多重簽名,版本号0
witness: 0 <signature1> <1 <pubkey1> <pubkey2> 2 CHECKMULTISIG>
scriptSig: (empty)
scriptPubKey: 0 <32-byte-hash>
(0x0020{32-byte-hash})
複制
在scriptPubKey 中的'0'辨別接下來的push操作是一個版本号為0的witness program。witness program的長度辨別是P2WSH類型。在witness中最後一項被彈出,并被SHA256後,與在scriptPubKey中的32位元組進行比較,和反序列化。
1 <pubkey1> <pubkey2> 2 CHECKMULTISIG
腳本使用witness中其餘的資料進行執行。
0 <signature1> 1 <pubkey1> <pubkey2> 2 CHECKMULTISIG
P2WSH 允許最大位元組腳本位元組為10,000,520位元組的限制被繞過。
scriptPubKey 占據34位元組,而不是P2SH中的23位元組。增加位元組提升了可能的碰撞攻擊的安全性,因為2**80是不再可行。可花費的腳本與BIP16中的交易輸出相同,但被已到了witness字段中。
P2WSH nested in BIP16 P2SH
接下來的示例是1-of-2的多重簽名,版本号0,但被嵌套在BIP16的P2SH輸出中。
witness: 0 <signature1> <1 <pubkey1> <pubkey2> 2 CHECKMULTISIG>
scriptSig: <0 <32-byte-hash>>
(0x220020{32-byte-hash})
scriptPubKey: HASH160 <20-byte-hash> EQUAL
(0xA914{20-byte-hash}87)
複制
對簽名腳本中的唯一項進行HASH160,然後與鎖定腳本中的20位元組進行比較,被解釋為
0 <32-byte-hash>
.
P2WSH的witnessScript接下來如上述示例繼續執行。
與以前的示例比較,鎖定腳本是小11個位元組(降低了安全);但是,它在簽名腳本中要求了35位元組的資料。
可拓展的承諾結構(Extensible commitment structure)
在coinbase交易中新的承諾結構是哈希
witness root hash
和
witness reserved value
。
witness reserved value
目前沒有共識含義,但是在未來的軟分叉中允許成為新的共識結構。例如:如果在未來要求一個新的嚴格共識結構,在coinbase中的承諾結構将變為:
Double-SHA256(Witness root hash|Hash(new commitment|witness reserved value))
為了向後相容,
Hash(new commitment|witness reserved value)
将移動到coinbase的 witness字段,并且
witness reserved value
将通過軟分叉被記錄在另一個地方。任何數量的新的共識結構都可以通過這種方式添加。
任何對于比特币不嚴格共識的承諾結構,如合并挖礦,一定不能使用
witness reserved value
字段來保留更新比特币共識協定的能力。
無信任的未确認交易依賴鍊
Segregated witness 從根本上修正了交易延展性問題,以一種無信任的方式建構未确認的交易依賴鍊。
兩個成員,Alice和Bob,可能同意發送一定數量的比特币到2-of-2的多重簽名輸出(資金交易)。不需要簽名這個資金交易,他們就可以建立另一個交易,時間鎖定在未來,花費2-of-2的多重簽名輸出至第三方(花費交易)。ALice和Bob将簽署花費交易,并交換簽名。驗證通過簽名後,他們将簽署并送出現金交易至塊鍊。不需要進一步的操作,花費交易将在時間戳到達之後被确認,并根據原始合同釋放資金。它也保留了在時間戳之間撤銷原始合同的靈活性,通過使用一個更短的時間戳的花費交易,但是這種情況隻能在雙方達成共識的情況下發生。
BIP62 的設定不可能修複交易延展性,因為花費交易不可能在雙方沒有簽署資金交易的情況下建立。如果Alice比Bob早一步展示資金交易簽名,Bob可以無限期的鎖定資金,而無需簽署任何花費交易。
未确認的交易依賴鍊是更複雜的支付網絡基本組成部分,例如:全雙工微型支付通道和閃電網絡,可能隐式的極大提升比特币系統的可拓展性和效率。
未來的拓展
用于SPV節點的緊湊型欺詐證明
比特币目前僅含有兩種安全模式。在系統中,使用者要麼運作全節點使用所有的規則驗證每個區塊,或一個SPV用戶端僅驗證頭部作為一些交易的釋出證明。比特币白皮書建議SPV用戶端可以接收來自全節點的警告,即當全節點檢測到一個無效的區塊,提示SPV節點去下載下傳這個有問題的區塊和交易去驗證。然而,這種方法可能會成為DOS攻擊的載體,因為可以幾乎沒有成本的産生警告。警告必須具有緊湊但确定性的欺詐證明。
在目前的比特币協定中,對于幾乎所有的規則,都能産生緊湊型欺詐證明,除了特别少的一些例外:
- 當沒有展示整個區塊和它的所有交易輸入,則不可能證明礦工在coinbase交易輸出中引入了太多的比特币。
- 當沒有展示整個區塊(和所有的交易輸入操作碼),則不可能證明違反了塊的指定限制(例如:位元組和操作碼數量限制)。
- 沒有展示塊鍊中的所有的交易ID顯示在建立的區塊中,則不能證明花費了不存在交易輸入。
可以送出額外的witness資料,以允許SPV節點可以快速驗證無效的區塊的簡短證明。
- 交易費的總和可以用來建立簡短的證明,證明礦工沒有在coinbase交易中添加額外的交易費。類似于區塊的大小和操作碼計數限制。
-
可以提供交易輸入所花費的輸出的反向連結。反向連結由塊的哈希和一個偏移量組成,請用戶端可以非常容易的查詢和檢查驗證交易輸出的存在。
這些承諾結構可以通過軟分叉被包含在可拓展的承諾結構中,并且對于不了解新規則的節點将是透明的。
新的腳本系統
因為一個版本位元組在witness program之前被push, 并且使用未知版本号的program被認為是anyone-can-spend腳本,所有可以通過軟分叉引入任何新的腳本系統。witness結構不會被任何已存在的腳本語義和限制所限制,特别是520位元組的push限制,是以允許任意大的腳本和簽名。
例如:包含Schnorr簽名的新腳本系統将顯著減少多簽名交易的位元組;包含Schnorr簽名的腳本是具有抗量子計算的,以及Merklized抽象語義樹允許在非常複雜的條件腳本上含有非常緊湊的witness資料。
每個輸入的鎖定時間和相對鎖定時間
在交易中僅含有一個nLockTime字段,所有的交易輸入飛享相同的值。BIP68使用nSequence字段辨別相對鎖定時間,然而,鎖定時間和和決議有限制。
使用軟分叉,可以引入一個分離的witness結構,允許每個交易輸入有自己的鎖定時間和相當鎖定時間,并且新的腳本系統可以簽名和操作新的資料(類似于BIP65和BIP112)。
向後相容
作為一個軟分叉,舊版本的軟體将沒有任何變化的繼續執行。未更新的節點,将不能看到并驗證witness資料,并且認為所有的witness program都是anyone-can-spend腳本(除了一些邊緣的案例,witness program等于0,該腳本執行肯定失敗)。錢包應當一直警惕anyone-can-spend腳本,并對他們持懷疑态度。所有未更新的節點強烈建議去更新,以便可以采用新功能。
未更新的錢包可以做什麼:
- 從已更新和未更新的錢包接收比特币
- 發送比特币給未更新的錢包,并且更新傳統P2PKH位址的錢包(沒有隔離見證交易的好處)
- 使用P2SH位址發送比特币給更新的錢包
- 通過BIP70 支付協定,使用本地隔離程式發送比特币給更新的錢包
未更新的錢包不可以做什麼:
- 驗證隔離見證交易。它假設這樣的一個交易是一直有效的。
部署
該BIP通過BIP9的版本位元組和SegWit名稱,使用bit 1的位置進行部署。
主網絡的部署時間(都為BIP9的中位數時間):開始:2016.11.15; 結束:2017.11.15
測試網路的部署時間(都為BIP9的中位數時間): 開始:2016.05.01; 結束:2017.05.01
腳注:
案例: 攜帶OP_0以及40個非0位元組PUSH資料的鎖定腳本,由于不正确的位元組長度,将導緻驗證失敗。然而,攜帶OP_0以及41個非0位元組的PUSH資料将通過,因為它不被認為是一個witness程式。
為了向後相容,對于從0到16的任何版本位元組,如果這個witness程式的CastToBool的值為0,這個腳本必須失敗。然而,這樣的哈希是一次成功的對哈希函數的原項攻擊,并且風險可以忽略。
合理使用單一複合限制,替代兩個分開的限制:1M的基本資料和3M witness資料;使用兩個單獨的限制将使挖礦和交易費預估幾乎不可能。礦工将要解決一個複雜的非線性優化問題:以找到一組符合兩者的最大交易費,且錢包無法知道需要支付多少交易費,因為此時的交易費依賴于當礦工使用交易産生區塊時,這兩個條件哪個條件受到最高限制。這種方法的另一個問題是freeloading。一旦一組交易的基本資料達到1M限制,僅通過最小化增加費用就可以給witness字段添加額外高達3M的資料。在這種情況下,額外witness空間的邊際成本實際變為0.
引用實作
https://github.com/bitcoin/bitcoin/pull/8149
引用
原文位址 : https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki
BIP143 : https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki
BIP62 : https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki
BIP144 : https://github.com/bitcoin/bips/blob/master/bip-0144.mediawiki
BIP146 : https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki
本文由
Copernicus團隊 姚永芯
翻譯,轉載無需授權。