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
我們可以讓全部節點,從這個節點開始重放。
謝謝大家,希望給大家幫助。