區塊鏈的核心是一個分布式數據庫,允許雙方直接交易,而無需中央機構,也就是通常大家所說的'去中心化'。'去中心化'這個簡單而重要的概念對銀行、政府和市場等機構具有重大意義,可以說,任何依賴中央數據庫作為核心競爭優勢的企業或組織都可能受到區塊鏈技術的挑戰甚至顛覆。
本文的目標是給你一個區塊鏈技術的實用介紹,而不是炒作比特幣和其他加密貨幣概念。第1節和第2節介紹了區塊鏈一些核心概念,第3節介紹了如何使用Python實現區塊鏈。我們還將實施2個Web前端程序,以方便用戶與區塊鏈系統交互。
本文中,我將使用比特幣作為“區塊鏈”的例子,但本文描述的大多數概念都適用于其他加密貨幣。
1.區塊鏈掃盲課2008年一個自稱Satoshi Nakamoto的家伙發布了區塊鏈白皮書,沒有人知道這個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)認證:驗證發送消息持有者是否持有與其配對的私鑰; (2)加密:私鑰的持有者只有用與公鑰配對的私鑰才能解密用公鑰加密的消息。 RSA和橢圓曲線數字簽名(ECDSA)是最流行的公鑰密碼算法。
就比特幣而言,ECDSA算法用于生成比特幣錢包。比特幣使用各種密鑰和地址,但為了簡單起見,我們將在本文中假設每個比特幣錢包都有一對私鑰/公鑰,比特幣地址就是錢包的公鑰。如果您對比特幣錢包的完整技術細節感興趣,我推薦這篇文章(https://en./wiki/Technical_background_of_version_1_Bitcoin_addresses)。
要發送或接收BTC,用戶首先生成一個包含一對私鑰和公鑰的錢包。如果Alice想要給Bob發送一些BTC,她需要創建一個交易,然后在該交易中輸入她和Bob的公鑰,以及她想要發送的BTC數量,最后使用她的私鑰簽署交易。區塊鏈中的計算機使用Alice的公鑰來驗證交易是否真實,并將交易記錄添加到區塊鏈的區塊。
2.2 哈希函數和'挖礦”所有比特幣交易都分別記錄在稱為塊的文件中。比特幣每10分鐘添加一個新的交易塊。一旦新塊被添加到區塊鏈中,它就不能被更改,也不能被刪除。礦工負責創建新的交易塊。礦工必須使用發送者的公鑰驗證每筆交易,確認發送者有足夠的余額用于此次交易請求,確認通過后交易將添加到區塊中。礦工們可以自由地選擇在區塊中添加哪些交易,因此發送者需要給礦工支付交易費以激勵礦工將其交易記錄添加到區塊中。
區塊加入區塊鏈的過程,被稱之為“挖礦”,“挖礦”的參與者被稱之為礦工,礦工需要破解一個加密問題才能講區塊加入區塊鏈。成功破解加密問題的礦工將獲得比特幣獎勵(注意這和上面的交易費是不同的)。'挖礦'過程也被稱為工作量證明(PoW),它是使區塊鏈變得安全和可靠的主要機制(安全性問題稍后會詳述)。
哈希和區塊鏈的密碼拼圖要理解區塊鏈的密碼拼圖,我們需要從哈希函數開始。哈希函數可用于將任意大小的數據映射到固定大小的數據。哈希函數返回的值稱為散列值,哈希函數通常用于通過檢測重復記錄來加速數據庫查找,它也廣泛用于密碼學。密碼哈希函數可以驗證某些輸入數據和給定的散列值之間的映射關系,但如果輸入數據是未知的,則要想通過散列值反推出輸入數據是非常困難的。 [2]
比特幣使用稱為SHA-256的哈希加密算法, SHA-256應用于塊數據(比特幣交易)和一個稱為nonce的隨機數組合,通過更改塊數據或隨機數,我們可以得到完全不同的散列值。一個對被認為有效(已'開采”)的塊,它的散列值和隨機數需要滿足一定的條件,例如,散列值的前4位數字需要為“0000”。我們可以通過使條件更復雜來增加'挖礦”的復雜性,例如我們可以增加散列值開始所需的0的數量。
礦工需要找到一個隨機數值,使得散列值滿足“開采”條件。可以使用下面的應用程序來模擬這個過程,當你在文本框輸入數據或更改隨機數值時,你可以注意到哈希值的變化。當你點擊“挖礦”按鈕時,應用程序nonce從0開始,計算散列值并檢查散列值的前四位數是否等于“0000”。如果前四位數字不等于“0000”,它將隨機數加1,并重復整個過程直到找到一個滿足條件的隨機數值。
(譯者注:此圖僅做靜態展示,程序演示請訪問原文連接) 2.3從塊到區塊鏈正如前面部分所討論的,交易以區塊形式分組,并且塊被附加到區塊鏈。為了創建區塊鏈,每個新塊都使用前一個塊的哈希散列作為其數據的一部分。為了創建一個新塊,礦工會在'挖礦”過程中添加上一個塊的散列并以2.2中說述的方式'開采'有效的區塊。
任何區塊中的數據的變更都會影響到它后面區塊的散列值,每一個區塊都會使用前一個塊的哈希散列作為其數據的一部分,如果前一個區塊數據變了,后面的區塊將會成為“無效”的區塊,區塊鏈也因此具有了不可變更的特性。
你可以使用下面的應用程序來模擬有3個區塊的區塊鏈。當你輸入“Data”文本框或更改nonce值時,可以注意到下一個塊的散列值和“Prev”值(前一個散列)的更改。您可以通過單擊每個塊的“開采”按鈕來模擬采礦過程。在挖出3個區塊之后,嘗試更改塊1或塊2中的數據,并且您會注意到后面的所有塊都變為無效。(譯者注:程序演示請訪問原文鏈接)
2.4 將區塊添加到區塊鏈比特幣網絡中的所有礦工彼此競爭,看誰能先找到有效的區塊,先找到的可以將其添加到區塊鏈中,并從網絡中獲得回報。發現一個有效的隨機數(上文中那個nonce值)是非常困難的,但正所謂重賞之下必有勇夫,總有人會嘗試并挖到礦。那如果兩名礦工或更多的人同時遞交他們的區塊,會發生什么?
沖突解決如果兩個礦工幾乎同時解決一個塊,那么我們將在網絡中有兩個不同的塊鏈(區款鏈1和區款鏈2),我們需要等待下一個區塊來解決沖突問題。一些礦工將繼續嘗試在區塊鏈1和區塊鏈2頂部開采,如果新區塊在區塊鏈1的頂部被開采,則區塊鏈2變為無效,開采區塊鏈1的礦工因此獲得獎勵,與此同時區塊鏈2的那部分未被添加到區塊鏈的交易信息將返回到事務池,并添加到下一個塊。簡而言之,如果區塊鏈上存在沖突,那么長一點的那個鏈將會是贏家。
2.5 區塊鏈和雙重支出在本節中,我們將介紹區塊鏈對雙重支出攻擊的常見處理方式,以及用戶應采取哪些措施來防止他們遭受損失。
種族攻擊 攻擊者快速連續發送同一個幣到兩個不同的地址。為了防止這種攻擊,只要在接受付款之前等待至少一個數據塊確認就可以避免。 [3]
芬尼攻擊 攻擊者預先在事務中'開采'一個塊,并在釋放塊之前在第二個事務中花費相同的幣。在這種情況下,第二個事務將不會被驗證。為了防止這種攻擊,只要在接受付款之前等待至少6個數據塊確認(?)就可以避免。 [3]
多數人攻擊(也被稱為51%攻擊) 在這次攻擊中,攻擊者擁有51%的網絡計算能力。攻擊者首先在整個網絡上創建一個交易,然后“開采”一個私人區塊鏈,在這私人區塊鏈里他將交易信息篡改,如收到100幣變成收到200幣。由于攻擊者擁有大部分計算能力,因此他可以保證他在交易的這個時間點的鏈路比“誠實的”區塊鏈更長,根據區塊鏈規則,這些私有的區塊將成為“誠實的”區塊,而這筆篡改的交易也披上了“合法”的外衣。當然,這種攻擊的可能性非常小,因為獲得51%的計算能力成本太高了,幾乎沒有人負擔的起。 [4]
3. Python中的區塊鏈實現在本節中,我們將使用Python實現基本區塊鏈和區塊鏈客戶端。 我們的區塊鏈將具有以下功能: 1)將多個節點添加到區塊鏈 2)工作證明(PoW) 3)節點之間的沖突解決 4)使用RSA加密交易
我們的區塊鏈客戶端將具有以下功能: 1)使用公鑰/私鑰加密(基于RSA算法)生成錢包 2)使用RSA加密生成事務
我們還將實施2個儀表板: 1) 面向礦工的“區款鏈前臺” 2)“區塊鏈客戶端”讓用戶生成錢包并發送硬幣
本項目基于這個github項目(https://github.com/dvf/blockchain)。我對原代碼進行了一些修改,目的是為事務添加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個選項卡: 1)錢包生成器:使用RSA加密算法生成錢包(公鑰/私鑰對); 2)進行交易:生成交易并將其發送到區塊鏈節點; 3)查看轉換:查看區塊鏈上的交易。為了制作或查看交易,至少需要運行一個區塊鏈節點(將在下一節中介紹)。 以下是blockchain_client.py代碼中最重要部分的一些說明。我們定義了一個名為Transaction的python類,它具有4個屬性sender_address,sender_private_key,recipient_address,value。 這些是發件人創建交易所需的4條信息。 to_dict()方法以Python字典格式(沒有發件人的私鑰)返回交易信息。 sign_transaction()方法獲取交易信息(不包括發件人的私鑰),并使用發件人的私鑰對其進行簽名。
下面的代碼啟動一個Python Flask應用程序,我們將使用它來創建不同的API來與區塊鏈及其客戶端進行交互。
下面我們定義返回html頁面的3個Flask路由,每個標簽頁都有一個html頁面。
下面我們定義一個生成錢包的API(私鑰/公鑰對)。
下面我們定義一個API,它將sender_address,sender_private_key,recipient_address,value作為輸入值,并返回事務(無私鑰)和簽名。 3.2區塊鏈實施你可以在blockchain文件夾啟動區塊鏈節點,然后輸入python blockchain_client.py或python blockchain_client.py -p <端口號>。如果未指定端口號,則它將默認為端口5000.在瀏覽器中,轉至http:// localhost:
儀表板在導航欄中有2個選項卡: 1. 挖礦:用于查看交易和區塊鏈數據,以及用于挖掘新的交易區塊; 2. 配置:用于配置不同區塊鏈節點之間的連接;
以下是blockchain.py代碼中最重要部分的一些說明。
我們首先定義一個具有以下屬性的區塊鏈類: 交易:將被添加交易列表; 鏈:一個有數據構建的區塊鏈; 節點:包含節點URL的集合。區塊鏈使用這些節點從其他節點檢索區塊鏈數據,并在區塊鏈不同步時更新區塊鏈; node_id:識別區塊鏈節點的隨機字符串;
Blockchain類還實現了以下方法: 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):向區塊鏈添加一個交易塊; 散列(塊):創建塊的SHA-256散列; proof_of_work():工作證明算法。尋找滿足采礦條件的隨機數; valid_proof(transactions,last_hash,nonce,difficulty = MINING_DIFFICULTY):檢查哈希值是否滿足挖掘條件。該函數在proof_of_work函數中使用; valid_chain(鏈):檢查鏈接是否有效; resolve_conflicts():通過替換網絡中最長的鏈來解決區塊鏈節點之間的沖突;
下面的代碼啟動一個Python Flask應用程序,我們將使用它來創建不同的API來與區塊鏈進行交互。proof_of_work():工作證明算法。尋找滿足采礦條件的隨機數。 valid_proof(transactions,last_hash,nonce,difficulty = MINING_DIFFICULTY):檢查哈希值是否滿足挖掘條件。該函數在proof_of_work函數中使用。 valid_chain(鏈):檢查鏈接是否有效。 resolve_conflicts():通過替換網絡中最長的鏈來解決區塊鏈節點之間的沖突。
下面的代碼啟動一個Python Flask應用程序,我們將使用它來創建不同的API來與區塊鏈進行交互。
接下來,我們啟動一個Blockchain實例。
下面我們定義返回我們區塊鏈前端儀表盤html頁面的2個Flask路由。
下面我們定義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 Flask應用程序,我們將使用它來創建不同的API來與區塊鏈進行交互。
接下來,我們啟動一個Blockchain實例。
下面我們定義返回我們區塊鏈前端儀表盤html頁面的2個Flask路由。
下面我們定義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返回節點列表。
4、結論在本文中,我們介紹了區塊鏈的一些核心概念,并學習了如何使用Python實現一個實例。為了簡單起見,我沒有介紹一些技術細節,例如:錢包地址和默克爾樹。如果你想了解更多建議閱讀比特幣白皮書。
參考 1 - 維基百科 - 公鑰密碼學 2 - 維基百科 - 哈希函數 3 - Bitcoin Stackexchange - 交易一旦產生會發生什么? 4 - 比特幣維基 - 多數人攻擊 END. |
|