python实现基于Docker容器的分布式区块链
基于Docker容器的分布式区块链搭建
该文用以记录自己学习python搭建基于Docker容器的分布式区块链的过程以及中间遇到的问题和实现后的感想。
配置环境与相关软件
- 需要确保python 引入了Flask、requests以及urlparse和hashlib;
- curl和Postman两个软件需要确保有一个(之后进行与区块链相关的操作时候需要用到);
搭建区块链程序框架
- 因为区块链是通过挖矿来保存交易信息的,所以需要添加列表(chain[],current_transactions[])来记录交易信息。当然还需要添加新区块、保存交易信息的方法(new_block()和new_transaction())。因为每一个区块都是不重复且唯一的,所以需要为每个区块定义一个唯一的标志,这里借助Hash模块计算Hash值,定义一个hash方法(哈希算法是单向密码体制,也就是一个从明文到密文的不可逆映射,只有加密没有解密。),当然也可以使用别的算法为每个区块生成一个唯一的值。当我们添加新的区块的时候,需要把区块添加到区块链的最后,因此要实现返回最后一个区块的方法(last_block())。
- 以下是框架的代码:
class Blockchain(object):
def __init__(self):
#定义两个列表,用于记录区块链及交易信息
self.chain = []
self.current_transactions = []
def new_block(self):
# 创建一个新的Block区块,并添加到区块链中
pass
def new_transaction(self):
# 在交易列表中添加一个交易信息
pass
@staticmethod
def hash(block):
# 通过Hash算法返回区块的Hash值
pass
@property
def last_block(self):
# 返回区块链中最后一个区块
pass
区块链功能的实现
1.首先我们先实现挖矿的功能,考虑到区块链需要去中心化,以及记录与前一个区块的关联,交易和交易时间,因此时间戳(timestamp)、交易信息(transactions)、区块号(index)、工作量证明(proof)以及前一个点的哈希值(precious_hash)都是必须的。因为区块链通过竞争记账方式解决去中心化的账本一致性问题,而竞争记账则是一个过程,而不证明结果,所以需要工作量证明的机制实现对竞争结果的判定。记录前一个节点的哈希值是因为区块链某一节点被破坏了,那后面区块的哈希值就不能够对上,这保证了区块链的不变性。
2.以下是挖矿功能的代码:
def new_block(self,proof,previous_hash=None):
"""
生成新块
:param proof: <int> 工作量证明,它是一个工作算法对应的一个值
:param previous_hash: (Optional) <str> 前一个区块的哈希值
:return: <dict> 返回一个新的块,这个块block是一个字典结构
"""
block ={
'index':len(self.chain)+1,
#时间戳,记录区块创建时间
'timestamp': time.time(),
#记录当前的交易记录
'transaction': self.current_transactions,
#工作量证明
'proof':proof,
#前一区块的哈希值
'previous_hash':previous_hash or self.hash(self.chain[-1])
}
#重置交易,记录下一次交易
self.current_transactions = []
# 将新生成的block添加到block列表中
self.chain.append(block)
# 返回新创建的blcok
return block
3.接下来是new_transaction、last_block以及hash方法以及创世区块的创建,其中@staticmethod 静态方法只是名义上归属类管理,但是不能使用类变量和实例变量,是类的工具包
放在函数前(该函数不传入self或者cls),所以不能访问类属性和实例属性;@property装饰器会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用,这样可以防止属性被修改。
def new_transaction(self,sender,recipient,amount):
'''
# 在交易列表中添加一个交易信息
sender <str>:发送者的地址
recipient <str>:接收者地址
amount <int>:交易的数值
return <int>:返回新的Block的Id值,新产生的交易将会被记录在新的Block中
'''
self.current_transactions.append({
'sender':sender,
'recipient':recipient,
'amount':amount,
})
return self.last_block['index']+1
@staticmethod
def hash(block):
'''
# 通过Hash算法返回区块的Hash值
#生成 SHA-256 哈希值
:param block:<dict> Block
:return:<str>
'''
#首先将block字典结构转换成json字符串,再通过sort_keys指定按key排好序
block_string = json.dumps(block,sort_keys=True).encode()
#调用sha256函数求摘要
return hashlib.sha256(block_string).hexdigest()
@property
def last_block(self):
# 返回区块链中最后一个区块
return self.chain[-1]
def __init__(self):
# 定义两个列表,用于记录区块链交易信息
self.chain =[]
self.current_transactions=[]
self.nodes = set()
# 创建“创世块”
self.new_block(previous_hash=1</