本文上半部分為 David A. Harding 在 Bitcoin Stack Exchange 問答網站上的回覆,解釋了 “時間扭曲攻擊”。時間扭曲攻擊是 “共識清理(The Great Consensus Cleanup)” 軟分叉提議嘗試解決的一種共識層面的弱點。然而,在應用共識清理軟分叉的 testnet 4 上,開發者 Zawy 又發現了一種類似的攻擊。下半部分為 murch 在 Delving Bitcoin 論壇上對該攻擊方式的介紹,以及他推薦的緩解方式。
時間扭曲攻擊
作者:David A. Harding
比特幣協議(共識規則)對區塊頭中的時間戳有兩項相關的規則:
- 節點不會接受一個時間戳超過本地時間 2 個小時以上的區塊。
- 一個區塊的時間戳必須超過過往 11 個區塊的中值(median),這是它被節點接受的前提。這條規則被稱為 :“過往時間中值(MTP)”。
就像你在問題中提到的,挖礦難度的變化幅度,是基於一個長達 2016 個區塊的難度調整週期的第一個區塊和最後一個區塊的時間戳(的差值)計算出來的。
給定上述規則,如果所有礦工一致行動,他們可以在一個週期的前 2015 個區塊中,按照 MTP 規則,讓每一個區塊的時間戳僅往前撥 1 秒(相比其上一個區塊)(這是 MTP 規則允許的最小增幅)。這樣做就僅僅只會帶來難度的些許降低,但想想看,在他們將最後一個區塊的時間戳撥到稍稍超過當前真實時間時,MTP 規則會怎麼樣:中值根本不會改變。
真實的時間戳是以秒為單位的,但這裡我們用天為單位,表示一組以當前時間為基準的 11 個時間戳:
[-13, -13, -13, -13, -13, -13, -13, -13, -13, -13, 0]
譯者注:前面的 “-13” 意味著這些時間戳表示的時間是真實時間的 13 天以前。
那麼,這 11 個區塊的時間戳中值依然是 -13,意思是,在礦工在難度調整週期的最後一個區塊中使用稍稍超過當前時間的時候,再往後,他們就又不需要讓時間戳往前撥動超過 1 秒了 —— 下一個難度週期的第一個區塊,又可以使用 -13 的時間戳,也即該難度週期又從 13 天以前開始。
在這第二個難度調整週期的末尾,礦工們可以再次將時間戳儘可能往前撥,所以,協議會認為花了 28 天才挖出這個週期的所有區塊 —— 只達到預期速度的一半 —— 所以,就將再下一個週期的挖礦難度降低一半。
在這個時刻,用在 MTP 規則中的數值看起來是這樣的:
[-27, -27, -27, -27, -27, -27, -27, -27, -27, -27, 0]
礦工可以不斷重複這種攻擊(將一個週期中前面的區塊的時間戳儘可能往後撥,將最後一個區塊的時間戳儘可能往前撥),不斷降低難度,直到挖出 2016 區塊用時不到 2016 秒,也即無法進一步降低難度的時候(因為 MTP 要求每個區塊的時間戳至少要推進 1 秒)。
你的主要問題是,這樣的攻擊,如果沒有礦工多數的串通,是如何可能的。現在你已經看到了,在所有礦工都串通的時候,攻擊是如何可能的。應該可以看出,對時間戳的選擇,讓一個足夠幸運、能夠找到區塊的攻擊者礦工可以可靠地阻止中值時間跳轉到一個誠實的數值。
舉個例子,設想過往 11 個區塊的時間戳是這樣的:
[-27, 0, -27, 0, -27, 0, -27, 0, -27, 0, -27]
如果你排序這些時間戳、找出中值,你會發現中值是 -27,即使 5/11(45%)的哈希算力都是誠實挖礦的。但是,這豈不意味著攻擊者礦工還是要擁有 55% 的哈希算力?也許不用,對於一個佔有超過 30% 的哈希率的大礦工來說,可以使用 “自私挖礦” 攻擊來獲得優勢,或者該礦工可以直接威脅要讓其它擁有誠實時間戳的區塊變成過時的、無後續的區塊(“孤兒塊”)、讓誠實礦工只能賺到更少收益。
我個人並不認為這種攻擊在比特幣上很有可能出現,因為它執行起來很慢,而且很顯眼,但別的一些協議的設計者可能在改變參數需要留個心眼,因為這些參數更改可能讓攻擊更容易執行。
Zawy 的另類時間扭曲攻擊
原文鏈接:https://delvingbitcoin.org/t/zawy-s-alternating-timestamp-attack/1062
作者:murch
@zawy 昨天在 Testnet 4 PR 中介紹了一種攻擊。我會用我的理解表述一下。
類似於時間扭曲攻擊,這種攻擊要求攻擊者能夠選擇佔多數的區塊的時間戳,但與時間扭曲攻擊不同的是,它並不依賴於難度調整週期不重合的特點(即,在度量難度週期持續期時候的差一錯誤(off-by-one error))。這種攻擊看起來在理論上是可靠的,雖然需要執行 16 星期的自私挖礦(而且可能要以 50% 的哈希算力為前提),理應使其變得不現實。
這種攻擊的大體思路是扣住絕大多數區塊的時間戳,但在難度調整週期的最後一個區塊交替放置表示未來和表示過去的時間戳,從而在最大限度降低和提高難度之間來回跳躍。這種過熱與低溫,讓攻擊者可以在相同時間內製造出比誠實礦工的的預期產出數量多得多的區塊。
具體來說,攻擊者是這樣做的:
攻擊者先讓時間戳儘可能往後撥。在最初的描述中,時間戳每個區塊只推進 1 秒,但時間戳只需每 6 秒推進一次。礦工佔據稍微佔多數的哈希算力,所以我們預期,區塊會每 20 分鐘出現一個。我們假設出塊的速度在一個難度週期中是恆定的,以簡化討論:
標籤 高度 MTP [s] 時間戳 [s] 實際經過的時間 難度 起點 0 < 0 0 0 D 1 < 0 0 20 min D 2 < 0 0 40 min D 3 < 0 0 60 min D … … … … … 6 0 1 2 h D … … … … … 12 1 2 4 h D … … … … … 攻擊者將難度調整週期的最後一個區塊的時間戳設為攻擊起始日期的 8 周以後。這個區塊不會被其它節點接受,因為它超過了節點的本地時間兩個小時以上,那麼攻擊者在這裡(暫時)將自己從網絡中分叉出去。然而,這個表示未來的時間戳,讓攻擊者可以將下一個週期的難度變成本週期難度的 1/4 。第二個難度調整週期的第一個區塊的時間戳也需要設為(攻擊起始日期的) 8 周以後,以應對共識清理提議的要求。
標籤 高度 MTP [s] 時間戳 [s] 實際經過的時間 難度 起點 0 < 0 0 0 D … … … … … 2014 335 336 4 周 – 40 分鐘 D 2015 335 8 w 4 周 − 20 分鐘 D 2016 336 8 w 4 周 D/4 攻擊者繼續在第二個難度週期中挖礦,以儘可能少的幅度推進時間戳,並再次將最後一個區塊的時間戳推進到又 8 周以後,從而再次將難度降低 4 倍。因為佔據了大約一半的哈希算力,攻擊者挖完第一個難度週期需要 4 周,但第二個難度週期就只要 1 周了。
標籤 高度 MTP [s] 時間戳 [s] 實際經過的時間 難度 起點 0 < 0 0 0 D 1 < 0 0 1200 D … … … … … 2014 335 336 4 周 – 40 分鐘 D 2015 335 8 w 4 周 − 20 分鐘 D 2016 336 8 w 4 周 D/4 2017 336 337 4 周+ 5 分鐘 D/4 2018 336 337 4 周 + 10 分鐘 D/4 … … … … … 4030 671 672 5 周 − 10 分鐘 D/4 4031 671 16 w 5 周 − 5 分鐘 D/4 4032 672 16 w 5 周 D/16 4033 672 673 5 周 + 75 秒 D/16 Zawy 也稱攻擊者可以為難度調整的最後一個區塊切換設置儘可能小的時間戳和儘可能大的時間戳。這會導致某些難度調整週期的名義經過時間為複數。不過,難度調整算法會將其等同於經過了半個星期,並依然將難度提高僅僅 4 倍。即使遵守共識清理提議的新限制(不允許將下一個難度週期的第一個區塊的時間戳設得比上一週期的最後一個區塊還要早),攻擊者依然可以在起始難度的 1/4 和 1/16 之間切換。攻擊者每 5/4 周就可以挖完兩個難度週期的區塊。
標籤 高度 MTP [s] 時間戳 [s] 實際經過的時間 難度 起點 0 < 0 0 0 D 1 < 0 0 1200 D … … … … … 2014 335 336 4 周 – 40 分鐘 D 2015 335 8 w 4 周 − 20 分鐘 D 2016 336 8 w 4 周 D/4 2017 336 337 4 周+ 5 分鐘 D/4 2018 336 337 4 周 + 10 分鐘 D/4 … … … … … 4030 671 672 5 周 − 10 分鐘 D/4 4031 671 16 w 5 周 − 5 分鐘 D/4 4032 672 16 w 5 周 D/16 4033 672 673 5 周 + 75 秒 D/16 … … … … … 6047 1007 1008 5 w 42 h − 75 s D/16 6048 1008 1009 5 w 42 h D/4 6049 1008 1009 5 w 42 h + 5 min D/4 … … … … … 8063 1343 1344 6 w 42 h − 5 min D/4 8064 1344 16 w 6 w 42 h D/16 8065 1344 16 w 6 w 42 h + 75 s D/16 … … … … … 10079 1679 1680 6 w 84 h − 75 s D/16 10080 1680 1681 6 w 84 h D/4 10081 1680 1681 6 w 84 h + 5 min D/4 … … … … … 12095 2015 2016 7 w 84 h − 5 min D/4 12096 2016 16 w 7 w 84 h D/16 12097 2016 16 w 7 w 84 h + 75 s D/16 … … … … … 一旦實際經過的時間達到 16 周,攻擊者就可以公開自己暗中挖出的鏈,並且(按照假定)其累計工作量會略微更高,從而將公開網絡上 16 周的交易活動作廢、重組大約 8064 個區塊、獲得大約 39816 個區塊的獎勵,而且可能收到比公開網絡上更多的交易手續費,因為可以打包在公開網絡緩慢出塊期間得到廣播的一切不衝突的交易。
Zawy 攻擊的變體
在昨天讀完這種攻擊的描述後,我有了一種微調它的想法:
不將週期的最後一個區塊的時間戳交替設為最小值和 16 周之後,攻擊者可以轉而在一個週期中降低到最小值,然後分兩步走向表示未來的時間戳:
label | height | MTP [s] | timestamp [s] | elapsed time [s] | difficulty |
---|---|---|---|---|---|
start | 0 | < 0 | 0 | 0 | D |
1 | < 0 | 0 | 1200 | D | |
2 | < 0 | 0 | 2400 | D | |
3 | < 0 | 0 | 3600 | D | |
… | … | … | … | … | |
6 | 0 | 1 | 7200 | D | |
… | … | … | … | … | |
12 | 1 | 2 | 14400 | D | |
… | … | … | … | … | |
2014 | 335 | 336 | 4 w − 40 min | D | |
2015 | 335 | 8 w | 4 w − 20 min | D | |
2nd diff period | 2016 | 336 | 8 w | 4 w | D/4 |
2017 | 336 | 337 | 4 w + 5 min | D/4 | |
2018 | 336 | 337 | 4 w + 10 min | D/4 | |
… | … | … | … | … | |
4030 | 671 | 672 | 5 w − 10 min | D/4 | |
4031 | 671 | 16 w | 5 − 5 min | D/4 | |
3rd diff period | 4032 | 672 | 16 w | 5 w | D/16 |
4033 | 672 | 673 | 5 w + 75 s | D/16 | |
… | … | … | … | … | |
6047 | 1007 | 1008 | 5 w 42 h − 75 s | D/16 | |
6048 | 1008 | 1009 | 5 w 42 h | D/4 | |
6049 | 1008 | 1009 | 5 w 42 h + 5 min | D/4 | |
… | … | … | … | … | |
8063 | 1343 | 1344 | 6 w 42 h − 5 min | D/4 | |
8064 | 1344 | 8 w | 6 w 42 h | D/16 | |
8065 | 1344 | 8 w | 6 w 42 h + 75 s | D/16 | |
… | … | … | … | … | |
10079 | 1679 | 1680 | 6 w 84 h − 75 s | D/16 | |
10080 | 1680 | 16 w | 6 w 84 h | D/64 | |
10081 | 1680 | 16 w | 6 w 84 h + 19 s | D/64 | |
… | … | … | … | … | |
12095 | 2015 | 2016 | … | D/64 | |
12096 | 2016 | 2017 | … | D/16 | |
12097 | 2016 | 2017 | … | D/16 | |
… | … | … | … | … | |
14111 | 2351 | 2352 | … | D/16 | |
14112 | 2352 | 8 w | … | D/64 | |
14113 | 2352 | 8 w | … | D/64 | |
… | … | … | … | … | |
16127 | 2687 | 2688 | … | D/64 | |
16128 | 2688 | 16 w | … | D/256 | |
16129 | 2688 | 16 w | … | D/256 | |
… | … | … | … | … | |
18143 | 3023 | 3024 | … | D/256 | |
18144 | 3024 | 3025 | … | D/64 | |
18145 | 3024 | 3025 | … | D/64 | |
… | … | … | … | … |
這不僅允許攻擊者創建更多區塊,而且可以指數級降低難度。
結論
讓軟分叉對時間戳提出額外的要求,要求一個難度週期 N 的最後一個區塊的時間戳大於同一週期的第一個區塊,可能是有用的。即,要求:
$$n ∈ ℕ; timestamp_{2016×n} < timestamp_{2016×n+2015}$$
我不認為誠實挖礦在跨難度週期時推進時間戳(至少一秒,這是由現有的 MTP 規則間接引起的)的需要會跟這條規則衝突,除非像上面說得那樣對時間戳進行極端的操控。但是,就我所知,這樣的規則應該能減少這種攻擊界面。