事情的起因是家里人想了解区块链。这事儿一两句话说不清,而我自己也想趁机整理整理区块链的相关知识点。所以就提笔写了写。

因为是给家里人看的,写得比较浅显。有谬误敬请指正。

区块链是什么

“区块链”就像“牛肉面”、“花生油”一样,是一个可以“顾名思义”的名字:“区块链”这个名字就指明了区块链是由“区块”组成的“链”——就好比“牛肉面”就是“加了牛肉的面”、“花生油”就是“用花生榨出来的油”一样。

不过,这“牛肉”是黄牛肉还是水牛肉?这“面”是拉面、挂面还是手擀面?这“花生”是山东花生还是东北花生?“榨油”的方法是物理压榨还是化学析出?这都是有说法的。同样,“区块”和“链”也是有说法的。

区块

区块链中的区块,不像一块牛肉、一块砖头那么简单,其中蕴含了复杂的数学原理和公式运算。

首先,每一个区块都包含了“区块头”和“区块体”两部分信息。“区块头”和人的脑袋一样,用来思考“我是谁”、“我从哪里来”这种比较形而上的问题。

在区块头中,主要存储了这样几部分信息:

自己的“身份证号”

记录的是“我是谁”。当我们需要从一个长长的链条中找到一个指定的区块时,就需要使用这个“身份证号”来查找它。

上一个和下一个区块的“身份证号”

小时候我们排队时,老师会让我们记住自己前面的同学是谁、后面的同学是谁。记牢了之后,无论课件我们玩儿得多乱,都能很快的排成一条长长的队列。区块链也是用同样的方法来把“区块”组装成链的。

实际上,一个区块自己的“身份证号”,是根据上一个区块的“身份证号”加上区块体中记录的数据计算出来的。这样一来,如果区块体中记录的数据发生了变化,或者上一个区块发生了变化,这个区块的身份证号都会随之变化。

高度

用来记录当前区块在整条链中的序号。如果不记录这个值,每次我们要获取序号时,就不得不从链条中第一个节点开始数,非常麻烦。所以,区块中会记录下这个数字,以备查用。

时间戳

记录的是当前这个区块头的出生年月日时分秒毫秒甚至皮秒。当多个区块要组成一个区块链时,就需要根据这个时间戳来排列顺序了。

万一有时间戳完全一致的怎么办?区块链会用一种“共识算法”来判定应该使用哪个链,后面再说。

“区块体”则和人的躯体一样,用来承担区块的主要功能——唱歌跳舞rap篮球……啊不对,是记录数据。

当然,区块体中记录数据的方式比较复杂,它使用了一种叫“默克尔树”的结构。这种技术我们会在后面细讲,这里只需要知道:在“默克尔树”这种结构中,每写一笔数据——无论是新增、修改还是删除,它都会重新计算出一个独一无二的“身份证号”来。

在各种武侠影视剧中,我们都能看到一种叫“易容术”的东西:主人公只需要往脸上随便抹点什么,就能化妆成另外一个人,别人就完全认不出他来了。“默克尔树”就是这样一种神奇的“易容术”:你换一件衣服、或者戴一个墨镜、或者少扎一朵头花,就能让你连身份证号都变成另外一个人的了。

在区块头计算自己的“身份证号”时,就会用到默克尔树的“身份证号”。

其实在“区块”部分,已经把“链”说得很清楚了:通过每一个区块上记录的“上一个区块的身份证号”、“自己的身份证号”以及“下一个区块的身份证号”,我们就可以把区块串成一个完整的链了。

区块链能做什么

特点

首先我们来设想一下:如果我要篡改区块链上记录的一笔数据,会发生什么呢?

假设一开始,区块链中只有两个区块。

第一个区块的区块体中记录了“林俊是大帅哥”这个数据,默克尔树根据这个数据,计算出了自己的“身份证号”:“198612”;随之,由于这是第一个区块,区块头只需根据这个“身份证号”就可以计算出整个区块的“身份证号”:“240073”。

第二个区块先在区块头记录了上一个区块的“身份证号”是“240073”。它根据这个“身份证号”、加上自己的默克尔树的“身份证号”,计算出了自己的“身份证号”:“000000”。然后它把这个“身份证号”告诉第一个区块,让它把“111111”记录到“下一个区块”的“身份证号”中。

