区块链——据说现在这玩意很火?
哈希原理
推论2:如果区块的内容变了,它的哈希一定会改变。
然后我们可以将区块与哈希是一一对应,每个区块的哈希都是针对"区块头"(Head)计算的。也就是说,把区块头的各项特征值,按照顺序连接在一起,组成一个很长的字符串,再对这个字符串计算哈希。
Hash = SHA256( 区块头 ),SHA256是区块链的哈希算法,因为区块链的哈希长度是256位。这个公式里面只包含区块头,不包含区块体,也就是说,哈希由区块头唯一决定。不过没有关系,区块头包含很多内容,其中有当前区块体的哈希,还有上一个区块的哈希。这意味着,如果当前区块体的内容变了,或者上一个区块的哈希变了,一定会引起当前区块的哈希改变。如果有人修改了一个区块,该区块的哈希就变了。为了让后面的区块还能连到它(因为下一个区块包含上一个区块的哈希),该人必须依次修改后面所有的区块,否则被改掉的区块就脱离区块链了。哈希的计算非常耗时,短时间内修改多个区块几乎不可能发生,除非有人掌握了全网51%以上的计算能力。正是通过这种联动机制,区块链保证了自身的可靠性,数据一旦写入,就无法被篡改。这就像历史一样,发生了就是发生了,从此再无法改变。
采矿
由于必须保证节点之间的同步,所以新区块的添加速度不能太快。不然你还没有生成完,另一边有了新的区块,你又要同步区块重新计算,这样太乱了。故区块链的发明者让添加新区块变得很困难。他故意设置了海量的计算。也就是说,只有通过极其大量的计算,才能得到当前区块的有效哈希,从而把新区块添加到区块链。由于计算量太大,所以快不起来。而且计算的难度还可以动态的调整,现在难度大概保持在平均10分钟出一个的效率。
区块头包含一个难度系数(difficulty),这个值决定了计算哈希的难度。举例来说,第100000个区块的难度系数是 14484.16236122。区块链协议规定,使用一个常量除以难度系数,可以得到目标值(target)。显然,难度系数越大,目标值就越小。哈希的有效性跟目标值密切相关,只有小于目标值的哈希才是有效的,否则哈希无效,必须重算。由于目标值非常小,哈希小于该值的机会极其渺茫,可能计算10亿次,才算中一次。这就是采矿如此之慢的根本原因。除此之外,我们知道当前区块的哈希由区块头唯一决定。如果要对同一个区块反复计算哈希,就意味着,区块头必须不停地变化,否则不可能算出不一样的哈希。区块头里面所有的特征值都是固定的,为了让区块头产生变化,所以增加了一个随机项,叫做 Nonce。Nonce 是一个随机值,矿工的作用其实就是猜出 Nonce 的值,使得区块头的哈希可以小于目标值,从而能够写入区块链。Nonce 是非常难猜的,目前只能通过穷举法一个个试。根据协议,Nonce 是一个32位的二进制值,即最大可以到21.47亿。第 100000 个区块的 Nonce 值是274148111,可以理解成,矿工从0开始,一直计算了 2.74 亿次,才得到了一个有效的 Nonce 值,使得算出的哈希能够满足条件。并且由于难度系数的不断调节,采矿效果会越来越低,因为区块链设计者担心以后的计算机计算性能变强而使采矿难度降低,所以他做出了一个设计:难度系数每两周(2016个区块)调整一次。如果这两周里面,区块的平均生成速度是9分钟,就意味着比法定速度快了10%,因此接下来的难度系数就要调高10%;如果平均生成速度是11分钟,就意味着比法定速度慢了10%,因此接下来的难度系数就要调低10%。难度系数越调越高(目标值越来越小),导致了采矿越来越难。
简单的区块链构造代码示例(py)
首先定义一个 Block的数据结构。在区块链中,每个块都存储了一个时间戳和一个索引。在 SnakeCoin 中,我们将存储两者。为了帮助确保整个区块链的完整性,每个块都有一个 hash 值作为标识符。与比特币一样,通过对 Block 的索引、时间戳、数据做哈希加密得到每个 Block 的哈希值。数据可以是任何内容。
import hashlib as hasher
import datetime as date
class Block:
def __init__(self, index, timestamp, data, previous_hash):
self.index = index
self.timestamp = timestamp
self.data = data
self.previous_hash = previous_hash
self.hash = self.hash_block()
def hash_block(self):
sha = hasher.sha256()
sha.update((str(self.index) +
str(self.timestamp) +
str(self.data) +
str(self.previous_hash)).encode('utf-8'))
return sha.hexdigest()
创建初始区块以及后续区块
def create_genesis_block():
# Manually construct a block with
# index zero and arbitrary previous hash
return Block(0, date.datetime.now(), "Genesis Block", "0")
def next_block(last_block):
this_index = last_block.index + 1
this_timestamp = date.datetime.now()
this_data = "Hey! I'm block " + str(this_index)
this_hash = last_block.hash
return Block(this_index, this_timestamp, this_data, this_hash)
调用及运行截图
# Create the blockchain and add the genesis block
blockchain = [create_genesis_block()]
previous_block = blockchain[0]
# How many blocks should we add to the chain
# after the genesis block
num_of_blocks_to_add = 20
# Add blocks to the chain
for i in range(0, num_of_blocks_to_add):
block_to_add = next_block(previous_block)
blockchain.append(block_to_add)
previous_block = block_to_add
# Tell everyone about it!
print ("Block #{} has been added to the blockchain!".format(block_to_add.index))
print ("Hash: {}\n".format(block_to_add.hash))
区块链到底有什么用呢?——没什么卵用
区块链最显著的特点就是去中心化,它避免了传统数据库管理者可以轻易的修改数据的问题,但是为了保证这样的特性,其也付出了惨痛的代价,就是效率低下且能耗严重。因为每次写入数据都需要等待很久的时间从而使所有节点同步,为了延迟写入数据时间又需要“矿工”进行高额的无效运算。
那么问题来了,用这样的代价去换所谓的什么“去中心化分布数据存储”到底有何意义,其实归根结底也只是为了解决用户对于核心管理者的不信任问题,在黑客横行的时代,没有谁能保证自己的服务器或数据库100%安全,尤其对于一些企业机构甚至*机构都不稳定的国家,大家就更担心自己财产账单的安全性、有效性问题了。这也就是比特币被一些人炒作的风生水起的主要原因。那么回到我们的现实生活中,从目前形势来说,我觉得我们的国管金融机构(各大银行)也好,平时使用的涉金融软件(微信、支付宝)也好,还算是安全靠谱,所以对于我们而言,区块链产品目前的存在性、价值性、重要性并没有网上吹的那么强势,也希望大家不要盲目跟风。
参考文章
https://zhuanlan.zhihu.com/p/28073110
推荐阅读