區塊鏈技術的核心概念
談到區塊鏈就不得不提一下密碼朋克(Cypherpunk):
- Tim May是密碼朋克(cypherpunk)組織的發起人,1992 年在他加州的家裏,發起了密碼朋克郵件列表組織。共同發起人包括 Eric Hughes 與 John Gilmore。
- 列出這個偉大組織中最知名的幾個名字:
- Tim May,Eric Hughes 與 John Gilmore(郵件列表組織發起人),
- Jim Bell,David Chaum (大衛喬姆),
- Phil Zimmerman (PGP),
- Julian Assange(阿桑奇,維基解密創始人),
- Adam Back (亞當·拜克),
- Wei-Dai (名字是中國的,不知道人是否華裔。他在圈子中地位尊崇)和 Hal Finney (哈爾芬尼),
- Tim-Berners Lee 爵士 (萬維網發明者),
- John Perry Barlow (賽博自由主義政治活動家)和 Nick Szabo(尼克薩博,BitGold 發明人,智能合約的發明人)。
- Facebook創始人:肖恩帕克
- 比特幣創始人:中本聰
- 該郵件組成員相關的技術發明:
- Adam Back 發明了Hashcash,使用了POW算法
- Haber / Stornetta 提出時間戳方法保證數字文件安全的協議
- 戴偉 發明了B-money,強調點對點交易和不可更改記錄
- 哈爾-芬尼 推出了 “加密現金”
- 最後中本聰借鑒了該組成員所提出的許多技術,在2008年推出了比特幣系統,並發表了白皮書《比特幣:一個點對點的電子現金系統》
區塊鏈:
- 上文中也提到了中本聰也是得益於許多組內成員提出的技術才創造出了比特幣,比特幣在一定程度上可以說是多種技術融合的實現,在當時其體現出來的思想是超前的,所以到現在才開始受到廣泛關註。把這些核心技術綜合提煉出來就形成了區塊鏈的概念,由於是多種技術的融合,所以區塊鏈技術不僅僅能夠做數字貨幣,還有其他許多的應用場景。這裏簡單提一下為什麽叫做區塊鏈:因為比特幣裏的數據是通過一個個的區塊來存儲的,然後通過hash值來把這些區塊連接起來,這樣就形成了一條由區塊組成的鏈條,所以被稱之為區塊鏈。
區塊鏈前景:
- 應用場景
- 資產:數字資產發行、支付(跨境支付)、交易、結算
- 記賬:股權交易、供應鏈金融、商業積分
- 不可篡改:溯源、眾籌、醫療證明、存在性證明
- 點對點:共享經濟、物聯網
- 隱私:匿名交易
比特幣是什麽
比特幣是一種數字貨幣,先不談什麽是數字貨幣,我們先來了解下什麽是貨幣:
- 凱恩斯《貨幣論》中說,貨幣是可以承載價值的一般等價物
一般等價物可以是任何東西,我們可以看看歷史中出現的貨幣代表:
- 貴金屬貨幣:銅幣、金銀,這類貨幣的價值在於其金屬本身的價值
- 信用貨幣:銀票,其價值取決於錢莊的背書
- 信用貨幣:法幣,其價值取決於政府央行的背書
數字貨幣:
- 一串數字,以數字的形式承載價值,其價值來自於貨幣的數學特性(持久性,可攜帶性,可互換性,稀缺性,可分割性和易識別性)而非依賴於物理特性(比如黃金和白銀)或中央權力機構的信任(比如法定貨幣),並且可以很方便的在網絡中進行全球性的交易。而其主要的核心價值還是在於信任以及流通性
數字貨幣的信任從何而來:
- 財產只受自己控制,不存在任何的中心機構以及第三方的信用機構,你的財產只在你的手上
- 無通貨膨脹,不存在央行大量印鈔的情況
- 沒有假鈔,作假的交易無法得到網絡中礦工的確認,無法得到確認的交易即無效
- 流通性好,可以全球流通,並且是點對點的直接到賬,沒有任何的中間環節
比特幣除了是數字貨幣外還是一個去中心化的記賬系統:
- 中心化的記賬系統:將賬本數據存儲到一個數據中心裏,或者說一個中心數據庫裏
- 去中心化的記賬系統:將賬本數據存儲到每一個人的電腦裏,分布式的進行存儲,每一個人的電腦裏都會有這份賬本數據
比特幣原理
賬本如何驗證:
- 如下圖,有一個賬本,這個賬本分別存儲在不同的電腦上:
那麽如果其中有一個人更改了自己電腦上的賬本,那麽不就會出現假數據了嗎。這樣情況該如何解決?
- 解決方案1:
- 一一核對賬本記錄
- 少數服從多數
- 但是效率相當的慢,該方案行不通
- 解決方案2:
- 使用hash進行驗證
- 哈希函數:Hash(原始信息)-> 摘要信息
- hash特點:
- 同樣的原始信息用同一個hash函數總能得到相同的摘要信息
- 原始信息任何微小的變化都會hash出面目全非的摘要信息
- 從摘要信息無法逆向推算出原始信息
例如下圖中,通過hash函數計算出了賬本的hash值,然後利用hash的特性進行賬本數據的比較驗證,也就是只需要對比hash值即可,那麽就要比對比整個賬本數據高效得多。這就好比我們下載文件時,經常會通過MD5來驗證文件是否已經損壞或者被修改了:
那麽計算出hash值並驗證後,這些信息存儲在什麽地方呢?區塊鏈中賬本的hash值和區塊序號以及時間戳都存放在區塊鏈的頭部分:
假設現在第一個賬本已經完成驗證且成功記賬了(存到區塊了),如果這時候又來了一個賬本,那麽當計算這個新賬本的hash時會加上上一個區塊(賬本)的hash一起進行計算。如下:
可以看到,當出現第二個賬本時,對該賬本進行hash計算,會將上一個區塊的hash也包含進去一起計算,最後得出來的才是這個新賬本的hash。
因為在計算下一個區塊的hash時必須包含上一個區塊的hash一起來進行計算才能得出,所以才會說這些區塊是通過hash串起來的。這樣也就形成了區塊鏈,每個區塊都包含上一個區塊的hash,如下:
由於這種下一個區塊永遠包含上一個區塊的hash的特性,那麽在進行賬本驗證的時候,只需要驗證最後一個區塊即可,因為到區塊鏈中最後一個區塊的hash摘要裏就是間接包含了前面所有區塊的hash,也就是驗證最後一個區塊時就可以間接驗證前面所有區塊的正確性,這樣就無需整條區塊鏈都進行逐個驗證。只需要驗證最後一個區塊,並且驗證的只是hash值,所以在速度上還是很快的。
賬戶所有權問題:
銀行系統:
- 需要去銀行開戶,提供各種資料
- 通過×××、照片、手機號、支付密碼等信息確認賬戶的所有權
比特幣系統:
- 點對點交易,沒有第三方機構
- 在比特幣系統中,賬戶就是一個地址,現在一般稱為錢包地址。賬戶 == 地址
- 交易時就是將比特幣從一個地址轉到另一個地址的過程,而且賬本上是不保存任何個人信息的,只保存交易信息
- 所以誰能使用地址進行交易,誰就擁有賬戶的所有權
- 銀行卡有密碼,相對的比特幣地址也有密碼,不同的是這個密碼是一個私鑰,誰獲得這個私鑰誰就能使用這個地址進行交易。所以私鑰要保管好,不能泄露出去。而且如果私鑰泄露了,要及時重新開一個地址,將比特幣轉走。因為私鑰與地址的關系不像是銀行賬戶與密碼的關系,私鑰和地址都是不能夠重置的,一旦泄露也就意味著這個地址已經報廢了。
我們都知道銀行賬戶與密碼是沒有緊密聯系的,而私鑰和地址則是有聯系的,因為地址就是通過對私鑰進行hash計算得出的,雖然私鑰可以推導出地址,但是地址是無法推導出私鑰的。銀行賬戶則不是由密碼計算出來的,所以私鑰不像銀行賬戶的密碼那樣能夠隨便重置的。唯一“重置”的辦法就是新開一個地址。私有與地址的關系如下:
地址: 2A39CBa2390FDe
私鑰: sdgHsdniNIhdsgaKIhkgnakgaihNKHIskdgal
Hash(Hash(fun(sdgHsdniNIhdsgaKIhkgnakgaihNKHIskdgal))) -> 2A39CBa2390FDe
- 比特幣交易紀錄看起來是這樣的:
{
"付款地址":"2A39CBa2390FDe"
"收款地址":"AAC9CBa239aFcc"
"金額":"0.2btc"
}
付款方需要擁有地址2A39CBa2390FDe的私鑰才能進行支付,在不泄露私鑰的前提下,如何證明我們擁有某個地址的所有權,也就是如何使用某個地址進行支付?這時候就需要用到非對稱加密技術(對交易進行簽名):
- 首先對交易信息進行hash計算得到摘要信息
- 然後用私鑰對摘要信息進行簽名,得到簽名信息
簽名過程大概是這樣:
1.對交易進行hash, 得到一個摘要信息(Hash值)
hash(‘
{"付款地址":"2A39CBa2390FDe",
"收款地址":"AAC9CBa239aFcc",
"金額":"0.2btc"
}‘) -> 8aDB23CDEA6
2.用私鑰對交易摘要進行簽名(付款方在安全的環境下進行,以避免私鑰泄密), 用代碼表示大概是這樣:
#參數1為交易摘要
#參數2為私鑰
#返回簽名信息
sign("8aDB23CDEA6", "J78sknJhidhLIqdngalket") -> "3cdferdadgadg"
簽名完成之後,就會開始在全網節點中廣播這筆交易,廣播內容包括:
- 交易的原始信息
- 交易的簽名信息
- 擬人來說就是相當於在某個廣場用喇叭喊了一句:我2A39CBa2390FDe支付了0.2btc到AAC9CBa239aFcc,簽名信息是3cdferdadgadg,你們來確認一下吧
廣播過程實際上是發信息到相連的其它節點,其它節點在驗證通過後再轉發到與之相連的節點。比如說A節點發起這筆交易的廣播,並讓網絡中的其他節點進行驗證。B節點與A節點相鄰,所以先收到這個廣播信息,然後又廣播給相鄰的C節點,C節點又廣播給相鄰的D節點,如此循環下去,直至廣播到整個比特幣網絡。
在其他節點收到交易信息的廣播後,就會進行驗證,主要是驗證該簽名信息是否是付款方使用私鑰對原始的交易信息進行簽名產生的,以及驗證支付方地址是否擁有足夠的支付金額。驗證過程實際是簽名過程的逆運算,用代碼表示大概過程是這樣的:
#參數1為簽名信息
#參數2為付款方地址
#返回交易摘要
verify("3cdferdadgadg", "2A39CBa2390FDe") -> "8aDB23CDEA6"
如果驗證輸出的信息和原始交易信息的hash一致,則驗證通過,記錄賬本,用代碼表示大概是這樣:
if(verify("3cdferdadgadg", "2A39CBa2390FDe")
== hash(‘{"付款地址":"2A39CBa2390FDe",
"收款地址":"AAC9CBa239aFcc",
"金額":"0.2btc"}‘)) :
# 寫入賬本
# 廣播
else:
# donothing
回顧一下簽名及驗證:
### 簽名 ###
#參數1為交易摘要
#參數2為私鑰
#返回簽名信息
sign("8aDB23CDEA6", "J78sknJhidhLIqdngalket") -> "3cdferdadgadg"
### 驗證 ###
#參數1為簽名信息
#參數2為付款方地址
#返回交易摘要
verify("3cdferdadgadg", "2A39CBa2390FDe") -> "8aDB23CDEA6"
可以看到簽名是對交易的摘要信息以及私鑰進行計算,得出簽名信息。而驗證則是通過對簽名信息和付款方地址進行一個逆運算得出交易的摘要信息,能夠成功逆運算得出交易的摘要信息就代表驗證通過,繼續廣播。
整個的交易過程及運算都不包含用戶的個人信息,保證了匿名、隱私。在安全性上,由於沒有第三方機構或信用中心,所以不會有人能夠凍結或減少你賬戶的金額。賬戶的所有權都在我們手上,只要私鑰不泄露,就能夠保證賬戶的安全性。
補充說明
上面為了更好的理解,我對一些信息進行了簡化。
比特幣系統使用了橢圓曲線簽名算法,算法的私鑰由32個字節隨機數組成,通過私鑰可以計算出公鑰,公鑰經過一序列哈希算法和編碼算法得到比特幣地址,地址也可以理解為公鑰的摘要。
為什麽要記賬(挖礦):
記賬工作:
- 記賬就是將交易記錄、交易時間、交易序號進行一個Hash打包的過程
- 這樣的一個打包過程是需要消耗計算機的計算資源以及電力的
- 既然要付出代價,為什麽還會有節點進行記賬呢?這就涉及到比特幣系統中的獎勵機制了,計算出該hash的節點能夠獲取一定數量的比特幣作為獎勵,這也就是所謂的挖礦
挖礦 - 工作量證明:
- 我們都知道現在比特幣很值錢,現在挖出一個區塊就能夠獎勵12.5個比特幣,而一個比特幣價值幾萬,那麽12.5個比特幣就是幾十萬。所以就會導致很多人爭先恐後的去挖礦,人一多起來那麽這就可能會導致記賬錯誤,所以比特幣系統中有規則來防止記賬錯誤:
- 首先在一段時間內(通常是10分鐘)只能有一個人可以記賬成功
- 並且需要通過解決密碼學難題(即工作量證明)來競爭獲得唯一記賬權,而難題的難度和計算時間以及區塊的產出時間是有聯系的,所以比特幣系統中有一個平衡算法來平衡每10分鐘左右才會產出新區塊
- 當產出新區塊進行記賬完成之後,其他節點只能復制記賬結果
- 工作量證明,通過上一個區塊的hash值和交集記錄集以及隨機數變量進行計算得出,並且計算出來的hash值根據平衡算法的規則需要以n個0開頭,只有不停地計算出滿足這個條件的hash值,才能獲取唯一的記賬權,用偽代碼表示一下:
Hash(上一個Hash值,交易記錄集,隨機數) = 0000aFD635BCD
- 我們知道改變Hash的原始信息的任何一部分,Hash值也會隨之不斷的變化,因此在運算Hash時,不斷的改變隨機數的值,總可以找的一個隨機數使的Hash的結果以若幹個0開頭,率先找到隨機數的節點就獲得此次記賬的唯一記賬權
-
在進行工作量證明之前,記賬節點會收集交集記錄集,獲取方式:
- 收集廣播中還沒有被記錄賬本的交易
- 然後驗證交易的有效性
- 接著添加一筆給自己地址轉賬的交易(挖礦獎勵),目前是12.5個比特幣
- 最後誰先計算出符合規則的hash值,就能將這筆賬記錄到挖出來的區塊中,這樣就能獲得了交集記錄集中所記錄的挖礦獎勵
工作量分析,我們簡單分析下記賬難度有多大,Hash值是由數字和大小寫字母構成的字符串,每一位有62種可能性(可能為26個大寫字母、26個小寫字母,10個數字中任一個),假設任何一個字符出現的概率是均等的,那麽第一位為0的概率是1/62(其他位出現什麽字符先不管),理論上需要嘗試62次Hash運算才會出現一次第一位為0的情況,如果前兩2位為0,就得嘗試62的平方次Hash運算,以n個0開頭就需要嘗試62的n次方次運算。我們結合當前實際區塊#522302信息來看看:
註:數據來源於 https://blockchain.info
以上這是一個真實的區塊,區塊的序號為522302,而該區塊工作量證明的hash值以20個0開頭,理論上需要嘗試62的20次方次,這個數是非常非常巨大的,我已經算不清楚了,應該是億億級別以上了。如此大的計算量需要投入大量的計算設備、電力等。可想而知這個計算量是驚人的,靠單臺計算機是無法計算出來的,所以現在的礦工都是組成礦池進行挖礦(礦池裏的礦工按算力百分比來分收益)。
驗證
在節點成功找到滿足的Hash值之後,會馬上對全網進行廣播打包區塊,網絡的節點收到廣播打包區塊,會立刻對其進行驗證。
如果驗證通過,則表明已經有節點成功計算出符合條件的hash,自己就不再競爭當前區塊打包,而是選擇接受這個區塊,記錄到自己的賬本中,然後進行下一個區塊的競爭。
網絡中只有最快得出hash的區塊,才會添加的賬本中,其他的節點進行復制,這樣就保證了整個賬本的唯一性。
假如節點有任何的作弊行為,都會導致網絡的節點驗證不通過,直接丟棄其打包的區塊,這個區塊就無法記錄到總賬本中,作弊的節點耗費的成本就白費了,因此在巨大的挖礦成本下,也使得礦工自覺自願的遵守比特幣系統的共識協議,也就確保了整個系統的安全。
以誰的賬本為準?(共識機制):
上一小節我們介紹了,完成工作量證明才能獲取唯一記賬權。但是當很多的礦工同時進行挖礦,就會出現兩個節點同時完成工作量證明的情況,這種時候該使用誰的區塊?這就涉及到比特幣中的共識機制了:
- 我們都知道比特幣是無仲裁機構進行裁決的,每個挖出區塊的礦工都會說用我的區塊,沒有一個第三方來裁決用誰的區塊。而比特幣中的共識機制就是用於解決這種問題的,共識機制就是大家都需要共同遵守的協議
- 為什麽要遵守協議?因為節點的工作量只有在其他節點認同後,才是被驗證為有效的。如果不遵守協議就無法獲得其他節點的認可,挖出的區塊就無法加入區塊鏈中,那麽礦工也就獲得不到收益,所以節點才會自發的去遵守協議
- 那麽以誰的賬本為準?答案就是取最長的那條鏈,也就是節點只會認可累計工作量最大的區塊鏈
- 而且每個節點都是獨立的,只會在最長的那條鏈上繼續進行挖礦,延長最長的那條鏈
下面我們簡單描述一下分叉的產生及解決,當不同的礦工同時挖出同一個區塊時,就會產生區塊鏈的分叉,如下:
註:因為區塊是保存上一個區塊的hash,所以箭頭是指向上一個區塊的
如上圖,在3457這個區塊上,產生了分叉,在同一時間上分別出現了3458A和3458B兩個區塊。此時,分叉不會馬上得到解決,而是3458A和3458B兩個區塊都會分別被廣播到比特幣網絡中。比特幣網絡中的節點視網絡的情況,會分別接收到3458A或3458B的廣播,也可能同時接收到3458A和3458B的廣播。只接收到3458A的節點,會基於3458A區塊上進行挖礦,而只接收到3458B的節點,則會基於3458B區塊上進行挖礦。如果同時接收到3458A和3458B的節點,會先判斷哪個區塊的工作量更大,然後就基於工作量最大的那個區塊上進行挖礦,另一個區塊則放在一個備用區塊池裏。因為網絡是不確定的,萬一最後是備用區塊池裏的那個區塊是有效的,則會把那個區塊替換回去。
我們以上提到了不同的節點只會在各自接收到的分叉區塊上進行挖礦,這樣不同的分叉鏈之間就會進行一個競爭,最後始終是有一個分叉區塊鏈的區塊產出慢了一步,這樣另一個分叉的區塊鏈會變得更長一些,那麽最終所有節點就會以那條最長的鏈作為主鏈。這樣分叉就得以解決了。說白了就是由於分叉出現的兩條區塊會進行競爭,最終總是能競爭出一個最長的區塊鏈,那麽網絡中的節點就會以那條最長的區塊鏈為準。例如,最終是3458B所在的鏈先產出下一個區塊,成為了最長的區塊鏈那麽就會以3458B所在的鏈為準:
區塊鏈技術的核心概念