当前火热的区块链技术,让好多人都为之疯狂。单纯地研究技术的话,还是可以花一点时间。所以这儿就记录一点自己的学习笔记。

区块链的英文名字叫BlockChain,从字面上理解是不是可以拆成Block和Chain。从Wikipedia上的解释是一些记录的列表打包在一起,称为区块,这些区块通过密码学的知识将他们连接在一起。

学计算机的同学可能都知道什么是链表,链表其实是一个数据结构,是一种线性表,并不会按线性的顺序存储数据,而是在每一个节点里存下一个节点的指针。

区块链的底层就是使用了链表数据结构,这个数据块是有顺序的,当前的数据块总能找到上一个数据块。

链表中有头(首)节点,区块链中的首块称为创世区块。在区块链中,每一个区块(链表中数据块)有两个基本结构:Head和Body。

先看区块的结构图:
区块的结构图
以比特币分析:

1
2
3
4
5
6
7
8
9
10
11
12
|-----HEAD - 6 attributes --- 80B(字节)
| |--- VERSION --- 4B 区块版本号,验证规则
| |--- CURRENT --- 32B 当前区块Hash
| |--- PREVIOUS --- 32B 前一个区块的Hash,SHA256(SHA256(父区块头))
| |--- TARGET --- 4B 该区块工作量证明算法的难度目标
| |--- TIME --- 4B 时间戳
| |--- NONCE --- 4B
|
|-----Body - 1 or more TRANSACTIONS(交易记录)
| |--- TRANSACTIONS
| |--- INPUT
| |--- OUTPUT

其中头部的CURRENT和PREVIOUS就是一串哈希值。NONCE和TARGET跟POW共识机制挖矿有关。
比特币目前的版本VERISON是0x20000000,相当于block的第五个版本。用一个位数表示一个独立的功能,以区分未来的软分叉。

Hash哈希

写代码的人都知道哈希是一种算法,输入一个东西(字符串,图片,视频等等),最后变成一个有固定长度的哈希值,这个值是唯一的,输入的内容稍微改了一点,哈希值都会改变。从这个哈希也很难推导出原始数据。在比特币中用的哈希算法是SHA256。

比如说PHP中

1
2
3
4
php > echo hash('sha256', 'ityike');
fc4b100a38b5c9894cfff0dab6c258bcbcfd34a79c7c4b54f440b30846aa581b
php > echo hash('sha256', 'iiyike');
dd81a0135044ea78686dd97503757eca984f8047c965db75dde5ce53b2202100

不难看出,稍微改了一个字符,输出的哈希值就是完全不一样,完全没有规律。

区块头和ID、挖矿

在上面提到了区块头部的CURRENT和PREVIOUS就是一串哈希值。每个区块的ID从他的区块头80个字节数据两次SHA256哈希得到。在比特币中,对于这个ID有要求,符合条件的ID才是合法的。区块头的哈希值必须小于一个数。每一个新的区块的长达64字节的id前面都用零补全,一个合法的区块id是长这样子的:0000000000000000003c19cdbebe2df5c7f82558e2c80a0c7341e25072b732a2

数据区块的产生就是要计算出新的区块Id,其实就是挖矿的过程。挖矿的机器,只要找到一个幸运数字填到Nonce的位置,使得区块头的数据两次哈希后的值以18个以上0位开头,就表明区块生成,符合条件。不断的尝试幸运数据,知道符合条件。

此外,比特币还会动态的调整调整难度,这样做主要为了保证大约每10分钟产生一个区块。然而全网算力是变化的,如果想要新区块的产生保持都基本这个速率,难度值必须根据全网算力的变化进行调整。难度的调整是在每个完整节点中独立自动发生的。每2016个区块,所有节点都会按统一的公式自动调整难度,也就是说,如果区块产生的速率比10分钟快则增加难度,比10分钟慢则降低难度。这个公式为:

1
新难度值 = 旧难度值 * ( 过去2016个区块花费时长 / 20160 分钟 )

比特币POW的目标值(target)计算公式如下:

1
目标值 = 最大目标值 / 难度值

目标值的最大值为一个恒定值:0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

难度系数越调越高(目标值越来越小),导致了采矿越来越难。

当计算出符合条件的区块ID后,就开始向全网广播这个新区块,从而获得奖励,目前的奖励是12.5个比特币,每4年减半。这个12.5个比特币是比特网络上唯一没有发款人只有收款人的交易,新比特币就这样凭空诞生了。

区块链的分叉

如果两个人同时向区块写入数据,也就是说有两个区块加入,因为他们的前一个区块是同一个,这就形成了分叉。

1
2
3
4
5
[]
/
[]<=[]<=
\
[]

目前的规则是,新节点总是采用最长的那条区块链。如果区块链有分叉,将看哪个分支在分叉点后面,先达到6个新区块(称为”六次确认”)。按照10分钟一个区块计算,一小时就可以确认。

1
2
3
4
5
[]
/
[]<=[]<=
\
[]<=[]<=[]<=[]<=[]<=[]

其实添加新的区块是需要算理的,最终拥有最大算力的一方获胜。如果有人掌握了51%以上的算力就能控制区块链。

小结

区块链是分布式的数据库,对于数据,哪怕修改了很小的一部分,数据的哈希就变了,区块头就变了。在目前来看,还是安全的,可行的。