区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法。区块链是目前比较火热的技术,它是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)
顾翔凡言:
软件的基本功能质量应该主要由开发人员负责,测试人员的主要责任在于非功能质量,比如:性能、易用性、可靠性。以及边缘问题及深层问题,边缘问题及深层问题主要靠探索式测试完成。