比特币源码分析之五:区块

比特币源码分析之五:区块

区块数据结构

区块的数据结构代码在block.cpp中

区块由区块头和交易集合组成,如下图

区块头由以下字段组成

int32_t nVersion; 表示版本号

uint256 hashPrevBlock; 表示前一个区块的hash值

uint256 hashMerkleRoot; 表示交易集合算出来的merkle 树的树根hash

uint32_t nTime; 表示区块的生成时间

uint32_t nBits; 表示当前区块需要的挖矿难度,可以简单理解为定义了挖矿需要hash的前几位是0

uint32_t nNonce; 一个用于挖矿的随机数

Txs是交易的集合

交易的主要结构已经在前面的文章中有介绍这里不再赘述,但是区块中有一个特殊的交易需要单独拿出来介绍一下,这个交易是每一个区块的第一个交易,被叫做coinbasetx

对比之前介绍的标准交易coinbasetx有几个不同

1、coinbasetx必须是在每一个区块的第一个交易

2、coinbasetx没有输入,只有输出,而这个输出一般是矿工的地址,而coinbasetx的输出其实就是给矿工的奖励。比特币体系中所有的比特币都是从这个途径出来了,然后流通在各个账户中。

3、coinbasetx的输入因为没有实际的交易意义,所以被用来存放别的信息,比如区块的witness merkle树的根hash,又比如区块的高度等,其中有一个字段和挖矿有关系,单独列出来,就是输入的脚本中会放一个nExtraNonce字段,这也是一个挖矿时候可以修改的随机数和blockheader中的nNonce字段结合可以达到调整block hash的目的

区块hash的计算方式

区块头中有一个字段hashPrevBlock这个字段表示的就是前一个区块的hash值,那么区块的hash值是怎么计算出来的呢?

其实很简单,区块的hash值就是区块头所有字段的hash256。那么细心的读者一定会注意到,如果区块的hash值只计算了区块头,那么交易集合怎么能保证不被恶意的第三方串改?

这个问题是区块头中有一个hashMerkleRoot,这个字段就是通过交易集合算出来的一个hash值,从网上盗图一张,放在这里供读者理解。

其中L1 L2 L3 L4就是一个一个的交易。

区块生成方式-挖矿

挖矿的主要代码在mining.cpp和miner.cpp中

先贴出来主逻辑

UniValue generateBlocks(…) 函数名称

{

While(…)主循环

{

nHeight = chainActive.Height(); 获取当前链的高度

生成一个区块数据结构,填上了当前的交易以及coinbasetx

pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbaseScript->reserveScript));

CBlock *pblock = &pblocktemplate->block;

调整区块coinbasetx中的输入脚本中的nExtraNonce

IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);

不停的调整区块头中的nNonce来碰撞正确的hash

while(pblock->nNonce<nInnerLoopCount&&

!CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus()))

{

++pblock->nNonce;

}

如果区块头中的nNonce的值用完了(加到最大值了),重启大循环,调整nExtraNonce

if (pblock->nNonce == nInnerLoopCount) {

continue;

}

尝试把挖矿出来的区块放入到候选链->主链->广播出去

ProcessNewBlock(Params(), shared_pblock, true, nullptr)

}

}

这段代码主要是完成以下步骤

1、生成一个区块的模版,填写一些基本的字段

2、调整coinbasetx的nExtraNonce

3、从0- nInnerLoopCount 累加区块头中的nNonce字段,如果累加到了nInnerLoopCount,转入第2步

4、计算区块头hash是否达标(也就是前n位是否为0),达标就进入第5步,否则重复3步

5、将生成好的区块经过验证等流程进入到候选链,进而进入主链,进而进入广播流程。

其中解释几个关键点

1、模版中的前n位为0,n是怎么确认的?

有一个公式,笔者也没有详细研究,原理就是比特币设想每10分钟生成一个区块,而每2016个区块会检查一下,这2016个区块生成的平均时间是否超过或者小于10分钟,如果超过10分钟就会把n调低,也就是降低挖矿难度,反之则把n调高。

另外一个疑问,如果某些恶意矿工,人为的把n设置低,来达到挖矿的目的会怎么样?岂不是它挖矿更容易?

这个问题也引出了比特币中伟大的发明,你把n降低了,再公网中广播的时候,区块的工作量就比别的矿主的少,也就导致了你的区块可能被别的矿工挖出来的区块pk掉的概率高,这就保证了矿工不敢随意降低n。(这么解释可能会比较难理解,后续文章会找机会进一步解释)

2、矿工的挖矿费是怎么确定的?

矿工的挖矿费是有两部分构成

1)、交易费,也就是所有交易的输出减去所有交易的输入的差价就是交易费Fee

2)、奖励,这个奖励是每4年减半,比如当前的奖励是25个比特币,再过一个四年周期会变成12.5个,依次类推。4年这个时间刻度是靠区块链的高度结合每一个区块10分钟的设想生成时间确定的。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏区块链入门

【易错概念】UTXO 和 Account 模型对比

在当前区块链世界中,主要有两种记录保存方式,UTXO 模式(Unspent Transaction Output) 和 Account 模式。Bitcoin 采...

781
来自专栏java达人

从三个直观的方面了解以太坊

在以太坊之前,存在着比特币,但比特币有一些缺陷,比如它只有很少的指令,并不符合图灵计算的标准(没有循环)。于是一位大神便想再创造一个加密货币系统,以支持未来可以...

730

我编写了一个应用程序来告诉你区块链是如何运作的

为了演示一个区块链, 我们将使用一个名为Blockchain CLI的开源命令行界面.

9257
来自专栏FreeBuf

由MtGox停止提现白话比特币交易安全

文/pnig0s|小P 由知乎上的一个问题引出:http://www.zhihu.com/question/22787360/answer/22662598 ...

17110
来自专栏Keegan小钢

016 | 漫谈区块链共识机制

并标明原文链接:http://keeganlee.me/post/blockchain/20180425微信订阅号:keeganlee_me写于2018-04-...

921
来自专栏存储

Burst Coin-挖矿原理介绍

Burst Coin挖矿蛮有意思,可以看看理解一下PoC的 网上有个很清楚的英文,详细描述了挖矿过程: https://forums.getburst.net/...

7118
来自专栏智能合约

以太坊智能合约开发第二篇:理解以太坊相关概念

2306
来自专栏何俊林

用Java实现简单的比特币系统

最近区块链技术突然爆火,身边做技术的朋友茶余饭后不谈点区块链什么的都被认为是跟不上时代了,为啥会这样了? 这其实跟比特币价格去年的突飞猛进是分不开的,比特币价格...

3613
来自专栏比原链

Derek解读Bytom源码-创世区块

Gitee地址:https://gitee.com/BytomBlockchain/bytom

652
来自专栏区块链大本营

一文看懂怎样用 Python 创建比特币交易

1.1K6

扫码关注云+社区