`

EOS blocks.log

    博客分类:
  • EOS
 
阅读更多
区块数据通过blocks.log与blocks.index持久化的.
其中,blocks.log是区块链的日志文件,该文件只能被追加内容,并且追加写入的内容必须是不可逆的区块的数据.blocks.log是区块的双链表结构
blocks.index:是一个二级索引文件,只保存区块的位置,通过该索引文件,可以在时间复杂度仅为O(1)的情况下根据区块号快速找到区块

区块链日志blocks.log文件内容的遍历,可以通过不断重复先跳过8字节,然后反序列化一个块获取明文数据,位置信息保存在后8字节.所以,可以不断向后跳转8字节,根据位置信息读取块,然后向后跳转8字节.在blocks.index索引文件中,可以通过随机区块号访问对应区块.

日志文件blocks.log是唯一需要持久化的文件.而索引文件blocks.index可以通过线性扫描blocks.log重新构建.blocks.log是不可逆且不可篡改的,所以以blocks.log为准

class block_log_impl {
public:
    signed_block_ptr         head;//signed_block类型的唯一指针,是一个已经签名的区块
    block_id_type            head_id;//区块id,sha256
    std::fstream             block_stream;//日志文件流,包含输入,输出
    std::fstream             index_stream;//索引文件流,包含输入,输出
    fc::path                 block_file;//日志文件(对应blocks.log文件)
    fc::path                 index_file;//索引文件(对应blocks.index文件)
    bool                     open_files = false;
    bool                     genesis_written_to_block_log = false;//创世块是否已写入的标志位
    uint32_t                 version = 0;
    uint32_t                 first_block_num = 0;


class block_log {
  public:
	 block_log(const fc::path& data_dir);
	 block_log(block_log&& other);
	 ~block_log();

	 uint64_t append(const signed_block_ptr& b);
	 void flush();
	 void reset( const genesis_state& gs, const signed_block_ptr& genesis_block, uint32_t first_block_num = 1 );

	 std::pair<signed_block_ptr, uint64_t> read_block(uint64_t file_pos)const;
	 signed_block_ptr read_block_by_num(uint32_t block_num)const;
	 signed_block_ptr read_block_by_id(const block_id_type& id)const {
		return read_block_by_num(block_header::num_from_id(id));
	 }

	 /**
	  * Return offset of block in file, or block_log::npos if it does not exist.
	  */
	 uint64_t get_block_pos(uint32_t block_num) const;
	 signed_block_ptr        read_head()const;
	 const signed_block_ptr& head()const;
	 uint32_t                first_block_num() const;

	 static const uint64_t npos = std::numeric_limits<uint64_t>::max();

	 static const uint32_t min_supported_version;
	 static const uint32_t max_supported_version;

	 static fc::path repair_log( const fc::path& data_dir, uint32_t truncate_at_block = 0 );

	 static genesis_state extract_genesis_state( const fc::path& data_dir );

  private:
	 void open(const fc::path& data_dir);
	 void construct_index();

	 std::unique_ptr<detail::block_log_impl> my;
};

1.open():参数只有一个data_dir,为节点文件目录,是不可改的fc::path类型的引用,值为数据存储目录路径.
a.函数一开始首先关闭block_stream和index_stream,根据data_dir创建目录,分别创建blocks.log文件作为block_file值,创建blocks.index作为index_file的值.
b.其次开启写入流block_stream及index_stream,并打开对应的标志位block_write和index_write.
c.最后启动持久化文件

2.construct_index():只有在blocks.index与blocks.log不匹配时使用,重播blocks.log重新构建blocks.index,以匹配当前blocks.log文件数据
a.首先关闭流index_stream,删除当前blocks.index之后,再次打开index写入流index_stream,并置标志位index_write为true.
b.通过block_stream读入blocks.log大小记录结尾位置end_pos,跳过起始的4字节(存储version信息,其他地方已经验证),开始遍历block_stream并按位置POS逐一读出
c.同时向index_stream写入对象,直到POS到达end_pos,也就是blocks.log被全部遍历完成,此时blocks.index也就被重新完整地生成,能够与blocks.log匹配

3.block_log(const fc::path& data_dir):构造函数,传入目录路径,创建my对象指针,同时调用私有函数open启动区块链日志

4.block_log(block_log&& other):传入一个block_log对象替换my指针

5.~block_log():析构,关闭文件流block_stream和index_stream,重置my指针

6.reset_to_genesis():该函数对外提供了重围区块链的接口.重置blocks.log和blocks.index,该函数首先会读取创世块的默认配置,并写入区块日志,同时恢复区块数据的版本

7.read_block():地外提供读取某固定位置区块的接口,通过核心代码my->block_stream.seekg(pos);将pos位置的区块从block_stream中查出,然后组装signed_block_ptr,返回结果.

8.get_block_pos():对外提供通过区块号找到区块的接口.

9.read_block_by_num():对外提供通过区块号找到区块的接口,内部实现是先通过get_block_pos函数找到区块位置,然后通过read_block读取区块.

10.read_head():对外提供读取头块的接口,返回类型都是signed_block_ptr.

11.append():参数是一个区块signed_block_ptr对象.该函数是使用频繁的接口,因为整个blocks.log文件不断变大.区块链数据不可篡改且不可逆,所以blocks.log文件只允许追加内容,即通过append函数实现
a.首先,进入函数体校验标志位genesis_written_to_block_log,blocks.log是否写入创世块,如果没有,则终止程序并报错.在这种情况下,需要调用open或reset_to_genesis函数初始化创世块数据.
b.其次,获取block_stream流的最高位置,然后将参数区块的数据打包写入,同时记录位置副本到index_stream,更新头块及头块id为新追加区块的数据
c.最后,关闭文件流block_stream和index_stream,返回最新追加区块的位置.

12.repair_log( const fc::path& data_dir, uint32_t truncate_at_block ):在区块链的运行过程中,往往会有一些意外情况,如电源断电,操作系统崩溃等异常是EOSIO无法捕捉到的,也就无法运行,退出代码这种情况如果是多节点,可以选择重置本地数据,并从其他节点同步重构数据,这个代价较高.
data_dir:数据目录路径
truncate_at_block:截取区块位置,也就是恢复该位置之前的数据,该位置之后的旧数据丢弃,默认为0,即全部重建不丢弃.
a.进入函数体,首先校验data_dir目录与blocks.log文件.在blocks同级目录创建一个backup_dir目录,名字为"blocks.log-时间戳",替代原blocks目录
b.其次,创建一个空的blocks目录,创建新文件流blocks/blocks.log与blocks-2019-10-01 T 07:43:32.122/blocks.log,开始重建
c.backup文件流从头到尾读取完整数据
d.从backup文件流中取出version字段数据写入新文件流最开始的位置
e.结合默认的创世块设置及backup文件流组装创世块,并写入新文件流
f.接着backup文件流的位置POS开始遍历,unpack解开包裹至临时signed_block对象tmp
g.检验tmp的previous区块号与当前区块号是否是加1的关系
h.将tmp.id赋值给previous,组装tmp写入新文件流,更新位置POS
i.重复f,g,h,直到当前区块号等于truncate_at_block,终止遍历

使用方法 ./nodeos --hard-replay-blockchain
分享到:
评论

相关推荐

    Microsoft.ApplicationBlocks.Data.dll

    Microsoft.ApplicationBlocks.Data.dll

    Building Blocks.dotx

    Building Blocks.dotx为word2007的页码模板,亲测有效,安装方法百度下即可

    oracle Microsoft.ApplicationBlocks.Data

    原来只有sqlserver的oracleMicrosoft.ApplicationBlocks.Data 现在oracle版的也有了

    Building Blocks.dotx office 2007页码模板

    Building Blocks.dotx office 2007页码模板

    Built-In Building Blocks.dotx

    Built-In Building Blocks.dotx office2016 .

    数据库处理封装 GotDotNet.ApplicationBlocks.Data AdoHelper Dao 源码

    《数据库处理封装 GotDotNet.ApplicationBlocks.Data AdoHelper Dao 源码解析》 在软件开发过程中,数据库操作是至关重要的部分,它涉及到数据的存取、查询、更新和删除等核心功能。GotDotNet.ApplicationBlocks....

    快递单打印 包括Microsoft.ApplicationBlocks.Data

    "Microsoft.ApplicationBlocks.Data"是微软公司提供的一套.NET框架组件,用于简化和增强.NET应用程序中的数据库访问。这个组件是微软 Patterns & Practices 团队创建的,旨在提高开发效率,减少重复工作,并提供最佳...

    GotDotNet.ApplicationBlocks.Data

    "GotDotNet.ApplicationBlocks.Data" 是微软发布的一个开源组件,主要包含了用于数据处理的源代码。这个组件的主要目的是为了简化数据库操作,通过函数重载来适应不同的需求,从而提高开发效率。它提供了对多种...

    Building Blocks.rar

    "Building Blocks.rar"这个压缩包提供了一个可能的解决方案,主要关注于使用"Building Blocks"功能来修复此类问题。Building Blocks是Word中一个强大的工具,它允许用户创建、存储和重复使用各种文档元素,如页眉、...

    huacai-Building Blocks.rar

    1. 首先,解压"huacai-Building Blocks.rar"文件,提取出"Building Blocks.dotx"。 2. 打开Word 2007,选择“文件” &gt; “新建” &gt; “从模板”。 3. 在打开的对话框中,点击“浏览”,导航到存放"Building Blocks....

    Embedded Systems Building Blocks.pdf

    Embedded Systems Building Blocks.pdf

    blocks.css:使用块some在页面上添加一些尺寸

    blocks.css :hot_beverage: 用块向页面添加一些尺寸 :rocket: 您可以在查看示例并开始使用blocks.css 。 文档中的blocks.css UI如下所示。 首先将blocks.css样式表添加到页面的&lt;head&gt; : &lt; link rel =...

    Microsoft.ApplicationBlocks.Common.zip

    这个压缩包中的"Microsoft.ApplicationBlocks.Common"很可能包含了用于.NET应用程序的通用类库,这些类库可能包含以下方面的功能: 1. **日志记录**:提供一个统一的日志接口,方便在整个项目中添加、管理和查看...

    Building-Blocks.rar_building

    标题“Building-Blocks.rar_building”暗示了这是一个关于构建音频处理基础模块的资源包,主要针对MATLAB环境。描述中提到的“very basic implementations of audio filters in matlab”表明这个压缩包包含了一些...

    Invoice Verification with SAP - Payment Blocks....zip

    sap press doc 解压密码:abap_developer

Global site tag (gtag.js) - Google Analytics