Bitcoin-Core

比特幣核心有什麼樣的漏洞必須被複製

  • April 10, 2020

為了建構目前比特幣節點接受的比特幣客戶端,我們必須模擬比特幣核心客戶端中存在的 C++ 程式碼,包括其所有屬性,甚至是錯誤。

例如,用 C++ 編寫的相同函式不會與 Python 中的函式完全相同。

我們是否有比特幣客戶端中必須存在的比特幣核心錯誤或屬性的範例?

比特幣的共識規則由(經濟相關的)執行節點定義。目前,這些主要是比特幣核心的各種版本,但沒有內在的原因會一直如此。

這意味著不能有這些規則的規範。想像一下,我們編寫了一份文件,盡可能詳細地描述了最新版本的 Bitcoin Core 所做的事情,並將其聲明為“比特幣協議”。現在,如果我們發現程式碼實際上做了一些稍微不同的事情,會發生什麼。現在哪個是錯的?程式碼還是文件?如果這是構成嚴重問題的事情(例如,偷錢),人們可能會試圖說服世界遷移到修改後的實現,或不同的實現。但這種方法不能保證:節點所有者擁有主權,沒有人可以強迫他們採用新程式碼。最後,這只是意味著我們的文件不是對規則的正確描述。

最終,這意味著我們充其量可以創建一個描述我們對共識規則的最佳知識的文件,但不能創建一個規定它的文件。人們實際執行的程式碼總是有最終決定權。

那麼為什麼我們不能準確描述目前程式碼的作用呢?因為我們不知道。了解程式碼的確切行為非常困難。在下文中,我將使用術語“怪癖”而不是“錯誤”,因為出於所有意圖和目的,這些細節構成了比特幣協議,無論好壞。這裡有些例子:

  • 最初比特幣依靠 OpenSSL 進行 ECDSA 驗證。ECDSA 被很好地指定,並且人們會期望 OpenSSL 實現的內容完全遵循該規範。它沒有。它允許與 DER 標準(指定 ECDSA 簽名中的大數字如何轉換為字節)的各種奇怪偏差。這不會破壞簽名系統的安全性(沒有私鑰的人仍然不可能生成簽名),但它確實給比特幣帶來了問題,因為這意味著我們必須永遠維護 OpenSSL 的怪癖。最終使用軟分叉解決了這個問題(BIP 66) 將有效簽名集限制為明確定義的子集。事實上,情況比這更糟糕:OpenSSL 與它自己在究竟接受了哪些與 DER 的偏差方面不一致:它在 64 位 Linux 和 Windows 上的行為不同,這將允許攻擊者在兩者之間分叉網路那兩個。你可以在這裡閱讀我對這個問題的披露(在 BIP 66 解決它之後)。
  • 2013 年 3 月,網路在執行比特幣 0.7 的節點和執行 0.8 的節點之間經歷了一次分叉。這段歷史在BIP 50中被描述為一個埠分析。問題是每個0.8 之前的版本使用了一個名為 BDB 的數據庫庫。BDB 需要配置最大數量的“鎖”(限制可以執行的同時操作的數量)。事實證明,這個數字在預設情況下有點太低了。比特幣 0.8 將 BDB 替換為沒有任何此類要求的 LevelDB。0.8 明顯更快,因此礦工迅速升級 - 並且意外建構了一個超過 0.7 使用的最大鎖數的塊。除礦工之外的大多數生態系統仍在 0.7 上,他們拒絕了多數鏈。通過讓礦工暫時恢復到 0.7、引入一個臨時軟分叉來“模擬”0.8 中的鎖定限制並最終讓整個網路在 0.8 上解決這個問題。

正如你所看到的,這些事情並不像查看一個函式並思考它的作用那麼簡單。這些例子都涉及比特幣無法控制的外部依賴,並且沒有完全指定這些行為。這並不意味著它們是怪癖的唯一來源,但它們肯定會使事情複雜化。

例如,用 C++ 編寫的相同函式不會與 Python 中的函式完全相同。

我希望您現在看到這實際上與程式語言無關。如果確切的共識規則是已知的,那麼肯定可以用另一種語言複製它們(假設也可以準確地推斷出另一種語言的行為)。相反,用相同的程式語言重新實現共識也有同樣的問題。關鍵是在處理共識程式碼時不要承擔不必要的風險——使用已經在使用的程式碼具有最低的風險,並且出於性能原因或有意的協議更改,在必要時對其進行小的易於審計的更改。

問題也不是已知的怪癖——而是未知的怪癖,我不能告訴你那些在哪裡。多年來已經發現了很多陷阱,並且在目前規則中仍然相關 - 也許這是您在問題中唯一想要的。在這種情況下,這裡有一個舊答案:Satoshi’s bitcoind implementation bugs。我會嘗試考慮是否可以提出更多最近的範例以添加到那裡。

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