精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

用Python從零開始創建區塊鏈

開發 后端
作者認為最快的學習區塊鏈的方式是自己創建一個,本文就跟隨作者用Python來創建一個區塊鏈。通過構建一個區塊鏈可以加深對區塊鏈的理解。

[[217272]]

作者認為最快的學習區塊鏈的方式是自己創建一個,本文就跟隨作者用Python來創建一個區塊鏈。

對數字貨幣的崛起感到新奇的我們,并且想知道其背后的技術——區塊鏈是怎樣實現的。

但是完全搞懂區塊鏈并非易事,我喜歡在實踐中學習,通過寫代碼來學習技術會掌握得更牢固。通過構建一個區塊鏈可以加深對區塊鏈的理解。

準備工作

本文要求讀者對Python有基本的理解,能讀寫基本的Python,并且需要對HTTP請求有基本的了解。

我們知道區塊鏈是由區塊的記錄構成的不可變、有序的鏈結構,記錄可以是交易、文件或任何你想要的數據,重要的是它們是通過哈希值(hashes)鏈接起來的。

如果你還不是很了解哈希,可以查看這篇文章

環境準備

環境準備,確保已經安裝Python3.6+, pip , Flask, requests

安裝方法:

 

  1. pip install Flask==0.12.2 requests==2.18.4 

同時還需要一個HTTP客戶端,比如Postman,cURL或其它客戶端。

參考源代碼(原代碼在我翻譯的時候,無法運行,我fork了一份,修復了其中的錯誤,并添加了翻譯,感謝star)

開始創建Blockchain

新建一個文件 blockchain.py,本文所有的代碼都寫在這一個文件中,可以隨時參考源代碼

Blockchain類

首先創建一個Blockchain類,在構造函數中創建了兩個列表,一個用于儲存區塊鏈,一個用于儲存交易。

以下是Blockchain類的框架:

 

  1. class Blockchain(object): 
  2.     def __init__(self): 
  3.         self.chain = [] 
  4.         self.current_transactions = [] 
  5.     def new_block(self): 
  6.         # Creates a new Block and adds it to the chain 
  7.         pass 
  8.     def new_transaction(self): 
  9.         # Adds a new transaction to the list of transactions 
  10.         pass 
  11.     @staticmethod 
  12.     def hash(block): 
  13.         # Hashes a Block 
  14.         pass 
  15.     @property 
  16.     def last_block(self): 
  17.         # Returns the last Block in the chain 
  18.         pass 

 

Blockchain類用來管理鏈條,它能存儲交易,加入新塊等,下面我們來進一步完善這些方法。

塊結構

每個區塊包含屬性:索引(index),Unix時間戳(timestamp),交易列表(transactions),工作量證明(稍后解釋)以及前一個區塊的Hash值。

