以太坊賬戶
對于以太坊中可能出現(xiàn)的replay attack對于賬戶中的每一筆交易都加上一個nonce值來記錄這是第幾次交易,然后將nonce值和交易一起進行簽名,之后如果有人重放這筆交易,經(jīng)過驗證發(fā)現(xiàn)nonce值對應(yīng)的交易已經(jīng)執(zhí)行過一次了,就不再執(zhí)行了。所以全節(jié)點也應(yīng)該保存每個節(jié)點的nonce值。
賬戶的概念有利于合約的執(zhí)行。
- 外部賬戶(普通賬戶)
- 與比特幣中的賬戶差不多,通過公私鑰對賬戶進行控制。
- 賬戶狀態(tài):賬戶余額,nonce(計數(shù)器)
- 合約賬戶
- 不是通過公私鑰進行控制,不能發(fā)起交易,所有的交易只能由外部賬戶發(fā)起。
- 可以被調(diào)用,調(diào)用其他合約。產(chǎn)生合約賬戶的時候會返回一個地址,調(diào)用地址來調(diào)用合約。
- 合約賬戶的狀態(tài)還包括code,storage。
ETH狀態(tài)樹
數(shù)據(jù)結(jié)構(gòu)的選擇:
-
選擇使用hash表?
怎么提供merkle proof:如果使用hash表來構(gòu)造merkle tree再把根hash放到區(qū)塊頭當中。如果是這樣的話,每當發(fā)布一個新的區(qū)塊,需要將所有的賬戶狀態(tài)構(gòu)成一顆新的merkle tree,但實際上每次發(fā)生狀態(tài)變化的只有少部分賬戶。所以,簡單的將所有的賬戶組成一顆merkle tree的方法代價有點大。而且難以保持區(qū)塊鏈中全節(jié)點的一致性
-
直接使用merkle tree?
一個是不好查找和更新數(shù)據(jù)的狀態(tài)。
是否進行排序,如果不排序的話
- 查找速度更慢
- 難以保證構(gòu)建的merkle tree的結(jié)構(gòu)再區(qū)塊鏈中是一致的。這樣就會導(dǎo)致不同節(jié)點算出來的merkle tree的hash值不同。
如果進行排序:
- 數(shù)據(jù)的加入復(fù)雜度較高,如果插入一個數(shù)據(jù),那么就有可能大半棵樹需要重新計算hash值。
以太坊中選擇的數(shù)據(jù)結(jié)構(gòu):
壓縮前綴樹
trie:
壓縮后的trie:
這里的指針用的是hash指針
保存歷史狀態(tài)的必要性,在以太坊網(wǎng)絡(luò)中,出現(xiàn)分叉的情況是十分常見的,而以太坊不像區(qū)塊鏈中存儲的是簡單的交易,以太坊中的智能合約可以實現(xiàn)比較復(fù)雜的功能,所以要想通過代碼分析來實現(xiàn)狀態(tài)的回滾是比較困難的。
- 狀態(tài)中的值的存儲是先經(jīng)過序列化之后在進行存儲,采用的是RLP方式(Recursive Length Profix)
ETH交易樹與收據(jù)樹
- 交易樹: 包含交易信息
- 收據(jù)樹: 對應(yīng)每個交易都有一個收據(jù)信息,記錄交易的相關(guān)信息,有利于查找相關(guān)交易的信息
兩個樹都采用的是MPT結(jié)構(gòu)
bloom filter結(jié)構(gòu):
通過計算集合中元素的信息計算出hash值,將其對應(yīng)到一個緊湊的digest當中,將對應(yīng)的位置bit置為一。這種方式可以證明某個元素不在這個集合當中,但是不能說明某個元素在集合當中。因為會存在hash碰撞,有的采用采用多個hash算法來計算多個digest,減少hash碰撞的可能性。
塊頭里的bloom filter是下面bloom filter中的并集。
為什么用戶狀態(tài)不只保存與當前交易相關(guān)的用戶狀態(tài)
- 如果有一筆交易,是A–>B,如果只保存部分用戶狀態(tài),那么當你需要找B賬戶的狀態(tài)時,因為只保存了部分用戶狀態(tài),所以需要一直往前面尋找是否存在B賬戶,但如果B是一個新建賬戶,那么就要找到創(chuàng)世區(qū)塊才能得到結(jié)果。
GHOST協(xié)議
如果繼續(xù)使用比特幣中的共識協(xié)議:
用為出塊時間的縮短,所以出現(xiàn)臨時性的分叉也會增加許多,當一個大型礦池挖到一個區(qū)塊之后,他所在的區(qū)塊會更有可能成為最長合法鏈,這也就意味著其他區(qū)塊就白挖了。在比特幣中個體用戶相較于礦池來說,雖然在算力上同樣不占有優(yōu)勢,但是比特幣中的用戶還是有可能會比礦池先挖到區(qū)塊,而且挖到的這個區(qū)塊絕大多數(shù)情況下是處于最長合法鏈上的(出塊時間比較長,沒那么容易就弄出分叉然后還更長。)
GHOST協(xié)議:
核心概念:uncle block
對于挖到了區(qū)塊,但是沒有成為最長合法鏈,這種區(qū)塊被對于后面新加入最長合法鏈的區(qū)塊來說,是它的叔父區(qū)塊。如果最長合法鏈后面的區(qū)塊包含了叔父區(qū)塊,那么被包含的叔父區(qū)塊會得到7/8的出塊獎勵,但是得不到gas fee,包含叔父區(qū)塊的新區(qū)快會得到1/32的出塊獎勵。最多可以包含兩個叔父區(qū)塊。
叔父區(qū)塊的定義最多只能隔著7代,而且隨著代數(shù)的增加,叔父區(qū)塊所獲得的獎勵會逐漸減少,包含他的哪個區(qū)塊所得到的建立依舊是1/32。以太坊中的出塊獎勵并不會不斷下調(diào)。
這樣設(shè)計的意義:
- 如果不規(guī)定叔父區(qū)塊最多隔著幾代,那么會使得全節(jié)點需要保存的很多叔父區(qū)塊。
- 鼓勵盡早將叔父區(qū)塊合并到最長合法鏈當中。
對于被包含的叔父區(qū)塊:
- 交易并不執(zhí)行,等到后面的最長合法鏈包含叔父區(qū)塊中的交易的時候再執(zhí)行
- 檢查合法性,并不是檢查交易的合法性,而是這個叔父區(qū)塊是否滿足難度要求。
叔父區(qū)塊只能使分叉后的第一個區(qū)塊,后續(xù)跟著的區(qū)塊都不能在算作是叔父區(qū)塊。
如果后續(xù)的區(qū)塊也是叔父區(qū)塊的話,那么會導(dǎo)致分叉攻擊的失敗代價太小了。
進行分叉攻擊,如果我成功了,那么就可以實現(xiàn)交易回滾,就算失敗了,也能夠得到叔父區(qū)塊的獎勵。
而只認第一個區(qū)塊為叔父區(qū)塊,就可以使得分叉攻擊失敗的代價增加,從而促使分叉區(qū)塊盡早合并。
ETH挖礦算法
memory-hard mining puzzle。以此來實現(xiàn)對asic芯片的不友好性。
litecoin的挖礦算法,scrypt
生成一個較大的數(shù)組,通過選擇一個seed計算出一個hash值存放在數(shù)組的第一個位置,后續(xù)數(shù)組位置的hash值依次通過前一個數(shù)組元素的hash值計算出來。在計算puzzle的時候首先選取一個位置之后再由這個位置的hash值確定下一個要讀取的位置。循環(huán)一定次數(shù)之后在配合nonce求解符合難度要求的nonce值。
加密貨幣的使用人數(shù)越少,越不安全。因為51%的算力比較容易達成。
以太坊中的挖礦算法(ethash):
以太坊中首先采取和litecoin中類似的方式,計算出一個16M的cache,之后再根據(jù)cache算出一個較大的DAG(cache和DAG的大小每隔一段時間會增大)。在seed中某一個數(shù)組位置開始,計算出一個hash之后由這個hash得到下一個要讀取的位置,結(jié)合那個位置數(shù)組的值進行hash的更新,經(jīng)過256輪更新迭代之后,將最終算出來的hash值填入DAG中的第一個位置。計算puzzle的過程為:根據(jù)block header和初始nonce值計算得到一個hash之后由這個hash所指向的位置獲取一個位置,取出這個位置以及相鄰位置的值,計算一個hash得到下一個位置,進行同樣的操作更新hash值,循環(huán)64次得到最終hash值,與難度閾值進行比較,看是否符合難度要求,不符合則更改nonce值再次進行計算。
每隔30000個區(qū)塊,seed的值會發(fā)生變化,cache的大小會增加初始大小的1/128,根據(jù)新的seed重新生成cache。
輕節(jié)點進行驗證的時候,將所得到的區(qū)塊中的header block和nonce一起計算出一個hash,由于輕節(jié)點沒有保存,所以要臨時生成DAG對應(yīng)位置的值。(計算量略大,但是對于輕節(jié)點來說只要計算一個nonce值,但對于挖礦機來說,由于需要嘗試的nonce值太多了,不保存DAG計算效率太低了)
Pos權(quán)益證明,不需要挖礦
使用ASIC芯片挖礦是安全的?:因為ASIC芯片是一種專門的挖礦芯片,如果使用ASIC芯片實現(xiàn)了51%的攻擊,那么加密貨幣的安全性就被證明有問題,這樣比特幣的價格會下降,最后可能導(dǎo)致虧本,到時候買來的礦機又不能拿來做其他事情,就虧了。而如果普通用戶機也能挖礦,那么發(fā)動攻擊的成本就會降低,因為等到不需要挖礦的時候這些機器還可以用來干其他事情。
以太坊難度調(diào)整(此部分最好看代碼)
https://www.bilibili.com/video/BV1Vt411X7JF?p=20&spm_id_from=pageDriver
難度炸彈:為了之后轉(zhuǎn)入權(quán)益證明而設(shè)置的,就是隨著區(qū)塊數(shù)量的增加,挖礦難度會呈現(xiàn)指數(shù)增長,這樣等到之后挖礦難度變得很大的時候,就有利于轉(zhuǎn)入PoS,但是PoS還未完全開發(fā)好的時候,難度炸彈的效果就已經(jīng)顯現(xiàn)出來了。所以就有了一次難度炸彈的區(qū)塊數(shù)量回調(diào)3000000個區(qū)塊。
權(quán)益證明
工作量證明的一個比較大的缺點是,耗電
以太坊中雖然還需要處理智能合約,但是出塊時間短,耗電比比特幣挖礦要低一些。
挖礦機制是通過算力的大小來決定獲取收益的比例,而挖礦能力的大小又取決于投入的資金多少。所以權(quán)益證明的想法就是,直接通過投入?yún)^(qū)塊鏈中資金的多少來決定收益的多少,而省略了挖礦這個步驟。
比特幣中是通過算力來爭取記賬權(quán),而以太坊中則是通過所投入的以太幣的數(shù)量來爭取記賬權(quán)。就是記賬權(quán)根據(jù)幣齡來按概率分配記賬權(quán)。不需要通過挖礦,發(fā)布區(qū)塊之后同樣獲得出塊獎勵。以太幣在設(shè)立之初預(yù)留了一部分的以太幣用來給別人投資。
權(quán)益證明的優(yōu)點:
維護以太幣區(qū)塊鏈的資源是一個閉環(huán)。
在比特幣中維護區(qū)塊鏈安全的資源來自比特幣的外部環(huán)境,就是用來爭取記賬權(quán)的資源是可以通過外部環(huán)境進行獲取的(使用加密貨幣之外的錢財,進而轉(zhuǎn)換為加密貨幣中的競爭資源。用房地產(chǎn)的錢來買礦機)。比特幣在世界經(jīng)濟的總市值比較小,如果有人愿意的話,它可以比較容易的湊到51%的算力。而在以太坊中,他如果想要發(fā)動51%攻擊,那他就需要擁有以太幣系統(tǒng)中51%的以太幣,這也就意味著會有大量的以太幣收購,這樣以太幣的價格也會隨之上漲。
有些加密貨幣采取兩種方式的結(jié)合:
既挖礦也進行權(quán)益證明,占有幣比較多的挖礦難度對應(yīng)降低。但是如果簡單的這樣進行設(shè)計會導(dǎo)致幣多的人挖礦越來越容易,進而獲得更多的幣,然后挖礦又會更加容易。所以有些設(shè)計成挖到區(qū)塊之后一段時間內(nèi)幣不能馬上繼續(xù)使用。
權(quán)益證明中存在的挑戰(zhàn):
兩邊下注:
就是當區(qū)塊鏈出現(xiàn)分叉之后,可以同時在兩邊進行下注(權(quán)益證明需要交類似于保證金一樣的東西來獲得權(quán)益,為了防止節(jié)點打包違法的交易,如果打包了違法的交易,就會得不到出塊獎勵,而且保證金也會被拿走),這種兩邊下注的行為在工作量證明的情況中是會分散算力的,而在權(quán)益證明中則沒有這種問題
Casper:區(qū)塊鏈中準備使用的權(quán)益證明
在挖礦和權(quán)益證明的混合階段,Validator(驗證者)成為Validator的前提是要投入一定金額的保證金。其職責是推進系統(tǒng)達成共識。Validator投票來決定哪一條鏈成為最長合法鏈,2/3以上的票數(shù)才可以通過。
每50個區(qū)塊為一個epoch在每一個epoch后進行一次投票。只有當連續(xù)兩個epoch都有2/3以上的節(jié)點同意之后才可以確認。Validator可以從投票的這件事中得到獎勵,不過得等一段時間,這段時間可以對Validator是否合法履行職責并對其做出處理。
智能合約
智能合約是一段運行在區(qū)塊鏈上的一段代碼,代碼的邏輯定義了合約
solidity語言中的hash不支持遍歷。
bid函數(shù)后面添加的payable表示這個函數(shù)接收外部轉(zhuǎn)賬
外部賬戶如何調(diào)用智能合約
調(diào)用合約與轉(zhuǎn)賬交易是類似的,如果轉(zhuǎn)賬對象是一個合約賬戶,也就意味著調(diào)用了這個合約,具體調(diào)用的那個函數(shù)會在data域中說明
一個合約如何調(diào)用另外一個合約
-
直接調(diào)用
-
使用address類型的call函數(shù)
-
代理調(diào)用delegatecall函數(shù)
前面兩個調(diào)用的區(qū)別在于,前一個如果調(diào)用的函數(shù)出錯的話會導(dǎo)致調(diào)用的合約也跟著出錯,但是使用call函數(shù),如果調(diào)用失敗,則會返回false
fallback函數(shù)(如果沒有找到對應(yīng)的函數(shù)就調(diào)用這個函數(shù))
智能合約的創(chuàng)建和運行
汽油費(gas fee)
以太坊中會一次性扣除最大的汽油費,如果最后算出來需要的汽油費沒有達到那個標準,會退回多收的汽油費,如果不夠,則會導(dǎo)致回滾,而且收掉的汽油費不退回。(感覺區(qū)塊鏈中一個防止惡意攻擊的有效方法就是讓一些攻擊方法的失敗付出較大的代價)
交易過程中如果出現(xiàn)任何錯誤,會導(dǎo)致整個交易回滾,就好像沒有發(fā)生過這個交易一樣。
一個發(fā)布的區(qū)塊所容許的最大汽油費有限制,就是為了防止發(fā)布的區(qū)塊過度消耗資源。類似于比特幣中區(qū)塊大小不能超過1M。
錯誤處理
revert()無條件拋出異常
嵌套調(diào)用
任何智能合約中對帳戶的操作都是對本地所保存的狀態(tài)樹的操作,只有發(fā)布到區(qū)塊鏈網(wǎng)絡(luò)上之后才會被共識
先執(zhí)行交易在進行挖礦,因為如果不先執(zhí)行,狀態(tài)樹就沒有辦法確定,也就沒有辦法算出root值,就沒有辦法嘗試nonce值。
如果有的礦工不對新發(fā)布的區(qū)塊進行驗證會怎么樣?如果不進行驗證就沒法繼續(xù)進行挖礦。因為驗證的過程就是將發(fā)布的區(qū)塊鏈中的內(nèi)容再執(zhí)行一遍,不執(zhí)行的話后續(xù)繼續(xù)挖礦所得到的狀態(tài)就會與其他節(jié)點不一致而導(dǎo)致不被承認。另外一種做法是將別人執(zhí)行完之后所得到的三棵樹復(fù)制一份,這樣的做法類似于礦池的做法。(直接從發(fā)布的區(qū)塊上是得不到樹中的內(nèi)容的,只有一個hash在塊頭里)
發(fā)布到區(qū)塊鏈上的交易并不一定都是成功執(zhí)行的,因為如果不發(fā)布的話是沒有辦法扣掉汽油費的。
Receipt數(shù)據(jù)結(jié)構(gòu)
智能合約可以獲得的相關(guān)信息
文章來源:http://www.zghlxwxcb.cn/news/detail-635529.html
三種轉(zhuǎn)賬方式:
- transfer()會引起連鎖回滾,給的汽油費很少
- send()不會引起連鎖回滾,給的汽油費很少
- call.value()會將剩下的汽油費都發(fā)過去
智能合約如果設(shè)計不好,可能會導(dǎo)致存進去的錢取不出來。文章來源地址http://www.zghlxwxcb.cn/news/detail-635529.html
到了這里,關(guān)于區(qū)塊鏈之以太坊的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!