ethereum當前和bitcoin一樣,採用基於工作量證明(proof of work,pow)的共識演算法來產生新的區塊。與bitcoin不同的是,ethereum採用的共識演算法可以抵禦asic礦機對挖礦工作的壟斷地位,這個演算法叫做ethash
。
為什麼要反asic
pow的的核心是hash運算,誰的hash運算更快,誰就更有可能挖掘出新的區塊,獲得更多的經濟利益。在bitcoin的發展過程中,挖礦裝置經歷了(cpu=>gpu=>asic)的進化過程,其中的動機就是為了更快地進行hash運算。隨著礦機門檻地提高,參與者久越來越少,這與區塊鏈的去中心化構想背道而馳。
因此,在共識演算法設計時,為了減少asic礦機的優勢(專用平行計算),ethereum增加了對於記憶體的要求,即在進行挖礦的過程中,需要占用消耗大量的記憶體空間,而這是asic礦機不具備的(配置符合運算那能力的記憶體太貴了,即使配置,這也就等同於大量cpu了)。即將挖礦演算法從cpu密集型(cpu bound)轉化為io密集型(i/o bound)
dagger-hashimoto
ethash
是從dagger-hashimoto
演算法改動而來的,而dagger-hashimoto
的原型是thaddeus dryja提出的hashimoto演算法,它在傳統bitcoin的工作量證明的基礎上增加了消耗記憶體的步驟。
傳統的pow的本質是不斷嘗試不同的nonce
,計算hash ha
sh_o
utpu
t=ha
sh(p
rev_
hash
,mer
kler
oot,
nonc
e)h as
h_ou
tput
=has
h(pr
ev_h
ash,
merk
lero
ot,n
once
)如果計算結果滿足ha
sh_o
utpu
trget
h as
h_ou
tput
rget
,則說明計算的nonce
是有效的
而對於hashimoto,hash運算僅僅是第一步,其演算法如下:
nonce:
64-bits.正在嘗試的nonce值
get_txid(t):歷史區塊上的交易t的hash
total_transactions: 歷史上的所有交易的個數for i = 0
to63 do
shifted_a = hash_output_a >> i
transaction = shifted_a mod total_transactions
txid[i] = get_txit(transaction) << i
endof
txid_mix = txid[0]^txid[1]...txid[63]
final_output = txid_mix ^ (nonce<<192)
可以看出,在進行了hash運算後,還需要進行64輪的混淆(mix)運算,而混淆的源資料是區塊鏈上的歷史交易,礦工節點在執行此演算法時,需要訪問記憶體中的歷史交易資訊(這是記憶體消耗的**),最終只有當 fi
nal_
outp
utrget
f in
al_o
utpu
trget
時,才算是找到了有效的nonce
dagger-hashimoto
相比於hashimoto,不同點在於混淆運算的資料來源不是區塊鏈上的歷史交易,而是以特定演算法生成的約1gb大小的資料集合(dataset
),礦工節點在挖礦時,需要將這1gb資料全部載入記憶體。
ethash演算法概要
ethash原始碼解析
dataset生成
dataset
通過generate()
方法生成,首先是生成cache,再從cache生成dataset
挖礦(seal)
在挖礦與共識中提到了,共識演算法通過實現engine.seal
介面,來實現挖礦,ethash演算法也不例外。
其頂層流程如下:
}hashmotofull()
是運算的核心,內部呼叫hashmoto()
,第三個引數為dataset
的大小(即1gb),第四個引數是乙個lookup
函式,它接收index引數,返回dataset
中64位元組的資料。
func hashimoto(hash byte, nonce uint64, size uint64, lookup func(index uint32) uint32) (byte, byte)
temp := make(uint32, len(mix))
// 進行總共loopaccesses=64輪的混淆計算,每次計算會去dataset裡查詢資料
for i :=0; i < loopaccesses; i++
fnvhash(mix, temp)
}// 壓縮mix:將32個uint32的mix壓縮成8個uint32
for i :=0; i < len(mix); i +=4
mix = mix[:len(mix)/4]
// 用8個uint32的mix填充32位元組的digest
digest := make(byte, common.hashlength)
for i, val := range mix
// 對seed+digest計算hash,得到最終的hash值
}
驗證(verify)
驗證時verifyseal()
呼叫hashimotolight()
,light表明驗證者不需要完整的dataset,它需要用到的dataset中的資料都是臨時從cache中計算。
func hashimotolight(size uint64, cache uint32, hash byte, nonce uint64) (byte, byte)
return data
}return hashimoto(hash, nonce, size, lookup)
}
除了lookup
函式不同,其餘部分hashimotofull
完全一樣
總結ethash相比與bitcoin的挖礦演算法,增加了對記憶體使用的要求,要求礦工提供在挖礦過程中使用了大量記憶體的工作量證明,最終達到抵抗asic礦機的目的。
參考資料
1 ethash-design-rationale
2 what-actually-is-a-dag
3 why-dagger-hashimoto-for-ethereum
以太坊原始碼分析 Whisper
whisper具有以下基本特性和概念 通訊加密 每一條whisper訊息在網路上都是加密傳輸的,可以選擇非對稱加密 橢圓曲線 和對稱加密 aes gsm 兩種加密演算法之一。envelope 信封 envelope是網路中傳輸的whisper訊息的基本單位,它包含已加密的原始訊息以及訊息相關的控制資...
以太坊挖礦返回null原始碼分析
在以太坊版本1.7.3中,無論是dev環境或是公鏈環境在console中執行miner.start 始終返回null,而不是期待的true。這是為什麼呢?這篇文章就帶大家從原始碼中找找原因。在這個過程中我們會了解到更多底層的知識。首先看一下呼叫挖礦的程式,在console中我們執行的是 miner....
以太坊原始碼分析 交易的執行
以太坊是乙個執行智慧型合約的平台,被稱作可程式設計的區塊鏈,允許使用者將編寫的智慧型合約部署在區塊鏈上執行。而執行合約的主體便是以太坊虛擬機器 evm 區塊 交易 合約 區塊鏈由區塊 block 組成,而區塊中打包一定數量的交易 transaction 交易可能是乙個單純的轉賬操作,也可能是呼叫乙個...