- 浏览: 761441 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (1045)
- 数据结构 (36)
- UML与设计模式 (42)
- c++ (87)
- rust (36)
- Qt (41)
- boost模板元编程 (43)
- Linux (77)
- 汇编 (4)
- 其它 (2)
- 烹饪 (3)
- unix c / socket (73)
- 软件工程 (4)
- shell (53)
- Python (37)
- c++ primer 5th(c++11) (22)
- 数据库/MySQL (27)
- 数据存储 (4)
- lisp (7)
- git (4)
- Utility (3)
- CDN与DNS (54)
- Http (53)
- php (7)
- nginx/lua/openresty (41)
- redis (11)
- TCP/IP (16)
- 互联网 (6)
- kernel (2)
- go (34)
- 区块链 (43)
- 比特股 (13)
- 以太坊 (23)
- 比特币 (23)
- 密码学 (10)
- EOS (53)
- DAG (1)
- docker (1)
- filecoin (7)
- solidity (65)
- ipfs (8)
- 零知识证明 (1)
- openzeppelin (3)
- java (1)
- defi (7)
- Ton (0)
最新评论
区块数据通过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为准
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
其中,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
发表评论
-
eos快照
2019-10-06 08:31 375快照:为区块链提供临时 ... -
eos待确认/分叉库
2019-10-05 08:32 244fork_database:管理了轻量级状态数据,是由未确认的 ... -
eos controller概述
2019-10-03 17:28 285EOS中的模型层是blocks.log和基于chainbase ... -
eos multi_index
2019-10-03 09:01 276EOS的数据库就是chainbase,而调用数据库服务的C++ ... -
eos chainbase状态库
2019-10-01 08:03 420chainbase:是一个快速包含 ... -
eos action
2019-09-28 17:18 179action:在EOS中,action被分配到对应程序(一般是 ... -
eos事务结构
2019-09-28 16:34 386transaction_header:事务头的数据大小是固定的 ... -
eos区块头结构
2019-09-28 08:54 275block_header:区块头 struct block ... -
eos rpc set
2019-09-26 19:27 278set contract:设置合约 xjdeMacBook- ... -
eos rpc create
2019-09-26 19:18 2511.创建公私钥对 xjdeMacBook-Pro:safeco ... -
引用区块
2019-09-25 07:26 305trx.set_reference_block(ref_blo ... -
EOS事务
2019-09-24 07:36 340调用函数add_standard_transaction_op ... -
全节点搭建
2019-09-22 09:34 2581.通过system regproducer命令可将普通账户注 ... -
eos名词解释
2019-09-14 09:34 6441.Authority:权力,要与Permission做好区分 ... -
智能合约依赖库
2019-08-29 07:32 361Action:这部分定义了查询或发送action的API.在E ... -
eos_rpc_system资源获取
2019-08-21 07:39 364资源主要有CPU,net bandwidt ... -
eos_rpc_sign
2019-08-21 07:22 238sign [OPTIONS] transaction:完成EO ... -
eos_rpc_wallet
2019-08-20 07:31 3121.wallet create [OPTIONS]:创建一个新 ... -
eos_rpc_get
2019-08-18 08:38 2841.get info:通过指定全节点API接口获取其连接的EO ... -
nodeos,cleos,keosd
2019-08-16 07:17 299nodeos:是运行在服务端的 ...
相关推荐
Microsoft.ApplicationBlocks.Data.dll
原来只有sqlserver的oracleMicrosoft.ApplicationBlocks.Data 现在oracle版的也有了
Building Blocks.dotx为word2007的页码模板,亲测有效,安装方法百度下即可
Building Blocks.dotx office 2007页码模板
Built-In Building Blocks.dotx office2016 .
《数据库处理封装 GotDotNet.ApplicationBlocks.Data AdoHelper Dao 源码解析》 在软件开发过程中,数据库操作是至关重要的部分,它涉及到数据的存取、查询、更新和删除等核心功能。GotDotNet.ApplicationBlocks....
"Microsoft.ApplicationBlocks.Data"是微软公司提供的一套.NET框架组件,用于简化和增强.NET应用程序中的数据库访问。这个组件是微软 Patterns & Practices 团队创建的,旨在提高开发效率,减少重复工作,并提供最佳...
"GotDotNet.ApplicationBlocks.Data" 是微软发布的一个开源组件,主要包含了用于数据处理的源代码。这个组件的主要目的是为了简化数据库操作,通过函数重载来适应不同的需求,从而提高开发效率。它提供了对多种...
"Building Blocks.rar"这个压缩包提供了一个可能的解决方案,主要关注于使用"Building Blocks"功能来修复此类问题。Building Blocks是Word中一个强大的工具,它允许用户创建、存储和重复使用各种文档元素,如页眉、...
1. 首先,解压"huacai-Building Blocks.rar"文件,提取出"Building Blocks.dotx"。 2. 打开Word 2007,选择“文件” > “新建” > “从模板”。 3. 在打开的对话框中,点击“浏览”,导航到存放"Building Blocks....
Embedded Systems Building Blocks.pdf
blocks.css :hot_beverage: 用块向页面添加一些尺寸 :rocket: 您可以在查看示例并开始使用blocks.css 。 文档中的blocks.css UI如下所示。 首先将blocks.css样式表添加到页面的<head> : < link rel =...
这个压缩包中的"Microsoft.ApplicationBlocks.Common"很可能包含了用于.NET应用程序的通用类库,这些类库可能包含以下方面的功能: 1. **日志记录**:提供一个统一的日志接口,方便在整个项目中添加、管理和查看...
标题“Building-Blocks.rar_building”暗示了这是一个关于构建音频处理基础模块的资源包,主要针对MATLAB环境。描述中提到的“very basic implementations of audio filters in matlab”表明这个压缩包包含了一些...
sap press doc 解压密码:abap_developer