• 使用Python,结合Flask框架,创建一个可以处理交易、挖矿新区块、验证区块链有效性,并能在网络节点间同步的区块链网络。(持续更新)


    目录

    前言

    二、代码注释

    1.添加新交易到区块链

    2.连接新节点

    3、替换区块链为最长链

    总结


    前言

    本篇文章将从一个实践者的角度出发,通过构建一个简单的区块链系统,揭开区块链技术的神秘面纱。我们将使用Python语言,结合Flask框架,创建一个可以处理交易、挖矿新区块、验证区块链有效性,并能在网络节点间同步的区块链网络。。


    一、代码展示

    1. # Module 1 -Create a Cryptocurrency
    2. #To be installed:
    3. #Flask==0.12.2:pip install Flask==0.12.2
    4. #Postman HTrp Client:https://www.getpostman.com
    5. #requests==2.18.4:pip install requests=-2.18.4
    6. #时间戳
    7. import datetime
    8. import hashlib
    9. import json
    10. #Flask可以定义Web应用的路由(URL到Python函数的映射),并处理HTTP请求和响应。jsonify是一个函数,用于将Python对象转换为JSON格式的响应。当你在Flask路由函数中返回一个jsonify对象时,Flask会自动将该对象对应的数据转换为JSON格式,并设置合适的HTTP响应头,以便客户端可以正确解析响应内容。
    11. from flask import Flask, jsonify,request
    12. import requests
    13. from uuid import uuid4
    14. from urllib.parse import urlparse
    15. # 1******Building a Blockchain
    16. class Blockchain:
    17. def __init__(self):
    18. self.transactions=[]
    19. self.chain=[]
    20. self.create_block(proof=1,previous_hash='0')
    21. self.nodes=set()
    22. def create_block(self,proof,previous_hash):
    23. block={'index':len(self.chain)+1,
    24. 'timestamp':str(datetime.datetime.now()),
    25. 'proof':proof,
    26. 'previous_hash':previous_hash,
    27. 'transactions':self.transactions}
    28. self.transactions=[]
    29. self.chain.append(block)
    30. return block
    31. def get_previous_block(self):
    32. return self.chain[-1]
    33. def proof_of_work(self,previous_proof):
    34. new_proof=1
    35. check_proof=False
    36. while check_proof is False:
    37. hash_oparation=hashlib.sha256(str(new_proof**2-previous_proof**2).encode()).hexdigest()
    38. if hash_oparation[:4]=='0000':
    39. check_proof=True
    40. else:
    41. new_proof+=1
    42. return new_proof
    43. def hash(self, block):
    44. encode_block = json.dumps(block, sort_keys=True).encode()
    45. return hashlib.sha256(encode_block).hexdigest()
    46. def is_chain_valid(self,chain):
    47. previous_block=chain[0]
    48. block_index=1
    49. while block_index<len(chain):
    50. block=chain[block_index]
    51. if block['previous_hash'] !=self.hash(previous_block):
    52. return False
    53. previous_proof=previous_block['proof']
    54. proof=block['proof']
    55. hash_oparation=hashlib.sha256(str(proof**2-previous_proof**2).encode()).hexdigest()
    56. if hash_oparation[:4] !='0000':
    57. return False
    58. previous_block=block
    59. block_index+=1
    60. return True
    61. def add_transaction(self,sender,receiver,amount):
    62. self.transactions.append({'sender':sender,
    63. 'receiver':receiver,
    64. 'amount':amount})
    65. previous_block=self.get_previous_block()
    66. return previous_block['index']+1
    67. def add_node(self,address):
    68. parsed_url=urlparse(address)
    69. self.nodes.add(parsed_url.netloc)
    70. def replace_chain(self):
    71. network = self.nodes
    72. longest_chain = None
    73. max_length = len(self.chain)
    74. for node in network:
    75. try:
    76. response = requests.get(f'http://{node}/get_chain')
    77. response.raise_for_status() # 这将抛出异常,如果请求失败
    78. except requests.exceptions.RequestException as e:
    79. print(f"Failed to get the chain from {node}. Exception: {e}")
    80. continue
    81. if response.status_code == 200:
    82. length = response.json()['length']
    83. chain = response.json()['chain']
    84. if length > max_length and self.is_chain_valid(chain):
    85. max_length = length
    86. longest_chain = chain
    87. if longest_chain:
    88. self.chain = longest_chain
    89. return True
    90. return False
    91. #Part 2 -Mining our Blockchain
    92. #Creating a Web App
    93. app = Flask(__name__)
    94. #Creating an address for the node on Port 5000
    95. node_address=str(uuid4()).replace('-', '')
    96. #Creating a Blockchain
    97. blockchain=Blockchain()
    98. #Mining a new block
    99. @app.route('/mine_block',methods=['GET'])
    100. def mine_block():
    101. previous_block=blockchain.get_previous_block()
    102. previous_proof=previous_block['proof']
    103. proof=blockchain.proof_of_work(previous_proof)
    104. previous_hash=blockchain.hash(previous_block)
    105. blockchain.add_transaction(sender=node_address,receiver='Lanzhile',amount=1)
    106. block=blockchain.create_block(proof, previous_hash)
    107. response={'message':'Congratulation,you just mined a block',
    108. 'index':block['index'],
    109. 'timestamp':block['timestamp'],
    110. 'proof':block['proof'],
    111. 'previous_hash':block['previous_hash'],
    112. 'transactions':block['transactions']}
    113. return jsonify(response),200
    114. #Getting the full Blockchain
    115. @app.route('/get_chain',methods=['GET'])
    116. def get_chain():
    117. response={'chain':blockchain.chain,
    118. 'length':len(blockchain.chain)}
    119. return jsonify(response),200
    120. #Checking if the Blockchain is valid
    121. @app.route('/is_valid',methods=['GET'])
    122. def get_valid():
    123. is_valid=blockchain.is_chain_valid(blockchain.chain)
    124. if is_valid:
    125. response={'message':'All good. The Blockchain is valid.'}
    126. else:
    127. response={'message':'Houston,we have a problem.The Blockchain is not valid.'}
    128. return jsonify(response),200
    129. #Addling a new transaction to the Blockchain
    130. @app.route('/add_transaction',methods=['POST'])
    131. def add_transaction():
    132. json =request.get_json()
    133. transaction_keys=['sender','receiver','amount']
    134. if not all(key in json for key in transaction_keys):
    135. return 'Some elements of the transaction are missing',400
    136. index=blockchain.add_transaction(json['sender'], json['receiver'],json['amount'])
    137. response={'message':f'This transaction will be added to Block {index}'}
    138. return jsonify(response),201
    139. #Connecting new nodes
    140. @@app.route('/connect_node', methods=['POST'])
    141. def connect_node():
    142. json = request.get_json()
    143. nodes = json.get('nodes')
    144. if nodes is None:
    145. return "No nodes provided", 400
    146. for node in nodes:
    147. blockchain.add_node(node)
    148. # 将响应构建移到循环外,并在所有节点添加后才返回
    149. response = {
    150. 'message': 'All the nodes are now connected. The Lancoin Blockchain now contains the following nodes:',
    151. 'total_nodes': list(blockchain.nodes)
    152. }
    153. return jsonify(response), 201
    154. #Replacing the chain by the longest chain if needed
    155. @app.route('/replace_chain', methods=['GET'])
    156. def replace_chain():
    157. is_chain_replaced = blockchain.replace_chain()
    158. if is_chain_replaced:
    159. response = {
    160. 'message': 'The nodes had different chains so the chain was replaced by the longest one.',
    161. 'new_chain': blockchain.chain
    162. }
    163. else:
    164. response = {
    165. 'message': 'All good. the chain is the largest one.',
    166. 'actual_chain': blockchain.chain
    167. }
    168. return jsonify(response), 200
    169. app.run(host='0.0.0.0',port=5000)

    二、代码注释

    注:下面对/add_transaction、/connect_node、/replace_chain路由和对应的视图函数进行讲解,其他函数的详解在我的另外两篇我的文章里“创建一个简单的区块链,并使用 Flask 框架提供一个简单的 Web 接口来与区块链交互。-CSDN博客”“使用了Python语言和Flask框架。创建一个区块链网络,允许用户通过HTTP请求进行交互,如包括创建区块链、挖矿、验证区块链等功能。-CSDN博客

    1.添加新交易到区块链

    1. @app.route('/add_transaction', methods=['POST'])
    2. def add_transaction():
    3. # 获取请求的JSON数据
    4. json = request.get_json()
    5. # 定义交易必须包含的键
    6. transaction_keys = ['sender', 'receiver', 'amount']
    7. # 检查JSON数据中是否包含所有必要的交易键
    8. if not all(key in json for key in transaction_keys):
    9. # 如果缺少任何一个键,返回错误信息和400状态码
    10. return 'Some elements of the transaction are missing', 400
    11. # 添加交易到区块链,并获取返回的区块索引
    12. index = blockchain.add_transaction(json['sender'], json['receiver'], json['amount'])
    13. # 构建响应消息,告知交易将被添加到的区块索引
    14. response = {'message': f'This transaction will be added to Block {index}'}
    15. # 返回JSON格式的响应和201状态码,表示交易已成功创建
    16. return jsonify(response), 201

    2.连接新节点

    1. @app.route('/connect_node', methods=['POST'])
    2. def connect_node():
    3. # 获取请求的JSON数据
    4. json = request.get_json()
    5. # 尝试从JSON数据中获取节点列表
    6. nodes = json.get('nodes')
    7. # 如果节点列表不存在,返回错误信息和400状态码
    8. if nodes is None:
    9. return "No nodes provided", 400
    10. # 遍历节点列表,并将每个节点添加到区块链网络中
    11. for node in nodes:
    12. blockchain.add_node(node)
    13. # 构建响应消息,列出所有已连接的节点
    14. response = {
    15. 'message': 'All the nodes are now connected. The Lancoin Blockchain now contains the following nodes:',
    16. 'total_nodes': list(blockchain.nodes)
    17. }
    18. # 返回JSON格式的响应和201状态码,表示节点已成功连接
    19. return jsonify(response), 201

    3、替换区块链为最长链

    1. @app.route('/replace_chain', methods=['GET'])
    2. def replace_chain():
    3. # 调用 Blockchain 类的 replace_chain 方法
    4. # 这个方法会遍历所有节点,并决定是否需要用更长的链替换当前链
    5. is_chain_replaced = blockchain.replace_chain()
    6. # 如果链被替换了
    7. if is_chain_replaced:
    8. # 构建一个包含替换信息的响应字典
    9. response = {
    10. 'message': 'The nodes had different chains so the chain was replaced by the longest one.',
    11. # 提供替换后区块链的完整信息
    12. 'new_chain': blockchain.chain
    13. }
    14. else:
    15. # 如果当前区块链已经是最长的,没有被替换
    16. # 构建一个包含当前区块链信息的响应字典
    17. response = {
    18. 'message': 'All good. the chain is the largest one.',
    19. # 提供当前区块链的完整信息
    20. 'actual_chain': blockchain.chain
    21. }
    22. # 使用 jsonify 将 Python 字典转换成 JSON 格式的响应体
    23. # 返回 200 OK HTTP 状态码
    24. return jsonify(response), 200

    总结

    这纸片文章主要介绍三个路由:/add_transaction/connect_node/replace_chain,分别用于添加交易、连接新节点和替换链。在处理请求时,代码首先获取请求中的JSON数据,然后根据不同的路由执行相应的操作,最后返回响应消息和状态码。

  • 相关阅读:
    cmake-format使用教程
    编译原理实验-词法分析
    HTTP面试题总结
    web网页设计——体育气步枪射击主题(5页面)带图片轮播特效(HTML+CSS) ~学生网页设计作业源码
    为共创行业解决方案寻找黄金合作伙伴,百数低代码服务商模式在等您
    酷开科技全球化智能大屏OS——Coolita ,将大屏数字化服务进行到底
    多线程之线程池
    Visual Studio Code+drawio扩展插件的安装和使用,免费的软件构图神器
    MVVM的前世今生与在苹果开发中的应用
    汇编语言实现for循环?怎么实现的,形象的比喻
  • 原文地址:https://blog.csdn.net/weixin_60680666/article/details/138198225