用python从0开始创建一个区块链,从代码深入理解区块链
作者認為最快的學習區塊鏈的方式是自己創建一個,本文就跟隨作者用Python來創建一個區塊鏈。
對數字貨幣的崛起感到新奇的我們,并且想知道其背后的技術——區塊鏈是怎樣實現的。
但是完全搞懂區塊鏈并非易事,我喜歡在實踐中學習,通過寫代碼來學習技術會掌握得更牢固。通過構建一個區塊鏈可以加深對區塊鏈的理解。
先看看什么去區塊鏈?
假如你是一位女生,在某個晚上,你男票跟你說了一句:"我愛你一生一世"; 然后,你把這句話發給了你的閨蜜、爸媽、朋友圈、公眾號、微信群等,你男票再也無法抵賴,你打賞點小費感謝他們給你記住并作證,這個小費就是token。 你、你男票、"我愛你一生一世"這句話、說這句話的時間地點等信息,打包起來形成一個結構化的信息包,這個信息包就叫"區塊"。 而你的閨蜜、爸媽、朋友圈、公眾號、微信群等節點就是鏈。最后你男票如果不承認說過這句話,當了負心漢;你翻出這個賬本對質,把他臭罵一頓,這就是區塊鏈應用。 還有啊,你男票這個節點會永遠被踢出網絡,如果你對朋友圈足夠大,這個男的可能永遠找不到女朋友了。在這個例子中好像區塊鏈解決了人與人之間的信任問題。但其實只是個假象。 N年后,男朋友對她的愛依然可能消失,海誓山盟并沒有被背書。至于,分手后對男方造成影響,更是不道德的,這分明就是一種網絡暴力。愛或者不愛,都是你們兩個的事,與區塊鏈無關。
準備工作
本文要求讀者對Python有基本的理解,能讀寫基本的Python,并且需要對HTTP請求有基本的了解。
我們知道區塊鏈是由區塊的記錄構成的不可變、有序的鏈結構,記錄可以是交易、文件或任何你想要的數據,重要的是它們是通過哈希值(hashes)鏈接起來的。
環境準備
環境準備,確保已經安裝Python3.6+, pip , Flask, requests
安裝方法:
同時還需要一個HTTP客戶端,比如Postman,cURL或其它客戶端。
開始創建Blockchain
新建一個文件 blockchain.py,本文所有的代碼都寫在這一個文件中,可以隨時參考源代碼。
Blockchain類
首先創建一個Blockchain類,在構造函數中創建了兩個列表,一個用于儲存區塊鏈,一個用于儲存交易。
以下是Blockchain類的框架:
Blockchain類用來管理鏈條,它能存儲交易、加入新塊等,下面我們來進一步完善這些方法。
塊結構
每個區塊包含屬性:索引(index)、Unix時間戳(timestamp)、交易列表(transactions)、工作量證明(稍后解釋)以及前一個區塊的Hash值。
以下是一個區塊的結構:
到這里區塊鏈的概念就清楚了,每個新的區塊都包含上一個區塊的Hash,這是關鍵的一點,它保障了區塊鏈不可變性。如果攻擊者破壞了前面的某個區塊,那么后面所有區塊的Hash都會變得不正確。不理解的話,慢慢消化,可參考{% post_link whatbc 區塊鏈技術原理 %}。
加入交易
接下來我們需要添加一個交易,來完善下new_transaction方法:
方法向列表中添加一個交易記錄,并返回該記錄將被添加到的區塊(下一個待挖掘的區塊)的索引,等下在用戶提交交易時會有用。
創建新塊
當Blockchain實例化后,我們需要構造一個創世塊(沒有前區塊的第一個區塊),并且給它加上一個工作量證明。
每個區塊都需要經過工作量證明,俗稱挖礦,稍后會繼續講解。
為了構造創世塊,我們還需要完善new_block(), new_transaction() 和hash() 方法:
通過上面的代碼和注釋可以對區塊鏈有直觀的了解,接下來我們看看區塊是怎么挖出來的。
理解工作量證明
新的區塊依賴工作量證明算法(PoW)來構造。PoW的目標是找出一個符合特定條件的數字,這個數字很難計算出來,但容易驗證。這就是工作量證明的核心思想。
為了方便理解,舉個例子:
假設一個整數 x 乘以另一個整數 y 的積的 Hash 值必須以 0 結尾,即 hash(x * y) = ac23dc...0。設變量 x = 5,求 y 的值?
用Python實現如下:
結果是y=21,因為:
在比特幣中,使用稱為Hashcash的工作量證明算法,它和上面的問題很類似,礦工們為了爭奪創建區塊的權利而爭相計算結果。通常,計算難度與目標字符串需要滿足的特定字符的數量成正比,礦工算出結果后,會獲得比特幣獎勵。
當然,在網絡上非常容易驗證這個結果。
實現工作量證明
讓我們來實現一個相似PoW算法,規則是:尋找一個數 p,使得它與前一個區塊的 proof 拼接成的字符串的 Hash 值以 4 個零開頭。
衡量算法復雜度的辦法是修改零開頭的個數。使用4個來用于演示,你會發現多一個零都會大大增加計算出結果所需的時間。
現在Blockchain類基本已經完成了,接下來使用HTTP requests來進行交互。
Blockchain作為API接口
我們將使用Python Flask框架,這是一個輕量Web應用框架,它方便將網絡請求映射到 Python函數,現在我們來讓Blockchain運行在基于Flask web上。
我們將創建三個接口:
/transactions/new 創建一個交易并添加到區塊;
/mine 告訴服務器去挖掘新的區塊;
/chain 返回整個區塊鏈。
創建節點
我們的“Flask服務器”將扮演區塊鏈網絡中的一個節點,我們先添加一些框架代碼:
簡單的說明一下以上代碼:
第15行:創建一個節點;
第18行:為節點創建一個隨機的名字;
第21行:實例Blockchain類;
第24–26行:創建/mine GET接口;
第28–30行:創建/transactions/new POST接口,可以給接口發送交易數據;
第32–38行:創建 /chain 接口, 返回整個區塊鏈;
第40–41行:服務運行在端口5000上。
發送交易
發送到節點的交易數據結構如下:
之前已經有添加交易的方法,基于接口來添加交易就很簡單了:
挖礦
挖礦正是神奇所在,它很簡單,做了以下三件事:
計算工作量證明PoW;
通過新增一個交易授予礦工(自己)一個幣;
構造新區塊并將其添加到鏈中。
注意交易的接收者是我們自己的服務器節點,我們做的大部分工作都只是圍繞Blockchain類方法進行交互。到此,我們的區塊鏈就算完成了,我們來實際運行下。
運行區塊鏈
你可以使用cURL或Postman去和API進行交互。
啟動server:
讓我們通過請求
來進行挖礦:
通過post請求,添加一個新交易:
如果不是使用Postman,則用以下的cURL語句也是一樣的:
在挖了兩次礦之后,就有3個塊了,通過請求
可以得到所有的塊信息。
一致性(共識)
我們已經有了一個基本的區塊鏈可以接受交易和挖礦,但是區塊鏈系統應該是分布式的。既然是分布式的,那么我們究竟拿什么保證所有節點有同樣的鏈呢?這就是一致性問題,我們要想在網絡上有多個節點,就必須實現一個一致性的算法。
注冊節點
在實現一致性算法之前,我們需要找到一種方式讓一個節點知道它相鄰的節點。每個節點都需要保存一份包含網絡中其它節點的記錄,因此讓我們新增幾個接口:
/nodes/register 接收URL形式的新節點列表;
/nodes/resolve 執行一致性算法,解決任何沖突,確保節點擁有正確的鏈。
我們修改下Blockchain的init函數并提供一個注冊節點方法:
我們用 set 來儲存節點,這是一種避免重復添加節點的簡單方法。
實現共識算法
前面提到,沖突是指不同的節點擁有不同的鏈,為了解決這個問題,規定最長的、有效的鏈才是最終的鏈,換句話說,網絡中有效最長鏈才是實際的鏈。
我們使用以下的算法,來達到網絡中的共識:
第一個方法 valid_chain() 用來檢查是否是有效鏈,遍歷每個塊驗證hash和proof。
第二個方法 resolve_conflicts() 用來解決沖突,遍歷所有的鄰居節點,并用上一個方法檢查鏈的有效性, 如果發現有效更長鏈,就替換掉自己的鏈。
讓我們添加兩個路由,一個用來注冊節點,一個用來解決沖突。
你可以在不同的機器運行節點,或在一臺機機開啟不同的網絡端口來模擬多節點的網絡,這里在同一臺機器開啟不同的端口演示,在不同的終端運行以下命令,就啟動了兩個節點:
。
然后在節點2上挖兩個塊,確保是更長的鏈,然后在節點1上訪問接口/nodes/resolve,這時節點1的鏈會通過共識算法被節點2的鏈取代。
本文來源網絡,不做任何商業目的。
https://zhuanlan.zhihu.com/p/34269882
總結
以上是生活随笔為你收集整理的用python从0开始创建一个区块链,从代码深入理解区块链的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python之区块链简单记账本实现
- 下一篇: 【译】A Practical Intro