用Python实现区块链

发表于:2018-4-28 09:29

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:顾翔    来源:51Testing软件测试网采编

  区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法。区块链是目前比较火热的技术,它是2008年由中本聪第一次提出的概念,采用去中心化技术,主要保证数据的不可篡改性。区块链在智能合约、证券交易、电子商务、物联网、社交通讯、文件存储、存在性证明、身份验证、股权众筹都得到了应用。区块链的结构如图所示:
  区块链是有一系列区块组成的,区块中主要存储如下三类数值:内容、由内容加密后的具有一定规则的Hash值(其中包含一个Hash种子值)以及前一个块的Hash值。内容存储的是区块中的主要内容。由内容加密后的具有一定规则的Hash值,主要目的是对内容的加密,以防止内容的篡改性。前一个块的Hash值是为了保证整个系统形成一个链,第一个块我们称作为原始区块,或者称作首区块。本文介绍如何用Python来实现区块链技术。
  在这个算法中我们首先从网上下载下来的区块文本文件读出来(这步不在本代码中体现),然后根据文本的定义,每一行为一个区块(第一行为原始区块),一个区块的表现形式为Python的哈希结构,形式如下:
  {'Data':Data,'Hash': HashCode, 'preHash': preHashCode, 'nonce': nonce }
  其中Data为数据、HashCode为内容加密后的具有一定规则的Hash值、preHashCode为前一个HashCode值(如果为原始区块,该项为空串)、nonce为Hash种子值。比如:
  {'Hash':'0000c8045d53e65886a0050654694b4def233382fdeb5b9e5adead01f60fe7e0', 'nonce':'122453','preHash':'0000c8045d53e65886a0050654694b4def233382fdeb5b9e5adead01f60fe7e0', 'Data':'Cindy bown ¥3 to Jerry'}
  整合区块是一个Python的列表结构,列表中的每一项为一个哈希结构,结构如下:
  [{'Hash': '…','Data': '…', 'preHash': '…', 'nonce': '…'}},{{'Hash': '…', 'Data': '…','preHash': '…', 'nonce': '…'}}…{{'Hash': '…', 'Data': '…', 'preHash': '…','nonce': '…'}}]
  接下来我们检查获得的区块数据是否正确(也就是说没有被篡改),检查的地方主要为以下两处:
  1) 由内容结合Hash种子值形成的Hash值是否正确。
  2 ) preHashCode是否等于前一个区块的Hash值。
  再接下来读取输入的本次内容形成新的区块。
  最后,把新区块加入到文件中,回传回网络(回传回网络功能不在本代码中体现)
  下面是区块链的主程序:
if __name__=="__main__":
#输入新产生区块内容
print ("输入新产生区块内容: ")
Data =str(input())
if len(Data.strip())==0:
print("输入的内容不允许为空")
else:
blockChain =  BlockChain('BlockChain.txt')
#读取区块链文件
BlockList =  blockChain.readFromFile()
if  len(BlockList)!=0:
#获得前一个区块链
preHash =  BlockList[len(BlockList)-1].get("Hash")
else:
preHash  =""
#检查区块链数据是否被篡改
if  blockChain.checkFile(BlockList):
#创建新的区块链
NewBlock =  blockChain.createBlockChain(BlockList,Data,preHash)
#写入文件
blockChain.writeToFile(NewBlock)
  首先区块的内容由用户输入创建,当然输入的内容不允许为空。然后获取区块链文件内容,进行正确性验证,保证正确的条件下把新的数据加入进去,写回区块链文件。
  方法readFromFile为获取区块链文件。
#读取区块链文件
def readFromFile(self):
f =  open(self.filename,"r")
blockList=[]
blockHash={}
for line in f:
blockHash =  eval(line)
blockList.append(blockHash)
f.close()
return blockList
  以读的方式打开区块链文件,按照刚才介绍的列表,每个列表为一个哈希类型的方式在Python中存储。方法返回这个列表。
  方法checkFile检查区块文件是否被篡改。
#检查区块链数据是否被篡改
def  checkFile(self,BlockList):
i=0
for blocklist in  BlockList:
PreHash =  blocklist.get("preHash")
Data =  blocklist.get("Data")
Hash =  blocklist.get("Hash")
nonce =  blocklist.get("nonce")
#检查当前Hash值是否正确
digest =  self.createHash(Data,nonce)
if digest !=  Hash:
print  ("当前Hash值不正确")
return  False;
#检查前一个哈希值是否正确
if i==0:
print(PreHash)
if PreHash  !="":
print  ("当前preHash值不正确")
return False;
else:
j = i-1
if PreHash  !=BlockList[j].get("Hash"):
print  ("当前preHash值不正确")
return  False;
i=i+1
return True
  遍历文件中的每一个区块,获得这个区块的内容、Hash值、hash种子以及前一个哈希,检查当前Hash值是否正确。我们通过digest = self.createHash(Data,nonce)和if digest != Hash语句来检查Hash值是否正确,如果用户篡改内容,他是不知道加密算法的,所以它很难对应修改相应的Hash值,所以这个验证是保证数据不可篡改性很重要的内容。接下来我们验证PreHash,如果是原始区块,检查PreHash是否为空串(if PreHash !=""),否则检查PreHash是否与前一个区块相同(ifPreHash !=BlockList[j].get("Hash"))。由于PreHash是连接这个区块与上一个区块的桥梁,所以这两个值的不一致性也就不能保证整个系统是一个链条。在这里我们看一下Hash生成算法createHash。