以下是一個區塊的結構:

 

  1. block = { 
  2.     'index': 1, 
  3.     'timestamp': 1506057125.900785, 
  4.     'transactions': [ 
  5.         { 
  6.             'sender'"8527147fe1f5426f9dd545de4b27ee00"
  7.             'recipient'"a77f5cdfa2934df3954a5c7c7da5df1f"
  8.             'amount': 5, 
  9.         } 
  10.     ], 
  11.     'proof': 324984774000, 
  12.     'previous_hash'"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824" 

 

到這里,區塊鏈的概念就清楚了,每個新的區塊都包含上一個區塊的Hash,這是關鍵的一點,它保障了區塊鏈不可變性。如果攻擊者破壞了前面的某個區塊,那么后面所有區塊的Hash都會變得不正確。不理解的話,慢慢消化,可參考區塊鏈記賬原理

加入交易

接下來我們需要添加一個交易,來完善下new_transaction方法

 

  1. class Blockchain(object): 
  2.  
  3.     ... 
  4.  
  5.     def new_transaction(self, sender, recipient, amount): 
  6.  
  7.         ""
  8.  
  9.         生成新交易信息,信息將加入到下一個待挖的區塊中 
  10.  
  11.         :param sender: <str> Address of the Sender 
  12.  
  13.         :param recipient: <str> Address of the Recipient 
  14.  
  15.         :param amount: <int> Amount 
  16.  
  17.         :return: <int> The index of the Block that will hold this transaction 
  18.  
  19.         ""
  20.  
  21.         self.current_transactions.append({ 
  22.  
  23.             'sender': sender, 
  24.  
  25.             'recipient': recipient, 
  26.  
  27.             'amount': amount, 
  28.  
  29.         }) 
  30.  
  31.         return self.last_block['index'] + 1 

 

方法向列表中添加一個交易記錄,并返回該記錄將被添加到的區塊(下一個待挖掘的區塊)的索引,等下在用戶提交交易時會有用。

創建新塊

當Blockchain實例化后,我們需要構造一個創世塊(沒有前區塊的第一個區塊),并且給它加上一個工作量證明。

每個區塊都需要經過工作量證明,俗稱挖礦,稍后會繼續講解。

為了構造創世塊,我們還需要完善newblock(), newtransaction() 和hash() 方法:

 

  1. import hashlib 
  2.  
  3. import json 
  4.  
  5. from time import time 
  6.  
  7. class Blockchain(object): 
  8.  
  9.     def __init__(self): 
  10.  
  11.         self.current_transactions = [] 
  12.  
  13.         self.chain = [] 
  14.  
  15.         # Create the genesis block 
  16.  
  17.         self.new_block(previous_hash=1, proof=100) 
  18.  
  19.     def new_block(self, proof, previous_hash=None): 
  20.  
  21.         ""
  22.  
  23.         生成新塊 
  24.  
  25.         :param proof: <int> The proof given by the Proof of Work algorithm 
  26.  
  27.         :param previous_hash: (Optional) <str> Hash of previous Block 
  28.  
  29.         :return: <dict> New Block 
  30.  
  31.         ""
  32.  
  33.         block = { 
  34.  
  35.             'index': len(self.chain) + 1, 
  36.  
  37.             'timestamp'time(), 
  38.  
  39.             'transactions': self.current_transactions, 
  40.  
  41.             'proof': proof, 
  42.  
  43.             'previous_hash': previous_hash or self.hash(self.chain[-1]), 
  44.  
  45.         } 
  46.  
  47.         # Reset the current list of transactions 
  48.  
  49.         self.current_transactions = [] 
  50.  
  51.         self.chain.append(block) 
  52.  
  53.         return block 
  54.  
  55.     def new_transaction(self, sender, recipient, amount): 
  56.  
  57.         ""
  58.  
  59.         生成新交易信息,信息將加入到下一個待挖的區塊中 
  60.  
  61.         :param sender: <str> Address of the Sender 
  62.  
  63.         :param recipient: <str> Address of the Recipient 
  64.  
  65.         :param amount: <int> Amount 
  66.  
  67.         :return: <int> The index of the Block that will hold this transaction 
  68.  
  69.         ""
  70.  
  71.         self.current_transactions.append({ 
  72.  
  73.             'sender': sender, 
  74.  
  75.             'recipient': recipient, 
  76.  
  77.             'amount': amount, 
  78.  
  79.         }) 
  80.  
  81.         return self.last_block['index'] + 1 
  82.  
  83.     @property 
  84.  
  85.     def last_block(self): 
  86.  
  87.         return self.chain[-1] 
  88.  
  89.     @staticmethod 
  90.  
  91.     def hash(block): 
  92.  
  93.         ""
  94.  
  95.         生成塊的 SHA-256 hash值 
  96.  
  97.         :param block: <dict> Block 
  98.  
  99.         :return: <str> 
  100.  
  101.         ""
  102.  
  103.         # We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes 
  104.  
  105.         block_string = json.dumps(block, sort_keys=True).encode() 
  106.  
  107.         return hashlib.sha256(block_string).hexdigest() 

 

通過上面的代碼和注釋可以對區塊鏈有直觀的了解,接下來我們看看區塊是怎么挖出來的。

理解工作量證明

新的區塊依賴工作量證明算法(PoW)來構造。PoW的目標是找出一個符合特定條件的數字,這個數字很難計算出來,但容易驗證。這就是工作量證明的核心思想。

為了方便理解,舉個例子:

假設一個整數 x 乘以另一個整數 y 的積的 Hash 值必須以 0 結尾,即 hash(x * y) = ac23dc…0。設變量 x = 5,求 y 的值?

用Python實現如下:

 

  1. from hashlib import sha256 
  2.  
  3. x = 5 
  4.  
  5. y = 0  # y未知 
  6.  
  7. while sha256(f'{x*y}'.encode()).hexdigest()[-1] != "0"
  8.  
  9.     y += 1 
  10.  
  11. print(f'The solution is y = {y}'

 

結果是y=21. 因為:

 

  1. hash(5 * 21) = 1253e9373e...5e3600155e860 

在比特幣中,使用稱為Hashcash的工作量證明算法,它和上面的問題很類似。礦工們為了爭奪創建區塊的權利而爭相計算結果。通常,計算難度與目標字符串需要滿足的特定字符的數量成正比,礦工算出結果后,會獲得比特幣獎勵。

當然,在網絡上非常容易驗證這個結果。

實現工作量證明

讓我們來實現一個相似PoW算法,規則是:尋找一個數 p,使得它與前一個區塊的 proof 拼接成的字符串的 Hash 值以 4 個零開頭。

 

  1. import hashlib 
  2.  
  3. import json 
  4.  
  5. from time import time 
  6.  
  7. from uuid import uuid4 
  8.  
  9. class Blockchain(object): 
  10.  
  11.     ... 
  12.  
  13.     def proof_of_work(self, last_proof): 
  14.  
  15.         ""
  16.  
  17.         簡單的工作量證明: 
  18.  
  19.          - 查找一個 p' 使得 hash(pp') 以4個0開頭 
  20.  
  21.          - p 是上一個塊的證明,  p' 是當前的證明 
  22.  
  23.         :param last_proof: <int
  24.  
  25.         :return: <int
  26.  
  27.         ""
  28.  
  29.         proof = 0 
  30.  
  31.         while self.valid_proof(last_proof, proof) is False
  32.  
  33.             proof += 1 
  34.  
  35.         return proof 
  36.  
  37.     @staticmethod 
  38.  
  39.     def valid_proof(last_proof, proof): 
  40.  
  41.         ""
  42.  
  43.         驗證證明: 是否hash(last_proof, proof)以4個0開頭? 
  44.  
  45.         :param last_proof: <int> Previous Proof 
  46.  
  47.         :param proof: <intCurrent Proof 
  48.  
  49.         :return: <bool> True if correct, False if not
  50.  
  51.         ""
  52.  
  53.         guess = f'{last_proof}{proof}'.encode() 
  54.  
  55.         guess_hash = hashlib.sha256(guess).hexdigest() 
  56.  
  57.         return guess_hash[:4] == "0000" 

 

衡量算法復雜度的辦法是修改零開頭的個數。使用4個來用于演示,你會發現多一個零都會大大增加計算出結果所需的時間。

現在Blockchain類基本已經完成了,接下來使用HTTP requests來進行交互。

Blockchain作為API接口

我們將使用Python Flask框架,這是一個輕量Web應用框架,它方便將網絡請求映射到 Python函數,現在我們來讓Blockchain運行在基于Flask web上。

我們將創建三個接口:

  • /transactions/new 創建一個交易并添加到區塊
  • /mine 告訴服務器去挖掘新的區塊
  • /chain 返回整個區塊鏈

創建節點

我們的“Flask服務器”將扮演區塊鏈網絡中的一個節點。我們先添加一些框架代碼:

 

  1. import hashlib 
  2.  
  3. import json 
  4.  
  5. from textwrap import dedent 
  6.  
  7. from time import time 
  8.  
  9. from uuid import uuid4 
  10.  
  11. from flask import Flask 
  12.  
  13. class Blockchain(object): 
  14.  
  15.     ... 
  16.  
  17. # Instantiate our Node 
  18.  
  19. app = Flask(__name__) 
  20.  
  21. # Generate a globally unique address for this node 
  22.  
  23. node_identifier = str(uuid4()).replace('-'''
  24.  
  25. # Instantiate the Blockchain 
  26.  
  27. blockchain = Blockchain() 
  28.  
  29. @app.route('/mine', methods=['GET']) 
  30.  
  31. def mine(): 
  32.  
  33.     return "We'll mine a new Block" 
  34.  
  35. @app.route('/transactions/new', methods=['POST']) 
  36.  
  37. def new_transaction(): 
  38.  
  39.     return "We'll add a new transaction" 
  40.  
  41. @app.route('/chain', methods=['GET']) 
  42.  
  43. def full_chain(): 
  44.  
  45.     response = { 
  46.  
  47.         'chain': blockchain.chain, 
  48.  
  49.         'length': len(blockchain.chain), 
  50.  
  51.     } 
  52.  
  53.     return jsonify(response), 200 
  54.  
  55. if __name__ == '__main__'
  56.  
  57.     app.run(host='0.0.0.0', port=5000) 

 

簡單的說明一下以上代碼:

第15行: 創建一個節點.

第18行: 為節點創建一個隨機的名字.

第21行: 實例Blockchain類.

第24–26行: 創建/mine GET接口。

第28–30行: 創建/transactions/new POST接口,可以給接口發送交易數據.

第32–38行: 創建 /chain 接口, 返回整個區塊鏈。

第40–41行: 服務運行在端口5000上.

發送交易

發送到節點的交易數據結構如下:

 

  1.  
  2.  "sender""my address"
  3.  
  4.  "recipient""someone else's address"
  5.  
  6.  "amount": 5 
  7.  

 

之前已經有添加交易的方法,基于接口來添加交易就很簡單了

 

  1. import hashlib 
  2.  
  3. import json 
  4.  
  5. from textwrap import dedent 
  6.  
  7. from time import time 
  8.  
  9. from uuid import uuid4 
  10.  
  11. from flask import Flask, jsonify, request 
  12.  
  13. ... 
  14.  
  15. @app.route('/transactions/new', methods=['POST']) 
  16.  
  17. def new_transaction(): 
  18.  
  19.     values = request.get_json() 
  20.  
  21.     # Check that the required fields are in the POST'ed data 
  22.  
  23.     required = ['sender''recipient''amount'
  24.  
  25.     if not all(k in values for k in required): 
  26.  
  27.         return 'Missing values', 400 
  28.  
  29.     # Create a new Transaction 
  30.  
  31.     index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount']) 
  32.  
  33.     response = {'message': f'Transaction will be added to Block {index}'
  34.  
  35.     return jsonify(response), 201 

 

挖礦

挖礦正是神奇所在,它很簡單,做了一下三件事:

  • 計算工作量證明PoW
  • 通過新增一個交易授予礦工(自己)一個幣
  • 構造新區塊并將其添加到鏈中

 

  1. import hashlib 
  2.  
  3. import json 
  4.  
  5. from time import time 
  6.  
  7. from uuid import uuid4 
  8.  
  9. from flask import Flask, jsonify, request 
  10.  
  11. ... 
  12.  
  13. @app.route('/mine', methods=['GET']) 
  14.  
  15. def mine(): 
  16.  
  17.     # We run the proof of work algorithm to get the next proof... 
  18.  
  19.     last_block = blockchain.last_block 
  20.  
  21.     last_proof = last_block['proof'
  22.  
  23.     proof = blockchain.proof_of_work(last_proof) 
  24.  
  25.     # 給工作量證明的節點提供獎勵. 
  26.  
  27.     # 發送者為 "0" 表明是新挖出的幣 
  28.  
  29.     blockchain.new_transaction( 
  30.  
  31.         sender="0"
  32.  
  33.         recipient=node_identifier, 
  34.  
  35.         amount=1, 
  36.  
  37.     ) 
  38.  
  39.     # Forge the new Block by adding it to the chain 
  40.  
  41.     block = blockchain.new_block(proof) 
  42.  
  43.     response = { 
  44.  
  45.         'message'"New Block Forged"
  46.  
  47.         'index': block['index'], 
  48.  
  49.         'transactions': block['transactions'], 
  50.  
  51.         'proof': block['proof'], 
  52.  
  53.         'previous_hash': block['previous_hash'], 
  54.  
  55.     } 
  56.  
  57.     return jsonify(response), 200 

 

注意交易的接收者是我們自己的服務器節點,我們做的大部分工作都只是圍繞Blockchain類方法進行交互。到此,我們的區塊鏈就算完成了,我們來實際運行下

運行區塊鏈

你可以使用cURL 或Postman 去和API進行交互

啟動server:

 

  1. $ python blockchain.py 
  2.  
  3. * Runing on http://127.0.0.1:5000/ (Press CTRL+C to quit) 

 

讓我們通過請求 http://localhost:5000/mine 來進行挖礦

用Postman請求挖礦

通過post請求,添加一個新交易

用Postman請求挖礦

如果不是使用Postman,則用一下的cURL語句也是一樣的:

 

  1. $ curl -X POST -H "Content-Type: application/json" -d '{ 
  2.  
  3.  "sender""d4ee26eee15148ee92c6cd394edd974e"
  4.  
  5.  "recipient""someone-other-address"
  6.  
  7.  "amount": 5 
  8.  
  9. }' "http://localhost:5000/transactions/new" 

 

在挖了兩次礦之后,就有3個塊了,通過請求 http://localhost:5000/chain 可以得到所有的塊信息。

 

  1.  
  2.   "chain": [ 
  3.  
  4.     { 
  5.  
  6.       "index": 1, 
  7.  
  8.       "previous_hash": 1, 
  9.  
  10.       "proof": 100, 
  11.  
  12.       "timestamp": 1506280650.770839, 
  13.  
  14.       "transactions": [] 
  15.  
  16.     }, 
  17.  
  18.     { 
  19.  
  20.       "index": 2, 
  21.  
  22.       "previous_hash""c099bc...bfb7"
  23.  
  24.       "proof": 35293, 
  25.  
  26.       "timestamp": 1506280664.717925, 
  27.  
  28.       "transactions": [ 
  29.  
  30.         { 
  31.  
  32.           "amount": 1, 
  33.  
  34.           "recipient""8bbcb347e0634905b0cac7955bae152b"
  35.  
  36.           "sender""0" 
  37.  
  38.         } 
  39.  
  40.       ] 
  41.  
  42.     }, 
  43.  
  44.     { 
  45.  
  46.       "index": 3, 
  47.  
  48.       "previous_hash""eff91a...10f2"
  49.  
  50.       "proof": 35089, 
  51.  
  52.       "timestamp": 1506280666.1086972, 
  53.  
  54.       "transactions": [ 
  55.  
  56.         { 
  57.  
  58.           "amount": 1, 
  59.  
  60.           "recipient""8bbcb347e0634905b0cac7955bae152b"
  61.  
  62.           "sender""0" 
  63.  
  64.         } 
  65.  
  66.       ] 
  67.  
  68.     } 
  69.  
  70.   ], 
  71.  
  72.   "length": 3 
  73.  

 

一致性(共識)

我們已經有了一個基本的區塊鏈可以接受交易和挖礦。但是區塊鏈系統應該是分布式的。既然是分布式的,那么我們究竟拿什么保證所有節點有同樣的鏈呢?這就是一致性問題,我們要想在網絡上有多個節點,就必須實現一個一致性的算法。

注冊節點

在實現一致性算法之前,我們需要找到一種方式讓一個節點知道它相鄰的節點。每個節點都需要保存一份包含網絡中其它節點的記錄。因此讓我們新增幾個接口:

/nodes/register 接收URL形式的新節點列表

/nodes/resolve執行一致性算法,解決任何沖突,確保節點擁有正確的鏈

我們修改下Blockchain的init函數并提供一個注冊節點方法:

 

  1. ... 
  2.  
  3. from urllib.parse import urlparse 
  4.  
  5. ... 
  6.  
  7. class Blockchain(object): 
  8.  
  9.     def __init__(self): 
  10.  
  11.         ... 
  12.  
  13.         self.nodes = set() 
  14.  
  15.         ... 
  16.  
  17.     def register_node(self, address): 
  18.  
  19.         ""
  20.  
  21.         Add a new node to the list of nodes 
  22.  
  23.         :param address: <str> Address of node. Eg. 'http://192.168.0.5:5000' 
  24.  
  25.         :return: None 
  26.  
  27.         ""
  28.  
  29.         parsed_url = urlparse(address) 
  30.  
  31.         self.nodes.add(parsed_url.netloc) 

 

我們用 set 來儲存節點,這是一種避免重復添加節點的簡單方法。

實現共識算法

前面提到,沖突是指不同的節點擁有不同的鏈,為了解決這個問題,規定最長的、有效的鏈才是最終的鏈,換句話說,網絡中有效最長鏈才是實際的鏈。

我們使用一下的算法,來達到網絡中的共識

 

  1. ... 
  2.  
  3. import requests 
  4.  
  5. class Blockchain(object) 
  6.  
  7.     ... 
  8.  
  9.     def valid_chain(self, chain): 
  10.  
  11.         ""
  12.  
  13.         Determine if a given blockchain is valid 
  14.  
  15.         :param chain: <list> A blockchain 
  16.  
  17.         :return: <bool> True if valid, False if not 
  18.  
  19.         ""
  20.  
  21.         last_block = chain[0] 
  22.  
  23.         current_index = 1 
  24.  
  25.         while current_index < len(chain): 
  26.  
  27.             block = chain[current_index] 
  28.  
  29.             print(f'{last_block}'
  30.  
  31.             print(f'{block}'
  32.  
  33.             print("\n-----------\n"
  34.  
  35.             # Check that the hash of the block is correct 
  36.  
  37.             if block['previous_hash'] != self.hash(last_block): 
  38.  
  39.                 return False 
  40.  
  41.             # Check that the Proof of Work is correct 
  42.  
  43.             if not self.valid_proof(last_block['proof'], block['proof']): 
  44.  
  45.                 return False 
  46.  
  47.             last_block = block 
  48.  
  49.             current_index += 1 
  50.  
  51.         return True 
  52.  
  53.     def resolve_conflicts(self): 
  54.  
  55.         ""
  56.  
  57.         共識算法解決沖突 
  58.  
  59.         使用網絡中最長的鏈. 
  60.  
  61.         :return: <bool> True 如果鏈被取代, 否則為False 
  62.  
  63.         ""
  64.  
  65.         neighbours = self.nodes 
  66.  
  67.         new_chain = None 
  68.  
  69.         # We're only looking for chains longer than ours 
  70.  
  71.         max_length = len(self.chain) 
  72.  
  73.         # Grab and verify the chains from all the nodes in our network 
  74.  
  75.         for node in neighbours: 
  76.  
  77.             response = requests.get(f'http://{node}/chain'
  78.  
  79.             if response.status_code == 200: 
  80.  
  81.                 length = response.json()['length'
  82.  
  83.                 chain = response.json()['chain'
  84.  
  85.                 # Check if the length is longer and the chain is valid 
  86.  
  87.                 if length > max_length and self.valid_chain(chain): 
  88.  
  89.                     max_length = length 
  90.  
  91.                     new_chain = chain 
  92.  
  93.         # Replace our chain if we discovered a new, valid chain longer than ours 
  94.  
  95.         if new_chain: 
  96.  
  97.             self.chain = new_chain 
  98.  
  99.             return True 
  100.  
  101.         return False 

 

第一個方法 valid_chain() 用來檢查是否是有效鏈,遍歷每個塊驗證hash和proof.

第2個方法 resolve_conflicts() 用來解決沖突,遍歷所有的鄰居節點,并用上一個方法檢查鏈的有效性, 如果發現有效更長鏈,就替換掉自己的鏈

讓我們添加兩個路由,一個用來注冊節點,一個用來解決沖突。

 

  1. @app.route('/nodes/register', methods=['POST']) 
  2.  
  3. def register_nodes(): 
  4.  
  5.     values = request.get_json() 
  6.  
  7.     nodes = values.get('nodes'
  8.  
  9.     if nodes is None: 
  10.  
  11.         return "Error: Please supply a valid list of nodes", 400 
  12.  
  13.     for node in nodes: 
  14.  
  15.         blockchain.register_node(node) 
  16.  
  17.     response = { 
  18.  
  19.         'message''New nodes have been added'
  20.  
  21.         'total_nodes': list(blockchain.nodes), 
  22.  
  23.     } 
  24.  
  25.     return jsonify(response), 201 
  26.  
  27. @app.route('/nodes/resolve', methods=['GET']) 
  28.  
  29. def consensus(): 
  30.  
  31.     replaced = blockchain.resolve_conflicts() 
  32.  
  33.     if replaced: 
  34.  
  35.         response = { 
  36.  
  37.             'message''Our chain was replaced'
  38.  
  39.             'new_chain': blockchain.chain 
  40.  
  41.         } 
  42.  
  43.     else
  44.  
  45.         response = { 
  46.  
  47.             'message''Our chain is authoritative'
  48.  
  49.             'chain': blockchain.chain 
  50.  
  51.         } 
  52.  
  53.     return jsonify(response), 200 

 

你可以在不同的機器運行節點,或在一臺機機開啟不同的網絡端口來模擬多節點的網絡,這里在同一臺機器開啟不同的端口演示,在不同的終端運行一下命令,就啟動了兩個節點:http://localhost:5000 和 http://localhost:5001

 

  1. pipenv run python blockchain.py 
  2.  
  3. pipenv run python blockchain.py -p 5001

注冊新節點

然后在節點2上挖兩個塊,確保是更長的鏈,然后在節點1上訪問接口/nodes/resolve ,這時節點1的鏈會通過共識算法被節點2的鏈取代。

共識算法解決沖突

 

好啦,你可以邀請朋友們一起來測試你的區塊鏈 

責任編輯:龐桂玉 來源: Python中文社區
相關推薦

2018-03-14 11:15:06

2018-03-05 09:31:23

2018-03-15 13:48:45

架構技術棧微信半月刊

2011-09-07 13:06:04

Android Wid

2021-05-17 22:40:56

區塊鏈比特幣技術

2017-12-12 12:24:39

Python決策樹

2017-07-19 10:22:07

2021-03-16 11:30:33

2015-11-17 16:11:07

Code Review

2018-04-18 07:01:59

Docker容器虛擬機

2019-01-18 12:39:45

云計算PaaS公有云

2024-12-06 17:02:26

2020-07-02 15:32:23

Kubernetes容器架構

2024-03-01 19:53:37

PyBuilderPython開發

2018-05-23 15:20:08

區塊鏈數字貨幣比特幣

2010-05-26 17:35:08

配置Xcode SVN

2018-09-14 17:16:22

云計算軟件計算機網絡

2024-05-15 14:29:45

2024-05-17 17:29:00

CurdlingPython開發

2018-05-09 20:08:09

人工智能深度學習Python
點贊
收藏

51CTO技術棧公眾號

成年人一级黄色片| 色综合蜜月久久综合网| 少妇高潮在线观看| 国产精品高清网站| 国产蜜臀av在线一区二区三区| 欧美bbbxxxxx| 日韩Av无码精品| 91高清视频在线免费观看| 国产成人精品综合在线观看 | 自产国语精品视频| 999久久久久久| 成人av在线不卡| 亚洲大胆人体视频| 久久人人97超碰国产公开结果| 欧美高清电影在线| 五月天婷婷亚洲| 欧美激情久久久| 久久久午夜精品理论片中文字幕| 成人自拍av| 欧美精品videos极品| 99久久精品无码一区二区毛片 | 日韩中文字幕在线视频观看| 日韩av最新在线观看| 狂野欧美一区| 午夜小视频福利在线观看| 黄色网址在线视频| 成人国产精品一区二区| 亚洲成精国产精品女| av影片在线一区| 丰满少妇被猛烈进入| 亚洲视频在线观看一区二区三区| 久久视频在线免费观看| 2019国产精品| 视频在线观看免费影院欧美meiju| 国产超碰人人爽人人做人人爱| 亚洲视频小说| 亚洲网在线观看| 成人中文字幕合集| 亚洲欧美在线人成swag| 日韩熟女一区二区| 北条麻妃在线视频观看| 久久人91精品久久久久久不卡| 日韩一区在线播放| 欧美韩日一区| 在线视频1区2区| 免费看裸体网站| 欧美少妇一区| 亚洲欧美一区二区三区久久| av电影一区二区| 欧美日韩大片免费观看| 可以免费观看的毛片| 国产成人av片| www.久久爱.cn| 精品久久人人做人人爰| 高清成人免费视频| 成人爽a毛片免费啪啪红桃视频| 99在线无码精品入口| 8x8x成人免费视频| 成人精品一二区| 精品欧美一区二区三区精品久久 | 无码人妻精品一区二区三区9厂 | 丰满诱人av在线播放| 欧美日韩国产精品综合| 丰满的少妇愉情hd高清果冻传媒| 欧美国产日韩二区| 丁香五六月婷婷久久激情| 麻豆久久精品| 久久精品资源| 国产综合视频在线| a天堂中文字幕| 国产精品波多野结衣| 久久免费观看视频| 欧美午夜精品一区二区蜜桃| 国产精品一级片| 九九热精品视频在线观看| 免费网站免费进入在线| 日韩精品在线免费看| 青青青国产在线观看| 日韩女优制服丝袜电影| 久久这里只有精品6| 久久日文中文字幕乱码| 99久久精品免费看国产小宝寻花| 在线观看日本网站| 欧美日韩一区二区区| 日韩在线电影一区| 国内精品久久久久久影视8| 欧美亚一区二区| 99re热视频这里只精品| 伊人久久大香线蕉精品组织观看| 成人在线爆射| 香蕉视频国产在线| 国产一区二区三区在线视频观看| 欧美色国产精品| 香蕉国产精品| 欧美亚洲大片| 亚洲日本国产精品| 国产主播在线观看| 国内自拍偷拍视频| 一区中文字幕在线观看| 国产精品7m视频| 亚洲午夜久久久影院| 欧美午夜激情小视频| 91在线云播放| 国产精品主播| 久久最新网址| 成人日韩在线观看| 成人动漫在线播放| 中文字幕网址在线| 欧美风情第一页| 亚洲图片 自拍偷拍| 久久福利一区二区| 国产日韩欧美一区二区三区四区| 久久免费福利视频| 亚洲日本中文字幕| 欧美卡1卡2卡| 亚洲va欧美va人人爽| 91麻豆国产精品久久| 蜜臀精品久久久久久蜜臀| 天天综合网91| 精品午夜电影| 日韩黄色碟片| xxxx视频在线| 欧洲美女少妇精品| 亚洲第一页综合| 最好看的日本字幕mv视频大全| 女人18毛片毛片毛片毛片区二| www,av在线| 999香蕉视频| 69精品丰满人妻无码视频a片| 国产在线一区二| 国产美女主播一区| 午夜精品一区二区三区av| 在线精品播放av| 精品播放一区二区| 日韩欧美亚洲另类制服综合在线| 黑人巨大精品欧美一区二区免费 | 午夜精品久久17c| 最近日韩中文字幕中文| 精品卡一卡二卡三卡四在线| 欧美色另类天堂2015| 欧美网色网址| 免费国产在线视频| 亚洲国产一二三区| 97国产精品久久久| 国产精品xxxxxx| 无码一区二区三区| 你懂的国产在线| 精品国产xxx| 日本免费在线观看视频| 激情五月色婷婷| 国产性xxxx高清| 亚洲黄色一区二区| 国产免费观看av| 免费在线不卡视频| 成年人免费看毛片| 国产午夜小视频| 国产69精品久久久久久久久久| 精品无码一区二区三区电影桃花| 国产这里有精品| 国产精品白浆一区二小说| 国产91av视频| 黄瓜视频在线免费观看| av片免费观看| 国产精品久久影视| 亚洲精品久久久蜜桃动漫| 天堂国产一区二区三区| 国产黄色在线播放| 黄色在线播放网站| 午夜dj在线观看高清视频完整版| 国产偷倩在线播放| 亚洲伦理影院| 日韩中文字幕无砖| 你懂的视频欧美| 我不卡影院28| 午夜在线精品| 极品尤物av久久免费看| 91免费看视频| 有坂深雪av一区二区精品| 欧美日韩国产中字| 欧美一区二区三区男人的天堂| 国产视频在线观看一区二区| 美女啪啪无遮挡免费久久网站| 欧美夜福利tv在线| av一区二区三区四区电影| 色婷婷精品国产一区二区三区| 大片在线观看网站免费收看| 国产一级特黄a大片免费| 男人网站在线观看| 成人免费毛片东京热| 一级特黄aaa大片| 国产日产精品久久久久久婷婷| 丁香花在线影院| 久久免费精品| 欧美.www| 成人激情免费网站| 亚洲一区二区3| 日韩精品一区二区三区三区免费 | 欧美亚洲福利| 成人在线免费观看视频| 日本aⅴ免费视频一区二区三区 | 国产精品久久久久免费a∨大胸 | 国产乱人伦精品一区二区在线观看| 久久久国产精华| 日韩欧美在线播放| 国产小视频国产精品| 国产精品久久久久久久久久免费 | 日日碰狠狠添天天爽超碰97| xxxx黄色片| 日韩人妻精品中文字幕| 精品资源在线看| 性欧美1819sex性高清| 精品国产91乱码一区二区三区四区 | 欧美a在线播放| 国产免费高清av| gogo高清在线播放免费| 尤物tv在线精品| 国模一区二区三区白浆| 亚洲一区二区四区蜜桃| 日韩精品在线视频美女| 国产日韩在线播放| av一区二区三区免费观看| 强伦人妻一区二区三区| 国产乱色精品成人免费视频| 黄色大片在线| 欧美激情偷拍自拍| 成人ar影院免费观看视频| 欧洲精品在线观看| 欧美精品情趣视频| 色综合久久久久久久久五月| xxxx视频在线观看| 又骚又黄的视频| 色戒汤唯在线观看| 午夜久久tv| 136国产福利精品导航| 国产亚洲精品一区二区| 国产一区二区三区色淫影院| 日本77777| 中文有码在线播放| 青青青免费在线视频| 欧美精品一线| 亚洲免费av网站| 操人视频在线观看欧美| 亚洲精品成人a8198a| 久久国产精品无码一级毛片| 欧美视频一二区| 亚洲精品黑牛一区二区三区| 国产一区 二区 三区一级| 欧美影院一区二区| 国产精品免费在线免费| 国产精品亚洲二区在线观看| 免费日韩在线视频| 男人资源在线播放| 日韩精品影视| 国产精品人妖ts系列视频| www国产精品com| 一区二区免费电影| www深夜成人a√在线| 黄色网址在线免费观看| 欧美成人69| 亚洲v精品v日韩v欧美v专区| 日本一本a高清免费不卡| 麻豆av免费在线| 国产又粗又猛又黄| 精品视频成人| 99视频一区二区三区| 亚洲视频在线视频| 日韩人妻精品一区二区三区| 久久一级黄色片| 亚洲黄色中文字幕| 激情五月婷婷综合网| 日韩一区二区三区三四区视频在线观看 | 妖精视频一区二区三区免费观看| 久久伊99综合婷婷久久伊| 精品国产一区二区三区在线观看| 日本一二三区视频在线| 日韩精品一区二区亚洲av| 色狠狠一区二区三区| 91网上在线视频| 久久香蕉国产线看观看av| 国产男女在线观看| 午夜久久久久久久久久| 国产精品欧美在线观看| 亚洲一区在线观看网站| 国产精品草莓在线免费观看| 无码国产精品一区二区免费式直播 | 国产99久久久欧美黑人 | 四虎精品永久免费| 久久综合狠狠综合久久综合88| 久久韩国免费视频| 一区二区三区视频网| 免费看男男www网站入口在线| 亚洲国产二区| 精品久久久久久久人人人人传媒 | 国语精品免费视频| 欧美日韩成人免费观看| 97久久中文字幕| 亚洲日本一区二区三区| 成人黄色片网站| 永久免费看片直接| 高清不卡一区| 亚洲欧美另类图片小说| 国产有码在线一区二区视频| 欧美a级片免费看| 一区在线不卡| 亚洲资源在线观看| 99久热re在线精品996热视频| 麻豆成人在线视频| 91欧美极品| 精品美女永久免费视频| 欧美高清性xxxxhdvideosex| 亚洲第一网站在线观看| 久久一区二区中文字幕| 在线不卡欧美精品一区二区三区| 强伦女教师2:伦理在线观看| 国产精品玖玖玖| 亚洲欧洲午夜| 在线视频欧美性高潮| 下面一进一出好爽视频| 国产拍在线视频| 国产精品久久看| 国产福利一区二区三区在线观看| 国内免费精品视频| 日韩精品免费一区二区在线观看| 日韩午夜在线观看| 国产超级av在线| 国产乱色在线观看| 91在线视频在线| 91精品综合久久| 亚洲图片欧美在线| 亚洲一区国产一区| 美女扒开尿口让男人操亚洲视频网站| 久久一区二区电影| 日本在线一区二区三区| 欧美午夜宅男影院| 美女福利视频在线| 国产自产自拍视频在线观看| 亚洲天堂网中文字| 日韩影片在线播放| 国产在线日本| 94色蜜桃网一区二区三区| 亚洲自拍中文字幕| 国产同性人妖ts口直男| 日韩高清不卡一区| 国产精品久久久久久久久久99| 国产中文字幕免费| 今天的高清视频免费播放成人| 久久视频这里只有精品| 婷婷社区五月天| 欧美xxxxx视频| 欧美成人sm免费视频| 性色国产成人久久久精品| 日韩在线视屏| 中文国产成人精品久久一| 18精品爽国产三级网站| 欧美老女人另类| 久久亚洲精品一区二区| 熟女少妇a性色生活片毛片| 91成人免费| 欧美极品少妇与黑人| 欧美一级视频免费观看| 99热免费精品| 国产精品三级美女白浆呻吟| 正在播放木下凛凛xv99| 国产米奇在线777精品观看| 99久久自偷自偷国产精品不卡| 婷婷视频在线观看| 久久久精品免费免费| 色撸撸在线观看| 2020国产在线| 亚洲激情图片qvod| 日韩av一级大片| 天堂网在线资源| 久久99精品国产.久久久久久| 91亚洲一区精品| 人妻中文字幕一区| 国产无一区二区| 天天做天天爱天天高潮| 国产91足控脚交在线观看| 狠狠躁夜夜躁人人躁婷婷91 | 青青草视频在线免费观看| 国产精品丝袜91| 97超碰青青草| 亚洲精品毛片| 亚洲欧美国产va在线影院| 色在线观看视频| 免费成人在线观看| 欧美国产一区二区在线| 免费看电影在线| 色综合久久天天| 中文字幕在线永久| 欧美1级日本1级| 亚洲va欧美va国产综合久久| www.视频在线.com| 日本精品一级二级| 久久久久国产免费| 一区二区影视| 91免费看蜜桃| 女人天堂av在线播放| 日韩你懂的电影在线观看| 777777国产7777777|