從新啓用的 op codes 的用例 by Steve Shadders

在比特幣原始版本中有幾個禁用的操做碼被禁用,但在5月15日比特幣現金協議升級中將被從新激活。html

做爲啓用這些舊操做代碼規範的共同做者,我認可未能理解社區對這個修改的明確解釋的胃口。在開發人員中,能夠認爲腳本語言中基本操做的用例很是廣泛,所以不須要聲明。咱們天天都會屢次使用像算術,字符串操做和按位邏輯這樣的基本操做,而在沒有它們的狀況下編寫任何有用的代碼幾乎是不可想象的。linux

然而比特幣現金社區不只僅是開發人員。事實上,上述論點即便對開發者有吸引力,仍然沒有提供這些操做碼如何用於比特幣現金環境的具體例子。這也不能解釋爲何他們被禁用或爲何從新啓用它們是安全的。這些都是比特幣現金社區有權收聽的解釋,因此咱們試着補救。git

禁用操做碼的歷史

LSHIFT 和 RETURN 錯誤github

2010年7月28日,在測試網絡上發現並演示了兩個錯誤。一是在處理包含OP_LSHIFT的交易時,會致使比特幣程序在某些機器上崩潰。二是利用交易處理代碼中的另外一個錯誤,並容許攻擊者花費他們沒有的幣。在主網絡上都沒有被利用,而且二者都在比特幣版本0.3.5修復。數組

在發現這些錯誤以後,許多目前未使用的腳本文件因安全而被禁用。安全

基本上,因爲缺少足夠的謹慎和缺少充分時間來充分探索和解決須要解決的邊緣案例,因此決定只是簡單地禁用任何有懷疑甚至暗示疑慮的操做碼。在比特幣的早期階段,咱們很是重視對安全付款方式進行更簡單的選擇並進行全面測試。對更復雜用途的探索必然推遲到晚些時候。網絡

Peter Todd 解釋爲何OP_CAT(和其它)被禁用(即咱們惶恐不安):測試

https://twitter.com/ryaneshea...優化

更多關於操做代碼的歷史記錄:編碼

https://scalingbitcoin.org/st...

相同介紹的視頻在這裏:

https://www.youtube.com/watch...

爲何從新啓用它們?

比特幣是用豐富的腳本語言建立的。若是它的使用目的僅限於從一個私鑰到另外一個私鑰的直接支付,甚至包括多重簽名交易,則根本不須要腳本語言。這些功能能夠簡單地進行硬編碼,大大簡化了代碼。比特幣是創建在具備豐富指令集的腳本語言的基礎之上的事實代表,它始終打算成爲一個基礎平臺,使得更復雜的規則集可以管理資金轉移。將比特幣恢復到最初預期的設計(修復了錯誤)自己就是一個緣由。

7年過去了,如今圍繞這些操做代碼的邊緣案例獲得了更好的理解。此外,禁用這些措施的決定是倉促和勉強採起的。BCH社區如今已經有了充分的時間來完全解決這些問題。

7年也爲人們提供了不少時間來思考如何使用這些操做代碼。實際上,它們已經在加密生態系統的各個部分(例如Elements Alpha)中啓用,以解鎖其中一些用例。

爲何只有一些操做碼建議從新啓用?

只是爲了繼續謹慎的作法。僅爲5月15日協議升級啓用少許操做碼不只能夠限制風險,還可使全部相關開發人員更加註意每一個操做代碼。經過將變化的範圍保持得很小,它使BCH開發人員社區有機會優化啓用這些功能的過程。這個過程包括調度,開發規格,吸引同行評審,提煉,與現有的協議達成高度兼容,創建和測試驗收和發佈方法,而且固然執行以上全部內容。

什麼是一些用例?

如下是近年來已發佈或討論的用例彙編。其中不少都在多個操做碼下引用,由於它們須要多個操做碼。這份清單毫無疑問是不完整的。

OP_CAT

https://lists.linuxfoundation...

