【译】A Practical Introduction to Blockchain with Python
區塊鏈可以說是互聯網自成立以來最重要和最具顛覆性的技術之一。?這是比特幣和其他加密貨幣背后的核心技術,在過去幾年引起了很多關注。
作為其核心,區塊鏈是一個分布式數據庫,允許雙方直接交易,而無需中央機構。?這個簡單而強大的概念對銀行,政府和市場等各種機構具有重大意義,僅舉幾例。?任何依賴中央數據庫作為核心競爭優勢的企業或組織都可能受到區塊鏈技術的干擾。
拋開所有關于比特幣和其他加密貨幣價格的炒作,本博文的目標是給你一個區塊鏈技術的實用介紹。?第1節和第2節介紹了區塊鏈背后的一些核心概念,第3節介紹了如何使用Python實現區塊鏈。?我們還將實施2個Web應用程序,以方便最終用戶與我們的區塊鏈互動。
請注意,我在此使用比特幣作為解釋“區塊鏈”更一般技術的媒介,本文中描述的大多數概念都適用于其他區塊鏈使用案例和加密貨幣。
以下是我們將在第3節中構建的兩個Web應用程序的動畫gif。
1.區塊鏈中的崩潰課程
這一切都始于2008年由一個不知名的人或實體使用Satoshi Nakamoto這個名字發布的白皮書。?該白皮書的標題是“比特幣:對等電子現金系統”?,它奠定了后來被稱為區塊鏈的基礎。?在最初的比特幣白皮書中,Satoshi描述了如何建立點對點電子現金系統,使得在線支付可以直接從一方發送到另一方,而無需通過中央機構。?該系統解決了數字貨幣中稱為雙重支出的重要問題。
1.1。?什么是雙重支出?
假設Alice想支付Bob 1 $。?如果Alice和Bob使用實物現金,那么在交易執行后Alice將不再擁有1美元。?如果Alice和Bob使用數字貨幣,那么問題變得更加復雜。?數字貨幣是數字形式,可以很容易地復制。?如果Alice通過電子郵件向Bob發送一個價值1美元的數字文件,Bob無法確定Alice是否刪除了她的文件副本。?如果Alice仍然有1 $數字文件,那么她可以選擇將同一個文件發送給Carol。?這個問題叫做雙重支出。
解決雙重支出問題的一種方法是在Alice,Bob和網絡中的所有其他參與者之間建立一個可信的第三方(例如銀行)。?該第三方負責管理集中分類帳,用于跟蹤和驗證網絡中的所有交易。?這個解決方案的缺點是要使系統正常工作,它需要信任一個集中的第三方。
1.2。?比特幣:雙重支出問題的分散解決方案
為了解決雙重支出問題,Satoshi提出了一個公共分類賬,即比特幣的區塊鏈來跟蹤網絡中的所有交易。?比特幣的區塊鏈具有以下特點:
- 分布式:分類賬在多臺計算機上復制,而不是存儲在中央服務器上。?任何具有互聯網連接的計算機都可以下載區塊鏈的完整副本。
- 密碼:密碼術用于確保發件人擁有她試圖發送的比特幣,并決定如何將交易添加到區塊鏈中。
- 不可變:區塊鏈可以以追加方式更改。?換句話說,交易只能添加到區塊鏈中,但不能刪除或修改。
- 使用工作證明(PoW):網絡中一種特殊類型的參與者稱為礦工競爭尋找加密難題的解決方案,這將使他們能夠在比特幣區塊鏈中添加大量交易。?這個過程稱為工作證明(Proof of Work),它允許系統安全(稍后會介紹這一點)。
發送比特幣錢如下:
- 步驟1(一次性努力):創建一個比特幣錢包。?對于一個人發送或接收比特幣,她需要創建一個比特幣錢包。?比特幣錢包存儲2條信息:私鑰和公鑰。?私鑰是一個秘密號碼,允許所有者向其他用戶發送比特幣,或者將比特幣用于接受他們的服務作為付款方式。?公鑰是接收比特幣所需的數字。?公鑰也被稱為比特幣地址(不完全正確,但為了簡單起見,我們將假定公鑰和比特幣地址相同)。?請注意,錢包本身不存儲比特幣。?關于比特幣余額的信息存儲在比特幣區塊鏈中。
- 第2步:創建一個比特幣交易。?如果Alice想要給Bob發送1 BTC,Alice需要使用她的私鑰連接到她的比特幣錢包,并創建一個包含她想要發送的比特幣數量和她要發送的地址的交易(在這種情況下鮑勃的公共地址)。
- 第3步:將交易廣播至比特幣網絡。?一旦Alice創建比特幣交易,她需要將此交易廣播到整個比特幣網絡。
- 第4步:確認交易。?一位收聽比特幣網絡的礦工使用Alice的公鑰驗證交易,證實Alice的錢包中有足夠的比特幣(在這種情況下至少為1 BTC),并在比特幣的區塊鏈中增加了一個新記錄,其中包含交易詳情。
- 第5步:將區塊鏈更改廣播給所有礦工。?交易確認后,礦工應該向所有礦工廣播區塊鏈更改,以確保區塊鏈的副本全部同步。
2.區塊鏈技術深入研究
本部分的目標是深入介紹區塊鏈技術構建模塊。?我們將介紹公鑰密碼學,散列函數,區塊鏈的挖掘和安全性。
2.1。?公鑰加密
公鑰密碼學或不對稱密碼學是使用密鑰對的任何密碼系統:可以廣泛傳播的公鑰和只有所有者知道的私鑰。?這實現了兩個功能:認證,其中公鑰驗證發送消息的配對私鑰的持有者和加密,其中只有配對私鑰持有者可以解密用公鑰加密的消息。?[1]
RSA和橢圓曲線數字簽名(ECDSA)是最流行的公鑰密碼算法。
就比特幣而言,ECDSA算法用于生成比特幣錢包。?比特幣使用各種密鑰和地址,但為了簡單起見,我們將在本博文中假設每個比特幣錢包都有一對私鑰/公鑰,比特幣地址就是錢包的公鑰。?如果您對比特幣錢包的完整技術細節感興趣,我推薦這篇文章?。
要發送或接收BTC,用戶首先生成一個包含一對私鑰和公鑰的錢包。?如果Alice想要給Bob發送一些BTC,她創建一個交易,在該交易中她輸入她和Bob的公鑰,以及她想要發送的BTC數量。?她然后使用她的私鑰簽署交易。?區塊鏈中的計算機使用Alice的公鑰來驗證交易是否真實,并將交易添加到稍后將添加到區塊鏈的區塊。
2.2。?散列函數和挖掘
所有比特幣交易都分組在稱為塊的文件中。?比特幣每10分鐘添加一個新的交易塊。?一旦新塊被添加到區塊鏈中,它就變得不可變,并且不能被刪除或修改。?網絡中一個特殊的參與者稱為礦工(連接到區塊鏈的計算機)負責創建新的交易塊。?礦工必須使用發件人的公鑰驗證每筆交易,確認發件人有足夠的余額用于所請求的交易,并將交易添加到該塊。?礦工們可以完全自由地選擇塊中包含哪些交易,因此發件人需要包含交易費以激勵礦工將其交易添加到塊中。
對于被區塊鏈接受的區塊,它需要被“挖掘”。?為了挖掘一個塊,礦工需要找到一個極其罕見的解決密碼難題的方法。?如果區塊鏈接受了開采區塊,礦工將獲得比特幣獎勵,這是對交易費用的額外激勵。?挖掘過程也被稱為工作量證明(PoW),它是使區塊鏈變得可靠和安全的主要機制(更多關于區塊鏈安全性)。
哈希和區塊鏈的密碼拼圖
要理解區塊鏈的加密難題,我們需要從哈希函數開始。?哈希函數是可用于將任意大小的數據映射到固定大小的數據的任何函數。?散列函數返回的值稱為散列。?散列函數通常用于通過檢測重復記錄來加速數據庫查找,并且它們也廣泛用于密碼學。?密碼散列函數允許人們容易地驗證某些輸入數據映射到給定的散列值,但是如果輸入數據是未知的,則通過知道存儲的散列值來重建它是故意困難的。?[2]
比特幣使用稱為SHA-256的加密散列函數。?SHA-256應用于塊數據(比特幣交易)和一個稱為nonce的數字的組合。?通過更改塊數據或隨機數,我們可以得到完全不同的哈希值。?對于被認為有效或“挖掘”的塊,塊的散列值和隨機數需要滿足一定的條件。?例如,散列的四位前導數字需要等于“0000”。?我們可以通過使條件更復雜來增加挖掘的復雜性,例如我們可以增加散列值開始所需的0的數量。
礦工需要解決的cryptograhic難題是找到一個隨機數值,使得哈希值滿足挖掘條件。?您可以使用下面的應用程序來模擬塊挖掘。?當您輸入“數據”文本框或更改隨機數值時,您可以注意到哈希值的變化。?當你點擊“我的”按鈕時,應用程序以nonce等于零開始,計算散列值并檢查散列值的前四位數是否等于“0000”。?如果前四位數字不等于“0000”,它將隨機數加1,并重復整個過程直到找到一個滿足條件的隨機數值。?如果該塊被視為開采,背景顏色將變成綠色。
隨機數:數據:哈希:礦2.3。?從塊到區塊鏈
正如前面部分所討論的,交易以塊形式分組,并且塊被附加到區塊鏈。?為了創建塊鏈,每個新塊都使用前一個塊的散列作為其數據的一部分。?為了創建一個新塊,礦工選擇一組事務,添加上一個塊的散列并以上述類似的方式挖掘塊。
對任何塊中的數據所做的任何更改都會影響到它后面的塊的所有散列值,并且它們將變為無效。?這給區塊鏈帶來了不變性。
您可以使用下面的應用程序來模擬3塊的區塊鏈。?當您輸入“Data”文本框或更改nonce值時,可以注意到下一個塊的散列值和“Prev”值(前一個散列)的更改。?您可以通過單擊每個塊的“Mine”按鈕來模擬采礦過程。?在挖掘3個塊之后,嘗試更改塊1或塊2中的數據,并且您會注意到后面的所有塊都變為無效。
塊:#隨機數:數據:上一篇:哈希:礦塊:#隨機數:數據:上一篇:哈希:礦塊:#隨機數:數據:上一篇:哈希:礦上述兩款采礦模擬器都是根據Anders Brownworth出色的Blockchain Demo改編的。
2.4。?將區塊添加到區塊鏈
比特幣網絡中的所有礦工相互競爭,找到一個有效的區塊,并將其添加到區塊鏈中,并從網絡中獲得獎勵。?發現一個驗證塊的隨機數很少見,但由于礦工人數眾多,網絡中的礦工驗證塊的可能性非常高。?第一位提交有效街區的礦工將他的街區加入區塊鏈,并獲得比特幣獎勵。?但是,如果兩名礦工或更多的同時遞交他們的塊,會發生什么?
解決沖突
如果兩個礦工幾乎同時解決一個塊,那么我們將在網絡中有兩個不同的塊鏈,我們需要等待下一個塊來解決沖突。?一些礦工將決定在區塊鏈1和區塊鏈2頂部的其他礦區之上開采礦石。第一個找到新區塊的礦工將解決沖突。?如果新區塊在區塊鏈1的頂部被開采,則區塊鏈2變為無效,前區塊的獎勵從區塊鏈1進入礦工,并且區塊鏈2的一部分并且未被添加到區塊鏈的交易返回到事務池并添加到下一個塊。?簡而言之,如果區塊鏈上存在沖突,那么最長的連鎖贏家。
2.5。?區塊鏈和雙重支出
在本節中,我們將介紹對區塊鏈執行雙重支出攻擊的最常見方式,以及用戶應采取哪些措施來防止他們遭受損失。
種族攻擊
攻擊者快速連續發送同一枚硬幣到兩個不同的地址。?為了防止這種攻擊,建議在接受付款之前等待至少一個數據塊確認。?[3]
芬尼攻擊
攻擊者預先在事務中挖掘一個塊,并在釋放塊之前在第二個事務中花費相同的硬幣。?在這種情況下,第二個事務將不會被驗證。?為了防止這種攻擊,建議在接受付款之前至少等待6個數據塊確認。?[3]
多數人攻擊(也被稱為51%攻擊)
在這次攻擊中,攻擊者擁有51%的網絡計算能力。?攻擊者首先在整個網絡上創建一個交易,然后挖掘一個私人區塊鏈,在那里他將前一個交易的硬幣加倍。?由于攻擊者擁有大部分計算能力,因此他可以保證他在某個時間點的鏈接比“誠實”的網絡要長。?然后,他可以發布他的較長的區塊鏈,取代“誠實”區塊鏈并取消原始交易。?這種攻擊極不可能,因為它在像比特幣這樣的區塊鏈網絡中非常昂貴。?[4]
3. Python中的區塊鏈實現
在本節中,我們將使用Python實現基本區塊鏈和區塊鏈客戶端。?我們的區塊鏈將具有以下功能:
- 將多個節點添加到區塊鏈的可能性
- 工作證明(PoW)
- 節點之間的簡單沖突解決
- 使用RSA加密的交易
我們的區塊鏈客戶端將具有以下功能:
- 使用公鑰/私鑰加密(基于RSA算法)生成錢包
- 使用RSA加密生成事務
我們還將實施2個儀表板:
- 面向礦工的“Blockchain Frontend”
- “區塊鏈客戶端”讓用戶生成錢包并發送硬幣
區塊鏈實施主要基于這個github項目?。?我對原始代碼進行了一些修改,以便為事務添加RSA加密。?錢包生成和交易加密基于Jupyter筆記本?。?2個儀表板從頭開始使用HTML / CSS / JS實現。
您可以從https://github.com/adilmoujahid/blockchain-python-tutorial下載完整的源代碼。
請注意,此實現僅用于教育目的,不應用于生產,因為它沒有很好的安全性,不能很好地擴展并缺少許多重要功能。
3.1。?區塊鏈客戶端實施
您可以通過訪問blockchain_client文件夾并鍵入python blockchain_client.py來從終端啟動區塊鏈客戶端。?在瀏覽器中,轉至http://localhost:8080?,您將看到下面的儀表板。
儀表板在導航欄中有3個選項卡:
- 錢包生成器:使用RSA加密算法生成錢包(公鑰/私鑰對)
- 進行交易:生成交易并將其發送到區塊鏈節點
- 查看轉換:查看區塊鏈上的交易
為了制作或查看交易,您至少需要運行一個區塊鏈節點(將在下一節中介紹)。
以下是blockchain_client.py代碼中最重要部分的一些說明。
我們定義了一個名為Transaction的python類,它具有4個屬性sender_address?,?sender_private_key?,?recipient_address?,?value?。?這些是發件人創建交易所需的4條信息。
to_dict()方法以Python字典格式(沒有發件人的私鑰)返回交易信息。?sign_transaction()方法獲取交易信息(不包括發件人的私鑰),并使用發件人的私鑰對其進行簽名。
類 交易 : def __init__ ( self , sender_address , sender_private_key , recipient_address , value ): 自我 。 sender_address = sender_address 自我 。 sender_private_key = sender_private_key 自我 。 recipient_address = recipient_address 自我 。 值 = 值 def __getattr__ ( self , attr ): 回歸 自我 。 數據 [ attr ] def to_dict ( self ): 返回 OrderedDict ({ 'sender_address' : self。sender_address , 'recipient_address' : 自我 。 recipient_address , '價值' : 自我 。 值 }) def sign_transaction ( self ): “”” 用私鑰簽名交易 “”” private_key = RSA 。 importKey ( binascii。unhexlify ( self。sender_private_key )) 簽署者 = PKCS1_v1_5 。 新 ( private_key ) h = SHA 。 new ( str ( self.to_dict ()) 。 encode ( 'utf8' )) 返回 binascii 。 hexlify ( 簽字人 簽字 ( h )) 。 解碼 ( 'ascii' )下面的代碼啟動一個Python Flask應用程序,我們將使用它來創建不同的API來與區塊鏈及其客戶端進行交互。
app = Flask ( __name__ )下面我們定義返回html頁面的3個Flask路由。?每個標簽頁都有一個html頁面。
@ app.route ( '/' ) def index (): 返回 render_template ( './index.html' ) @ app.route ( '/ make / transaction' ) def make_transaction (): 返回 render_template ( './make_transaction.html' ) @ app.route ( '/ view / transactions' ) def view_transaction (): 返回 render_template ( './view_transactions.html' )下面我們定義一個生成錢包的API(私鑰/公鑰對)。
@ app.route ( '/ wallet / new' , methods = [ 'GET' ]) def new_wallet (): random_gen = 加密 。 隨機 。 new () 。 讀 private_key = RSA 。 生成 ( 1024 , random_gen ) public_key = private_key 。 publickey () response = { 'private_key' : binascii 。 hexlify ( private_key。exportKey ( format = 'DER' )) 。 解碼 ( 'ascii' ), 'public_key' : binascii 。 hexlify ( public_key。exportKey ( format = 'DER' )) 。 解碼 ( 'ascii' ) } 返回 jsonify ( 響應 ), 200下面我們定義一個API,它將輸入sender_address?,?sender_private_key?,?recipient_address?,?value作為輸入,并返回事務(無私鑰)和簽名。
@ app.route ( '/ generate / transaction' , methods = [ 'POST' ]) def generate_transaction (): sender_address = 請求 。 表單 [ 'sender_address' ] sender_private_key = 請求 。 表單 [ 'sender_private_key' ] recipient_address = 請求 。 表單 [ 'recipient_address' ] 值 = 請求 。 形式 [ 'amount' ] transaction = Transaction ( sender_address , sender_private_key , recipient_address , value ) response = { 'transaction' : 交易 。 to_dict (), '簽名' : 事務 。 sign_transaction ()} 返回 jsonify ( 響應 ), 2003.2。?區塊鏈實施
您可以通過轉到blockchain文件夾啟動區塊鏈節點,然后輸入python blockchain_client.py或python blockchain_client.py -p <PORT NUMBER>?。?如果您未指定端口號,則默認為端口5000.在瀏覽器中,轉到http://localhost:<PORT NUMBER>以查看區塊鏈前端儀表板。
儀表板在導航欄中有2個選項卡:
- Mine:用于查看交易和區塊鏈數據,以及用于挖掘新的交易區塊。
- 配置:用于配置不同區塊鏈節點之間的連接。
以下是blockchain.py代碼中最重要部分的一些說明。
我們首先定義一個具有以下屬性的Blockchain類:
- transactions?:將被添加到下一個塊的交易列表。
- chain?:實際的區塊鏈,這是一個塊數組。
- nodes?:包含節點URL的集合。?區塊鏈使用這些節點從其他節點檢索區塊鏈數據,并在區塊鏈不同步時更新區塊鏈。
- node_id?:識別node_id鏈節點的隨機字符串。
Blockchain類還實現了以下方法:
- register_node(node_url)?:將新的register_node(node_url)鏈節點添加到節點列表中。
- verify_transaction_signature(sender_address, signature, transaction)?:檢查提供的簽名是否與由公鑰簽名的事務(sender_address)相對應。
- submit_transaction(sender_address, recipient_address, value, signature)?:如果驗證簽名,則將事務添加到事務列表。
- create_block(nonce, previous_hash)?:向區塊鏈添加一個交易塊。
- hash(block)?:創建hash(block)的SHA-256散列。
- proof_of_work()?:工作證明算法。?尋找滿足采礦條件的隨機數。
- valid_proof(transactions, last_hash, nonce, difficulty=MINING_DIFFICULTY)?:檢查哈希值是否滿足挖掘條件。該函數在proof_of_work函數中使用。
- valid_chain(chain)?:檢查鏈接是否有效。
- resolve_conflicts()?:通過替換網絡中最長的鏈來解決區塊鏈節點之間的沖突。
下面的代碼啟動一個Python Flask應用程序,我們將使用它來創建不同的API來與區塊鏈進行交互。
app = Flask ( __name__ ) CORS ( 應用程序 )接下來,我們啟動一個Blockchain實例。
blockchain = 區塊鏈 ()下面我們定義返回我們區塊鏈前端儀表盤html頁面的2個Flask路由。
@ app.route ( '/' ) def index (): 返回 render_template ( './index.html' ) @ app.route ( '/ configure' ) def configure (): 返回 render_template ( './configure.html' )下面我們定義Flask?API來管理交易和挖掘區塊鏈。
- '/transactions/new'?:這個API作為'sender_address'?,?'recipient_address'?,?'amount'和'signature'?,并將交易添加到交易列表中,如果簽名有效,交易列表將被添加到下一個區塊。
- '/transactions/get'?:該API返回將被添加到下一個塊的所有事務。
- '/chain'?:該API返回所有區塊鏈數據。
- '/mine'?:該API運行工作證明算法,并將新的交易塊添加到區塊鏈。
下面我們定義Flask API來管理區塊鏈節點。
- '/nodes/register'?:該API將節點URL列表作為輸入,并將它們添加到節點列表中。
- '/nodes/resolve'?:該API通過用網絡中可用的最長鏈替換本地鏈來解決區塊鏈節點之間的沖突。
- '/nodes/get'?:該API返回節點列表。
結論
在本篇博文中,我們介紹了區塊鏈背后的一些核心概念,并學習了如何使用Python實現一個核心概念。?為了簡單起見,我沒有介紹一些技術細節,例如:錢包地址和默克爾樹。?如果您想了解更多關于此主題的信息,我建議您閱讀比特幣原始白皮書,并跟進比特幣維基和Andreas Antonopoulos出色的書籍:?掌握比特幣:編程開放區塊鏈?。
參考
- 1 -?維基百科 - 公鑰密碼學
- 2 -?維基百科 - 哈希函數
- 3 -?Bitcoin Stackexchange - 交易一旦產生會發生什么?
- 4 -?比特幣維基 - 多數人攻擊
http://adilmoujahid.com/posts/2018/03/intro-blockchain-bitcoin-python/
總結
以上是生活随笔為你收集整理的【译】A Practical Introduction to Blockchain with Python的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【译】Engineering Secur
- 下一篇: Hadoop将死,图数据库成为新趋势!