区块链原理的实现(Python)

区块结构

一个块应该包含的信息:
块的索引
时间戳
交易信息  

   一个数组,包含交易的发送者、接收者、交易的金额
工作量证明
上一个区块的哈希值

 

 

实现区块类结构

# {
#     "index":0,
#     "timestamp":"",
#     "transactions":[
#         {
#         "sender":"",
#         "recipient":"",
#         "amount":5,
#         }
#     ],
#     "proof":"",
#     "previous_hash":""
# }



class Blockchain:

    def __init__(self):
        self.chain = []     #数组中的元素都是一个个区块
        self.current_transations = []  #保存当前的交易信息

    def new_block(self):    #新添加一个块
        pass

    def new_transaction(self):    #新添加交易
        pass

    @staticmethod
    def hash(block):  #计算区块的哈希值
        pass

    @property
    def last_block(self): #获取区块中的最后一个块
        pass

 

添加交易

# {
#     "index":0,
#     "timestamp":"",
#     "transactions":[
#         {
#         "sender":"",
#         "recipient":"",
#         "amount":5,
#         }
#     ],
#     "proof":"",
#     "previous_hash":""
# }



class Blockchain:

    def __init__(self):
        self.chain = []     #数组中的元素都是一个个区块
        self.current_transations = []  #保存当前的交易信息

    def new_block(self):    #新添加一个块
        pass

    def new_transaction(self,sender,recipient,amount) -> int:    #新添加交易
        self.current_transations.append(
            {
                'sender':sender,
                'recipient':recipient,
                'amount':amount
            }
        )

        return self.last_block['index'] + 1

    @staticmethod
    def hash(block):  #计算区块的哈希值
        pass

    @property
    def last_block(self): #获取区块中的最后一个块
        pass

 

实现创建区块

# {
#     "index":0,
#     "timestamp":"",
#     "transactions":[
#         {
#         "sender":"",
#         "recipient":"",
#         "amount":5,
#         }
#     ],
#     "proof":"",
#     "previous_hash":""
# }
import hashlib
import json
from time import time
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse
from uuid import uuid4

import requests
from flask import Flask, jsonify, request


class Blockchain:

    def __init__(self):
        self.chain = []     #数组中的元素都是一个个区块
        self.current_transations = []  #保存当前的交易信息
        #创世纪的区块
        self.new_block(proof=100, previous_hash=1)

    def new_block(self,proof,previous_hash):    #新添加一个块
        block = {
            'index':len(self.chain) + 1,
            'timestamp':time(),
            'transcations': self.current_transationsm,
            'proof':proof,
            'previous_hash':previous_hash or self.hash(self.self_block)
        }

        #交易已经打包成区块了,把当前的交易清空
        self.current_transations = []
        self.chain.append(block)

        return block


    def new_transaction(self,sender,recipient,amount) -> int:    #新添加交易
        self.current_transations.append(
            {
                'sender':sender,
                'recipient':recipient,
                'amount':amount
            }
        )

        return self.last_block['index'] + 1

    @staticmethod
    def hash(block):  #计算区块的哈希值
        #把block转换成字节数组
        block_string = json.dumps(block,sorted_keys=True)
        hashlib.sha256(block_string).hexdigest()


    @property
    def last_block(self): #获取区块中的最后一个块
        return self.chain(-1)

 

实现工作量证明

是否满足以4个0开头

import hashlib
import json
from time import time
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse
from uuid import uuid4

import requests
from flask import Flask, jsonify, request


class Blockchain:

    def __init__(self):
        self.chain = []     #数组中的元素都是一个个区块
        self.current_transations = []  #保存当前的交易信息
        #创世纪的区块
        self.new_block(proof=100, previous_hash=1)

    def new_block(self,proof,previous_hash):    #新添加一个块
        block = {
            'index':len(self.chain) + 1,
            'timestamp':time(),
            'transcations': self.current_transations,
            'proof':proof,
            'previous_hash':previous_hash or self.hash(self.self_block)
        }

        #交易已经打包成区块了,把当前的交易清空
        self.current_transations = []
        self.chain.append(block)

        return block


    def new_transaction(self,sender,recipient,amount) -> int:    #新添加交易
        self.current_transations.append(
            {
                'sender':sender,
                'recipient':recipient,
                'amount':amount
            }
        )

        return self.last_block['index'] + 1

    @staticmethod
    def hash(block):  #计算区块的哈希值
        #把block转换成字节数组
        block_string = json.dumps(block,sorted_keys=True)
        hashlib.sha256(block_string).hexdigest()


    @property
    def last_block(self): #获取区块中的最后一个块
        return self.chain(-1)


    def proof_of_work(self, last_proof:int) -> int:
        proof = 0
        while self.valid_proof(last_proof, proof) is False:
            proof += 1

        print(proof)
        return proof


    def valid_proof(self, last_proof: int, proof:int) -> bool:
        guess = f'{last_proof}{proof}'.encode()
        guess_hash = hashlib.sha256(guess).hexdigest()

        print(guess_hash)
        if guess_hash[0:4] == '0000':
            return True
        else:
            return False


