文章抛开技术的实现细节,着重讲解比特币如何解决分布式存储带来的一致性问题,若是读者已经对区块链的分布式存储和同步的原理和解决方案很是清楚,为了避免浪费读者的时间,能够忽略。html
为了不读者缺乏对比特币、区块链、挖矿知识点的了解而产生过多的疑惑,文章前小部分专门为这部分读者准备,经过简单了解比特币是什么?区块链是什么?挖矿的原理,方便部分读者消化接下来的知识点,但愿能够给读者一些收获,若是发现本人有理解不对的地方,或者有须要补充的地方,欢迎评论交流。算法
2008 年中本聪发表了一篇《比特币:一种点对点式的电子现金系统》(Bitcoin: A Peer-to-Peer Electronic Cash System)论文,它在论文中构思出比特币的雏形(建模),描述了一种去中心化、对等式、基于数学和密码学构建的加密货币——比特币。正因为这个革命性的发明,2015 年,加州大学洛杉矶分校金融学教授 Bhagwan Chowdhry 曾提名中本聪为 2016 年诺贝尔奖经济学奖的候选人。数据库
2009 年中本聪发布了首个比特币软件,并正式启动了比特币金融系统,截止至今日(2018-02-16)1 BTC ≈ ¥6.4万,最高时 1 BTC ≈ ¥12万,最低 1 BTC ≈ ¥0.4。安全
若是你问目前挖矿还来得及吗?那咱们先来看一组数据。网络
该系统截止至 2018-02-15 08:00:00,已经有 16,867,188 个比特币被挖出,占总发行量 2100 万的 80.3%,只剩下不到 20% 的比特币未被开采,因此如今才想去出挖矿有点为时已晚。并发
比特币去中心化底层采用的技术就是区块链,其本质是一个分布式数据库,用于存储每一笔比特币交易记录。比特币网络仅仅承认和维护比特币网络上每个节点存储着的那条彻底相同且长度最长的区块链,全部通过检验并符合要求的交易记录都会被“矿工”打包成进区块,而后发送给比特币网络上全部的客户端节点,客户端节点检查区块没有问题以后,将区块链接起来串成一条链,这条链很形象的就被称为区块链。分布式
区块是由比特币网络上被称为“矿工”的节点所生成,他们负责接收到网络上的全部的比特币交易记录,逐个检查这些交易记录是否符合要求,好比检查每条记录是否有正确的数字签名,交易是否重复使用等等;而后将符合要求的交易记录添加到本身增长制做的新区块中。函数
中本聪为了让添加区块的变得困难,当“矿工”成功制做好这个新区块时,还须要完成两个额外的工做。区块链
字符串 = 前一个区块的SHA256函数值 + 新区块的基本信息 + 新区块的全部交易记录
。SHA256(字符串 + 随机数)
知足某个 256 位的二进制 Hash 值(好比知足 Hash 值的前 n 位为 0,当 n = 50,计算出这个随机数的几率就是 1 / (2 的 50 次方))。经过设置 n
的大小便可改变随机数被计算出来的几率,致使第二点的难度很是高,高到比特币网络平均每 10 分钟才会有一个矿工产生一个新区块;随着如今挖矿设备不断的升级,计算 hash 值的速度也愈来愈快,目前该难度值控制在每产生 2016 个区块(两个星期)就会动态改变一次,使得整个比特币网络平均每隔 10 分钟才会计算出一个符合要求的随机数。加密
当矿工计算出这个随机数以后,立刻把这个随机数添加到新区块中,立刻把这个新区块发送给比特币网络上的各个客户端节点,各个节点检查没问题以后就会把这个区块添加到本身的区块链的尾部,这样子矿工才有可能获得比特币的奖励。
对于比特币来讲,每一笔转帐记录都表明着“钱”,它是系统运行的基础,若是把交易记录保存在一台电脑上,当电脑发生故障时,那么整个交易系统将瘫痪没法正常运行,因此这种作法不具有高可用性;交给专业的值得信赖的公司管理和维护?好比银行,那么谁能保证公司或我的在巨大的金钱诱惑下或在他人的威胁下,不会篡改交易记录呢?中本聪发明比特币的其中一个目的,就是消除对银行等经融机构的依赖。因此比特币采用的方案是,将每一条比特币转帐信息都发送到网络上,让全部运行比特币客户端的计算机都存储全部的比特币交易信息,这样,每一条记录都会被不少计算机存储,不用担忧记录缺失,而这样会带来三个一致性方面的问题:
若是一部分客户端没联网、没有登陆比特币客户端或者电脑关机,致使没有接收到交易记录,那交易记录确定是没有被这部分计算机存储的,这样不一样计算机上面的比特币交易记录就会不一致,那到底以谁为准?如何让他们互相同步从而储存相同的交易记录呢?
若是黑客篡改了网络上某个节点的一条或多个交易记录,致使比特币网络上的多个节点的交易记录不一致,甚至出现交易信息先后矛盾的问题,从而致使比特币网络没法运行,那么如何保证交易记录不被篡改呢?
假设只有 S 转帐 10BTC 给 A,而且交易记录已经获得验证且有效,此时 A 帐号中只有 S 转帐给他的 10 BTC,而 A 几乎同时向 B 和 C 帐号转入 10 BTC,以下表格:
序号 | 交易记录 | 数字签名 |
记录1 | “S帐号”支付10BTC给“A帐号” | S用本身的私钥加密【SHA-256(“S帐号”支付10BTC给“A帐号”)】 |
记录2 | “S帐号”支付10BTC给“A帐号” -> “A帐号”支付10BTC给“B帐号” | A用本身的私钥加密【SHA-256(“S帐号”支付10BTC给“A帐号” -> “A帐号”支付10BTC给“B帐号”)】 |
记录3 | “S帐号”支付10BTC给“A帐号” -> “A帐号”支付10BTC给“C帐号” | A用本身的私钥加密【SHA-256(“S帐号”支付10BTC给“A帐号” -> “A帐号”支付10BTC给“C帐号”)】 |
因为地域问题和网络等问题,不一样矿工节点先接收到的交易记录可能会发生这样的状况
不一样的客户端先接收的比特币交易记录不一致,而客户端只承认最早接收到的交易记录是有效的,好比记录 2 先被接收,则记录 3 做废,同理,记录 3 先被接收,则记录 2 做废,不一样计算机对同一交易记录的有效性产生分歧,致使不一样节点的交易记录不一致要如何解决呢?
比特币底层使用区块链技术解决一致性问题,那它是如何解决的呢?下面开始讲解区块链如何解决上面提到的三个一致性问题。
区块链会被存储在网络上每个节点中(客户端),若是你有一个比特币交易的客户端,一段时间没有联网以后再次链接到网络,客户端会自动向网络中的其它节点发起同步本身没有的区块的操做,检查无误以后才逐一把区块添加到本身的区块链上。
这样,每个启动并联网的客户端都会同步全部的比特币交易记录了。而检查的过程是十分严格的,包括了每一区块中每一笔的交易记录是否符合要求,区块间的交易记录是否符合要求,下个区块是否包含上一个区块的 SHA-256(上个区块的全部记录) 值,检查区块是否符合要求等。
在讲解区块链如何防止交易记录被篡改以前,咱们有必要了解一下区块链中关于区块的基础知识。
在区块链中,每一个区块能够当作由消息头和消息体组成。
区块链中的每个区块都会包含上一个区块的 Hash 值,构成以下图:
这里的 Hash 值其实就是一种散列函数,比特币中使用的 Hash 函数是 SHA256。只要给定一个输入值 x, 就能够获得一个固定长度的输出值 H(x) ,例如字符串 123
输入到 SHA256 hash 函数的值为:
SHA256("123") = a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3
将返回值转换成 256 位的二进制数:
1010011001100101101001000101100100100000010000100011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
该算法目前尚未存在有效的破解手段,因此是安全的。
到这里能够开始讲解防篡改问题了,当交易记录被存放到区块中,而且这个区块被加入到区块链上,那么这个区块中的全部信息都是不可修改,一旦修改,就会出现先后 hash 不一致,致使区块链断裂。
除非恶意的节点总数的 CPU 算力比诚实节点总数的 CPU 算力还要强,那才有可能被“坏人”得逞,由于他能够依靠本身的算力,将节点以后的全部区块从新打包并发布到比特币网络上全部的节点,最终成为那条最长的区块链从而被比特币网络所承认。
然而这种状况几乎是不可能的,第一,由于比特币每次打包区块,都须要完成一个难度很是高的工做,这个工做就是猜随机数,专业术语叫作工做量证实(Proof-of-Work,PoW),难度随着矿工算力的总和动态变化的,比特币网络经过使用这个策略,让全网平均每 10 分钟只会产生一个新区块,限制了恶意节点批量修改区块的可能性;第二,比特币通过了 8 年时间的发展,随着比特币价格的攀升,愈来愈多的矿工加入到“挖矿”当中,这使得比特币网络算力不断加强,想要超过全网的算力总和的可能性微乎其微。
为了解决防止篡改问题,比特币也付出了很是大的代价,它让全网几乎全部的算力都花在了计算错误的 hash 上,致使了很是多的资源浪费。
中本聪在他的论文中提到:
We propose a solution to the double-spending problem using a peer-to-peer network. The network timestamps transactions by hashing them into an ongoing chain of hash-based proof-of-work, forming a record that cannot be changed without redoing the proof-of-work.
大体意思:中本聪提出经过对等式网络(peer-to-peer network)来解决双重支付(double-spending) 问题。网络上的交易记录按照时间的前后顺序(这个时间是由矿工记帐时决定的)被散列成一个持续的基于Hash的工做证实,造成一种不从新验证(hash),就没法更改记录的工做证实链。
严格来说,对等式网络 + 时间戳 + Hash 才是解决双重支付的主要手段,而区块链只是它们的存储形式而已。
知道双重支付的解决方案,在讲解解决双重支付原理以前,还须要知道一个知识点,比特币软件是如何计算用户的余额(剩下多少可用的比特币)?
在比特币中,计算某个钱包余额的过程,是经过计算这个钱包地址的全部相关的转帐记录,来得出这个钱包地址对应还剩多少比特币未被使用。
举例说明如何计算 A 钱包的余额:
序号 | 交易记录 | 数字签名 |
记录1 | “S帐号”支付10BTC给“A帐号” | S用本身的私钥加密【SHA-256(“S帐号”支付10BTC给“A帐号”)】 |
记录2 | “S帐号”支付10BTC给“A帐号” -> “A帐号”支付10BTC给“B帐号” | A用本身的私钥加密【SHA-256(“S帐号”支付10BTC给“A帐号” -> “A帐号”支付10BTC给“B帐号”)】 |
记录3 | “S帐号”支付10BTC给“A帐号” -> “A帐号”支付10BTC给“C帐号” | A用本身的私钥加密【SHA-256(“S帐号”支付10BTC给“A帐号” -> “A帐号”支付10BTC给“C帐号”)】 |
假设有上面的比特币转帐记录,而且交易记录时有效的,比特币客户端经过计算 A 钱包相关的每一笔交易记录的输入(接收 BTC 转帐记录)和输出(消费 BTC 转帐记录)值来得出 A 钱包所剩可用的比特币数量,以下表格:
钱包 | 转帐 | 可用比特币 |
A | +10 BTC | 10 BTC |
A | -10 BTC | 0 BTC |
A | -10 BTC | -10 BTC |
上面的 -10 BTC 只是为了演示计算比特币的过程,真正的比特币中不可能会出现这种状况。
了解余额计算原理以后再回头来看看,区块链如何解决双重支付问题。
这个过程当中可能会出现三种状况:
综上所述,比特币网络老是有办法知道你把一分钱花两次,因此双重支付是不可能的。