diff --git a/.github/workflows/build-and-test.mac.yml b/.github/workflows/build-and-test.mac.yml index 17c99cf982..ed3874107a 100644 --- a/.github/workflows/build-and-test.mac.yml +++ b/.github/workflows/build-and-test.mac.yml @@ -50,6 +50,33 @@ jobs: libraries/fc/tests/run-parallel-tests.sh _build/tests/chain_test -l test_suite _build/tests/cli_test -l test_suite df -h + - name: Quick test for program arguments + run: | + _build/programs/witness_node/witness_node --version + _build/programs/witness_node/witness_node --help + if _build/programs/witness_node/witness_node --bad-arg ; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi + if _build/programs/witness_node/witness_node --plugins "account_history elasticsearch" ; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi + if _build/programs/witness_node/witness_node --rpc-endpoint --plugins "witness"; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi + _build/programs/cli_wallet/cli_wallet --version + _build/programs/cli_wallet/cli_wallet --help + _build/programs/cli_wallet/cli_wallet --suggest-brain-key + if _build/programs/cli_wallet/cli_wallet --bad-arg ; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi - name: Node-Test run: | df -h diff --git a/.github/workflows/build-and-test.ubuntu-debug.yml b/.github/workflows/build-and-test.ubuntu-debug.yml index ddec5bdec3..3a2de40eaa 100644 --- a/.github/workflows/build-and-test.ubuntu-debug.yml +++ b/.github/workflows/build-and-test.ubuntu-debug.yml @@ -104,6 +104,33 @@ jobs: libraries/fc/tests/run-parallel-tests.sh _build/tests/chain_test -l test_suite _build/tests/cli_test -l test_suite df -h + - name: Quick test for program arguments + run: | + _build/programs/witness_node/witness_node --version + _build/programs/witness_node/witness_node --help + if _build/programs/witness_node/witness_node --bad-arg ; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi + if _build/programs/witness_node/witness_node --plugins "account_history elasticsearch" ; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi + if _build/programs/witness_node/witness_node --rpc-endpoint --plugins "witness"; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi + _build/programs/cli_wallet/cli_wallet --version + _build/programs/cli_wallet/cli_wallet --help + _build/programs/cli_wallet/cli_wallet --suggest-brain-key + if _build/programs/cli_wallet/cli_wallet --bad-arg ; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi - name: Node-Test run: | df -h diff --git a/.github/workflows/build-and-test.ubuntu-release.yml b/.github/workflows/build-and-test.ubuntu-release.yml index 5f5be7fd12..8f310d8d0a 100644 --- a/.github/workflows/build-and-test.ubuntu-release.yml +++ b/.github/workflows/build-and-test.ubuntu-release.yml @@ -80,6 +80,33 @@ jobs: libraries/fc/tests/run-parallel-tests.sh _build/tests/chain_test -l test_suite _build/tests/cli_test -l test_suite df -h + - name: Quick test for program arguments + run: | + _build/programs/witness_node/witness_node --version + _build/programs/witness_node/witness_node --help + if _build/programs/witness_node/witness_node --bad-arg ; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi + if _build/programs/witness_node/witness_node --plugins "account_history elasticsearch" ; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi + if _build/programs/witness_node/witness_node --rpc-endpoint --plugins "witness"; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi + _build/programs/cli_wallet/cli_wallet --version + _build/programs/cli_wallet/cli_wallet --help + _build/programs/cli_wallet/cli_wallet --suggest-brain-key + if _build/programs/cli_wallet/cli_wallet --bad-arg ; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi - name: Node-Test run: | df -h diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index e7af75ea45..cda85540b1 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -129,6 +129,33 @@ jobs: echo "Cleanup" rm -rf /tmp/graphene* df -h + - name: Quick test for program arguments + run: | + _build/programs/witness_node/witness_node --version + _build/programs/witness_node/witness_node --help + if _build/programs/witness_node/witness_node --bad-arg ; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi + if _build/programs/witness_node/witness_node --plugins "account_history elasticsearch" ; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi + if _build/programs/witness_node/witness_node --rpc-endpoint --plugins "witness"; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi + _build/programs/cli_wallet/cli_wallet --version + _build/programs/cli_wallet/cli_wallet --help + _build/programs/cli_wallet/cli_wallet --suggest-brain-key + if _build/programs/cli_wallet/cli_wallet --bad-arg ; then \ + echo "Fail: did not get expected error."; false; \ + else \ + echo "Pass: got expected error."; \ + fi - name: Prepare for scanning with SonarScanner run: | mkdir -p sonar_cache diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index ba97a82d62..5906ea63c2 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -179,10 +179,10 @@ namespace graphene { namespace app { void network_broadcast_api::broadcast_transaction(const precomputable_transaction& trx) { + FC_ASSERT( _app.p2p_node() != nullptr, "Not connected to P2P network, can't broadcast!" ); _app.chain_database()->precompute_parallel( trx ).wait(); _app.chain_database()->push_transaction(trx); - if( _app.p2p_node() != nullptr ) - _app.p2p_node()->broadcast_transaction(trx); + _app.p2p_node()->broadcast_transaction(trx); } fc::variant network_broadcast_api::broadcast_transaction_synchronous(const precomputable_transaction& trx) @@ -197,19 +197,19 @@ namespace graphene { namespace app { void network_broadcast_api::broadcast_block( const signed_block& b ) { + FC_ASSERT( _app.p2p_node() != nullptr, "Not connected to P2P network, can't broadcast!" ); _app.chain_database()->precompute_parallel( b ).wait(); _app.chain_database()->push_block(b); - if( _app.p2p_node() != nullptr ) - _app.p2p_node()->broadcast( net::block_message( b )); + _app.p2p_node()->broadcast( net::block_message( b )); } void network_broadcast_api::broadcast_transaction_with_callback(confirmation_callback cb, const precomputable_transaction& trx) { + FC_ASSERT( _app.p2p_node() != nullptr, "Not connected to P2P network, can't broadcast!" ); _app.chain_database()->precompute_parallel( trx ).wait(); _callbacks[trx.id()] = cb; _app.chain_database()->push_transaction(trx); - if( _app.p2p_node() != nullptr ) - _app.p2p_node()->broadcast_transaction(trx); + _app.p2p_node()->broadcast_transaction(trx); } network_node_api::network_node_api( application& a ) : _app( a ) @@ -218,6 +218,7 @@ namespace graphene { namespace app { fc::variant_object network_node_api::get_info() const { + FC_ASSERT( _app.p2p_node() != nullptr, "No P2P network!" ); fc::mutable_variant_object result = _app.p2p_node()->network_get_info(); result["connection_count"] = _app.p2p_node()->get_connection_count(); return result; @@ -225,26 +226,33 @@ namespace graphene { namespace app { void network_node_api::add_node(const fc::ip::endpoint& ep) { - _app.p2p_node()->add_node(ep); + if( _app.p2p_node() != nullptr ) + _app.p2p_node()->add_node(ep); } std::vector network_node_api::get_connected_peers() const { - return _app.p2p_node()->get_connected_peers(); + if( _app.p2p_node() != nullptr ) + return _app.p2p_node()->get_connected_peers(); + return {}; } std::vector network_node_api::get_potential_peers() const { - return _app.p2p_node()->get_potential_peers(); + if( _app.p2p_node() != nullptr ) + return _app.p2p_node()->get_potential_peers(); + return {}; } fc::variant_object network_node_api::get_advanced_node_parameters() const { + FC_ASSERT( _app.p2p_node() != nullptr, "No P2P network!" ); return _app.p2p_node()->get_advanced_node_parameters(); } void network_node_api::set_advanced_node_parameters(const fc::variant_object& params) { + FC_ASSERT( _app.p2p_node() != nullptr, "No P2P network!" ); return _app.p2p_node()->set_advanced_node_parameters(params); } diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index d78b9c1df6..f8436ec844 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -114,12 +114,17 @@ namespace detail { namespace graphene { namespace app { namespace detail { +application_impl::~application_impl() +{ + this->shutdown(); +} + void application_impl::reset_p2p_node(const fc::path& data_dir) { try { _p2p_network = std::make_shared("BitShares Reference Implementation"); _p2p_network->load_configuration(data_dir / "p2p"); - _p2p_network->set_node_delegate(this); + _p2p_network->set_node_delegate(shared_from_this()); if( _options->count("seed-node") ) { @@ -158,7 +163,7 @@ void application_impl::reset_p2p_node(const fc::path& data_dir) void application_impl::new_connection( const fc::http::websocket_connection_ptr& c ) { auto wsc = std::make_shared(c, GRAPHENE_NET_MAX_NESTED_OBJECTS); - auto login = std::make_shared( std::ref(*_self) ); + auto login = std::make_shared( _self ); login->enable_api("database_api"); wsc->register_api(login->database()); @@ -228,16 +233,17 @@ void application_impl::reset_websocket_tls_server() _websocket_tls_server->start_accept(); } FC_CAPTURE_AND_RETHROW() } -void application_impl::set_dbg_init_key( graphene::chain::genesis_state_type& genesis, const std::string& init_key ) +void application_impl::initialize(const fc::path& data_dir, shared_ptr options) { - flat_set< std::string > initial_witness_names; - public_key_type init_pubkey( init_key ); - for( uint64_t i=0; icount("io-threads") > 0 ) + { + const uint16_t num_threads = _options->at("io-threads").as(); + fc::asio::default_io_service_scope::set_num_threads(num_threads); + } -void application_impl::initialize() -{ if( _options->count("force-validate") > 0 ) { ilog( "All transaction signatures will be validated" ); @@ -287,6 +293,7 @@ void application_impl::initialize() _apiaccess.permission_map["*"] = wild_access; } + initialize_plugins(); } void application_impl::set_api_limit() { @@ -389,19 +396,17 @@ void application_impl::set_api_limit() { } } -void application_impl::startup() -{ try { - fc::create_directories(_data_dir / "blockchain"); - - auto initial_state = [this] { +graphene::chain::genesis_state_type application_impl::initialize_genesis_state() const +{ + try { ilog("Initializing database..."); - if( _options->count("genesis-json") ) + if( _options->count("genesis-json") > 0 ) { std::string genesis_str; fc::read_file_contents( _options->at("genesis-json").as(), genesis_str ); - graphene::chain::genesis_state_type genesis = fc::json::from_string( genesis_str ).as( 20 ); + auto genesis = fc::json::from_string( genesis_str ).as( 20 ); bool modified_genesis = false; - if( _options->count("genesis-timestamp") ) + if( _options->count("genesis-timestamp") > 0 ) { genesis.initial_timestamp = fc::time_point_sec( fc::time_point::now() ) + genesis.initial_parameters.block_interval @@ -415,11 +420,11 @@ void application_impl::startup() ("timestamp", genesis.initial_timestamp.to_iso_string()) ); } - if( _options->count("dbg-init-key") ) + if( _options->count("dbg-init-key") > 0 ) { std::string init_key = _options->at( "dbg-init-key" ).as(); FC_ASSERT( genesis.initial_witness_candidates.size() >= genesis.initial_active_witnesses ); - set_dbg_init_key( genesis, init_key ); + genesis.override_witness_signing_keys( init_key ); modified_genesis = true; ilog("Set init witness key to ${init_key}", ("init_key", init_key)); } @@ -427,10 +432,8 @@ void application_impl::startup() { wlog("WARNING: GENESIS WAS MODIFIED, YOUR CHAIN ID MAY BE DIFFERENT"); genesis_str += "BOGUS"; - genesis.initial_chain_id = fc::sha256::hash( genesis_str ); } - else - genesis.initial_chain_id = fc::sha256::hash( genesis_str ); + genesis.initial_chain_id = fc::sha256::hash( genesis_str ); return genesis; } else @@ -443,13 +446,18 @@ void application_impl::startup() genesis.initial_chain_id = fc::sha256::hash( egenesis_json ); return genesis; } - }; + } FC_CAPTURE_AND_RETHROW() +} - if( _options->count("resync-blockchain") ) +void application_impl::open_chain_database() const +{ try { + fc::create_directories(_data_dir / "blockchain"); + + if( _options->count("resync-blockchain") > 0 ) _chain_db->wipe(_data_dir / "blockchain", true); flat_map loaded_checkpoints; - if( _options->count("checkpoint") ) + if( _options->count("checkpoint") > 0 ) { auto cps = _options->at("checkpoint").as>(); loaded_checkpoints.reserve( cps.size() ); @@ -461,23 +469,23 @@ void application_impl::startup() } _chain_db->add_checkpoints( loaded_checkpoints ); - if( _options->count("enable-standby-votes-tracking") ) + if( _options->count("enable-standby-votes-tracking") > 0 ) { _chain_db->enable_standby_votes_tracking( _options->at("enable-standby-votes-tracking").as() ); } - if( _options->count("replay-blockchain") || _options->count("revalidate-blockchain") ) + if( _options->count("replay-blockchain") > 0 || _options->count("revalidate-blockchain") > 0 ) _chain_db->wipe( _data_dir / "blockchain", false ); try { // these flags are used in open() only, i. e. during replay uint32_t skip; - if( _options->count("revalidate-blockchain") ) // see also handle_block() + if( _options->count("revalidate-blockchain") > 0 ) // see also handle_block() { if( !loaded_checkpoints.empty() ) wlog( "Warning - revalidate will not validate before last checkpoint" ); - if( _options->count("force-validate") ) + if( _options->count("force-validate") > 0 ) skip = graphene::chain::database::skip_nothing; else skip = graphene::chain::database::skip_transaction_signatures; @@ -491,8 +499,12 @@ void application_impl::startup() graphene::chain::database::skip_tapos_check | graphene::chain::database::skip_witness_schedule_check; - graphene::chain::detail::with_skip_flags( *_chain_db, skip, [this,&initial_state] () { - _chain_db->open( _data_dir / "blockchain", initial_state, GRAPHENE_CURRENT_DB_VERSION ); + auto genesis_loader = [this](){ + return initialize_genesis_state(); + }; + + graphene::chain::detail::with_skip_flags( *_chain_db, skip, [this, &genesis_loader] () { + _chain_db->open( _data_dir / "blockchain", genesis_loader, GRAPHENE_CURRENT_DB_VERSION ); }); } catch( const fc::exception& e ) @@ -500,8 +512,21 @@ void application_impl::startup() elog( "Caught exception ${e} in open(), you might want to force a replay", ("e", e.to_detail_string()) ); throw; } +} FC_LOG_AND_RETHROW() } + +void application_impl::startup() +{ try { + bool enable_p2p_network = true; + if( _options->count("enable-p2p-network") > 0 ) + enable_p2p_network = _options->at("enable-p2p-network").as(); + + open_chain_database(); + + startup_plugins(); + + if( enable_p2p_network && _active_plugins.find( "delayed_node" ) == _active_plugins.end() ) + reset_p2p_node(_data_dir); - reset_p2p_node(_data_dir); reset_websocket_server(); reset_websocket_tls_server(); } FC_LOG_AND_RETHROW() } @@ -553,7 +578,7 @@ bool application_impl::has_item(const net::item_id& id) * @throws exception if error validating the item, otherwise the item is safe to broadcast on. */ bool application_impl::handle_block(const graphene::net::block_message& blk_msg, bool sync_mode, - std::vector& contained_transaction_message_ids) + std::vector& contained_transaction_msg_ids) { try { auto latency = fc::time_point::now() - blk_msg.block.timestamp; @@ -562,7 +587,8 @@ bool application_impl::handle_block(const graphene::net::block_message& blk_msg, const auto& witness = blk_msg.block.witness(*_chain_db); const auto& witness_account = witness.witness_account(*_chain_db); auto last_irr = _chain_db->get_dynamic_global_properties().last_irreversible_block_num; - ilog("Got block: #${n} ${bid} time: ${t} transaction(s): ${x} latency: ${l} ms from: ${w} irreversible: ${i} (-${d})", + ilog("Got block: #${n} ${bid} time: ${t} transaction(s): ${x} " + "latency: ${l} ms from: ${w} irreversible: ${i} (-${d})", ("t",blk_msg.block.timestamp) ("n", blk_msg.block.block_num()) ("bid", blk_msg.block.id()) @@ -596,12 +622,12 @@ bool application_impl::handle_block(const graphene::net::block_message& blk_msg, // happens, there's no reason to fetch the transactions, so construct a list of the // transaction message ids we no longer need. // during sync, it is unlikely that we'll see any old - contained_transaction_message_ids.reserve( contained_transaction_message_ids.size() + contained_transaction_msg_ids.reserve( contained_transaction_msg_ids.size() + blk_msg.block.transactions.size() ); for (const processed_transaction& ptrx : blk_msg.block.transactions) { graphene::net::trx_message transaction_message(ptrx); - contained_transaction_message_ids.emplace_back(graphene::net::message(transaction_message).id()); + contained_transaction_msg_ids.emplace_back(graphene::net::message(transaction_message).id()); } } @@ -620,7 +646,7 @@ bool application_impl::handle_block(const graphene::net::block_message& blk_msg, if( !_is_finished_syncing && !sync_mode ) { _is_finished_syncing = true; - _self->syncing_finished(); + _self.syncing_finished(); } } FC_CAPTURE_AND_RETHROW( (blk_msg)(sync_mode) ) return false; } @@ -965,36 +991,112 @@ void application_impl::error_encountered(const std::string& message, const fc::o uint8_t application_impl::get_current_block_interval_in_seconds() const { + FC_ASSERT( _chain_db, "Chain database is not operational" ); return _chain_db->get_global_properties().parameters.block_interval; } +void application_impl::shutdown() +{ + ilog( "Shutting down application" ); + if( _websocket_tls_server ) + _websocket_tls_server.reset(); + if( _websocket_server ) + _websocket_server.reset(); + // TODO wait until all connections are closed and messages handled? + + // plugins E.G. witness_plugin may send data to p2p network, so shutdown them first + ilog( "Shutting down plugins" ); + shutdown_plugins(); + + if( _p2p_network ) + { + ilog( "Disconnecting from P2P network" ); + // FIXME wait() is called in close() but it doesn't block this thread + _p2p_network->close(); + _p2p_network.reset(); + } + else + ilog( "P2P network is disabled" ); + + if( _chain_db ) + { + ilog( "Closing chain database" ); + _chain_db->close(); + _chain_db.reset(); + } + else + ilog( "Chain database is not open" ); +} +void application_impl::enable_plugin( const string& name ) +{ + FC_ASSERT(_available_plugins[name], "Unknown plugin '" + name + "'"); + _active_plugins[name] = _available_plugins[name]; +} + +void application_impl::initialize_plugins() const +{ + for( const auto& entry : _active_plugins ) + { + ilog( "Initializing plugin ${name}", ( "name", entry.second->plugin_name() ) ); + entry.second->plugin_initialize( *_options ); + ilog( "Initialized plugin ${name}", ( "name", entry.second->plugin_name() ) ); + } +} + +void application_impl::startup_plugins() const +{ + for( const auto& entry : _active_plugins ) + { + ilog( "Starting plugin ${name}", ( "name", entry.second->plugin_name() ) ); + entry.second->plugin_startup(); + ilog( "Started plugin ${name}", ( "name", entry.second->plugin_name() ) ); + } +} + +void application_impl::shutdown_plugins() const +{ + for( const auto& entry : _active_plugins ) + { + ilog( "Stopping plugin ${name}", ( "name", entry.second->plugin_name() ) ); + entry.second->plugin_shutdown(); + ilog( "Stopped plugin ${name}", ( "name", entry.second->plugin_name() ) ); + } +} + +void application_impl::add_available_plugin(std::shared_ptr p) +{ + _available_plugins[p->plugin_name()] = p; +} + +void application_impl::set_block_production(bool producing_blocks) +{ + _is_block_producer = producing_blocks; +} } } } // namespace graphene namespace app namespace detail namespace graphene { namespace app { application::application() - : my(std::make_unique(this)) -{} + : my(std::make_shared(*this)) +{ + //nothing else to do +} application::~application() { - if( my->_p2p_network ) - { - my->_p2p_network->close(); - my->_p2p_network.reset(); - } - if( my->_chain_db ) - { - my->_chain_db->close(); - } + ilog("Application quitting"); + my->shutdown(); } void application::set_program_options(boost::program_options::options_description& command_line_options, boost::program_options::options_description& configuration_file_options) const { configuration_file_options.add_options() + ("enable-p2p-network", bpo::value()->implicit_value(true), + "Whether to enable P2P network. Note: if delayed_node plugin is enabled, " + "this option will be ignored and P2P network will always be disabled.") ("p2p-endpoint", bpo::value(), "Endpoint for P2P node to listen on") ("seed-node,s", bpo::value>()->composing(), "P2P nodes to connect to on startup (may specify multiple times)") @@ -1006,15 +1108,18 @@ void application::set_program_options(boost::program_options::options_descriptio "Endpoint for websocket RPC to listen on") ("rpc-tls-endpoint", bpo::value()->implicit_value("127.0.0.1:8089"), "Endpoint for TLS websocket RPC to listen on") - ("server-pem,p", bpo::value()->implicit_value("server.pem"), "The TLS certificate file for this server") + ("server-pem,p", bpo::value()->implicit_value("server.pem"), + "The TLS certificate file for this server") ("server-pem-password,P", bpo::value()->implicit_value(""), "Password for this certificate") ("proxy-forwarded-for-header", bpo::value()->implicit_value("X-Forwarded-For-Client"), "A HTTP header similar to X-Forwarded-For (XFF), used by the RPC server to extract clients' address info, " "usually added by a trusted reverse proxy") ("genesis-json", bpo::value(), "File to read Genesis State from") - ("dbg-init-key", bpo::value(), "Block signing key to use for init witnesses, overrides genesis file") + ("dbg-init-key", bpo::value(), + "Block signing key to use for init witnesses, overrides genesis file, for debug") ("api-access", bpo::value(), "JSON file specifying API permissions") - ("io-threads", bpo::value()->implicit_value(0), "Number of IO threads, default to 0 for auto-configuration") + ("io-threads", bpo::value()->implicit_value(0), + "Number of IO threads, default to 0 for auto-configuration") ("enable-subscribe-to-all", bpo::value()->implicit_value(true), "Whether allow API clients to subscribe to universal object creation and removal events") ("enable-standby-votes-tracking", bpo::value()->implicit_value(true), @@ -1074,7 +1179,8 @@ void application::set_program_options(boost::program_options::options_descriptio "For database_api_impl::get_trade_history_by_sequence to set max limit value") ("api-limit-get-withdraw-permissions-by-giver",boost::program_options::value()->default_value(101), "For database_api_impl::get_withdraw_permissions_by_giver to set max limit value") - ("api-limit-get-withdraw-permissions-by-recipient",boost::program_options::value()->default_value(101), + ("api-limit-get-withdraw-permissions-by-recipient", + boost::program_options::value()->default_value(101), "For database_api_impl::get_withdraw_permissions_by_recipient to set max limit value") ("api-limit-get-tickets", boost::program_options::value()->default_value(101), "Set maximum limit value for database APIs which query for tickets") @@ -1096,24 +1202,20 @@ void application::set_program_options(boost::program_options::options_descriptio configuration_file_options.add(_cfg_options); } -void application::initialize(const fc::path& data_dir, const boost::program_options::variables_map& options) +void application::initialize(const fc::path& data_dir, + std::shared_ptr options) const { - my->_data_dir = data_dir; - my->_options = &options; - - if ( options.count("io-threads") > 0 ) - { - const uint16_t num_threads = options["io-threads"].as(); - fc::asio::default_io_service_scope::set_num_threads(num_threads); - } - - my->initialize(); + ilog( "Initializing application" ); + my->initialize( data_dir, options ); + ilog( "Done initializing application" ); } void application::startup() { try { + ilog( "Starting up application" ); my->startup(); + ilog( "Done starting up application" ); } catch ( const fc::exception& e ) { elog( "${e}", ("e",e.to_detail_string()) ); throw; @@ -1157,7 +1259,7 @@ std::shared_ptr application::chain_database() const void application::set_block_production(bool producing_blocks) { - my->_is_block_producer = producing_blocks; + my->set_block_production(producing_blocks); } optional< api_access_info > application::get_api_access_info( const string& username )const @@ -1175,56 +1277,14 @@ bool application::is_finished_syncing() const return my->_is_finished_syncing; } -void graphene::app::application::enable_plugin(const string& name) +void application::enable_plugin(const string& name) const { - FC_ASSERT(my->_available_plugins[name], "Unknown plugin '" + name + "'"); - my->_active_plugins[name] = my->_available_plugins[name]; - my->_active_plugins[name]->plugin_set_app(this); + my->enable_plugin(name); } -void graphene::app::application::add_available_plugin(std::shared_ptr p) +void application::add_available_plugin(std::shared_ptr p) const { - my->_available_plugins[p->plugin_name()] = p; -} - -void application::shutdown_plugins() -{ - for( auto& entry : my->_active_plugins ) - { - ilog( "Stopping plugin ${name}", ( "name", entry.second->plugin_name() ) ); - entry.second->plugin_shutdown(); - ilog( "Stopped plugin ${name}", ( "name", entry.second->plugin_name() ) ); - } -} -void application::shutdown() -{ - if( my->_p2p_network ) - my->_p2p_network->close(); - if( my->_chain_db ) - { - my->_chain_db->close(); - my->_chain_db = nullptr; - } -} - -void application::initialize_plugins( const boost::program_options::variables_map& options ) -{ - for( auto& entry : my->_active_plugins ) - { - ilog( "Initializing plugin ${name}", ( "name", entry.second->plugin_name() ) ); - entry.second->plugin_initialize( options ); - ilog( "Initialized plugin ${name}", ( "name", entry.second->plugin_name() ) ); - } -} - -void application::startup_plugins() -{ - for( auto& entry : my->_active_plugins ) - { - ilog( "Starting plugin ${name}", ( "name", entry.second->plugin_name() ) ); - entry.second->plugin_startup(); - ilog( "Started plugin ${name}", ( "name", entry.second->plugin_name() ) ); - } + my->add_available_plugin(p); } const application_options& application::get_options() diff --git a/libraries/app/application_impl.hxx b/libraries/app/application_impl.hxx index 9218770c7c..64775cfe0d 100644 --- a/libraries/app/application_impl.hxx +++ b/libraries/app/application_impl.hxx @@ -12,7 +12,7 @@ namespace graphene { namespace app { namespace detail { -class application_impl : public net::node_delegate +class application_impl : public net::node_delegate, public std::enable_shared_from_this { public: fc::optional _lock_file; @@ -28,20 +28,19 @@ class application_impl : public net::node_delegate void reset_websocket_tls_server(); - explicit application_impl(application* self) + explicit application_impl(application& self) : _self(self), _chain_db(std::make_shared()) { } - virtual ~application_impl() - { - } + virtual ~application_impl(); + + void set_block_production(bool producing_blocks); - void set_dbg_init_key( graphene::chain::genesis_state_type& genesis, const std::string& init_key ); void set_api_limit(); - void initialize(); + void initialize(const fc::path& data_dir, std::shared_ptr options); void startup(); fc::optional< api_access_info > get_api_access_info(const string& username)const; @@ -51,22 +50,22 @@ class application_impl : public net::node_delegate /** * If delegate has the item, the network has no need to fetch it. */ - virtual bool has_item(const net::item_id& id) override; + bool has_item(const net::item_id& id) override; /** * @brief allows the application to validate an item prior to broadcasting to peers. * * @param blk_msg the message which contains the block * @param sync_mode true if the message was fetched through the sync process, false during normal operation - * @param contained_transaction_message_ids container for the transactions to write back into + * @param contained_transaction_msg_ids container for the transactions to write back into * @returns true if this message caused the blockchain to switch forks, false if it did not * * @throws exception if error validating the item, otherwise the item is safe to broadcast on. */ - virtual bool handle_block(const graphene::net::block_message& blk_msg, bool sync_mode, - std::vector& contained_transaction_message_ids) override; + bool handle_block(const graphene::net::block_message& blk_msg, bool sync_mode, + std::vector& contained_transaction_msg_ids) override; - virtual void handle_transaction(const graphene::net::trx_message& transaction_message) override; + void handle_transaction(const graphene::net::trx_message& transaction_message) override; void handle_message(const graphene::net::message& message_to_process) override; @@ -81,16 +80,17 @@ class application_impl : public net::node_delegate * in our blockchain after the last item returned in the result, * or 0 if the result contains the last item in the blockchain */ - virtual std::vector get_block_ids(const std::vector& blockchain_synopsis, - uint32_t& remaining_item_count, - uint32_t limit) override; + std::vector get_block_ids( + const std::vector& blockchain_synopsis, + uint32_t& remaining_item_count, + uint32_t limit) override; /** * Given the hash of the requested data, fetch the body. */ - virtual graphene::net::message get_item(const graphene::net::item_id& id) override; + graphene::net::message get_item(const graphene::net::item_id& id) override; - virtual graphene::chain::chain_id_type get_chain_id()const override; + graphene::chain::chain_id_type get_chain_id()const override; /** * Returns a synopsis of the blockchain used for syncing. This consists of a list of @@ -150,46 +150,68 @@ class application_impl : public net::node_delegate * successfully pushed to the blockchain, so that tells us whether the peer is on a fork or on * the main chain. */ - virtual std::vector get_blockchain_synopsis(const graphene::net::item_hash_t& reference_point, - uint32_t number_of_blocks_after_reference_point) override; + std::vector get_blockchain_synopsis( + const graphene::net::item_hash_t& reference_point, + uint32_t number_of_blocks_after_reference_point) override; /** * Call this after the call to handle_message succeeds. * - * @param item_type the type of the item we're synchronizing, will be the same as item passed to the sync_from() call + * @param item_type the type of the item we're synchronizing, + * will be the same as item passed to the sync_from() call * @param item_count the number of items known to the node that haven't been sent to handle_item() yet. * After `item_count` more calls to handle_item(), the node will be in sync */ - virtual void sync_status(uint32_t item_type, uint32_t item_count) override; + void sync_status(uint32_t item_type, uint32_t item_count) override; /** * Call any time the number of connected peers changes. */ - virtual void connection_count_changed(uint32_t c) override; + void connection_count_changed(uint32_t c) override; - virtual uint32_t get_block_number(const graphene::net::item_hash_t& block_id) override; + uint32_t get_block_number(const graphene::net::item_hash_t& block_id) override; /** * Returns the time a block was produced (if block_id = 0, returns genesis time). * If we don't know about the block, returns time_point_sec::min() */ - virtual fc::time_point_sec get_block_time(const graphene::net::item_hash_t& block_id) override; + fc::time_point_sec get_block_time(const graphene::net::item_hash_t& block_id) override; - virtual graphene::net::item_hash_t get_head_block_id() const override; + graphene::net::item_hash_t get_head_block_id() const override; - virtual uint32_t estimate_last_known_fork_from_git_revision_timestamp(uint32_t unix_timestamp) const override; + uint32_t estimate_last_known_fork_from_git_revision_timestamp(uint32_t unix_timestamp) const override; - virtual void error_encountered(const std::string& message, const fc::oexception& error) override; + void error_encountered(const std::string& message, const fc::oexception& error) override; uint8_t get_current_block_interval_in_seconds() const override; + /// Add an available plugin + void add_available_plugin( std::shared_ptr p ); + + /// Enables a plugin + void enable_plugin(const string& name); + /// Returns whether a plugin is enabled bool is_plugin_enabled(const string& name) const; - application* _self; + private: + void shutdown(); + + void initialize_plugins() const; + void startup_plugins() const; + void shutdown_plugins() const; + + /// Initialize genesis state. Called by @ref open_chain_database. + graphene::chain::genesis_state_type initialize_genesis_state() const; + /// Open the chain database. Called by @ref startup. + void open_chain_database() const; + + friend graphene::app::application; + + application& _self; fc::path _data_dir; - const boost::program_options::variables_map* _options = nullptr; + std::shared_ptr _options; api_access _apiaccess; std::shared_ptr _chain_db; @@ -201,7 +223,7 @@ class application_impl : public net::node_delegate std::map> _available_plugins; bool _is_finished_syncing = false; - private: + fc::serial_valve valve; }; diff --git a/libraries/app/include/graphene/app/application.hpp b/libraries/app/include/graphene/app/application.hpp index f3f54ae54e..3b0cbb2808 100644 --- a/libraries/app/include/graphene/app/application.hpp +++ b/libraries/app/include/graphene/app/application.hpp @@ -85,20 +85,17 @@ namespace graphene { namespace app { void set_program_options(boost::program_options::options_description& command_line_options, boost::program_options::options_description& configuration_file_options)const; - void initialize(const fc::path& data_dir, const boost::program_options::variables_map& options); - void initialize_plugins(const boost::program_options::variables_map& options); + void initialize(const fc::path& data_dir, + std::shared_ptr options) const; void startup(); - void shutdown(); - void startup_plugins(); - void shutdown_plugins(); template std::shared_ptr register_plugin(bool auto_load = false) { - auto plug = std::make_shared(); - plug->plugin_set_app(this); + auto plug = std::make_shared(*this); string cli_plugin_desc = plug->plugin_name() + " plugin. " + plug->plugin_description() + "\nOptions"; - boost::program_options::options_description plugin_cli_options( cli_plugin_desc ), plugin_cfg_options; + boost::program_options::options_description plugin_cli_options( cli_plugin_desc ); + boost::program_options::options_description plugin_cfg_options; plug->plugin_set_program_options(plugin_cli_options, plugin_cfg_options); if( !plugin_cli_options.options().empty() ) @@ -143,14 +140,16 @@ namespace graphene { namespace app { const application_options& get_options(); - void enable_plugin( const string& name ); + void enable_plugin( const string& name ) const; bool is_plugin_enabled(const string& name) const; std::shared_ptr elasticsearch_thread; private: - void add_available_plugin( std::shared_ptr p ); + /// Add an available plugin + void add_available_plugin( std::shared_ptr p ) const; + std::shared_ptr my; boost::program_options::options_description _cli_options; diff --git a/libraries/app/include/graphene/app/plugin.hpp b/libraries/app/include/graphene/app/plugin.hpp index b833d97feb..cc61aafc27 100644 --- a/libraries/app/include/graphene/app/plugin.hpp +++ b/libraries/app/include/graphene/app/plugin.hpp @@ -33,10 +33,18 @@ namespace graphene { namespace app { class abstract_plugin { public: - virtual ~abstract_plugin(){} + explicit abstract_plugin(application& a) : _app(a) {} + virtual ~abstract_plugin() = default; + + /// Get the name of the plugin virtual std::string plugin_name()const = 0; + + /// Get the description of the plugin virtual std::string plugin_description()const = 0; + /// Get a reference of the application bound to the plugin + application& app()const { return _app; } + /** * @brief Perform early startup routines and register plugin indexes, callbacks, etc. * @@ -66,13 +74,6 @@ class abstract_plugin */ virtual void plugin_shutdown() = 0; - /** - * @brief Register the application instance with the plugin. - * - * This is called by the framework to set the application. - */ - virtual void plugin_set_app( application* a ) = 0; - /** * @brief Fill in command line parameters used by the plugin. * @@ -88,6 +89,8 @@ class abstract_plugin boost::program_options::options_description& command_line_options, boost::program_options::options_description& config_file_options ) = 0; + protected: + application& _app; }; /** @@ -97,27 +100,21 @@ class abstract_plugin class plugin : public abstract_plugin { public: - plugin(); - virtual ~plugin() override; - - virtual std::string plugin_name()const override; - virtual std::string plugin_description()const override; - virtual void plugin_initialize( const boost::program_options::variables_map& options ) override; - virtual void plugin_startup() override; - virtual void plugin_shutdown() override; - virtual void plugin_set_app( application* app ) override; - virtual void plugin_set_program_options( + using abstract_plugin::abstract_plugin; + + std::string plugin_name()const override; + std::string plugin_description()const override; + void plugin_initialize( const boost::program_options::variables_map& options ) override; + void plugin_startup() override; + void plugin_shutdown() override; + void plugin_set_program_options( boost::program_options::options_description& command_line_options, boost::program_options::options_description& config_file_options ) override; chain::database& database() { return *app().chain_database(); } - application& app()const { assert(_app); return *_app; } protected: - net::node& p2p_node() { return *app().p2p_node(); } - - private: - application* _app = nullptr; + net::node_ptr p2p_node() const { return app().p2p_node(); } }; /// @ingroup Some useful tools for boost::program_options arguments using vectors of JSON strings diff --git a/libraries/app/plugin.cpp b/libraries/app/plugin.cpp index 02d1fdb828..58e781f3dd 100644 --- a/libraries/app/plugin.cpp +++ b/libraries/app/plugin.cpp @@ -27,17 +27,6 @@ namespace graphene { namespace app { -plugin::plugin() -{ - _app = nullptr; - return; -} - -plugin::~plugin() -{ - return; -} - std::string plugin::plugin_name()const { return ""; @@ -50,23 +39,17 @@ std::string plugin::plugin_description()const void plugin::plugin_initialize( const boost::program_options::variables_map& options ) { - return; + // nothing to do } void plugin::plugin_startup() { - return; + // nothing to do } void plugin::plugin_shutdown() { - return; -} - -void plugin::plugin_set_app( application* app ) -{ - _app = app; - return; + // nothing to do } void plugin::plugin_set_program_options( @@ -74,7 +57,7 @@ void plugin::plugin_set_program_options( boost::program_options::options_description& config_file_options ) { - return; + // nothing to do } } } // graphene::app diff --git a/libraries/chain/genesis_state.cpp b/libraries/chain/genesis_state.cpp index ae6b015990..78771a8a93 100644 --- a/libraries/chain/genesis_state.cpp +++ b/libraries/chain/genesis_state.cpp @@ -34,6 +34,15 @@ chain_id_type genesis_state_type::compute_chain_id() const return initial_chain_id; } +void genesis_state_type::override_witness_signing_keys( const std::string& new_key ) +{ + public_key_type new_pubkey( new_key ); + for( auto& wit : initial_witness_candidates ) + { + wit.block_signing_key = new_pubkey; + } +} + } } // graphene::chain FC_REFLECT_DERIVED_NO_TYPENAME(graphene::chain::genesis_state_type::initial_account_type, BOOST_PP_SEQ_NIL, diff --git a/libraries/chain/include/graphene/chain/genesis_state.hpp b/libraries/chain/include/graphene/chain/genesis_state.hpp index 98538e824e..391e3e58d4 100644 --- a/libraries/chain/include/graphene/chain/genesis_state.hpp +++ b/libraries/chain/include/graphene/chain/genesis_state.hpp @@ -124,6 +124,10 @@ struct genesis_state_type { * This is the SHA256 serialization of the genesis_state. */ chain_id_type compute_chain_id() const; + + /// Method to override initial witness signing keys for debug + void override_witness_signing_keys( const std::string& new_key ); + }; } } // namespace graphene::chain diff --git a/libraries/db/object_database.cpp b/libraries/db/object_database.cpp index 75b7090be4..6767051264 100644 --- a/libraries/db/object_database.cpp +++ b/libraries/db/object_database.cpp @@ -98,7 +98,7 @@ void object_database::wipe(const fc::path& data_dir) close(); ilog("Wiping object database..."); fc::remove_all(data_dir / "object_database"); - ilog("Done wiping object databse."); + ilog("Done wiping object database."); } void object_database::open(const fc::path& data_dir) diff --git a/libraries/net/include/graphene/net/message.hpp b/libraries/net/include/graphene/net/message.hpp index 6d254b6120..b6463aaa4a 100644 --- a/libraries/net/include/graphene/net/message.hpp +++ b/libraries/net/include/graphene/net/message.hpp @@ -51,7 +51,7 @@ namespace graphene { namespace net { } }; - typedef fc::uint160_t message_hash_type; + using message_hash_type = fc::ripemd160; /** * Abstracts the process of packing/unpacking a message for a @@ -80,7 +80,7 @@ namespace graphene { namespace net { size = (uint32_t)data.size(); } - fc::uint160_t id()const + message_hash_type id()const { return fc::ripemd160::hash( data.data(), (uint32_t)data.size() ); } diff --git a/libraries/net/include/graphene/net/node.hpp b/libraries/net/include/graphene/net/node.hpp index 0d4d5159d9..98981a7813 100644 --- a/libraries/net/include/graphene/net/node.hpp +++ b/libraries/net/include/graphene/net/node.hpp @@ -29,8 +29,6 @@ #include -#include - namespace graphene { namespace net { using fc::variant_object; @@ -39,11 +37,8 @@ namespace graphene { namespace net { namespace detail { class node_impl; - struct node_impl_deleter - { - void operator()(node_impl*); - }; } + using node_impl_ptr = std::shared_ptr; // during network development, we need to track message propagation across the network // using a structure like this: @@ -61,7 +56,7 @@ namespace graphene { namespace net { class node_delegate { public: - virtual ~node_delegate(){} + virtual ~node_delegate() = default; /** * If delegate has the item, the network has no need to fetch it. @@ -73,14 +68,14 @@ namespace graphene { namespace net { * * @param blk_msg the message which contains the block * @param sync_mode true if the message was fetched through the sync process, false during normal operation - * @param contained_transaction_message_ids container for the transactions to write back into + * @param contained_transaction_msg_ids container for the transactions to write back into * @returns true if this message caused the blockchain to switch forks, false if it did not * * @throws exception if error validating the item, otherwise the item is * safe to broadcast on. */ virtual bool handle_block( const graphene::net::block_message& blk_msg, bool sync_mode, - std::vector& contained_transaction_message_ids ) = 0; + std::vector& contained_transaction_msg_ids ) = 0; /** * @brief Called when a new transaction comes in from the network @@ -199,7 +194,7 @@ namespace graphene { namespace net { void close(); - void set_node_delegate( node_delegate* del ); + void set_node_delegate( std::shared_ptr del ) const; void load_configuration( const fc::path& configuration_directory ); @@ -318,34 +313,10 @@ namespace graphene { namespace net { void disable_peer_advertising(); fc::variant_object get_call_statistics() const; private: - std::unique_ptr my; + node_impl_ptr my; }; - class simulated_network : public node - { - public: - ~simulated_network(); - simulated_network(const std::string& user_agent) : node(user_agent) {} - void listen_to_p2p_network() override {} - void connect_to_p2p_network() override {} - void connect_to_endpoint(const fc::ip::endpoint& ep) override {} - - fc::ip::endpoint get_actual_listening_endpoint() const override { return fc::ip::endpoint(); } - - void sync_from(const item_id& current_head_block, const std::vector& hard_fork_block_numbers) override {} - void broadcast(const message& item_to_broadcast) override; - void add_node_delegate(node_delegate* node_delegate_to_add); - - virtual uint32_t get_connection_count() const override { return 8; } - private: - struct node_info; - void message_sender(node_info* destination_node); - std::list network_nodes; - }; - - - typedef std::shared_ptr node_ptr; - typedef std::shared_ptr simulated_network_ptr; + using node_ptr = std::shared_ptr; } } // graphene::net diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index cdabcf6ba2..d3b1129c9e 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -146,13 +146,15 @@ namespace graphene { namespace net { // for network performance stats message_propagation_data propagation_data; - fc::uint160_t message_contents_hash; // hash of whatever the message contains (if it's a transaction, this is the transaction id, if it's a block, it's the block_id) + /// hash of whatever the message contains + /// (if it's a transaction, this is the transaction id, if it's a block, it's the block_id) + message_hash_type message_contents_hash; message_info( const message_hash_type& message_hash, const message& message_body, uint32_t block_clock_when_received, const message_propagation_data& propagation_data, - fc::uint160_t message_contents_hash ) : + message_hash_type message_contents_hash ) : message_hash( message_hash ), message_body( message_body ), block_clock_when_received( block_clock_when_received ), @@ -160,15 +162,14 @@ namespace graphene { namespace net { message_contents_hash( message_contents_hash ) {} }; - typedef boost::multi_index_container - < message_info, - bmi::indexed_by< bmi::ordered_unique< bmi::tag, - bmi::member >, - bmi::ordered_non_unique< bmi::tag, - bmi::member >, - bmi::ordered_non_unique< bmi::tag, - bmi::member > > - > message_cache_container; + using message_cache_container = boost::multi_index_container < message_info, + bmi::indexed_by< + bmi::ordered_unique< bmi::tag, + bmi::member >, + bmi::ordered_non_unique< bmi::tag, + bmi::member >, + bmi::ordered_non_unique< bmi::tag, + bmi::member > > >; message_cache_container _message_cache; @@ -179,10 +180,13 @@ namespace graphene { namespace net { block_clock( 0 ) {} void block_accepted(); - void cache_message( const message& message_to_cache, const message_hash_type& hash_of_message_to_cache, - const message_propagation_data& propagation_data, const fc::uint160_t& message_content_hash ); + void cache_message( const message& message_to_cache, + const message_hash_type& hash_of_message_to_cache, + const message_propagation_data& propagation_data, + const message_hash_type& message_content_hash ); message get_message( const message_hash_type& hash_of_message_to_lookup ); - message_propagation_data get_message_propagation_data( const fc::uint160_t& hash_of_message_contents_to_lookup ) const; + message_propagation_data get_message_propagation_data( + const message_hash_type& hash_of_msg_contents_to_lookup ) const; size_t size() const { return _message_cache.size(); } }; @@ -190,14 +194,14 @@ namespace graphene { namespace net { { ++block_clock; if( block_clock > cache_duration_in_blocks ) - _message_cache.get().erase(_message_cache.get().begin(), - _message_cache.get().lower_bound(block_clock - cache_duration_in_blocks ) ); + _message_cache.get().erase(_message_cache.get().begin(), + _message_cache.get().lower_bound(block_clock - cache_duration_in_blocks ) ); } void blockchain_tied_message_cache::cache_message( const message& message_to_cache, - const message_hash_type& hash_of_message_to_cache, - const message_propagation_data& propagation_data, - const fc::uint160_t& message_content_hash ) + const message_hash_type& hash_of_message_to_cache, + const message_propagation_data& propagation_data, + const message_hash_type& message_content_hash ) { _message_cache.insert( message_info(hash_of_message_to_cache, message_to_cache, @@ -215,12 +219,13 @@ namespace graphene { namespace net { FC_THROW_EXCEPTION( fc::key_not_found_exception, "Requested message not in cache" ); } - message_propagation_data blockchain_tied_message_cache::get_message_propagation_data( const fc::uint160_t& hash_of_message_contents_to_lookup ) const + message_propagation_data blockchain_tied_message_cache::get_message_propagation_data( + const message_hash_type& hash_of_msg_contents_to_lookup ) const { - if( hash_of_message_contents_to_lookup != fc::uint160_t() ) + if( hash_of_msg_contents_to_lookup != message_hash_type() ) { message_cache_container::index::type::const_iterator iter = - _message_cache.get().find(hash_of_message_contents_to_lookup ); + _message_cache.get().find(hash_of_msg_contents_to_lookup ); if( iter != _message_cache.get().end() ) return iter->propagation_data; } @@ -854,7 +859,7 @@ namespace graphene { namespace net { namespace detail { _retrigger_advertise_inventory_loop_promise->set_value(); } - void node_impl::terminate_inactive_connections_loop() + void node_impl::kill_inactive_conns_loop(node_impl_ptr self) { VERIFY_CORRECT_THREAD(); std::list peers_to_disconnect_gently; @@ -862,6 +867,9 @@ namespace graphene { namespace net { namespace detail { std::list peers_to_send_keep_alive; std::list peers_to_terminate; + try { + // Note: if the node is shutting down, it's possible that _delegate is already unusable, + // in this case, we'll get an exception _recent_block_interval_in_seconds = _delegate->get_current_block_interval_in_seconds(); // Disconnect peers that haven't sent us any data recently @@ -1071,10 +1079,21 @@ namespace graphene { namespace net { namespace detail { offsetof(current_time_request_message, request_sent_time)); peers_to_send_keep_alive.clear(); - if (!_node_is_shutting_down && !_terminate_inactive_connections_loop_done.canceled()) - _terminate_inactive_connections_loop_done = fc::schedule( [this](){ terminate_inactive_connections_loop(); }, - fc::time_point::now() + fc::seconds(GRAPHENE_NET_PEER_HANDSHAKE_INACTIVITY_TIMEOUT / 2), - "terminate_inactive_connections_loop" ); + } catch( const fc::exception& e ) { + wlog( "Exception caught in kill_inactive_conns_loop: ${e}", ("e",e.to_detail_string()) ); + // If the node is shutting down, we just quit, no need to throw. + // If the node is not shutting down, the old code will throw, which means we won't schedule a new loop, + // likely it's unexpected behavior. + // Thus we don't throw here. + } + + if (!_node_is_shutting_down && !_kill_inactive_conns_loop_done.canceled()) + { + _kill_inactive_conns_loop_done = fc::schedule( + [this,self](){ kill_inactive_conns_loop(self); }, + fc::time_point::now() + fc::seconds(GRAPHENE_NET_PEER_HANDSHAKE_INACTIVITY_TIMEOUT / 2), + "kill_inactive_conns_loop" ); + } } void node_impl::fetch_updated_peer_lists_loop() @@ -2658,8 +2677,8 @@ namespace graphene { namespace net { namespace detail { try { - std::vector contained_transaction_message_ids; - _delegate->handle_block(block_message_to_send, true, contained_transaction_message_ids); + std::vector contained_transaction_msg_ids; + _delegate->handle_block(block_message_to_send, true, contained_transaction_msg_ids); ilog("Successfully pushed sync block ${num} (id:${id})", ("num", block_message_to_send.block.block_num()) ("id", block_message_to_send.block_id)); @@ -2981,11 +3000,13 @@ namespace graphene { namespace net { namespace detail { { if (!_node_is_shutting_down && (!_process_backlog_of_sync_blocks_done.valid() || _process_backlog_of_sync_blocks_done.ready())) - _process_backlog_of_sync_blocks_done = fc::async([=](){ process_backlog_of_sync_blocks(); }, "process_backlog_of_sync_blocks"); + _process_backlog_of_sync_blocks_done = fc::async( [this](){ process_backlog_of_sync_blocks(); }, + "process_backlog_of_sync_blocks" ); } - void node_impl::process_block_during_sync( peer_connection* originating_peer, - const graphene::net::block_message& block_message_to_process, const message_hash_type& message_hash ) + void node_impl::process_block_during_syncing( peer_connection* originating_peer, + const graphene::net::block_message& block_message_to_process, + const message_hash_type& ) { VERIFY_CORRECT_THREAD(); dlog( "received a sync block from peer ${endpoint}", ("endpoint", originating_peer->get_remote_endpoint() ) ); @@ -2996,13 +3017,14 @@ namespace graphene { namespace net { namespace detail { trigger_process_backlog_of_sync_blocks(); } - void node_impl::process_block_during_normal_operation( peer_connection* originating_peer, - const graphene::net::block_message& block_message_to_process, - const message_hash_type& message_hash ) + void node_impl::process_block_when_in_sync( peer_connection* originating_peer, + const graphene::net::block_message& block_message_to_process, + const message_hash_type& message_hash ) { fc::time_point message_receive_time = fc::time_point::now(); - dlog( "received a block from peer ${endpoint}, passing it to client", ("endpoint", originating_peer->get_remote_endpoint() ) ); + dlog( "received a block from peer ${endpoint}, passing it to client", + ("endpoint", originating_peer->get_remote_endpoint() ) ); std::set peers_to_disconnect; std::string disconnect_reason; fc::oexception disconnect_exception; @@ -3019,8 +3041,8 @@ namespace graphene { namespace net { namespace detail { if (std::find(_most_recent_blocks_accepted.begin(), _most_recent_blocks_accepted.end(), block_message_to_process.block_id) == _most_recent_blocks_accepted.end()) { - std::vector contained_transaction_message_ids; - _delegate->handle_block(block_message_to_process, false, contained_transaction_message_ids); + std::vector contained_transaction_msg_ids; + _delegate->handle_block(block_message_to_process, false, contained_transaction_msg_ids); message_validated_time = fc::time_point::now(); ilog("Successfully pushed block ${num} (id:${id})", ("num", block_message_to_process.block.block_num()) @@ -3028,7 +3050,7 @@ namespace graphene { namespace net { namespace detail { _most_recent_blocks_accepted.push_back(block_message_to_process.block_id); bool new_transaction_discovered = false; - for (const item_hash_t& transaction_message_hash : contained_transaction_message_ids) + for (const item_hash_t& transaction_message_hash : contained_transaction_msg_ids) { /*size_t items_erased =*/ _items_to_fetch.get().erase(item_id(trx_message_type, transaction_message_hash)); // there are two ways we could behave here: we could either act as if we received @@ -3150,7 +3172,8 @@ namespace graphene { namespace net { namespace detail { for (const peer_connection_ptr& peer : peers_to_disconnect) { - wlog("disconnecting client ${endpoint} because it offered us the rejected block", ("endpoint", peer->get_remote_endpoint())); + wlog("disconnecting client ${endpoint} because it offered us the rejected block", + ("endpoint", peer->get_remote_endpoint())); disconnect_from_peer(peer.get(), disconnect_reason, true, *disconnect_exception); } } @@ -3168,7 +3191,7 @@ namespace graphene { namespace net { namespace detail { if (item_iter != originating_peer->items_requested_from_peer.end()) { originating_peer->items_requested_from_peer.erase(item_iter); - process_block_during_normal_operation(originating_peer, block_message_to_process, message_hash); + process_block_when_in_sync(originating_peer, block_message_to_process, message_hash); if (originating_peer->idle()) trigger_fetch_items_loop(); return; @@ -3187,7 +3210,7 @@ namespace graphene { namespace net { namespace detail { { originating_peer->last_sync_item_received_time = fc::time_point::now(); _active_sync_requests.erase(block_message_to_process.block_id); - process_block_during_sync(originating_peer, block_message_to_process, message_hash); + process_block_during_syncing(originating_peer, block_message_to_process, message_hash); if (originating_peer->idle()) { // we have finished fetching a batch of items, so we either need to grab another batch of items @@ -3861,8 +3884,8 @@ namespace graphene { namespace net { namespace detail { // our loops now try { - _terminate_inactive_connections_loop_done.cancel_and_wait("node_impl::close()"); - dlog("Terminate inactive connections loop terminated"); + _kill_inactive_conns_loop_done.cancel_and_wait("node_impl::close()"); + dlog("Kill inactive connections loop terminated"); } catch ( const fc::exception& e ) { @@ -4120,12 +4143,12 @@ namespace graphene { namespace net { namespace detail { } // methods implementing node's public interface - void node_impl::set_node_delegate(node_delegate* del, fc::thread* thread_for_delegate_calls) + void node_impl::set_node_delegate(std::shared_ptr del, fc::thread* thread_for_delegate_calls) { VERIFY_CORRECT_THREAD(); _delegate.reset(); if (del) - _delegate.reset(new statistics_gathering_node_delegate_wrapper(del, thread_for_delegate_calls)); + _delegate = std::make_unique(del, thread_for_delegate_calls); if( _delegate ) _chain_id = del->get_chain_id(); } @@ -4298,7 +4321,7 @@ namespace graphene { namespace net { namespace detail { } } - void node_impl::connect_to_p2p_network() + void node_impl::connect_to_p2p_network(node_impl_ptr self) { VERIFY_CORRECT_THREAD(); assert(_node_public_key != fc::ecc::public_key_data()); @@ -4309,20 +4332,25 @@ namespace graphene { namespace net { namespace detail { !_fetch_sync_items_loop_done.valid() && !_fetch_item_loop_done.valid() && !_advertise_inventory_loop_done.valid() && - !_terminate_inactive_connections_loop_done.valid() && + !_kill_inactive_conns_loop_done.valid() && !_fetch_updated_peer_lists_loop_done.valid() && !_bandwidth_monitor_loop_done.valid() && !_dump_node_status_task_done.valid()); if (_node_configuration.accept_incoming_connections) - _accept_loop_complete = fc::async( [=](){ accept_loop(); }, "accept_loop"); - _p2p_network_connect_loop_done = fc::async( [=]() { p2p_network_connect_loop(); }, "p2p_network_connect_loop" ); - _fetch_sync_items_loop_done = fc::async( [=]() { fetch_sync_items_loop(); }, "fetch_sync_items_loop" ); - _fetch_item_loop_done = fc::async( [=]() { fetch_items_loop(); }, "fetch_items_loop" ); - _advertise_inventory_loop_done = fc::async( [=]() { advertise_inventory_loop(); }, "advertise_inventory_loop" ); - _terminate_inactive_connections_loop_done = fc::async( [=]() { terminate_inactive_connections_loop(); }, "terminate_inactive_connections_loop" ); - _fetch_updated_peer_lists_loop_done = fc::async([=](){ fetch_updated_peer_lists_loop(); }, "fetch_updated_peer_lists_loop"); - _bandwidth_monitor_loop_done = fc::async([=](){ bandwidth_monitor_loop(); }, "bandwidth_monitor_loop"); - _dump_node_status_task_done = fc::async([=](){ dump_node_status_task(); }, "dump_node_status_task"); + _accept_loop_complete = fc::async( [this](){ accept_loop(); }, "accept_loop"); + + _p2p_network_connect_loop_done = fc::async( [this]() { p2p_network_connect_loop(); }, + "p2p_network_connect_loop" ); + _fetch_sync_items_loop_done = fc::async( [this]() { fetch_sync_items_loop(); }, "fetch_sync_items_loop" ); + _fetch_item_loop_done = fc::async( [this]() { fetch_items_loop(); }, "fetch_items_loop" ); + _advertise_inventory_loop_done = fc::async( [this]() { advertise_inventory_loop(); }, + "advertise_inventory_loop" ); + _kill_inactive_conns_loop_done = fc::async( [this,self]() { kill_inactive_conns_loop(self); }, + "kill_inactive_conns_loop" ); + _fetch_updated_peer_lists_loop_done = fc::async([this](){ fetch_updated_peer_lists_loop(); }, + "fetch_updated_peer_lists_loop"); + _bandwidth_monitor_loop_done = fc::async([this](){ bandwidth_monitor_loop(); }, "bandwidth_monitor_loop"); + _dump_node_status_task_done = fc::async([this](){ dump_node_status_task(); }, "dump_node_status_task"); schedule_next_update_seed_nodes_task(); } @@ -4671,7 +4699,7 @@ namespace graphene { namespace net { namespace detail { void node_impl::broadcast( const message& item_to_broadcast, const message_propagation_data& propagation_data ) { VERIFY_CORRECT_THREAD(); - fc::uint160_t hash_of_message_contents; + message_hash_type hash_of_message_contents; if( item_to_broadcast.msg_type.value() == graphene::net::block_message_type ) { graphene::net::block_message block_message_to_broadcast = item_to_broadcast.as(); @@ -4889,15 +4917,17 @@ namespace graphene { namespace net { namespace detail { #endif // P2P_IN_DEDICATED_THREAD node::node(const std::string& user_agent) : - my(new detail::node_impl(user_agent)) + my(new detail::node_impl(user_agent), detail::node_impl_deleter()) { + // nothing else to do } node::~node() { + // nothing to do } - void node::set_node_delegate( node_delegate* del ) + void node::set_node_delegate( std::shared_ptr del ) const { fc::thread* delegate_thread = &fc::thread::current(); INVOKE_IN_IMPL(set_node_delegate, del, delegate_thread); @@ -4915,7 +4945,7 @@ namespace graphene { namespace net { namespace detail { void node::connect_to_p2p_network() { - INVOKE_IN_IMPL(connect_to_p2p_network); + INVOKE_IN_IMPL(connect_to_p2p_network, my); } void node::add_node( const fc::ip::endpoint& ep ) @@ -5044,63 +5074,6 @@ namespace graphene { namespace net { namespace detail { INVOKE_IN_IMPL(close); } - struct simulated_network::node_info - { - node_delegate* delegate; - fc::future message_sender_task_done; - std::queue messages_to_deliver; - node_info(node_delegate* delegate) : delegate(delegate) {} - }; - - simulated_network::~simulated_network() - { - for( node_info* network_node_info : network_nodes ) - { - network_node_info->message_sender_task_done.cancel_and_wait("~simulated_network()"); - delete network_node_info; - } - } - - void simulated_network::message_sender(node_info* destination_node) - { - while (!destination_node->messages_to_deliver.empty()) - { - try - { - const message& message_to_deliver = destination_node->messages_to_deliver.front(); - if (message_to_deliver.msg_type.value() == trx_message_type) - destination_node->delegate->handle_transaction(message_to_deliver.as()); - else if (message_to_deliver.msg_type.value() == block_message_type) - { - std::vector contained_transaction_message_ids; - destination_node->delegate->handle_block(message_to_deliver.as(), false, contained_transaction_message_ids); - } - else - destination_node->delegate->handle_message(message_to_deliver); - } - catch ( const fc::exception& e ) - { - elog( "${r}", ("r",e) ); - } - destination_node->messages_to_deliver.pop(); - } - } - - void simulated_network::broadcast( const message& item_to_broadcast ) - { - for (node_info* network_node_info : network_nodes) - { - network_node_info->messages_to_deliver.emplace(item_to_broadcast); - if (!network_node_info->message_sender_task_done.valid() || network_node_info->message_sender_task_done.ready()) - network_node_info->message_sender_task_done = fc::async([=](){ message_sender(network_node_info); }, "simulated_network_sender"); - } - } - - void simulated_network::add_node_delegate( node_delegate* node_delegate_to_add ) - { - network_nodes.push_back(new node_info(node_delegate_to_add)); - } - namespace detail { #define ROLLING_WINDOW_SIZE 1000 @@ -5110,7 +5083,8 @@ namespace graphene { namespace net { namespace detail { , BOOST_PP_CAT(_, BOOST_PP_CAT(method_name, _delay_after_accumulator))(boost::accumulators::tag::rolling_window::window_size = ROLLING_WINDOW_SIZE) - statistics_gathering_node_delegate_wrapper::statistics_gathering_node_delegate_wrapper(node_delegate* delegate, fc::thread* thread_for_delegate_calls) : + statistics_gathering_node_delegate_wrapper::statistics_gathering_node_delegate_wrapper( + std::shared_ptr delegate, fc::thread* thread_for_delegate_calls) : _node_delegate(delegate), _thread(thread_for_delegate_calls) BOOST_PP_SEQ_FOR_EACH(INITIALIZE_ACCUMULATOR, unused, NODE_DELEGATE_METHOD_NAMES) @@ -5213,9 +5187,10 @@ namespace graphene { namespace net { namespace detail { INVOKE_AND_COLLECT_STATISTICS(handle_message, message_to_handle); } - bool statistics_gathering_node_delegate_wrapper::handle_block( const graphene::net::block_message& block_message, bool sync_mode, std::vector& contained_transaction_message_ids) + bool statistics_gathering_node_delegate_wrapper::handle_block( const graphene::net::block_message& block_message, + bool sync_mode, std::vector& contained_transaction_msg_ids) { - INVOKE_AND_COLLECT_STATISTICS(handle_block, block_message, sync_mode, contained_transaction_message_ids); + INVOKE_AND_COLLECT_STATISTICS(handle_block, block_message, sync_mode, contained_transaction_msg_ids); } void statistics_gathering_node_delegate_wrapper::handle_transaction( const graphene::net::trx_message& transaction_message ) diff --git a/libraries/net/node_impl.hxx b/libraries/net/node_impl.hxx index f1f44b6046..4cc89d8e0f 100644 --- a/libraries/net/node_impl.hxx +++ b/libraries/net/node_impl.hxx @@ -144,15 +144,16 @@ struct prioritized_item_id class statistics_gathering_node_delegate_wrapper : public node_delegate { -private: - node_delegate *_node_delegate; - fc::thread *_thread; - - typedef boost::accumulators::accumulator_set > call_stats_accumulator; + private: + std::shared_ptr _node_delegate; + fc::thread *_thread; + + using call_stats_accumulator = boost::accumulators::accumulator_set< int64_t, + boost::accumulators::stats< boost::accumulators::tag::min, + boost::accumulators::tag::rolling_mean, + boost::accumulators::tag::max, + boost::accumulators::tag::sum, + boost::accumulators::tag::count> >; #define NODE_DELEGATE_METHOD_NAMES (has_item) \ (handle_message) \ (handle_block) \ @@ -194,7 +195,7 @@ private: { std::shared_ptr _collector; public: - actual_execution_measurement_helper(std::shared_ptr collector) : + explicit actual_execution_measurement_helper(std::shared_ptr collector) : _collector(collector) { _collector->starting_execution(); @@ -245,14 +246,16 @@ private: _execution_completed_time = fc::time_point::now(); } }; - public: - statistics_gathering_node_delegate_wrapper(node_delegate* delegate, fc::thread* thread_for_delegate_calls); + public: + statistics_gathering_node_delegate_wrapper(std::shared_ptr delegate, + fc::thread* thread_for_delegate_calls); fc::variant_object get_call_statistics(); bool has_item( const graphene::net::item_id& id ) override; void handle_message( const message& ) override; - bool handle_block( const graphene::net::block_message& block_message, bool sync_mode, std::vector& contained_transaction_message_ids ) override; + bool handle_block( const graphene::net::block_message& block_message, bool sync_mode, + std::vector& contained_transaction_msg_ids ) override; void handle_transaction( const graphene::net::trx_message& transaction_message ) override; std::vector get_block_ids(const std::vector& blockchain_synopsis, uint32_t& remaining_item_count, @@ -269,9 +272,9 @@ private: uint32_t estimate_last_known_fork_from_git_revision_timestamp(uint32_t unix_timestamp) const override; void error_encountered(const std::string& message, const fc::oexception& error) override; uint8_t get_current_block_interval_in_seconds() const override; - }; +}; -class node_impl : public peer_connection_delegate +class node_impl : public peer_connection_delegate, public std::enable_shared_from_this { public: #ifdef P2P_IN_DEDICATED_THREAD @@ -348,7 +351,7 @@ class node_impl : public peer_connection_delegate concurrent_unordered_set _new_inventory; /// @} - fc::future _terminate_inactive_connections_loop_done; + fc::future _kill_inactive_conns_loop_done; uint8_t _recent_block_interval_in_seconds; // a cached copy of the block interval, to avoid a thread hop to the blockchain to get the current value std::string _user_agent_string; @@ -475,7 +478,7 @@ class node_impl : public peer_connection_delegate void advertise_inventory_loop(); void trigger_advertise_inventory_loop(); - void terminate_inactive_connections_loop(); + void kill_inactive_conns_loop(node_impl_ptr self); void fetch_updated_peer_lists_loop(); void update_bandwidth_data(uint32_t bytes_read_this_second, uint32_t bytes_written_this_second); @@ -558,11 +561,23 @@ class node_impl : public peer_connection_delegate void send_sync_block_to_node_delegate(const graphene::net::block_message& block_message_to_send); void process_backlog_of_sync_blocks(); void trigger_process_backlog_of_sync_blocks(); - void process_block_during_sync(peer_connection* originating_peer, const graphene::net::block_message& block_message, const message_hash_type& message_hash); - void process_block_during_normal_operation(peer_connection* originating_peer, const graphene::net::block_message& block_message, const message_hash_type& message_hash); - void process_block_message(peer_connection* originating_peer, const message& message_to_process, const message_hash_type& message_hash); - - void process_ordinary_message(peer_connection* originating_peer, const message& message_to_process, const message_hash_type& message_hash); + void process_block_during_syncing( + peer_connection* originating_peer, + const graphene::net::block_message& block_message, + const message_hash_type& message_hash); + void process_block_when_in_sync( + peer_connection* originating_peer, + const graphene::net::block_message& block_message, + const message_hash_type& message_hash); + void process_block_message( + peer_connection* originating_peer, + const message& message_to_process, + const message_hash_type& message_hash); + + void process_ordinary_message( + peer_connection* originating_peer, + const message& message_to_process, + const message_hash_type& message_hash); void start_synchronizing(); void start_synchronizing_with_peer(const peer_connection_ptr& peer); @@ -594,10 +609,10 @@ class node_impl : public peer_connection_delegate const fc::oexception& additional_data = fc::oexception() ); // methods implementing node's public interface - void set_node_delegate(node_delegate* del, fc::thread* thread_for_delegate_calls); + void set_node_delegate(std::shared_ptr del, fc::thread* thread_for_delegate_calls); void load_configuration( const fc::path& configuration_directory ); void listen_to_p2p_network(); - void connect_to_p2p_network(); + void connect_to_p2p_network(node_impl_ptr self); void add_node( const fc::ip::endpoint& ep ); void add_seed_node( const std::string& seed_string ); void resolve_seed_node_and_add( const std::string& seed_string ); @@ -637,4 +652,9 @@ class node_impl : public peer_connection_delegate uint32_t get_next_known_hard_fork_block_number(uint32_t block_number) const; }; // end class node_impl + struct node_impl_deleter + { + void operator()(node_impl*); + }; + }}} // end of namespace graphene::net::detail diff --git a/libraries/plugins/account_history/account_history_plugin.cpp b/libraries/plugins/account_history/account_history_plugin.cpp index c0bbcebc2e..dd8a5c6215 100644 --- a/libraries/plugins/account_history/account_history_plugin.cpp +++ b/libraries/plugins/account_history/account_history_plugin.cpp @@ -46,11 +46,9 @@ namespace detail class account_history_plugin_impl { public: - account_history_plugin_impl(account_history_plugin& _plugin) + explicit account_history_plugin_impl(account_history_plugin& _plugin) : _self( _plugin ) { } - virtual ~account_history_plugin_impl(); - /** this method is called as a callback after a block is applied * and will process/index all operations that were applied in the block. @@ -62,6 +60,9 @@ class account_history_plugin_impl return _self.database(); } + friend class graphene::account_history::account_history_plugin; + + private: account_history_plugin& _self; flat_set _tracked_accounts; flat_set _extended_history_accounts; @@ -70,17 +71,12 @@ class account_history_plugin_impl primary_index< operation_history_index >* _oho_index; uint64_t _max_ops_per_account = -1; uint64_t _extended_max_ops_per_account = -1; - private: + /** add one history record, then check and remove the earliest history record */ void add_account_history( const account_id_type account_id, const operation_history_id_type op_id ); }; -account_history_plugin_impl::~account_history_plugin_impl() -{ - return; -} - void account_history_plugin_impl::update_account_histories( const signed_block& b ) { graphene::chain::database& db = database(); @@ -282,14 +278,14 @@ void account_history_plugin_impl::add_account_history( const account_id_type acc -account_history_plugin::account_history_plugin() : +account_history_plugin::account_history_plugin(graphene::app::application& app) : + plugin(app), my( std::make_unique(*this) ) { + // Nothing else to do } -account_history_plugin::~account_history_plugin() -{ -} +account_history_plugin::~account_history_plugin() = default; std::string account_history_plugin::plugin_name()const { diff --git a/libraries/plugins/account_history/include/graphene/account_history/account_history_plugin.hpp b/libraries/plugins/account_history/include/graphene/account_history/account_history_plugin.hpp index 99492768ce..6ceda572a7 100644 --- a/libraries/plugins/account_history/include/graphene/account_history/account_history_plugin.hpp +++ b/libraries/plugins/account_history/include/graphene/account_history/account_history_plugin.hpp @@ -64,19 +64,19 @@ namespace detail class account_history_plugin : public graphene::app::plugin { public: - account_history_plugin(); - virtual ~account_history_plugin(); + explicit account_history_plugin(graphene::app::application& app); + ~account_history_plugin() override; std::string plugin_name()const override; - virtual void plugin_set_program_options( + void plugin_set_program_options( boost::program_options::options_description& cli, boost::program_options::options_description& cfg) override; - virtual void plugin_initialize(const boost::program_options::variables_map& options) override; - virtual void plugin_startup() override; + void plugin_initialize(const boost::program_options::variables_map& options) override; + void plugin_startup() override; flat_set tracked_accounts()const; - friend class detail::account_history_plugin_impl; + private: std::unique_ptr my; }; diff --git a/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp b/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp index 548c5fc689..79c996399c 100644 --- a/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp +++ b/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp @@ -133,7 +133,7 @@ namespace detail class api_helper_indexes_impl { public: - api_helper_indexes_impl(api_helper_indexes& _plugin) + explicit api_helper_indexes_impl(api_helper_indexes& _plugin) : _self( _plugin ) { } @@ -142,22 +142,20 @@ class api_helper_indexes_impl return _self.database(); } - api_helper_indexes& _self; - private: - + api_helper_indexes& _self; }; } // end namespace detail -api_helper_indexes::api_helper_indexes() : +api_helper_indexes::api_helper_indexes(graphene::app::application& app) : + plugin(app), my( std::make_unique(*this) ) { + // Nothing else to do } -api_helper_indexes::~api_helper_indexes() -{ -} +api_helper_indexes::~api_helper_indexes() = default; std::string api_helper_indexes::plugin_name()const { diff --git a/libraries/plugins/api_helper_indexes/include/graphene/api_helper_indexes/api_helper_indexes.hpp b/libraries/plugins/api_helper_indexes/include/graphene/api_helper_indexes/api_helper_indexes.hpp index 49b79bee90..bfd7502ab1 100644 --- a/libraries/plugins/api_helper_indexes/include/graphene/api_helper_indexes/api_helper_indexes.hpp +++ b/libraries/plugins/api_helper_indexes/include/graphene/api_helper_indexes/api_helper_indexes.hpp @@ -79,8 +79,8 @@ namespace detail class api_helper_indexes : public graphene::app::plugin { public: - api_helper_indexes(); - virtual ~api_helper_indexes(); + explicit api_helper_indexes(graphene::app::application& app); + ~api_helper_indexes() override; std::string plugin_name()const override; std::string plugin_description()const override; diff --git a/libraries/plugins/custom_operations/custom_operations_plugin.cpp b/libraries/plugins/custom_operations/custom_operations_plugin.cpp index c9c6b21f18..e9fb5b971c 100644 --- a/libraries/plugins/custom_operations/custom_operations_plugin.cpp +++ b/libraries/plugins/custom_operations/custom_operations_plugin.cpp @@ -35,10 +35,9 @@ namespace detail class custom_operations_plugin_impl { public: - custom_operations_plugin_impl(custom_operations_plugin& _plugin) + explicit custom_operations_plugin_impl(custom_operations_plugin& _plugin) : _self( _plugin ) { } - virtual ~custom_operations_plugin_impl(); void onBlock(); @@ -47,12 +46,12 @@ class custom_operations_plugin_impl return _self.database(); } - custom_operations_plugin& _self; - - uint32_t _start_block = 45000000; + friend class graphene::custom_operations::custom_operations_plugin; private: + custom_operations_plugin& _self; + uint32_t _start_block = 45000000; }; struct custom_op_visitor @@ -98,21 +97,16 @@ void custom_operations_plugin_impl::onBlock() } } -custom_operations_plugin_impl::~custom_operations_plugin_impl() -{ - return; -} - } // end namespace detail -custom_operations_plugin::custom_operations_plugin() : +custom_operations_plugin::custom_operations_plugin(graphene::app::application& app) : + plugin(app), my( std::make_unique(*this) ) { + // Nothing to do } -custom_operations_plugin::~custom_operations_plugin() -{ -} +custom_operations_plugin::~custom_operations_plugin() = default; std::string custom_operations_plugin::plugin_name()const { diff --git a/libraries/plugins/custom_operations/include/graphene/custom_operations/custom_operations_plugin.hpp b/libraries/plugins/custom_operations/include/graphene/custom_operations/custom_operations_plugin.hpp index f4baacd573..add8ce8637 100644 --- a/libraries/plugins/custom_operations/include/graphene/custom_operations/custom_operations_plugin.hpp +++ b/libraries/plugins/custom_operations/include/graphene/custom_operations/custom_operations_plugin.hpp @@ -41,18 +41,18 @@ namespace detail class custom_operations_plugin : public graphene::app::plugin { public: - custom_operations_plugin(); - virtual ~custom_operations_plugin(); + explicit custom_operations_plugin(graphene::app::application& app); + ~custom_operations_plugin() override; std::string plugin_name()const override; std::string plugin_description()const override; - virtual void plugin_set_program_options( + void plugin_set_program_options( boost::program_options::options_description& cli, boost::program_options::options_description& cfg) override; - virtual void plugin_initialize(const boost::program_options::variables_map& options) override; - virtual void plugin_startup() override; + void plugin_initialize(const boost::program_options::variables_map& options) override; + void plugin_startup() override; - friend class detail::custom_operations_plugin_impl; + private: std::unique_ptr my; }; diff --git a/libraries/plugins/debug_witness/debug_api.cpp b/libraries/plugins/debug_witness/debug_api.cpp index 43ffd6cd38..7fd8792af5 100644 --- a/libraries/plugins/debug_witness/debug_api.cpp +++ b/libraries/plugins/debug_witness/debug_api.cpp @@ -34,7 +34,9 @@ class debug_api_impl }; debug_api_impl::debug_api_impl( graphene::app::application& _app ) : app( _app ) -{} +{ + // Nothing else to do +} void debug_api_impl::debug_push_blocks( const std::string& src_filename, uint32_t count ) diff --git a/libraries/plugins/debug_witness/debug_witness.cpp b/libraries/plugins/debug_witness/debug_witness.cpp index ea7f209fa6..1a9533166a 100644 --- a/libraries/plugins/debug_witness/debug_witness.cpp +++ b/libraries/plugins/debug_witness/debug_witness.cpp @@ -38,7 +38,10 @@ using std::vector; namespace bpo = boost::program_options; -debug_witness_plugin::~debug_witness_plugin() {} +debug_witness_plugin::~debug_witness_plugin() +{ + cleanup(); +} void debug_witness_plugin::plugin_set_program_options( boost::program_options::options_description& command_line_options, @@ -100,7 +103,6 @@ void debug_witness_plugin::plugin_startup() _changed_objects_conn = db.changed_objects.connect([this](const std::vector& ids, const fc::flat_set& impacted_accounts){ on_changed_objects(ids, impacted_accounts); }); _removed_objects_conn = db.removed_objects.connect([this](const std::vector& ids, const std::vector& objs, const fc::flat_set& impacted_accounts){ on_removed_objects(ids, objs, impacted_accounts); }); - return; } void debug_witness_plugin::on_changed_objects( const std::vector& ids, const fc::flat_set& impacted_accounts ) @@ -155,11 +157,15 @@ void debug_witness_plugin::flush_json_object_stream() } void debug_witness_plugin::plugin_shutdown() +{ + cleanup(); +} + +void debug_witness_plugin::cleanup() { if( _json_object_stream ) { _json_object_stream->close(); _json_object_stream.reset(); } - return; } diff --git a/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_witness.hpp b/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_witness.hpp index 4b5369211a..92f1b21d74 100644 --- a/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_witness.hpp +++ b/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_witness.hpp @@ -34,23 +34,25 @@ namespace graphene { namespace debug_witness_plugin { class debug_witness_plugin : public graphene::app::plugin { public: - ~debug_witness_plugin(); + using graphene::app::plugin::plugin; + ~debug_witness_plugin() override; std::string plugin_name()const override; - virtual void plugin_set_program_options( + void plugin_set_program_options( boost::program_options::options_description &command_line_options, boost::program_options::options_description &config_file_options ) override; - virtual void plugin_initialize( const boost::program_options::variables_map& options ) override; - virtual void plugin_startup() override; - virtual void plugin_shutdown() override; + void plugin_initialize( const boost::program_options::variables_map& options ) override; + void plugin_startup() override; + void plugin_shutdown() override; void set_json_object_stream( const std::string& filename ); void flush_json_object_stream(); private: + void cleanup(); void on_changed_objects( const std::vector& ids, const fc::flat_set& impacted_accounts ); void on_removed_objects( const std::vector& ids, const std::vector objs, const fc::flat_set& impacted_accounts ); diff --git a/libraries/plugins/delayed_node/delayed_node_plugin.cpp b/libraries/plugins/delayed_node/delayed_node_plugin.cpp index d85b6291e7..b16aadd233 100644 --- a/libraries/plugins/delayed_node/delayed_node_plugin.cpp +++ b/libraries/plugins/delayed_node/delayed_node_plugin.cpp @@ -46,17 +46,19 @@ struct delayed_node_plugin_impl { }; } -delayed_node_plugin::delayed_node_plugin() - : my(nullptr) -{} +delayed_node_plugin::delayed_node_plugin(graphene::app::application& app) : + plugin(app) +{ + // Nothing else to do +} -delayed_node_plugin::~delayed_node_plugin() -{} +delayed_node_plugin::~delayed_node_plugin() = default; void delayed_node_plugin::plugin_set_program_options(bpo::options_description& cli, bpo::options_description& cfg) { cli.add_options() - ("trusted-node", boost::program_options::value(), "RPC endpoint of a trusted validating node (required for delayed_node)") + ("trusted-node", boost::program_options::value(), + "RPC endpoint of a trusted validating node (required for delayed_node)") ; cfg.add(cli); } diff --git a/libraries/plugins/delayed_node/include/graphene/delayed_node/delayed_node_plugin.hpp b/libraries/plugins/delayed_node/include/graphene/delayed_node/delayed_node_plugin.hpp index 509ef4c717..448d979782 100644 --- a/libraries/plugins/delayed_node/include/graphene/delayed_node/delayed_node_plugin.hpp +++ b/libraries/plugins/delayed_node/include/graphene/delayed_node/delayed_node_plugin.hpp @@ -32,14 +32,14 @@ class delayed_node_plugin : public graphene::app::plugin { std::unique_ptr my; public: - delayed_node_plugin(); - virtual ~delayed_node_plugin(); + explicit delayed_node_plugin(graphene::app::application& app); + ~delayed_node_plugin() override; std::string plugin_name()const override { return "delayed_node"; } - virtual void plugin_set_program_options(boost::program_options::options_description&, - boost::program_options::options_description& cfg) override; - virtual void plugin_initialize(const boost::program_options::variables_map& options) override; - virtual void plugin_startup() override; + void plugin_set_program_options(boost::program_options::options_description&, + boost::program_options::options_description& cfg) override; + void plugin_initialize(const boost::program_options::variables_map& options) override; + void plugin_startup() override; void mainloop(); protected: diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index 3d80c64f1c..d583afccc0 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -36,7 +36,7 @@ namespace detail class elasticsearch_plugin_impl { public: - elasticsearch_plugin_impl(elasticsearch_plugin& _plugin) + explicit elasticsearch_plugin_impl(elasticsearch_plugin& _plugin) : _self( _plugin ) { curl = curl_easy_init(); @@ -102,7 +102,6 @@ elasticsearch_plugin_impl::~elasticsearch_plugin_impl() curl_easy_cleanup(curl); curl = nullptr; } - return; } bool elasticsearch_plugin_impl::update_account_histories( const signed_block& b ) @@ -433,14 +432,14 @@ void elasticsearch_plugin_impl::populateESstruct() } // end namespace detail -elasticsearch_plugin::elasticsearch_plugin() : +elasticsearch_plugin::elasticsearch_plugin(graphene::app::application& app) : + plugin(app), my( std::make_unique(*this) ) { + // Nothing else to do } -elasticsearch_plugin::~elasticsearch_plugin() -{ -} +elasticsearch_plugin::~elasticsearch_plugin() = default; std::string elasticsearch_plugin::plugin_name()const { diff --git a/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp b/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp index 7b08e1d73f..fbd8366b3f 100644 --- a/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp +++ b/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp @@ -55,16 +55,16 @@ enum mode { only_save = 0 , only_query = 1, all = 2 }; class elasticsearch_plugin : public graphene::app::plugin { public: - elasticsearch_plugin(); - virtual ~elasticsearch_plugin(); + explicit elasticsearch_plugin(graphene::app::application& app); + ~elasticsearch_plugin() override; std::string plugin_name()const override; std::string plugin_description()const override; - virtual void plugin_set_program_options( + void plugin_set_program_options( boost::program_options::options_description& cli, boost::program_options::options_description& cfg) override; - virtual void plugin_initialize(const boost::program_options::variables_map& options) override; - virtual void plugin_startup() override; + void plugin_initialize(const boost::program_options::variables_map& options) override; + void plugin_startup() override; operation_history_object get_operation_by_id(operation_history_id_type id); vector get_account_history(const account_id_type account_id, diff --git a/libraries/plugins/es_objects/es_objects.cpp b/libraries/plugins/es_objects/es_objects.cpp index 7be78a2630..2e0fd4613e 100644 --- a/libraries/plugins/es_objects/es_objects.cpp +++ b/libraries/plugins/es_objects/es_objects.cpp @@ -41,7 +41,7 @@ namespace detail class es_objects_plugin_impl { public: - es_objects_plugin_impl(es_objects_plugin& _plugin) + explicit es_objects_plugin_impl(es_objects_plugin& _plugin) : _self( _plugin ) { curl = curl_easy_init(); @@ -269,19 +269,18 @@ es_objects_plugin_impl::~es_objects_plugin_impl() curl_easy_cleanup(curl); curl = nullptr; } - return; } } // end namespace detail -es_objects_plugin::es_objects_plugin() : +es_objects_plugin::es_objects_plugin(graphene::app::application& app) : + plugin(app), my( std::make_unique(*this) ) { + // Nothing else to do } -es_objects_plugin::~es_objects_plugin() -{ -} +es_objects_plugin::~es_objects_plugin() = default; std::string es_objects_plugin::plugin_name()const { diff --git a/libraries/plugins/es_objects/include/graphene/es_objects/es_objects.hpp b/libraries/plugins/es_objects/include/graphene/es_objects/es_objects.hpp index fa91e3bde4..dff4812498 100644 --- a/libraries/plugins/es_objects/include/graphene/es_objects/es_objects.hpp +++ b/libraries/plugins/es_objects/include/graphene/es_objects/es_objects.hpp @@ -38,18 +38,18 @@ namespace detail class es_objects_plugin : public graphene::app::plugin { public: - es_objects_plugin(); - virtual ~es_objects_plugin(); + explicit es_objects_plugin(graphene::app::application& app); + ~es_objects_plugin() override; std::string plugin_name()const override; std::string plugin_description()const override; - virtual void plugin_set_program_options( + void plugin_set_program_options( boost::program_options::options_description& cli, boost::program_options::options_description& cfg) override; - virtual void plugin_initialize(const boost::program_options::variables_map& options) override; - virtual void plugin_startup() override; + void plugin_initialize(const boost::program_options::variables_map& options) override; + void plugin_startup() override; - friend class detail::es_objects_plugin_impl; + private: std::unique_ptr my; }; diff --git a/libraries/plugins/grouped_orders/grouped_orders_plugin.cpp b/libraries/plugins/grouped_orders/grouped_orders_plugin.cpp index b83ee7d8f7..b745ea494c 100644 --- a/libraries/plugins/grouped_orders/grouped_orders_plugin.cpp +++ b/libraries/plugins/grouped_orders/grouped_orders_plugin.cpp @@ -34,9 +34,8 @@ namespace detail class grouped_orders_plugin_impl { public: - grouped_orders_plugin_impl(grouped_orders_plugin& _plugin) + explicit grouped_orders_plugin_impl(grouped_orders_plugin& _plugin) :_self( _plugin ) {} - virtual ~grouped_orders_plugin_impl(); graphene::chain::database& database() { @@ -235,20 +234,17 @@ void limit_order_group_index::remove_order( const limit_order_object& o, bool re } } -grouped_orders_plugin_impl::~grouped_orders_plugin_impl() -{} - } // end namespace detail -grouped_orders_plugin::grouped_orders_plugin() : +grouped_orders_plugin::grouped_orders_plugin(graphene::app::application& app) : + plugin(app), my( std::make_unique(*this) ) { + // Nothing else to do } -grouped_orders_plugin::~grouped_orders_plugin() -{ -} +grouped_orders_plugin::~grouped_orders_plugin() = default; std::string grouped_orders_plugin::plugin_name()const { diff --git a/libraries/plugins/grouped_orders/include/graphene/grouped_orders/grouped_orders_plugin.hpp b/libraries/plugins/grouped_orders/include/graphene/grouped_orders/grouped_orders_plugin.hpp index 8f91ccbd9c..4a0e4452ea 100644 --- a/libraries/plugins/grouped_orders/include/graphene/grouped_orders/grouped_orders_plugin.hpp +++ b/libraries/plugins/grouped_orders/include/graphene/grouped_orders/grouped_orders_plugin.hpp @@ -69,23 +69,22 @@ namespace detail class grouped_orders_plugin : public graphene::app::plugin { public: - grouped_orders_plugin(); - virtual ~grouped_orders_plugin(); + explicit grouped_orders_plugin(graphene::app::application& app); + ~grouped_orders_plugin() override; std::string plugin_name()const override; - virtual void plugin_set_program_options( + void plugin_set_program_options( boost::program_options::options_description& cli, boost::program_options::options_description& cfg) override; - virtual void plugin_initialize( + void plugin_initialize( const boost::program_options::variables_map& options) override; - virtual void plugin_startup() override; + void plugin_startup() override; const flat_set& tracked_groups()const; const map< limit_order_group_key, limit_order_group_data >& limit_order_groups(); private: - friend class detail::grouped_orders_plugin_impl; std::unique_ptr my; }; diff --git a/libraries/plugins/market_history/include/graphene/market_history/market_history_plugin.hpp b/libraries/plugins/market_history/include/graphene/market_history/market_history_plugin.hpp index 4007b11d15..bc70ae8794 100644 --- a/libraries/plugins/market_history/include/graphene/market_history/market_history_plugin.hpp +++ b/libraries/plugins/market_history/include/graphene/market_history/market_history_plugin.hpp @@ -380,16 +380,16 @@ namespace detail class market_history_plugin : public graphene::app::plugin { public: - market_history_plugin(); - virtual ~market_history_plugin(); + explicit market_history_plugin(graphene::app::application& app); + ~market_history_plugin() override; std::string plugin_name()const override; - virtual void plugin_set_program_options( + void plugin_set_program_options( boost::program_options::options_description& cli, boost::program_options::options_description& cfg) override; - virtual void plugin_initialize( + void plugin_initialize( const boost::program_options::variables_map& options) override; - virtual void plugin_startup() override; + void plugin_startup() override; uint32_t max_history()const; const flat_set& tracked_buckets()const; @@ -397,7 +397,6 @@ class market_history_plugin : public graphene::app::plugin uint32_t max_order_his_seconds_per_market()const; private: - friend class detail::market_history_plugin_impl; std::unique_ptr my; }; diff --git a/libraries/plugins/market_history/market_history_plugin.cpp b/libraries/plugins/market_history/market_history_plugin.cpp index b6d3800d4a..adca4f5b77 100644 --- a/libraries/plugins/market_history/market_history_plugin.cpp +++ b/libraries/plugins/market_history/market_history_plugin.cpp @@ -43,9 +43,8 @@ namespace detail class market_history_plugin_impl { public: - market_history_plugin_impl(market_history_plugin& _plugin) + explicit market_history_plugin_impl(market_history_plugin& _plugin) :_self( _plugin ) {} - virtual ~market_history_plugin_impl(); /** this method is called as a callback after a block is applied * and will process/index all operations that were applied in the block. @@ -294,9 +293,6 @@ struct operation_process_fill_order } }; -market_history_plugin_impl::~market_history_plugin_impl() -{} - void market_history_plugin_impl::update_market_histories( const signed_block& b ) { graphene::chain::database& db = database(); @@ -731,18 +727,14 @@ void market_history_plugin_impl::update_liquidity_pool_histories( } // end namespace detail - - - - -market_history_plugin::market_history_plugin() : +market_history_plugin::market_history_plugin(graphene::app::application& app) : + plugin(app), my( std::make_unique(*this) ) { + // Nothing else to do } -market_history_plugin::~market_history_plugin() -{ -} +market_history_plugin::~market_history_plugin() = default; std::string market_history_plugin::plugin_name()const { diff --git a/libraries/plugins/snapshot/include/graphene/snapshot/snapshot.hpp b/libraries/plugins/snapshot/include/graphene/snapshot/snapshot.hpp index eb8d3a16cb..c4de7b7624 100644 --- a/libraries/plugins/snapshot/include/graphene/snapshot/snapshot.hpp +++ b/libraries/plugins/snapshot/include/graphene/snapshot/snapshot.hpp @@ -32,19 +32,17 @@ namespace graphene { namespace snapshot_plugin { class snapshot_plugin : public graphene::app::plugin { public: - ~snapshot_plugin() {} + using graphene::app::plugin::plugin; std::string plugin_name()const override; std::string plugin_description()const override; - virtual void plugin_set_program_options( + void plugin_set_program_options( boost::program_options::options_description &command_line_options, boost::program_options::options_description &config_file_options ) override; - virtual void plugin_initialize( const boost::program_options::variables_map& options ) override; - virtual void plugin_startup() override; - virtual void plugin_shutdown() override; + void plugin_initialize( const boost::program_options::variables_map& options ) override; private: void check_snapshot( const graphene::chain::signed_block& b); diff --git a/libraries/plugins/snapshot/snapshot.cpp b/libraries/plugins/snapshot/snapshot.cpp index a7e9d5138c..12a0553417 100644 --- a/libraries/plugins/snapshot/snapshot.cpp +++ b/libraries/plugins/snapshot/snapshot.cpp @@ -82,10 +82,6 @@ void snapshot_plugin::plugin_initialize(const boost::program_options::variables_ ilog("snapshot plugin: plugin_initialize() end"); } FC_LOG_AND_RETHROW() } -void snapshot_plugin::plugin_startup() {} - -void snapshot_plugin::plugin_shutdown() {} - static void create_snapshot( const graphene::chain::database& db, const fc::path& dest ) { ilog("snapshot plugin: creating snapshot"); diff --git a/libraries/plugins/template_plugin/include/graphene/template_plugin/template_plugin.hpp b/libraries/plugins/template_plugin/include/graphene/template_plugin/template_plugin.hpp index 168dac42bf..b9ccee9b79 100644 --- a/libraries/plugins/template_plugin/include/graphene/template_plugin/template_plugin.hpp +++ b/libraries/plugins/template_plugin/include/graphene/template_plugin/template_plugin.hpp @@ -52,18 +52,20 @@ namespace detail class template_plugin : public graphene::app::plugin { public: - template_plugin(); - virtual ~template_plugin(); + explicit template_plugin(graphene::app::application& app); + ~template_plugin() override; std::string plugin_name()const override; std::string plugin_description()const override; - virtual void plugin_set_program_options( + void plugin_set_program_options( boost::program_options::options_description& cli, boost::program_options::options_description& cfg) override; - virtual void plugin_initialize(const boost::program_options::variables_map& options) override; - virtual void plugin_startup() override; + void plugin_initialize(const boost::program_options::variables_map& options) override; + void plugin_startup() override; + void plugin_shutdown() override; - friend class detail::template_plugin_impl; + private: + void cleanup(); std::unique_ptr my; }; diff --git a/libraries/plugins/template_plugin/template_plugin.cpp b/libraries/plugins/template_plugin/template_plugin.cpp index 7c2cfbc831..72020a8588 100644 --- a/libraries/plugins/template_plugin/template_plugin.cpp +++ b/libraries/plugins/template_plugin/template_plugin.cpp @@ -32,45 +32,53 @@ namespace detail class template_plugin_impl { public: - template_plugin_impl(template_plugin& _plugin) - : _self( _plugin ) - { } + explicit template_plugin_impl( template_plugin& _plugin ); virtual ~template_plugin_impl(); - void onBlock( const signed_block& b ); + void on_block( const signed_block& b ); graphene::chain::database& database() { return _self.database(); } + friend class graphene::template_plugin::template_plugin; + + private: template_plugin& _self; std::string _plugin_option = ""; - private: - }; -void template_plugin_impl::onBlock( const signed_block& b ) +void template_plugin_impl::on_block( const signed_block& b ) { wdump((b.block_num())); } +template_plugin_impl::template_plugin_impl( template_plugin& _plugin ) : + _self( _plugin ) +{ + // Put other code here +} + template_plugin_impl::~template_plugin_impl() { - return; + // Put the real code here. If none, remove the destructor. } } // end namespace detail -template_plugin::template_plugin() : - my( new detail::template_plugin_impl(*this) ) +template_plugin::template_plugin(graphene::app::application& app) : + plugin(app), + my( std::make_unique(*this) ) { + // Add needed code here } template_plugin::~template_plugin() { + cleanup(); } std::string template_plugin::plugin_name()const @@ -96,7 +104,7 @@ void template_plugin::plugin_set_program_options( void template_plugin::plugin_initialize(const boost::program_options::variables_map& options) { database().applied_block.connect( [&]( const signed_block& b) { - my->onBlock(b); + my->on_block(b); } ); if (options.count("template_plugin") > 0) { @@ -109,4 +117,15 @@ void template_plugin::plugin_startup() ilog("template_plugin: plugin_startup() begin"); } +void template_plugin::plugin_shutdown() +{ + ilog("template_plugin: plugin_shutdown() begin"); + cleanup(); +} + +void template_plugin::cleanup() +{ + // Add cleanup code here +} + } } diff --git a/libraries/plugins/witness/include/graphene/witness/witness.hpp b/libraries/plugins/witness/include/graphene/witness/witness.hpp index 8ca09a5b27..e3e1497af2 100644 --- a/libraries/plugins/witness/include/graphene/witness/witness.hpp +++ b/libraries/plugins/witness/include/graphene/witness/witness.hpp @@ -42,17 +42,19 @@ namespace block_production_condition low_participation = 5, lag = 6, exception_producing_block = 7, - shutdown = 8 + shutdown = 8, + no_network = 9 }; } class witness_plugin : public graphene::app::plugin { public: - ~witness_plugin() { stop_block_production(); } + using graphene::app::plugin::plugin; + ~witness_plugin() override { cleanup(); } std::string plugin_name()const override; - virtual void plugin_set_program_options( + void plugin_set_program_options( boost::program_options::options_description &command_line_options, boost::program_options::options_description &config_file_options ) override; @@ -60,14 +62,16 @@ class witness_plugin : public graphene::app::plugin { void set_block_production(bool allow) { _production_enabled = allow; } void stop_block_production(); - virtual void plugin_initialize( const boost::program_options::variables_map& options ) override; - virtual void plugin_startup() override; - virtual void plugin_shutdown() override; + void plugin_initialize( const boost::program_options::variables_map& options ) override; + void plugin_startup() override; + void plugin_shutdown() override { cleanup(); } inline const fc::flat_map< chain::witness_id_type, fc::optional >& get_witness_key_cache() { return _witness_key_cache; } private: + void cleanup() { stop_block_production(); } + void schedule_production_loop(); block_production_condition::block_production_condition_enum block_production_loop(); block_production_condition::block_production_condition_enum maybe_produce_block( fc::limited_mutable_variant_object& capture ); diff --git a/libraries/plugins/witness/witness.cpp b/libraries/plugins/witness/witness.cpp index 88e1499086..1d9ad36c9e 100644 --- a/libraries/plugins/witness/witness.cpp +++ b/libraries/plugins/witness/witness.cpp @@ -195,11 +195,6 @@ void witness_plugin::plugin_startup() ilog("witness plugin: plugin_startup() end"); } FC_CAPTURE_AND_RETHROW() } -void witness_plugin::plugin_shutdown() -{ - stop_block_production(); -} - void witness_plugin::stop_block_production() { _shutting_down = true; @@ -300,6 +295,9 @@ block_production_condition::block_production_condition_enum witness_plugin::bloc case block_production_condition::shutdown: ilog( "shutdown producing block" ); return result; + case block_production_condition::no_network: + ilog( "not connected to P2P network" ); + return result; default: elog( "unknown condition ${result} while producing block", ("result", (unsigned char)result) ); break; @@ -374,6 +372,9 @@ block_production_condition::block_production_condition_enum witness_plugin::mayb return block_production_condition::lag; } + if( p2p_node() == nullptr ) + return block_production_condition::no_network; + auto block = db.generate_block( scheduled_time, scheduled_witness, @@ -381,7 +382,7 @@ block_production_condition::block_production_condition_enum witness_plugin::mayb _production_skip_flags ); capture("n", block.block_num())("t", block.timestamp)("c", now)("x", block.transactions.size()); - fc::async( [this,block](){ p2p_node().broadcast(net::block_message(block)); } ); + fc::async( [this,block](){ p2p_node()->broadcast(net::block_message(block)); } ); return block_production_condition::produced; } diff --git a/programs/witness_node/main.cpp b/programs/witness_node/main.cpp index b2dd6d77d6..50f1562d63 100644 --- a/programs/witness_node/main.cpp +++ b/programs/witness_node/main.cpp @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include #include @@ -49,20 +51,36 @@ #include #include -#include +#include #ifdef WIN32 -# include +# include #else # include #endif -using namespace graphene; namespace bpo = boost::program_options; +/// Disable default logging +void disable_default_logging() +{ + fc::configure_logging( fc::logging_config() ); +} + +/// Hack to log messages to console with default color and no format via fc::console_appender +// TODO fix console_appender and use ilog() or etc instead: 1) stream is always stderr, 2) format can not change +void my_log( const std::string& s ) +{ + static fc::console_appender::config my_console_config; + static fc::console_appender my_appender( my_console_config ); + my_appender.print(s); + my_appender.print("\n"); // This is needed, otherwise the next message will cover it +} + +/// The main program int main(int argc, char** argv) { fc::print_stacktrace_on_segfault(); - auto node = std::make_unique(); + auto node = std::make_unique(); fc::oexception unhandled_exception; try { bpo::options_description app_options("BitShares Witness Node"); @@ -78,9 +96,11 @@ int main(int argc, char** argv) { "Space-separated list of plugins to activate") ("ignore-api-helper-indexes-warning", "Do not exit if api_helper_indexes plugin is not enabled."); - bpo::variables_map options; + auto sharable_options = std::make_shared(); + auto& options = *sharable_options; - bpo::options_description cli, cfg; + bpo::options_description cli; + bpo::options_description cfg; node->set_program_options(cli, cfg); cfg_options.add(cfg); @@ -89,47 +109,59 @@ int main(int argc, char** argv) { "Space-separated list of plugins to activate") ("ignore-api-helper-indexes-warning", "Do not exit if api_helper_indexes plugin is not enabled."); - auto witness_plug = node->register_plugin(); - auto debug_witness_plug = node->register_plugin(); - auto history_plug = node->register_plugin(); - auto elasticsearch_plug = node->register_plugin(); - auto market_history_plug = node->register_plugin(); - auto delayed_plug = node->register_plugin(); - auto snapshot_plug = node->register_plugin(); - auto es_objects_plug = node->register_plugin(); - auto grouped_orders_plug = node->register_plugin(); - auto api_helper_indexes_plug = node->register_plugin(); - auto custom_operations_plug = node->register_plugin(); + node->register_plugin(); + node->register_plugin(); + node->register_plugin(); + node->register_plugin(); + node->register_plugin(); + node->register_plugin(); + node->register_plugin(); + node->register_plugin(); + node->register_plugin(); + node->register_plugin(); + node->register_plugin(); // add plugin options to config try { - bpo::options_description cli, cfg; - node->set_program_options(cli, cfg); - app_options.add(cli); - cfg_options.add(cfg); + bpo::options_description tmp_cli; + bpo::options_description tmp_cfg; + node->set_program_options(tmp_cli, tmp_cfg); + app_options.add(tmp_cli); + cfg_options.add(tmp_cfg); bpo::store(bpo::parse_command_line(argc, argv, app_options), options); } catch (const boost::program_options::error& e) { - std::cerr << "Error parsing command line: " << e.what() << "\n"; - return 1; + disable_default_logging(); + std::stringstream ss; + ss << "Error parsing command line: " << e.what(); + my_log( ss.str() ); + return EXIT_FAILURE; } if( options.count("version") > 0 ) { - std::cout << "Version: " << graphene::utilities::git_revision_description << "\n"; - std::cout << "SHA: " << graphene::utilities::git_revision_sha << "\n"; - std::cout << "Timestamp: " << fc::get_approximate_relative_time_string(fc::time_point_sec(graphene::utilities::git_revision_unix_timestamp)) << "\n"; - std::cout << "SSL: " << OPENSSL_VERSION_TEXT << "\n"; - std::cout << "Boost: " << boost::replace_all_copy(std::string(BOOST_LIB_VERSION), "_", ".") << "\n"; - std::cout << "Websocket++: " << websocketpp::major_version << "." << websocketpp::minor_version << "." << websocketpp::patch_version << "\n"; - return 0; + disable_default_logging(); + std::stringstream ss; + ss << "Version: " << graphene::utilities::git_revision_description << "\n"; + ss << "SHA: " << graphene::utilities::git_revision_sha << "\n"; + ss << "Timestamp: " << fc::get_approximate_relative_time_string(fc::time_point_sec( + graphene::utilities::git_revision_unix_timestamp)) << "\n"; + ss << "SSL: " << OPENSSL_VERSION_TEXT << "\n"; + ss << "Boost: " << boost::replace_all_copy(std::string(BOOST_LIB_VERSION), "_", ".") << "\n"; + ss << "Websocket++: " << websocketpp::major_version << "." << websocketpp::minor_version + << "." << websocketpp::patch_version; // No end of line in the end + my_log( ss.str() ); + return EXIT_SUCCESS; } if( options.count("help") > 0 ) { - std::cout << app_options << "\n"; - return 0; + disable_default_logging(); + std::stringstream ss; + ss << app_options << "\n"; + my_log( ss.str() ); + return EXIT_SUCCESS; } fc::path data_dir; @@ -139,23 +171,29 @@ int main(int argc, char** argv) { if( data_dir.is_relative() ) data_dir = fc::current_path() / data_dir; } - app::load_configuration_options(data_dir, cfg_options, options); + graphene::app::load_configuration_options(data_dir, cfg_options, options); std::set plugins; boost::split(plugins, options.at("plugins").as(), [](char c){return c == ' ';}); if( plugins.count("account_history") > 0 && plugins.count("elasticsearch") > 0 ) { - std::cerr << "Plugin conflict: Cannot load both account_history plugin and elasticsearch plugin\n"; - return 1; + disable_default_logging(); + std::stringstream ss; + ss << "Plugin conflict: Cannot load both account_history plugin and elasticsearch plugin"; + my_log( ss.str() ); + return EXIT_FAILURE; } if( plugins.count("api_helper_indexes") == 0 && options.count("ignore-api-helper-indexes-warning") == 0 && ( options.count("rpc-endpoint") > 0 || options.count("rpc-tls-endpoint") > 0 ) ) { - std::cerr << "\nIf this is an API node, please enable api_helper_indexes plugin." - "\nIf this is not an API node, please start with \"--ignore-api-helper-indexes-warning\"" - " or enable it in config.ini file.\n\n"; - return 1; + disable_default_logging(); + std::stringstream ss; + ss << "\nIf this is an API node, please enable api_helper_indexes plugin." + "\nIf this is not an API node, please start with \"--ignore-api-helper-indexes-warning\"" + " or enable it in config.ini file.\n"; + my_log( ss.str() ); + return EXIT_FAILURE; } std::for_each(plugins.begin(), plugins.end(), [&node](const std::string& plug) mutable { @@ -166,32 +204,34 @@ int main(int argc, char** argv) { bpo::notify(options); - node->initialize(data_dir, options); - node->initialize_plugins( options ); + node->initialize(data_dir, sharable_options); node->startup(); - node->startup_plugins(); fc::promise::ptr exit_promise = fc::promise::create("UNIX Signal Handler"); - fc::set_signal_handler([&exit_promise](int signal) { - elog( "Caught SIGINT attempting to exit cleanly" ); - exit_promise->set_value(signal); + fc::set_signal_handler([&exit_promise](int the_signal) { + wlog( "Caught SIGINT, attempting to exit cleanly" ); + exit_promise->set_value(the_signal); }, SIGINT); - fc::set_signal_handler([&exit_promise](int signal) { - elog( "Caught SIGTERM attempting to exit cleanly" ); - exit_promise->set_value(signal); + fc::set_signal_handler([&exit_promise](int the_signal) { + wlog( "Caught SIGTERM, attempting to exit cleanly" ); + exit_promise->set_value(the_signal); }, SIGTERM); +#ifdef SIGQUIT + fc::set_signal_handler( [&exit_promise](int the_signal) { + wlog( "Caught SIGQUIT, attempting to exit cleanly" ); + exit_promise->set_value(the_signal); + }, SIGQUIT ); +#endif + ilog("Started BitShares node on a chain with ${h} blocks.", ("h", node->chain_database()->head_block_num())); ilog("Chain ID is ${id}", ("id", node->chain_database()->get_chain_id()) ); - int signal = exit_promise->wait(); - ilog("Exiting from signal ${n}", ("n", signal)); - node->shutdown_plugins(); - node->shutdown(); - node.reset(); + auto caught_signal = exit_promise->wait(); + ilog("Exiting from signal ${n}", ("n", caught_signal)); return EXIT_SUCCESS; } catch( const fc::exception& e ) { // deleting the node can yield, so do this outside the exception handler @@ -201,8 +241,6 @@ int main(int argc, char** argv) { if (unhandled_exception) { elog("Exiting with error:\n${e}", ("e", unhandled_exception->to_detail_string())); - node->shutdown(); - node.reset(); return EXIT_FAILURE; } } diff --git a/tests/app/main.cpp b/tests/app/main.cpp index 27291dee98..b07eda1736 100644 --- a/tests/app/main.cpp +++ b/tests/app/main.cpp @@ -246,12 +246,12 @@ BOOST_AUTO_TEST_CASE( two_node_network ) app1.register_plugin< graphene::market_history::market_history_plugin >(); app1.register_plugin< graphene::witness_plugin::witness_plugin >(); app1.register_plugin< graphene::grouped_orders::grouped_orders_plugin>(); - app1.startup_plugins(); - boost::program_options::variables_map cfg; + auto sharable_cfg = std::make_shared(); + auto& cfg = *sharable_cfg; cfg.emplace("p2p-endpoint", boost::program_options::variable_value(app1_p2p_endpoint_str, false)); cfg.emplace("genesis-json", boost::program_options::variable_value(genesis_file, false)); cfg.emplace("seed-nodes", boost::program_options::variable_value(string("[]"), false)); - app1.initialize(app_dir.path(), cfg); + app1.initialize(app_dir.path(), sharable_cfg); BOOST_TEST_MESSAGE( "Starting app1 and waiting" ); app1.startup(); @@ -271,11 +271,11 @@ BOOST_AUTO_TEST_CASE( two_node_network ) app2.register_plugin< graphene::market_history::market_history_plugin >(); app2.register_plugin< graphene::witness_plugin::witness_plugin >(); app2.register_plugin< graphene::grouped_orders::grouped_orders_plugin>(); - app2.startup_plugins(); - boost::program_options::variables_map cfg2; + auto sharable_cfg2 = std::make_shared(); + auto& cfg2 = *sharable_cfg2; cfg2.emplace("genesis-json", boost::program_options::variable_value(genesis_file, false)); cfg2.emplace("seed-nodes", boost::program_options::variable_value(app2_seed_nodes_str, false)); - app2.initialize(app2_dir.path(), cfg2); + app2.initialize(app2_dir.path(), sharable_cfg2); BOOST_TEST_MESSAGE( "Starting app2 and waiting for connection" ); app2.startup(); @@ -390,13 +390,15 @@ BOOST_AUTO_TEST_CASE( two_node_network ) } } -// a contrived example to test the breaking out of application_impl to a header file - +/// a contrived example to test the breaking out of application_impl to a header file BOOST_AUTO_TEST_CASE(application_impl_breakout) { + + static graphene::app::application my_app; + class test_impl : public graphene::app::detail::application_impl { // override the constructor, just to test that we can public: - test_impl() : application_impl(nullptr) {} + test_impl() : application_impl(my_app) {} bool has_item(const net::item_id& id) override { return true; } diff --git a/tests/cli/main.cpp b/tests/cli/main.cpp index 9626c5ecd2..d5ed125e09 100644 --- a/tests/cli/main.cpp +++ b/tests/cli/main.cpp @@ -96,7 +96,7 @@ using std::cerr; /// @returns the application object ////////// std::shared_ptr start_application(fc::temp_directory& app_dir, int& server_port_number) { - std::shared_ptr app1(new graphene::app::application{}); + auto app1 = std::make_shared(); app1->register_plugin(true); app1->register_plugin< graphene::market_history::market_history_plugin >(true); @@ -104,11 +104,8 @@ std::shared_ptr start_application(fc::temp_directory app1->register_plugin< graphene::api_helper_indexes::api_helper_indexes>(true); app1->register_plugin(true); - app1->startup_plugins(); - boost::program_options::variables_map cfg; -#ifdef _WIN32 - sockInit(); -#endif + auto sharable_cfg = std::make_shared(); + auto& cfg = *sharable_cfg; server_port_number = fc::network::get_available_port(); cfg.emplace( "rpc-endpoint", @@ -117,10 +114,7 @@ std::shared_ptr start_application(fc::temp_directory cfg.emplace("genesis-json", boost::program_options::variable_value(create_genesis_file(app_dir), false)); cfg.emplace("seed-nodes", boost::program_options::variable_value(string("[]"), false)); cfg.emplace("custom-operations-start-block", boost::program_options::variable_value(uint32_t(1), false)); - app1->initialize(app_dir.path(), cfg); - - app1->initialize_plugins(cfg); - app1->startup_plugins(); + app1->initialize(app_dir.path(), sharable_cfg); app1->startup(); @@ -280,6 +274,16 @@ class client_connection struct cli_fixture { +#ifdef _WIN32 + struct socket_maintainer { + socket_maintainer() { + sockInit(); + } + ~socket_maintainer() { + sockQuit(); + } + } sock_maintainer; +#endif int server_port_number; fc::temp_directory app_dir; std::shared_ptr app1; @@ -317,10 +321,6 @@ struct cli_fixture ~cli_fixture() { BOOST_TEST_MESSAGE("Cleanup cli_wallet::boost_fixture_test_case"); - app1->shutdown(); -#ifdef _WIN32 - sockQuit(); -#endif } }; @@ -1500,8 +1500,6 @@ BOOST_AUTO_TEST_CASE( cli_multisig_transaction ) edump((e.to_detail_string())); throw; } - app1->shutdown(); - app1.reset(); } graphene::wallet::plain_keys decrypt_keys( const std::string& password, const vector& cipher_keys ) @@ -1734,8 +1732,6 @@ BOOST_AUTO_TEST_CASE( cli_create_htlc ) edump((e.to_detail_string())); throw; } - app1->shutdown(); - app1.reset(); } static string encapsulate( const graphene::wallet::signed_message& msg ) @@ -2311,6 +2307,4 @@ BOOST_AUTO_TEST_CASE( cli_create_htlc_bsip64 ) edump((e.to_detail_string())); throw; } - app1->shutdown(); - app1.reset(); } diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 69f2099b3a..847181c5cf 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -22,7 +22,6 @@ * THE SOFTWARE. */ #include -#include #include #include @@ -44,8 +43,6 @@ #include #include -#include - #include #include @@ -71,10 +68,15 @@ void clearable_block::clear() _block_id = block_id_type(); } -database_fixture::database_fixture(const fc::time_point_sec &initial_timestamp) - : app(), db( *app.chain_database() ) -{ - try { +database_fixture_base::database_fixture_base() + : app(), db( *app.chain_database() ), + private_key( fc::ecc::private_key::generate() ), + init_account_priv_key( fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")) ) ), + init_account_pub_key( init_account_priv_key.get_public_key() ), + current_test_name( buf::current_test_case().p_name.value ), + current_suite_name( buf::get(buf::current_test_case().p_parent_id).p_name + .value ) +{ try { int argc = buf::master_test_suite().argc; char** argv = buf::master_test_suite().argv; for( int i=1; i(current_test_suite_id).p_name.value; +database_fixture_base::~database_fixture_base() +{ + // cleanup data in ES + if( !es_index_prefix.empty() || !es_obj_index_prefix.empty() ) + { + CURL *curl; // curl handler + curl = curl_easy_init(); + curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); - auto mhplugin = app.register_plugin(true); - auto goplugin = app.register_plugin(true); + graphene::utilities::ES es; + es.curl = curl; + es.elasticsearch_url = GRAPHENE_TESTING_ES_URL; - init_account_pub_key = init_account_priv_key.get_public_key(); + if( !es_index_prefix.empty() ) + { + es.index_prefix = es_index_prefix; + // delete all + try { + graphene::utilities::deleteAll(es); + } catch (...) { + // nothing to do + } + } + + if( !es_obj_index_prefix.empty() ) + { + es.index_prefix = es_obj_index_prefix; + // delete all + try { + graphene::utilities::deleteAll(es); + } catch (...) { + // nothing to do + } + } + } - boost::program_options::variables_map options; + try { + // If we're unwinding due to an exception, don't do any more checks. + // This way, boost test's last checkpoint tells us approximately where the error was. + if( !std::uncaught_exception() ) + { + verify_asset_supplies(db); + BOOST_CHECK( db.get_node_properties().skip_flags == database::skip_nothing ); + } + } catch (fc::exception& ex) { + BOOST_FAIL( std::string("fc::exception in ~database_fixture: ") + ex.to_detail_string() ); + } catch (std::exception& e) { + BOOST_FAIL( std::string("std::exception in ~database_fixture:") + e.what() ); + } catch (...) { + BOOST_FAIL( "Uncaught exception in ~database_fixture" ); + } - genesis_state.initial_timestamp = initial_timestamp; +} - if(current_test_name == "hf_1270_test") +void database_fixture_base::init_genesis( database_fixture_base& fixture ) +{ + fixture.genesis_state.initial_timestamp = fc::time_point_sec(GRAPHENE_TESTING_GENESIS_TIMESTAMP); + if( fixture.current_test_name == "hf_1270_test" ) { - genesis_state.initial_active_witnesses = 20; + fixture.genesis_state.initial_active_witnesses = 20; } else { - genesis_state.initial_active_witnesses = 10; - genesis_state.immutable_parameters.min_committee_member_count = INITIAL_COMMITTEE_MEMBER_COUNT; - genesis_state.immutable_parameters.min_witness_count = INITIAL_WITNESS_COUNT; + fixture.genesis_state.initial_active_witnesses = 10; + fixture.genesis_state.immutable_parameters.min_committee_member_count = INITIAL_COMMITTEE_MEMBER_COUNT; + fixture.genesis_state.immutable_parameters.min_witness_count = INITIAL_WITNESS_COUNT; } - for( unsigned int i = 0; i < genesis_state.initial_active_witnesses; ++i ) + for( unsigned int i = 0; i < fixture.genesis_state.initial_active_witnesses; ++i ) { auto name = "init"+fc::to_string(i); - genesis_state.initial_accounts.emplace_back(name, - init_account_priv_key.get_public_key(), - init_account_priv_key.get_public_key(), - true); - genesis_state.initial_committee_candidates.push_back({name}); - genesis_state.initial_witness_candidates.push_back({name, init_account_priv_key.get_public_key()}); + fixture.genesis_state.initial_accounts.emplace_back( name, fixture.init_account_pub_key, + fixture.init_account_pub_key, true); + fixture.genesis_state.initial_committee_candidates.push_back({name}); + fixture.genesis_state.initial_witness_candidates.push_back({ name, fixture.init_account_pub_key }); } - genesis_state.initial_parameters.get_mutable_fees().zero_all_fees(); + fixture.genesis_state.initial_parameters.get_mutable_fees().zero_all_fees(); genesis_state_type::initial_asset_type init_mpa1; init_mpa1.symbol = "INITMPA"; @@ -129,136 +174,150 @@ database_fixture::database_fixture(const fc::time_point_sec &initial_timestamp) init_mpa1.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; init_mpa1.accumulated_fees = 0; init_mpa1.is_bitasset = true; + fixture.genesis_state.initial_assets.push_back( init_mpa1 ); // TODO add initial UIA's; add initial short positions; test non-zero accumulated_fees - genesis_state.initial_assets.push_back( init_mpa1 ); - - open_database(); +} +std::shared_ptr database_fixture_base::init_options( + database_fixture_base& fixture ) +{ + auto sharable_options = std::make_shared(); + auto& options = *sharable_options; + set_option( options, "seed-nodes", std::string("[]") ); // Do not connect to default seed nodes /** * Test specific settings */ - if (current_test_name == "get_account_history_operations") + if (fixture.current_test_name == "broadcast_transaction_with_callback_test") + set_option( options, "enable-p2p-network", true ); + else if (fixture.current_test_name == "broadcast_transaction_disabled_p2p_test") + set_option( options, "enable-p2p-network", false ); + else if( rand() % 100 >= 50 ) // Disable P2P network randomly for test cases + set_option( options, "enable-p2p-network", false ); + else if( rand() % 100 >= 50 ) // this should lead to no change + set_option( options, "enable-p2p-network", true ); + + if (fixture.current_test_name == "get_account_history_operations") { options.insert(std::make_pair("max-ops-per-account", boost::program_options::variable_value((uint64_t)75, false))); } - if (current_test_name == "api_limit_get_account_history_operations") + if (fixture.current_test_name == "api_limit_get_account_history_operations") { options.insert(std::make_pair("max-ops-per-account", boost::program_options::variable_value((uint64_t)125, false))); options.insert(std::make_pair("api-limit-get-account-history-operations", boost::program_options::variable_value((uint64_t)300, false))); } - if(current_test_name =="api_limit_get_account_history") + if(fixture.current_test_name =="api_limit_get_account_history") { options.insert(std::make_pair("max-ops-per-account", boost::program_options::variable_value((uint64_t)125, false))); options.insert(std::make_pair("api-limit-get-account-history", boost::program_options::variable_value((uint64_t)250, false))); } - if(current_test_name =="api_limit_get_grouped_limit_orders") + if(fixture.current_test_name =="api_limit_get_grouped_limit_orders") { options.insert(std::make_pair("api-limit-get-grouped-limit-orders", boost::program_options::variable_value((uint64_t)250, false))); } - if(current_test_name =="api_limit_get_relative_account_history") + if(fixture.current_test_name =="api_limit_get_relative_account_history") { options.insert(std::make_pair("max-ops-per-account", boost::program_options::variable_value((uint64_t)125, false))); options.insert(std::make_pair("api-limit-get-relative-account-history", boost::program_options::variable_value((uint64_t)250, false))); } - if(current_test_name =="api_limit_get_account_history_by_operations") + if(fixture.current_test_name =="api_limit_get_account_history_by_operations") { options.insert(std::make_pair("api-limit-get-account-history-by-operations", boost::program_options::variable_value((uint64_t)250, false))); options.insert(std::make_pair("api-limit-get-relative-account-history", boost::program_options::variable_value((uint64_t)250, false))); } - if(current_test_name =="api_limit_get_asset_holders") + if(fixture.current_test_name =="api_limit_get_asset_holders") { options.insert(std::make_pair("api-limit-get-asset-holders", boost::program_options::variable_value((uint64_t)250, false))); } - if(current_test_name =="api_limit_get_key_references") + if(fixture.current_test_name =="api_limit_get_key_references") { options.insert(std::make_pair("api-limit-get-key-references", boost::program_options::variable_value((uint64_t)200, false))); } - if(current_test_name =="api_limit_get_limit_orders") + if(fixture.current_test_name =="api_limit_get_limit_orders") { options.insert(std::make_pair("api-limit-get-limit-orders", boost::program_options::variable_value( (uint64_t)350, false))); } - if(current_test_name =="api_limit_get_limit_orders_by_account") + if(fixture.current_test_name =="api_limit_get_limit_orders_by_account") { options.insert(std::make_pair("api-limit-get-limit-orders-by-account", boost::program_options::variable_value( (uint64_t)150, false))); } - if(current_test_name =="api_limit_get_call_orders") + if(fixture.current_test_name =="api_limit_get_call_orders") { options.insert(std::make_pair("api-limit-get-call-orders", boost::program_options::variable_value( (uint64_t)350, false))); } - if(current_test_name =="api_limit_get_settle_orders") + if(fixture.current_test_name =="api_limit_get_settle_orders") { options.insert(std::make_pair("api-limit-get-settle-orders", boost::program_options::variable_value( (uint64_t)350, false))); } - if(current_test_name =="api_limit_get_order_book") + if(fixture.current_test_name =="api_limit_get_order_book") { options.insert(std::make_pair("api-limit-get-order-book", boost::program_options::variable_value( (uint64_t)80, false))); } - if(current_test_name =="api_limit_lookup_accounts") + if(fixture.current_test_name =="api_limit_lookup_accounts") { options.insert(std::make_pair("api-limit-lookup-accounts", boost::program_options::variable_value ((uint64_t)200, false))); } - if(current_test_name =="api_limit_lookup_witness_accounts") + if(fixture.current_test_name =="api_limit_lookup_witness_accounts") { options.insert(std::make_pair("api-limit-lookup-witness-accounts", boost::program_options::variable_value ((uint64_t)200, false))); } - if(current_test_name =="api_limit_lookup_committee_member_accounts") + if(fixture.current_test_name =="api_limit_lookup_committee_member_accounts") { options.insert(std::make_pair("api-limit-lookup-committee-member-accounts", boost::program_options::variable_value ((uint64_t)200, false))); } - if(current_test_name =="api_limit_lookup_committee_member_accounts") + if(fixture.current_test_name =="api_limit_lookup_committee_member_accounts") { options.insert(std::make_pair("api-limit-lookup-committee-member-accounts", boost::program_options::variable_value ((uint64_t)200, false))); } - if(current_test_name =="api_limit_lookup_vote_ids") + if(fixture.current_test_name =="api_limit_lookup_vote_ids") { options.insert(std::make_pair("api-limit-lookup-vote-ids", boost::program_options::variable_value ((uint64_t)2, false))); } - if(current_test_name =="api_limit_get_account_limit_orders") + if(fixture.current_test_name =="api_limit_get_account_limit_orders") { options.insert(std::make_pair("api-limit-get-account-limit-orders", boost::program_options::variable_value ((uint64_t)250, false))); } - if(current_test_name =="api_limit_get_collateral_bids") + if(fixture.current_test_name =="api_limit_get_collateral_bids") { options.insert(std::make_pair("api-limit-get-collateral-bids", boost::program_options::variable_value ((uint64_t)250, false))); } - if(current_test_name =="api_limit_get_top_markets") + if(fixture.current_test_name =="api_limit_get_top_markets") { options.insert(std::make_pair("api-limit-get-top-markets", boost::program_options::variable_value ((uint64_t)250, false))); } - if(current_test_name =="api_limit_get_trade_history") + if(fixture.current_test_name =="api_limit_get_trade_history") { options.insert(std::make_pair("api-limit-get-trade-history", boost::program_options::variable_value ((uint64_t)250, false))); } - if(current_test_name =="api_limit_get_trade_history_by_sequence") + if(fixture.current_test_name =="api_limit_get_trade_history_by_sequence") { options.insert(std::make_pair("api-limit-get-trade-history-by-sequence", boost::program_options::variable_value ((uint64_t)250, false))); } - if(current_test_name =="api_limit_get_withdraw_permissions_by_giver") + if(fixture.current_test_name =="api_limit_get_withdraw_permissions_by_giver") { options.insert(std::make_pair("api-limit-get-withdraw-permissions-by-giver", boost::program_options::variable_value ((uint64_t)250, false))); } - if(current_test_name =="api_limit_get_withdraw_permissions_by_recipient") + if(fixture.current_test_name =="api_limit_get_withdraw_permissions_by_recipient") { options.insert(std::make_pair("api-limit-get-withdraw-permissions-by-recipient", boost::program_options::variable_value ((uint64_t)250, false))); } - if(current_test_name =="api_limit_get_full_accounts2") + if(fixture.current_test_name =="api_limit_get_full_accounts2") { options.insert(std::make_pair("api-limit-get-full-accounts", boost::program_options::variable_value ((uint64_t)200, false))); @@ -267,7 +326,7 @@ database_fixture::database_fixture(const fc::time_point_sec &initial_timestamp) } // add account tracking for ahplugin for special test case with track-account enabled - if( !options.count("track-account") && current_test_name == "track_account") { + if( !options.count("track-account") && fixture.current_test_name == "track_account") { std::vector track_account; std::string track = "\"1.2.17\""; track_account.push_back(track); @@ -275,7 +334,7 @@ database_fixture::database_fixture(const fc::time_point_sec &initial_timestamp) options.insert(std::make_pair("partial-operations", boost::program_options::variable_value(true, false))); } // account tracking 2 accounts - if( !options.count("track-account") && current_test_name == "track_account2") { + if( !options.count("track-account") && fixture.current_test_name == "track_account2") { std::vector track_account; std::string track = "\"1.2.0\""; track_account.push_back(track); @@ -284,14 +343,15 @@ database_fixture::database_fixture(const fc::time_point_sec &initial_timestamp) options.insert(std::make_pair("track-account", boost::program_options::variable_value(track_account, false))); } // standby votes tracking - if( current_test_name == "track_votes_witnesses_disabled" - || current_test_name == "track_votes_committee_disabled") { - app.chain_database()->enable_standby_votes_tracking( false ); + if( fixture.current_test_name == "track_votes_witnesses_disabled" + || fixture.current_test_name == "track_votes_committee_disabled") { + fixture.app.chain_database()->enable_standby_votes_tracking( false ); } // load ES or AH, but not both - if(current_test_name == "elasticsearch_account_history" || current_test_name == "elasticsearch_suite" || - current_test_name == "elasticsearch_history_api") { - auto esplugin = app.register_plugin(true); + if(fixture.current_test_name == "elasticsearch_account_history" || + fixture.current_test_name == "elasticsearch_suite" || + fixture.current_test_name == "elasticsearch_history_api") { + fixture.app.register_plugin(true); options.insert(std::make_pair("elasticsearch-node-url", boost::program_options::variable_value(GRAPHENE_TESTING_ES_URL, false))); @@ -310,23 +370,18 @@ database_fixture::database_fixture(const fc::time_point_sec &initial_timestamp) options.insert(std::make_pair("elasticsearch-mode", boost::program_options::variable_value(uint16_t(2), false))); - es_index_prefix = string("bitshares-") + fc::to_string(uint64_t(rand())) + "-"; - BOOST_TEST_MESSAGE( string("ES index prefix is ") + es_index_prefix ); + fixture.es_index_prefix = string("bitshares-") + fc::to_string(uint64_t(rand())) + "-"; + BOOST_TEST_MESSAGE( string("ES index prefix is ") + fixture.es_index_prefix ); options.insert(std::make_pair("elasticsearch-index-prefix", - boost::program_options::variable_value(es_index_prefix, false))); - - esplugin->plugin_initialize(options); - esplugin->plugin_startup(); + boost::program_options::variable_value(fixture.es_index_prefix, false))); } - else if( current_suite_name != "performance_tests" ) + else if( fixture.current_suite_name != "performance_tests" ) { - auto ahplugin = app.register_plugin(true); - ahplugin->plugin_initialize(options); - ahplugin->plugin_startup(); + fixture.app.register_plugin(true); } - if(current_test_name == "elasticsearch_objects" || current_test_name == "elasticsearch_suite") { - auto esobjects_plugin = app.register_plugin(true); + if(fixture.current_test_name == "elasticsearch_objects" || fixture.current_test_name == "elasticsearch_suite") { + fixture.app.register_plugin(true); options.insert(std::make_pair("es-objects-elasticsearch-url", boost::program_options::variable_value(GRAPHENE_TESTING_ES_URL, false))); @@ -347,117 +402,37 @@ database_fixture::database_fixture(const fc::time_point_sec &initial_timestamp) options.insert(std::make_pair("es-objects-asset-bitasset", boost::program_options::variable_value(true, false))); - es_obj_index_prefix = string("objects-") + fc::to_string(uint64_t(rand())) + "-"; - BOOST_TEST_MESSAGE( string("ES_OBJ index prefix is ") + es_obj_index_prefix ); + fixture.es_obj_index_prefix = string("objects-") + fc::to_string(uint64_t(rand())) + "-"; + BOOST_TEST_MESSAGE( string("ES_OBJ index prefix is ") + fixture.es_obj_index_prefix ); options.insert(std::make_pair("es-objects-index-prefix", - boost::program_options::variable_value(es_obj_index_prefix, false))); - - esobjects_plugin->plugin_initialize(options); - esobjects_plugin->plugin_startup(); + boost::program_options::variable_value(fixture.es_obj_index_prefix, false))); } - if( current_test_name == "asset_in_collateral" - || current_test_name == "htlc_database_api" - || current_test_name == "liquidity_pool_apis_test" - || current_suite_name == "database_api_tests" - || current_suite_name == "api_limit_tests" ) + if( fixture.current_test_name == "asset_in_collateral" + || fixture.current_test_name == "htlc_database_api" + || fixture.current_test_name == "liquidity_pool_apis_test" + || fixture.current_suite_name == "database_api_tests" + || fixture.current_suite_name == "api_limit_tests" ) { - auto ahiplugin = app.register_plugin(true); - ahiplugin->plugin_initialize(options); - ahiplugin->plugin_startup(); + fixture.app.register_plugin(true); } - if(current_test_name == "custom_operations_account_storage_map_test" || - current_test_name == "custom_operations_account_storage_list_test") { - auto custom_operations_plugin = app.register_plugin(true); - options.insert(std::make_pair("custom-operations-start-block", boost::program_options::variable_value(uint32_t(1), false))); - custom_operations_plugin->plugin_initialize(options); - custom_operations_plugin->plugin_startup(); + if(fixture.current_test_name == "custom_operations_account_storage_map_test" || + fixture.current_test_name == "custom_operations_account_storage_list_test") { + fixture.app.register_plugin(true); + options.insert(std::make_pair("custom-operations-start-block", + boost::program_options::variable_value(uint32_t(1), false))); } options.insert(std::make_pair("bucket-size", boost::program_options::variable_value(string("[15]"),false))); - // apply api limits, initialize the "has_market_history_plugin" variable and etc in app_options - app.initialize(graphene::utilities::temp_directory_path(), options); - - mhplugin->plugin_initialize(options); - goplugin->plugin_initialize(options); - - mhplugin->plugin_startup(); - goplugin->plugin_startup(); - - generate_block(); - - asset_id_type mpa1_id(1); - BOOST_REQUIRE( mpa1_id(db).is_market_issued() ); - BOOST_CHECK( mpa1_id(db).bitasset_data(db).asset_id == mpa1_id ); - - set_expiration( db, trx ); - - } catch ( const fc::exception& e ) - { - edump( (e.to_detail_string()) ); - throw; - } + fixture.app.register_plugin(true); + fixture.app.register_plugin(true); + return sharable_options; } -database_fixture::~database_fixture() -{ - try { - // If we're unwinding due to an exception, don't do any more checks. - // This way, boost test's last checkpoint tells us approximately where the error was. - if( !std::uncaught_exception() ) - { - verify_asset_supplies(db); - BOOST_CHECK( db.get_node_properties().skip_flags == database::skip_nothing ); - } - - } catch (fc::exception& ex) { - BOOST_FAIL( std::string("fc::exception in ~database_fixture: ") + ex.to_detail_string() ); - } catch (std::exception& e) { - BOOST_FAIL( std::string("std::exception in ~database_fixture:") + e.what() ); - } catch (...) { - BOOST_FAIL( "Uncaught exception in ~database_fixture" ); - } - - // cleanup data in ES - if( !es_index_prefix.empty() || !es_obj_index_prefix.empty() ) - { - CURL *curl; // curl handler - curl = curl_easy_init(); - curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); - - graphene::utilities::ES es; - es.curl = curl; - es.elasticsearch_url = GRAPHENE_TESTING_ES_URL; - - if( !es_index_prefix.empty() ) - { - es.index_prefix = es_index_prefix; - // delete all - try { - graphene::utilities::deleteAll(es); - } catch (...) { - // nothing to do - } - } - - if( !es_obj_index_prefix.empty() ) - { - es.index_prefix = es_obj_index_prefix; - // delete all - try { - graphene::utilities::deleteAll(es); - } catch (...) { - // nothing to do - } - } - } - -} - -void database_fixture::vote_for_committee_and_witnesses(uint16_t num_committee, uint16_t num_witness) +void database_fixture_base::vote_for_committee_and_witnesses(uint16_t num_committee, uint16_t num_witness) { try { auto &init0 = get_account("init0"); @@ -498,7 +473,7 @@ void database_fixture::vote_for_committee_and_witnesses(uint16_t num_committee, } FC_CAPTURE_AND_RETHROW() } -fc::ecc::private_key database_fixture::generate_private_key(string seed) +fc::ecc::private_key database_fixture_base::generate_private_key(string seed) { static const fc::ecc::private_key committee = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key"))); if( seed == "null_key" ) @@ -506,14 +481,14 @@ fc::ecc::private_key database_fixture::generate_private_key(string seed) return fc::ecc::private_key::regenerate(fc::sha256::hash(seed)); } -string database_fixture::generate_anon_acct_name() +string database_fixture_base::generate_anon_acct_name() { // names of the form "anon-acct-x123" ; the "x" is necessary // to workaround issue #46 return "anon-acct-x" + std::to_string( anon_acct_count++ ); } -void database_fixture::verify_asset_supplies( const database& db ) +void database_fixture_base::verify_asset_supplies( const database& db ) { //wlog("*** Begin asset supply verification ***"); const asset_dynamic_data_object& core_asset_data = db.get_core_asset().dynamic_asset_data_id(db); @@ -643,15 +618,7 @@ void database_fixture::verify_asset_supplies( const database& db ) // wlog("*** End asset supply verification ***"); } -void database_fixture::open_database() -{ - if( !data_dir ) { - data_dir = fc::temp_directory( graphene::utilities::temp_directory_path() ); - db.open(data_dir->path(), [this]{return genesis_state;}, "test"); - } -} - -signed_block database_fixture::generate_block(uint32_t skip, const fc::ecc::private_key& key, int miss_blocks) +signed_block database_fixture_base::generate_block(uint32_t skip, const fc::ecc::private_key& key, int miss_blocks) { skip |= database::skip_undo_history_check; // skip == ~0 will skip checks specified in database::validation_steps @@ -663,13 +630,13 @@ signed_block database_fixture::generate_block(uint32_t skip, const fc::ecc::priv return block; } -void database_fixture::generate_blocks( uint32_t block_count ) +void database_fixture_base::generate_blocks( uint32_t block_count ) { for( uint32_t i = 0; i < block_count; ++i ) generate_block(); } -uint32_t database_fixture::generate_blocks(fc::time_point_sec timestamp, bool miss_intermediate_blocks, uint32_t skip) +uint32_t database_fixture_base::generate_blocks(fc::time_point_sec timestamp, bool miss_intermediate_blocks, uint32_t skip) { if( miss_intermediate_blocks ) { @@ -690,7 +657,7 @@ uint32_t database_fixture::generate_blocks(fc::time_point_sec timestamp, bool mi return blocks; } -account_create_operation database_fixture::make_account( +account_create_operation database_fixture_base::make_account( const std::string& name /* = "nathan" */, public_key_type key /* = key_id_type() */ ) @@ -721,7 +688,7 @@ account_create_operation database_fixture::make_account( return create_account; } FC_CAPTURE_AND_RETHROW() } -account_create_operation database_fixture::make_account( +account_create_operation database_fixture_base::make_account( const std::string& name, const account_object& registrar, const account_object& referrer, @@ -762,7 +729,7 @@ account_create_operation database_fixture::make_account( FC_CAPTURE_AND_RETHROW((name)(referrer_percent)) } -const asset_object& database_fixture::get_asset( const string& symbol )const +const asset_object& database_fixture_base::get_asset( const string& symbol )const { const auto& idx = db.get_index_type().indices().get(); const auto itr = idx.find(symbol); @@ -770,7 +737,7 @@ const asset_object& database_fixture::get_asset( const string& symbol )const return *itr; } -const account_object& database_fixture::get_account( const string& name )const +const account_object& database_fixture_base::get_account( const string& name )const { const auto& idx = db.get_index_type().indices().get(); const auto itr = idx.find(name); @@ -778,7 +745,7 @@ const account_object& database_fixture::get_account( const string& name )const return *itr; } -asset_create_operation database_fixture::make_bitasset( +asset_create_operation database_fixture_base::make_bitasset( const string& name, account_id_type issuer /* = GRAPHENE_WITNESS_ACCOUNT */, uint16_t market_fee_percent /* = 100 */ /* 1% */, @@ -809,7 +776,7 @@ asset_create_operation database_fixture::make_bitasset( return creator; } -const asset_object& database_fixture::create_bitasset( +const asset_object& database_fixture_base::create_bitasset( const string& name, account_id_type issuer /* = GRAPHENE_WITNESS_ACCOUNT */, uint16_t market_fee_percent /* = 100 */ /* 1% */, @@ -832,7 +799,7 @@ const asset_object& database_fixture::create_bitasset( return db.get(ptx.operation_results[0].get()); } FC_CAPTURE_AND_RETHROW( (name)(flags) ) } -const asset_object& database_fixture::create_prediction_market( +const asset_object& database_fixture_base::create_prediction_market( const string& name, account_id_type issuer /* = GRAPHENE_WITNESS_ACCOUNT */, uint16_t market_fee_percent /* = 100 */ /* 1% */, @@ -865,7 +832,7 @@ const asset_object& database_fixture::create_prediction_market( } FC_CAPTURE_AND_RETHROW( (name)(flags) ) } -const asset_object& database_fixture::create_user_issued_asset( const string& name ) +const asset_object& database_fixture_base::create_user_issued_asset( const string& name ) { asset_create_operation creator; creator.issuer = account_id_type(); @@ -885,7 +852,7 @@ const asset_object& database_fixture::create_user_issued_asset( const string& na return db.get(ptx.operation_results[0].get()); } -const asset_object& database_fixture::create_user_issued_asset( const string& name, const account_object& issuer, +const asset_object& database_fixture_base::create_user_issued_asset( const string& name, const account_object& issuer, uint16_t flags, const price& core_exchange_rate, uint8_t precision, uint16_t market_fee_percent, additional_asset_options_t additional_options) @@ -911,7 +878,7 @@ const asset_object& database_fixture::create_user_issued_asset( const string& na return db.get(ptx.operation_results[0].get()); } -void database_fixture::issue_uia( const account_object& recipient, asset amount ) +void database_fixture_base::issue_uia( const account_object& recipient, asset amount ) { BOOST_TEST_MESSAGE( "Issuing UIA" ); asset_issue_operation op; @@ -924,12 +891,12 @@ void database_fixture::issue_uia( const account_object& recipient, asset amount trx.operations.clear(); } -void database_fixture::issue_uia( account_id_type recipient_id, asset amount ) +void database_fixture_base::issue_uia( account_id_type recipient_id, asset amount ) { issue_uia( recipient_id(db), amount ); } -void database_fixture::reserve_asset( account_id_type account, asset amount ) +void database_fixture_base::reserve_asset( account_id_type account, asset amount ) { BOOST_TEST_MESSAGE( "Reserving asset" ); asset_reserve_operation op; @@ -943,7 +910,7 @@ void database_fixture::reserve_asset( account_id_type account, asset amount ) trx.operations.clear(); } -void database_fixture::change_fees( +void database_fixture_base::change_fees( const fee_parameters::flat_set_type& new_params, uint32_t new_scale /* = 0 */ ) @@ -973,7 +940,7 @@ void database_fixture::change_fees( }); } -const account_object& database_fixture::create_account( +const account_object& database_fixture_base::create_account( const string& name, const public_key_type& key /* = public_key_type() */ ) @@ -987,7 +954,7 @@ const account_object& database_fixture::create_account( return result; } -const account_object& database_fixture::create_account( +const account_object& database_fixture_base::create_account( const string& name, const account_object& registrar, const account_object& referrer, @@ -1008,7 +975,7 @@ const account_object& database_fixture::create_account( FC_CAPTURE_AND_RETHROW( (name)(registrar)(referrer) ) } -const account_object& database_fixture::create_account( +const account_object& database_fixture_base::create_account( const string& name, const private_key_type& key, const account_id_type& registrar_id /* = account_id_type() */, @@ -1042,7 +1009,7 @@ const account_object& database_fixture::create_account( FC_CAPTURE_AND_RETHROW( (name)(registrar_id)(referrer_id) ) } -const committee_member_object& database_fixture::create_committee_member( const account_object& owner ) +const committee_member_object& database_fixture_base::create_committee_member( const account_object& owner ) { committee_member_create_operation op; op.committee_member_account = owner.id; @@ -1054,14 +1021,14 @@ const committee_member_object& database_fixture::create_committee_member( const return db.get(ptx.operation_results[0].get()); } -const witness_object&database_fixture::create_witness(account_id_type owner, +const witness_object& database_fixture_base::create_witness(account_id_type owner, const fc::ecc::private_key& signing_private_key, uint32_t skip_flags ) { return create_witness(owner(db), signing_private_key, skip_flags ); } -const witness_object& database_fixture::create_witness( const account_object& owner, +const witness_object& database_fixture_base::create_witness( const account_object& owner, const fc::ecc::private_key& signing_private_key, uint32_t skip_flags ) { try { @@ -1076,7 +1043,7 @@ const witness_object& database_fixture::create_witness( const account_object& ow return db.get(ptx.operation_results[0].get()); } FC_CAPTURE_AND_RETHROW() } -const worker_object& database_fixture::create_worker( const account_id_type owner, const share_type daily_pay, const fc::microseconds& duration ) +const worker_object& database_fixture_base::create_worker( const account_id_type owner, const share_type daily_pay, const fc::microseconds& duration ) { try { worker_create_operation op; op.owner = owner; @@ -1092,7 +1059,7 @@ const worker_object& database_fixture::create_worker( const account_id_type owne return db.get(ptx.operation_results[0].get()); } FC_CAPTURE_AND_RETHROW() } -uint64_t database_fixture::fund( +uint64_t database_fixture_base::fund( const account_object& account, const asset& amount /* = asset(500000) */ ) @@ -1101,17 +1068,17 @@ uint64_t database_fixture::fund( return get_balance(account, amount.asset_id(db)); } -void database_fixture::sign(signed_transaction& trx, const fc::ecc::private_key& key) +void database_fixture_base::sign(signed_transaction& trx, const fc::ecc::private_key& key) { trx.sign( key, db.get_chain_id() ); } -digest_type database_fixture::digest( const transaction& tx ) +digest_type database_fixture_base::digest( const transaction& tx ) { return tx.digest(); } -const limit_order_object*database_fixture::create_sell_order(account_id_type user, const asset& amount, const asset& recv, +const limit_order_object* database_fixture_base::create_sell_order(account_id_type user, const asset& amount, const asset& recv, const time_point_sec order_expiration, const price& fee_core_exchange_rate ) { @@ -1120,7 +1087,7 @@ const limit_order_object*database_fixture::create_sell_order(account_id_type use return r; } -const limit_order_object* database_fixture::create_sell_order( const account_object& user, const asset& amount, const asset& recv, +const limit_order_object* database_fixture_base::create_sell_order( const account_object& user, const asset& amount, const asset& recv, const time_point_sec order_expiration, const price& fee_core_exchange_rate ) { @@ -1141,7 +1108,7 @@ const limit_order_object* database_fixture::create_sell_order( const account_obj return db.find( processed.operation_results[0].get() ); } -asset database_fixture::cancel_limit_order( const limit_order_object& order ) +asset database_fixture_base::cancel_limit_order( const limit_order_object& order ) { limit_order_cancel_operation cancel_order; cancel_order.fee_paying_account = order.seller; @@ -1156,7 +1123,7 @@ asset database_fixture::cancel_limit_order( const limit_order_object& order ) return processed.operation_results[0].get(); } -void database_fixture::transfer( +void database_fixture_base::transfer( account_id_type from, account_id_type to, const asset& amount, @@ -1166,7 +1133,7 @@ void database_fixture::transfer( transfer(from(db), to(db), amount, fee); } -void database_fixture::transfer( +void database_fixture_base::transfer( const account_object& from, const account_object& to, const asset& amount, @@ -1193,7 +1160,7 @@ void database_fixture::transfer( } FC_CAPTURE_AND_RETHROW( (from.id)(to.id)(amount)(fee) ) } -void database_fixture::update_feed_producers( const asset_object& mia, flat_set producers ) +void database_fixture_base::update_feed_producers( const asset_object& mia, flat_set producers ) { try { set_expiration( db, trx ); trx.operations.clear(); @@ -1210,7 +1177,7 @@ void database_fixture::update_feed_producers( const asset_object& mia, flat_set< verify_asset_supplies(db); } FC_CAPTURE_AND_RETHROW( (mia)(producers) ) } -void database_fixture::publish_feed( const asset_object& mia, const account_object& by, const price_feed& f, +void database_fixture_base::publish_feed( const asset_object& mia, const account_object& by, const price_feed& f, const optional icr ) { set_expiration( db, trx ); @@ -1236,7 +1203,7 @@ void database_fixture::publish_feed( const asset_object& mia, const account_obje verify_asset_supplies(db); } -void database_fixture::publish_feed(const account_id_type& publisher, +void database_fixture_base::publish_feed(const account_id_type& publisher, const asset_id_type& asset1, int64_t amount1, const asset_id_type& asset2, int64_t amount2, const asset_id_type& core_id, const optional icr) @@ -1260,7 +1227,7 @@ void database_fixture::publish_feed(const account_id_type& publisher, trx.clear(); } -void database_fixture::force_global_settle( const asset_object& what, const price& p ) +void database_fixture_base::force_global_settle( const asset_object& what, const price& p ) { try { set_expiration( db, trx ); trx.operations.clear(); @@ -1276,7 +1243,7 @@ void database_fixture::force_global_settle( const asset_object& what, const pric verify_asset_supplies(db); } FC_CAPTURE_AND_RETHROW( (what)(p) ) } -operation_result database_fixture::force_settle( const account_object& who, asset what ) +operation_result database_fixture_base::force_settle( const account_object& who, asset what ) { try { set_expiration( db, trx ); trx.operations.clear(); @@ -1293,7 +1260,7 @@ operation_result database_fixture::force_settle( const account_object& who, asse return op_result; } FC_CAPTURE_AND_RETHROW( (who)(what) ) } -const call_order_object* database_fixture::borrow( const account_object& who, asset what, asset collateral, +const call_order_object* database_fixture_base::borrow( const account_object& who, asset what, asset collateral, optional target_cr ) { try { set_expiration( db, trx ); @@ -1319,7 +1286,7 @@ const call_order_object* database_fixture::borrow( const account_object& who, as return call_obj; } FC_CAPTURE_AND_RETHROW( (who.name)(what)(collateral)(target_cr) ) } -void database_fixture::cover(const account_object& who, asset what, asset collateral, optional target_cr) +void database_fixture_base::cover(const account_object& who, asset what, asset collateral, optional target_cr) { try { set_expiration( db, trx ); trx.operations.clear(); @@ -1336,7 +1303,7 @@ void database_fixture::cover(const account_object& who, asset what, asset collat verify_asset_supplies(db); } FC_CAPTURE_AND_RETHROW( (who.name)(what)(collateral)(target_cr) ) } -void database_fixture::bid_collateral(const account_object& who, const asset& to_bid, const asset& to_cover) +void database_fixture_base::bid_collateral(const account_object& who, const asset& to_bid, const asset& to_cover) { try { set_expiration( db, trx ); trx.operations.clear(); @@ -1352,7 +1319,7 @@ void database_fixture::bid_collateral(const account_object& who, const asset& to verify_asset_supplies(db); } FC_CAPTURE_AND_RETHROW( (who.name)(to_bid)(to_cover) ) } -void database_fixture::fund_fee_pool( const account_object& from, const asset_object& asset_to_fund, const share_type amount ) +void database_fixture_base::fund_fee_pool( const account_object& from, const asset_object& asset_to_fund, const share_type amount ) { asset_fund_fee_pool_operation fund; fund.from_account = from.id; @@ -1369,7 +1336,7 @@ void database_fixture::fund_fee_pool( const account_object& from, const asset_ob verify_asset_supplies(db); } -ticket_create_operation database_fixture::make_ticket_create_op( account_id_type account, ticket_type type, +ticket_create_operation database_fixture_base::make_ticket_create_op( account_id_type account, ticket_type type, const asset& amount ) const { ticket_create_operation op; @@ -1379,7 +1346,7 @@ ticket_create_operation database_fixture::make_ticket_create_op( account_id_type return op; } -const ticket_object& database_fixture::create_ticket( account_id_type account, ticket_type type, +const ticket_object& database_fixture_base::create_ticket( account_id_type account, ticket_type type, const asset& amount ) { ticket_create_operation op = make_ticket_create_op( account, type, amount ); @@ -1396,7 +1363,7 @@ const ticket_object& database_fixture::create_ticket( account_id_type account, t return db.get( op_result.get() ); } -ticket_update_operation database_fixture::make_ticket_update_op( const ticket_object& ticket, ticket_type type, +ticket_update_operation database_fixture_base::make_ticket_update_op( const ticket_object& ticket, ticket_type type, const optional& amount ) const { ticket_update_operation op; @@ -1407,7 +1374,7 @@ ticket_update_operation database_fixture::make_ticket_update_op( const ticket_ob return op; } -generic_operation_result database_fixture::update_ticket( const ticket_object& ticket, ticket_type type, +generic_operation_result database_fixture_base::update_ticket( const ticket_object& ticket, ticket_type type, const optional& amount ) { ticket_update_operation op = make_ticket_update_op( ticket, type, amount ); @@ -1424,7 +1391,7 @@ generic_operation_result database_fixture::update_ticket( const ticket_object& t return op_result.get(); } -liquidity_pool_create_operation database_fixture::make_liquidity_pool_create_op( +liquidity_pool_create_operation database_fixture_base::make_liquidity_pool_create_op( account_id_type account, asset_id_type asset_a, asset_id_type asset_b, asset_id_type share_asset, uint16_t taker_fee_percent, uint16_t withdrawal_fee_percent )const @@ -1439,7 +1406,7 @@ liquidity_pool_create_operation database_fixture::make_liquidity_pool_create_op( return op; } -const liquidity_pool_object& database_fixture::create_liquidity_pool( account_id_type account, asset_id_type asset_a, +const liquidity_pool_object& database_fixture_base::create_liquidity_pool( account_id_type account, asset_id_type asset_a, asset_id_type asset_b, asset_id_type share_asset, uint16_t taker_fee_percent, uint16_t withdrawal_fee_percent ) { @@ -1458,7 +1425,7 @@ const liquidity_pool_object& database_fixture::create_liquidity_pool( account_id return db.get( *op_result.get().new_objects.begin() ); } -liquidity_pool_delete_operation database_fixture::make_liquidity_pool_delete_op( account_id_type account, +liquidity_pool_delete_operation database_fixture_base::make_liquidity_pool_delete_op( account_id_type account, liquidity_pool_id_type pool )const { liquidity_pool_delete_operation op; @@ -1467,7 +1434,7 @@ liquidity_pool_delete_operation database_fixture::make_liquidity_pool_delete_op( return op; } -generic_operation_result database_fixture::delete_liquidity_pool( account_id_type account, +generic_operation_result database_fixture_base::delete_liquidity_pool( account_id_type account, liquidity_pool_id_type pool ) { liquidity_pool_delete_operation op = make_liquidity_pool_delete_op( account, pool ); @@ -1484,7 +1451,7 @@ generic_operation_result database_fixture::delete_liquidity_pool( account_id_typ return op_result.get(); } -liquidity_pool_deposit_operation database_fixture::make_liquidity_pool_deposit_op( account_id_type account, +liquidity_pool_deposit_operation database_fixture_base::make_liquidity_pool_deposit_op( account_id_type account, liquidity_pool_id_type pool, const asset& amount_a, const asset& amount_b )const { @@ -1496,7 +1463,7 @@ liquidity_pool_deposit_operation database_fixture::make_liquidity_pool_deposit_o return op; } -generic_exchange_operation_result database_fixture::deposit_to_liquidity_pool( account_id_type account, +generic_exchange_operation_result database_fixture_base::deposit_to_liquidity_pool( account_id_type account, liquidity_pool_id_type pool, const asset& amount_a, const asset& amount_b ) { @@ -1514,7 +1481,7 @@ generic_exchange_operation_result database_fixture::deposit_to_liquidity_pool( a return op_result.get(); } -liquidity_pool_withdraw_operation database_fixture::make_liquidity_pool_withdraw_op( account_id_type account, +liquidity_pool_withdraw_operation database_fixture_base::make_liquidity_pool_withdraw_op( account_id_type account, liquidity_pool_id_type pool, const asset& share_amount )const { liquidity_pool_withdraw_operation op; @@ -1524,7 +1491,7 @@ liquidity_pool_withdraw_operation database_fixture::make_liquidity_pool_withdraw return op; } -generic_exchange_operation_result database_fixture::withdraw_from_liquidity_pool( account_id_type account, +generic_exchange_operation_result database_fixture_base::withdraw_from_liquidity_pool( account_id_type account, liquidity_pool_id_type pool, const asset& share_amount ) { liquidity_pool_withdraw_operation op = make_liquidity_pool_withdraw_op( account, pool, share_amount ); @@ -1541,7 +1508,7 @@ generic_exchange_operation_result database_fixture::withdraw_from_liquidity_pool return op_result.get(); } -liquidity_pool_exchange_operation database_fixture::make_liquidity_pool_exchange_op( account_id_type account, +liquidity_pool_exchange_operation database_fixture_base::make_liquidity_pool_exchange_op( account_id_type account, liquidity_pool_id_type pool, const asset& amount_to_sell, const asset& min_to_receive )const { @@ -1553,7 +1520,7 @@ liquidity_pool_exchange_operation database_fixture::make_liquidity_pool_exchange return op; } -generic_exchange_operation_result database_fixture::exchange_with_liquidity_pool( account_id_type account, +generic_exchange_operation_result database_fixture_base::exchange_with_liquidity_pool( account_id_type account, liquidity_pool_id_type pool, const asset& amount_to_sell, const asset& min_to_receive ) { @@ -1573,7 +1540,7 @@ generic_exchange_operation_result database_fixture::exchange_with_liquidity_pool } -void database_fixture::enable_fees() +void database_fixture_base::enable_fees() { db.modify(global_property_id_type()(db), [](global_property_object& gpo) { @@ -1581,12 +1548,12 @@ void database_fixture::enable_fees() }); } -void database_fixture::upgrade_to_lifetime_member(account_id_type account) +void database_fixture_base::upgrade_to_lifetime_member(account_id_type account) { upgrade_to_lifetime_member(account(db)); } -void database_fixture::upgrade_to_lifetime_member( const account_object& account ) +void database_fixture_base::upgrade_to_lifetime_member( const account_object& account ) { try { @@ -1603,12 +1570,12 @@ void database_fixture::upgrade_to_lifetime_member( const account_object& account FC_CAPTURE_AND_RETHROW((account)) } -void database_fixture::upgrade_to_annual_member(account_id_type account) +void database_fixture_base::upgrade_to_annual_member(account_id_type account) { upgrade_to_annual_member(account(db)); } -void database_fixture::upgrade_to_annual_member(const account_object& account) +void database_fixture_base::upgrade_to_annual_member(const account_object& account) { try { account_upgrade_operation op; @@ -1622,7 +1589,7 @@ void database_fixture::upgrade_to_annual_member(const account_object& account) } FC_CAPTURE_AND_RETHROW((account)) } -void database_fixture::print_market( const string& syma, const string& symb )const +void database_fixture_base::print_market( const string& syma, const string& symb )const { const auto& limit_idx = db.get_index_type(); const auto& price_idx = limit_idx.indices().get(); @@ -1650,7 +1617,7 @@ void database_fixture::print_market( const string& syma, const string& symb )con } } -string database_fixture::pretty( const asset& a )const +string database_fixture_base::pretty( const asset& a )const { std::stringstream ss; ss << a.amount.value << " "; @@ -1658,7 +1625,7 @@ string database_fixture::pretty( const asset& a )const return ss.str(); } -void database_fixture::print_limit_order( const limit_order_object& cur )const +void database_fixture_base::print_limit_order( const limit_order_object& cur )const { std::cout << std::setw(10) << cur.seller(db).name << " "; std::cout << std::setw(10) << "LIMIT" << " "; @@ -1667,7 +1634,7 @@ void database_fixture::print_limit_order( const limit_order_object& cur )const std::cout << std::setw(16) << cur.sell_price.to_real() << " "; } -void database_fixture::print_call_orders()const +void database_fixture_base::print_call_orders()const { cout << std::fixed; cout.precision(5); @@ -1695,7 +1662,7 @@ void database_fixture::print_call_orders()const std::cout << "\n"; } -void database_fixture::print_joint_market( const string& syma, const string& symb )const +void database_fixture_base::print_joint_market( const string& syma, const string& symb )const { cout << std::fixed; cout.precision(5); @@ -1719,27 +1686,27 @@ void database_fixture::print_joint_market( const string& syma, const string& sym } } -int64_t database_fixture::get_balance( account_id_type account, asset_id_type a )const +int64_t database_fixture_base::get_balance( account_id_type account, asset_id_type a )const { return db.get_balance(account, a).amount.value; } -int64_t database_fixture::get_balance( const account_object& account, const asset_object& a )const +int64_t database_fixture_base::get_balance( const account_object& account, const asset_object& a )const { return db.get_balance(account.get_id(), a.get_id()).amount.value; } -int64_t database_fixture::get_market_fee_reward( account_id_type account_id, asset_id_type asset_id)const +int64_t database_fixture_base::get_market_fee_reward( account_id_type account_id, asset_id_type asset_id)const { return db.get_market_fee_vesting_balance(account_id, asset_id).amount.value; } -int64_t database_fixture::get_market_fee_reward( const account_object& account, const asset_object& asset )const +int64_t database_fixture_base::get_market_fee_reward( const account_object& account, const asset_object& asset )const { return get_market_fee_reward(account.get_id(), asset.get_id()); } -vector< operation_history_object > database_fixture::get_operation_history( account_id_type account_id )const +vector< operation_history_object > database_fixture_base::get_operation_history( account_id_type account_id )const { vector< operation_history_object > result; const auto& stats = account_id(db).statistics(db); @@ -1757,7 +1724,7 @@ vector< operation_history_object > database_fixture::get_operation_history( acco return result; } -vector< graphene::market_history::order_history_object > database_fixture::get_market_order_history( asset_id_type a, asset_id_type b )const +vector< graphene::market_history::order_history_object > database_fixture_base::get_market_order_history( asset_id_type a, asset_id_type b )const { const auto& history_idx = db.get_index_type().indices().get(); graphene::market_history::history_key hkey; @@ -1775,7 +1742,7 @@ vector< graphene::market_history::order_history_object > database_fixture::get_m return result; } -flat_map< uint64_t, graphene::chain::fee_parameters > database_fixture::get_htlc_fee_parameters() +flat_map< uint64_t, graphene::chain::fee_parameters > database_fixture_base::get_htlc_fee_parameters() { flat_map ret_val; @@ -1803,7 +1770,7 @@ flat_map< uint64_t, graphene::chain::fee_parameters > database_fixture::get_htlc return ret_val; } -void database_fixture::set_htlc_committee_parameters() +void database_fixture_base::set_htlc_committee_parameters() { // htlc fees // get existing fee_schedule @@ -1877,7 +1844,7 @@ bool _push_block( database& db, const signed_block& b, uint32_t skip_flags /* = processed_transaction _push_transaction( database& db, const signed_transaction& tx, uint32_t skip_flags /* = 0 */ ) { try { auto pt = db.push_transaction( precomputable_transaction(tx), skip_flags ); - database_fixture::verify_asset_supplies(db); + database_fixture_base::verify_asset_supplies(db); return pt; } FC_CAPTURE_AND_RETHROW((tx)) } diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index 45aa1e6e27..5c9f746af4 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -25,6 +25,11 @@ #include +#include +#include + +#include + #include #include @@ -36,6 +41,7 @@ #include #include #include +#include #include @@ -192,7 +198,7 @@ bool _push_block( database& db, const signed_block& b, uint32_t skip_flags = 0 ) processed_transaction _push_transaction( database& db, const signed_transaction& tx, uint32_t skip_flags = 0 ); } // namespace test -struct database_fixture { +struct database_fixture_base { // the reason we use an app is to exercise the indexes of built-in // plugins graphene::app::application app; @@ -201,11 +207,11 @@ struct database_fixture { signed_transaction trx; public_key_type committee_key; account_id_type committee_account; - fc::ecc::private_key private_key = fc::ecc::private_key::generate(); - fc::ecc::private_key init_account_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")) ); - public_key_type init_account_pub_key; + const fc::ecc::private_key private_key; + const fc::ecc::private_key init_account_priv_key; + const public_key_type init_account_pub_key; - optional data_dir; + fc::temp_directory data_dir; bool skip_key_index_test = false; uint32_t anon_acct_count; bool hf1270 = false; @@ -214,14 +220,24 @@ struct database_fixture { string es_index_prefix; ///< Index prefix for elasticsearch plugin string es_obj_index_prefix; ///< Index prefix for es_objects plugin - database_fixture(const fc::time_point_sec &initial_timestamp = - fc::time_point_sec(GRAPHENE_TESTING_GENESIS_TIMESTAMP)); - ~database_fixture(); + const std::string current_test_name; + const std::string current_suite_name; + + database_fixture_base(); + virtual ~database_fixture_base(); + + template + static void set_option( boost::program_options::variables_map& options, const std::string& name, const T& value ) + { + options.insert( std::make_pair( name, boost::program_options::variable_value( value, false ) ) ); + } + + static void init_genesis( database_fixture_base& fixture ); + static std::shared_ptr init_options( database_fixture_base& fixture ); static fc::ecc::private_key generate_private_key(string seed); string generate_anon_acct_name(); static void verify_asset_supplies( const database& db ); - void open_database(); void vote_for_committee_and_witnesses(uint16_t num_committee, uint16_t num_witness); signed_block generate_block(uint32_t skip = ~0, const fc::ecc::private_key& key = generate_private_key("null_key"), @@ -483,4 +499,36 @@ struct database_fixture { }; +template +struct database_fixture_init : database_fixture_base { + database_fixture_init() + { + F::init( *this ); + + asset_id_type mpa1_id(1); + BOOST_REQUIRE( mpa1_id(db).is_market_issued() ); + BOOST_CHECK( mpa1_id(db).bitasset_data(db).asset_id == mpa1_id ); + } + + static void init( database_fixture_init& fixture ) + { try { + fixture.data_dir = fc::temp_directory( graphene::utilities::temp_directory_path() ); + fc::create_directories( fixture.data_dir.path() ); + F::init_genesis( fixture ); + fc::json::save_to_file( fixture.genesis_state, fixture.data_dir.path() / "genesis.json" ); + auto options = F::init_options( fixture ); + set_option( *options, "genesis-json", boost::filesystem::path(fixture.data_dir.path() / "genesis.json") ); + fixture.app.initialize( fixture.data_dir.path(), options ); + fixture.app.startup(); + + fixture.generate_block(); + + test::set_expiration( fixture.db, fixture.trx ); + } FC_LOG_AND_RETHROW() } +}; + +struct database_fixture : database_fixture_init +{ +}; + } } diff --git a/tests/common/simulated_network.cpp b/tests/common/simulated_network.cpp new file mode 100644 index 0000000000..91557b1f25 --- /dev/null +++ b/tests/common/simulated_network.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "simulated_network.hpp" + +#include + +namespace graphene { namespace net { + + struct simulated_network::node_info + { + std::shared_ptr delegate; + fc::future message_sender_task_done; + std::queue messages_to_deliver; + explicit node_info(std::shared_ptr del) : delegate(del) {} + }; + + simulated_network::~simulated_network() + { + for( auto network_node_info : network_nodes ) + { + network_node_info->message_sender_task_done.cancel_and_wait("~simulated_network()"); + } + } + + void simulated_network::message_sender(std::shared_ptr destination_node) + { + while (!destination_node->messages_to_deliver.empty()) + { + try + { + const message& message_to_deliver = destination_node->messages_to_deliver.front(); + if (message_to_deliver.msg_type.value() == trx_message_type) + destination_node->delegate->handle_transaction(message_to_deliver.as()); + else if (message_to_deliver.msg_type.value() == block_message_type) + { + std::vector contained_transaction_msg_ids; + destination_node->delegate->handle_block(message_to_deliver.as(), false, + contained_transaction_msg_ids); + } + else + destination_node->delegate->handle_message(message_to_deliver); + } + catch ( const fc::exception& e ) + { + elog( "${r}", ("r",e) ); + } + destination_node->messages_to_deliver.pop(); + } + } + + void simulated_network::broadcast( const message& item_to_broadcast ) + { + for (auto network_node_info : network_nodes) + { + network_node_info->messages_to_deliver.emplace(item_to_broadcast); + if (!network_node_info->message_sender_task_done.valid() || network_node_info->message_sender_task_done.ready()) + network_node_info->message_sender_task_done = fc::async([=](){ message_sender(network_node_info); }, + "simulated_network_sender"); + } + } + + void simulated_network::add_node_delegate( std::shared_ptr node_delegate_to_add ) + { + network_nodes.push_back(std::make_shared(node_delegate_to_add)); + } + +} } // graphene::net diff --git a/tests/common/simulated_network.hpp b/tests/common/simulated_network.hpp new file mode 100644 index 0000000000..85f59e213a --- /dev/null +++ b/tests/common/simulated_network.hpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#pragma once + +#include + +#include + +namespace graphene { namespace net { + +class simulated_network : public node +{ +public: + ~simulated_network() override; + explicit simulated_network(const std::string& user_agent) : node(user_agent) {} + void listen_to_p2p_network() override {} + void connect_to_p2p_network() override {} + void connect_to_endpoint(const fc::ip::endpoint& ep) override {} + + fc::ip::endpoint get_actual_listening_endpoint() const override { return fc::ip::endpoint(); } + + void sync_from(const item_id& current_head_block, const std::vector& hard_fork_block_numbers) override {} + void broadcast(const message& item_to_broadcast) override; + void add_node_delegate(std::shared_ptr node_delegate_to_add); + + uint32_t get_connection_count() const override { return 8; } +private: + struct node_info; + void message_sender(std::shared_ptr destination_node); + std::list> network_nodes; +}; + +using simulated_network_ptr = std::shared_ptr; + +} } // graphene::net diff --git a/tests/elasticsearch/main.cpp b/tests/elasticsearch/main.cpp index 7bbb090ea5..315c9f3dc2 100644 --- a/tests/elasticsearch/main.cpp +++ b/tests/elasticsearch/main.cpp @@ -29,9 +29,10 @@ #include #include +#include "../common/init_unit_test_suite.hpp" + #include "../common/database_fixture.hpp" -#include "../common/init_unit_test_suite.hpp" #include "../common/utils.hpp" #define ES_WAIT_TIME (fc::milliseconds(10000)) diff --git a/tests/tests/block_tests.cpp b/tests/tests/block_tests.cpp index c36455361f..c83ef29e7b 100644 --- a/tests/tests/block_tests.cpp +++ b/tests/tests/block_tests.cpp @@ -39,6 +39,7 @@ #include #include +#include #include "../common/database_fixture.hpp" @@ -1246,7 +1247,13 @@ BOOST_FIXTURE_TEST_CASE( transaction_invalidated_in_cache, database_fixture ) fc::temp_directory data_dir2( graphene::utilities::temp_directory_path() ); database db2; - db2.open(data_dir2.path(), make_genesis, "TEST"); + { + std::string genesis_json; + fc::read_file_contents( data_dir.path() / "genesis.json", genesis_json ); + genesis_state_type genesis = fc::json::from_string( genesis_json ).as( 50 ); + genesis.initial_chain_id = fc::sha256::hash( genesis_json ); + db2.open(data_dir2.path(), [&genesis] () { return genesis; }, "TEST"); + } BOOST_CHECK( db.get_chain_id() == db2.get_chain_id() ); while( db2.head_block_num() < db.head_block_num() ) diff --git a/tests/tests/network_broadcast_api_tests.cpp b/tests/tests/network_broadcast_api_tests.cpp index a40c112662..9a4a264492 100644 --- a/tests/tests/network_broadcast_api_tests.cpp +++ b/tests/tests/network_broadcast_api_tests.cpp @@ -72,6 +72,36 @@ BOOST_AUTO_TEST_CASE( broadcast_transaction_with_callback_test ) { } FC_LOG_AND_RETHROW() } +BOOST_AUTO_TEST_CASE( broadcast_transaction_disabled_p2p_test ) { + try { + + uint32_t called = 0; + auto callback = [&]( const variant& v ) + { + ++called; + }; + + fc::ecc::private_key cid_key = fc::ecc::private_key::regenerate( fc::digest("key") ); + const account_id_type cid_id = create_account( "cid", cid_key.get_public_key() ).id; + fund( cid_id(db) ); + + auto nb_api = std::make_shared< graphene::app::network_broadcast_api >( app ); + + set_expiration( db, trx ); + transfer_operation trans; + trans.from = cid_id; + trans.to = account_id_type(); + trans.amount = asset(1); + trx.operations.push_back( trans ); + sign( trx, cid_key ); + + BOOST_CHECK_THROW( nb_api->broadcast_transaction( trx ), fc::exception ); + BOOST_CHECK_THROW( nb_api->broadcast_transaction_with_callback( callback, trx ), fc::exception ); + BOOST_CHECK_EQUAL( called, 0u ); + + } FC_LOG_AND_RETHROW() +} + BOOST_AUTO_TEST_CASE( broadcast_transaction_too_large ) { try { diff --git a/tests/tests/operation_tests2.cpp b/tests/tests/operation_tests2.cpp index e99182f02e..26d2215b2d 100644 --- a/tests/tests/operation_tests2.cpp +++ b/tests/tests/operation_tests2.cpp @@ -829,7 +829,6 @@ BOOST_AUTO_TEST_CASE( witness_create ) generate_block(skip); auto wtplugin = app.register_plugin(); - wtplugin->plugin_set_app(&app); boost::program_options::variables_map options; // init witness key cahce @@ -995,6 +994,8 @@ BOOST_AUTO_TEST_CASE( witness_create ) produced++; } BOOST_CHECK_GE( produced, 1 ); + + wtplugin->plugin_shutdown(); } FC_LOG_AND_RETHROW() } /**