180行python代码实现区块链+猜单词游戏

180行python代码实现区块链+猜单词游戏


依赖环境: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)

猜你喜欢

转载自blog.csdn.net/the_little_fairy___/article/details/81608210
今日推荐