if __name__ == '__main__':
    testPow = Blockchain()
    testPow.proof_of_work(100)

 

添加节点通信功能

通过Flask

import hashlib
import json
from time import time
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse
from uuid import uuid4

import requests
from flask import Flask, jsonify, request


class Blockchain:

    def __init__(self):
        self.chain = []     #数组中的元素都是一个个区块
        self.current_transations = []  #保存当前的交易信息
        #创世纪的区块
        self.new_block(proof=100, previous_hash=1)

    def new_block(self,proof,previous_hash):    #新添加一个块
        block = {
            'index':len(self.chain) + 1,
            'timestamp':time(),
            'transcations': self.current_transations,
            'proof':proof,
            'previous_hash':previous_hash or self.hash(self.self_block)
        }

        #交易已经打包成区块了,把当前的交易清空
        self.current_transations = []
        self.chain.append(block)

        return block


    def new_transaction(self,sender,recipient,amount) -> int:    #新添加交易
        self.current_transations.append(
            {
                'sender':sender,
                'recipient':recipient,
                'amount':amount
            }
        )

        return self.last_block['index'] + 1

    @staticmethod
    def hash(block):  #计算区块的哈希值
        #把block转换成字节数组
        block_string = json.dumps(block,sorted_keys=True)
        hashlib.sha256(block_string).hexdigest()


    @property
    def last_block(self): #获取区块中的最后一个块
        return self.chain(-1)


    def proof_of_work(self, last_proof:int) -> int:
        proof = 0
        while self.valid_proof(last_proof, proof) is False:
            proof += 1

        print(proof)
        return proof


    def valid_proof(self, last_proof: int, proof:int) -> bool:
        guess = f'{last_proof}{proof}'.encode()
        guess_hash = hashlib.sha256(guess).hexdigest()

        print(guess_hash)
        if guess_hash[0:4] == '0000':
            return True
        else:
            return False



app = Flask(__name__)

@app.route('/index',methods=['GET'])
def index():
    return 'Hello BlockChain'

@app.route('/transactions/new',methods=['POST'])
def new_transction():
    return "We'll add a new transctions"


@app.route('/mine',methods=['GET'])
def mine():
    return "We'll mine a new block"

@app.route('/chain', methods=['GET'])
def full_chain():
    return 'retutn full chain'


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

 

交易接口实现

就是实现以下上面定义的几个flask函数

import hashlib
import json
from time import time
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse
from uuid import uuid4

import requests
from flask import Flask, jsonify, request


class Blockchain:

    def __init__(self):
        self.chain = []     #数组中的元素都是一个个区块
        self.current_transations = []  #保存当前的交易信息
        #创世纪的区块
        self.new_block(proof=100, previous_hash=1)

    def new_block(self,proof,previous_hash):    #新添加一个块
        block = {
            'index':len(self.chain) + 1,
            'timestamp':time(),
            'transcations': self.current_transations,
            'proof':proof,
            'previous_hash':previous_hash or self.hash(self.self_block)
        }

        #交易已经打包成区块了,把当前的交易清空
        self.current_transations = []
        self.chain.append(block)

        return block


    def new_transaction(self,sender,recipient,amount) -> int:    #新添加交易
        self.current_transations.append(
            {
                'sender':sender,
                'recipient':recipient,
                'amount':amount
            }
        )

        return self.last_block['index'] + 1

    @staticmethod
    def hash(block):  #计算区块的哈希值
        #把block转换成字节数组
        block_string = json.dumps(block,sorted_keys=True)
        hashlib.sha256(block_string).hexdigest()


    @property
    def last_block(self): #获取区块中的最后一个块
        return self.chain[-1]


    def proof_of_work(self, last_proof:int) -> int:
        proof = 0
        while self.valid_proof(last_proof, proof) is False:
            proof += 1

        print(proof)
        return proof


    def valid_proof(self, last_proof: int, proof:int) -> bool:
        guess = f'{last_proof}{proof}'.encode()
        guess_hash = hashlib.sha256(guess).hexdigest()

        print(guess_hash)
        if guess_hash[0:4] == '0000':
            return True
        else:
            return False



