导语:本课堂用通俗易懂的系列内容为大家呈现区块链与密码学领域相关知识。这里有知识也有故事,从感兴趣到有乐趣,全民课堂等你来学。这个系列中的课程内容首先从比特币着手进行入门介绍,再延伸至区块链的相关技术原理与发展趋势,然后深入浅出地依次介绍在区块链中应用的各类密码学技术。欢迎大家订阅本公众号,持续进行学习。
【本课堂内容全部选编自PlatON首席密码学家、武汉大学国家网络安全学院教授、博士生导师何德彪教授的《区块链与密码学》授课讲义及互联网,版权归属其原作者所有,如有侵权请立即与我们联系,我们将及时处理。】
1.5 比特币的挖矿
如何优雅地获得你人生中第一枚比特币?这是一个值得思考的问题。我们在第二堂课的时候简单讲过挖矿对于比特币价格和走势的影响,以及挖矿周边衍生出的各行各业。今天我们详细说说挖矿原理。
“挖矿”成功即是该节点成功获得当前区块记账权,也就是说其他节点就“照抄”该挖矿成功的节点的当前区块。获得记账权的节点会获取一定数量的比特币奖励,以此激励比特币网络中的所有积极参与记账工作。该奖励包含系统奖励和交易手续费两部分,系统奖励则作为比特币发行的手段。
最初每生产一个“交易记录区块”可以获得50比特币的系统奖励,为控制比特币发行数量,该奖励每4年就会减半,到2140年会基本发放完毕,最终整个系统中最多的只能有2100万个比特币。如果按照目前比特币的价格计算,比特币的总价值将在2000亿美金左右。
注:价格取自2020年5月30日13:35
比特币系统大约每10分钟会记录一个数据块,这个数据块里包含了这10分钟内全网待确认的部分或全部交易。所谓的“挖矿”,就是争夺将这些交易打包成“交易记录区块”的权利。比特币系统会随机生成一道数学难题,后续会详细描述该数学难题,所有参与挖矿的节点一起参与计算这道数学难题。首先算出结果的节点奖获得记账权。
每个节点会将过去一段时间内发生的、尚未经过网络公认的交易信息进行收集、检验、确认,最后打包并加签名为一个无法被篡改的“交易记录区块”,并在获得记账权后将该区块进行广播,从而让这个区块被全部节点认可,让区块中的交易成为比特币网络上公认已经完成的交易记录,永久保存。
挖矿最主要的工作就是计算上文提到的数学难题,最先求出解的矿工即可获得该块的记账权。在介绍这个数学难题前,先简单介绍一下哈希算法。哈希算法的基本功能概括来说,就是把任意长度的输入值通过一定的计算,生成一个固定长度的字符串,输出的字符串即为该输入的哈希值。比特币系统中采用SHA-256算法,该算法最终输出的哈希值长度为256bit。
1.5.1
挖矿的原理
讲到挖矿原理,首先我们要了解一种“植物”——Merkle树
比特币科普之Merkle树是什么树?
Merkle树通常称为Merkle Hash Tree,是数据结构中所说的树,常用于高效汇总和验证大数据集的完整性.具有以下特点:
① 默克尔树常见的结构是二叉树,但它也可以是多叉树,它具有树结构的全部特点。
② 默克尔树的基础数据不是固定的,因为它只要数据经过哈希运算得到的hash值。
③ 默克尔树是从下往上逐层计算的,就是说每个中间节点是根据相邻的两个叶子节点组合计算得出的,而根节点是根据两个中间节点组合计算得出的,所以叶子节点是基础。
比特币中每个区块生成时,需要把上一个区块的哈希值、本区块的交易信息的默克尔树根、一个未知的随机数(nonce)拼在一起计算一个新的哈希值。为了保证10分钟产生一个区块,该工作必须具有一定难度,即哈希值必须以若干个0开头。哈希算法中,输入信息的任何微小改动即可引起哈希值的巨大变动,且这个变动不具有规律性。因为哈希值的位数是有限的,通过不断尝试随机数nonce,总可以计算出一个符合要求的哈希值,且该随机数无法通过寻找规律计算出来。这意味着,该随机数只能通过暴力枚举的方式获得。挖矿中计算数学难题即为寻找该随机数的过程。
哈希值由16进制数字表示,即每一位有16种可能。根据哈希算法的特性,出现任何一个数字的概率是均等的,即每一位为“0”的概率为1/16.要求某一位为“0”平均需要16次哈希运算,要求前n位为“0”,则需要进行哈希计算的平均次数为16的n次方。矿工为了计算出该随机数,需要花费一定的时间进行大量的哈希运算。某个矿工成功计算出该随机数后,则会进行区块打包并全网广播。
其他节点收到广播后,只需对包含随机数的区块按照同样的方法进行一次哈希运算即可,若哈希值以“0”开头的个数满足要求,且通过其他合法性校验,则接受这个区块,停止本地对当前区块随机数的寻找,开始下个区块随机数的计算。
随着技术的发展,进行一次哈希计算速度越来越快,同时随着矿工的逐渐增多,算出满足哈希值以一定数量“0”开头的随机数的时间越来越短。为保证比特币始终按照平均每10分钟一个区块的速度出块,必须不断调整计算出随机哈希计算的平均次数,即调整哈希值以“0”开头的数量要求,以此调整难度。比特币中,每生成2016个区块就会调整一次难度,即调整周期大约为两周(2016x10min=14天)。也就是说,对比生成最新2016个区块花费的实际时间和按照每10分钟出一个块生成2016个块的期望时间,若实际时间大于期望时间则降低难度,若实际时间小于期望时间则增加难度。
同时,为防止难度变化波动太大,每个周期调整幅度必须小于一个因子(当前为4倍)。若幅度大于4倍,则按照4倍调整。由于按照该幅度调整,出块速度仍然不满足预期,因此会在下一个周期继续调整。
1.5.2 矿池的原理
随着区块链的日渐火爆,参与挖矿的人越来越多,按照比特币原本的设计模式,只有成功打包一个区块的人才能获取奖励。如果每个矿工都独立挖矿,在如此庞大的基数下,挖矿成功的概率几乎为0,只有一个幸运儿可以获取一大笔财富,其他矿工投入的算力、电力资源就会白白亏损。或许投入一台矿机,持续挖矿好几年甚至更久才能挖到一个区块。
为了降低这种不确定性,矿池应运而生。假如有10万矿工参与挖矿工作,这10万矿工的算力和占这个网络的10%,则这10万个矿工中的某个矿工成功挖到下个块的概率即为1/10。即平均每个矿工成功挖到下个区块的概率为1/1000000,即平均每个矿工要花费19年可以成功挖到一个区块,然后获得相应的比特币奖励。这种挖矿模式风险过大,几乎没人可以承受。但是假设这10万个矿工共同协作参与挖矿,则平均每100分钟即可成功挖到一个区块,然后按照每个矿工提供的算力分配该次收益。这10万个矿工的收益也会趋于稳定。
协调矿工进行计算的思路也非常简单,矿池将打包区块需要的交易等信息验证完成后发送给矿工,然后降低矿工的挖矿难度。比如某个时段比特币系统需要哈希值“0”开头的个数大于50个,矿池可以将难度降低到40个“0”开头,矿工找到一个40个“0”开头哈希值的方案后,即可提交给矿池。矿池收到一个满足哈希值“0”开头个数大于50个的方案时,即可提交至比特币网络。
当然,你也许会想:如果矿工计算得到一个“0”开头个数大于50的哈希值后,则直接提交给比特币网络,独享该区块的收益;如果计算得到一个“0”开头数在40到50之间的则提交到矿池,享受整个矿池分配的收益。该方案当然是行不通的,因为区块内容是由矿池发送给矿工的,即受益者地址已经包含在该区块中了,即使直接提交,最终受益的也是矿池。如果修改该地址,即意味着区块内容改变,则前面计算的哈希值也无效了。最后矿池按照矿工提交方案数量计算贡献的算力,最后根据算力分配收益。
当前的主流挖矿协议是stratum,以前还有GBT(getblocktemplate)、getwork等几种协议,它们都过时了。可以用免费的Cpuminer软件把协议调通。
软件地址为:
https://sourceforge.net/projects/cpuminer/files
接下来我们看看挖矿的具体流程吧~
1、客户端首先向服务器发送subscribe指令
{“id”: 1, “method”: “mining.subscribe”, “params”: [“cpuminer/2.5.0”]}
参数中指名矿工软件的名称和版本号。
2、服务器端返回信息
比特币挖矿实际上就是去寻找随机数nonce,有时所有的随机数都试遍了,仍无法满足目标,就需要用到extra nonce。
3、客户端发送认证信息
用户名是钱包的地址,我这里使用的是比特币测试网络的地址,并没有以1开头。
4、服务器返回true,表示用户验证通过
{“id”:2,”result”:true,”error”:null}
5、服务器端发回难度设置消息
{“id”:null,”method”:”mining.set_difficulty”,”params”:[8]}
6、服务器发送通知消息
矿工可能用到了多线程,所以需要job id来区分不用的线程,后面是一堆用于区块生成的信息。
7、客户端发现一个nonce,提交给服务器
8、服务器返回结果
返回true表示服务器认可客户端的工作。
今天的课程就到这里啦,下一期的内容可以用热血沸腾来形容,比特币的“分叉大战”即将上演,敬请期待!
本文转载自https://mp.weixin.qq.com/s?__biz=MzUzNTg2ODg5MQ==&mid=2247487481&idx=1&sn=37abc2de3b062724d22b4144b1cae44d&chksm=faffab4dcd88225b5458a787ffefdbef48c3608419c85d88fec0d74448ed686ed5ef82b8f102&scene=178&cur_album_id=1411898566347735044#rd