Python 创建区块链

2019-03-30  本文已影响0人  sunshaoping

前言:近期在看关于区块链的相关资料,看到这个使用python创建区块链的,就大概总结下。区块链是由区块的记录构成的不可变、有序的链结构,记录可以是交易、文件或任何你想要的数据,重要的是它们是通过哈希值(hashes)链接起来的。

一、创建Blockchain

1. 首先创建一个Blockchain类,在构造函数中创建两个列表,一个用来存储交易,一个用来存储区块链

Blockchain类

# Blockchain类用来管理链条,它能存储交易,加入新块
class Blockchain(object):
    def __init__(self):
        self.chain = []
        self.current_transactions = []
        
    def new_block(self):
        # 区块
        pass
    
    def new_transaction(self):
        # 交易
        pass
    
    @staticmethod
    def hash(block):
        # 区块链
        pass

    @property
    def last_block(self):
        # 返回链中最后一个区块
        pass
2. 块结构
# 每个区块包含属性:索引(index),Unix时间戳(timestamp),交易列表(transactions),工作量证明(稍后解释)以及前一个区块的Hash值
block = {
    'index': 1,
    'timestamp': 1506057125.900785,
    'transactions': [
        {
            'sender': "8527147fe1f5426f9dd545de4b27ee00",
            'recipient': "a77f5cdfa2934df3954a5c7c7da5df1f",
            'amount': 5,
        }
    ],
    'proof': 324984774000,
    'previous_hash': "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
}
3.加入交易
class Blockchain(object):
    ...
    def new_transaction(self, sender, recipient, amount):
        # 生成新交易信息,信息将加入到下一个待挖的区块中
        self.current_transactions.append({
            'sender': sender,
            'recipient': recipient,
            'amount': amount,
        })

        return self.last_block['index'] + 1
4. 创建新块
import hashlib
import json
from time import time


class Blockchain(object):
    def __init__(self):
        self.current_transactions = []
        self.chain = []
        self.new_block(previous_hash=1, proof=100)

    def new_block(self, proof, previous_hash=None):
        # 生成新块
        block = {
            'index': len(self.chain) + 1,
            'timestamp': time(),
            'transactions': self.current_transactions,
            'proof': proof,
            'previous_hash': previous_hash or self.hash(self.chain[-1]),
        }
        self.current_transactions = []
        self.chain.append(block)
        return block

    def new_transaction(self, sender, recipient, amount):
        # 生成新交易信息,信息将加入到下一个待挖的区块中
        self.current_transactions.append({
            'sender': sender,
            'recipient': recipient,
            'amount': amount,
        })

        return self.last_block['index'] + 1

    @property
    def last_block(self):
        return self.chain[-1]

    @staticmethod
    def hash(block):
        # 生成块的 SHA-256 hash值
        block_string = json.dumps(block, sort_keys=True).encode()
        return hashlib.sha256(block_string).hexdigest()
5. 工作量证明

新的区块依赖工作量证明算法来构造。PoW的目标是找出一个符合特定条件的数字,这个数字很难计算出来,但容易验证。这就是工作量证明的核心思想。在比特币中矿工们为了争夺创建区块的权利而争相计算结果。通常,计算难度与目标字符串需要满足的特定字符的数量成正比,矿工算出结果后,会获得比特币奖励。
当然,在网络上非常容易验证这个结果。

6. 实现工作量证明

衡量算法复杂度的办法是修改零开头的个数。使用4个来用于演示,你会发现多一个零都会大大增加计算出结果所需的时间。

import hashlib
import json

from time import time
from uuid import uuid4


class Blockchain(object):

    def proof_of_work(self, last_proof):
        '''
        简单的工作量证明:
         - 查找一个 p' 使得 hash(pp') 以4个0开头
         - p 是上一个块的证明,  p' 是当前的证明
        '''
        proof = 0
        while self.valid_proof(last_proof, proof) is False:
            proof += 1
        return proof

    @staticmethod
    def valid_proof(last_proof, proof):
        # 验证证明: 是否hash(last_proof, proof)以4个0开头?

        guess = f'{last_proof}{proof}'.encode()
        guess_hash = hashlib.sha256(guess).hexdigest()
        return guess_hash[:4] == "0000"

二、API接口

1. 创建节点
# Flask服务器将扮演区块链网络中的一个节点
import hashlib
import json
from textwrap import dedent
from time import time
from uuid import uuid4
from flask import Flask


class Blockchain(object):
    ...


app = Flask(__name__)
node_identifier = str(uuid4()).replace('-', '')
blockchain = Blockchain()


@app.route('/mine', methods=['GET'])
def mine():
    return "We'll mine a new Block"
  
@app.route('/transactions/new', methods=['POST'])
def new_transaction():
    return "We'll add a new transaction"

@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)
2.发送交易
import hashlib
import json
from textwrap import dedent
from time import time
from uuid import uuid4
from flask import Flask, jsonify, request

...

@app.route('/transactions/new', methods=['POST'])
def new_transaction():
    values = request.get_json()

    required = ['sender', 'recipient', 'amount']
    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'Transaction will be added to Block {index}'}
    return jsonify(response), 201
3. 挖矿

(1)计算工作量证明PoW
(2)通过新增一个交易授予矿工(自己)一个币
(3)构造新区块并将其添加到链中

import hashlib
import json
from time import time
from uuid import uuid4
from flask import Flask, jsonify, request

@app.route('/mine', methods=['GET'])
def mine():
    last_block = blockchain.last_block
    last_proof = last_block['proof']
    proof = blockchain.proof_of_work(last_proof)

    # 给工作量证明的节点提供奖励.
    # 发送者为 "0" 表明是新挖出的币
    blockchain.new_transaction(
        sender="0",
        recipient=node_identifier,
        amount=1,
    )

    block = blockchain.new_block(proof)

    response = {
        'message': "New Block Forged",
        'index': block['index'],
        'transactions': block['transactions'],
        'proof': block['proof'],
        'previous_hash': block['previous_hash'],
    }
    return jsonify(response), 200
4. 运行区块链项目

(1)启动项目
(2)使用postman发送请求,开始挖矿
挖矿:http://localhost:5000/mine,这里就可以开始挖矿了,需要一点时间,就可以看到返回的区块信息
区块信息:http://localhost:5000/chain,可以得到所有区块信息

有关区块链的知识,先给大家聊到这了,后面如果有新的认识,还会写出来让大家共同探讨!
上一篇下一篇

猜你喜欢

热点阅读