app = Flask(__name__)
blockchain = Blockchain()

@app.route('/index',methods=['GET'])
def index():
    return 'Hello BlockChain'

@app.route('/transactions/new',methods=['POST'])
def new_transction():
    values = request.get_json()
    required = ['sender', 'recipient','amount']

    if values is None:
        return 'Missing values', 400
    if not all (k in values for k in required):
        return "Missing values", 400
    index = blockchain.new_transaction(values['sender'],
                                       values['recipient'],
                                       values['amount'])
    response = {"message":f'Transcation will be added to Block {index}'}

    return jsonify(response), 201


@app.route('/mine',methods=['GET'])
def mine():
    return "We'll mine a new block"

@app.route('/chain', methods=['GET'])
def full_chain():
    response = {
        'chain':blockchain.chain,
        'length': len(blockchain.chain)

    }
    return jsonify(response),200


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

 

第一块是创始块,所以是第二块

 

挖矿接口实现

import hashlib
import json
from time import time
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse
from uuid import uuid4

import requests
from flask import Flask, jsonify, request


class Blockchain:

    def __init__(self):
        self.chain = []     #数组中的元素都是一个个区块
        self.current_transations = []  #保存当前的交易信息
        #创世纪的区块
        self.new_block(proof=100, previous_hash=1)

    def new_block(self,proof,previous_hash):    #新添加一个块
        block = {
            'index':len(self.chain) + 1,
            'timestamp':time(),
            'transactions': self.current_transations,
            'proof':proof,
            'previous_hash':previous_hash or self.hash(self.chain[-1])
        }

        #交易已经打包成区块了,把当前的交易清空
        self.current_transations = []
        self.chain.append(block)

        return block


    def new_transaction(self,sender,recipient,amount) -> int:    #新添加交易
        self.current_transations.append(
            {
                'sender':sender,
                'recipient':recipient,
                'amount':amount
            }
        )

        return self.last_block['index'] + 1

    @staticmethod
    def hash(block):  #计算区块的哈希值
        #把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:int) -> int:
        proof = 0
        while self.valid_proof(last_proof, proof) is False:
            proof += 1

        # print(proof)
        return proof


    def valid_proof(self, last_proof: int, proof:int) -> bool:
        guess = f'{last_proof}{proof}'.encode()
        guess_hash = hashlib.sha256(guess).hexdigest()

        # print(guess_hash)
        if guess_hash[0:4] == '0000':
            return True
        else:
            return False



app = Flask(__name__)
blockchain = Blockchain()

node_identifier = str(uuid4()).replace('-', '')

@app.route('/index',methods=['GET'])
def index():
    return 'Hello BlockChain'

@app.route('/transactions/new',methods=['POST'])
def new_transction():
    values = request.get_json()
    required = ['sender', 'recipient','amount']

    if values is None:
        return 'Missing values', 400
    if not all (k in values for k in required):
        return "Missing values", 400
    index = blockchain.new_transaction(values['sender'],
                                       values['recipient'],
                                       values['amount'])
    response = {"message":f'Transcation will be added to Block {index}'}

    return jsonify(response), 201


@app.route('/mine',methods=['GET'])
def mine():
    #先算块的工作量证明,然后给自己添加奖励交易
    last_block = blockchain.last_block
    last_proof = last_block['proof']
    proof = blockchain.proof_of_work(last_proof)

    blockchain.new_transaction(sender="0",
                               recipient=node_identifier,
                               amount=1)
    
    block = blockchain.new_block(proof,None)
    
    response = {
        "message": "New Block Forged",
        "index": block['index'],
        "transactions": block['transactions'],
        "proof": block['proof'],
        "previous_hash": block['previous_hash']
    }

    return jsonify(response),200
    
