From 49e48d1b1adbf028c0284943a0115cc2a53d79b5 Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Sat, 25 Nov 2017 14:35:16 -0600 Subject: [PATCH 1/2] Added configuration for pending transaction queue depth limit. --- libraries/chain/chain_controller.cpp | 6 ++++-- libraries/chain/include/eos/chain/chain_controller.hpp | 2 ++ libraries/chain/include/eos/chain/config.hpp | 2 ++ plugins/chain_plugin/chain_plugin.cpp | 8 +++++++- tests/common/database_fixture.cpp | 6 ++++-- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/libraries/chain/chain_controller.cpp b/libraries/chain/chain_controller.cpp index 927963c6bb7..a5fe0326042 100644 --- a/libraries/chain/chain_controller.cpp +++ b/libraries/chain/chain_controller.cpp @@ -241,7 +241,7 @@ processed_transaction chain_controller::_push_transaction(const signed_transacti if (!_pending_tx_session.valid()) _pending_tx_session = _db.start_undo_session(true); - FC_ASSERT( _pending_transactions.size() < 1000, "too many pending transactions, try again later" ); + FC_ASSERT( _pending_transactions.size() < _pending_txn_depth_limit, "too many pending transactions, try again later" ); auto temp_session = _db.start_undo_session(true); validate_referenced_accounts(trx); @@ -1199,6 +1199,7 @@ chain_controller::chain_controller(database& database, fork_database& fork_db, b uint32_t txn_execution_time, uint32_t rcvd_block_txn_execution_time, uint32_t create_block_txn_execution_time, const txn_msg_limits& rate_limit, + uint32_t pending_txn_depth_limit, const applied_irreverisable_block_func& applied_func) : _db(database), _fork_db(fork_db), _block_log(blocklog), _admin(std::move(admin)), _block_interval_seconds(block_interval_seconds), _txn_execution_time(txn_execution_time), @@ -1206,7 +1207,8 @@ chain_controller::chain_controller(database& database, fork_database& fork_db, b _per_auth_account_txn_msg_rate_limit_time_frame_sec(rate_limit.per_auth_account_txn_msg_rate_time_frame_sec), _per_auth_account_txn_msg_rate_limit(rate_limit.per_auth_account_txn_msg_rate), _per_code_account_txn_msg_rate_limit_time_frame_sec(rate_limit.per_code_account_txn_msg_rate_time_frame_sec), - _per_code_account_txn_msg_rate_limit(rate_limit.per_code_account_txn_msg_rate) { + _per_code_account_txn_msg_rate_limit(rate_limit.per_code_account_txn_msg_rate), + _pending_txn_depth_limit(pending_txn_depth_limit) { if (applied_func) applied_irreversible_block.connect(*applied_func); diff --git a/libraries/chain/include/eos/chain/chain_controller.hpp b/libraries/chain/include/eos/chain/chain_controller.hpp index 89b5cb69c9a..712da786c81 100644 --- a/libraries/chain/include/eos/chain/chain_controller.hpp +++ b/libraries/chain/include/eos/chain/chain_controller.hpp @@ -45,6 +45,7 @@ namespace eosio { namespace chain { uint32_t txn_execution_time, uint32_t rcvd_block_txn_execution_time, uint32_t create_block_txn_execution_time, const txn_msg_limits& rate_limit, + uint32_t pending_txn_depth_limit, const applied_irreverisable_block_func& applied_func = {}); chain_controller(const chain_controller&) = delete; chain_controller(chain_controller&&) = delete; @@ -432,6 +433,7 @@ namespace eosio { namespace chain { const uint32_t _per_auth_account_txn_msg_rate_limit; const fc::time_point_sec _per_code_account_txn_msg_rate_limit_time_frame_sec; const uint32_t _per_code_account_txn_msg_rate_limit; + const uint32_t _pending_txn_depth_limit; flat_map _checkpoints; diff --git a/libraries/chain/include/eos/chain/config.hpp b/libraries/chain/include/eos/chain/config.hpp index f5ed8f03431..c3026039108 100644 --- a/libraries/chain/include/eos/chain/config.hpp +++ b/libraries/chain/include/eos/chain/config.hpp @@ -41,6 +41,8 @@ const static int default_per_code_account_rate = 18000; const static int default_per_code_account_max_db_limit_mbytes = 5; const static int default_row_overhead_db_limit_bytes = 8 + 8 + 8 + 8; // storage for scope/code/table + 8 extra +const static int default_pending_txn_depth_limit = 1000; + const static uint32 required_producer_participation = 33 * config::percent1; const static uint32 default_max_block_size = 5 * 1024 * 1024; diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 19f324b264c..66d90a65206 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -60,6 +60,7 @@ class chain_plugin_impl { uint32_t txn_execution_time; uint32_t create_block_txn_execution_time; txn_msg_limits cfg_txn_msg_limits; + uint32_t pending_txn_depth_limit; }; #ifdef NDEBUG @@ -107,7 +108,9 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip "Limits the maximum database storage that an account's code is allowed.") ("row-overhead-db-limit-bytes", bpo::value()->default_value(config::default_row_overhead_db_limit_bytes), "The overhead to apply per row for approximating total database storage.") - ; + ("pending-txn-depth-limit", bpo::value()->default_value(config::default_pending_txn_depth_limit), + "The maximum depth the pending transaction queue will be allowed to reach till new pushed transactions are rejected.") + ; cli.add_options() ("replay-blockchain", bpo::bool_switch()->default_value(false), "clear chain database and replay all blocks") @@ -201,6 +204,8 @@ void chain_plugin::plugin_initialize(const variables_map& options) { my->cfg_txn_msg_limits.per_code_account_txn_msg_rate_time_frame_sec = fc::time_point_sec(options.at("per-code-account-transaction-msg-rate-limit-time-frame-sec").as()); my->cfg_txn_msg_limits.per_code_account_txn_msg_rate = options.at("per-code-account-transaction-msg-rate-limit").as(); + my->pending_txn_depth_limit = options.at("pending-txn-depth-limit").as(); + chain::wasm_interface::get().per_code_account_max_db_limit_mbytes = options.at("per-code-account-max-storage-db-limit-mbytes").as(); chain::wasm_interface::get().row_overhead_db_limit_bytes = options.at("row-overhead-db-limit-bytes").as(); } @@ -237,6 +242,7 @@ void chain_plugin::plugin_startup() my->rcvd_block_txn_execution_time, my->create_block_txn_execution_time, my->cfg_txn_msg_limits, + my->pending_txn_depth_limit, applied_func)); if(!my->readonly) { diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 2b522c4d54f..1b0c8128561 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -96,7 +96,8 @@ testing_blockchain::testing_blockchain(chainbase::database& db, fork_database& f ::eosio::chain_plugin::default_transaction_execution_time * 1000, ::eosio::chain_plugin::default_received_block_transaction_execution_time * 1000, ::eosio::chain_plugin::default_create_block_transaction_execution_time * 1000, - chain_controller::txn_msg_limits{ fc::time_point_sec(30), 100000, fc::time_point_sec(30), 100000 }), + chain_controller::txn_msg_limits{ fc::time_point_sec(30), 100000, fc::time_point_sec(30), 100000 }, + config::default_pending_txn_depth_limit), db(db), fixture(fixture) {} @@ -111,7 +112,8 @@ testing_blockchain::testing_blockchain(chainbase::database& db, fork_database& f transaction_execution_time_msec * 1000, received_block_execution_time_msec * 1000, create_block_execution_time_msec * 1000, - rate_limits), + rate_limits, + config::default_pending_txn_depth_limit), db(db), fixture(fixture) {} From 6f156066be3da18e19f2b7c2db04fb354f7e6c43 Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Sat, 25 Nov 2017 17:26:34 -0600 Subject: [PATCH 2/2] Added configuration for block generation time limit and moved pending transaction depth limit into rate limiting configuration structure. --- libraries/chain/chain_controller.cpp | 6 +++--- .../chain/include/eos/chain/chain_controller.hpp | 4 +++- libraries/chain/include/eos/chain/config.hpp | 1 + libraries/fc/include/fc/time.hpp | 1 + plugins/chain_plugin/chain_plugin.cpp | 7 ++++--- tests/common/database_fixture.cpp | 12 ++++++++---- 6 files changed, 20 insertions(+), 11 deletions(-) diff --git a/libraries/chain/chain_controller.cpp b/libraries/chain/chain_controller.cpp index a5fe0326042..c1c15bc8357 100644 --- a/libraries/chain/chain_controller.cpp +++ b/libraries/chain/chain_controller.cpp @@ -323,7 +323,7 @@ signed_block chain_controller::_generate_block( pending_block.cycles[0].resize(1); // single thread for( const auto& pending_trx : _pending_transactions ) { - if( (fc::time_point::now() - start) > fc::milliseconds(200) || + if( (fc::time_point::now() - start) > _gen_block_time_limit || pending_block_size > gprops.configuration.max_blk_size) { pending.push_back(pending_trx); @@ -1199,7 +1199,6 @@ chain_controller::chain_controller(database& database, fork_database& fork_db, b uint32_t txn_execution_time, uint32_t rcvd_block_txn_execution_time, uint32_t create_block_txn_execution_time, const txn_msg_limits& rate_limit, - uint32_t pending_txn_depth_limit, const applied_irreverisable_block_func& applied_func) : _db(database), _fork_db(fork_db), _block_log(blocklog), _admin(std::move(admin)), _block_interval_seconds(block_interval_seconds), _txn_execution_time(txn_execution_time), @@ -1208,7 +1207,8 @@ chain_controller::chain_controller(database& database, fork_database& fork_db, b _per_auth_account_txn_msg_rate_limit(rate_limit.per_auth_account_txn_msg_rate), _per_code_account_txn_msg_rate_limit_time_frame_sec(rate_limit.per_code_account_txn_msg_rate_time_frame_sec), _per_code_account_txn_msg_rate_limit(rate_limit.per_code_account_txn_msg_rate), - _pending_txn_depth_limit(pending_txn_depth_limit) { + _pending_txn_depth_limit(rate_limit.pending_txn_depth_limit), + _gen_block_time_limit(rate_limit.gen_block_time_limit) { if (applied_func) applied_irreversible_block.connect(*applied_func); diff --git a/libraries/chain/include/eos/chain/chain_controller.hpp b/libraries/chain/include/eos/chain/chain_controller.hpp index 712da786c81..da7973ec2be 100644 --- a/libraries/chain/include/eos/chain/chain_controller.hpp +++ b/libraries/chain/include/eos/chain/chain_controller.hpp @@ -45,7 +45,6 @@ namespace eosio { namespace chain { uint32_t txn_execution_time, uint32_t rcvd_block_txn_execution_time, uint32_t create_block_txn_execution_time, const txn_msg_limits& rate_limit, - uint32_t pending_txn_depth_limit, const applied_irreverisable_block_func& applied_func = {}); chain_controller(const chain_controller&) = delete; chain_controller(chain_controller&&) = delete; @@ -304,6 +303,8 @@ namespace eosio { namespace chain { uint32_t per_auth_account_txn_msg_rate = config::default_per_auth_account_rate; fc::time_point_sec per_code_account_txn_msg_rate_time_frame_sec = fc::time_point_sec(config::default_per_code_account_rate_time_frame_seconds); uint32_t per_code_account_txn_msg_rate = config::default_per_code_account_rate; + uint32_t pending_txn_depth_limit = config::default_pending_txn_depth_limit; + fc::microseconds gen_block_time_limit = config::default_gen_block_time_limit; }; private: @@ -434,6 +435,7 @@ namespace eosio { namespace chain { const fc::time_point_sec _per_code_account_txn_msg_rate_limit_time_frame_sec; const uint32_t _per_code_account_txn_msg_rate_limit; const uint32_t _pending_txn_depth_limit; + const fc::microseconds _gen_block_time_limit; flat_map _checkpoints; diff --git a/libraries/chain/include/eos/chain/config.hpp b/libraries/chain/include/eos/chain/config.hpp index c3026039108..b7ba7203382 100644 --- a/libraries/chain/include/eos/chain/config.hpp +++ b/libraries/chain/include/eos/chain/config.hpp @@ -42,6 +42,7 @@ const static int default_per_code_account_max_db_limit_mbytes = 5; const static int default_row_overhead_db_limit_bytes = 8 + 8 + 8 + 8; // storage for scope/code/table + 8 extra const static int default_pending_txn_depth_limit = 1000; +const static fc::microseconds default_gen_block_time_limit = fc::milliseconds(200); const static uint32 required_producer_participation = 33 * config::percent1; diff --git a/libraries/fc/include/fc/time.hpp b/libraries/fc/include/fc/time.hpp index 11aa96d6418..3e99880e2bf 100644 --- a/libraries/fc/include/fc/time.hpp +++ b/libraries/fc/include/fc/time.hpp @@ -27,6 +27,7 @@ namespace fc { microseconds& operator-=(const microseconds& c) { _count -= c._count; return *this; } int64_t count()const { return _count; } int64_t to_seconds()const { return _count/1000000; } + int64_t to_milliseconds()const { return _count/1000; } private: friend class time_point; int64_t _count; diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 66d90a65206..1f4d0f79192 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -60,7 +60,6 @@ class chain_plugin_impl { uint32_t txn_execution_time; uint32_t create_block_txn_execution_time; txn_msg_limits cfg_txn_msg_limits; - uint32_t pending_txn_depth_limit; }; #ifdef NDEBUG @@ -110,6 +109,8 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip "The overhead to apply per row for approximating total database storage.") ("pending-txn-depth-limit", bpo::value()->default_value(config::default_pending_txn_depth_limit), "The maximum depth the pending transaction queue will be allowed to reach till new pushed transactions are rejected.") + ("gen-block-time-limit-msec", bpo::value()->default_value(config::default_gen_block_time_limit.to_milliseconds()), + "The maximum allowed for generating a block before subsequent transactions get put back on the pending transaction queue.") ; cli.add_options() ("replay-blockchain", bpo::bool_switch()->default_value(false), @@ -204,7 +205,8 @@ void chain_plugin::plugin_initialize(const variables_map& options) { my->cfg_txn_msg_limits.per_code_account_txn_msg_rate_time_frame_sec = fc::time_point_sec(options.at("per-code-account-transaction-msg-rate-limit-time-frame-sec").as()); my->cfg_txn_msg_limits.per_code_account_txn_msg_rate = options.at("per-code-account-transaction-msg-rate-limit").as(); - my->pending_txn_depth_limit = options.at("pending-txn-depth-limit").as(); + my->cfg_txn_msg_limits.pending_txn_depth_limit = options.at("pending-txn-depth-limit").as(); + my->cfg_txn_msg_limits.gen_block_time_limit = fc::milliseconds(options.at("gen-block-time-limit-msec").as()); chain::wasm_interface::get().per_code_account_max_db_limit_mbytes = options.at("per-code-account-max-storage-db-limit-mbytes").as(); chain::wasm_interface::get().row_overhead_db_limit_bytes = options.at("row-overhead-db-limit-bytes").as(); @@ -242,7 +244,6 @@ void chain_plugin::plugin_startup() my->rcvd_block_txn_execution_time, my->create_block_txn_execution_time, my->cfg_txn_msg_limits, - my->pending_txn_depth_limit, applied_func)); if(!my->readonly) { diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 1b0c8128561..0c0924c8343 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -96,8 +96,13 @@ testing_blockchain::testing_blockchain(chainbase::database& db, fork_database& f ::eosio::chain_plugin::default_transaction_execution_time * 1000, ::eosio::chain_plugin::default_received_block_transaction_execution_time * 1000, ::eosio::chain_plugin::default_create_block_transaction_execution_time * 1000, - chain_controller::txn_msg_limits{ fc::time_point_sec(30), 100000, fc::time_point_sec(30), 100000 }, - config::default_pending_txn_depth_limit), + chain_controller::txn_msg_limits{ fc::time_point_sec(30), + 100000, + fc::time_point_sec(30), + 100000, + config::default_pending_txn_depth_limit, + config::default_gen_block_time_limit + }), db(db), fixture(fixture) {} @@ -112,8 +117,7 @@ testing_blockchain::testing_blockchain(chainbase::database& db, fork_database& f transaction_execution_time_msec * 1000, received_block_execution_time_msec * 1000, create_block_execution_time_msec * 1000, - rate_limits, - config::default_pending_txn_depth_limit), + rate_limits), db(db), fixture(fixture) {}