至此,一个简单的区块链就构造完毕了。

特点一:不可篡改

然后,有个人想要把第一个区块体中的数据改成“林俊是大笨蛋”。虽然只改了两个字,但是,由于数据不同,这个默克尔树的“身份证号”也会发生变化:从“198612”就变成了“360313”。随之,当前区块的“身份证号”也变了、第二个区块上记录的“上一个区块”的“身份证号”也变了、随之第二个区块的“身份证号”也变了、第一个区块上记录的“下一个区块”的身份证号也变了……

实际操作中,这两个区块一般是放在不同的人手里的。当这个人修改完第一个区块中的数据之后,通常他都无法修改第二个区块。这样,当需要对账时,我们就很容易发现:第一个区块上记录的下一个区块是第二个区块,但是第二个区块上记录的上一个区块不是第一个区块(这是区块链的绕口令……)。显然,第一个区块被篡改的事情就东窗事发了。

你看,这么简单的一个区块链、这么简单的一个修改,都会产生这么大的修改工作量;如果一个区块上有上千个节点、一个区块链上有上万个区块呢?这个改动量就海了去了。这些区块同样的都存放在不同的地方,任谁也无法把所有数据都修改一遍。而只要漏掉哪怕一个区块没有修改,那么数据被篡改这件事就一定会暴露出来。

特点二:不会遗失

另外,其实上面已经隐藏地介绍了它的另外一个特点了:区块保存在不同的人的手里。

实际上,区块链中的区块不仅保存在不同的人的手里,而且每一个区块都有若干件复制品。这不仅保证了这些数据很难被篡改,而且还保证了他们几乎不可能丢失不见。这个很好理解——我把“林俊是大帅哥”这句话抄写一万遍,分别放到一万个人的口袋里。这样,即使其中九千九百九十九个人都弄丢了这张纸条,我也能从最后这个人口袋中找到这句话。

这就是区块链的两个最大的特点:不可篡改、不会遗失。

应用场景

不可篡改和不会遗失这两个特点,使得区块链成为了一套非常可靠的记录数据的工具。这种可靠性,最早就是用在了金融领域。

金融领域

金融系统对可靠性的要求非常非常高,毕竟系统里记录的都是客户的真金白银。

前阵子看了个新闻,英格兰一家银行的系统在升级过程中出现bug,搞丢客户数据,导致客户损失了28亿英镑的财产。这银行实在太不可靠了。

搞丢客户数据这种问题,根子上就是因为所有的客户数据都存在一个地方——也就是鸡蛋都放在一个篮子里。万一这个地方停电了、着火了、地震了什么的,那客户数据很容易就下落不明了。

区块链就不会发生这种问题:它可是不会遗失的。即使一个篮子里的鸡蛋都碎了,没关系,还有成千上万个篮子里有克隆过去的鸡蛋呢,随便拿一个出来都能做孵出小鸡来。

此外,鸡蛋都放在一个篮子里,还存在一个问题:万一这个篮子里的鸡蛋被人掉包了呢?如果他掉包的是你的股票交易记录呢?本来你要花100块钱从库克手里收购苹果10%的股份;你都付了钱了,库克突然说不对合同上写的是100块钱收购1%的股份。然后你拿出合同来一看:它已经被库克买通中间人给篡改掉了。

ps,春秋时期有一个非常经典的这种耍赖的故事:张仪用商於七百里土地欺骗楚怀王。

区块链就不会发生这种问题。如果我们把合同存放到区块链上,任凭库克张仪手眼通天,也无法篡改里面的内容。

离岸结算

金融机构把数据都记录在一个地方,还存在离岸结算的问题。

想象一下我们在中国银行办了一张visa卡,然后拿着这张卡去国外旅游去了。在国外旅游期间——假设是2020-01-19 11:00,我们用这张卡刷了100块钱,pos机显示可用余额为50元。这时,在国内、中国银行的数据中心里,我们的卡上还有多少钱呢?怎么想都应该是50块钱吧?但是很可能,这是国内记录的仍然是100块钱。

为什么呢?

产品溯源

说实话,用区块链做产品溯源,真有点大材小用。