@app.route('/chain', methods=['GET'])
def full_chain():
    response = {
        'chain':blockchain.chain,
        'length': len(blockchain.chain)

    }
    return jsonify(response),200


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

成功挖了一个

返回所有区块信息

 

这样,一个单节点的区块链就实现了

 

实现注册节点

import hashlib
import json
from time import time
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse
from uuid import uuid4

import requests
from flask import Flask, jsonify, request


class Blockchain:

    def __init__(self):
        self.chain = []     #数组中的元素都是一个个区块
        self.current_transations = []  #保存当前的交易信息
        self.nodes = set()  #保存节点信息
        #创世纪的区块
        self.new_block(proof=100, previous_hash=1)

    def register_node(self, address:str):
        #http://127.0.0.1:5001
        parsed_url = urlparse(address)
        self.nodes.add(parsed_url.netloc)



    def new_block(self,proof,previous_hash):    #新添加一个块
        block = {
            'index':len(self.chain) + 1,
            'timestamp':time(),
            'transactions': self.current_transations,
            'proof':proof,
            'previous_hash':previous_hash or self.hash(self.chain[-1])
        }

        #交易已经打包成区块了,把当前的交易清空
        self.current_transations = []
        self.chain.append(block)

        return block


    def new_transaction(self,sender,recipient,amount) -> int:    #新添加交易
        self.current_transations.append(
            {
                'sender':sender,
                'recipient':recipient,
                'amount':amount
            }
        )

        return self.last_block['index'] + 1

    @staticmethod
    def hash(block):  #计算区块的哈希值
        #把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:int) -> int:
        proof = 0
        while self.valid_proof(last_proof, proof) is False:
            proof += 1

        # print(proof)
        return proof


    def valid_proof(self, last_proof: int, proof:int) -> bool:
        guess = f'{last_proof}{proof}'.encode()
        guess_hash = hashlib.sha256(guess).hexdigest()

        # print(guess_hash)
        if guess_hash[0:4] == '0000':
            return True
        else:
            return False



app = Flask(__name__)
blockchain = Blockchain()

node_identifier = str(uuid4()).replace('-', '')

@app.route('/index',methods=['GET'])
def index():
    return 'Hello BlockChain'

@app.route('/transactions/new',methods=['POST'])
def new_transction():
    values = request.get_json()
    required = ['sender', 'recipient','amount']

    if values is None:
        return 'Missing values', 400
    if not all (k in values for k in required):
        return "Missing values", 400
    index = blockchain.new_transaction(values['sender'],
                                       values['recipient'],
                                       values['amount'])
    response = {"message":f'Transcation will be added to Block {index}'}

    return jsonify(response), 201


@app.route('/mine',methods=['GET'])
def mine():
    #先算块的工作量证明,然后给自己添加奖励交易
    last_block = blockchain.last_block
    last_proof = last_block['proof']
    proof = blockchain.proof_of_work(last_proof)

    blockchain.new_transaction(sender="0",
                               recipient=node_identifier,
                               amount=1)
    
    block = blockchain.new_block(proof,None)
    
    response = {
        "message": "New Block Forged",
        "index": block['index'],
        "transactions": block['transactions'],
        "proof": block['proof'],
        "previous_hash": block['previous_hash']
    }

    return jsonify(response),200
    
@app.route('/chain', methods=['GET'])
def full_chain():
    response = {
        'chain':blockchain.chain,
        'length': len(blockchain.chain)

    }
    return jsonify(response),200


#{"nodes":["http://127.0.0.2:5000"]}
@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

    for node in nodes:
        blockchain.register_node(node)

    response = {
        "message": "New nodes have been added",
        "total_nodes": list(blockchain.nodes)
    }
    return jsonify(response),201


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

 

实现共识机制

import hashlib
import json
from time import time
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse
from uuid import uuid4

import requests
from flask import Flask, jsonify, request
from argparse import ArgumentParser


