前面的文章讲到了比特币里的矿工都在做什么(比特币里的矿工到底在干嘛?区块链伪技术简介(一)),今天我们通过一个简单的例子,来给大家直观的感受一下矿工的所谓“工作”,除了费电以外,具体是在干嘛。
我们先来看一下区块链的一个简化模型。
区块链的四个基础特征分别是:不可篡改,不可复制的唯一性,智能合约,去中心化。这里面不可篡改、不可复制的唯一性都与区块链结构中的哈希(Hash)算法紧密关联。
我们知道,哈希算法的特点就是,如果内容稍加改动,则得出的哈希值就会具有极大的差异。因此,在上图的链式结构中,如果我们改动了区块1中的数据,那么由于其哈希值是从数据中得来的,所以哈希值必然发生变化,而这个区块的哈希值变化了,它后面的区块就都要改。而如果这条链特别长了,那么修改的成本也就很高,接近不可能。
那么我们就写段Python代码来实现一下上图这个区块。
首先我们写一个区块类,代码如下:
classBlock: blockNo =0data =Nonenext =Nonehash =Nonenonce =0previous_hash =0x0timestamp = datetime.datetime.now()def__init__(self, data):self.data = datadefhash(self): h = hashlib.sha256() h.update(str(self.nonce).encode('utf-8') +str(self.data).encode('utf-8') +str(self.previous_hash).encode('utf-8') +str(self.timestamp).encode('utf-8') +str(self.blockNo).encode('utf-8') )returnh.hexdigest()def__str__(self):return"Block Hash: "+str(self.hash()) +"\nBlockNo: "+str(self.blockNo) +"\nBlock Data: "+str(self.data) +"\nHashes: "+str(self.nonce) +"\n--------------"
我们可以看到,其哈希值产生于数据,前一区块哈希值,随机数,当前时间和区块号,这里面任何一个数据发生变化,哈希值就会变化。这个类里最主要的就是这个哈希生成算法,其它的都很简单。
接下来我们再写一个区块链的链表类,代码如下:
class Blockchain: diff = 20 maxNonce = 2 ** 32 target = 2 ** (256 - diff) block = Block("Genesis") dummy = head = block def add(self, block): block.previous_hash = self.block.hash() block.blockNo = self.block.blockNo + 1 self.block.next = block self.block = self.block.next def mine(self, block): for n in range(self.maxNonce): print(n) # if (random.randint(1, 10) <2): # self.add(block) # print(block) # break if int(block.hash(), 16) <= self.target: self.add(block) print(block) break else: block.nonce += 1
这里面主要有两个函数,一个是将新区块加到链上的函数add,另一个是挖矿函数mine,这个函数就是矿工主要在做的所谓“工作”,它决定了新的区块是如何产生的。
我们看到,在一个循环里,实际挖矿的时候也可能是while(true),如果发现了一个区块达到了某个限定条件,在上面的代码中,执行的代码是int(block.hash(), 16) <= self.target,这个就比较难达到。注释掉的代码是random.randint(1, 10) <2,这个条件相对就好达到,在比特币等空气币里,条件要比这个难一些,而且难度是可调的,以保证大约十分钟左右生成一个新的区块。
通过以上的代码,我们就实现了一个简单的区块链,也让大家看到了矿工的所谓“工作”,就是想办法达到一个或难或易的算法条件。
最后我们写段代码执行一下这个简单的区块,代码如下:
blockchain = Blockchain()for n in range(5):blockchain.mine(Block("Block " + str(n + 1)))while blockchain.head != None:print(blockchain.head)blockchain.head = blockchain.head.next
结果如下:
喜欢本文的话,欢迎关注活在信息时代哦:)