现代人越吃越精细,恨不得一根白萝卜都是长白山上长了七十年的野生白萝卜。但是,当有人把一根长白山上长了七十年的野生白萝卜拿到眼前时,鉴于现在骗子那么多,人们必然要心里犯嘀咕:这东西,真的是长白山上长了七十年的野生白萝卜吗?真的不是从地里随便挖一根然后随手贴了个标签吗?

用区块链可以解决这个问题。我们用区块链来记录这根萝卜从种子开始的成长数据——GPS/北斗定位数据、DNA信息、身高、体重、年龄等等,一直记录七十年,这样,拿出这根萝卜的同时甩出这根区块链,就可以证明它的的确确是长白山上长了七十年的野生白萝卜。想往这根区块链里安插什么假货?不可能的。即使能伪造出最后的标签,这七十年的生长记录也是无法伪造、无法篡改的。

现在有些阳澄湖大闸蟹就用上了区块链技术来为自己正名。

区块链的核心技术

严格来说,区块链不是“一种”技术,而是由三种技术组成的一套技术方案。这三种技术分别是对等网络、加密算法、共识算法。

一种技术和一套方案有什么区别呢?可以这样理解:发动机是一种技术,变速箱是一种技术,悬挂是一种技术……它们有机地组合在一起得到的汽车是一套方案。

对等网络

对等网络的意思是:网络上的每一个节点都是对等的。没有谁比别人更高级,也没有谁比谁更重要。

与之对应的当然是不对等网络。在不对等网络中,网络节点之间是有高低贵贱之分的。有些节点是主服务器,它们的“地位”就更高一些:带宽啊、电力啊、硬盘啊等等资源都要优先保证给它们使用。有些节点是从服务器,它们的“地位”就更低一些,如果遇到资源紧张,它们往往就要给核心服务器让路,就像绿皮车给高铁让车一样。如果主/从服务器之间出现了分歧——例如主服务器上记录的账户余额是10块钱,从服务器上记录的是20块钱,那么一律以主服务器数据为准——就像老话说的:领导说行,不行也行,领导说不行,行也不行。

而在对等网络中则不存在这种差别:所有节点都有同样的权重。也就是说,无论在资源分配上、还是数据权威性上,所有的节点都是一样的。

专业名词不好懂,打个比方就好办了。

比如我手头紧了,需要借点钱。我找我们领导借了1000,找平级的同事借了1000,找下属小弟借了1000。那么,我和这三个人就组成了一个借贷关系网络。在这个网络中,显然领导的钱是要优先还的,平级同事的可以好商量,小弟的么……说不定哪天他就离职了呢哈哈哈。哪天领导耍赖皮,非说你其实借了他2000,你也没辙只能打落牙齿和血吞。这种关系网络就是不对等网络。

但是,如果我是通过一些方式向三个陌生人借的钱呢?我完全不知道这三个陌生人叫什么、长什么样子、是什么样的人,所以这笔钱该先还给谁、后还给谁,这对我来说无关紧要。他们要跟你耍赖皮?我还跟他们耍赖皮玩失联呢。这种关系网络就是对等网络。

这个例子中提到的借钱的方式,就是这几年很火的P2P(Person To Person)。很巧,对等网络也有个别名叫P2P(Point To Point)网络。曾经风靡一时的BT下载就是P2P网络的一个经典应用。

区块链中的应用

区块链中对等网络的作用和BT下载差不多,都是用来把同一份数据存在多个权重相等的节点上的。这里的“多个”,不是几个、几十个这种量级,而是成千上万的量级。有新闻说,2018年的时候,闪电网络的节点数就达到了4,345个;比特币的节点数甚至一度超过了110,000个。即使2019年的节点数普遍在下降,以太坊的节点数最高还是达到过10,078个。

加密算法

加密算法是这样一种东西:它能让甲乙两个人在说话时,只有自己能听懂对方说了什么,其他人即使听见了内容也听不懂含义。

谍战片中出现的密码本,福尔摩斯探案集中的跳舞小人,甚至旁人听不懂的地方方言,都可以归入加密算法中。据说二战期间,美军就曾经使用过一种非常生僻的印第安方言来通话,德军即使窃听到了内容,也完全不知道电话两头在说什么。

计算机领域的加密算法和数学有很深的渊源,后面会用一些数学符号来解释。所以先做一点定义。

