想知道更多关于区块链技术知识,请百度【链客区块链技术问答社区】链客,有问必答!!
比特币的出块时间是10分钟左右。每个区块内包含最多8笔交易,这些交易需要被验证和确认,才能实现账户代币的转移。每个挖矿节点做的工作就是去验证和确认这个区块,使区块内的交易得以实现。而他们用的算法就是pow。pow计算的是一个数学运算难题,矿工们首先验证要挖坑区块的合法性,如果合法,他们就开始计算本次挖矿的数学难题,谁第一个做出来并且广播出去,告诉其他矿工我做出来了,你们不用做了。其他矿工们验证你的计算结果和对应的区块,如果大部分的矿工认同你的结果,那么他们将停止挖坑并同步你的数据。区块内的所有交易也就得到认可,实现转账。你的成功挖矿会被比特币激励模块记录,并会给你发送比特币奖励金。
pow算法主要寻找一个随机数(Block里的Nonce值)作为输入,通过改变这个输入,使Block数据不重复变化,Hash函数(一般是sha256)不断计算这个改变后Block的hash值,找出一个特定格式哈希值的过程(即要求有一定数量的前导0),这里找到的值就是当前hash值 < 目标值(Bits),只不过这个比较是在2进制的格式下比较运算的,也就是比较2进制后数字前面0的个数。这个过程就是pow运算过程。而要求的前导0的个数越多,代表难度越大。在将pow算法之前,先学习下区块信息。
区块
如下图所示从图上可知,比特币区块结构分为区块头和区块体,区块体保存交易的具体信息,由它生成的hash保存在区块头里。其中区块头细分为:
父区块头哈希值:前一区块的哈希值,使用SHA256(SHA256(父区块头))计算。版本(Version):区块版本号,表示本区块遵守的验证规则 。
时间戳(Timestamp):该区块产生的近似时间,精确到秒的UNIX时间戳,必须严格大于前11个区块时间的中值,同时全节点也会拒绝那些超出自己2个小时时间戳的区块。
目标值(Bits):该区块工作量证明算法的难度目标,已经使用特定算法编码。
随机数(Nonce):为了找到满足难度目标所设定的随机数,为了解决32位随机数在算力飞升的情况下不够用的问题,规定时间戳和coinbase交易信息均可更改,以此扩展nonce的位数。
Merkle根(MerkleRoot):该区块中交易的Merkle树根的哈希值。矿工收到计算过的区块,会跟自己的区块进行比较,其中Merkle root就是比较它们包含的交易是否一样。
区块头里的所有信息拼接成一个新的字节数组,pow函数运算的参数就是这个字节数组。函数运算是采用SHA256(SHA256())计算。
var genesisBlock = wire.MsgBlock{Header: wire.BlockHeader{ Version: 1, PrevBlock: chainhash.Hash{}, // 0000000000000000000000000000000000000000000000000000000000000000 MerkleRoot: genesisMerkleRoot, // 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b Timestamp: time.Unix(0x495fab29, 0), // 2009-01-03 18:15:05 +0000 UTC Bits: 0x1d00ffff, // 486604799 Nonce: 0x7c2bac1d, // 2083236893},Transactions: []*wire.MsgTx{&genesisCoinbaseTx},
}
Pow三要素1.Hash函数:在比特币中使用的是SHA256算法函数,是密码哈希函数家族中输出值为256位的哈希算法。2.区块头 Hash函数运算需要的参数,也就是区块头的所有信息字节拼接后的字节数组。
3.目标值(Bits) 每一个区块会用一种压缩的格式(被称为“Bits”)来表示实际的16进制的目标值。通过这个值和系统中其他常量可计算出该难度值下的难度目标值。Hash函数运算出来的结果与目标值进行比较大小,如果小,则表示挖坑成功,否则继续运算。比较大小时为使运算速度快速,目标值和hash值都会转换成2进制,所以比较大小就是比较前导0的个数。比特币是每隔2016个区块后调整难度值。
pow挖矿的难度与目标值成反比,如果Bits的实际值增大,那么挖矿容易点;反之,挖矿难度加大。比特币pow挖矿及共识流程
比特币挖矿的过程如下:构建一个空区块,称为候选区块
从内存池中打包交易至候选区块构造区块头,填写区块头的下述字段 1)填写版本号version字段 2)填写父区块哈希prevhash字段 3)用merkle树汇总全部的交易,将merkle root的哈希值填写至merkle root字段 4)填写时间戳timestamp字段 5)填写目标值Bits字段开始挖矿。挖矿就是不断重复计算区块头的哈希值,修改nonce参数,直到找到一个满足条件的nonce值,也就是该nonce值下,hash函数运算出来的hash值 < Bits。当挖矿节点成功求出一个解后把解填入区块头的nonce字段。这时一个新区块就成功挖出了,然后挖矿节点会做下面这些事: 1) 按照标准清单检验新区块,检验通过后进行下面的 2)和 3)步骤 2)立刻将这个新区块发给它的所有相邻节点,相邻节点收到这个新区块后进行验证,验证有效后会继续传播给所有相邻节点。 3)将这个新区块连接到现有的区块链中,按照如下规则: 根据新区块的prevhash字段在现有区块链中寻找这个父区块, (Ⅰ) 如果父区块是主区块链的“末梢”,则将新区块添加上去即可; (Ⅱ) 如果父区块所在的链是备用链,则节点将新区块添加到备用链,同时比较备用链与主链的工作量。如果备用链比主链积累了更多的工作量,节点将选择备用链作为其新的主链,而之前的主链则成为了备用链; (Ⅲ) 如果在现有的区块链中找不到它的父区块,那么这个区块被认为是“孤块”。孤块会被保存在孤块池中,直到它们的父区块被节点接收到。一旦收到了父区块并且将其连接到现有的区块链上,节点就会将孤块从孤块池中取出,并且连接到它的父区块,让它作为区块链的一部分比特币整个网络会通过调整“难度”这个变量来控制生成工作量证明所需要的计算力,使整个网络的计算力大致每10分钟产生一个区块