精品欧美一区二区三区在线观看 _久久久久国色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| 日韩在线视频免费| 日本亚洲三级在线| 欧美日韩爱爱视频| 久久久久久久久久久久久久久| 999精品视频在线观看| 亚洲成a人片在线不卡一二三区| 日韩精品最新在线观看| www夜片内射视频日韩精品成人| 国产精品嫩草99av在线| 久久精品国产成人精品| 一本加勒比波多野结衣| 996久久国产精品线观看| 欧美日韩亚洲精品内裤| 超碰超碰超碰超碰超碰| 国产美女视频一区二区三区| 国产精品自在在线| 国产91在线播放| 久久久精品91| 久久精品99久久无色码中文字幕| 亚洲福利在线观看| 999热精品视频| 欧美成人性网| 亚洲成a人在线观看| 成年人免费观看的视频| 国产精品麻豆一区二区三区| 99视频一区二区三区| 92国产精品视频| 亚洲精品91天天久久人人| 国产欧美日韩一区二区三区在线| 欧美人成在线视频| 国产中文av在线| 国产日产精品一区二区三区四区的观看方式 | 亚洲精品自在久久| 超碰caoprom| 日本在线视频一区二区三区| 欧美日韩不卡在线| 黄色片在线免费| 日本免费久久| 欧美天堂在线观看| 青青青青草视频| 大桥未久在线播放| 亚洲综合成人网| 男人的天堂视频在线| 秋霞午夜理伦电影在线观看| 中文欧美字幕免费| 一区二区免费在线视频| 欧美成人二区| 亚洲欧洲成人精品av97| 在线视频精品一区| 成人影院在线看| 亚洲乱码国产乱码精品精可以看 | av文字幕在线观看| 亚洲视频一区在线| av动漫在线免费观看| 手机av免费在线| 亚洲成人1区2区| 日韩少妇内射免费播放18禁裸乳| 一区二区精品伦理... | 国产婷婷在线视频| 国产福利不卡视频| 国产精品免费视频一区二区| 欧美自拍偷拍一区二区| av日韩在线网站| 蜜桃麻豆91| av每日在线更新| 国产精品久久久久久久第一福利| 亚洲资源在线网| 麻豆视频在线观看免费| 亚洲黄色av一区| 欧美成人高潮一二区在线看| 韩国美女久久| 欧美日韩一区在线| 熟妇无码乱子成人精品| 国产乱人伦丫前精品视频| 日韩精品小视频| 国产不卡在线观看视频| 欧美激情第8页| 欧美诱惑福利视频| 伊人影院中文字幕| 成人在线综合网| 色姑娘综合av| 污网站在线免费看| 91国产精品成人| 性久久久久久久久久久久久久| 国产精品超碰| 色先锋资源久久综合5566| 久久亚洲av午夜福利精品一区| 美女诱惑黄网站一区| 91九色视频导航| 五月婷婷丁香花| 亚洲欧洲国产日韩| 116极品美女午夜一级| 亚洲免费资源| 亚洲乱码国产乱码精品精| 蜜桃av.com| 国产欧美二区| 超碰97在线资源| 91官网在线| 天天射综合影视| 亚洲精品视频三区| 亚洲区小说区图片区qvod| 久久精彩免费视频| 五月天婷婷激情| 国产传媒欧美日韩成人| 亚洲欧美日韩国产成人综合一二三区 | 日韩在线观看免费高清| 欧美videossex极品| 韩国精品久久久| 青青草成人激情在线| 丝袜综合欧美| 91精品国产入口| 国产精品酒店视频| 视频在线观看国产精品| 国产自产精品| av免费在线视| 日韩一区二区三区精品视频| 波兰性xxxxx极品hd| 久久精品人人| 久久久久久艹| 97蜜桃久久| 精品国产精品一区二区夜夜嗨| 99久久久无码国产精品不卡| 手机精品视频在线观看| 蜜桃av噜噜一区二区三| 91九色国产在线播放| 欧美变态tickling挠脚心| 久久高清内射无套| 精品在线亚洲视频| 亚洲综合第一| 国产欧美自拍| 中文字幕亚洲字幕| 久久精品国产亚洲av麻豆蜜芽| 99久久精品国产网站| www.日本在线视频| 一区二区三区视频免费视频观看网站| 中文字幕精品av| 青青国产在线视频| 久久久精品黄色| 欧美污视频网站| 伊人久久大香线蕉综合网蜜芽| 欧洲午夜精品久久久| 日本午夜在线| 日本久久一区二区| 国产真人做爰视频免费| 免费一区二区视频| 亚洲一区不卡在线| 亚洲青青一区| 欧美高清在线观看| 日本精品一区二区在线观看| 亚洲成a人v欧美综合天堂| 菠萝菠萝蜜网站| 先锋影音久久| 亚洲精品免费在线看| 91成人小视频| 色综合久久久久久中文网| 男人天堂综合网| 黑人精品xxx一区一二区| 成年人免费观看视频网站| 青椒成人免费视频| 最新视频 - x88av| 亚洲性视频在线| 欧美一级淫片播放口| 国产香蕉在线| 777欧美精品| 国产精品成人久久| 久久这里只有精品6| 鲁一鲁一鲁一鲁一av| 欧美激情aⅴ一区二区三区| 国严精品久久久久久亚洲影视 | 人妻丰满熟妇aⅴ无码| 久久一区精品| 97超碰免费观看| 欧美变态网站| 国产精品视频久久久| 午夜小视频在线观看| 亚洲精品视频网上网址在线观看| 中文在线资源天堂| 亚洲综合在线免费观看| 中文幕无线码中文字蜜桃| 久久精品99久久久| 免费在线观看视频a| 欧美日中文字幕| 97人人模人人爽视频一区二区| 无码小电影在线观看网站免费| 中文字幕日韩精品在线观看| 黑人乱码一区二区三区av| 欧美在线观看视频在线| 久久免费视频6| 国产亚洲欧美日韩日本| 女女调教被c哭捆绑喷水百合| 久久久一二三| 福利视频免费在线观看| 日韩欧美在线中字| 精品国产一区二区三区麻豆免费观看完整版 | 精品无人区一区二区三区| 开心久久婷婷综合中文字幕| 久久青草福利网站| 日韩大片在线永久免费观看网站| 精品国产sm最大网站免费看| 亚洲网站在线免费观看| 午夜不卡在线视频| tube国产麻豆| 国产色91在线| 亚洲永久无码7777kkk| 国产精品一区二区三区乱码| 少妇黄色一级片| 中文高清一区| 国产在线观看欧美| 日韩久久精品| 日本亚洲自拍| 米奇777超碰欧美日韩亚洲| 豆国产97在线| 久久国产精品美女| 国产精品视频导航| 电影一区二区三| 91禁国产网站| 3344国产永久在线观看视频| 插插插亚洲综合网| 蜜桃视频在线观看www社区| 亚洲视频视频在线| 日韩国产福利| 亚洲精品美女久久| 日本xxxxxwwwww| 日韩视频免费直播| 一本一道人人妻人人妻αv| 欧美在线视频不卡| 成人av网站在线播放| 欧美日韩亚洲高清| 伊人久久综合视频| 欧美丝袜一区二区| 欧美精品亚洲精品日韩精品| 亚洲丰满少妇videoshd| 国产亚洲欧美精品久久久久久| 亚洲精品ww久久久久久p站| 天天色影综合网| 最新日韩在线视频| 51精品免费网站| 亚洲欧美日韩中文播放| 男人晚上看的视频| 亚洲色图在线看| 免费看一级大片| 亚洲靠逼com| 麻豆一区产品精品蜜桃的特点| 亚洲免费av在线| 青娱乐国产盛宴| 五月婷婷综合在线| 一区二区三区福利视频| 日韩欧美在线字幕| 亚洲 小说区 图片区| 欧美手机在线视频| 国产精品视频久久久久久| 欧美一区日本一区韩国一区| 精品人妻久久久久一区二区三区| 日韩一区二区在线播放| 蜜臀久久精品久久久久| 日韩精品免费一线在线观看| 欧美在线观看在线观看| 这里只有精品久久| 菠萝蜜视频国产在线播放| 色综合久久88| 综合久久2023| 成人福利免费观看| 国产精品99久久免费观看| 奇米精品在线| 在线中文一区| 无码精品国产一区二区三区免费| 日韩av中文在线观看| 交换做爰国语对白| 99视频精品全部免费在线| 五月天婷婷丁香网| 亚洲线精品一区二区三区| 日韩电影在线观看一区二区| 欧美人妖巨大在线| 欧美 日韩 人妻 高清 中文| 亚洲桃花岛网站| 国产日产一区二区| 国产69久久精品成人看| 欧美xxxx性| 狠狠久久综合婷婷不卡| 日韩精品免费| 国产欧美日韩网站| 日本美女一区二区| 亚洲国产精品狼友在线观看| 国产亚洲一本大道中文在线| 午夜爱爱毛片xxxx视频免费看| 婷婷夜色潮精品综合在线| 中文字幕久久网| 精品国产凹凸成av人网站| 色影院视频在线| 97超视频免费观看| 国产精久久久| 欧美久久电影| 影音先锋一区| 日韩va在线观看| 久久久国产综合精品女国产盗摄| 内射一区二区三区| 91久久人澡人人添人人爽欧美 | 亚洲欧美国产视频| 青青在线视频| 国产一区二区在线免费视频| 日韩美女毛片| 大荫蒂性生交片| 美美哒免费高清在线观看视频一区二区 | 中文字幕一二区| 日韩大陆毛片av| caoporn97在线视频| 国产精品免费久久久久影院| 神马香蕉久久| 成人av在线不卡| 狠狠色丁香婷婷综合久久片| 欧美偷拍一区二区三区| 午夜精品久久久久久久久久| www.爱爱.com| 久久手机精品视频| 成人影院在线免费观看| 欧美精品七区| 在线综合亚洲| 中文字幕 亚洲一区| 亚洲永久免费av| 国产ts变态重口人妖hd| 日韩亚洲在线观看| 久久久加勒比| 久久久久无码国产精品一区| 黄色免费成人| 国产成人av免费观看| 亚洲视频一区在线| 一区二区三区精| 日韩精品视频三区| 免费看男女www网站入口在线| 国产69精品久久久久9999apgf| 欧美一区久久| 久久精品一二三四| 亚洲视频在线一区| 国产成人精品毛片| 欧美日韩xxxxx| 欧美一级片网址| 男女啪啪免费观看| 国产成人在线免费| 国产精品9191| 亚洲国产精品999| 啊啊啊久久久| 蜜桃传媒一区二区| 三级成人在线视频| 蜜桃av免费观看| 3d动漫精品啪啪一区二区竹菊| 男人天堂手机在线| 亚洲xxxxx| 极品尤物久久久av免费看| 欧产日产国产精品98| 欧美日韩精品在线视频| 欧美日韩在线精品一区二区三区激情综 | 黄色污污在线观看| 国产不卡免费视频| 日本在线免费观看| 亚洲毛片在线看| 成人涩涩视频| 成人在线观看www| 国产激情视频一区二区在线观看| 国产小视频在线观看免费| 日韩精品久久久久久福利| 欧美与亚洲与日本直播| 中文字幕中文字幕在线中心一区| 国产福利一区二区三区视频| 国产视频91在线| 一区二区欧美日韩视频| 日韩美女在线| 免费国产黄色网址| 欧美国产欧美综合| www久久久com| 日本高清视频精品| 91精品国产成人观看| 五月天丁香社区| 在线精品国精品国产尤物884a| 日本在线观看免费| 国精产品99永久一区一区| 日韩电影在线观看网站| 99久久婷婷国产综合| 精品香蕉一区二区三区| 亚洲欧洲二区| 91精品91久久久中77777老牛| 国产精品国产三级国产aⅴ原创| 精品人妻伦一二三区久久| 日韩美女视频在线观看| 亚洲精品国产首次亮相| 无码h肉动漫在线观看| 欧美一区二区播放| 欧美第一视频| 成人污网站在线观看| 国产欧美一区视频| 丰满少妇被猛烈进入| 91精品久久久久久久久不口人| 中文久久精品| 久久国产露脸精品国产| 中文字幕av一区中文字幕天堂 | 日本少妇裸体做爰|