依赖环境:python3.5+
依赖第三方库:requests,Flask
网络环境:局域网
参考引用:
区块链基础知识(4)-共识机制和挖矿(谁来记账)https://blog.csdn.net/foupwang/article/details/79215980
看完此文再不懂区块链算我输,用Python从零开始创建区块链https://blog.csdn.net/bjweimengshu/article/details/79549858
关于区块链的解读和简单Python实现https://blog.csdn.net/bmwgaara/article/details/79059007
bitcoin官网FAQ https://bitcoin.org/en/faq
确认是否是有效的英文单词,可以在这里下载常用的英文单词 https://www.cnblogs.com/bonelee/p/7771609.html
import requests
import random
from random import choice
import hashlib
import json
from textwrap import dedent
from time import time
from uuid import uuid4
from flask import Flask, jsonify, request
from urllib.parse import urlparse
class Blockchain(object):
def __init__(self):
self.chain = []
self.current_transactions = []
self.nodes = set()
self.wordManager = WordManager()
def register_node(self, address):
parsed_url = urlparse(address)
self.nodes.add(parsed_url.netloc)
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
last_block = block
current_index += 1
return True
def resolve_conflicts(self):#共识算法解决冲突
neighbours = self.nodes
max_length = len(self.chain)
new_chain = None
for node in neighbours:
response = requests.get('http://'+str(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 boardcast_resolve(self):
for node in self.nodes:
if node.find(app_port)>=0:
continue
response = requests.get('http://'+str(node)+'/nodes/resolve')
def new_block(self,head_letter, previous_hash=None):
word=''
if len(self.chain)==0:
word='c_t'
self.current_transactions.append({
'sender_addr': 0,
'recv_addr': node_identifier,
'word': word,
})
else:
word=self.wordManager.generate_word(head_letter)#上一链的开头
self.current_transactions.append({
'sender_addr': self.chain[-1]['transactions'][0]['recv_addr'],
'recv_addr': node_identifier,
'word': word,
})
block = {
'index': len(self.chain) + 1,
'timestamp': time(),
'transactions': self.current_transactions,
'previous_hash': previous_hash or self.hash(self.chain[-1]),
}
proof = 0
while self.valid_proof(self.hash(block), proof) is False:
block['timestamp']=time()
proof += 1
# Reset the current list of transactions
self.chain.append(block)
self.current_transactions = []
return block
@property
def last_block(self):
return self.chain[-1]
@staticmethod
def hash(block):#hash化区块
block_string = json.dumps(block, sort_keys=True).encode()
return hashlib.sha256(block_string).hexdigest()
@staticmethod
def valid_proof(last_proof, proof):
guess = (str(last_proof)+str(proof)).encode('utf-8')
guess_hash = hashlib.sha256(guess).hexdigest()
return guess_hash[:4] == "0000"
class WordManager:
def __init__(self):
word_file=open("wordsEn.txt")
self.word_list=list(word.strip().lower() for word in word_file)
word_file.close()
def is_english_word(self,word):
return word.lower() in self.word_list
def generate_word(self,h):
word=choice([word_sub for word_sub in self.word_list if word_sub.startswith(h)])
word_len=len(word)
mask_idx=random.randint(1,word_len-1)
word=word[:mask_idx]+'_'+word[mask_idx+1:]
return word
app = Flask(__name__)
# 生成uuit
node_identifier = str(uuid4()).replace('-', '')
# 加载
blockchain = Blockchain()
blockchain.new_block('c','0')
app_port=0
@app.route('/mine', methods=['POST'])
def mine():
values = request.get_json()
head_letter = values.get('head_letter')
is_valid =blockchain.wordManager.is_english_word(blockchain.chain[-1]
['transactions'][0]['word'].replace('_',head_letter))
if is_valid == False:
return 'Not a word', 400
block = blockchain.new_block(head_letter)
blockchain.boardcast_resolve()#sync
response = {
'message': "Done",
'index': block['index'],
'transactions': block['transactions'],
'previous_hash': block['previous_hash'],
}
return jsonify(response), 201
@app.route('/chain', methods=['GET'])
def get_full_chain():
response = {
'chain': blockchain.chain,
'length': len(blockchain.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 "Something wrong", 400
for node in nodes:
blockchain.register_node(node)
#print('successful!'+node)
response = {
'message': 'Done',
'total_nodes': list(blockchain.nodes),
}
return jsonify(response), 201
@app.route('/nodes/resolve', methods=['GET'])
def resolve():
replaced = blockchain.resolve_conflicts()
response = {
'message': 'Sync Done',
'chain': blockchain.chain
}
return jsonify(response), 200
import sys
if __name__ == '__main__':
port=sys.argv[1]
app_port=port
app.run(host='127.0.0.1', port=port)