1.设置好区块链的对应方法
import hashlib
import json
from time import time
from urllib.parse import urlparse
import requests
class Blokchain:
def __init__(self):
self.chain=[]
self.current_trascations=[]
self.new_block(proof=1,previous_hash=1)
self.nodes=set()
def register_node(self,address:str):
parsed_url=urlparse(address)
self.nodes.add(parsed_url.netloc)
def resolve_conflics(self):
neighbours=self.nodes
max_length=len(self.chain)
new_chain=None
for node in neighbours:
response=requests.get(f'http://{node}/chain')
if response.status_code==200:
length=response.json()['length']
chain=response.json()['chain']
if length>max_length and self.valid_chain(chain):
max_length=length
new_chain=chain
if new_chain:
self.chain=new_chain
return True
return False
def new_block(self,proof,previous_hash=None):
block={
'index':len(self.chain)+1,
'timestamp':time(),
'trascations':self.current_trascations,
'proof':proof,
'previous_hash':previous_hash or self.hash(self.last_block)
}
self.current_trascations=[]
self.chain.append(block)
return block
def new_trascations(self,sender,recipient,amout):
'''
:param sender: 交易的发送者
:param recipient: 交易的接收者
:param amout: 交易的金额
:return: 整型,返回创建新区块链的索引。
'''
self.current_trascations.append({
'sender':sender,
'recipient':recipient,
'amout':amout
})
return self.last_block['index']+1
@staticmethod
def hash(block):
block_string=json.dumps(block,sort_keys=True).encode()
return hashlib.sha256(block_string).hexdigest()
@property
def last_block(self):
return self.chain[-1]
def proof_of_work(self,last_proof):
proof=0
while self.valid_proof(last_proof,proof) is False:
proof+=1
print(proof)
return proof
def valid_proof(self,last_proof,proof):
guess=f'{last_proof}{proof}'.encode()
guess_hash=hashlib.sha256(guess).hexdigest()
print(guess_hash)
return guess_hash[0:4]=='0000'
def valid_chain(self, chain):
last_block=chain[0]
current_index=1
while current_index<len(chain):
block=chain[current_index]
if block['previous_hash']!=self.hash(last_block):
return False
if not self.valid_proof(last_block['proof'],block['proof']):
return False
last_block=block
current_index+=1
return True
if __name__=="__main__":
testPow=Blokchain()
testPow.proof_of_work(100)
2通过flask 实现网络节点的调用
'''
设置网络模拟,区块链中各个节点的运行原理
'''
from uuid import uuid4
from blockchain import Blokchain
import flask
import requests
from flask import Flask, jsonify, request
block_chain=Blokchain()
app=Flask(__name__)
@app.route('/transction/new',methods=['POST'])
def new_transction():
values=request.get_json()
required=['sender','recipient','amout']
if values==None:
return 'Miss values !', 400
if not all(k in values for k in required):
return 'Miss values !',400
index=block_chain.new_trascations(values['sender'],values['recipient'],values['amout'])
response={'message':f'Transction will be added to Block {index}'}
return jsonify(response),201
node_identifier=str(uuid4().replace('-',''))
@app.route('/mine',methods=['GET'])
def mine():
last_block=block_chain.last_block
last_proof=last_block['proof']
proof=block_chain.proof_of_work(last_proof)
block_chain.new_trascations(sender='0',
recipient=node_identifier,
amout=1)
block=block_chain.new_block(proof,None)
response={
"message":'Now block forgod',
'index':block['index'],
'transactions':block['transactions'],
'proof':block['proof'],
'previous_hash':block['previous_hash']
}
return jsonify(response),200
@app.route('/chain',methods=['GET'])
def chain():
response={
'chain':block_chain.chain,
'length':len(block_chain.chain)
}
return jsonify(response),200
@app.route('nodes/register',methods=['POST'])
def register_nodes():
values=request.get_json()
nodes=values.get('nodes')
if nodes is None:
return "Error:please supply a valid list of nodes",400
response={
"message":"New nodes have been added",
"total_nodes":list(block_chain.nodes)
}
return jsonify(response),201
@app.route('/nodes/resolve',methods=['GET'])
def consensus():
replace=block_chain.resolve_conflics()
if replace:
response={
'message':"our chain was replaced",
'chain':block_chain.chain
}
else:
response = {
'message': "our chain was authoritative",
'chain': block_chain.chain
}
return jsonify(response),200
if __name__=='__main__':
app.run(host='0.0.0.0', port=6000)