这篇分析的源码部分是Appinit2中的第九步:Step 9: import blocks 导入块数据。
第九步代码看起来很简单,也就是上面的几行,总的来说分了两部分,第一部分是在数据库中查找一条最好的链。第二部分是根据用户输入的区块链数据文件导入相应的区块数据。
我们继续发扬我们追查到底的精神,具体看下具体是怎样查找出一条最好的链和如何导入数据的吧。
第一部分通过调用 ActivateBestChain函数查找并激活的最好的区块链。(关于什么是最好的区块链,我的理解是当前最长和有效的链)。传的参数是一个CValidationState 的类对象,这个类在init.cpp中。
这个类就是验证区块数据和交易数据有效性的一个类。在源码中可以看到此类有三种状态:MODE_VALID(有效),MODE_INVALID(数据无效,网络规则不对),MODE_ERROR(运行时错误),默认为有效状态。我们现在进入ActivateBestChain函数内部去看一下,这个函数在main.cpp中。
我们在这段代码看到了blocknotify命令的执行方式,是通过多线程调用runCommand,然后调用:system调用的系统函数执行的此命令。
现在我们看第二部分的代码,分析下如何导入区块数据的。
可以看到,首先定义了一个 boost::filesystem::path的数组,关于这个filesystem我们简单说下:
boost.filesystem以实现可移植的文件系统的操作为目标,通过精心设计一个中间概念来完成大多数可移植的文件系统的操作,这个中间层试图独立于所有的具体文件系统,然后把操作任务映射到这个中间层。当然这个中间层可能与现有的文件系统有最大的相似之处。
所以使用boost的目的也是为了跨平台。
通过loadblock命令获取要导入的区块文件地址。并放入该数组中,通过建立一个新的线程来加载区块数据。这个线程执行的函数是ThreadImport并把数组做为参数传递了过去。
现在我们就去看看这个ThreadImport函数。这个函数也在init.cpp中。
这段代码就是导入区块数据的过程了。可以看到这个过程是从给当前加载区块的线程命名开始的。首先如果需要重新索引区块,则将所有的blk区块数据重新索引从0开始导入一遍,然后查看项目目录下如果有bootstrap.dat文件,则也导入一下这里面的区块数据,这个文件是是以前的区块数据,加载这个文件的目的是不用重新从网络上再下载所有的数据,这样可以加快更新的速度。最后我们通过遍历数据文件数组把数组里的区块数据文件也导入了进来。
好了,这就是第九步导入区块的内容了,这样看来东西也是很多的,由于我最近换工作了,经常加班,更新速度开始变慢,不过我会坚持下来的。
作者:区块链研习社比特币源码研读班,black