python从零开始实现区块链(区块链数据结构、挖矿、交易、分布性⼀致性解
决⽅案源码)
1区块链数据结构()
⼀个区块主要结构如下:
block ={
python请求并解析json数据'index':len(self.chain)+1,
'timestamp': time(),
'transactions': self.currentTransaction,qt截取字符串一部分
'proof': proof,
'previousHash': previousHash or self.hash(self.chain[-1])
}
具体说也就是当前区块的索引。
创建区块时间戳
区块⾥⾯包含的交易
知识证明
前⼀个区块的hash值
1.1 区块链初始化:
def__init__(self):
self.chain =[]
self.currentTransaction =[]
#Create the genesis block
有⼀个区块链的数组
以及需要区块链⾥⾯的交易的数组
⼀个⼀个创世区块
1.2. 创建新区块
def newBlock(self, proof, previousHash =None):
# Creates a new Block and adds it to the chain
"""
⽣成新块
:param proof: <int> The proof given by the Proof of Work algorithm
:param previous_hash: (Optional) <str> Hash of previous Block
:return: <dict> New Block
"""
block ={
'index':len(self.chain)+1,
'timestamp': time(),
'transactions': self.currentTransaction,
'proof': proof,
'previousHash': previousHash or self.hash(self.chain[-1])
}
# Reset the current list of transactions
self.currentTransaction =[]
self.chain.append(block)
return block
前⾯的交易需要加⼊到新⽣成的区块中
因此新⽣成的区块包含前⾯的交易,⽣成之后,当前交易数组清空,最后返回当前区块
1.3. 创建新的交易
def newTransaction(self, sender, recipient, amount):
# Adds a new transaction to the list of transactions
"""
⽣成新交易信息,信息将加⼊到下⼀个待挖的区块中
:param sender: <str> Address of the Sender
:param recipient: <str> Address of the Recipient
:param amount: <int> Amount
:
return: <int> The index of the Block that will hold this transaction
"""
self.currentTransaction.append({
'sender': sender,
'recipient': recipient,
'amount': amount,
})
#下⼀个待挖的区块中
return self.lastBlock['index']+1
交易有三个属性
1. 发送⽅
2. 接收⽅
3. 数量
返回值的意思是,需要将交易记录在下⼀个区块中
1.4. 区块hash
@staticmethod
def hash(block):
# Hashes a Block
"""
⽣成块的 SHA-256 hash值
:param block: <dict> Block
:return: <str>
转化为json编码格式之后hash,最后以16进制的形式输出
"""
# We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes
blockString = json.dumps(block, sort_keys=True).encode()
return hashlib.sha256(blockString).hexdigest()
使⽤python装饰器语法糖将hash⽅法设置为静态⽅法
将block的字符串通过SHA-256⽣成hash值,然后转变为16进制的数字返回
1.5. get最后区块⽅法
@property
def lastBlock(self):
transformer怎么翻译# Returns the last Block in the chain
return self.chain[-1]
1.6. ⼯作量证明
新的区块依赖⼯作量证明算法(PoW)来构造。PoW的⽬标是出⼀个符合特定条件的数字,这个数字很难计算出来,但容易验证。这就是⼯作量证明的核⼼思想。
为了⽅便理解,举个例⼦:
假设⼀个整数 x 乘以另⼀个整数 y 的积的 Hash 值必须以 0 结尾,即 hash(x * y) = ac23dc…0。设变量 x = 5,求 y 的值?
让我们来实现⼀个相似PoW算法,规则是:寻⼀个数 p,使得它与前⼀个区块的 proof 拼接成的字符串的 Hash 值以 4 个零开头。
@staticmethod
def validProof(lastProof, proof):
"""
验证证明: 是否hash(last_proof, proof)以4个0开头?
:param last_proof: <int> Previous Proof
:param proof: <int> Current Proof
:return: <bool> True if correct, False if not.
"""
guess = f'{lastProof}{proof}'.encode()
guessHash = hashlib.sha256(guess).hexdigest()
return guessHash[:4]=='0000'
def proofOfWork(self, lastProof):
"""
简单的⼯作量证明:
-
查⼀个 p' 使得 hash(pp') 以4个0开头
- p 是上⼀个块的证明, p' 是当前的证明
:param last_proof: <int>
:return: <int>
"""
proof =0
vue当前时间的年月日时分秒while self.validProof(lastProof, proof)is False:
proof +=1
return proof
逻辑是:当⼀台机器算出新的proof值之后,才能够创建新的区块
2.使⽤Flask框架来简历区块服务器()
2.1. 准备⼯作
import hashlib
import json
from textwrap import dedent
from time import time
from uuid import uuid4
from flask import Flask, jsonify, request
from BlockChain import Blockchain
# Instantiate our Node
app = Flask(__name__)
# Generate a globally unique address for this node
django电影管理系统
# 基于随机数⽣成唯⼀的id
nodeIdentifier =str(uuid4()).replace('-','')
# Instantiate the BlockChain
blockchain = Blockchain()
2.2. 挖矿实现
#创建/mine GET接⼝
@ute('/mine', methods=['GET'])
def mine():
# 1.计算⼯作量证明PoW
# 2.通过新增⼀个交易授予矿⼯(⾃⼰)⼀个币
# 3.构造新区块并且添加到链中
# We run the proof of work algorithm to get the
lastBlock = blockchain.lastBlock
lastProof = lastBlock['proof']
proof = blockchain.proofOfWork(lastProof)
# 给⼯作量证明的节点提供奖励.
# 发送者为 "0" 表明是新挖出的币
sender='0',
recipient=nodeIdentifier,
amount=1
)
#加⼊到链中
block = wBlock(proof)
response ={
'message':"New Block Forged",
'index': block['index'],
'transactions': block['transactions'],
'proof': block['proof'],
'previousHash': block['previousHash'],
}
return jsonify(response),200
先获取到上⼀个区块的⼯作量证明,然后算出新的⼯作量证明
区块的第⼀个交易为:
⾃⼰收到的⼀个⽐特币的奖励,假设发送⽅为:‘0’
如果成功,那么返回200ok,并且返回新区块的json
2.3. 新的交易
交易是放在区块上的,并且会放在下⼀个区块上,随着下⼀个区块的⽣成⽽被记录。#创建/transactions/new POST接⼝,可以给接⼝发送交易数据
@ute('/transactions/new', methods=['POST'])
def newTransaction():
values = _json()
# Check that the required fields are in the POST'ed data
required =['sender','recipient','amount']
if not all(k in values for k in required):
return'Missing values',400
# Create a new Transaction
index = wTransaction(values['sender'], values['recipient'], values['amount'])
response ={'message': f'Transaction will be added to Block {index}'}
return jsonify(response),201
⾸先获得post请求的json值
然后解析该json,如果没有sender…这些数据返回400,表⽰客户端错误
之后产⽣新的交易,返回新的交易将要放在的区块的索引。
2.4. 打印整个区块
#创建/chain接⼝, 返回整个区块链。
@ute('/chain', methods=['GET'])
def fullChain():
response ={
'chain': blockchain.chain,
网站制作公司兴田德润怎么联系'length':len(blockchain.chain),
}
return jsonify(response),200
2.5. 运⾏整个服务
if __name__ =='__main__':
#服务运⾏在端⼝5000上.
app.run(host='127.0.0.1', port=5000)
3.区块链测试
使⽤postman进⾏测试,可以⾃⾏下载
3.1 运⾏
3.2 创建交易
3.3 创建区块
4 实现分布式共识算法
4.1 验证区块链有效性
为了验证区块链的有效性,从两个⽅⾯:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论