比特币原理细节的温习
一,私钥、公钥与比特币地址
由随机数生成私钥
比特币软件使用操作系统底层的随机数生成器来产生256位的熵(随机性),也就是说首先在1-2256之间生成一个随机数,然后用SHA256算法生成一个256位的二进制数(即64位的十六进制)。
由私钥生成公钥
通过椭圆曲线算法可以由私钥生产公钥,这个过程是不可逆的,也就是说无法通过公钥反推出私钥,这样就保证了私钥的安全性。
由公钥生成比特币地址
比特币地址由公钥通过单向的哈希加密算法(SHA256和RIPEMD160)获得,生成过程:
![](https://img2018.cnblogs.com/blog/762938/201904/762938-20190424165534656-2146443396.png)
钱包:管理私钥的容器
比特币钱包是管理私钥的容器。比特币钱包只包含私钥,没有包含比特币,用户用私钥来签名交易,从而证明他们拥有交易输出,比特币是以交易输出的形式存储在区块链中。
二,交易
当我们说用户的钱包已经“收到”比特币时,我们的意思是,钱包已经检测到了可用的UTXO。 因此,用户的比特币“余额”是指用户钱包中可用的UTXO总和,而他们可能分散在数百个交易和区块中。 “一个用户的比特币余额”,这个概念是比特币钱包应用创建的派生之物。比特币钱包通过扫描区块链并聚集所有属于该用户的UTXO来计算该用户的余额 。大多数钱包维护一个数据库或使用数据库服务来存储所有UTXO的快速参考集,这些UTXO由用户所有的密钥来控制花费行为。
一个UTXO可以是1“聪”(satoshi)的任意倍数(整数倍)。就像美元可以被分割成表示两位小数的“分”一样,比特币可以被分割成八位小数的“聪”。(比特币的最小单位虽然是「聪」,但基本单位却是「UTXO」,别搞混了。)尽管UTXO可以是任意值,但一旦被创造出来,即不可分割。这是UTXO值得被强调的一个重要特性:UTXO是面值为“聪”的离散(不连续)且不可分割的价值单元,一个UTXO只能在一次交易中作为一个整体被消耗。
交易过程
上图中的输入1-4,在交易前,是4个独立的UTXO;而输出1-3,是新产生的3个独立的UTXO,可以作为下次交易的输入。
签名
每个UTXO都对应某个比特币地址,只有这个比特币地址对应的私钥才能对这个UTXO进行签名,使其作为下一次交易的输入。
所以,当比特币钱包显示某个比特币地址总金额时,其实它是统计该地址对应的所有UTXO,只有这个地址对应的私钥才能使用(消费)这些UTXO,所以务必保存好你的私钥。
找零
UTXO是比特币交易的最小单位,也就是说它不可分割。但是在现实中,如果比特币作为一种支付货币,难免会面临找零的情况,它是怎么处理的呢?
其实很简单,就是把自己的地址也作为交易输出的一部分。举个例子,假设张三需要支付1.5个BTC给李四,但是当前张三所拥有的最小UTXO为1.8个BTC,也就是说需要找零0.3个BTC,那么这个交易的输入为张三的1.8个BTC,输出为李四的1.5个BTC和张三的0.3个BTC。
交易费
一般比特币交易的输入总额不等于输出总额,其中的差额就是交易费。为什么会有交易费呢?后续我在介绍挖坑的原理中会详细介绍,这里你只要简单知道这个交易费是给矿工奖励的就行,因为比特币的交易需要依赖于矿工挖矿确认,而矿工确认的优先级是根据交易费大小排序的,因此谁出的交易费越高,谁的交易就越有可能被尽早确认。大家知道,比特币被人诟病的其中一个主要问题就是交易性能很差,TPS(即每秒交易笔数)大概为7左右,远远低于银行网关,更别提支付宝、微信支付了。
挖矿的奖励(Coinbase交易)
每个区块的第一个交易比较特殊,它没有输入,也就是说是凭空产生的(大家可以想象下印钞机),叫做Coinbase交易,它是给挖矿者的奖励,金额从50BTC开始,每4年递减,目前是12.5BTC。
三,网络
比特币采用去中心化的P2P(点对点)的网络架构,所谓P2P是指网络中的每个节点都是对等的,不存在「特权」节点,这也是比特币「去中心化」的底层实现。
虽然比特币P2P网络中每个节点是对等的,但根据其功能不同,分为如下几种节点类型:
![](http://upload-images.jianshu.io/upload_images/11226944-e254ca981432f333.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp)
网络路由节点
拥有网络路由功能的节点都可以作为网络路由节点,所有的网络路由节点通过TCP协议连成一张巨大的P2P网络。
这里需要注意,对于单个节点来说,它并不需要与其它所有节点建立直接连接,否则性能会成为瓶颈,它只需要跟其相邻的几个节点建立直接连接即可,和其它节点是间接连接。
全节点
全节点是指包含完整区块链数据库的节点,我们知道比特币从2009年1月诞生以来,平均每10分钟产生1个区块,目前为止已经产生了51万个区块,至少需要占用150G的磁盘空间。比特币刚诞生的时候,区块链数据库很小,大部分都是全节点,但随着区块链数据库越来越大,全节点的比例在不断缩小。
简单支付验证(SPV)节点
对于跑在智能手机上的钱包客户端来说,下载整个区块链数据库肯定是不可行的。于是,简单支付验证(SPV)节点孕育而生,SPV节点只需要下载区块头,不用下载区块体(即交易信息),因此它占用的空间大大减少。
独立矿工节点
所谓独立矿工节点是跟矿池相对立,是指不依赖其它节点的算力、单独进行挖矿的节点,因此它拥有完整的区块链数据库。在比特币前期,由于全网的算力不大,独立矿工还有生存空间,但随着比特币价格一路攀升,全网算力越来越大,独立矿工节点的生存空间越来越小,除非是大的数据中心。
矿池及其挖矿节点
前面说过,随着比特币全网算力越来越大,独立矿工挖到矿的概率越来越小,因此就产生了矿池。所谓矿池是指很多个挖矿节点集合在一起组成挖矿联盟,如果挖到矿,所获得的收益根据挖矿节点贡献的算力分摊,当然矿池还会收一部分管理费。这个挖矿联盟一般基于Pool或Stratum协议。
综上所述,比特币网络架构如下图所示:
![](http://upload-images.jianshu.io/upload_images/11226944-63c01f9d15edd055.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp)
四,挖矿
比特币挖坑的过程简单说就是:矿工使用挖矿节点尝试解一道数学难题,谁先解出来谁就能获得新产生的比特币和交易费。具体过程如下:
整合交易至候选区块
挖矿节点不断监听比特币网络中的交易信息,并将这些交易信息暂存到自己的内存池里,挖矿节点会根据以下信息对这些交易进行排序:
1)优先选择「块龄」更大的交易,「块龄」是指自该交易被记录到区块链为止所经历过的区块数,即这个交易在区块链中的深度。简单说,就是会优先处理那些旧的交易,这样确保即使没有交易费的交易最终也能得到确认,只是要等的时间比较长一些。
2)优先选择相对交易费更高的交易,也就是说出的交易费越高,越有可能越快得到确认。因此如果你想你的交易被尽快确认,应该主动多付些交易费。
挖矿节点根据上述条件排序后生成候选区块,同时会在候选区块里加入一笔特殊的交易-「Coinbase交易」,该交易是候选区块的第一笔交易,它会把新产生的比特币(当前是12.5个)和交易费发送给矿工的地址,是给矿工挖矿的奖励。
求解数学难题使候选区块成为合法的新区块(PoW)
构建候选区块完毕后,矿机就要开始使用PoW(Proof of Work,工作量证明)算法来获得一个正确的nonce值,来向全网证明新区块是它挖的。
所谓的PoW算法其实并不复杂,假设你是一个矿机,你会不断的尝试改变nonce值,并计算区块头的哈希值,如果你足够幸运,算出的哈希值正好小于难度值,说明你的这个nonce值是有效的,表示你成功挖到矿了,于是你会迅速的向全网广播,告诉大家这个区块我已经挖到了,你们继续挖下一个吧。但现实更多的情况是,你尝试了成千上亿次后,还是没有猜出有效地nonce值,却收到了其它矿工发来的通知说他已经挖到了,于是你只好放弃之前的所有工作,继续尝试挖下一个区块。上述描述的整个过程大概每10分钟会重复一次,生生不息,永不停止。
看到这里,相信很多人会有以下两个疑问。
第一个疑问是「我难道只能不断尝试不同的nonce值这种暴力破解的笨办法吗?是否存在更好的办法呢?」。数学家已经证明没有比暴力破解更好的办法,所以这也是很多人诟病比特币不环保、空耗大量算力的原因,但这也是比特币能够维持一个去中心化共识的根本原因。
第二个疑问是「难度值是如何确定的?」。比特币为了确保平均每10分钟出个新区块,它必须能够动态调整难度值,起初由于全网算力很小,因此难度值也比较小,但随着全网算力越来越大,难度值必须不断动态增大才行。但大家知道比特币是去中心化的,也就是说从来没有一个中心可以动态调整难度值,那比特币是怎么做到的呢?它把难度值的调整交给了每个全节点(什么是全节点可参考「比特币(4):网络架构」),具体是这样的:每2,016个区块调整一次难度值,难度的调整公式是由最新2,016个区块的真正花费时长与20,160分钟(两周,即这些区块如以10分钟速率所期望花费的时长)比较得出的,如果发现平均时长小于10分钟,说明之前的难度值过小,需要加大难度,反之亦然。
区块链分叉
上述描述的基于PoW算法的挖矿过程可能会产生这样一种状况:假设矿工A挖到了新区块,但由于比特币的节点分布在全球各地,网络传输需要一定的时间,所以在他向全网广播的过程中,正好又有一个矿工B挖到了新区块,他也会向全网广播他挖到的新区块,这时就会出现两个新区块互相竞争的情况,这就是区块链分叉。
那么比特币是怎么解决分叉的问题呢?答案是暂时不解决,就让分叉存在着,相信时间最终来解决。也就是说,这时候比特币网络被分成了两派,一派基于A继续挖新区块,另一派基于B继续挖新区块,随着时间的推移,一定会出现其中一个分叉成为主链,另外一个分支慢慢被放弃。注意:这里谁能成为主链,并不是简单的基于谁先挖到算谁的,而是谁后续能获得大多数节点的认可。
这样又会带来两个问题:
问题1:有可能导致已被确认的交易被取消。比如上述例子我们假设A成为了主链,B被抛弃了,那么B挖到的这个新区块,虽然已被确认是有效的,但由于不是主链,最终会被抛弃,也就是说B创建的这个新区块上的交易都失效了。这也是为什么虽然比特币平均每10分钟生成一个区块,但一个交易真正被确认需要60分钟,因为一般认为经过后续6个区块的确认后,基本就很难被取消了。
![](http://upload-images.jianshu.io/upload_images/11226944-86d90d6b73dac87d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/640/format/webp)
问题2:有可能受到51%的算力攻击。假设有个人或机构非常强大,他能控制比特币全网51%的算力,就可能随意强行分叉,并让他的链总是成为主链,那么比特币的共识就崩溃了。虽然理论上存在这样的可能性,但由于现在比特币全网的算力过于强大,想要控制51%的算力,几乎不可能