多方哈希鎖:

安全且緊湊地驗證許多哈希和哈希原像。這將大大下降鏈下 Tumblebit 交易的大小。例如交易TxA檢查交易TxB的原像 x1,x2,...,x10,使得y1 = H(x1),y2 = H(x2),...,y10 = H(x10)。

目前須要有y1,... y10,才能檢查正確的 hash 原像。

使用OP_CAT,你只須要在TxA中存儲一個 yhash

ytotal = H(OP_CAT(H(OP_CAT(y1,y2)),y3)... y10)

而後,TxA能夠對TxB提供的全部原像進行哈希處理,並確認它們hash。這會將TxA的大小從大約10 32B減少到32 + 10 16B。

https://blockstream.com/2015/...

簡單的merkle樹驗證:

這能夠在更大規模上實現多重簽名。按照目前腳本大小限制,能夠實現理論極限是40億分之一。在886字節的腳本中,能夠達到250000分之一1的限制,這在沒有OP_CAT的狀況下須要約8mb。

OP_SPLIT

https://scalingbitcoin.org/st...

OP_LEFT弱散列:

弱散列只是比日常小的散列。它們在比特幣地址中用做校驗和以提供必定程度的錯誤檢查(32位校驗出現未檢測到錯誤的機率爲2 ^ 32分之1)。它們能夠經過散列並獲取開頭(或最後)n個字節來生成。

迷你工做證實:

確保對於接收者,計算出使用迷你POW的腳本簽名是昂貴的。經過要求籤名或散列以特定的位串開頭。對小於2 ^ 32的數字可使用OP_SPLIT和OP_LESSTHAN來實現。OP_EQUALS也能夠與OP_SPLIT一塊兒用於較大的數字,但限於2 ^ n的難度,其中n必須是8的倍數(您只能使用整個字節)。對於更大的數字,OP_SPLIT和OP_AND的組合容許任何2的冪的有效難度。例如,若是但願PoW平均須要80億次嘗試來解決該腳本,則可能須要最後的33個比特爲零:

<pow_hash> SIZE 5 SUB SPLIT 0x01FFFFFFFF AND IF RETURN ELSE //完成腳本

說明:

  1. SIZE 5 SUB - 獲取pow_hash的長度並減去5
  2. SPLIT - 使用len(pow_hash)-5做爲分割點,分割最後5個字節的字節
  3. 0x01FFFFFFFF AND - 置零最左邊的7位。
  4. IF RETURN - 若是最右邊的33位不全是0,則腳本失效
  5. ELSE
  6. //完成腳本

檢查字節數組的部分。例如查看簽名的SIGHASH_FLAGS:

這是強制限制資金花費方式的一個例子。

<sig> <pubkey> | 1 PICK SIZE 1 SUB SPLIT 1 ROLL DROP

說明:

  1. 1 PICK - 將sig複製到堆棧頂部
  2. SIZE 1 SUB - 獲取sig的長度並減去1
  3. SPLIT - 使用len(sig)-1做爲分割點分割最後一個字節
  4. 1 ROLL DROP - 將分割字節的左邊部分移動到堆棧頂部,並放下它,在堆棧頂部留下sig的最後一個字節。

0x80 和 驗證

說明:

  1. 0x80 - 將0x80推入堆棧(這是ANYONECANPAY標誌,但多是其餘標誌)
  2. AND - sig的最後一個字節 & 0x80,返回SIGHASH_ANYONECANPAY,不然返回0x00。
  3. 驗證 - 若是未設置標誌則腳本失敗。
  4. //作P2PKH腳本的其他部分

堆棧狀態如今是:<sig> <pubkey>,這是p2pkh所須要的。完整的腳本將是:

<sig> <pubkey> | 1 PICK SIZE 1 SUB SPLIT 1 ROLL DROP 0x80 AND VERIFY DUP HASH160 <pubkeyhash> EQUALVERIFY CHECKSIG

使用OP_SPLIT和OP_DATASIGVERIFY:

