Published: Nov 11, 2019 by Cypherpunks Core
原文:比特币粉尘和空块
最近看了bitcoinj的TransactionOutput類發現了裡面的關於粉塵的一些功能。網上搜索關於比特幣粉塵的知識,發現了空塊攻擊和粉塵攻擊的一些說明,但是隻是簡單地進行表述而已。也看到了礦工如何利用各種手段進行作弊,這個可能就是區塊鏈所不能監控的了。所以我覺得區塊鏈的問題還是很多的。
什麼是空塊攻擊
空塊的意思很明確,就是區塊中沒有交易,其實不管怎麼樣應該是有一筆交易的,就是挖礦獎勵的coinbase交易。但是呢塊被接收是經過大量的計算工作量的,所以這個看起來有點不太現實。從經濟的角度來說這是不太靠譜,但是這種攻擊最大的好處就是不用啟動算力攻擊。比如說你有全網1%的算力,那麼發起空包攻擊的概率也是很大的,但是就是這1%的算力也是不小的投入。算力攻擊其實就是能控制全網51%的算力,這個時候你可以隨意更改區塊的資訊。我在想以後會不會出現網路攻擊,癱瘓大部分網路,在一小片網路中佔據算力,從本質上說,區域網內的機器也可以進行挖礦,所以也比較困難。
另外個別情況下偶爾一次,也沒有問題,但短期內頻繁空塊就是攻擊了,其效果是使交易記憶體池變大,交易平均確認時間變長。其實已經有很多礦池消滅了空塊的,技術上沒有難度的。打包空塊並不會比打包滿塊有優勢。但是有ASICBoost專利就不同了,空塊有利於ASICBoost專利的實施。
粉塵攻擊
如果要想理解粉塵攻擊就必須先理解什麼是粉塵。任何會消耗其費用三分之一以上的交易輸出都不是比特幣系統現在想要處理的東西,所以我們稱之為“粉塵輸出”,並且它們是非標準的。
一個典型的輸出是33位元組(pubkey hash +操作碼),需要輸入148位元組的消耗,所以我們將它們加在一起以找出用於傳輸這個數值的總資料量。請注意,這個公式對於任何不是付費地址輸出的東西都是錯誤的,不幸的是,我們必須遵循比特幣核心的錯誤以確保我們被認為是標準。一個更好的公式可以估計滿足所有不同指令碼類型所需的資料大小,或者只是使用硬編碼33。
// 這個是根據實時的資料進行的計算。
public Coin getMinNonDustValue(Coin feePerKb) {
final long size = this.unsafeBitcoinSerialize().length + 148;
// 計算交易費
return feePerKb.multiply(size).divide(1000);
}
// 預設是費用的3倍
public Coin getMinNonDustValue() {
return getMinNonDustValue(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(3));
}
上面的這段程式碼就是用來計算最小的輸出,如果小於這個輸出值,我們就認為這個輸出是粉塵輸出。
關於小金額的問題
如果地址上未花費輸出比較小,那麼很有可能就是使用的時候,這筆錢都不能支付交易費(這就是粉塵判斷所不能接受的),這樣會損失金額。也可以通過賬戶不停地將賬戶的錢轉移到大賬戶裡面去,看來不管是何種數字貨幣,都不能避免零頭損失的問題。我們做錢包的應用多少都存在這樣的問題。但是以太坊不是基於UTXO,而是基於賬戶多少能緩解不少的問題。
廣播攻擊
如果不停地向網路廣播大量的垃圾交易會阻塞網路,如果我們的節點能檢測出這個交易是非法的,並且停止廣播,那麼這個問題就不會很嚴重,但是如果修改了程式碼,不做這個的檢測就會出現大問題。比如說礦池大量傳送這樣的交易,這就會引起災難性的後果。