區塊鏈基礎知識
區塊鏈技術基礎
什麼是區塊鏈技術?
- 執行區塊鏈客戶端的計算節點彼此可以相互通訊。
- 每個節點維護一個賬本。
- 每個節點的收支記錄都會廣播給其他節點。
- 篩選出一個節點作為一段時間的總記錄。
- 其它節點接收該被選中的節點的記錄,和自己賬本對照後,沒有問題則進行儲存。
- 被選中的節點會因為這段時間付出的勞動而獲得一定的報酬。
- 節點通過非對稱加密的公鑰來表示身份,通過加密來傳遞資料。
區塊鏈的組成模組
- 區塊鏈賬本。區塊鏈賬本用來記錄資料,區塊分為區塊頭和區塊體,區塊頭會儲存上一個區塊的雜湊值,這樣各個區塊就串聯起來,區塊頭通過梅克爾根關聯記錄的交易事務。如果修改鏈中的某個資料塊,則會導致該資料塊無法鏈入區塊鏈賬本,在其它節點中驗證時會被發現,所以區塊鏈賬本可以防止對資料的篡改。
- 共識機制。一種篩選演算法,可以選出特定的節點,該節點會作為大家對賬的參考。
- 密碼演算法。其中包括,計算區塊hash值得演算法,計算區塊中交易事務的hash值和梅克爾根的演算法,建立賬戶、簽名交易的演算法等。
- 腳本系統。腳本系統驅動著節點收發資料,通過實現不同功能的指令碼來實現不同的業務。
- 網路路由。在由這些節點組成的網路中,沒有固定節點路由伺服器,所以每個節點都起到了路由服務者和使用者的角色,通過路由進行資料的交換。
什麼是挖礦
挖礦就是競爭獲得區塊的打包權,通過計算打包獲得報酬。
什麼是難度值?
難度值描述了獲得打包權的門檻,計算所得結果要小於該難度值才有機會獲得打包權,每段時間整個系統會更新難度值,保持10分鐘就能計算出一個區塊的速度。
初始難度值很大,很容易競爭獲得,如下是0號區塊鏈的難度值:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
值越大越容易滿足,隨著計算能力提升,為了保持每10分鐘建立一個區塊的速度,值會逐漸減小,也越來越難滿足。初始難度值表述資訊如下,bits
是上述值的壓縮值,可以通過0x00FFFF*2^(8*(0x1D-3)
恢復上述值(近似值)。將0號區塊的難度作為1,當前difficulty為初始難度值除以當前難度值:
"nonce": 2083236893, "bits": "1d00ffff", "difficulty": 1
如何獲得打包權?
每筆交易都會通過廣播的形式傳送給其它節點,所以計算節點會拉取一段時間內快取的交易記錄,然後採用如下公式計算:
SHA256(SHA256(version + prev_ hash + merkle_ root + ntime + nbits + nonce)) < TARGET
如果計算出的值小於TARGET,也就是目標難度值,就算成功了。引數解釋如下:
名稱 | 含義 | 描述 |
---|---|---|
version | 區塊的版本號 | 固定值 |
prev_hash | 前一個區塊的hash值 | 固定值 |
merkle_root | 準備打包的交易事務hash樹的根值,也就是梅克爾根值 | 可變的,由獲取的交易事務決定的,獲取交易事務也是有一定優先順序規則的,比如根據手續費大小 |
ntime | 區塊時間戳 | 要大於前11個區塊的平均時間戳,不得超過當前網路時間2個小時,可能小於前一個區塊的時間戳 |
nbits | 當前難度值 | 固定值 |
nonce | 隨機數 | 0~2^32的數值 |
想要小於目標難度值,需要不斷的嘗試各種引數組合,這個過程消耗大量計算資源。一旦計算成功,就會廣播新的區塊,其它客戶端驗證通過後會寫到自己的區塊鏈賬本中。
什麼是挖礦?
當獲得打包權後,整個區塊鏈系統會給予該客戶端賬戶一定的獎勵,這個獎勵就是打包的交易事務的第一條記錄,這個獎勵相當於發行新的貨幣。整個比特幣的數目是有限的,每隔4年獎勵的比特幣減半,真到2140年所有的比特幣將被挖完,到時挖礦的收入來源為交易的手續費。
多個節點符合條件這麼辦?
如果同時多個節點計算出符合條件的區塊,則會一起廣播,最後傳播最廣,處於最長鏈中的區塊將會被保留。
比特幣地址如何生成
- 隨機數生成器產生一個隨機數作為私鑰。
- 私鑰作為引數,用SECP256K1演算法生成公鑰,SECP256K1演算法是一種橢圓曲線演算法。但是無法從公鑰計算出私鑰。
- 計算公鑰雜湊值。通過SHA256和RIPEMD160計算公鑰的雜湊值,確保數值的唯一性。
- 將地址版本號連線到公鑰雜湊值,位元網主版本號為0x00,然後兩次SHA256取得前四個位元組作為校驗值。
- 將版本號+公鑰雜湊值+校驗值連線起來,進行BASE58編碼,最後得到比特幣地址。
比特幣如何驗證一個交易
SPV錢包的驗證過程:
- 下載完整的區塊鏈頭資料,頭資料中包含梅克爾根。
- 計算出想要驗證交易的雜湊值。
- 根據雜湊值找到對應的區塊頭。
- 獲取計算梅克爾根所需要的雜湊值。
- 計算梅克爾根。
- 對照梅克爾根是否正確。
- 根據所在區塊高度位置,可以確定該交易得到了多少確認。
比特幣如何管理交易記錄
比特幣中交易事務的模型為UTXO(Unspent Transaction Output),未花費事務輸出。使用者擁有的UTXO相當於他的資產,UTXO只記錄用戶獲得的比特幣,一個未花費事務輸出只能被使用一次。
一筆交易分為輸入和輸出。在A轉10個比特幣給B的事務中,整個模型運轉如下:
- A賬戶有兩個UTXO,分別是5個比特幣和6個比特幣。
- A找出自己名下滿足10個比特幣的UTXO,可以由多個未花費事務組成(5+6),這些UTXO作為輸入。
- 輸出則是B獲得10個比特幣的UTXO,A獲得1個比特幣(找零)的UTXO。
區塊鏈技術的意義
- 資料不可篡改。
- 分散式儲存,資料在多地存有備份。
- 匿名性。通過地址來標識使用者,而地址是通過公鑰生成,所以僅僅通過該地址無法獲取其背後的真實使用者。
- 價值專遞。自成體系的信任機制,工作量表明比特幣是有價值的,比特幣可以在任何比特幣節點傳遞。
- 自動網路共識。一個交易被其它所有節點見證,自動的達成了共識。
區塊鏈的發展
什麼是合約?
合約是大家行為的共同準則,少數人的不守約對整個系統不造成影響。
在比特幣中,所有節點都遵循合約來處理每筆轉賬交易。比如A將100比特幣轉賬給B,則A所在節點需要驗證使用的UTXO是否屬於A,並且保證裡面有足夠的錢給B,然後將該交易記錄廣播給其它所有節點,其它節點會驗證A用作輸入的UTXO是屬於A的,且真實存在的(檢視交易記錄簽名),並且這筆轉賬輸入和輸出是持平的,驗證成功後才將該交易記錄進區塊鏈。如果部分節點沒有按照上述過程轉賬和驗證,但是整個系統最終會保證結果的正確。
密碼演算法
雜湊計算
雜湊計算的特性:
- 輸入長度是任意長度
- 輸出是固定長度
- 計算過程是有效率的
雜湊函式為了滿足密碼學上的安全性,需要滿足如下條件:
- 抗衝突。兩個不同的輸入產生了相同的輸出,這就產生了衝突。為了滿足安全性,雜湊函式需要保證找出兩個輸出相同的輸入是很困難的,需要付出很大的時間代價。
- 資訊隱藏。獲得了雜湊函式的輸出,不能倒推出輸入。
- 難題友好性。在已知結果需要滿足的條件下,很難找出輸入滿足該條件。
常見的雜湊演算法:MD5,SHA1,SHA2,SHA3。
區塊鏈中用到的雜湊計算:
- 區塊鏈雜湊。區塊鏈中會對區塊頭進行雜湊計算,得出該區塊的雜湊值。該雜湊值會作為下一個區塊的一部分被儲存,所以該雜湊值起到了一個指標的作用,將各個區塊連結起來。這保證了每個區塊被加入鏈後不可被修改。
- 梅克爾樹。梅克爾根用來驗證區塊中交易記錄是否正確。比特幣中的梅克爾根是一個二叉梅克爾樹,首先對交易事務的雜湊值兩兩結對計算出新的雜湊值,然後將新的雜湊值兩兩結對計算出下一個雜湊值,依次遞迴,只到算出最後一個雜湊值,從而構成了一個雜湊樹。梅克爾樹可以驗證交易記錄的完整性。
非對稱加密演算法
常用的非對稱加密演算法:
- RSA。RSA演算法的公鑰和私鑰是一對大質數,從公鑰和密文恢復明文的難度等價於分解兩個大質數之積,質數越大破解難度越大。但是計算速度較慢。
- 橢圓曲線密碼演算法。安全性高、生成公鑰方便,儲存空間小。比特幣中使用的是SECP256k1演算法。
編碼解碼演算法
- ASCII編碼。常用的位元組編碼。
- Base64編碼。用64個字元來表示二進位制檔案,所以每3個位元組被表示為4個字元,不足3個位元組的補x00。
- Base58編碼。去掉了Base64中一些容易混淆,如0,O,I,1和容易轉義的+、/。
- Base58Check。在Base58的基礎上加上了校驗碼,比特幣在生成地址時最後就採用了Base58check,可以在接收到地址時進行校驗,如果計算出的校驗值和接收到的校驗值不同,則認為資料無效。
密碼演算法具體的應用
- 生成賬戶地址。利用公鑰生成地址和作為賬號,用私鑰驗證賬號。
- 價值轉移保衛。用私鑰簽名交易,他人用公鑰驗證交易是本人發出。用他人公鑰加密交易資料,只有接受者才能解密資料。
- 完整性證明。通過哈係數來校驗區塊資料。
- 零知識證明。為了證明自己對某筆交易的所有權,只需要解碼交易中部分內容,就能證明所有權,而不需要提交自己的密碼來驗證。
共識演算法
FLP定理(通道可靠,節點失效)
在網路可靠,存在節點失敗的最小化非同步模型中,不存在可以解決一致性問題的確定演算法。
CAP定理
分散式計算不可能同時保證一致性、可用性和分割槽容錯性。
- 一致性。所有節點在同一時刻,所處狀態相同。
- 可用性。系統可以正常被訪問。
- 分割槽容錯性。因為網路故障導致節點被劃分為不可聯通的幾塊,但系統仍能正常使用。
兩軍問題(通道不可靠)
A->B<-C
A和C需要聯合攻擊B才能取得勝利,所以雙方需要約定一個確定的時間發起進攻,兩方的信使都需要經過B,所以信使可能被B截獲。A傳送訊息給C,C需要傳送確認告訴A訊息到達,如果不傳送確認,A同樣會認為訊息被B截獲;同樣,A收到C的確認後,同樣需要傳送確認訊息給C,否則C會認為訊息被B截獲。如此往復,導致A和C無法達到最終的一致。
兩軍問題的關鍵點在於兩點之間的通道傳輸不可靠。
拜占庭將軍問題(通道可靠,節點不失效,節點產生錯誤資料)
N個將軍通過傳令兵傳遞訊息,並且需要達成一致的計劃,但是這N個將軍中存在叛徒,會故意傳送假的訊息來擾亂計劃。已經證明,如果背叛的將軍超過了1/3,則不可能達成一致的計劃。
如何實現共識
既然保證一致性存在上述問題,那麼如何實現一套實際可用的的共識演算法?
激勵機制:採用一定的激勵機制,依據博弈論,每個節點會最大化自己的利益,最後大部分節點會依照規則行事。
隨機性:拜占庭問題是每個將軍通過協調達到一致,如果有一個大將軍做出最後決定,那麼問題就會簡單很多。在去中心化的系統中,如何選出這個“大將軍”呢?
- 根據計算力,PoW共識。
- 根據資源,PoS共識。
常用的共識演算法:
- PoW。如,比特幣。
- PoS。如,PeerCoin。
- DPoS。
- Paxos。如,ZooKeeper。
- PBFT。
- Raft。如,etcd。
以下是對部分共識演算法的簡單介紹。
Paxos演算法
Paxos演算法解決的是非拜占庭問題,存在失敗節點,但沒有惡意節點。
演算法分為提案者、接收者。提案者發出提案,由接收者投票,超過半數則認為提案通過。
在處理多個提案者、多個接收者場景的時候,採用了“兩階段提交”的方案:準備階段解決對哪個提案做出表決,提交階段確認提案是否通過。
Raft演算法
該演算法通過選出一個“大將軍”角色的方式來解決一致性問題。容錯數目為(n-1)/2。
- 沒有“大將軍”時會發起選舉,每個人進行投票,票數居多的成為“大將軍”。
- 出現平票時選舉失敗,每人被分配一個隨機的睡眠時間,睡眠者只能投票,無法被選舉。第一個醒的人會發起新一輪的選舉。
- 被選出的“大將軍”和每個人保持心跳,一旦“大將軍”失效,則需要進行新的選舉。
- 由“大將軍”負責下發指令,村長收到上級指令後會向所有人傳送指令,等接收到超過半數的反饋後,“大將軍”向上級確認資料已經接收。“大將軍”接收到上級的響應後,會通知所有人資料已提交。
PBFT演算法
Pbft演算法的基本流程主要有以下四步,f表示錯誤節點數目。容錯數目為n/3。
- 客戶端傳送請求給主節點。主節點為隨機挑選出來的。
- 主節點廣播請求給其它節點,節點執行 pbft 演算法的三階段共識流程。
- 節點處理完三階段流程後,返回訊息給客戶端。
- 客戶端收到來自f+1個節點的相同訊息後,代表共識已經正確完成。
PBFT演算法多應用於聯盟鏈中,它達成共識的延時為秒級,基本滿足商業要求。
PoW工作量證明演算法
演算法流程:
- 向所有節點廣播交易;
- 每個節點收到交易資訊並放入塊中;
- 每一輪,獲得打包權的節點廣播它保留的塊;
- 其它節點驗證塊中的交易無誤後接收該區塊;
- 其它節點將接收的區塊的雜湊值放入他們建立的區塊中,以表示承認該區塊的正確性。
節點以最長的鏈為合法的鏈。節點在收到一個他人的區塊後可以選擇拒絕,或者基於該區塊繼續挖礦。如果選擇拒絕,則不得不自己計算出一個正確的區塊,但是會導致該自己另起爐灶的鏈不會長於主流的鏈,所以自己構造的鏈不會得到承認;根據“不利原理”,節點會積極的接收其他人廣播的區塊,並且基於該區塊接著挖礦。
PoW的特點:
- 完全去中心化;
- 效能消耗高,效率低;
- 達成共識的週期較長;
- 1/2的容錯率。
PoS股權權益證明
PoS不像PoW,任何人都可以參與產生區塊,而是事前需要投入一些利益在區塊鏈中,投入越多則越被信任。整個流程如下:
- 加入PoS機制的成為持幣人,成為驗證者validator;
- 根據持幣的多少挑選一個給予打包區塊的權利;
- 如果沒有在規定時間內計算出新的區塊,則選擇下一個節點給予打包權;
- 打包成功後進行廣播,被大家接受後可以獲得一定的利息,這個利息通過持幣數量和幣齡決定,每次打包成功後,會清零幣齡。
DPoS
委託權益人證明機制(Delegated Proof of Stake),在PoS的基礎上進行了改造,每個持幣人可以選出代表來代替自己計算、驗證區塊鏈,代表因此會收到一定的酬勞,代表可以主動退出、或被淘汰。該演算法減少了參與節點的數量,減少了節點響應的時間,提高了交易效率。
區塊鏈遇到的問題
區塊擴容
比特幣的區塊限制在1M,導致記錄的交易數量很少,限制了比特幣在大規模快速交易中的應用,所以提出了兩種方案來解決這個問題:
- 區塊擴容。將區塊大小設定的大一些。
- 隔離見證。從區塊中去掉見證交易合法性的簽名。
由於比特幣是無中心化的,讓所有節點進行改造是不可能的,並且這些節點的擁有者對改造的意見也不相同。所以節點的不同選擇會導致整個鏈分叉,從而形成兩種區塊鏈。
側鏈
為了讓資產可以在不同區塊鏈之間轉移而提出了側鏈的概念,主、側鏈之間的轉移步驟如下:
- 在比特幣主鏈上鎖定一定的比特幣,在側鏈上啟用對等的資產;
- 側鏈按照自己的遊戲規則交易這些資產;
- 相應的,側鏈可以凍結相應的資產,將比特幣歸還到主鏈。
閃電鏈
為了加快交易速度,減少對主鏈的壓力,提出了閃電網的概念。閃電網是在主鏈外開闢快速交易通道,臨時記錄一段時間的頻繁交易,定期將最後結果提交到主鏈。
區塊鏈存在的問題
分叉
由於部分節點採用新版本的合約,而導致和老版本的節點不相容,導致區塊鏈分叉為老節點產生的區塊鏈和新節點產生的區塊鏈,如果一直保持這種狀況,則會導致整個區塊鏈分裂為兩個系統,形成“各玩各的”局面。
除了版本差異導致的分叉,還有可能是網路問題導致部分節點被孤立起來,從而這些被割裂的節點組成一個小的區塊鏈系統,產生的區塊鏈和主鏈也會產生較大差異。在某個時刻這部分節點重新加入主鏈,則整個系統需要耗費一些代價來彌合原來產生的分歧。
51%算力
如果一個人擁有了區塊鏈超過一半的算力,他就擁有了大多數的打包權,那麼他就可以在對交易打包時進行作弊,從而從中牟利。
擁有算力優勢的人還可以拒絕一些交易記錄,使得一些交易長時間無法完成。
如果擁有算力優勢的人採用一些手段違反當初的約定,這會打擊其他人挖礦的積極性,對整個區塊鏈產生負面的影響。
私鑰丟失
私鑰丟失代表著在整個區塊鏈中所擁有的財富丟失,目前還沒有辦法找回。
交易確認延遲
非所有的交易會被立刻打包進區塊,一筆交易需要耗費一定的時間才能被計入區塊鏈。交易被確認前是快取在記憶體中的,打包區塊需要時間進行計算,並且區塊有大小限制,即使被打包進區塊還要被大多數節點接受,所以一筆交易本最終確認週期較長。
有的節點會根據手續費來控制打包的順序,所以普通的交易更難被打包進區塊了。
不斷膨脹的區塊鏈
隨著交易數量的日積月累,承載記賬功能的區塊鏈資料會越來越多,對這些資料的查詢和儲存會越來越困難。
內容參考《白話區塊鏈》