加密算法一般定义为y=f(x),解密算法则是x=f(y)。其中的x是加密前的信息,y是加密后的信息。通常,f(x)和f(y)中都会有几个参数,这些参数就被叫做密钥。例如,如果f(x)=x+5,那么这个加密算法的密钥就是5。如果f(x)=x^7%22,那么这个加密算法的密钥就是7和22。

顺便说明一下,^表示幂运算,x^7表示x的7次方;%表示求余运算,也叫取模运算,n%22表示n除以22后得到的余数。幂运算和求余运算都按照从左到右的顺序进行运算。

计算机中的加密算法主要分两种:对称加密和非对称加密。

对称加密

对称加密就是加密和解密使用同一个密钥来做计算的加密算法。例如,加密算法f(x)=x+5,那么解密算法就是f(y)=y-5。这里,加密和解密公用一个密钥:5。这种公用的密钥,就叫做公钥。“对称”的含义其实就是指加密和解密双方使用相同的密钥。

想象一下你是一名情报员。你和中央约定的情报加密方式是这样的:首先把所有的英文字母都用一个数字来代替,借此把英语单词转换成了一串数字;然后用上面这个加密算法把这串数字做了加密处理,得到一串新的数字。解密则用上面的解密算法来处理。这样,鬼子即使拿到了这串新的数字,即使猜到了数字对应英文字母,在不知道密钥——并且你没有叛变革命的情况下,也很难破解这串字母代表什么单词。例如,"a boy"转换成数字就是"1 2 15 25",再用f(x)=x+5处理一遍就是"6 7 20 30",转回单词就是"f g t ?",这根本看不出是个什么鬼。据说,这是世界上最早的加密算法,并且是由凯撒大帝发明的,因而被命名为凯撒密码。

显然,对称加密比较简单,使用和实现起来也很高效。但是它的问题也很明显:一旦这个公用的密钥泄露出去了,那么这套加密算法就等于是失效了。

非对称加密

非对称加密的算法就要复杂而安全得多。例如前面举例所使用的加密算法f(x)=x^7%22,你能想到他的解密算法是什么样的吗?这个解密算法涉及长篇累牍的数学演算,最终得到的结果是:f(y)=y^C%22,(C≠7。为了保证后面举例的效果,这里暂时不告诉你这个数字是多少。目前只要知道它是一个不等于7的常量就可以了)。

先别往后看,仔细观察一下加密和解密的两个算法,看看你能不能发现非对称加密算法的奥秘。

这个奥秘就是:加密算法和解密算法所使用密钥是不一样的。这两个密钥中,22是双方共同使用的公钥,而7和C则是彼此私人秘藏的,叫私钥。“非对称”的意思就是加密和解密双方使用了不同的密钥,一般都是指不同的私钥。

我们仍然用"a boy"来举例。中央给你下发了新的加密算法,你使用新的加密算法后得到了一串新的数字:""。这时候,革命队伍中出了一个叛徒,他把加密算法告诉了鬼子。同时,鬼子也窃听到了加密后的数字。然后呢?在不知道解密所使用的私钥C——并且你没有叛变革命的情况下,敌人还是要大眼瞪小眼,干着急。而这解密的私钥呢?藏在千里之外的中央指挥部里,想弄到它可就难于上青天咯。

f(x)=x^a%b和f(y)=y^c%b就是计算机中一种经典的非对称加密算法——RSA算法的简单应用。当a=7、b=22的时候,c=3。你可以拿这个公式去表演读心术。当然,实际使用中的密钥可能长达几百几千位,因此运算起来会非常麻烦,但是安全性也会成百上千倍的提高。

不可逆加密

广义上来说,还有一种加密算法叫不可逆加密。不可逆加密只有加密算法、没有对应的解密算法。例如前面提到的求余运算,还有大名鼎鼎的MD5算法都是不可逆加密。不可逆加密算法主要用来验证信息传递过程中数据没有被篡改,也可以用来存储敏感信息。

举个例子来说,中央和情报员约定每封情报末尾用一个数字来表示这封情报中正文的字数。有一天你作为情报员给中央发了一封情报(暂时不考虑可逆加密,不然例子太复杂了):“鬼子2月5日进攻8”。没想到传递情报的通讯员叛变革命了,这封情报落在了鬼子手里。狡猾的鬼子把这封情报改成了“鬼子2月15日进攻8”——因为不知道最后那个数字8是什么意思,鬼子只好把它原样照抄上去,然后让通讯员把假情报交给了中央。中央一看,情报正文里有9个字,最后一个数字却是8,这肯定是个假情报,而且问题很可能出在通讯员身上。这就是不可逆算法的第一个常见用途。