若是交易所產生「BCHUSD:20180228:120000:132500:119500:130000」(BCHUSD市場,2018年2月28日,開盤價120000美圓/ BCH,最高132500,最低119500,收盤價130000)等簽署數據。OP_SPLIT將用於在簽名驗證以後從該數據中提取用於決策的值。例如:確認數據用於BCHUSD市場,日期爲2018-02-28,收盤值大於125000。

按位

AND / OR:設置和檢查位標誌,這是一種緊湊地表示一大組布爾值的有用方法。

若是實現這些操做中的任何一個,則另外兩個是微不足道的添加(最簡單的實現是單個案例語句和單行代碼)。經過一個操做符來實現全部其它的功能,例如對操做數長度和格式的限制。

OP_AND

檢查和清除位標誌

要求籤名使用特定的sighash標誌(請參閱OP_SPLIT下的詳細說明)。

OP_OR

設置位標誌。檢查未設置的位標誌。

OP_XOR

https://scalingbitcoin.org/st...

使用OP_XOR生成肯定性隨機數:

結合不一樣方面的祕密價值。

http://www.cs.technion.ac.il/...

使用OP_XOR和OP_MOD將兩個拋硬幣結合成一個結果。大多數論文是關於在不信任的狀況下在兩方之間進行拋硬幣的協議,最後階段是使用xor和mod將參與者選擇的隨機值組合成結果。

相似這裏描述 https://github.com/jl2012/bip...

https://en.wikipedia.org/wiki...

使用異或的快速肯定性隨機數生成:

  • 注意:這也須要OP_LSHIFT,它不在爲五月硬叉範圍內。

算術

智能合約中的任何鏈式計算都須要算術。目前可使用很是大的腳原本模擬更高階的運算符。OP_MUL是一系列OP_ADD。OP_DIV是一系列OP_SUB,同時遞增計數器並在每一步中檢查結果是否小於除數。OP_MOD是一系列OP_SUB,一旦獲得否認結果,取OP_ABS值。考慮到循環不存在於腳本中(而且從未成爲原始設計的一部分)而且腳本具備大小限制,所以存在實際限制。當兩個正在操做的值都是可變的時,它也變得更加複雜(與其中一個值是常數值相反)。

謹慎的作法是合理的,這就是爲何不是全部的算術運算符都被提議用於同一次的硬分叉。

OP_MOD

加密算術 - 目前的32位限制要求使用OP_SPLIT來實現這一點。可是,這是增長算術輸入的有效位長度的先決條件。

http://www.cs.technion.ac.il/... - 也須要OP_XOR

OP_DIV

沒有特定用例,但它是OP_MOD行爲的一個子集,而且全部適用於DIV的邊緣狀況都已由MOD解決。

數據輸入

儘管腳本沒有明確的數據類型系統,但在實踐中隱含地使用了兩種數據類型。數字和字節數組。像算術,字符串和位運算符被設計爲使用特定的數據類型(分別爲數字,字節數組和多個字節數組)。爲了減輕同行評審規範中關於這些操做碼誤用於不正確數據類型的擔心,決定引入兩個新的操做碼來提供類型間數據的安全和明確的轉換。這僅僅是爲了使腳本語言更安全且更易於使用,而不是添加特定用例。這個好處不只適用於本文提到的操做代碼,並且適用於許多現有的操做代碼。

OP_NUM2BIN

請參閱這裏的「腳本數據類型」部分:

https://github.com/shadders/u...

OP_BIN2NUM

請參閱這裏的「腳本數據類型」部分:

https://github.com/shadders/u...

結論

這份清單並不是詳盡無遺。但它確實說明,由於這些操做代碼是腳本語言的基本組成部分,因此它們的實用性很是普遍。這些都是本來不可能實現的例子。如今,他們的使用是一個真正的可能性,這是合理的,指望創造性的頭腦會更多地關注,以釋放比特幣現金經濟的進一步潛力。

相關文章
相關標籤/搜索