作者:BitMEX Research
摘要:在比特幣區塊鏈上,有兩對一模一樣的交易,其中一對夾在另一對之間,而且全都出現在 2010 年 11 月中旬。重合交易可能會導致混淆,而比特幣開發者已經想盡各種辦法與之搏鬥了多年。這問題仍未得到完全解決,下一次可能重合會發生在 2046 年。雖然現在與重合交易有關的風險是很小的,但它依然是一個值得思考的有趣 bug。

概述
正常的一筆比特幣交易會花費來自過往交易的至少一個輸出,也即是會引用前序交易的交易標識符(TXID)。這些未花費的輸出只能花費一次 —— 要是能花費兩次,那就意味著你可以重複花費同一筆比特幣,那比特幣就沒有價值了。然而,實際上,比特幣鏈上出現過兩對完全一樣的交易。這是有可能的,因為 coinbase 交易(讓出塊者獲得區塊獎勵的交易)並沒有任何交易輸入,而是產生了新的貨幣。因此,有可能兩筆不同的 coinbse 交易會發送相同的數額到同一個地址中、並以完全相同的方式構造出來,從而它們是完全一樣的。因為交易是一樣的,所以它們的 TXID 也是一樣的(TXID 是交易數據的哈希摘要)。除此之外,導致 TXID 重合的唯一可能性便是哈希碰撞(兩個不同的原像產生了完全相同的哈希值);對於一種密碼學安全的哈希函數來說,這被假設是不太可能的、不會出現的。對於 SHA256 哈希算法來說,哈希碰撞在比特幣和其它地方都從來沒有發生過。
這兩對相同的交易的發生時間都很接近,在 2010 年 11 月 14 日 UTC 時間 08:37 到 2010 年 11 月 15 日 UTC 時間 00:38 之間。第一對交易交易把第二對交易夾在中間,就像三明治一樣。我們將 d5d2….8599 當作第一對重合交易,因為它是最先出現重合的,雖然(奇怪的是),更早的一筆交易 e3bf….b468 與未來的一筆交易產生的重合。
重合交易的細節
在下文中,你可以看到來自 mempool.space 區塊瀏覽器的兩張截圖,它們是第一對重合交易,發生在兩個不同的區塊中。