第二个常见用途是存敏感信息。比如,银行的计算机系统里肯定要存我的银行卡密码,但是这个密码太敏感了,既不可能不加密直接存储,也不可能用可逆的加密算法来加密存储,只能用不可逆的加密算法来处理,否则程序员岂不是可以为所欲为了?

那我去取钱的时候怎么检查我输入的密码对不对呢?很简单,用同样的不可逆加密算法把我输入的数据加密一遍,然后把这个秘文和系统存储的那个秘文对比一下:如果相同则密码输入正确,否则就是密码输入错误了。

当然,不可逆加密算法会精心设计,保证相同内容得到的结果一定相同、不同内容得到的结果一定不同。不可逆加密算法也叫摘要算法——因为这种加密算法会丢失信息,就像给一篇很长的文章写了个很简短的摘要一样。大名鼎鼎的MD5算法以及HASH算法都属于不可逆加密算法。

最后提一嘴,某些特定情况下,不可逆加密算法也是可逆的。不过这种可逆情况太罕见也太复杂了。

区块链中的应用

在区块链中,加密算法有什么用呢?

区块链最初是金融领域的一项技术方案,金融数据如此重要而敏感,怎么可能不做加密就在网络上传递、存储。

另外,区块链还用加密算法做了一件很牛的事情:保证区块链上的数据不被篡改。这个具体到后面再说。

共识算法

“共识”这个词经常出现在新闻联播里:“某甲与某乙、某丁就某件事情达成共识”。这个词很好理解:双方或多方就同一事件达成统一认识。共识是各方合作的基础。大到中美双方发布的《中美联合公报》、小到我和出租车司机都认为特朗x是个不靠谱的小人,这都是共识。

有人参与的情况下,分歧还是很容易变成共识的。即使特朗普那么不靠谱,鹤仙人每次去了之后总还能达成一些协议。但是,如果没有人来参与、纯靠计算机运算,要怎样才能达成共识呢?如果是在不对等网络中,那当然是主服务器说了算。但是在对等网络中呢?服务器A说甲刚花了4块钱他的账户上还剩6块钱,服务器B说不对他刚花了7块钱现在账户上只剩3块钱了。这种时候,由于两台服务器的地位和权重是相同的,到底应该听谁的呢?

说来惭愧,虽然“共识算法”这个名字中也有“算法”两个字,但是它的核心思想却远不如“加密算法”那么高深,而是简单粗暴地按某个规则来竞选:无论服务器A还是服务器B,谁能证明自己是正确的,其它服务器就听谁的。

这有点像美国大选。如果选民们一看打卡记录,发现特朗普每天加班到半夜11点,希拉里却每天9点就去睡美容觉了,这可以证明特朗普是合适的总统!这种共识机制就叫“工作量证明”机制。

如果他们一查银行账户,特朗普账户里还剩10块钱,希拉里却还剩15块钱,这证明希拉里更合适!这种共识机制就叫“权益证明”机制。

后来又一想,也不能老是谁钱多就让谁当总统吧!再多考虑点别的因素吧,体重乘以账户余额,或者年龄乘以账户余额,或者干脆一个随机数乘以账户余额,这种就是改进的“权益证明”机制。

此外还有一些其它的证明机制,不一一例举了。

当然,共识算法远没有它看上去那么简单。设想一下,假如特朗普证明了自己更应该当选总统后,有些州明面上支持他、背地里却把票投给了希拉里,会发生什么结果呢?

在共识算法领域里,这种“背叛”问题有一个更经典的描述,叫做“拜占庭将军问题”。

拜占庭将军问题

拜占庭是东罗马帝国的首都,也叫君士坦丁堡,现在叫伊斯坦布尔。这是一座非常宏伟的城市:城墙周匝若干公里,有若干个城门,相距都非常远。有一年,拜占庭遭到了奥斯曼帝国派来的一群将军的围攻。这几个将军之间互不统属,各自攻击这座城市的一个城门。而且由于军务繁忙,这些将军没法脱身出来组织一场面对面的军事会议、而只能通过信使来回传话。