class Blockchain:

    def __init__(self):
        self.chain = []     #数组中的元素都是一个个区块
        self.current_transations = []  #保存当前的交易信息
        self.nodes = set()  #保存节点信息
        #创世纪的区块
        self.new_block(proof=100, previous_hash=1)

    def register_node(self, address:str):
        #http://127.0.0.1:5001
        parsed_url = urlparse(address)
        self.nodes.add(parsed_url.netloc)

    def valid_chain(self, chain) -> bool:
        #判断依据就是看它的每个哈希值是否是上一个块的哈希
        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


    def resolve_conflicts(self) -> bool:

        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):    #新添加一个块
        block = {
            'index':len(self.chain) + 1,
            'timestamp':time(),
            'transactions': self.current_transations,
            'proof':proof,
            'previous_hash':previous_hash or self.hash(self.chain[-1])
        }

        #交易已经打包成区块了,把当前的交易清空
        self.current_transations = []
        self.chain.append(block)

        return block


    def new_transaction(self,sender,recipient,amount) -> int:    #新添加交易
        self.current_transations.append(
            {
                'sender':sender,
                'recipient':recipient,
                'amount':amount
            }
        )

        return self.last_block['index'] + 1

    @staticmethod
    def hash(block):  #计算区块的哈希值
        #把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:int) -> int:
        proof = 0
        while self.valid_proof(last_proof, proof) is False:
            proof += 1

        # print(proof)
        return proof


    def valid_proof(self, last_proof: int, proof:int) -> bool:
        guess = f'{last_proof}{proof}'.encode()
        guess_hash = hashlib.sha256(guess).hexdigest()

        # print(guess_hash)
        if guess_hash[0:4] == '0000':
            return True
        else:
            return False



app = Flask(__name__)
blockchain = Blockchain()

node_identifier = str(uuid4()).replace('-', '')

@app.route('/index',methods=['GET'])
def index():
    return 'Hello BlockChain'

@app.route('/transactions/new',methods=['POST'])
def new_transction():
    values = request.get_json()
    required = ['sender', 'recipient','amount']

    if values is None:
        return 'Missing values', 400
    if not all (k in values for k in required):
        return "Missing values", 400
    index = blockchain.new_transaction(values['sender'],
                                       values['recipient'],
                                       values['amount'])
    response = {"message":f'Transcation will be added to Block {index}'}

    return jsonify(response), 201


@app.route('/mine',methods=['GET'])
def mine():
    #先算块的工作量证明,然后给自己添加奖励交易
    last_block = blockchain.last_block
    last_proof = last_block['proof']
    proof = blockchain.proof_of_work(last_proof)

    blockchain.new_transaction(sender="0",
                               recipient=node_identifier,
                               amount=1)
    
    block = blockchain.new_block(proof,None)
    
    response = {
        "message": "New Block Forged",
        "index": block['index'],
        "transactions": block['transactions'],
        "proof": block['proof'],
        "previous_hash": block['previous_hash']
    }

    return jsonify(response),200
    
@app.route('/chain', methods=['GET'])
def full_chain():
    response = {
        'chain':blockchain.chain,
        'length': len(blockchain.chain)

    }
    return jsonify(response),200


#{"nodes":["http://127.0.0.2:5000"]}
@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

    for node in nodes:
        blockchain.register_node(node)

    response = {
        "message": "New nodes have been added",
        "total_nodes": list(blockchain.nodes)
    }
    return jsonify(response),201

@app.route('/nodes/resolve',methods=['GET'])
def consensus():
    replaced = blockchain.resolve_conflicts()

    if replaced:
        response = {
            "message": 'Our chain was replaced',
            'new_chain': blockchain.chain
        }
    else:
        response={
            'message': 'Our chain is authoritative',
            'chain': blockchain.chain
        }

    return jsonify(response),200


if __name__ == '__main__':
    parser = ArgumentParser()
    parser.add_argument('-p','--port',default=5051, type=int,help='port to listen to')
    args = parser.parse_args()
    port = args.port
    
    app.run(host='0.0.0.0', port=port)

 

分别在5000和5001起两个终端

先看一下5000的链条

长度是1

然后我们给5000节点添加一个交易

此时链条长度还是1,因为我们没有挖矿

请求挖矿

此时看一下链条长度

长度是2

 

此时看一下5001节点的链条长度

长度是1

 

这个时候,就发生了节点5000和节点5001的长度是不一样的

按照共识机制,应该是采用5000节点的长度

然后现在我们把节点5000节点注册到5001上去,将5001节点注册到5000上

显示节点已添加

显示节点已添加

此时查看5001节点解决冲突的方法

链条已经被替换成长的

此时查看5001的链条长度

 

