前几天跟朋友聊起比特币。朋友问,「比特币是一种实际存在的东西吗?挖矿又是什么,为什么可以获得比特币?」
我说,「比特币是一种去中心化的货币,每个人手中都有一本账本。有人要交易的时候就全网吼一声,『矿工』们通过解决谜题来争取记账的权利并且获得对应的比特币激励。这种通过解谜来获取激励的行为就被形象地称为『挖矿』。」
「我还是不太理解比特币到底是什么。」
「这些谜题由谁来出,奖励又是谁给的?」
我非常能理解这些问题,毕竟比特币不像法定货币一样存在实体,也远没有像支付宝和微信支付那样流行。即便是专业程序员,也未必都了解过比特币的原理。
如果你对比特币的设计感兴趣,又恰好是一名专业程序员,可以通读一遍只有 9 页的比特币的白皮书。如果你像大部分人一样,没有分布式网络和密码学基础,那么要完全理解比特币的工作原理还需要一点点的前置知识。
分布式网络 🔗
你可能听说过 P2P 技术。远到以前的 BT 下载,近到现在的百度网盘和一些视频网站,都有使用 P2P 技术。如果我正在从百度网盘上下载一个文件,恰好张三和李四也通过百度网盘下载过这个文件,那么 P2P 技术就可以让我的百度网盘客户端直接连接张三和李四的客户端,从张三和李四的电脑上分别下载这个文件的一部分。好处当然是可以帮助百度网盘的服务器节约带宽。如果我们恰巧在同一家星巴克蹭网(处于同一个局域网),那么很可能可以享受局域网内的传输速度。
上面说的就是一种分布式网络。每个连接到这个分布式网络中的客户端都是一个节点(peer),节点与节点之间可以互相建立连接并且发现更多的节点。P2P 也就是节点到节点(peer to peer)的简称。如果没有 P2P,我只能从百度网盘的服务器上下载文件,此时百度网盘的服务器就是「中心」节点,一旦中心节点故障,我就无法下载文件了。相对地,分布式网络中每个节点是平等的,没有中心的概念,所以也叫「去中心化」。即便百度网盘的服务器故障了,李四也关机了,只要张三的客户端还开着,我就可以继续从张三的电脑上下载文件。
我们见过的大多交易系统都是中心化的。比如我用支付宝给你转账 ¥100,并不是直接与你建立了连接,而是连接到支付宝的服务器,发起转账的请求。支付宝「中心」完成记账,确保每一笔交易有效。银行卡转账也是类似,银行的服务器就是「中心」。
这种交易模型需要有一个「可信」的中心机构。而比特币的设计目的就是构建一个分布式网络,激励每个节点一起参与记账,去除交易过程中对中心机构的依赖。
记账的本质 🔗
许多人平时有记账的习惯,记录每笔支出的时间、金额和去向。这是从个人的角度出发记账。我们也可以从货币的角度出发,追踪货币的流通。
比如,我用一张 ¥100 纸币从张三那购买了一些东西,张三又用这 ¥100 纸币从李四那购买了一些东西。从货币的角度看,这两宗交易本质上是这张 ¥100 纸币的两次易主。我们可以把这张纸币参与的所有交易按照时间顺序记录下来,形成一条交易链,就可以追踪货币的流通,从而实现记账。比特币也是一样,每个「币」的本质就是一条交易链,或者说是所有权链。
当我们发起比特币交易的时候,实际上是续写这个交易链,在后面追加一个交易。我们只需要在比特币的分布式网络中广播这宗交易的信息,包括这宗交易的上一个交易是哪个(这样才能形成交易链),以及要把币易主给谁,也就是收款方。当比特币网络中的多数节点确认了这宗交易,交易就不可逆地完成了。
李四把币转给王五之后,这个币的所有权链就变成了这样:
证明「我是我」 🔗
每个人都能在比特币网络中广播交易信息。为了验证交易是否由持币人本人发出,广播交易的时候需要证明「我是我」。现实生活中要证明「我是我」,通常是将交易密码告诉支付宝或者银行,由这些中心机构来验证。而比特币网络中的交易信息是广播的,所有节点都能看到,显然不能把密码公诸于世,这一点也不「密码」。
要在数字世界中证明「我是我」,我们可以使用数字签名技术。数字签名的工作原理跟我们在现实中签名完全不同。数字签名是基于密码学中的非对称加密完成的。
传统的加密,比如我们在 Word 中给文件添加密码,或者用 WinRAR 和 7-Zip 给压缩文件添加密码,解密的时候也是使用同一个密码。这种加密和解密共用一个密钥的加密方式称为对称加密。
![](decompress@2x.png)
非对称加密,则是有一对密钥,一个是公开的、用于加密的公钥(public key);另一个是私密的,用于解密的私钥(private key)。想象我是一个无情的树洞,大家希望跟树洞倾诉秘密的时候不被他人窃听,这时就可以用非对称加密。张三和李四分别把他们的秘密用我公布的公钥加密,把加密后的密文告诉了我。因为只有我有私钥,所以只有我能够解密出他们的秘密;张三和李四只有公钥,即便听到了对方说了什么,也没法得知实际的内容。
实现非对称加密的关键在于找到一件对计算机来说正向很容易,但是逆向很难的事情。比如说计算两个非常大的素数 p 、q 的乘积 pq 对计算机来说是一件非常容易的事情;而已知两个随机大素数的乘积 pq,要分解出这两个素数 p 、q 则是一件非常困难的事情,整数分解至今没有高效的算法。
这是一个比较容易理解的例子,实际比特币中使用的非对称加密算法是一种名叫椭圆曲线的加密算法。
利用这种特性,我们可以设计出一种可逆的函数 E,正向计算很简单,但是逆向计算(或者说找到其反函数 D=E-1)非常困难。这样我们就可以公布 E 用来加密,而不需要担心有人可以解密。而知道更多信息的人(比如上面例子中生成 p 、q 的人)则可以轻易求出其反函数 D=E-1,从而轻易解密密文。这种函数叫做陷门函数(trapdoor function),可以想象是一个很深的坑,掉进去容易爬出来难,但只要你有梯子(也就是陷门),就可以很方便地爬出来。私钥就是非对称加密中的「梯子」。
数字签名则是反过来。考虑把加密函数和解密函数互换, E’=D=E-1, D’=E,就可以构造出一种加密很难但解密很容易的算法。私钥的持有者可以用新的加密函数 E’(也就是原来的解密函数)把他想说的话「加密」成一串「密文」,而因为原先的公钥已经昭告天下,所有人都可以用新的解密函数 D’(也就是原来的加密函数)来「解密」这段「密文」。显然,这完全没有加密的效果,但是,由于加解密互换后,只有私钥的持有者才能加密,所以可以证明这段消息是私钥的持有者发出的,从而实现「签名」的效果。当然,实际的签名算法并不是用私钥去「加密」整段消息的,而是先用摘要算法算出整段消息的摘要,再用私钥「加密」摘要,将「加密」结果附在明文的消息之后发送。摘要算法会在后文中提到。