diff --git a/libraries/chain/include/eosio/chain/exceptions.hpp b/libraries/chain/include/eosio/chain/exceptions.hpp index a871750fbc94cefab08620d3b671ae12ec826447..578decc9e7c337d98d97444b1bb9c3b4080bfd2a 100644 --- a/libraries/chain/include/eosio/chain/exceptions.hpp +++ b/libraries/chain/include/eosio/chain/exceptions.hpp @@ -246,6 +246,8 @@ namespace eosio { namespace chain { 3100003, "unknown transaction" ) FC_DECLARE_DERIVED_EXCEPTION( fixed_reversible_db_exception, misc_exception, 3100004, "corrupted reversible block database was fixed" ) + FC_DECLARE_DERIVED_EXCEPTION( extract_genesis_state_exception, misc_exception, + 3100005, "extracted genesis state from blocks.log" ) FC_DECLARE_DERIVED_EXCEPTION( missing_plugin_exception, chain_exception, 3110000, "missing plugin exception" ) diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 0c2113d30cbf3cee5f3a1e0d04d80a8a3c4f6a41..25690cb5a30fadbff0f8f250cee74b910f5b6ec5 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -117,7 +117,9 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip ("wasm-runtime", bpo::value()->value_name("wavm/binaryen"), "Override default WASM runtime") ("chain-state-db-size-mb", bpo::value()->default_value(config::default_state_size / (1024 * 1024)), "Maximum size (in MB) of the chain state database") ("reversible-blocks-db-size-mb", bpo::value()->default_value(config::default_reversible_cache_size / (1024 * 1024)), "Maximum size (in MB) of the reversible blocks database") - + ("contracts-console", bpo::bool_switch()->default_value(false), + "print contract's output to console") + ; #warning TODO: rate limiting /*("per-authorized-account-transaction-msg-rate-limit-time-frame-sec", bpo::value()->default_value(default_per_auth_account_time_frame_seconds), @@ -128,8 +130,12 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip "The time frame, in seconds, that the per-code-account-transaction-msg-rate-limit is imposed over.") ("per-code-account-transaction-msg-rate-limit", bpo::value()->default_value(default_per_code_account), "Limits the maximum rate of transaction messages that an account's code is allowed each per-code-account-transaction-msg-rate-limit-time-frame-sec.")*/ - ; + cli.add_options() + ("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(), + "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), @@ -140,8 +146,6 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip "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") - ("contracts-console", bpo::bool_switch()->default_value(false), - "print contract's output to console") ; } @@ -209,6 +213,27 @@ void chain_plugin::plugin_initialize(const variables_map& options) { my->chain_config->force_all_checks = options.at("force-all-checks").as(); my->chain_config->contracts_console = options.at("contracts-console").as(); + if( options.count("extract-genesis-json") || options.at("print-genesis-json").as() ) { + auto gs = block_log::extract_genesis_state( my->blocks_dir ); + + if( options.at("print-genesis-json").as() ) { + ilog( "Genesis JSON:\n${genesis}", ("genesis", json::to_pretty_string(gs)) ); + } + + if( options.count("extract-genesis-json") ) { + auto p = options.at("extract-genesis-json").as(); + + if( p.is_relative() ) { + p = bfs::current_path() / p; + } + + fc::json::save_to_file( gs, p, true ); + ilog( "Saved genesis JSON to '${path}'", ("path", p.generic_string()) ); + } + + EOS_THROW( extract_genesis_state_exception, "extracted genesis state from blocks.log" ); + } + if( options.at("delete-all-blocks").as() ) { ilog("Deleting state database and blocks"); fc::remove_all( my->chain_config->state_dir ); diff --git a/programs/nodeos/main.cpp b/programs/nodeos/main.cpp index 910c6f10443256cfdc180268291cbd52d905049b..6e16ad9c008615112e07a502eb1c932938f7721b 100644 --- a/programs/nodeos/main.cpp +++ b/programs/nodeos/main.cpp @@ -80,11 +80,13 @@ void initialize_logging() } enum return_codes { - OTHER_FAIL = -2, - INITIALIZE_FAIL = -1, - SUCCESS = 0, - BAD_ALLOC = 1, - FIXED_REVERSIBLE = 2 + OTHER_FAIL = -2, + INITIALIZE_FAIL = -1, + SUCCESS = 0, + BAD_ALLOC = 1, + DATABASE_DIRTY = 2, + FIXED_REVERSIBLE = 3, + EXTRACTED_GENESIS = 4 }; int main(int argc, char** argv) @@ -103,6 +105,8 @@ int main(int argc, char** argv) ilog("eosio root is ${root}", ("root", root.string())); app().startup(); app().exec(); + } catch( const extract_genesis_state_exception& e ) { + return EXTRACTED_GENESIS; } catch( const fixed_reversible_db_exception& e ) { return FIXED_REVERSIBLE; } catch( const fc::exception& e ) { @@ -117,11 +121,14 @@ int main(int argc, char** argv) } catch( const std::runtime_error& e ) { if( std::string(e.what()) == "database dirty flag set" ) { elog( "database dirty flag set (likely due to unclean shutdown): replay required" ); + return DATABASE_DIRTY; } else if( std::string(e.what()) == "database metadata dirty flag set" ) { elog( "database metadata dirty flag set (likely due to unclean shutdown): replay required" ); + return DATABASE_DIRTY; } else { elog( "${e}", ("e",e.what())); } + return OTHER_FAIL; } catch( const std::exception& e ) { elog("${e}", ("e",e.what())); return OTHER_FAIL;