至此,一个区块链的雏形就实现了

总的

blockchain.py

import hashlib
import json
from time import time
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse
from uuid import uuid4

import requests
from flask import Flask, jsonify, request
from argparse import ArgumentParser


class Blockchain:

    def __init__(self):
        self.chain = []     #数组中的元素都是一个个区块
        self.current_transations = []  #保存当前的交易信息
        self.nodes = set()  #保存节点信息
        #创世纪的区块
        self.new_block(proof=100, previous_hash=1)

    def register_node(self, address:str):
        #http://127.0.0.1:5001
        parsed_url = urlparse(address)
        self.nodes.add(parsed_url.netloc)

    def valid_chain(self, chain) -> bool:
        #判断依据就是看它的每个哈希值是否是上一个块的哈希
        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


    def resolve_conflicts(self) -> bool:

        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):    #新添加一个块
        block = {
            'index':len(self.chain) + 1,
            'timestamp':time(),
            'transactions': self.current_transations,
            'proof':proof,
            'previous_hash':previous_hash or self.hash(self.chain[-1])
        }

        #交易已经打包成区块了,把当前的交易清空
        self.current_transations = []
        self.chain.append(block)

        return block


    def new_transaction(self,sender,recipient,amount) -> int:    #新添加交易
        self.current_transations.append(
            {
                'sender':sender,
                'recipient':recipient,
                'amount':amount
            }
        )

        return self.last_block['index'] + 1

    @staticmethod
    def hash(block):  #计算区块的哈希值
        #把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:int) -> int:
        proof = 0
        while self.valid_proof(last_proof, proof) is False:
            proof += 1

        # print(proof)
        return proof


    def valid_proof(self, last_proof: int, proof:int) -> bool:
        guess = f'{last_proof}{proof}'.encode()
        guess_hash = hashlib.sha256(guess).hexdigest()

        # print(guess_hash)
        if guess_hash[0:4] == '0000':
            return True
        else:
            return False



app = Flask(__name__)
blockchain = Blockchain()

node_identifier = str(uuid4()).replace('-', '')

@app.route('/index',methods=['GET'])
def index():
    return 'Hello BlockChain'

@app.route('/transactions/new',methods=['POST'])
def new_transction():
    values = request.get_json()
    required = ['sender', 'recipient','amount']

    if values is None:
        return 'Missing values', 400
    if not all (k in values for k in required):
        return "Missing values", 400
    index = blockchain.new_transaction(values['sender'],
                                       values['recipient'],
                                       values['amount'])
    response = {"message":f'Transcation will be added to Block {index}'}

    return jsonify(response), 201


@app.route('/mine',methods=['GET'])
def mine():
    #先算块的工作量证明,然后给自己添加奖励交易
    last_block = blockchain.last_block
    last_proof = last_block['proof']
    proof = blockchain.proof_of_work(last_proof)

    blockchain.new_transaction(sender="0",
                               recipient=node_identifier,
                               amount=1)
    
    block = blockchain.new_block(proof,None)
    
    response = {
        "message": "New Block Forged",
        "index": block['index'],
        "transactions": block['transactions'],
        "proof": block['proof'],
        "previous_hash": block['previous_hash']
    }

    return jsonify(response),200
    
@app.route('/chain', methods=['GET'])
def full_chain():
    response = {
        'chain':blockchain.chain,
        'length': len(blockchain.chain)

    }
    return jsonify(response),200


#{"nodes":["http://127.0.0.2:5000"]}
@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

    for node in nodes:
        blockchain.register_node(node)

    response = {
        "message": "New nodes have been added",
        "total_nodes": list(blockchain.nodes)
    }
    return jsonify(response),201

@app.route('/nodes/resolve',methods=['GET'])
def consensus():
    replaced = blockchain.resolve_conflicts()

    if replaced:
        response = {
            "message": 'Our chain was replaced',
            'new_chain': blockchain.chain
        }
    else:
        response={
            'message': 'Our chain is authoritative',
            'chain': blockchain.chain
        }

    return jsonify(response),200


if __name__ == '__main__':
    parser = ArgumentParser()
    parser.add_argument('-p','--port',default=5000, type=int,help='port to listen to')
    args = parser.parse_args()
    port = args.port
    
    app.run(host='0.0.0.0', port=port)

 

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值