文档介绍:比特币主链上,平均每十分钟会出一个块。随着数字货币的发展,参与的miner数量与日俱增,挖矿技术日新月异,全网的算力也是以惊人的速度增长。BTC中为了保证主链平均的高度增加速度依然维持最初设定,进而设置了挖矿难度调整的功能。深入理解挖矿难度的概念,以及挖矿难度调整的方案,对开发人员以及miner都很重要,因为挖矿难度设置不合理可能会导致全网出块速度极不稳定。本文将详细介绍BTC&BCH挖矿难度及调整方案,我们先从PoW算法讲起。 1、PoW算法PoW(Proof-of-Work)工作量证明算法是一种对应服务与资源滥用、或是阻断服务攻击的经济对策。一般是要求用户进行一些耗时适当的复杂运算,并且答案能被服务方快速验算,以此耗用的时间、设备与能源做为担保成本,以确保服务与资源是被真正的需求所使用。PoW算法具有:去中心化,单向,随机性,目标难度易调整等特点,所以现在包括BTC,BCH在内的很多币种都采用了PoW共识机制。从实现上来说,PoW算法的输入为任意长度,输出为固定长度,比如通常使用SHA256算法对应输出256-bit。在挖矿过程中miner用PoW算法计算整个块头的hash值,由于SHA256的特性:块头任意一位发生变化,得到的hash值会变得完全不一样,而且大小变化方向不确定。于是,我们比较hash值是否小于某个值(实际上这个值是保存在块头中的nBit「解压后」的current_target值)来判断是否满足要求;如果小于,则广播这个区块;如果不小于,则按照当前挖矿节点的规则改变块头中可以改变的值,然后再次计算块头hash值,以此往复,直到结果小于目标值。由此可知,current_target值越小,满足挖矿要求的概率就越小,挖矿难度就越大。 2、块头&Coinbase交易块头的生成:当miner开始新一轮打包之后,首先会创建一个空的块,块结构分为块头以及块信息两部分。先打包块信息,再根据块信息填充块头。首先看一下已经成功打包的块。下图是写本文稿时截取最新的BTCblock详情。块信息存放的是从mempool里取出来的一系列交易信息,miner并以此创建了一个MerkleTree,交易信息的hash值作为leaf,最终生成的MerkleRoot将填到块头里。值得注意的是,交易列表中的第一个是一个非常独特的交易:CoinbaseTransaction。CoinbaseTransaction与普通交易主要的区别有:1)CoinbaseTransaction不消耗UTXO2)input只有一个,叫做Coinbase3)output的addresss为miner的btc/bch地址4)value由挖矿奖励和交易费组成5)更值得注意的是input中没有Unlocking-script,取而代之的是CoinbaseData(这部分数据包含ExtraNonce,在挖矿难度非常高时,将起非常重要的作用)Coinbase交易input的结构如下:Coinbasedata,该字段数据长度范围为2-byte~100-byte:blockheight起初Coinbase是不包含块高度信息,由于重复交易的问题出现,诞⽣了BIP30,随后第二套解决方案BIP34)。BIP34规定Coinbasedata最高字节表示用于表示块高度的数据段的字节数,接下来的字节以⼩端法表示具体的块高度,创世块的高度为0。例如:2013-12-28BTC的一个块的Coinbase解析中coinbasedata为0x03443b04...,则块高度用16进制表示为0x043b44,十进制为277316;extranonce作为中间字段,将会在后续提及的ExtraNonceSolution详细说明作用;上图Coinbasedata中用以结尾的「/P2SH/」是12年miner进行投票支持BTC是采用BIP16还是BIP17的产物,现已弃用。(众所周知,BIP16P2SH获得了更多票数,被BTC采用)在交易信息聚合完毕得到了MerkleRoot之后,接下来填充区块头。块头结构如下(其中nBit就是PoW小节提到的current-target的压缩版):区块头80-byte,一共6个字段:版本号,允许改变但不推荐前一个块的hash值,不允许改变MerkleRoot的hash值,用于存块信息里的交易的MerkleTree的root节点的值,允许改变(改变coinbase中input中的值)时间戳,允许基于MTP11进行调整改变nonce,用于PoW算法的随机值,允许改变nBit,PoW算法结果必须小于这个数对应的current_target才能算块打包成功。这个值是在每一个块开始打包之前就确定了,不允许改变块头中80bytes任意一个值发生改变,PoW的Hash结果就会发生改变。