到了城下之后,将军们很快意识到一个问题:拜占庭实在太易守难攻了!除非所有人同时发起进攻,否则自己毫无胜算。但同时,也有些人心里打起了退堂鼓:这是一座受到祝福的、永不陷落的上帝之城啊,与其进攻,不如撤退。

这时候,将军们就必须达成一个共识:要么全体进攻,要么全体撤退。如果一部分人进攻、一部分人撤退,最后的结果一定是进攻的人因为兵力不足而战死城下、撤退的人因为临阵脱逃而军法处置。

又由于前面说的原因,将军们只能通过信使跑腿,来尝试达成一致。

为了简化描述,我们先考虑只有三个将军的情况。

主战最积极的将军A,和主和最积极的将军B,都派出了信使,去征询其他将军的意见,并根据最终汇总的多数意见来采取行动。显然,如果将军C主战,那么三个将军就会尽力一战;如果将军C主和,那么第二天就拔营撤军。

万万没想到的是,将军C却心存鬼胎。他给将军A回信说“打吧”,却给将军B回信说“撤吧”。结果,将军A独自进攻,战死沙场;将军B独自撤退,斩首示众。只有将军C收拢将军A的残兵剩勇后班师回朝,报告说“A和B意见不和,各行其是。我从中斡旋无果,只能尽力维持。”最终将军C吞并了A和B的军队,从此大权在握独揽朝纲。

把将军的数量从3扩展到n,我们可以发现:只要内奸的数量超过了n/3,他们就可以轻易地操纵“共识”,把它改写成他们想要的结果。换句话说,如果内奸的数量低于n/3,那么他们的意见左右不了最终共识。

区块链中的应用

这个结论有什么意义呢?

回到前面的美国大选的例子上来。

按照前面提到的共识算法——工作量证明和权益证明,特朗普必须在每个州都发表一次演讲、证明自己更适合当美国总统,然后他才能成功当选。

这种办法有什么问题呢?效率太低。美国有50个州就要发表50次演讲。前面说过,区块链使用的对等网络中可能有几千、几万个节点。如果每次达成共识都要这样每个节点“做一次演讲”,花的时间就太多了,最后很可能导致用户在手机上点一下“支付”按钮,然后屏幕上一个圈圈转了半个小时还没支付成功,这谁受得了?

不过,这种办法也有一个好处:除非有51%的节点当了内奸,否则最终共识就不会受影响。像前面说的,除非有26个州明里支持特朗普、暗里投票给希拉里,否则美国总统这个宝座就不会旁落。

而从拜占庭将军问题出发,工程师们研发出了一套新的共识算法。这套共识算法大幅度提高了性能——原本需要转半个小时的圈圈,到这里一秒钟就可以搞定了。

但是,有得必有失,在这套算法下,只要有31%的节点当了内奸,最终共识就要变味了。不过,考虑到对等网络里节点总数有那么多,31%也是一个很可观的数字,要想“买通”这么多节点也绝非易事。所以在实践中,这种算法还是比较常用的。

默克尔树

树结构是由一个节点出发、一生二二生三地生长出若干个节点来的一种结构。其中,最初的这个节点叫做“根节点”——显然,一棵树只有一个根节点,最后的、没有再生长出其它节点的节点叫做“叶子节点”,其它的叫分支节点;从一个节点上生长出来其它节点都叫做这个节点的子节点。

这种树结构和族谱的结构非常像:一个老祖宗生了两个儿子,两个儿子分别娶妻,又生了两个儿子……

在默克尔树中,只有叶子节点上记录了最终数据,比如身高172cm,体重62kg,年龄33,性别男……等等。根据这些数据,叶子节点会运用哈希算法——这个名字先记着,后面会有介绍——计算出一个值。这个值就是这个叶子节点的“身份证号”。 哈希算法的特性保证了不同的数据计算出来的结果肯定不一样,这样就可以保证每个叶子节点的身份证号都不同。分支节点和根节点的“身份证号”则是用哈希算法根据它的子节点的“身份证号”计算出来的。由于子节点的“身份证号”都不同,显然各分支节点以及根节点的“身份证号”也不同。

当时写到这里就没继续写了……抽空再补上后续内容吧。