比特币和区块链

这篇文章根据16年读bitcoin的论文写的笔记扩展而来的。

最近读了这篇关于bitcoin的论文,觉得很有意思。记得还是读大学的时候,有一段时间新闻里比特币炒的特别火热,身边也有同学认识的人很早之前买的比特币小赚了一笔,网上到处都是挖矿的帖子。那时是第一次听说比特币的概念,一直不是很能理解脱离了国家政府发行的货币有什么意义?数字货币又是怎样防止造假的?这背后的技术除了比特币以外还有别的用处吗?

直到读了这篇论文,我大概弄懂了bitcoin的基本流程,这里我想要尝试着回答一下上面的几个问题,如有谬误,欢迎指出。

什么是比特币

认识一个新的事物,先了解一下它的定义。参考wiki,bitcoin是一种全球通用的加密互联网货币,它的主要特点是采用点对点网络开发的区块链技术,实现了去中心化的数字安全货币。

好了,定义就以上这些,如果看这有点头晕没有关系,这是正常的,现在你只用知道每个比特币使用者都有一个数字账户,账户里存放着比特币,比特币是一种去中心化的数字货币,它最主要的用途就是在网上交易。下面我们就来一一了解它会遇到什么问题,又是怎样解决的。

比特币会遇到哪些问题

作为一种货币,虽然是数字没有实体的,它依然会遇到其他货币遇到的问题,比如如何防止被伪造?如何判断重复使用?如何防止别人偷窃你的金钱?

让我一一来看比特币对上面问题的解决方法。

如何防止偷窃?

这个问题比较好解决,只要用到密码学中的非对称加密的概念。每个用户接受比特币的地址由用户的公钥哈希得来,而私钥只有用户自己持有,在每一笔用户的交易上,用户都要用自己的私钥签名,这就是数据签名。收到钱的其他用户可以用公钥验证数字签名是否正确,这样就可以防止别人伪装成自己跟其他人交易了。这样做的缺点就是,一旦私钥被他人获取,就想到于你自己的钱包丢了,里面的钱都被人偷窃走啦。

如何防止被伪造?

那么假设我就是我自己,不是别人伪装的,但是我自己的钱包里没有钱,我想伟钊出一些钱来使用,比如我没有钱但却给张三发出了转账100元的信息,张三如何判断我到底到底有没有这100元呢?

想想现实生活中我们使用的人民币是怎样解决这个问题的?没错,就是给没张钱一个独一无二的序列号。仿照着,我们的比特币也可以这样做,通过一个中心化的类似于银行的节点,为每个比特币发放一个唯一的序列号,用户收到别人的转账后可以这个中心节点查询这次转账的钱是否有效,用户可以向中心节点确认两个信息,一是这个序列号对应的钱是否属于转账者,二是他是否还没有把这张钱花掉。如果这两点都是真的,那么用户就可以确认接受这次转账。

如何防止使用两次(double send)?

如何防止一张钱被使用两次呢?按照有中心节点的上面的做法,比如我有一张100元的钱,我同时给张三和李四发送转账100元的消息,他们都会跟中心节点联系,只有一个人会收到中心节点确认的消息,另外一个人会收到钱已经被使用了的消息,那么他就会拒绝接受这次转账。

看上去上面已经解决了这个问题,那还有什么好说的呢?上面的流程正确的前提是这个中心节点是安全而且可靠的,如果中心节点有意欺骗张三和李四,那么他们都会确认这次转账,这一张100元就被使用了两次。这个才是比特币要解决的问题的大头。

区块链

为了解决上面中心节点不可靠的问题,比特币的发明者直接放弃了中心节点,改为使用p2p。为了验证一次交易是否成功,收到转账的节点会将这次转账信息广播给整个网络,交由网络上的所有节点来判断这次交易是否有效。

那什么是区块链(block chain)呢?区块链是一串使用密码学方法相关系产生的数据块(称为“区块”,block)。新增的数据块总能链接到上一个区块,即整条区块链的尾部。kafka的一个工程师写个一篇文章,其中有提到整个数据库中的数据可以看做一连串日志记录后的结果,在这里比特币点对点网络将所有的交易历史都存储在“区块链”(blockchain)中,所以区块链可以看作记录着比特币交易的账本。区块链就是一个分布式数据,数据存储在每个客户端上,里面有每一张钱交易的所有历史,无需中心节点来分配序列号,一张钱从出生开始的所有流程都在区块链中存在。

一旦一次交易被”确认”,一个区块就被产生,链接在区块链的尾部。这里的关键是如何确定产生一个区块而又不会被伪造,比如如果我们设计的是类似于paxos协议一样,一次交易被整个网络中的大多数节点接受,就会产生一个区块,但是如果伪造者伪造出一大堆虚假的ip地址来冒充节点,就可以绕开其他人的判断,引导接受者确认交易。这里的关键是我们要选择一种伪造者不容易伪造两次的方法。

比特币选择的时计算量。计算量代表了一个机器的计算能力,伪造者只有拥有比一个网络更强更多的计算量才能误导接受者,而这是成本很高很难做到的。

具体的实现细节是,增对每个新增加的区块,需要计算hash的结果,关键是需要计算出的结果中必须要有指定个数的前导零,网络中的节点可以在消息中加上一个数比如10,然后计算hash,看前导零是否满足要求,如果不满足,换一个数再试。这就要求hash函数有足够的安全性,不能被逆向。比特币选的sha-256。

这样的计算没有什么取巧的途径,只能不断计算不能重试,这就需要很强的计算量才行。通过这样的手段,将伪造者挡在了门外。

分叉

其实上面的方法并不能避免区块链的分叉。考虑这样一种情况,如果有两台机器同时计算出了指定前导零的hash,并且同时广播给了网络,网络上的节点验证了计算出的结果是对的就会更新自己的区块链,那么现在网络上的区块链在末尾就有了分叉。

怎么解决这个问题呢?接受它。接受分叉,但是会不停的跟踪两个分叉,只要有一个分叉比另外一个更长,就转到更长的分叉上去。这样做的原理是,永远靠近计算能力更强的分支。

Reference

Bitcoin 论文

How the Bitcoin protocol actually works