#生成当前的Hash值
def  createHash(self,data,nonce):
messages =  hashlib.sha256()
messages.update(str(data).encode('utf-8'))
messages.update(nonce.encode('utf-8'))
digest =  messages.hexdigest()
return digest
  哈希算法又叫散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)用于加密相关的操作。这里我们使用Python的hashlib.sha256()来生成Hash值64位的哈希字符串。hash.update(arg) 更新哈希对象以字符串参数。hash.hexdigest() 返回摘要,作为十六进制数据字符串值返回。
  方法createBlockChain()为生成区块链,代码如下。
#创建新的区块链
def  createBlockChain(self,BlockList,data,preHash):
hashlist =  self.getHash(data)
nonce = hashlist[0]
digest = hashlist[1]
NewBlock={"preHash":preHash,"Data":data,"Hash":digest,"nonce":nonce}
return str(NewBlock)
  首先根据data生成hashlist,hashlist包括Hash值以及种子值,然后按照之前定义把内容、Hash值、前一个Hash值以及种子值放入到一个hash类型的变量中,最后以字符串的形式返回。
  方法getHash获得指定格式的Hash值,也就是所谓的挖矿,代码如下。
#获取HashCode,挖矿
def getHash(self,data):
i=0
prefix =  "0000"
while True:
nonce = str(i)
digest =  self.createHash(data,nonce)
if  digest.startswith(prefix):
myhash =  [nonce,digest]
return myhash
i=i+1
  在这里我们的特定格式定义为Hash值前4位为0,通过从0开始步长为1为增量结合内容来生成,如果不符合特定格式定义,再次循环计算,直到满足条件。
  最后我们把生成的新的区块,用方法writeToFile写到先前的文件中。
#写入文件
def  writeToFile(self,NewBlock):
f =  open(self.filename,"a")
f.write(NewBlock+"\n")
f.close()
  综上所述,我们把最后的代码分享给大家。
#!/usr/bin/env python
#coding:utf-8
import hashlib
class BlockChain:
def  __init__(self,filename):
self.filename =  filename
#读取区块链文件
def readFromFile(self):
f =  open(self.filename,"r")
blockList=[]
blockHash={}
for line in f:
blockHash =  eval(line)
blockList.append(blockHash)
f.close()
return blockList
#生成当前的Hash值
def createHash(self,data,nonce):
messages =  hashlib.sha256()
messages.update(str(data).encode('utf-8'))
messages.update(nonce.encode('utf-8'))
digest =  messages.hexdigest()
return digest
#获取HashCode,挖矿
def getHash(self,data):
i=0
prefix =  "0000"
while True:
nonce = str(i)
digest =  self.createHash(data,nonce)
if  digest.startswith(prefix):
myhash =  [nonce,digest]
return  myhash
i=i+1
#检查区块链数据是否被篡改
def  checkFile(self,BlockList):
i=0
for blocklist in  BlockList:
PreHash =  blocklist.get("preHash")
Data =  blocklist.get("Data")
Hash = blocklist.get("Hash")
nonce =  blocklist.get("nonce")
#检查当前Hash值是否正确
digest =  self.createHash(Data,nonce)
if digest !=  Hash:
print  ("当前Hash值不正确")
return  False;
#检查前一个哈希值是否正确
if i==0:
print(PreHash)
if PreHash  !="":
print  ("当前preHash值不正确")
return  False;
else:
j = i-1
if PreHash  !=BlockList[j].get("Hash"):
print  ("当前preHash值不正确")
return  False;
i=i+1
return True
#创建新的区块链
def  createBlockChain(self,BlockList,data,preHash):
hashlist =  self.getHash(data)
nonce = hashlist[0]
digest = hashlist[1]
NewBlock={"preHash":preHash,"Data":data,"Hash":digest,"nonce":nonce}
return str(NewBlock)
#写入文件
def  writeToFile(self,NewBlock):
f =  open(self.filename,"a")
f.write(NewBlock+"\n")
f.close()
if __name__=="__main__":
#输入新产生区块内容
print ("输入新产生区块内容: ")
Data =str(input())
if len(Data.strip())==0:
print("输入的内容不允许为空")
else:
blockChain =  BlockChain('BlockChain.txt')
#读取区块链文件
BlockList =  blockChain.readFromFile()
if  len(BlockList)!=0:
#获得前一个区块链
preHash =  BlockList[len(BlockList)-1].get("Hash")
else:
preHash  =""
#检查区块链数据是否被篡改
if blockChain.checkFile(BlockList):
#创建新的区块链
NewBlock =  blockChain.createBlockChain(BlockList,Data,preHash)
#写入文件
blockChain.writeToFile(NewBlock)
  总结:
  软件的基本功能质量应该主要由开发人员负责,测试人员的主要责任在于非功能质量,比如:性能、易用性、可靠性。以及边缘问题及深层问题,边缘问题及深层问题主要靠探索式测试完成。

本文经作者授权同意转载,如有问题联系博为峰小编(021-64471599-8017)。
《2023软件测试行业现状调查报告》独家发布~

精彩评论

  • jimi2018
    2018-7-12 14:25:23

    分享一个python用web3.py开发以太坊区块链应用的教程:
    http://xc.hubwiz.com/course/5b40462cc02e6b6a59171de4?affid=71251testing

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号