区块链(1)—— 比特币中的区块、账户验证和记账

上一篇说到比特币是一种去中心化的电子现金系统。

 

去中心化说起来似乎挺简单,但是不用细想就会发现很多问题:

账本存储在每个节点中,如何保证每个节点中的数据一致,或者说如何防止某些节点的账本被恶意篡改而影响到整个网络的交易?

 如果说交易的验证由各个节点完成,那么如何在不把密码泄露给其他节点的前提下,证明自己对某个账户的所有权呢?

 去中心化就要求时刻有节点在线,由这些节点去完成记账、验证交易等工作,那么有什么机制能够让节点(即用户)有动力自发的保持在线去完成这些工作呢?

 区块链(1)—— 比特币中的区块、账户验证和记账 

对于上面的问题,比特币都给出了很优雅的解决方案,我们一一道来。

 

1. 账本验证问题

实际上对于第一个问题,很容易想到解决方法,那就是少数服从多数,如果某个节点的账本数据被篡改了,那么只需要和全网其他节点的数据比对,就必然能发现异常。

但问题在于,随着时间的推移,记录的累积,数据量会越来越庞大,记得在13年的时候,笔者下载的比特币钱包,从网络同步下载下来的交易账本数据就已经多达几十GB,如果说要对这么大的数据进行逐一传输、比对,可以说是不现实的。

 

在介绍比特币的解决方案前,我们先了解一个函数:Hash函数,俗称哈希函数。

 

关于Hash函数的细节,我们以后再描述,现在我们需要知道就是:一段数据经过Hash函数的运算后,得到一段长度很短的数据,我们称之为摘要数据,可以表示成:

Hash(原始数据) = 摘要数据

而Hash函数有以下三个特点:

(1) 同样的原始数据,经过同一个Hash函数,总是能得到相同的摘要数据;

(2) 原始信息的任何微小的修改,通过Hash函数后,得到的摘要数据会面目全非;

(3)不可逆运算,即:拥有摘要数据,无法逆向反推出原始数据。

 

比特币的做法是,交易账本数据按照时间分块存储,每一块只存储10分钟的交易账本数据,这每个存储单元即称之为“区块”。而每一个区块的头部会记录这一数据块的序号、时间和Hash摘要数据。

比较巧妙的地方在于,区块头部中的Hash摘要数据是由上一个区块的摘要数据和本区块的交易账本数据叠加后经过Hash函数得到的,即:

 

第n块的Hash值 = Hash(第n-1块的Hash值 + 第n块的账本数据)

 

可以看到,虽然每一个区块内的交易账本数据是独立的,但是区块头部的Hash值却是依赖于上一区块的Hash值,从而形成了一条链式的结构。这想必也就是“区块链”名字的由来。

链上的任何一个区块中的数据受到的篡改,都将反映到最新的一个区块的Hash值上,因此,要想验证某个节点的账本数据是否正确,只需要比对最新一个区块的Hash值即可。

 

2. 账户所有权的证明

如果我要通过某个账户给另一个账户转账,必然需要证明我对此账户的所有权。对于中心化的货币系统,我们只需要向银行出示密码即可,但是对于去中心化的系统,如果我们也通过出示密码给其他节点,来证明我们对账户的所有权,那么我们的密码也就泄露给了其他节点(即用户)。

 

事实上这是一个现代密码学中比较基础的问题,说白了就是如何在不暴露自己私钥的前提下,自证身份,也有很成熟的解决方法:利用非对称加密算法。关于算法的细节,计划在后面单独说说现代密码学的一些基础算法,这里我们就用类比的方法描述一下。

 

首先我们来确定要解决的问题:

A要从账户X中转账一笔钱给账户Y,就需要向全网广播一条消息,网络中的其他节点收到消息后,要有方法能够验证广播这条消息的人(也就是A),确实拥有账户X的所有权。同时,消息中不能包含账户X的密码,否则就意味着账户的控制权泄露给了全网的用户。

 

解决方法是这样的:

由A向全网发布广播,广播的消息中需要包括:

①           原始交易信息(如打款账户地址、收款账户地址、打款金额等)

②           原始交易信息经过Hash算法后得到的一条摘要信息

③           签名

 

前两条很好理解,关于签名,我们可以这么理解:

有这么个签名函数,输入是打款账户的私钥(只有账户的所有者才有)和②摘要信息,而输出就是③签名,即:

            

签名= sign (私钥, 交易信息摘要)

 

网络中其他节点收到广播后需要验证A是否有权将账户X中的钱转出去,验证步骤如下:

广播中①原始交易信息中,有打款者的账户地址,这个地址其实就相当于公钥。

相对应于签名函数,还有个校验函数,输入是③签名和公钥(也就是①中的打款账户地址),输出则是摘要信息,即:


交易信息摘要 = verify(签名, 公钥)


只需要比对verify函数算出的交易信息摘要与广播中的②交易信息摘要相吻合,那么就认为广播这条消息的人(也就是A),拥有正确的私钥,即拥有账户X的所有权。

而通过公钥是无法推算出私钥的,因此也不会有泄露私钥的风险。

 

说到这里,大家可能一脸懵逼,私钥、公钥是啥?签名、验证又是啥?

关于私钥、公钥、sign函数和verify函数分别怎样实现,这就是密码学的范畴了,我们这里先不细讲,我们可以通过以下的类比来形象的理解签名和验证的过程:

 

我们假设A拥有账户X的私钥,而这私钥就是一种红色光的手电,公钥呢,则是一种绿色光的手电,红光和绿光照在一起得到白光,而白光与任何另一种颜色的光照在一起,都仍然是另一种颜色。

区块链(1)—— 比特币中的区块、账户验证和记账

假设交易信息摘要是一种浅蓝色的光,签名过程就是把浅蓝色的光和红色的光(私钥)照在一起,得到一种新的颜色,这就是签名。

区块链(1)—— 比特币中的区块、账户验证和记账

而验证过程,就只需要把绿色(公钥)照在签名色上,这就相当于红色、绿色、浅蓝色光照在了一起,就还原出了浅蓝色,也就是交易信息摘要。

区块链(1)—— 比特币中的区块、账户验证和记账

因此,密码学要做的事情,首先就是找到一种方法,能用私钥得到公钥,并且要保证公钥无法反推出公钥;其次,还要基于公钥和私钥,找到签名和验证的数学方法。


看到这里,相信大家对于签名和验证的过程应该比较理解了,可以在回过头去再理解下比特币是如何验证账户的所有权的。

 

3. 记账问题

去中心化的前提就是,时刻需要有节点在线,否则就没有人处理记账、验证交易等工作,那么,比特币有什么机制,让人们心甘情愿的时刻保持在线呢?

我们之前说过,比特币毎10分钟,会将这10分钟内的交易数据打包记录成一个区块,也就是记账。但是不是所有人都有权利去记账的,全网的每个节点,都会去计算一个问题,只有第一个解出符合要求的答案的节点,才有记账权,而作为奖励,该节点会得到一定数量的比特币。随着比特币的价格越来越高,越来越多的人参与到这种解题竞赛中去,并将这一过程戏称为“挖矿”,也正是这些“矿工”,维持着整个比特币网络的运转。而这也就是比特币的发行过程:毎10分钟,通过奖励矿工的形式,产生新的比特币。

 

至此,我们已经大致了解了比特币“去中心化”运转的逻辑。后面的章节,我们会再深入聊聊一些细节,比如:挖矿到底是要解决什么样的难题?比特币的账本结构是怎样的?