有趣的是,如果你給區塊瀏覽器網站輸入相關的 URL 來查詢它們,mempool.space 區塊瀏覽器在顯示第一對重合交易(d5d2….8599)時默認顯示更早的區塊(高度 91812)中的那一筆;而在顯示第二對重合交易(e3bf….b468)時則默認顯示更晚的區塊(高度 91880)。Blockstream.info 和 Btcscan.org 的結果也是一樣的。根據我們的基礎測試,Blockchain.com 和 Blockchair.com 不一樣,它們總是顯示更新的那一個區塊。
在這裡涉及到的 4 個區塊中,只有一個包含了 coinbase 交易以外的其它交易,那就是高度為 91812 的區塊;該交易將 1 BTC 和 19 BTC 彙集成一個價值 20 BTC 的輸出。
這些輸出能夠花費嗎?
因為有兩對一模一樣的 TXID,後來的交易要引用它們就發生了難題。每一筆重合交易都價值 50 BTC。因此,這些重合交易總計涉及 4 * 50 BTC = 200 BTC;或者,也可以說是 2 * 50 BTC = 100 BTC,這就取決於你怎麼理解它們了。從一個角度看,有 100 BTC 並不存在。截至今日,全部 200 BTC 都還沒有被花費。就我們所知(不一定完全準確),如果有人知道這些輸出背後的私鑰,那麼可以花費這些比特幣,然而,一旦花費,這些 UTXO 就將從數據庫中移除,而相關重合交易中的 50 BTC 就會因此變得不可花費(丟失),所以,只有 100 BTC 是可以找回的。至於花費的到底是來自哪個區塊的交易(較早出現的那一筆還是較晚出現的那一筆),那是無法定義的,不可能說得清楚。
在重合交易產生之前,當事人是可以花費交易中所有的比特幣的;當事人可以之後再創建重合輸出,從而在數據庫(或者說未花費輸出集合)中創建一個新的條目。如果真是這樣,那就意味著不僅會出現重合交易,還可能出現帶有重合的已花費輸出的重合交易。如果真是這樣,那就開啟了創建甚至更多重合交易的可能性,在這些輸出被花費的時候,產生重合交易的鏈條。當事人得非常小心安排事件的順序,確保總是在重合交易創建之前先花掉它,不然,可能就有一部分比特幣永遠找不回來了。這些新的重合交易將不是 coinbase 交易,而是 “常規” 交易。幸運的是這一切沒有發生。
重合交易帶來的問題
重合交易顯然是壞事。它會給錢包和區塊瀏覽器帶來混淆,讓比特幣的來源變得模糊。它還產生了許多攻擊和爆破的可能性。比如說,你可能會使用兩筆重合交易,給同一個人支付兩次。然後,當這人決定花費這些資金的時候,就發現只有一半是可以花費的。還比如說,這也可能給交易所帶來危險、讓交易所資不抵債,攻擊者沒有任何代價,因為他們可以在存入資金後立即要求取款。
禁止帶有重合 TXID 的交易
為了緩解重合交易問題,在 2012 年 2 月,比特幣開發者 Pieter Wuille 提出了 BIP30,這個 BIP 禁止了創造與已有 TXID 重合的交易,除非之前那筆交易已被完全花費掉。這一軟分叉應用在 2012 年 3 月 15 日之後的所有區塊上。
在 2012 年 9 月,比特幣開發者 Greg Maxwell 修改了規則,將 BIP30 檢查應有在所有區塊上(而不僅僅是 2012 年 3 月 15 日之後產生的區塊)。上文提到的兩組重合交易被處理為例外。這修復了一些 DoS 漏洞。技術上來說,這是另一次軟分叉,雖然規則變更僅適用於 6 個月以前產生的區塊,所以不具備常規的協議規則變更所具有的任何風險。
BIP30 檢查是重度計算。節點必須檢查一個新區快中的所有交易輸出,看哪一個輸出的輸出點(output endpoints)是否已經存在於 UTXO 集中。這可能是為什麼 Wuille 設計了只檢查未花費的輸出。如果要檢查(從創世區塊以來的)所有輸出,那計算量會更加恐怖,而剪枝模式也不再可能實現。(譯者注:剪枝模式是刪去一部分歷史區塊,但保留完整的 UTXO 集,從而可以驗證新區塊的節點運行模式。)
BIP34
在 2012 年 7 月,比特幣開發者 Gavin Andresen 提出了 BIP34,這個軟分叉在 2013 年 3 月激活。該協議變更要求 coinbase 交易包含區塊高度,同時啟用了區塊格式的版本區分。區塊高度要作為添加到 coinbase 交易的 scriptSig(腳本簽名)中的第一個元素。conbase 交易腳本簽名中的第一個字節要指明區塊高度數字所用的字節數量,然後就是區塊高度數字本身。在第一個 160 年(2 ^ 23 / (144 blocks/day * 356 day/year))裡,第一個字節應該都是 0x03。這就是為什麼今天的 coinbase 腳本簽名(的十六進制編碼)總是以 03 開頭。這一軟分叉似乎完全解決了重複交易問題,現在所有交易都應該是獨一無二的了。
在 BIP34 已經得到採用之後,2015 年的 11 月,比特幣開發者 Alex Morcos 向 Bitcoin Core 軟件倉庫添加了一個合併請求,該變更意味著節點將停止執行 BIP30 檢查。畢竟,因為 BIP34 已經修復了這個問題,這種昂貴的檢查也就不再必要了。當時還不知道,但從技術上來說,這確實是一次硬分叉,會將未來以極小概率出現的區塊判為無效。現在來說,這種潛在的硬分叉不重要了,因為幾乎沒有人還運行 2015 年 11 月以前發佈的節點軟件。在 forkmonitor.info,我們正在運行 Bitcoin Core 0.10.3,它是在 2015 年 10 月 發佈的。因此,這是一個遵循硬分叉以前規則的客戶端,依然會執行昂貴的 BIP30 檢查。
區塊 198 3702 的問題
後來人們發現,有一些在 BIP34 激活以前的區塊的 coinbase 交易,其腳本簽名的開頭恰好跟未來(BIP34 規則下)有效的區塊一致。因此,雖然 BIP34 在絕大部分情況下都修復了問題,但還不是 100% 修復。在 2018 年,比特幣開發者 John Newbery 列出了這些可能重合的完全列表,如下:
| 老區塊 | 新區塊 | 預計新區塊到來的日期 |
|---|---|---|
| 209,920 | 209,921 | 28/11/2012* |
| 176,684 | 490,897 | 21/10/2017* |
| 164,384 | 1,983,702 | 13/01/2046 |
| 169,895 | 3,708,179 | 28/10/2078 |
| 170,307 | 3,709,183 | 03/11/2078 |
| 171,896 | 3,712,990 | 30/11/2078 |
| 172,069 | 3,713,413 | 03/12/2078 |
| 172,357 | 3,714,082 | 07/12/2078 |
| 172,428 | 3,714,265 | 09/12/2078 |
| 183,669 | 3,761,471 | 02/11/2079 |
| 196,988 | 4,275,806 | 12/08/2089 |
| 174,151 | 5,208,854 | 11/05/2107 |
| 201,577 | 5,327,833 | 14/08/2109 |
| 206,039 | 7,299,941 | 11/02/2147 |
| 206,354 | 7,299,941 | 11/02/2147 |
- 來源:https://gist.github.com/jnewbery/df0a98f3d2fea52e487001bf2b9ef1fd -
關於 “*” 的註解: 這些區塊已經在 2012 年和 2017 年挖出,它們的 coinbase 交易並沒有重合。209921 區塊(第一次增髮量減半的倒數第 79 個區塊)不可能重合,因為那時候還實行 BIP30 檢查。
重合 coinbase 交易的可能數量年度表

