EOSIO网络运行一段时间了,我们开发的产品,需要和EOS主网连接和数据同步。我们看看如何连接和同步。
参考 https://eosnode.tools/blocks
针对EOSIO主网连接和数据同步问题,参考文章已经写的很好了。
今天我们探讨一下,如何实现区块链数据回滚。
假设,整个测试网络区块高度已经到了10000,block-num:10000,我们发现,在9001的位置,交易有问题,我们希望交易回滚。我们怎么办。
我们查看源代码:
eos\plugins\chain_plugin\chain_plugin.cpp文件。
cli.add_options()
("genesis-json", bpo::value<bfs::path>(), "File to read Genesis State from")
("genesis-timestamp", bpo::value<string>(), "override the initial timestamp in the Genesis State file")
("print-genesis-json", bpo::bool_switch()->default_value(false),
"extract genesis_state from blocks.log as JSON, print to console, and exit")
("extract-genesis-json", bpo::value<bfs::path>(),
"extract genesis_state from blocks.log as JSON, write into specified file, and exit")
("fix-reversible-blocks", bpo::bool_switch()->default_value(false),
"recovers reversible block database if that database is in a bad state")
("force-all-checks", bpo::bool_switch()->default_value(false),
"do not skip any checks that can be skipped while replaying irreversible blocks")
("disable-replay-opts", bpo::bool_switch()->default_value(false),
"disable optimizations that specifically target replay")
("replay-blockchain", bpo::bool_switch()->default_value(false),
"clear chain state database and replay all blocks")
("hard-replay-blockchain", bpo::bool_switch()->default_value(false),
"clear chain state database, recover as many blocks as possible from the block log, and then replay those blocks")
("delete-all-blocks", bpo::bool_switch()->default_value(false),
"clear chain state database and block log")
("truncate-at-block", bpo::value<uint32_t>()->default_value(0),
"stop hard replay / block log recovery at this block number (if set to non-zero number)")
("import-reversible-blocks", bpo::value<bfs::path>(),
"replace reversible block database with blocks imported from specified file and then exit")
("export-reversible-blocks", bpo::value<bfs::path>(),
"export reversible block database in portable format into specified file and then exit")
("snapshot", bpo::value<bfs::path>(), "File to read Snapshot State from")
;
}
我们查看参数:truncate-at-block
("truncate-at-block", bpo::value<uint32_t>()->default_value(0),
"stop hard replay / block log recovery at this block number (if set to non-zero number)")
参数写的很清楚。在此块编号处停止硬重放/阻止日志恢复(如果设置为非零数字)
我们只需要将这个参数,设定为要回滚的区块即可。
我们再仔细查看内部源码是怎么运行的。
源文件位于 eos\plugins\chain_plugin\chain_plugin.cpp
if( options.at( "delete-all-blocks" ).as<bool>()) {
ilog( "Deleting state database and blocks" );
if( options.at( "truncate-at-block" ).as<uint32_t>() > 0 )
wlog( "The --truncate-at-block option does not make sense when deleting all blocks." );
clear_directory_contents( my->chain_config->state_dir );
fc::remove_all( my->blocks_dir );
} else if( options.at( "hard-replay-blockchain" ).as<bool>()) {
ilog( "Hard replay requested: deleting state database" );
clear_directory_contents( my->chain_config->state_dir );
auto backup_dir = block_log::repair_log( my->blocks_dir, options.at( "truncate-at-block" ).as<uint32_t>());
if( fc::exists( backup_dir / config::reversible_blocks_dir_name ) ||
options.at( "fix-reversible-blocks" ).as<bool>()) {
// Do not try to recover reversible blocks if the directory does not exist, unless the option was explicitly provided.
if( !recover_reversible_blocks( backup_dir / config::reversible_blocks_dir_name,
my->chain_config->reversible_cache_size,
my->chain_config->blocks_dir / config::reversible_blocks_dir_name,
options.at( "truncate-at-block" ).as<uint32_t>())) {
ilog( "Reversible blocks database was not corrupted. Copying from backup to blocks directory." );
fc::copy( backup_dir / config::reversible_blocks_dir_name,
my->chain_config->blocks_dir / config::reversible_blocks_dir_name );
fc::copy( backup_dir / config::reversible_blocks_dir_name / "shared_memory.bin",
my->chain_config->blocks_dir / config::reversible_blocks_dir_name / "shared_memory.bin" );
fc::copy( backup_dir / config::reversible_blocks_dir_name / "shared_memory.meta",
my->chain_config->blocks_dir / config::reversible_blocks_dir_name / "shared_memory.meta" );
}
}
} else if( options.at( "replay-blockchain" ).as<bool>()) {
ilog( "Replay requested: deleting state database" );
if( options.at( "truncate-at-block" ).as<uint32_t>() > 0 )
wlog( "The --truncate-at-block option does not work for a regular replay of the blockchain." );
clear_directory_contents( my->chain_config->state_dir );
if( options.at( "fix-reversible-blocks" ).as<bool>()) {
if( !recover_reversible_blocks( my->chain_config->blocks_dir / config::reversible_blocks_dir_name,
my->chain_config->reversible_cache_size )) {
ilog( "Reversible blocks database was not corrupted." );
}
}
} else if( options.at( "fix-reversible-blocks" ).as<bool>()) {
if( !recover_reversible_blocks( my->chain_config->blocks_dir / config::reversible_blocks_dir_name,
my->chain_config->reversible_cache_size,
optional<fc::path>(),
options.at( "truncate-at-block" ).as<uint32_t>())) {
ilog( "Reversible blocks database verified to not be corrupted. Now exiting..." );
} else {
ilog( "Exiting after fixing reversible blocks database..." );
}
EOS_THROW( fixed_reversible_db_exception, "fixed corrupted reversible blocks database" );
}
我们从源文件里分析到,要让truncate-at-block生效,需要配合以下几个参数。
--delete-all-blocks
or
--hard-replay-blockchain
or
--replay-blockchain
or
--fix-reversible-blocks
等等这些参数一起生效。
node ... --truncate-at-block 9000 --hard-replay-blockchain
我们可以让全部节点,从这个节点开始重放。
谢谢大家,希望给大家帮助。