摘要:通過入門區(qū)塊鏈本文翻譯自的文章原文地址區(qū)塊鏈可能是繼互聯(lián)網(wǎng)之后最重大和最具突破性的技術(shù)。先不管對比特幣和其他加密貨幣價格的瘋狂行情,本文旨在幫助讀者入門區(qū)塊鏈技術(shù)。
通過Python入門區(qū)塊鏈
本文翻譯自 Adil Moujahid 的文章 A Practical Introduction to Blockchain with Python原文地址:http://adilmoujahid.com/posts/2018/03/intro-blockchain-bitcoin-python/
區(qū)塊鏈可能是繼互聯(lián)網(wǎng)之后最重大和最具突破性的技術(shù)。它是比特幣和其他加密貨幣背后的核心技術(shù),在近幾年可謂賺足了人們的眼球。
本質(zhì)上講,區(qū)塊鏈?zhǔn)且环N不需第三方權(quán)威機構(gòu),直接在兩者之間點對點交易的分布式數(shù)據(jù)庫。這種簡單卻強大的理念對銀行、政府和市場等各種各樣的機構(gòu)產(chǎn)生了巨大的影響。任何以中央數(shù)據(jù)庫作為技術(shù)壁壘的公司和組織都可能被區(qū)塊鏈技術(shù)顛覆。
先不管對比特幣和其他加密貨幣價格的瘋狂行情,本文旨在幫助讀者入門區(qū)塊鏈技術(shù)。第一、二節(jié)講解了一些區(qū)塊鏈的核心概念,第三節(jié)展示了如何通過Python實現(xiàn)區(qū)塊鏈。我們也將實現(xiàn)兩個web網(wǎng)站方便用戶與我們的區(qū)塊鏈交互。
本文通過比特幣作為例子來解釋主流的區(qū)塊鏈技術(shù),大部分概念在其他區(qū)塊鏈應(yīng)用場景和加密貨幣中同樣適用。
下圖使我們將在第三節(jié)實現(xiàn)的web應(yīng)用:
1. 區(qū)塊鏈快速入門所有的一切開始于2008年,一個自稱中本聰?shù)哪涿娜嘶蛘邎F體發(fā)表了一篇白皮書。這篇名為『比特幣:一種點對點的電子現(xiàn)金系統(tǒng)』的白皮書為后來成為區(qū)塊鏈的技術(shù)打下了基礎(chǔ)。在白皮書中,重本從描述了如何建立一個點對點的電子貨幣系統(tǒng),可以直接從個體支付給另一個個體,而不需要中央權(quán)威機構(gòu)的介入。該系統(tǒng)解決了電子貨幣的一個重要問題——雙重支付。
1.1 什么是雙重支付?假設(shè)Alice想要付1美元給Bob。如果Alice和Bob使用物理貨幣,那么Alice在支付給Bob1美元之后,將不再擁有那1美元貨幣。如果Alice和Bob使用數(shù)字貨幣,那么問題就變復(fù)雜了。數(shù)字貨幣很容易被復(fù)制,比如說,如果Alice通過電子郵件發(fā)給Bob一個價值1美元的數(shù)字文件,Bob并不知道Alien是否已經(jīng)刪掉她自己的文件。如果Alice沒有刪掉,并且又用同樣的方式發(fā)給了Carol。這就是雙重支付問題。
一種雙重支付的解決方案是通過一個獨立于Aliec,Bob和其他網(wǎng)絡(luò)中的參與者的可信第三方機構(gòu)(比如說銀行)。主要職責(zé)是維護一個用于記錄和驗證網(wǎng)絡(luò)中所有的交易的中央賬本。這個解決方案的缺點是需要一個可信的中心化第三方機構(gòu)。
1.2 比特幣:一個雙重支付問題的去中心化解決方案為了解決雙重支付問題,中本聰提出了一種公開賬本,換言之,比特幣中的區(qū)塊鏈技術(shù)用于記錄網(wǎng)絡(luò)中所有的交易,有如下幾個特征:
分布性:賬本復(fù)制存儲在大量的計算機中,而不是一個中央數(shù)據(jù)庫。任何聯(lián)網(wǎng)的且運行比特幣軟件的計算機都會下載一份區(qū)塊鏈的完整拷貝。
加密性:密碼學(xué)用來保證付款方擁有他發(fā)送的比特幣,并且決定交易如何添加到區(qū)塊鏈上。
不可篡改性:區(qū)塊鏈僅僅能在添加元素的時候被修改,也就是說,交易只能添加到區(qū)塊鏈,而不能刪除或篡改。
工作量證明機制:網(wǎng)絡(luò)中一種特殊的參與者叫做礦工,他們通過計算尋找密碼學(xué)難題,解開難題的礦工可以將新的交易塊添加到區(qū)塊鏈中。
發(fā)送比特幣需要如下幾步操作:
第一步(只需一次):創(chuàng)建比特幣錢包。對于發(fā)送和接受比特幣的人來說,他們都需要創(chuàng)建一個比特幣錢包。比特幣錢包保存了兩部分信息:私鑰和公鑰。私鑰是一個密碼,允許擁有者發(fā)送比特幣給另一位用戶,或者把比特幣作為支付手段來使用。 公鑰是一串用來接受比特幣的字符串,同時也被稱作比特幣錢包地址(不完全正確,但一般來說我們認為公鑰和錢包地址是相同的)。請注意錢包不存儲比特幣本身,比特幣余額的信息被存儲在區(qū)塊鏈上。
第二步:創(chuàng)建比特幣交易。如果Alice想發(fā)送1美元給Bob,Alice需要使用私鑰打開她的比特幣錢包,創(chuàng)建一個包含金額的交易(該場景中,使用Bob的公鑰地址)
第三步:向比特幣網(wǎng)絡(luò)廣播該交易事件。一旦Alice創(chuàng)建了比特幣交易,他需要向整個比特幣網(wǎng)絡(luò)廣播這個交易。
第四步:確認交易。監(jiān)聽比特幣網(wǎng)絡(luò)的某個礦工使用Alice的公鑰對交易進行驗證,確認她的錢包中有足夠的比特幣(該場景中,最少1個比特幣),并且向區(qū)塊鏈中添加包含交易詳情的新紀錄。
第五步:向所有礦工廣播區(qū)塊鏈的修改。一旦交易被確認,該礦工應(yīng)該向所有的礦工廣播區(qū)塊鏈的修改,以保證其他礦工的區(qū)塊鏈內(nèi)容及時同步。
2. 深入理解區(qū)塊鏈本節(jié)旨在深入探討驅(qū)動區(qū)塊鏈的核心步驟——新建區(qū)塊的技術(shù)細節(jié),將從公開密鑰加密,哈希函數(shù),挖礦和區(qū)塊鏈安全幾個方便展開。
2.1 公開密鑰加密公開密鑰加密,或者說非對稱加密,是指一種使用一對鑰匙的加密系統(tǒng),公鑰可能被廣泛的三波,私鑰只有擁有者本人知道。它實現(xiàn)了兩個功能:認證,公鑰可以驗證持有者通過私鑰加密的信息;加密,只有私鑰擁有者可以解開通過公鑰加密的信息。
RSA和橢圓曲線數(shù)字簽名算法(ECDSA)是最廣泛應(yīng)用的兩種公開密鑰加密算法。
對比特幣來說,ECDSA算法被用于生成比特幣錢包。比特幣通常使用多個鑰匙和地址,但簡單起見,本文中假設(shè)每個比特幣錢包只使用一堆公鑰和私鑰,并且比特幣錢包地址就是公鑰。如果你對比特幣錢包的完整技術(shù)感興趣,我推薦這篇文章。
發(fā)送和接受比特幣時,用戶首先創(chuàng)建一個包含公鑰和私鑰的錢包。如果Alice想要給Bob發(fā)送一些比特幣,她在創(chuàng)建交易的時候需要將她和Bob雙方的公鑰,以及比特幣金額輸入進去。然后使用自己的私鑰簽署這筆交易。區(qū)塊鏈上的某臺計算機可以通過Alice的公鑰去驗證這筆交易是不是Alice本人發(fā)出的,然后將交易添加到區(qū)塊上,之后該區(qū)塊會被添加到區(qū)塊鏈當(dāng)中。
2.2. 哈希函數(shù)和挖礦所有比特幣交易被存放在成為區(qū)塊的文件中。比特幣每十分鐘向區(qū)塊鏈中添加一個包含新增交易記錄的新區(qū)塊。一旦新區(qū)快被添加進區(qū)塊鏈,它將不可修改和刪除。在區(qū)塊鏈網(wǎng)絡(luò)中,一種被稱為礦工(他們的計算機連接著區(qū)塊鏈)的特殊群體負責(zé)創(chuàng)建新的交易區(qū)塊。礦工必須使用發(fā)送者的公鑰驗證每一筆交易,確認發(fā)送者擁有足夠的余額支付完成該交易,并且將交易添加到區(qū)塊中。礦工可以完全自主選擇將哪些交易添加到區(qū)塊中,因此發(fā)送者需要提交一些交易費來激勵礦工將它們的交易添加到區(qū)塊中。
對于每一個被區(qū)塊鏈接受的區(qū)塊,都需要被挖礦。挖一個區(qū)塊的時候,礦工需要尋找一個極難的加密難題的答案。如果一個被挖礦的區(qū)塊被區(qū)塊鏈接受,礦工將獲得一定的比特幣作為除了交易費的額外獎勵。挖礦程序也被稱為工作量證明機制,它是保障區(qū)塊鏈可靠和安全的主要機制(稍后再討論區(qū)塊鏈的安全性)。
哈希和區(qū)塊鏈加密難題為了理解區(qū)塊鏈加密難題,需要先理解哈希函數(shù)。哈希函數(shù)可以將任意范圍的數(shù)據(jù)映射到指定的數(shù)據(jù)范圍。哈希函數(shù)返回的結(jié)果成為哈希值。哈希函數(shù)通常被用于通過重復(fù)檢查來加速數(shù)據(jù)庫查找,并且在密碼學(xué)中也有廣泛的應(yīng)用。加密哈希函數(shù)幫助人們輕松地驗證某些輸入數(shù)據(jù)是否映射到了給定的哈希值,但如果不知道輸入數(shù)據(jù),那么通過哈希值來構(gòu)造輸入數(shù)據(jù)是極其困難的。[2]
比特幣使用SHA-256作為加密哈希函數(shù)。SHA-256應(yīng)用于區(qū)塊數(shù)據(jù)(比特幣交易)與一種名為nonce(譯者注:實際上是一個隨機數(shù))的數(shù)字的組合。通過改變區(qū)塊數(shù)據(jù)和nonce,可以得到完全不同的哈希值。對于一個被認為是有效或者說是被挖礦的區(qū)塊,區(qū)塊和nonce的哈希值需要滿足一個特定的條件。比如說,哈希值前面的四位數(shù)等于"0000"。我們可以通過規(guī)定更加復(fù)雜的條件來提高挖礦的難度,比如說我們可以要求哈希值的開頭包含更多個0。
礦工面臨的加密難題需要尋找一個nonce值,使得哈希值滿足挖礦成功條件。我們可以通過下面的應(yīng)用來模擬區(qū)塊挖礦。當(dāng)在Data欄輸入內(nèi)容或者改變nonce值時,哈希值會隨之改變。當(dāng)點擊"挖礦"按鈕,應(yīng)用從0開始枚舉nonce的值,并檢查哈希值的前四位數(shù)是否等于"0000"。如果前四位數(shù)不等于"0000",那么nonce值加一并重復(fù)相同的操作直到nonce值滿足條件。如果區(qū)塊完成挖礦,那么背景色會變成綠色。
為了保證體驗,請到原文鏈接中相應(yīng)位置進行模擬。2.3. 從區(qū)塊到區(qū)塊鏈
如前一節(jié)所述,交易被分組存放在區(qū)塊中,區(qū)塊被附加在區(qū)塊鏈中。為了把區(qū)塊串成鏈,每個新區(qū)塊都存儲著它前一個區(qū)塊的哈希值。創(chuàng)建新區(qū)塊時,礦工選擇一些交易,添加前一個區(qū)塊的哈希值,并且對區(qū)塊進行挖礦。
任何區(qū)塊中任何數(shù)據(jù)上的改變都會影響該區(qū)塊的哈希值,進而導(dǎo)致該區(qū)塊失效。這賦予了區(qū)塊鏈不可篡改的特性。
你可以通過如下軟件模擬包含三個區(qū)塊的區(qū)塊鏈。當(dāng)你在Data欄輸入內(nèi)容或者概念nonce值時,可以發(fā)現(xiàn)該區(qū)塊的哈希值和下一個區(qū)塊的前導(dǎo)值(前導(dǎo)哈希值)隨之改變??梢酝ㄟ^點擊每個獨立區(qū)塊的"挖礦"按鈕模擬挖礦過程。三個區(qū)塊挖礦完成后,嘗試改變區(qū)塊1或區(qū)塊2的內(nèi)容,會發(fā)現(xiàn)該操作導(dǎo)致該區(qū)塊之后的區(qū)塊失效。
為了保證體驗,請到原文鏈接中相應(yīng)位置進行模擬。
上面的兩個挖礦模擬器都是由Anders Brownworth的BlockChain Demo改編而來的。
2.4. 向區(qū)塊鏈添加區(qū)塊比特幣網(wǎng)絡(luò)中的所有礦工互相競爭,率先找到可以添加到區(qū)塊鏈的合法區(qū)塊的礦工將獲得獎勵。找到可以驗證區(qū)塊的nonce值是極其困難的,但由于比特幣網(wǎng)絡(luò)中有大量的礦工,尋找到該值并驗證區(qū)塊的可能性是非常高的。第一個礦工提交一個有效區(qū)塊到區(qū)塊鏈,會得到一定的比特幣作為獎勵。但如果兩個或更多礦工同時提交了他們的區(qū)塊該如何處理呢?
解決沖突如果兩個礦工幾乎在同一時間驗證了區(qū)塊,那么區(qū)塊鏈便產(chǎn)生了分叉,需要等待下一個區(qū)塊去解決沖突。一些礦工會選擇在第一條分叉上挖礦,另一些礦工選擇在第二條分叉上挖礦。第一個找到新區(qū)塊的礦工將解決該沖突。如果新區(qū)塊在第一條分叉上,那么第二條分叉便失效了,前一個區(qū)塊的獎勵由將區(qū)塊提交到第一個分叉上的礦工獲得,第二個分叉上的交易沒有被提交到區(qū)塊鏈中,將回到交易池等待被提交到之后的區(qū)塊中。簡言之,如果區(qū)塊鏈中產(chǎn)生分叉,最長的分叉將被保留下來。
2.5. 區(qū)塊鏈和雙重支付本節(jié)將探討區(qū)塊鏈雙重支付攻擊的最常見方法,和用戶需要采取的一些使自己免于傷害的措施。
Race 攻擊攻擊者在極短的時間內(nèi)使用同一個貨幣發(fā)送給兩個不同的地址。為了防范這種攻擊,推薦等待至少1個區(qū)塊確認后,再接受對方的支付。
Finney 攻擊攻擊者預(yù)先挖好一個包含某條交易的區(qū)塊,釋放該區(qū)塊之前,在第二次交易中使用相同的貨幣。在該場景中,第二次交易將不會生效。為了防范這種攻擊,推薦等待至少6個區(qū)塊確認后,再接受對方的支付。
多數(shù)人攻擊(也稱為51%攻擊)在該攻擊中,攻擊者掌握了比特幣網(wǎng)絡(luò)中51%的算力。攻擊者首先把構(gòu)造好的交易廣播到整個網(wǎng)絡(luò),然后對包含雙重支付貨幣交易的私有區(qū)塊鏈進行挖礦。由于掌握了多數(shù)的算力,他可以保證在某個點上比正確的區(qū)塊鏈擁有更長的鏈,這將取代正確的區(qū)塊鏈,并取消原來的交易。這種攻擊極其不可能發(fā)生,因為成本很高。
3. 通過Python實現(xiàn)的區(qū)塊鏈本節(jié)我們講使用Python實現(xiàn)一個簡單的區(qū)塊鏈和區(qū)塊鏈客戶端。我們的區(qū)塊鏈將有如下特征:
支持向區(qū)塊鏈網(wǎng)絡(luò)中添加多個節(jié)點
工作量證明機制(PoW)
節(jié)點之間簡單的沖突處理
基于RSA加密的交易
區(qū)塊鏈客戶端將有如下特性:
通過公鑰和私鑰生成錢包(基于RSA算法)
基于RSA加密生成交易
我們將實現(xiàn)兩個儀表盤:
礦工使用的"區(qū)塊鏈后臺"
用戶用來生成錢包和發(fā)送比特幣的"區(qū)塊鏈客戶端"
區(qū)塊鏈實現(xiàn)主要基于這個Github項目。我對源碼進行了一些修改,添加了RSA加密算法交易。錢包生成和交易加密基于Jupyter notebook.這兩個儀表盤通過HTML/CSS/JS實現(xiàn)。
你可以從https://github.com/adilmoujahid/blockchain-python-tutorial下載完整源碼。
3.1. 區(qū)塊鏈客戶端實現(xiàn)通過終端進入blockchain_client文件夾中的blockchain客戶端,輸入python blockchain_client.py。在瀏覽器中打開http://localhost:8080將看到如下儀表盤。
儀表盤的導(dǎo)航欄中有三個標(biāo)簽頁:
生成錢包:通過RSA加密算法生成錢包(公鑰私鑰對)
發(fā)起交易:生成交易,并且將它們發(fā)送給區(qū)塊鏈節(jié)點
查看交易:查看區(qū)塊鏈中的交易
為了發(fā)起或查看交易,需要至少運行一個區(qū)塊鏈節(jié)點(下一節(jié)將講解此內(nèi)容)
接下來將解釋一些blockchain_client.py中的關(guān)鍵代碼。
我們定義了含有sender_address, sender_private_key, recipient_address, value這4個屬性的Transaction類。用戶發(fā)起一筆交易時需要填寫這4個內(nèi)容。
to_dict()方法以Python字典格式返回交易信息(無需發(fā)送者密鑰)。sign_transaction()方法取出交易信息(無需發(fā)送者密鑰),并使用發(fā)送者的私鑰簽署該交易信息。
class Transaction: def __init__(self, sender_address, sender_private_key, recipient_address, value): self.sender_address = sender_address self.sender_private_key = sender_private_key self.recipient_address = recipient_address self.value = value def __getattr__(self, attr): return self.data[attr] def to_dict(self): return OrderedDict({"sender_address": self.sender_address, "recipient_address": self.recipient_address, "value": self.value}) def sign_transaction(self): """ Sign transaction with private key """ private_key = RSA.importKey(binascii.unhexlify(self.sender_private_key)) signer = PKCS1_v1_5.new(private_key) h = SHA.new(str(self.to_dict()).encode("utf8")) return binascii.hexlify(signer.sign(h)).decode("ascii")
下面這行代碼會初始化一個Python Flask應(yīng)用,我們將用它創(chuàng)建API,使客戶端與區(qū)塊鏈進行交互。
app = Flask(__name__)
下面我們定義了三個返回html頁面的Flask路由,每個標(biāo)簽頁都有個一個html頁面與之對應(yīng)。
@app.route("/") def index(): return render_template("./index.html") @app.route("/make/transaction") def make_transaction(): return render_template("./make_transaction.html") @app.route("/view/transactions") def view_transaction(): return render_template("./view_transactions.html")
下面我們定義了一個生成錢包(公鑰私鑰對)的API。
@app.route("/wallet/new", methods=["GET"]) def new_wallet(): random_gen = Crypto.Random.new().read private_key = RSA.generate(1024, random_gen) public_key = private_key.publickey() response = { "private_key": binascii.hexlify(private_key.exportKey(format="DER")).decode("ascii"), "public_key": binascii.hexlify(public_key.exportKey(format="DER")).decode("ascii") } return jsonify(response), 200
下面我們定義了一個入?yún)?b>sender_address, sender_private_key, recipient_address, value的API,它會返回交易(無需私鑰)和簽名。
@app.route("/generate/transaction", methods=["POST"]) def generate_transaction(): sender_address = request.form["sender_address"] sender_private_key = request.form["sender_private_key"] recipient_address = request.form["recipient_address"] value = request.form["amount"] transaction = Transaction(sender_address, sender_private_key, recipient_address, value) response = {"transaction": transaction.to_dict(), "signature": transaction.sign_transaction()} return jsonify(response), 2003.2. 區(qū)塊鏈實現(xiàn)
通過終端進入blockchain文件夾,輸入python blockchain.py或者python blockchain.py -p
儀表盤的導(dǎo)航欄中有兩個標(biāo)簽頁:
挖礦:查看交易和區(qū)塊鏈數(shù)據(jù),對新的交易區(qū)塊進行挖礦。
配置:配置不同區(qū)塊鏈節(jié)點之間的鏈接。
接下來將解釋一些blockchain.py中的關(guān)鍵代碼。
我們定義Blockchain類,包含如下屬性:
transactions: 將被添加到下一個區(qū)塊的所有交易的集合。
chain: 實際的區(qū)塊鏈,以區(qū)塊類型數(shù)組的形式存放。
nodes: 節(jié)點url的集合。區(qū)塊鏈通過這些節(jié)點檢索區(qū)塊鏈數(shù)據(jù),更新節(jié)點上尚未同步的區(qū)塊鏈數(shù)據(jù)。
node_id: 用于標(biāo)識區(qū)塊鏈節(jié)點的隨機字符串。
Blockchain類實現(xiàn)了如下方法:
register_node(node_url): 向節(jié)點列表添加新的區(qū)塊鏈節(jié)點。
verify_transaction_signature(sender_address, signature, transaction): 使用公鑰(發(fā)送者地址)驗證提供的簽名。
submit_transaction(sender_address, recipient_address, value, signature): 如果簽名驗證通過,向交易列表中添加交易。
create_block(nonce, previous_hash): 向區(qū)塊鏈添加新的區(qū)塊。
hash(block): 為區(qū)塊創(chuàng)建SHA_256哈希值。
proof_of_work(): 工作量證明算法。尋找滿足挖礦條件的nonce值。
valid_proof(transaction, last_hash, nonce, difficulty=MININGDIFFICULTY): 檢查哈希值是否滿足挖礦條件。這個方法在proof_of_work方法中使用。
valid_chain(chain): 檢查區(qū)塊鏈?zhǔn)欠窈戏ā?/p>
resolve_conflicts(): 通過保留最長分叉解決區(qū)塊鏈節(jié)點之間的沖突。
class Blockchain: def __init__(self): self.transactions = [] self.chain = [] self.nodes = set() #Generate random number to be used as node_id self.node_id = str(uuid4()).replace("-", "") #Create genesis block self.create_block(0, "00") def register_node(self, node_url): """ Add a new node to the list of nodes """ ... def verify_transaction_signature(self, sender_address, signature, transaction): """ Check that the provided signature corresponds to transaction signed by the public key (sender_address) """ ... def submit_transaction(self, sender_address, recipient_address, value, signature): """ Add a transaction to transactions array if the signature verified """ ... def create_block(self, nonce, previous_hash): """ Add a block of transactions to the blockchain """ ... def hash(self, block): """ Create a SHA-256 hash of a block """ ... def proof_of_work(self): """ Proof of work algorithm """ ... def valid_proof(self, transactions, last_hash, nonce, difficulty=MINING_DIFFICULTY): """ Check if a hash value satisfies the mining conditions. This function is used within the proof_of_work function. """ ... def valid_chain(self, chain): """ check if a bockchain is valid """ ... def resolve_conflicts(self): """ Resolve conflicts between blockchain"s nodes by replacing our chain with the longest one in the network. """ ...
下面這行代碼初始化一個Python Flask應(yīng)用,我們將用它創(chuàng)建API,使客戶端與區(qū)塊鏈進行交互。
app = Flask(__name__) CORS(app)
接下來,初始化一個Blockchain實例。
blockchain = Blockchain()
下面我們?yōu)閰^(qū)塊鏈后臺儀表盤定義了兩個返回html頁面的Flask路由。
@app.route("/") def index(): return render_template("./index.html") @app.route("/configure") def configure(): return render_template("./configure.html")
下面我們定義了一些Flask API來管理交易和挖礦。
"/transactions/new": 這個API對應(yīng)在簽名驗證正確后,添加包含sender_address,"recipient_address", amount 和 signature參數(shù)的交易到新的區(qū)塊中。
/transaction/get: 這個API返回所有將被添加到下一個區(qū)塊的交易。
/chain: 這個API返回所有的區(qū)塊鏈數(shù)據(jù)。
/mine: 這個API運行工作量證明算法,并且添加新的交易區(qū)塊到區(qū)塊鏈上。
@app.route("/transactions/new", methods=["POST"]) def new_transaction(): values = request.form # Check that the required fields are in the POST"ed data required = ["sender_address", "recipient_address", "amount", "signature"] if not all(k in values for k in required): return "Missing values", 400 # Create a new Transaction transaction_result = blockchain.submit_transaction(values["sender_address"], values["recipient_address"], values["amount"], values["signature"]) if transaction_result == False: response = {"message": "Invalid Transaction!"} return jsonify(response), 406 else: response = {"message": "Transaction will be added to Block "+ str(transaction_result)} return jsonify(response), 201 @app.route("/transactions/get", methods=["GET"]) def get_transactions(): #Get transactions from transactions pool transactions = blockchain.transactions response = {"transactions": transactions} return jsonify(response), 200 @app.route("/chain", methods=["GET"]) def full_chain(): response = { "chain": blockchain.chain, "length": len(blockchain.chain), } return jsonify(response), 200 @app.route("/mine", methods=["GET"]) def mine(): # We run the proof of work algorithm to get the next proof... last_block = blockchain.chain[-1] nonce = blockchain.proof_of_work() # We must receive a reward for finding the proof. blockchain.submit_transaction(sender_address=MINING_SENDER, recipient_address=blockchain.node_id, value=MINING_REWARD, signature="") # Forge the new Block by adding it to the chain previous_hash = blockchain.hash(last_block) block = blockchain.create_block(nonce, previous_hash) response = { "message": "New Block Forged", "block_number": block["block_number"], "transactions": block["transactions"], "nonce": block["nonce"], "previous_hash": block["previous_hash"], } return jsonify(response), 200
下面我們定義Flash API來管理區(qū)塊鏈節(jié)點:
"/nodes/register": 這個API的入?yún)⑹枪?jié)點url列表,然后將它們更新到列表中每一個節(jié)點中。
"/nodes/resolve": 這個API通過保留最長分叉解決區(qū)塊鏈節(jié)點之間的沖突。
"/nodes/get": 這個API返回所有的節(jié)點列表。
@app.route("/nodes/register", methods=["POST"]) def register_nodes(): values = request.form nodes = values.get("nodes").replace(" ", "").split(",") if nodes is None: return "Error: Please supply a valid list of nodes", 400 for node in nodes: blockchain.register_node(node) response = { "message": "New nodes have been added", "total_nodes": [node for node in blockchain.nodes], } return jsonify(response), 201 @app.route("/nodes/resolve", methods=["GET"]) def consensus(): replaced = blockchain.resolve_conflicts() if replaced: response = { "message": "Our chain was replaced", "new_chain": blockchain.chain } else: response = { "message": "Our chain is authoritative", "chain": blockchain.chain } return jsonify(response), 200 @app.route("/nodes/get", methods=["GET"]) def get_nodes(): nodes = list(blockchain.nodes) response = {"nodes": nodes} return jsonify(response), 200總結(jié)
本文探討了區(qū)塊鏈底層的核心概念和如何通過Python實現(xiàn)一個區(qū)塊鏈系統(tǒng)。簡單起見,本文并沒有覆蓋一些技術(shù)細節(jié),比如說:錢包地址和默克爾樹。如果你想深入了解這些細節(jié),我推薦閱讀比特幣白皮書原文,和bitcoin wiki,以及Andreas Antonopoulos的精彩著作: Mastering Bitcoin: Programming the Open Blockchain
參考文獻Wikipedia - Public-key cryptography
Wikipedia - Hash function
Bitcoin Stackexchange - What happens to a transaction once generated?
Bitcoin Wiki - Majority attack
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/24006.html
摘要:通過入門區(qū)塊鏈本文翻譯自的文章原文地址區(qū)塊鏈可能是繼互聯(lián)網(wǎng)之后最重大和最具突破性的技術(shù)。先不管對比特幣和其他加密貨幣價格的瘋狂行情,本文旨在幫助讀者入門區(qū)塊鏈技術(shù)。 通過Python入門區(qū)塊鏈 本文翻譯自 Adil Moujahid 的文章 A Practical Introduction to Blockchain with Python原文地址:http://adilmoujahi...
摘要:和比特幣協(xié)議有所不同的是,以太坊的設(shè)計十分靈活,極具適應(yīng)性。超級賬本區(qū)塊鏈的商業(yè)應(yīng)用超級賬本超級賬本是基金會下的眾多項目中的一個。證書頒發(fā)機構(gòu)負責(zé)簽發(fā)撤 showImg(https://segmentfault.com/img/bV2ge9?w=900&h=385); 從比特幣開始 一個故事告訴你比特幣的原理及運作機制 這篇文章的定位會比較科普,盡量用類比的方法將比特幣的基本原理講出來...
摘要:所以不用多說,讓我們看看我們的個函數(shù)區(qū)塊鏈的核心是函數(shù)。讀取前一個區(qū)塊的信息,并將其用于將其鏈接到新區(qū)塊。這也是區(qū)塊鏈理念的核心。以太坊開發(fā)教程,主要是針對和程序員進行區(qū)塊鏈以太坊開發(fā)的詳解。 我想對于那里的很多人來說,區(qū)塊鏈就是這種現(xiàn)象,很難不讓你頭腦發(fā)熱。我開始觀看視頻和閱讀文章,但對我個人而言,直到我編寫自己的簡單區(qū)塊鏈,我才真正理解它是什么以及它的潛在應(yīng)用價值。 我對區(qū)塊鏈的看...
摘要:所以不用多說,讓我們看看我們的個函數(shù)區(qū)塊鏈的核心是函數(shù)。讀取前一個區(qū)塊的信息,并將其用于將其鏈接到新區(qū)塊。這也是區(qū)塊鏈理念的核心。以太坊開發(fā)教程,主要是針對和程序員進行區(qū)塊鏈以太坊開發(fā)的詳解。 我想對于那里的很多人來說,區(qū)塊鏈就是這種現(xiàn)象,很難不讓你頭腦發(fā)熱。我開始觀看視頻和閱讀文章,但對我個人而言,直到我編寫自己的簡單區(qū)塊鏈,我才真正理解它是什么以及它的潛在應(yīng)用價值。 我對區(qū)塊鏈的看...
摘要:我們目前正處于一個新興的區(qū)塊鏈開發(fā)行業(yè)中。,一種在以太坊開發(fā)人員中流行的新的簡單編程語言,因為它是用于開發(fā)以太坊智能合約的語言。它是全球至少萬開發(fā)人員使用的世界上最流行的編程語言之一。以太坊,主要是針對工程師使用進行區(qū)塊鏈以太坊開發(fā)的詳解。 我們目前正處于一個新興的區(qū)塊鏈開發(fā)行業(yè)中。區(qū)塊鏈技術(shù)處于初期階段,然而這種顛覆性技術(shù)已經(jīng)成功地風(fēng)靡全球,并且最近經(jīng)歷了一場與眾不同的繁榮。由于許多...
閱讀 1215·2021-11-23 09:51
閱讀 1993·2021-10-08 10:05
閱讀 2351·2019-08-30 15:56
閱讀 1910·2019-08-30 15:55
閱讀 2644·2019-08-30 15:55
閱讀 2498·2019-08-30 13:53
閱讀 3510·2019-08-30 12:52
閱讀 1259·2019-08-29 10:57