- 來源:https://gist.github.com/jnewbery/df0a98f3d2fea52e487001bf2b9ef1fd -
因此,下一個可能出現重合交易的區塊是 198 3702 高度,預計會在大約 2046 年 1 月產生。高度為 16 4384 的區塊產生於 2012 年 1 月,其 coinbase 交易發送了 170 BTC 到 7 個不同的地址。因此,如果 2046 年的一個礦工要發動這種攻擊,就不僅要能夠挖出這個區塊,還得燒掉接近 170 BTC 的手續費,總成本會稍微高於 170 BTC(包括了 0.09765625 BTC 區塊補貼的機會成本)。基於當前的比特幣匯率 88500 美元,這需要付出 1500 萬美元的代價。至於誰擁有 2012 年這筆 coinbase 交易中的 7 個地址,則是未知的,有很大概率這些私鑰以及丟失了。這筆 coinbase 交易的所有 7 個輸出都已經被花掉了,其中 3 個是在同一筆交易中花掉的。我們認為,這些資金可能跟 Pirate40 龐氏騙局有關,雖然這只是一種猜測。因此,這種攻擊似乎不僅是非常昂貴的,還幾乎是完全無用的。要花費相當相當大的一筆錢,才能將一個運行 31 年的軟件的節點從網絡中踢出。
(譯者注:此處的邏輯是,BIP34 並不禁止重合交易出現,BIP30 才禁止。因此,如果 198 3702 高度創造出了重合交易,只會對仍在運行 BIP30 檢查的節點帶來困擾 —— 將它從已經不再運行 BIP30 檢查的節點所組成的網絡中分叉出去。當然,因此也可以說,在當前,關於如何處理重合交易,我們是沒有明確標準的。)
下一個可能發生危險的區塊,其 coinbase 交易可能跟 2012 年 3 月出現的高度為 16 9985 的區塊重合。歷史上這筆 coinbase 交易的輸出只略微超過 50 BTC,遠遠低於 170 BTC。50 BTC 當然跟當時的區塊補貼有關,而在有重合危險的未來,2078 年,區塊補貼會低得多。因此,為了利用這個漏洞,礦工要燒掉大約 50 BTC 的手續費,這些手續費是拿不回來的,因為它們必須發送給在 2012 年的交易中出現的輸出。誰也不知道 2078 年比特幣的價格,但這種攻擊可能也是極度昂貴的。因此,這一問題可能不是比特幣面臨的主要風險,但依然算是一個困擾。
自 2017 年隔離見證升級以來,coinbase 交易還可以包含一個對區塊內所有交易的承諾。這些 BIP34 以前的區塊並不包含見證數據承諾。因此,為了產生重合的 coinbase 交易,礦工需要從區塊中剔除所有花費隔離見證輸出的交易,這就進一步地增加了攻擊的機會成本,因為能夠納入區塊的、支付手續費的交易就更少了。
結論
重合交易 bug 看起來不是比特幣的重大安全問題,因為利用它的難度非常高、代價非常昂貴,而且機會也很罕見。然而,這依然是一個有趣的問題,考慮到其時間尺度和重合交易的有趣特性。儘管如此,開發者已經在這個問題上花費了大量時間,2046 這個日期可能一直埋在一些開發者的腦海中,作為修復這個問題的最後期限。有不少辦法可以修復這個問題,可能需要一次軟分叉。一種可能的辦法是讓(coinbase 交易包含)隔離見證承諾成為強制要求。
(完)





