当前位置: 首页> 移动电源

比特币源码研读之十二

发布时间:2020-05-24

在我发表了第十一篇源码研读分享之后,社友大硕给我打赏了,而且还说了一句倒出了我心声的话:“菜菜子,你的工作成果能让后来者节省很多时间,很有价值,谢谢分享!”。是的,我在简书中的Sia教程、比特币源码研读系列在我最初编写的时候,只要有2个目的:一是为了保留自己的学习记录,以便后面可以随时回顾自己所学知☆识,减去重复学习的时间;二是可以让后来者少走弯路,提升学习效率。就∈是基于这2个原因,我才会坚持写比特币源码研读系列(在这期间我还会穿插),让自己和更多的人节省时间,提高效率,说大点是可以促进比特币和区块链的快速发展!希望我的文章真正能帮到大家,同时,也欢迎大家◣给我提出宝贵意见,这也能对我成长提供帮助。

本文将继续开展应用程序参数交互源码部分(AppInitParameterInteraction)的研读与分析。

本文主要涉及的源码文件包括:

src/bitcond.cpp、src/init.h、src/init.cpp、src/util.h、src/util.cpp、src/validation.h、src/uint256.h、src/uint256.cpp、consensus/Params.h

一、检测点参数提示

检测点参数信息获取代码如下:

fCheckpointsEnabled =GetBoolArg("-checkpミoints", DEFAULT_CHECKPOINTS_ENABLED);

ν

检测点设置参数checkpoints,在程序中其默认值为DEFAULT_CHECKPOINTS_ENABLED,该常量在src/validation.h中定义,其默认值为true,即需要进行检测点检查。那何为checkpoints,它的作用是什么呢?带着这两个疑问我在网上搜索了一番,找了一篇解≧释得比较全面的英文帖子(https『://biбtcoin.stackexchange.com/questions/1797/what-are-checkpoints):

首先是提问≮者的给出的疑问(Question):

这段话的含义是这样的:检测点是通过硬编δ码方式写入标准客户端的。意味着标准客户端将在检测点之前将接受所有有效交易,这些交易将是不可逆的。如果任何人试图在检测点前从一个区块对区块链进行分叉,客户端将不会接受这个分叉,这使得那些区块一成不变(set in stone)。

$

从上述提问与回答我们可以看出chⅩeckpoint的重要性,通过checkpoint可以防范区块链被恶意分叉,保护比特币网络的正Ω常运行。

我们再来看看fCheckpointsEnabled的使用情况,该变量为全局变量,声明于src/validation.h,定义于src/validation.cpp中,并且其默认为true。主要在AcceptBlockHeader与TestBlockValidity中使用,这两个函数的具体解释将在后续实际使用时进行详细说明,但我们通过其函数名也可以看出检测点主要是对区块相关内容的检测。

二、哈希假定有效参数

我们首先来看哈希假定有效参数的处理代码:

hashAssumeValid= uint256S(GetArg("-assumevalid", chainparams.GetConsensus().defaultAssumeVa●lid.GetHex()));

if (!hashAssumeValid.IsNull())

LogPrintf("Assumingancestors of block→ %s have valid signatures.\n",hashAssumeValid.GetHex());

else

LogPrintf("Validating signatures for all ≌block‰s.\n");

在该源码中,我们可以看到assumevalid参数的默认值可以通过chainparams.GetConsensus().defaultAssumeValid.GetHex()获得,这个默认值的获得过程包括3个步骤:

(1)获得链上共识参数:通过c⿸hainparamЙs.GetCon№sensus()获得链上共识参数(chainparams在前面的文章中已多次提起,此处就不再赘述),返回类型为Consensus::Params,其详细定义我们可以在consensus/Params.h中找到,Params为一ⓛ个结构体,该结构体主要定义了影响链上共识的重要参数,比如:创世块(hashGenesisBloc│┃k)、奖励减半时间间隔(nSubsidyHalvingInterval)、各种BIP启动时的区块高度、工作量证明参数(powLimit、fPowAllowMinDifficultyBlocks等)、难度调整间隔计算函数(Dif≤ficultyAdjustmentInterval)以及默认假定有效对象(defaultAssumeValid);

(2)默认假定有效对象:默认假定有效对象在Consensus::Params中定义uint256 defaultAssumeValid,其类型uint256是一个类,定义于src/uint256.h中,其基类为模板类base_blob,主要用于存储固定大小不透明二进制数值模板,在其后实现了uiⅦnt160与uint≠256两个子类,分别实现了160位与256位二进制数值存储类,所以在此处我们可以看到默认假定有效对象主要是需要存储二进制值,而通过base_blob与uint256可以发现该二进制数为区块的哈希值;

(3)获取哈希值:最后一步就是获取哈希值的十六进值,其获取方式通过GetHex()实现。

assumevalid参数的值也可以由用户在命令行中输入,输入形式为包含64位数的十六进制值,其样式如下:

0x00000Э000000a4d0a398161ffc163c50●3763b1f4360639393e0e4c8e30☼0e0caec▓

在获得十六进制◆值后,我们通过uint256S函数将其转换为uint256对象,该函数定义于src/unit256.h中。其函数实现如下:

inline uint256 uint256S(const char *str)

{

uint256 rv;

rv.SetHex(str);

return rv;

}

最后判断hashAssumeValid的有效性,如果不为空,则假定该哈希值对应区块的所有父区块都具备有效的签名,否则需要验证所有区块的签名,并将判断信息输入在日志╠╡中。hashAssumeValid主要在src/Validation.cpp的CoΘnnectBlock函数中使用。

三、交易池大小限定参√数

交易池大小限定参数设置代码比较简单,主要是设$定交易池最大与最小容量,其代码如下:

ξ

而交易池最小存储容量对应的默认值为DEFAULT_DESCENDANT_SIZE_LIMIT常量,定义于src/validation.h,其单位为KB,通过其定¥义我们可以看到其最小存储容量为101KB。

/** Default for-limitdescendantsize, maximum kilobytes of in-mempool descendants */

s▀tatic const unsigned int

DEFAULT_DESCENDANT_SIZE_LIMIT = 101;

以上就是本次源码研读的内■容,在这篇研读文章中我们知道了检测点、哈╨希假定有效、共识信息参数以及交易池大小范围等内容,可以说我们离比特币源码的核心越来越近了!后面的难度也会随之增加,但只要坚持研读就好,一遍不行就看两遍,不会就的就去学,只要通过努力我们一定能把比特币源码读懂读透的,因为《精通比特币》的作者就是这么过来的,他可是技术≡大牛啊,连他都愿意花了几个月的时间专注比特币源码的分析,进而掌握比特币的运行原理,我们还有什么理由不跟随着他的脚步前行呢!

一起学习成长 长按 关注我们

目前20000+人已关注加入我们

И

马云提出区块链改造制造业,未来区块链将如何大显身手呢?

脸书信息泄露可见私密信息裸奔,区块链如何保护我们的隐私

日本出租车允许数字货币支付,对区块链应用发展有什么影响?

高晓松在清华称区块链使传媒大有可为,区块链+文娱值得期待

菜菜子

赞赏

︹︺︻