Consensus

為什麼替代客戶實施比特幣核心共識規則如此困難?

  • June 27, 2017

我知道人們永遠無法確定 alt 比特幣客戶端是否完全達成共識,但共識規則是什麼讓它們難以在其他客戶端中實施?

因為他們不知道

這聽起來可能令人驚訝,但你必須意識到比特幣的共識規則是由(經濟相關的)完整節點實際執行的內容定義的。在這一點上,我們可以假設這主要是比特幣核心的各種版本和衍生項目,但這可能會隨著時間而改變。

但是,它們肯定不是由人們祝福成為規則的某些文件定義的。即使我們以某種方式創建這樣一個文件,並且每個人都同意它,如果我們意識到實際實現中存在錯誤會發生什麼?在這種情況下,您可以將實現稱為錯誤,但您不能只是更改它。對實現的任何(不協調的)更改都可能導致它們最終出現在自己的分叉中,從而導致所有預先存在的硬幣在每一側都可以花費兩次(區塊鏈旨在防止的確切事情)。因此,在這種情況下,別無選擇,只能更改文件。本質上,比特幣的共識規則是可以描述的,但不是規定的

以上所有內容都是為了說明複製任何特定的預期行為是不夠的;您必須模仿現有軟體的確切行為。你必須:

  • 接受每一個有效的區塊,但你也拒絕每一個導致拒絕的邊緣情況。
  • 保證節點可以互相找到
  • 保證節點在各種情況下不斷地相互下載區塊
  • 防止傳遞斷開/禁止(A 不應該能夠將塊中繼到 B - 這可能執行不同的軟體 - 當 B 將其中繼到 C 時,C 斷開或禁止 B)。
  • 考慮性能因素。如果可以建構一個塊或交易需要大量時間來驗證,那麼您就可以簡化自私挖礦攻擊。如果可以使驗證時間接近塊間隔時間(10 分鐘),則整個網路的收斂可能會完全失敗。

更糟糕的是,所有這些屬性都必須在對抗環境下保持。塊可能不僅包含隨機偶然發現的邊緣情況;人們可能會積極嘗試觸發它們。

準確地模仿軟體的行為是一個非常困難的問題。雖然在可證明正確的軟體(包括證明兩個程序之間的等價性)領域取得了一些進展,但它還遠遠不夠先進到適用於比特幣的共識規則之類的東西。因此,複製的唯一方法是重新實現您認為它們已經實現的規則,而沒有強有力的方法來保證您是正確的。

簡而言之,為了複製行為,您必須知道現有行為。歷史表明,在許多情況下,現有行為並不完全清楚:

  • **OP_CHECKMULTISIG 冗餘堆棧彈出。**這個早已為人所知,但在比特幣歷史的最初幾個月甚至幾年中,它可能並不為人所知。OP_CHECKMULTISIG 操作碼從堆棧中彈出一個比需要更多的元素。人們通過在花費多重簽名輸出時推送額外的 OP_0 來解決它。BIP 147已被提議要求它甚至是 OP_0。在比特幣的早期,重新實現者可能會錯誤地複制它。
  • **壓縮和混合公鑰。**根據各種規範,secp256k1 公鑰可以採用未壓縮、壓縮或混合格式進行編碼。比特幣最初只使用未壓縮的密鑰(原始碼中的註釋表明該軟體的原作者不知道壓縮密鑰),但由於當時每個節點都使用 OpenSSL 進行驗證,人們能夠開始使用壓縮密鑰網路接受了他們。在這種情況下,規則的未知部分被“濫用”以進行改進。
  • **OP_SIZE 不彈出堆棧。**檢查堆棧元素的所有操作碼也會彈出該元素。有一個例外(OP_SIZE),至少有一個重新實現出錯了。
  • **簽名驗證失敗和腳本執行失敗的區別。**一些重新實現最初將簽名失敗視為腳本失敗(這是幾乎所有腳本的正確假設,但並非全部)。考慮一個形式的腳本<pubkey> OP_CHECKSIG OP_NOT。這是一個腳本,它消耗堆棧中的一個簽名,並要求它使用一個無效的簽名才能通過。
  • **序列化大小與標準大小。**塊、事務、腳本的大小存在各種資源限制……但是,這些大小是根據序列化資料結構產生的字節數來定義的。有時,曾經存在多個有效的序列化。在一段時間內,至少有一次重新實現使用了塊的大小(通過網路發送)來檢查塊大小限制。然而,一個 999999 字節的塊可能已經使用超過必要的序列化處理其中的事務數發送,從而可能導致 1000001 字節。這是一個有效的塊,但重新實現會拒絕它。
  • **OpenSSL 不一致的 DER 解析器。**OpenSSL 用於支持使用與 DER 標準的各種偏差進行編碼的簽名,通常具有任意限制和奇怪的差異(整數可以編碼為包含整數的結構),在數千行難以閱讀的 C 程式碼中實現。當時,每一次不使用 OpenSSL 的重新實現都可以通過創建一個濫用這些奇怪偏差的事務來輕鬆分叉。這是一個很好的例子,因為很可能沒有人確切地知道 OpenSSL 接受和不接受什麼。這最終由 BIP66 修復,這使得簽名解析更加嚴格,並允許我們在 OpenSSL 成為網路規則後遠離它。
  • **OpenSSL 簽名解析器不一致。**OpenSSL 簽名解析故事更進一步:發現其允許的 DER 偏差之一是平台相關的。特定長度的描述符在 32 位系統和 64 位 Windows 上最多允許 4 個字節,在其他系統上最多允許 8 個字節。這導致不同平台上的比特幣核心實例甚至彼此不一致,更不用說與當時的重新實現保持一致了。BIP66 也間接修復了這一發現,要求必須使用盡可能短的長度描述符。完整的時間表在本披露中。
  • **BDB 鎖定限制。**比特幣核心的早期版本(之前被稱為這種方式),直到版本 0.7.x,使用在 BDB 中實現的鏈狀態數據庫。BDB 是一個多程序數據庫環境(我們不需要的東西),它需要預先分配數量的鎖來防止對記錄的並發訪問和死鎖檢測。事實證明,選擇的鎖數量大部分足以處理比特幣塊,直到 2013 年 3 月 11 日出現一個不幸的塊。這是一個具有非常多的輸入(和很少的輸出)的塊,導致更多的交易記錄在當時的數據庫模型受到影響。超過了預先配置的鎖數,數據庫操作失敗,比特幣無法處理該塊。結果,出現了一個叉子。許多礦工已經升級到 0.8 版本的事實使情況更加複雜。0(它使用了 LevelDB 並且不再有這個鎖限制),而許多其他節點沒有。更多資訊可以在驗屍文件中找到BIP50
  • …誰知道我們還不知道哪些事情?

引用自:https://bitcoin.stackexchange.com/questions/54878