diff --git a/plugins/chain_api_plugin/chain_api_plugin.cpp b/plugins/chain_api_plugin/chain_api_plugin.cpp index 93bf9b91ab..f2a6543135 100644 --- a/plugins/chain_api_plugin/chain_api_plugin.cpp +++ b/plugins/chain_api_plugin/chain_api_plugin.cpp @@ -51,11 +51,12 @@ parse_params(body);\ - fc::variant result( api_handle.call_name( std::move(params) ) ); \ - cb(http_response_code, std::move(result)); \ + FC_CHECK_DEADLINE(deadline);\ + fc::variant result( api_handle.call_name( std::move(params), deadline ) ); \ + cb(http_response_code, deadline, std::move(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ @@ -64,10 +65,11 @@ parse_params(body);\ - api_handle.call_name( std::move(params),\ + FC_CHECK_DEADLINE(deadline);\ + api_handle.call_name( std::move(params), \ [cb, body](const std::variant& result){\ if (std::holds_alternative(result)) {\ try {\ @@ -76,7 +78,7 @@ parse_params().chain())); auto& chain = app().get_plugin(); - auto ro_api = chain.get_read_only_api(); - auto rw_api = chain.get_read_write_api(); + auto& http = app().get_plugin(); + fc::microseconds max_response_time = http.get_max_response_time(); + + auto ro_api = chain.get_read_only_api(max_response_time); + auto rw_api = chain.get_read_write_api(max_response_time); auto& _http_plugin = app().get_plugin(); ro_api.set_shorten_abi_errors( !_http_plugin.verbose_errors() ); diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 85c9d8c766..07e00766ed 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -764,8 +764,7 @@ void chain_plugin::plugin_initialize(const variables_map& options) { LOAD_VALUE_SET( options, "profile-account", my->chain_config->profile_accounts ); - if(options.count("abi-serializer-max-time-ms")) - my->abi_serializer_max_time_us = fc::microseconds(options.at("abi-serializer-max-time-ms").as() * 1000); + my->abi_serializer_max_time_us = fc::microseconds(options.at("abi-serializer-max-time-ms").as() * 1000); my->chain_config->blocks_dir = my->blocks_dir; my->chain_config->state_dir = app().data_dir() / config::default_state_dir_name; @@ -1321,10 +1320,15 @@ void chain_plugin::handle_sighup() { _deep_mind_log.update_logger( deep_mind_logger_name ); } -chain_apis::read_write::read_write(controller& db, std::optional& trx_retry, const fc::microseconds& abi_serializer_max_time, bool api_accept_transactions) +chain_apis::read_write::read_write(controller& db, + std::optional& trx_retry, + const fc::microseconds& abi_serializer_max_time, + const fc::microseconds& http_max_response_time, + bool api_accept_transactions) : db(db) , trx_retry(trx_retry) , abi_serializer_max_time(abi_serializer_max_time) +, http_max_response_time(http_max_response_time) , api_accept_transactions(api_accept_transactions) { } @@ -1334,12 +1338,12 @@ void chain_apis::read_write::validate() const { "Not allowed, node has api-accept-transactions = false" ); } -chain_apis::read_write chain_plugin::get_read_write_api() { - return chain_apis::read_write(chain(), my->_trx_retry_db, get_abi_serializer_max_time(), api_accept_transactions()); +chain_apis::read_write chain_plugin::get_read_write_api(const fc::microseconds& http_max_response_time) { + return chain_apis::read_write(chain(), my->_trx_retry_db, get_abi_serializer_max_time(), http_max_response_time, api_accept_transactions()); } -chain_apis::read_only chain_plugin::get_read_only_api() const { - return chain_apis::read_only(chain(), my->_account_query_db, get_abi_serializer_max_time(), my->producer_plug, my->_trx_finality_status_processing.get()); +chain_apis::read_only chain_plugin::get_read_only_api(const fc::microseconds& http_max_response_time) const { + return chain_apis::read_only(chain(), my->_account_query_db, get_abi_serializer_max_time(), http_max_response_time, my->producer_plug, my->_trx_finality_status_processing.get()); } @@ -1425,7 +1429,7 @@ std::string itoh(I n, size_t hlen = sizeof(I)<<1) { return r; } -read_only::get_info_results read_only::get_info(const read_only::get_info_params&) const { +read_only::get_info_results read_only::get_info(const read_only::get_info_params&, const fc::time_point&) const { const auto& rm = db.get_resource_limits_manager(); return { @@ -1454,7 +1458,8 @@ read_only::get_info_results read_only::get_info(const read_only::get_info_params }; } -read_only::get_transaction_status_results read_only::get_transaction_status(const read_only::get_transaction_status_params& param) const { +read_only::get_transaction_status_results +read_only::get_transaction_status(const read_only::get_transaction_status_params& param, const fc::time_point& deadline) const { EOS_ASSERT(trx_finality_status_proc, unsupported_feature, "Transaction Status Interface not enabled. To enable, configure nodeos with '--transaction-finality-status-max-storage-size-gb '."); trx_finality_status_processing::chain_state ch_state = trx_finality_status_proc->get_chain_state(); @@ -1481,7 +1486,8 @@ read_only::get_transaction_status_results read_only::get_transaction_status(cons } read_only::get_activated_protocol_features_results -read_only::get_activated_protocol_features( const read_only::get_activated_protocol_features_params& params )const { +read_only::get_activated_protocol_features( const read_only::get_activated_protocol_features_params& params, + const fc::time_point& deadline )const { read_only::get_activated_protocol_features_results result; const auto& pfm = db.get_protocol_feature_manager(); @@ -1499,6 +1505,9 @@ read_only::get_activated_protocol_features( const read_only::get_activated_proto if( upper_bound_value < lower_bound_value ) return result; + fc::microseconds params_time_limit = params.time_limit_ms ? fc::milliseconds(*params.time_limit_ms) : fc::milliseconds(10); + fc::time_point params_deadline = fc::time_point::now() + params_time_limit; + auto walk_range = [&]( auto itr, auto end_itr, auto&& convert_iterator ) { fc::mutable_variant_object mvo; mvo( "activation_ordinal", 0 ); @@ -1508,11 +1517,11 @@ read_only::get_activated_protocol_features( const read_only::get_activated_proto auto& activation_block_num_value = mvo["activation_block_num"]; auto cur_time = fc::time_point::now(); - auto end_time = cur_time + fc::microseconds(1000 * 10); /// 10ms max time for( unsigned int count = 0; - cur_time <= end_time && count < params.limit && itr != end_itr; + cur_time <= params_deadline && count < params.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { + FC_CHECK_DEADLINE(deadline); const auto& conv_itr = convert_iterator( itr ); activation_ordinal_value = conv_itr.activation_ordinal(); activation_block_num_value = conv_itr.activation_block_num(); @@ -1695,7 +1704,7 @@ string get_table_type( const abi_def& abi, const name& table_name ) { EOS_ASSERT( false, chain::contract_table_query_exception, "Table ${table} is not specified in the ABI", ("table",table_name) ); } -read_only::get_table_rows_result read_only::get_table_rows( const read_only::get_table_rows_params& p )const { +read_only::get_table_rows_result read_only::get_table_rows( const read_only::get_table_rows_params& p, const fc::time_point& deadline )const { const abi_def abi = eosio::chain_apis::get_abi( db, p.code ); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" @@ -1705,43 +1714,43 @@ read_only::get_table_rows_result read_only::get_table_rows( const read_only::get EOS_ASSERT( p.table == table_with_index, chain::contract_table_query_exception, "Invalid table name ${t}", ( "t", p.table )); auto table_type = get_table_type( abi, p.table ); if( table_type == KEYi64 || p.key_type == "i64" || p.key_type == "name" ) { - return get_table_rows_ex(p,abi); + return get_table_rows_ex(p,abi,deadline); } EOS_ASSERT( false, chain::contract_table_query_exception, "Invalid table type ${type}", ("type",table_type)("abi",abi)); } else { EOS_ASSERT( !p.key_type.empty(), chain::contract_table_query_exception, "key type required for non-primary index" ); if (p.key_type == chain_apis::i64 || p.key_type == "name") { - return get_table_rows_by_seckey(p, abi, [](uint64_t v)->uint64_t { + return get_table_rows_by_seckey(p, abi, deadline, [](uint64_t v)->uint64_t { return v; }); } else if (p.key_type == chain_apis::i128) { - return get_table_rows_by_seckey(p, abi, [](uint128_t v)->uint128_t { + return get_table_rows_by_seckey(p, abi, deadline, [](uint128_t v)->uint128_t { return v; }); } else if (p.key_type == chain_apis::i256) { if ( p.encode_type == chain_apis::hex) { using conv = keytype_converter; - return get_table_rows_by_seckey(p, abi, conv::function()); + return get_table_rows_by_seckey(p, abi, deadline, conv::function()); } using conv = keytype_converter; - return get_table_rows_by_seckey(p, abi, conv::function()); + return get_table_rows_by_seckey(p, abi, deadline, conv::function()); } else if (p.key_type == chain_apis::float64) { - return get_table_rows_by_seckey(p, abi, [](double v)->float64_t { + return get_table_rows_by_seckey(p, abi, deadline, [](double v)->float64_t { float64_t f = *(float64_t *)&v; return f; }); } else if (p.key_type == chain_apis::float128) { if ( p.encode_type == chain_apis::hex) { - return get_table_rows_by_seckey(p, abi, [](uint128_t v)->float128_t{ + return get_table_rows_by_seckey(p, abi, deadline, [](uint128_t v)->float128_t{ return *reinterpret_cast(&v); }); } - return get_table_rows_by_seckey(p, abi, [](double v)->float128_t{ + return get_table_rows_by_seckey(p, abi, deadline, [](double v)->float128_t{ float64_t f = *(float64_t *)&v; float128_t f128; f64_to_f128M(f, &f128); @@ -1750,18 +1759,23 @@ read_only::get_table_rows_result read_only::get_table_rows( const read_only::get } else if (p.key_type == chain_apis::sha256) { using conv = keytype_converter; - return get_table_rows_by_seckey(p, abi, conv::function()); + return get_table_rows_by_seckey(p, abi, deadline, conv::function()); } else if(p.key_type == chain_apis::ripemd160) { using conv = keytype_converter; - return get_table_rows_by_seckey(p, abi, conv::function()); + return get_table_rows_by_seckey(p, abi, deadline, conv::function()); } EOS_ASSERT(false, chain::contract_table_query_exception, "Unsupported secondary index type: ${t}", ("t", p.key_type)); } #pragma GCC diagnostic pop } -read_only::get_table_by_scope_result read_only::get_table_by_scope( const read_only::get_table_by_scope_params& p )const { +read_only::get_table_by_scope_result read_only::get_table_by_scope( const read_only::get_table_by_scope_params& p, + const fc::time_point& deadline )const { + + fc::microseconds params_time_limit = p.time_limit_ms ? fc::milliseconds(*p.time_limit_ms) : fc::milliseconds(10); + fc::time_point params_deadline = fc::time_point::now() + params_time_limit; + read_only::get_table_by_scope_result result; const auto& d = db.db(); @@ -1785,8 +1799,8 @@ read_only::get_table_by_scope_result read_only::get_table_by_scope( const read_o auto walk_table_range = [&]( auto itr, auto end_itr ) { auto cur_time = fc::time_point::now(); - auto end_time = cur_time + fc::microseconds(1000 * 10); /// 10ms max time - for( unsigned int count = 0; cur_time <= end_time && count < p.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { + for( unsigned int count = 0; cur_time <= params_deadline && count < p.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { + FC_CHECK_DEADLINE(deadline); if( p.table && itr->table != p.table ) continue; result.rows.push_back( {itr->code, itr->scope, itr->table, itr->payer, itr->count} ); @@ -1809,7 +1823,7 @@ read_only::get_table_by_scope_result read_only::get_table_by_scope( const read_o return result; } -vector read_only::get_currency_balance( const read_only::get_currency_balance_params& p )const { +vector read_only::get_currency_balance( const read_only::get_currency_balance_params& p, const fc::time_point& deadline )const { const abi_def abi = eosio::chain_apis::get_abi( db, p.code ); (void)get_table_type( abi, name("accounts") ); @@ -1835,7 +1849,7 @@ vector read_only::get_currency_balance( const read_only::get_currency_bal return results; } -fc::variant read_only::get_currency_stats( const read_only::get_currency_stats_params& p )const { +fc::variant read_only::get_currency_stats( const read_only::get_currency_stats_params& p, const fc::time_point& deadline )const { fc::mutable_variant_object results; const abi_def abi = eosio::chain_apis::get_abi( db, p.code ); @@ -1876,14 +1890,15 @@ fc::variant get_global_row( const database& db, const abi_def& abi, const abi_se return abis.binary_to_variant(abis.get_table_type("global"_n), data, abi_serializer::create_yield_function( abi_serializer_max_time_us ), shorten_abi_errors ); } -read_only::get_producers_result read_only::get_producers( const read_only::get_producers_params& p ) const try { +read_only::get_producers_result +read_only::get_producers( const read_only::get_producers_params& params, const fc::time_point& deadline ) const try { const abi_def abi = eosio::chain_apis::get_abi(db, config::system_account_name); const auto table_type = get_table_type(abi, "producers"_n); const abi_serializer abis{ abi, abi_serializer::create_yield_function( abi_serializer_max_time ) }; EOS_ASSERT(table_type == KEYi64, chain::contract_table_query_exception, "Invalid table type ${type} for table producers", ("type",table_type)); const auto& d = db.db(); - const auto lower = name{p.lower_bound}; + const auto lower = name{params.lower_bound}; static const uint8_t secondary_index_num = 0; const auto* const table_id = d.find( @@ -1898,7 +1913,6 @@ read_only::get_producers_result read_only::get_producers( const read_only::get_p const auto& secondary_index_by_secondary = secondary_index.get(); read_only::get_producers_result result; - const auto stopTime = fc::time_point::now() + fc::microseconds(1000 * 10); // 10ms vector data; auto it = [&]{ @@ -1911,13 +1925,17 @@ read_only::get_producers_result read_only::get_producers( const read_only::get_p boost::make_tuple(secondary_table_id->id, lower.to_uint64_t()))); }(); + fc::microseconds params_time_limit = params.time_limit_ms ? fc::milliseconds(*params.time_limit_ms) : fc::milliseconds(10); + fc::time_point params_deadline = fc::time_point::now() + params_time_limit; + for( ; it != secondary_index_by_secondary.end() && it->t_id == secondary_table_id->id; ++it ) { - if (result.rows.size() >= p.limit || fc::time_point::now() > stopTime) { + FC_CHECK_DEADLINE(deadline); + if (result.rows.size() >= params.limit || fc::time_point::now() > params_deadline) { result.more = name{it->primary_key}.to_string(); break; } copy_inline_row(*kv_index.find(boost::make_tuple(table_id->id, it->primary_key)), data); - if (p.json) + if (params.json) result.rows.emplace_back( abis.binary_to_variant( abis.get_table_type("producers"_n), data, abi_serializer::create_yield_function( abi_serializer_max_time ), shorten_abi_errors ) ); else result.rows.emplace_back(fc::variant(data)); @@ -1927,8 +1945,9 @@ read_only::get_producers_result read_only::get_producers( const read_only::get_p return result; } catch (...) { read_only::get_producers_result result; + result.rows.reserve(db.active_producers().producers.size()); - for (auto p : db.active_producers().producers) { + for (const auto& p : db.active_producers().producers) { auto row = fc::mutable_variant_object() ("owner", p.producer_name) ("producer_authority", p.authority) @@ -1943,13 +1962,13 @@ read_only::get_producers_result read_only::get_producers( const read_only::get_p } } - result.rows.push_back(row); + result.rows.emplace_back(std::move(row)); } return result; } -read_only::get_producer_schedule_result read_only::get_producer_schedule( const read_only::get_producer_schedule_params& p ) const { +read_only::get_producer_schedule_result read_only::get_producer_schedule( const read_only::get_producer_schedule_params& p, const fc::time_point& deadline ) const { read_only::get_producer_schedule_result result; to_variant(db.active_producers(), result.active); if(!db.pending_producers().producers.empty()) @@ -1981,7 +2000,11 @@ auto make_resolver(const controller& control, abi_serializer::yield_function_t y } read_only::get_scheduled_transactions_result -read_only::get_scheduled_transactions( const read_only::get_scheduled_transactions_params& p ) const { +read_only::get_scheduled_transactions( const read_only::get_scheduled_transactions_params& p, const fc::time_point& deadline ) const { + + fc::microseconds params_time_limit = p.time_limit_ms ? fc::milliseconds(*p.time_limit_ms) : fc::milliseconds(10); + fc::time_point params_deadline = fc::time_point::now() + params_time_limit; + const auto& d = db.db(); const auto& idx_by_delay = d.get_index(); @@ -2015,8 +2038,8 @@ read_only::get_scheduled_transactions( const read_only::get_scheduled_transactio auto resolver = make_resolver(db, abi_serializer::create_yield_function( abi_serializer_max_time )); uint32_t remaining = p.limit; - auto time_limit = fc::time_point::now() + fc::microseconds(1000 * 10); /// 10ms max time - while (itr != idx_by_delay.end() && remaining > 0 && time_limit > fc::time_point::now()) { + while (itr != idx_by_delay.end() && remaining > 0 && params_deadline > fc::time_point::now()) { + FC_CHECK_DEADLINE(deadline); auto row = fc::mutable_variant_object() ("trx_id", itr->trx_id) ("sender", itr->sender) @@ -2053,7 +2076,7 @@ read_only::get_scheduled_transactions( const read_only::get_scheduled_transactio return result; } -fc::variant read_only::get_block(const read_only::get_block_params& params) const { +fc::variant read_only::get_block(const read_only::get_block_params& params, const fc::time_point& deadline) const { signed_block_ptr block; std::optional block_num; @@ -2089,7 +2112,7 @@ fc::variant read_only::get_block(const read_only::get_block_params& params) cons ("ref_block_prefix", ref_block_prefix); } -fc::variant read_only::get_block_info(const read_only::get_block_info_params& params) const { +fc::variant read_only::get_block_info(const read_only::get_block_info_params& params, const fc::time_point& deadline) const { signed_block_ptr block; try { @@ -2118,7 +2141,7 @@ fc::variant read_only::get_block_info(const read_only::get_block_info_params& pa ("ref_block_prefix", ref_block_prefix); } -fc::variant read_only::get_block_header_state(const get_block_header_state_params& params) const { +fc::variant read_only::get_block_header_state(const get_block_header_state_params& params, const fc::time_point& deadline) const { block_state_ptr b; std::optional block_num; std::exception_ptr e; @@ -2360,7 +2383,7 @@ void read_write::send_transaction2(const read_write::send_transaction2_params& p } CATCH_AND_CALL(next); } -read_only::get_abi_results read_only::get_abi( const get_abi_params& params )const { +read_only::get_abi_results read_only::get_abi( const get_abi_params& params, const fc::time_point& deadline )const { get_abi_results result; result.account_name = params.account_name; const auto& d = db.db(); @@ -2374,7 +2397,7 @@ read_only::get_abi_results read_only::get_abi( const get_abi_params& params )con return result; } -read_only::get_code_results read_only::get_code( const get_code_params& params )const { +read_only::get_code_results read_only::get_code( const get_code_params& params, const fc::time_point& deadline )const { get_code_results result; result.account_name = params.account_name; const auto& d = db.db(); @@ -2397,7 +2420,7 @@ read_only::get_code_results read_only::get_code( const get_code_params& params ) return result; } -read_only::get_code_hash_results read_only::get_code_hash( const get_code_hash_params& params )const { +read_only::get_code_hash_results read_only::get_code_hash( const get_code_hash_params& params, const fc::time_point& deadline )const { get_code_hash_results result; result.account_name = params.account_name; const auto& d = db.db(); @@ -2409,7 +2432,7 @@ read_only::get_code_hash_results read_only::get_code_hash( const get_code_hash_p return result; } -read_only::get_raw_code_and_abi_results read_only::get_raw_code_and_abi( const get_raw_code_and_abi_params& params)const { +read_only::get_raw_code_and_abi_results read_only::get_raw_code_and_abi( const get_raw_code_and_abi_params& params, const fc::time_point& deadline)const { get_raw_code_and_abi_results result; result.account_name = params.account_name; @@ -2425,7 +2448,7 @@ read_only::get_raw_code_and_abi_results read_only::get_raw_code_and_abi( const g return result; } -read_only::get_raw_abi_results read_only::get_raw_abi( const get_raw_abi_params& params )const { +read_only::get_raw_abi_results read_only::get_raw_abi( const get_raw_abi_params& params, const fc::time_point& deadline )const { get_raw_abi_results result; result.account_name = params.account_name; @@ -2441,7 +2464,7 @@ read_only::get_raw_abi_results read_only::get_raw_abi( const get_raw_abi_params& return result; } -read_only::get_account_results read_only::get_account( const get_account_params& params )const { +read_only::get_account_results read_only::get_account( const get_account_params& params, const fc::time_point& deadline )const { get_account_results result; result.account_name = params.account_name; @@ -2620,7 +2643,7 @@ static fc::variant action_abi_to_variant( const abi_def& abi, type_name action_t return v; }; -read_only::abi_json_to_bin_result read_only::abi_json_to_bin( const read_only::abi_json_to_bin_params& params )const try { +read_only::abi_json_to_bin_result read_only::abi_json_to_bin( const read_only::abi_json_to_bin_params& params, const fc::time_point& deadline )const try { abi_json_to_bin_result result; const auto code_account = db.db().find( params.code ); EOS_ASSERT(code_account != nullptr, contract_query_exception, "Contract can't be found ${contract}", ("contract", params.code)); @@ -2642,7 +2665,7 @@ read_only::abi_json_to_bin_result read_only::abi_json_to_bin( const read_only::a } FC_RETHROW_EXCEPTIONS( warn, "code: ${code}, action: ${action}, args: ${args}", ("code", params.code)( "action", params.action )( "args", params.args )) -read_only::abi_bin_to_json_result read_only::abi_bin_to_json( const read_only::abi_bin_to_json_params& params )const { +read_only::abi_bin_to_json_result read_only::abi_bin_to_json( const read_only::abi_bin_to_json_params& params, const fc::time_point& deadline )const { abi_bin_to_json_result result; const auto& code_account = db.db().get( params.code ); abi_def abi; @@ -2655,7 +2678,7 @@ read_only::abi_bin_to_json_result read_only::abi_bin_to_json( const read_only::a return result; } -read_only::get_required_keys_result read_only::get_required_keys( const get_required_keys_params& params )const { +read_only::get_required_keys_result read_only::get_required_keys( const get_required_keys_params& params, const fc::time_point& deadline )const { transaction pretty_input; auto resolver = make_resolver(db, abi_serializer::create_yield_function( abi_serializer_max_time )); try { @@ -2702,12 +2725,13 @@ void read_only::compute_transaction(const compute_transaction_params& params, ne chain_plugin::handle_bad_alloc(); } CATCH_AND_CALL(next); } -read_only::get_transaction_id_result read_only::get_transaction_id( const read_only::get_transaction_id_params& params)const { +read_only::get_transaction_id_result read_only::get_transaction_id( const read_only::get_transaction_id_params& params, const fc::time_point& deadline)const { return params.id(); } -account_query_db::get_accounts_by_authorizers_result read_only::get_accounts_by_authorizers( const account_query_db::get_accounts_by_authorizers_params& args) const +account_query_db::get_accounts_by_authorizers_result +read_only::get_accounts_by_authorizers( const account_query_db::get_accounts_by_authorizers_params& args, const fc::time_point& deadline) const { EOS_ASSERT(aqdb.has_value(), plugin_config_exception, "Account Queries being accessed when not enabled"); return aqdb->get_accounts_by_authorizers(args); @@ -2753,7 +2777,7 @@ chain::symbol read_only::extract_core_symbol()const { } read_only::get_consensus_parameters_results -read_only::get_consensus_parameters(const get_consensus_parameters_params& ) const { +read_only::get_consensus_parameters(const get_consensus_parameters_params&, const fc::time_point& deadline ) const { get_consensus_parameters_results results; results.chain_config = db.get_global_properties().configuration; diff --git a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp index ddf4c8132c..377adb00ae 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp @@ -91,6 +91,7 @@ class read_only { const controller& db; const std::optional& aqdb; const fc::microseconds abi_serializer_max_time; + const fc::microseconds http_max_response_time; bool shorten_abi_errors = true; const producer_plugin* producer_plug; const trx_finality_status_processing* trx_finality_status_proc; @@ -98,12 +99,26 @@ class read_only { public: static const string KEYi64; - read_only(const controller& db, const std::optional& aqdb, const fc::microseconds& abi_serializer_max_time, const producer_plugin* producer_plug, const trx_finality_status_processing* trx_finality_status_proc) - : db(db), aqdb(aqdb), abi_serializer_max_time(abi_serializer_max_time), producer_plug(producer_plug), trx_finality_status_proc(trx_finality_status_proc) { + read_only(const controller& db, const std::optional& aqdb, + const fc::microseconds& abi_serializer_max_time, const fc::microseconds& http_max_response_time, + const producer_plugin* producer_plug, + const trx_finality_status_processing* trx_finality_status_proc) + : db(db) + , aqdb(aqdb) + , abi_serializer_max_time(abi_serializer_max_time) + , http_max_response_time(http_max_response_time) + , producer_plug(producer_plug) + , trx_finality_status_proc(trx_finality_status_proc) { } void validate() const {} + // return deadline for call + fc::time_point start() const { + validate(); + return fc::time_point::now() + http_max_response_time; + } + void set_shorten_abi_errors( bool f ) { shorten_abi_errors = f; } using get_info_params = empty; @@ -134,7 +149,7 @@ class read_only { std::optional earliest_available_block_num; std::optional last_irreversible_block_time; }; - get_info_results get_info(const get_info_params&) const; + get_info_results get_info(const get_info_params&, const fc::time_point& deadline) const; struct get_transaction_status_params { chain::transaction_id_type id; @@ -155,7 +170,7 @@ class read_only { chain::block_id_type earliest_tracked_block_id; uint32_t earliest_tracked_block_number = 0; }; - get_transaction_status_results get_transaction_status(const get_transaction_status_params& params) const; + get_transaction_status_results get_transaction_status(const get_transaction_status_params& params, const fc::time_point& deadline) const; struct get_activated_protocol_features_params { @@ -164,6 +179,7 @@ class read_only { uint32_t limit = 10; bool search_by_block_num = false; bool reverse = false; + std::optional time_limit_ms; // defaults to 10ms }; struct get_activated_protocol_features_results { @@ -171,7 +187,8 @@ class read_only { std::optional more; }; - get_activated_protocol_features_results get_activated_protocol_features( const get_activated_protocol_features_params& params )const; + get_activated_protocol_features_results + get_activated_protocol_features( const get_activated_protocol_features_params& params, const fc::time_point& deadline )const; struct producer_info { name producer_name; @@ -229,7 +246,7 @@ class read_only { name account_name; std::optional expected_core_symbol; }; - get_account_results get_account( const get_account_params& params )const; + get_account_results get_account( const get_account_params& params, const fc::time_point& deadline )const; struct get_code_results { @@ -286,11 +303,11 @@ class read_only { }; - get_code_results get_code( const get_code_params& params )const; - get_code_hash_results get_code_hash( const get_code_hash_params& params )const; - get_abi_results get_abi( const get_abi_params& params )const; - get_raw_code_and_abi_results get_raw_code_and_abi( const get_raw_code_and_abi_params& params)const; - get_raw_abi_results get_raw_abi( const get_raw_abi_params& params)const; + get_code_results get_code( const get_code_params& params, const fc::time_point& deadline )const; + get_code_hash_results get_code_hash( const get_code_hash_params& params, const fc::time_point& deadline )const; + get_abi_results get_abi( const get_abi_params& params, const fc::time_point& deadline )const; + get_raw_code_and_abi_results get_raw_code_and_abi( const get_raw_code_and_abi_params& params, const fc::time_point& deadline)const; + get_raw_abi_results get_raw_abi( const get_raw_abi_params& params, const fc::time_point& deadline)const; @@ -303,7 +320,7 @@ class read_only { vector binargs; }; - abi_json_to_bin_result abi_json_to_bin( const abi_json_to_bin_params& params )const; + abi_json_to_bin_result abi_json_to_bin( const abi_json_to_bin_params& params, const fc::time_point& deadline )const; struct abi_bin_to_json_params { @@ -315,7 +332,7 @@ class read_only { fc::variant args; }; - abi_bin_to_json_result abi_bin_to_json( const abi_bin_to_json_params& params )const; + abi_bin_to_json_result abi_bin_to_json( const abi_bin_to_json_params& params, const fc::time_point& deadline )const; struct get_required_keys_params { @@ -326,30 +343,30 @@ class read_only { flat_set required_keys; }; - get_required_keys_result get_required_keys( const get_required_keys_params& params)const; + get_required_keys_result get_required_keys( const get_required_keys_params& params, const fc::time_point& deadline)const; using get_transaction_id_params = transaction; using get_transaction_id_result = transaction_id_type; - get_transaction_id_result get_transaction_id( const get_transaction_id_params& params)const; + get_transaction_id_result get_transaction_id( const get_transaction_id_params& params, const fc::time_point& deadline)const; struct get_block_params { string block_num_or_id; }; - fc::variant get_block(const get_block_params& params) const; + fc::variant get_block(const get_block_params& params, const fc::time_point& deadline) const; struct get_block_info_params { uint32_t block_num = 0; }; - fc::variant get_block_info(const get_block_info_params& params) const; + fc::variant get_block_info(const get_block_info_params& params, const fc::time_point& deadline) const; struct get_block_header_state_params { string block_num_or_id; }; - fc::variant get_block_header_state(const get_block_header_state_params& params) const; + fc::variant get_block_header_state(const get_block_header_state_params& params, const fc::time_point& deadline) const; struct get_table_rows_params { bool json = false; @@ -364,7 +381,8 @@ class read_only { string index_position; // 1 - primary (first), 2 - secondary index (in order defined by multi_index), 3 - third index, etc string encode_type{"dec"}; //dec, hex , default=dec std::optional reverse; - std::optional show_payer; // show RAM pyer + std::optional show_payer; // show RAM payer + std::optional time_limit_ms; // defaults to 10ms }; struct get_table_rows_result { @@ -373,7 +391,7 @@ class read_only { string next_key; ///< fill lower_bound with this value to fetch more rows }; - get_table_rows_result get_table_rows( const get_table_rows_params& params )const; + get_table_rows_result get_table_rows( const get_table_rows_params& params, const fc::time_point& deadline )const; struct get_table_by_scope_params { name code; // mandatory @@ -382,6 +400,7 @@ class read_only { string upper_bound; // upper bound of scope, optional uint32_t limit = 10; std::optional reverse; + std::optional time_limit_ms; // defaults to 10ms }; struct get_table_by_scope_result_row { name code; @@ -395,7 +414,7 @@ class read_only { string more; ///< fill lower_bound with this value to fetch more rows }; - get_table_by_scope_result get_table_by_scope( const get_table_by_scope_params& params )const; + get_table_by_scope_result get_table_by_scope( const get_table_by_scope_params& params, const fc::time_point& deadline )const; struct get_currency_balance_params { name code; @@ -403,7 +422,7 @@ class read_only { std::optional symbol; }; - vector get_currency_balance( const get_currency_balance_params& params )const; + vector get_currency_balance( const get_currency_balance_params& params, const fc::time_point& deadline )const; struct get_currency_stats_params { name code; @@ -417,12 +436,13 @@ class read_only { account_name issuer; }; - fc::variant get_currency_stats( const get_currency_stats_params& params )const; + fc::variant get_currency_stats( const get_currency_stats_params& params, const fc::time_point& deadline )const; struct get_producers_params { bool json = false; string lower_bound; uint32_t limit = 50; + std::optional time_limit_ms; // defaults to 10ms }; struct get_producers_result { @@ -431,7 +451,7 @@ class read_only { string more; ///< fill lower_bound with this value to fetch more rows }; - get_producers_result get_producers( const get_producers_params& params )const; + get_producers_result get_producers( const get_producers_params& params, const fc::time_point& deadline )const; struct get_producer_schedule_params { }; @@ -442,12 +462,13 @@ class read_only { fc::variant proposed; }; - get_producer_schedule_result get_producer_schedule( const get_producer_schedule_params& params )const; + get_producer_schedule_result get_producer_schedule( const get_producer_schedule_params& params, const fc::time_point& deadline )const; struct get_scheduled_transactions_params { bool json = false; string lower_bound; /// timestamp OR transaction ID uint32_t limit = 50; + std::optional time_limit_ms; // defaults to 10ms }; struct get_scheduled_transactions_result { @@ -455,7 +476,7 @@ class read_only { string more; ///< fill lower_bound with this to fetch next set of transactions }; - get_scheduled_transactions_result get_scheduled_transactions( const get_scheduled_transactions_params& params ) const; + get_scheduled_transactions_result get_scheduled_transactions( const get_scheduled_transactions_params& params, const fc::time_point& deadline ) const; struct compute_transaction_results { chain::transaction_id_type transaction_id; fc::variant processed; @@ -494,7 +515,14 @@ class read_only { static uint64_t get_table_index_name(const read_only::get_table_rows_params& p, bool& primary); template - read_only::get_table_rows_result get_table_rows_by_seckey( const read_only::get_table_rows_params& p, const abi_def& abi, ConvFn conv )const { + read_only::get_table_rows_result get_table_rows_by_seckey( const read_only::get_table_rows_params& p, + const abi_def& abi, + const fc::time_point& deadline, + ConvFn conv )const { + + fc::microseconds params_time_limit = p.time_limit_ms ? fc::milliseconds(*p.time_limit_ms) : fc::milliseconds(10); + fc::time_point params_deadline = fc::time_point::now() + params_time_limit; + read_only::get_table_rows_result result; const auto& d = db.db(); @@ -551,9 +579,9 @@ class read_only { auto walk_table_row_range = [&]( auto itr, auto end_itr ) { auto cur_time = fc::time_point::now(); - auto end_time = cur_time + fc::microseconds(1000 * 10); /// 10ms max time vector data; - for( unsigned int count = 0; cur_time <= end_time && count < p.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { + for( unsigned int count = 0; cur_time <= params_deadline && count < p.limit && itr != end_itr; ++itr, cur_time = fc::time_point::now() ) { + FC_CHECK_DEADLINE(deadline); const auto* itr2 = d.find( boost::make_tuple(t_id->id, itr->primary_key) ); if( itr2 == nullptr ) continue; copy_inline_row(*itr2, data); @@ -591,7 +619,13 @@ class read_only { } template - read_only::get_table_rows_result get_table_rows_ex( const read_only::get_table_rows_params& p, const abi_def& abi )const { + read_only::get_table_rows_result get_table_rows_ex( const read_only::get_table_rows_params& p, + const abi_def& abi, + const fc::time_point& deadline )const { + + fc::microseconds params_time_limit = p.time_limit_ms ? fc::milliseconds(*p.time_limit_ms) : fc::milliseconds(10); + fc::time_point params_deadline = fc::time_point::now() + params_time_limit; + read_only::get_table_rows_result result; const auto& d = db.db(); @@ -630,9 +664,9 @@ class read_only { auto walk_table_row_range = [&]( auto itr, auto end_itr ) { auto cur_time = fc::time_point::now(); - auto end_time = cur_time + fc::microseconds(1000 * 10); /// 10ms max time vector data; - for( unsigned int count = 0; cur_time <= end_time && count < p.limit && itr != end_itr; ++count, ++itr, cur_time = fc::time_point::now() ) { + for( unsigned int count = 0; cur_time <= params_deadline && count < p.limit && itr != end_itr; ++count, ++itr, cur_time = fc::time_point::now() ) { + FC_CHECK_DEADLINE(deadline); copy_inline_row(*itr, data); fc::variant data_var; @@ -667,7 +701,7 @@ class read_only { using get_accounts_by_authorizers_result = account_query_db::get_accounts_by_authorizers_result; using get_accounts_by_authorizers_params = account_query_db::get_accounts_by_authorizers_params; - get_accounts_by_authorizers_result get_accounts_by_authorizers( const get_accounts_by_authorizers_params& args) const; + get_accounts_by_authorizers_result get_accounts_by_authorizers( const get_accounts_by_authorizers_params& args, const fc::time_point& deadline) const; chain::symbol extract_core_symbol()const; @@ -676,18 +710,27 @@ class read_only { chain::chain_config chain_config; chain::wasm_config wasm_config; }; - get_consensus_parameters_results get_consensus_parameters(const get_consensus_parameters_params&) const; + get_consensus_parameters_results get_consensus_parameters(const get_consensus_parameters_params&, const fc::time_point& deadline) const; }; class read_write { controller& db; std::optional& trx_retry; const fc::microseconds abi_serializer_max_time; + const fc::microseconds http_max_response_time; const bool api_accept_transactions; public: - read_write(controller& db, std::optional& trx_retry, const fc::microseconds& abi_serializer_max_time, bool api_accept_transactions); + read_write(controller& db, std::optional& trx_retry, + const fc::microseconds& abi_serializer_max_time, const fc::microseconds& http_max_response_time, + bool api_accept_transactions); void validate() const; + // return deadline for call + fc::time_point start() const { + validate(); + return fc::time_point::now() + http_max_response_time; + } + using push_block_params = chain::signed_block; using push_block_results = empty; void push_block(push_block_params&& params, chain::plugin_interface::next_function next); @@ -803,8 +846,8 @@ class chain_plugin : public plugin { void plugin_shutdown(); void handle_sighup() override; - chain_apis::read_write get_read_write_api(); - chain_apis::read_only get_read_only_api() const; + chain_apis::read_write get_read_write_api(const fc::microseconds& http_max_response_time); + chain_apis::read_only get_read_only_api(const fc::microseconds& http_max_response_time) const; bool accept_block( const chain::signed_block_ptr& block, const chain::block_id_type& id ); void accept_transaction(const chain::packed_transaction_ptr& trx, chain::plugin_interface::next_function next); @@ -855,7 +898,7 @@ FC_REFLECT(eosio::chain_apis::read_only::get_info_results, FC_REFLECT(eosio::chain_apis::read_only::get_transaction_status_params, (id) ) FC_REFLECT(eosio::chain_apis::read_only::get_transaction_status_results, (state)(block_number)(block_id)(block_timestamp)(expiration)(head_number)(head_id) (head_timestamp)(irreversible_number)(irreversible_id)(irreversible_timestamp)(earliest_tracked_block_id)(earliest_tracked_block_number) ) -FC_REFLECT(eosio::chain_apis::read_only::get_activated_protocol_features_params, (lower_bound)(upper_bound)(limit)(search_by_block_num)(reverse) ) +FC_REFLECT(eosio::chain_apis::read_only::get_activated_protocol_features_params, (lower_bound)(upper_bound)(limit)(search_by_block_num)(reverse)(time_limit_ms) ) FC_REFLECT(eosio::chain_apis::read_only::get_activated_protocol_features_results, (activated_protocol_features)(more) ) FC_REFLECT(eosio::chain_apis::read_only::get_block_params, (block_num_or_id)) FC_REFLECT(eosio::chain_apis::read_only::get_block_info_params, (block_num)) @@ -864,10 +907,10 @@ FC_REFLECT(eosio::chain_apis::read_only::get_block_header_state_params, (block_n FC_REFLECT( eosio::chain_apis::read_write::push_transaction_results, (transaction_id)(processed) ) FC_REFLECT( eosio::chain_apis::read_write::send_transaction2_params, (return_failure_trace)(retry_trx)(retry_trx_num_blocks)(transaction) ) -FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_params, (json)(code)(scope)(table)(table_key)(lower_bound)(upper_bound)(limit)(key_type)(index_position)(encode_type)(reverse)(show_payer) ) +FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_params, (json)(code)(scope)(table)(table_key)(lower_bound)(upper_bound)(limit)(key_type)(index_position)(encode_type)(reverse)(show_payer)(time_limit_ms) ) FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_result, (rows)(more)(next_key) ); -FC_REFLECT( eosio::chain_apis::read_only::get_table_by_scope_params, (code)(table)(lower_bound)(upper_bound)(limit)(reverse) ) +FC_REFLECT( eosio::chain_apis::read_only::get_table_by_scope_params, (code)(table)(lower_bound)(upper_bound)(limit)(reverse)(time_limit_ms) ) FC_REFLECT( eosio::chain_apis::read_only::get_table_by_scope_result_row, (code)(scope)(table)(payer)(count)); FC_REFLECT( eosio::chain_apis::read_only::get_table_by_scope_result, (rows)(more) ); @@ -875,13 +918,13 @@ FC_REFLECT( eosio::chain_apis::read_only::get_currency_balance_params, (code)(ac FC_REFLECT( eosio::chain_apis::read_only::get_currency_stats_params, (code)(symbol)); FC_REFLECT( eosio::chain_apis::read_only::get_currency_stats_result, (supply)(max_supply)(issuer)); -FC_REFLECT( eosio::chain_apis::read_only::get_producers_params, (json)(lower_bound)(limit) ) +FC_REFLECT( eosio::chain_apis::read_only::get_producers_params, (json)(lower_bound)(limit)(time_limit_ms) ) FC_REFLECT( eosio::chain_apis::read_only::get_producers_result, (rows)(total_producer_vote_weight)(more) ); FC_REFLECT_EMPTY( eosio::chain_apis::read_only::get_producer_schedule_params ) FC_REFLECT( eosio::chain_apis::read_only::get_producer_schedule_result, (active)(pending)(proposed) ); -FC_REFLECT( eosio::chain_apis::read_only::get_scheduled_transactions_params, (json)(lower_bound)(limit) ) +FC_REFLECT( eosio::chain_apis::read_only::get_scheduled_transactions_params, (json)(lower_bound)(limit)(time_limit_ms) ) FC_REFLECT( eosio::chain_apis::read_only::get_scheduled_transactions_result, (transactions)(more) ); FC_REFLECT( eosio::chain_apis::read_only::account_resource_info, (used)(available)(max)(last_usage_update_time)(current_used) ) diff --git a/plugins/chain_plugin/test/test_chain_plugin.cpp b/plugins/chain_plugin/test/test_chain_plugin.cpp index f8e31dcf5c..15b7533aa2 100644 --- a/plugins/chain_plugin/test/test_chain_plugin.cpp +++ b/plugins/chain_plugin/test/test_chain_plugin.cpp @@ -235,8 +235,8 @@ class chain_plugin_tester : public TESTER { read_only::get_account_results get_account_info(const account_name acct){ auto account_object = control->get_account(acct); read_only::get_account_params params = { account_object.name }; - chain_apis::read_only plugin(*(control.get()), {}, fc::microseconds::maximum(), {}, {}); - return plugin.get_account(params); + chain_apis::read_only plugin(*(control.get()), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); + return plugin.get_account(params, fc::time_point::maximum()); } transaction_trace_ptr setup_producer_accounts( const std::vector& accounts ) { diff --git a/plugins/db_size_api_plugin/db_size_api_plugin.cpp b/plugins/db_size_api_plugin/db_size_api_plugin.cpp index e22ce41460..e8ba858625 100644 --- a/plugins/db_size_api_plugin/db_size_api_plugin.cpp +++ b/plugins/db_size_api_plugin/db_size_api_plugin.cpp @@ -15,7 +15,7 @@ using namespace eosio; try { \ body = parse_params(body); \ INVOKE \ - cb(http_response_code, fc::variant(result)); \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ diff --git a/plugins/http_plugin/http_plugin.cpp b/plugins/http_plugin/http_plugin.cpp index 13c4a59f10..6e91cf0020 100644 --- a/plugins/http_plugin/http_plugin.cpp +++ b/plugins/http_plugin/http_plugin.cpp @@ -93,8 +93,8 @@ class http_plugin_impl : public std::enable_shared_from_this { return; } - url_response_callback wrapped_then = [tracked_b, then=std::move(then)](int code, std::optional resp) { - then(code, std::move(resp)); + url_response_callback wrapped_then = [tracked_b, then=std::move(then)](int code, const fc::time_point& deadline, std::optional resp) { + then(code, deadline, std::move(resp)); }; // post to the app thread taking shared ownership of next (via std::shared_ptr), @@ -253,8 +253,8 @@ class http_plugin_impl : public std::enable_shared_from_this { "Maximum size in megabytes http_plugin should use for processing http requests. -1 for unlimited. 429 error response when exceeded." ) ("http-max-in-flight-requests", bpo::value()->default_value(-1), "Maximum number of requests http_plugin should use for processing http requests. 429 error response when exceeded." ) - ("http-max-response-time-ms", bpo::value()->default_value(30), - "Maximum time for processing a request.") + ("http-max-response-time-ms", bpo::value()->default_value(30), + "Maximum time for processing a request, -1 for unlimited") ("verbose-http-errors", bpo::bool_switch()->default_value(false), "Append the error log to HTTP responses") ("http-validate-host", boost::program_options::value()->default_value(true), @@ -286,8 +286,13 @@ class http_plugin_impl : public std::enable_shared_from_this { my->plugin_state->max_bytes_in_flight = max_bytes_mb * 1024 * 1024; } my->plugin_state->max_requests_in_flight = options.at( "http-max-in-flight-requests" ).as(); - my->plugin_state->max_response_time = fc::microseconds( options.at("http-max-response-time-ms").as() * 1000 ); - + int64_t max_reponse_time_ms = options.at("http-max-response-time-ms").as(); + EOS_ASSERT( max_reponse_time_ms == -1 || max_reponse_time_ms >= 0, chain::plugin_config_exception, + "http-max-response-time-ms must be -1, or non-negative: ${m}", ("m", max_reponse_time_ms) ); + // set to one year for -1, unlimited, since this is added to fc::time_point::now() for a deadline + my->plugin_state->max_response_time = max_reponse_time_ms == -1 ? + fc::days(365) : fc::microseconds( max_reponse_time_ms * 1000 ); + my->plugin_state->validate_host = options.at("http-validate-host").as(); if( options.count( "http-alias" )) { const auto& aliases = options["http-alias"].as>(); @@ -430,7 +435,7 @@ class http_plugin_impl : public std::enable_shared_from_this { try { if (body.empty()) body = "{}"; auto result = (*this).get_supported_apis(); - cb(200, fc::variant(result)); + cb(200, fc::time_point::maximum(), fc::variant(result)); } catch (...) { handle_exception("node", "get_supported_apis", body, cb); } @@ -487,36 +492,36 @@ class http_plugin_impl : public std::enable_shared_from_this { throw; } catch (chain::unknown_block_exception& e) { error_results results{400, "Unknown Block", error_results::error_info(e, verbose_http_errors)}; - cb( 400, fc::variant( results )); + cb( 400, fc::time_point::maximum(), fc::variant( results )); } catch (chain::invalid_http_request& e) { error_results results{400, "Invalid Request", error_results::error_info(e, verbose_http_errors)}; - cb( 400, fc::variant( results )); + cb( 400, fc::time_point::maximum(), fc::variant( results )); } catch (chain::unsatisfied_authorization& e) { error_results results{401, "UnAuthorized", error_results::error_info(e, verbose_http_errors)}; - cb( 401, fc::variant( results )); + cb( 401, fc::time_point::maximum(), fc::variant( results )); } catch (chain::tx_duplicate& e) { error_results results{409, "Conflict", error_results::error_info(e, verbose_http_errors)}; - cb( 409, fc::variant( results )); + cb( 409, fc::time_point::maximum(), fc::variant( results )); } catch (fc::eof_exception& e) { error_results results{422, "Unprocessable Entity", error_results::error_info(e, verbose_http_errors)}; - cb( 422, fc::variant( results )); + cb( 422, fc::time_point::maximum(), fc::variant( results )); fc_elog( logger(), "Unable to parse arguments to ${api}.${call}", ("api", api_name)( "call", call_name ) ); fc_dlog( logger(), "Bad arguments: ${args}", ("args", body) ); } catch (fc::exception& e) { error_results results{500, "Internal Service Error", error_results::error_info(e, verbose_http_errors)}; - cb( 500, fc::variant( results )); + cb( 500, fc::time_point::maximum(), fc::variant( results )); fc_dlog( logger(), "Exception while processing ${api}.${call}: ${e}", ("api", api_name)( "call", call_name )("e", e.to_detail_string()) ); } catch (std::exception& e) { error_results results{500, "Internal Service Error", error_results::error_info(fc::exception( FC_LOG_MESSAGE( error, e.what())), verbose_http_errors)}; - cb( 500, fc::variant( results )); + cb( 500, fc::time_point::maximum(), fc::variant( results )); fc_elog( logger(), "STD Exception encountered while processing ${api}.${call}", ("api", api_name)( "call", call_name ) ); fc_dlog( logger(), "Exception Details: ${e}", ("e", e.what()) ); } catch (...) { error_results results{500, "Internal Service Error", error_results::error_info(fc::exception( FC_LOG_MESSAGE( error, "Unknown Exception" )), verbose_http_errors)}; - cb( 500, fc::variant( results )); + cb( 500, fc::time_point::maximum(), fc::variant( results )); fc_elog( logger(), "Unknown Exception encountered while processing ${api}.${call}", ("api", api_name)( "call", call_name ) ); } diff --git a/plugins/http_plugin/include/eosio/http_plugin/common.hpp b/plugins/http_plugin/include/eosio/http_plugin/common.hpp index 211147ec78..faabf789bb 100644 --- a/plugins/http_plugin/include/eosio/http_plugin/common.hpp +++ b/plugins/http_plugin/include/eosio/http_plugin/common.hpp @@ -212,18 +212,24 @@ auto make_in_flight(T&& object, std::shared_ptr plugin_state) */ auto make_http_response_handler(std::shared_ptr plugin_state, detail::abstract_conn_ptr session_ptr) { return [plugin_state{std::move(plugin_state)}, - session_ptr{std::move(session_ptr)}](int code, std::optional response) { + session_ptr{std::move(session_ptr)}](int code, fc::time_point deadline, std::optional response) { auto tracked_response = make_in_flight(std::move(response), plugin_state); if(!session_ptr->verify_max_bytes_in_flight()) { return; } - // post back to an HTTP thread to to allow the response handler to be called from any thread + auto start = fc::time_point::now(); + if( deadline == fc::time_point::maximum() ) { // no caller supplied deadline so use http configured deadline + deadline = start + plugin_state->max_response_time; + } + + // post back to an HTTP thread to allow the response handler to be called from any thread boost::asio::post(plugin_state->thread_pool->get_executor(), - [plugin_state, session_ptr, code, tracked_response = std::move(tracked_response)]() { + [plugin_state, session_ptr, code, deadline, start, + tracked_response = std::move(tracked_response)]() { try { if(tracked_response->obj().has_value()) { - std::string json = fc::json::to_string(*tracked_response->obj(), fc::time_point::now() + plugin_state->max_response_time); + std::string json = fc::json::to_string(*tracked_response->obj(), deadline + (fc::time_point::now() - start)); auto tracked_json = make_in_flight(std::move(json), plugin_state); session_ptr->send_response(std::move(tracked_json->obj()), code); } else { diff --git a/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp b/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp index c8882d8fc8..a842c0b326 100644 --- a/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp +++ b/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp @@ -12,9 +12,9 @@ namespace eosio { * @brief A callback function provided to a URL handler to * allow it to specify the HTTP response code and body * - * Arguments: response_code, response_body + * Arguments: response_code, deadline, response_body */ - using url_response_callback = std::function)>; + using url_response_callback = std::function)>; /** * @brief Callback type for a URL handler diff --git a/plugins/login_plugin/login_plugin.cpp b/plugins/login_plugin/login_plugin.cpp index 5d1903c093..9ad2b498dc 100644 --- a/plugins/login_plugin/login_plugin.cpp +++ b/plugins/login_plugin/login_plugin.cpp @@ -65,7 +65,7 @@ void login_plugin::plugin_initialize(const variables_map& options) { if (body.empty()) \ body = "{}"; \ fc::variant result( call_name(fc::json::from_string(body).as()) ); \ - cb(http_response_code, std::move(result)); \ + cb(http_response_code, fc::time_point::maximum(), std::move(result)); \ } catch (...) { \ http_plugin::handle_exception("login", #call_name, body, cb); \ } \ diff --git a/plugins/net_api_plugin/net_api_plugin.cpp b/plugins/net_api_plugin/net_api_plugin.cpp index 6274f1189e..479ee6418d 100644 --- a/plugins/net_api_plugin/net_api_plugin.cpp +++ b/plugins/net_api_plugin/net_api_plugin.cpp @@ -24,7 +24,7 @@ using namespace eosio; [&api_handle](string, string body, url_response_callback cb) mutable { \ try { \ INVOKE \ - cb(http_response_code, fc::variant(result)); \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ diff --git a/plugins/producer_api_plugin/producer_api_plugin.cpp b/plugins/producer_api_plugin/producer_api_plugin.cpp index fa9f55080a..023e7bcb00 100644 --- a/plugins/producer_api_plugin/producer_api_plugin.cpp +++ b/plugins/producer_api_plugin/producer_api_plugin.cpp @@ -32,7 +32,7 @@ struct async_result_visitor : public fc::visitor { [&api_handle](string, string body, url_response_callback cb) mutable { \ try { \ INVOKE \ - cb(http_response_code, fc::variant(result)); \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ @@ -50,7 +50,7 @@ struct async_result_visitor : public fc::visitor { http_plugin::handle_exception(#api_name, #call_name, body, cb);\ }\ } else {\ - cb(http_response_code, std::visit(async_result_visitor(), result));\ + cb(http_response_code, fc::time_point::maximum(), std::visit(async_result_visitor(), result));\ }\ };\ INVOKE\ diff --git a/plugins/test_control_api_plugin/test_control_api_plugin.cpp b/plugins/test_control_api_plugin/test_control_api_plugin.cpp index 7aefdaf464..03e8be75ef 100644 --- a/plugins/test_control_api_plugin/test_control_api_plugin.cpp +++ b/plugins/test_control_api_plugin/test_control_api_plugin.cpp @@ -37,7 +37,7 @@ struct async_result_visitor : public fc::visitor { try { \ auto params = parse_params(body);\ fc::variant result( api_handle.call_name( std::move(params) ) ); \ - cb(http_response_code, std::move(result)); \ + cb(http_response_code, fc::time_point::maximum(), std::move(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ diff --git a/plugins/trace_api_plugin/trace_api_plugin.cpp b/plugins/trace_api_plugin/trace_api_plugin.cpp index c3c37bd24d..3279a7e68f 100644 --- a/plugins/trace_api_plugin/trace_api_plugin.cpp +++ b/plugins/trace_api_plugin/trace_api_plugin.cpp @@ -255,6 +255,8 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_thiscalc_deadline( max_response_time ); + auto block_number = ([&body]() -> std::optional { if (body.empty()) { return {}; @@ -274,19 +276,18 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_thiscalc_deadline( max_response_time ); auto resp = that->req_handler->get_block_trace(*block_number, [deadline]() { FC_CHECK_DEADLINE(deadline); }); if (resp.is_null()) { error_results results{404, "Trace API: block trace missing"}; - cb( 404, fc::variant( results )); + cb( 404, deadline, fc::variant( results )); } else { - cb( 200, std::move(resp) ); + cb( 200, deadline, std::move(resp) ); } } catch (...) { http_plugin::handle_exception("trace_api", "get_block", body, cb); @@ -302,6 +303,8 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_thiscalc_deadline( max_response_time ); + auto trx_id = ([&body]() -> std::optional { if (body.empty()) { return {}; @@ -320,24 +323,23 @@ struct trace_api_rpc_plugin_impl : public std::enable_shared_from_thiscalc_deadline( max_response_time ); // search for the block that contains the transaction get_block_n blk_num = common->store->get_trx_block_number(*trx_id, common->minimum_irreversible_history_blocks, [deadline]() { FC_CHECK_DEADLINE(deadline); }); if (!blk_num.has_value()){ error_results results{404, "Trace API: transaction id missing in the transaction id log files"}; - cb( 404, fc::variant( results )); + cb( 404, deadline, fc::variant( results )); } else { auto resp = that->req_handler->get_transaction_trace(*trx_id, *blk_num, [deadline]() { FC_CHECK_DEADLINE(deadline); }); if (resp.is_null()) { error_results results{404, "Trace API: transaction trace missing"}; - cb( 404, fc::variant( results )); + cb( 404, deadline, fc::variant( results )); } else { - cb( 200, std::move(resp) ); + cb( 200, deadline, std::move(resp) ); } } } catch (...) { diff --git a/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp b/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp index 4715b28842..49365ad82b 100644 --- a/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp +++ b/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp @@ -45,7 +45,7 @@ using namespace eosio::chain; try { \ if (body.empty()) body = "{}"; \ INVOKE \ - cb(http_response_code, fc::variant(result)); \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ @@ -80,7 +80,7 @@ using namespace eosio::chain; http_plugin::handle_exception(#api_name, #call_name, body, cb);\ }\ } else {\ - cb(http_response_code, fc::variant(eosio::detail::txn_test_gen_empty())); \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(eosio::detail::txn_test_gen_empty())); \ }\ };\ INVOKE \ diff --git a/plugins/wallet_api_plugin/wallet_api_plugin.cpp b/plugins/wallet_api_plugin/wallet_api_plugin.cpp index 35b18b8e3a..24ffca3f4d 100644 --- a/plugins/wallet_api_plugin/wallet_api_plugin.cpp +++ b/plugins/wallet_api_plugin/wallet_api_plugin.cpp @@ -25,7 +25,7 @@ using namespace eosio; [&api_handle](string, string body, url_response_callback cb) mutable { \ try { \ INVOKE \ - cb(http_response_code, fc::variant(result)); \ + cb(http_response_code, fc::time_point::maximum(), fc::variant(result)); \ } catch (...) { \ http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ diff --git a/programs/cleos/main.cpp b/programs/cleos/main.cpp index 3d73abf31c..3d0cf920e5 100644 --- a/programs/cleos/main.cpp +++ b/programs/cleos/main.cpp @@ -1420,6 +1420,7 @@ struct unapprove_producer_subcommand { struct list_producers_subcommand { bool print_json = false; uint32_t limit = 50; + uint32_t time_limit_ms = 10; std::string lower; list_producers_subcommand(CLI::App* actionRoot) { @@ -1427,15 +1428,18 @@ struct list_producers_subcommand { list_producers->add_flag("--json,-j", print_json, localized("Output in JSON format")); list_producers->add_option("-l,--limit", limit, localized("The maximum number of rows to return")); list_producers->add_option("-L,--lower", lower, localized("Lower bound value of key, defaults to first")); + list_producers->add_option("--time-limit", time_limit_ms, localized("Limit time of execution in milliseconds, defaults to 10ms")); list_producers->callback([this] { - auto rawResult = call(get_producers_func, fc::mutable_variant_object - ("json", true)("lower_bound", lower)("limit", limit)); + fc::mutable_variant_object mo; + mo("json", true)("lower_bound", lower)("limit", limit); + if( time_limit_ms != 10 ) mo("time_limit_ms", time_limit_ms); + auto rawResult = call(get_producers_func, mo); if ( print_json ) { std::cout << fc::json::to_pretty_string(rawResult) << std::endl; return; } auto result = rawResult.as(); - if ( result.rows.empty() ) { + if ( result.rows.empty() && result.more.empty() ) { std::cout << "No producers found" << std::endl; return; } @@ -3060,6 +3064,7 @@ int main( int argc, char** argv ) { string encode_type{"dec"}; bool binary = false; uint32_t limit = 10; + uint32_t time_limit_ms = 10; string index_position; bool reverse = false; bool show_payer = false; @@ -3068,6 +3073,7 @@ int main( int argc, char** argv ) { getTable->add_option( "scope", scope, localized("The scope within the contract in which the table is found") )->required(); getTable->add_option( "table", table, localized("The name of the table as specified by the contract abi") )->required(); getTable->add_option( "-l,--limit", limit, localized("The maximum number of rows to return") ); + getTable->add_option( "--time-limit", time_limit_ms, localized("Limit time of execution in milliseconds, defaults to 10ms")); getTable->add_option( "-k,--key", table_key, localized("Deprecated") ); getTable->add_option( "-L,--lower", lower, localized("JSON representation of lower bound value of key, defaults to first") ); getTable->add_option( "-U,--upper", upper, localized("JSON representation of upper bound value of key, defaults to last") ); @@ -3086,20 +3092,22 @@ int main( int argc, char** argv ) { getTable->callback([&] { - auto result = call(get_table_func, fc::mutable_variant_object("json", !binary) - ("code",code) - ("scope",scope) - ("table",table) - ("table_key",table_key) // not used - ("lower_bound",lower) - ("upper_bound",upper) - ("limit",limit) - ("key_type",key_type) - ("index_position", index_position) - ("encode_type", encode_type) - ("reverse", reverse) - ("show_payer", show_payer) - ); + fc::mutable_variant_object mo; + mo( "json", !binary ) + ( "code", code ) + ( "scope", scope ) + ( "table", table ) + ( "table_key", table_key ) // not used + ( "lower_bound", lower ) + ( "upper_bound", upper ) + ( "limit", limit ) + ( "key_type", key_type ) + ( "index_position", index_position ) + ( "encode_type", encode_type ) + ( "reverse", reverse ) + ( "show_payer", show_payer ); + if( time_limit_ms != 10 ) mo( "time_limit_ms", time_limit_ms ); + auto result = call( get_table_func, mo ); std::cout << fc::json::to_pretty_string(result) << std::endl; @@ -3109,17 +3117,21 @@ int main( int argc, char** argv ) { getScope->add_option( "contract", code, localized("The contract who owns the table") )->required(); getScope->add_option( "-t,--table", table, localized("The name of the table as filter") ); getScope->add_option( "-l,--limit", limit, localized("The maximum number of rows to return") ); + getScope->add_option( "--time-limit", time_limit_ms, localized("Limit time of execution in milliseconds, defaults to 10ms")); getScope->add_option( "-L,--lower", lower, localized("Lower bound of scope") ); getScope->add_option( "-U,--upper", upper, localized("Upper bound of scope") ); getScope->add_flag("-r,--reverse", reverse, localized("Iterate in reverse order")); getScope->callback([&] { - auto result = call(get_table_by_scope_func, fc::mutable_variant_object("code",code) - ("table",table) - ("lower_bound",lower) - ("upper_bound",upper) - ("limit",limit) - ("reverse", reverse) - ); + fc::mutable_variant_object mo; + mo( "code", code ) + ( "table", table ) + ( "lower_bound", lower ) + ( "upper_bound", upper ) + ( "limit", limit ) + ( "reverse", reverse ); + if( time_limit_ms != 10 ) mo( "time_limit_ms", time_limit_ms ); + auto result = call( get_table_by_scope_func, mo ); + std::cout << fc::json::to_pretty_string(result) << std::endl; }); diff --git a/programs/keosd/main.cpp b/programs/keosd/main.cpp index 15893cd3bb..e3391fe951 100644 --- a/programs/keosd/main.cpp +++ b/programs/keosd/main.cpp @@ -93,7 +93,11 @@ int main(int argc, char** argv) } initialize_logging(); auto& http = app().get_plugin(); - http.add_handler("/v1/" + keosd::config::key_store_executable_name + "/stop", [&a=app()](string, string, url_response_callback cb) { cb(200, fc::variant(fc::variant_object())); a.quit(); } ); + http.add_handler("/v1/" + keosd::config::key_store_executable_name + "/stop", + [&a=app()](string, string, url_response_callback cb) { + cb(200, fc::time_point::maximum(), fc::variant(fc::variant_object())); + a.quit(); + } ); app().startup(); app().exec(); } catch (const fc::exception& e) { diff --git a/tests/chain_plugin_tests.cpp b/tests/chain_plugin_tests.cpp index 6f9ea3a28f..cee9ab4ba3 100644 --- a/tests/chain_plugin_tests.cpp +++ b/tests/chain_plugin_tests.cpp @@ -90,10 +90,10 @@ BOOST_FIXTURE_TEST_CASE( get_block_with_invalid_abi, TESTER ) try { char headnumstr[20]; sprintf(headnumstr, "%d", headnum); chain_apis::read_only::get_block_params param{headnumstr}; - chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {}); + chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); // block should be decoded successfully - std::string block_str = json::to_pretty_string(plugin.get_block(param)); + std::string block_str = json::to_pretty_string(plugin.get_block(param, fc::time_point::maximum())); BOOST_TEST(block_str.find("procassert") != std::string::npos); BOOST_TEST(block_str.find("condition") != std::string::npos); BOOST_TEST(block_str.find("Should Not Assert!") != std::string::npos); @@ -111,7 +111,7 @@ BOOST_FIXTURE_TEST_CASE( get_block_with_invalid_abi, TESTER ) try { BOOST_CHECK_THROW(resolver("asserter"_n), invalid_type_inside_abi); // get the same block as string, results in decode failed(invalid abi) but not exception - std::string block_str2 = json::to_pretty_string(plugin.get_block(param)); + std::string block_str2 = json::to_pretty_string(plugin.get_block(param, fc::time_point::maximum())); BOOST_TEST(block_str2.find("procassert") != std::string::npos); BOOST_TEST(block_str2.find("condition") == std::string::npos); // decode failed BOOST_TEST(block_str2.find("Should Not Assert!") == std::string::npos); // decode failed @@ -123,9 +123,9 @@ BOOST_FIXTURE_TEST_CASE( get_consensus_parameters, TESTER ) try { produce_blocks(1); chain_apis::read_only::get_info_params p; - chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), nullptr, nullptr); + chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), nullptr, nullptr); - auto parms = plugin.get_consensus_parameters({}); + auto parms = plugin.get_consensus_parameters({}, fc::time_point::maximum()); // verifying chain_config BOOST_TEST(parms.chain_config.max_block_cpu_usage == control->get_global_properties().configuration.max_block_cpu_usage); @@ -170,11 +170,11 @@ BOOST_FIXTURE_TEST_CASE( get_account, TESTER ) try { produce_block(); - chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), nullptr, nullptr); + chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), nullptr, nullptr); chain_apis::read_only::get_account_params p{"alice"_n}; - chain_apis::read_only::get_account_results result = plugin.read_only::get_account(p); + chain_apis::read_only::get_account_results result = plugin.read_only::get_account(p, fc::time_point::maximum()); auto check_result_basic = [](chain_apis::read_only::get_account_results result, eosio::name nm, bool isPriv) { BOOST_REQUIRE_EQUAL(nm, result.account_name); @@ -214,7 +214,7 @@ BOOST_FIXTURE_TEST_CASE( get_account, TESTER ) try { // test link authority link_authority(name("alice"_n), name("bob"_n), name("active"_n), name("foo"_n)); produce_block(); - result = plugin.read_only::get_account(p); + result = plugin.read_only::get_account(p, fc::time_point::maximum()); check_result_basic(result, name("alice"_n), false); auto perm = result.permissions[0]; @@ -232,7 +232,7 @@ BOOST_FIXTURE_TEST_CASE( get_account, TESTER ) try { // test link authority to eosio.any link_authority(name("alice"_n), name("bob"_n), name("eosio.any"_n), name("foo"_n)); produce_block(); - result = plugin.read_only::get_account(p); + result = plugin.read_only::get_account(p, fc::time_point::maximum()); check_result_basic(result, name("alice"_n), false); // active permission should no longer have linked auth, as eosio.any replaces it perm = result.permissions[0]; diff --git a/tests/get_producers_tests.cpp b/tests/get_producers_tests.cpp index 7611672ccd..b3c24c720f 100644 --- a/tests/get_producers_tests.cpp +++ b/tests/get_producers_tests.cpp @@ -16,10 +16,10 @@ using namespace eosio::testing; BOOST_AUTO_TEST_CASE( get_producers) { try { tester chain; - eosio::chain_apis::read_only plugin(*(chain.control), {}, fc::microseconds::maximum(), {}, {}); + eosio::chain_apis::read_only plugin(*(chain.control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); eosio::chain_apis::read_only::get_producers_params params = { .json = true, .lower_bound = "", .limit = 21 }; - auto results = plugin.get_producers(params); + auto results = plugin.get_producers(params, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(results.more, ""); BOOST_REQUIRE_EQUAL(results.rows.size(), 1); const auto& row = results.rows[0].get_object(); @@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE( get_producers) { try { chain.set_producers( {"dan"_n,"sam"_n,"pam"_n} ); chain.produce_blocks(30); - results = plugin.get_producers(params); + results = plugin.get_producers(params, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(results.rows.size(), 3); auto owners = std::vector{"dan", "sam", "pam"}; auto it = owners.begin(); @@ -52,10 +52,10 @@ BOOST_AUTO_TEST_CASE( get_producers_from_table) { try { // ensure that enough voting is occurring so that producer1111 is elected as the producer chain.cross_15_percent_threshold(); - eosio::chain_apis::read_only plugin(*(chain.control), {}, fc::microseconds::maximum(), {}, {}); + eosio::chain_apis::read_only plugin(*(chain.control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); eosio::chain_apis::read_only::get_producers_params params = { .json = true, .lower_bound = "", .limit = 21 }; - auto results = plugin.get_producers(params); + auto results = plugin.get_producers(params, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(results.more, ""); BOOST_REQUIRE_EQUAL(results.rows.size(), 1); const auto& row = results.rows[0].get_object(); diff --git a/tests/get_table_seckey_tests.cpp b/tests/get_table_seckey_tests.cpp index fa97dbc266..751db74684 100644 --- a/tests/get_table_seckey_tests.cpp +++ b/tests/get_table_seckey_tests.cpp @@ -42,7 +42,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { set_abi( "test"_n, contracts::get_table_seckey_test_abi().data() ); produce_block(); - chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {}); + chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); chain_apis::read_only::get_table_rows_params params = []{ chain_apis::read_only::get_table_rows_params params{}; params.json=true; @@ -66,17 +66,17 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "6"; params.lower_bound = "a"; params.upper_bound = "a"; - auto res_nm = plugin.get_table_rows(params); + auto res_nm = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_nm.rows.size() == 1); params.lower_bound = "a"; params.upper_bound = "b"; - res_nm = plugin.get_table_rows(params); + res_nm = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_nm.rows.size() == 2); params.lower_bound = "a"; params.upper_bound = "c"; - res_nm = plugin.get_table_rows(params); + res_nm = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_nm.rows.size() == 3); push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 8)("nm", "1111")); @@ -85,12 +85,12 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.lower_bound = "1111"; params.upper_bound = "3333"; - res_nm = plugin.get_table_rows(params); + res_nm = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_nm.rows.size() == 3); params.lower_bound = "2222"; params.upper_bound = "3333"; - res_nm = plugin.get_table_rows(params); + res_nm = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_nm.rows.size() == 2); } FC_LOG_AND_RETHROW() /// get_table_next_key_test diff --git a/tests/get_table_tests.cpp b/tests/get_table_tests.cpp index f384495d9d..41a72b8525 100644 --- a/tests/get_table_tests.cpp +++ b/tests/get_table_tests.cpp @@ -89,9 +89,9 @@ BOOST_FIXTURE_TEST_CASE( get_scope_test, TESTER ) try { produce_blocks(1); // iterate over scope - eosio::chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {}); + eosio::chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); eosio::chain_apis::read_only::get_table_by_scope_params param{"eosio.token"_n, "accounts"_n, "inita", "", 10}; - eosio::chain_apis::read_only::get_table_by_scope_result result = plugin.read_only::get_table_by_scope(param); + eosio::chain_apis::read_only::get_table_by_scope_result result = plugin.read_only::get_table_by_scope(param, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(4u, result.rows.size()); BOOST_REQUIRE_EQUAL("", result.more); @@ -109,7 +109,7 @@ BOOST_FIXTURE_TEST_CASE( get_scope_test, TESTER ) try { param.lower_bound = "initb"; param.upper_bound = "initc"; - result = plugin.read_only::get_table_by_scope(param); + result = plugin.read_only::get_table_by_scope(param, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(2u, result.rows.size()); BOOST_REQUIRE_EQUAL("", result.more); if (result.rows.size() >= 2) { @@ -118,17 +118,17 @@ BOOST_FIXTURE_TEST_CASE( get_scope_test, TESTER ) try { } param.limit = 1; - result = plugin.read_only::get_table_by_scope(param); + result = plugin.read_only::get_table_by_scope(param, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL("initc", result.more); param.table = name(0); - result = plugin.read_only::get_table_by_scope(param); + result = plugin.read_only::get_table_by_scope(param, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL("initc", result.more); param.table = "invalid"_n; - result = plugin.read_only::get_table_by_scope(param); + result = plugin.read_only::get_table_by_scope(param, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(0u, result.rows.size()); BOOST_REQUIRE_EQUAL("", result.more); @@ -194,14 +194,14 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { produce_blocks(1); // get table: normal case - eosio::chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {}); + eosio::chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); eosio::chain_apis::read_only::get_table_rows_params p; p.code = "eosio.token"_n; p.scope = "inita"; p.table = "accounts"_n; p.json = true; p.index_position = "primary"; - eosio::chain_apis::read_only::get_table_rows_result result = plugin.read_only::get_table_rows(p); + eosio::chain_apis::read_only::get_table_rows_result result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(4u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 4) { @@ -213,7 +213,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { // get table: reverse ordered p.reverse = true; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(4u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 4) { @@ -226,7 +226,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { // get table: reverse ordered, with ram payer p.reverse = true; p.show_payer = true; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(4u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 4) { @@ -245,7 +245,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { p.lower_bound = "BBB"; p.upper_bound = "CCC"; p.reverse = false; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(2u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 2) { @@ -257,7 +257,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { p.lower_bound = "BBB"; p.upper_bound = "CCC"; p.reverse = true; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(2u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 2) { @@ -269,7 +269,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { p.lower_bound = p.upper_bound = ""; p.limit = 1; p.reverse = false; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL(true, result.more); if (result.rows.size() >= 1) { @@ -280,7 +280,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { p.lower_bound = p.upper_bound = ""; p.limit = 1; p.reverse = true; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL(true, result.more); if (result.rows.size() >= 1) { @@ -292,7 +292,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { p.upper_bound = "CCC"; p.limit = 1; p.reverse = false; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL(true, result.more); if (result.rows.size() >= 1) { @@ -304,7 +304,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_test, TESTER ) try { p.upper_bound = "CCC"; p.limit = 1; p.reverse = true; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL(true, result.more); if (result.rows.size() >= 1) { @@ -363,7 +363,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_by_seckey_test, TESTER ) try { produce_blocks(1); // get table: normal case - eosio::chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {}); + eosio::chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); eosio::chain_apis::read_only::get_table_rows_params p; p.code = "eosio"_n; p.scope = "eosio"; @@ -371,7 +371,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_by_seckey_test, TESTER ) try { p.json = true; p.index_position = "secondary"; // ordered by high_bid p.key_type = "i64"; - eosio::chain_apis::read_only::get_table_rows_result result = plugin.read_only::get_table_rows(p); + eosio::chain_apis::read_only::get_table_rows_result result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(4u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 4) { @@ -395,7 +395,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_by_seckey_test, TESTER ) try { // reverse search, with show ram payer p.reverse = true; p.show_payer = true; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(4u, result.rows.size()); BOOST_REQUIRE_EQUAL(false, result.more); if (result.rows.size() >= 4) { @@ -424,7 +424,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_by_seckey_test, TESTER ) try { p.reverse = false; p.show_payer = false; p.limit = 1; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL(true, result.more); if (result.rows.size() >= 1) { @@ -437,7 +437,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_by_seckey_test, TESTER ) try { p.reverse = true; p.show_payer = false; p.limit = 1; - result = plugin.read_only::get_table_rows(p); + result = plugin.read_only::get_table_rows(p, fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(1u, result.rows.size()); BOOST_REQUIRE_EQUAL(true, result.more); if (result.rows.size() >= 1) { @@ -515,7 +515,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { // } - chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {}); + chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), fc::microseconds::maximum(), {}, {}); chain_apis::read_only::get_table_rows_params params = []{ chain_apis::read_only::get_table_rows_params params{}; params.json=true; @@ -532,12 +532,12 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "1"; params.lower_bound = "0"; - auto res_1 = plugin.get_table_rows(params); + auto res_1 = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_1.rows.size() > 0); BOOST_TEST(res_1.rows[0].get_object()["key"].as() == 0); BOOST_TEST(res_1.next_key == "1"); params.lower_bound = res_1.next_key; - auto more2_res_1 = plugin.get_table_rows(params); + auto more2_res_1 = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(more2_res_1.rows.size() > 0); BOOST_TEST(more2_res_1.rows[0].get_object()["key"].as() == 1); @@ -547,12 +547,12 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "2"; params.lower_bound = "5"; - auto res_2 = plugin.get_table_rows(params); + auto res_2 = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(res_2.rows.size() > 0); BOOST_TEST(res_2.rows[0].get_object()["sec64"].as() == 5); BOOST_TEST(res_2.next_key == "7"); params.lower_bound = res_2.next_key; - auto more2_res_2 = plugin.get_table_rows(params); + auto more2_res_2 = plugin.get_table_rows(params, fc::time_point::maximum()); BOOST_REQUIRE(more2_res_2.rows.size() > 0); BOOST_TEST(more2_res_2.rows[0].get_object()["sec64"].as() == 7); @@ -561,13 +561,13 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "3"; params.lower_bound = "5"; - auto res_3 = plugin.get_table_rows(params); + auto res_3 = plugin.get_table_rows(params, fc::time_point::maximum()); chain::uint128_t sec128_expected_value = 5; BOOST_REQUIRE(res_3.rows.size() > 0); BOOST_CHECK(res_3.rows[0].get_object()["sec128"].as() == sec128_expected_value); BOOST_TEST(res_3.next_key == "7"); params.lower_bound = res_3.next_key; - auto more2_res_3 = plugin.get_table_rows(params); + auto more2_res_3 = plugin.get_table_rows(params, fc::time_point::maximum()); chain::uint128_t more2_sec128_expected_value = 7; BOOST_REQUIRE(more2_res_3.rows.size() > 0); BOOST_CHECK(more2_res_3.rows[0].get_object()["sec128"].as() == more2_sec128_expected_value); @@ -577,14 +577,14 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "4"; params.lower_bound = "5.0"; - auto res_4 = plugin.get_table_rows(params); + auto res_4 = plugin.get_table_rows(params, fc::time_point::maximum()); float64_t secdouble_expected_value = ui64_to_f64(5); BOOST_REQUIRE(res_4.rows.size() > 0); float64_t secdouble_res_value = res_4.rows[0].get_object()["secdouble"].as(); BOOST_CHECK(secdouble_res_value == secdouble_expected_value); BOOST_TEST(res_4.next_key == "7.00000000000000000"); params.lower_bound = res_4.next_key; - auto more2_res_4 = plugin.get_table_rows(params); + auto more2_res_4 = plugin.get_table_rows(params, fc::time_point::maximum()); float64_t more2_secdouble_expected_value = ui64_to_f64(7); BOOST_REQUIRE(more2_res_4.rows.size() > 0); float64_t more2_secdouble_res_value = more2_res_4.rows[0].get_object()["secdouble"].as(); @@ -595,14 +595,14 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "5"; params.lower_bound = "5.0"; - auto res_5 = plugin.get_table_rows(params); + auto res_5 = plugin.get_table_rows(params, fc::time_point::maximum()); float128_t secldouble_expected_value = ui64_to_f128(5); BOOST_REQUIRE(res_5.rows.size() > 0); float128_t secldouble_res_value = res_5.rows[0].get_object()["secldouble"].as(); BOOST_TEST(secldouble_res_value == secldouble_expected_value); BOOST_TEST(res_5.next_key == "7.00000000000000000"); params.lower_bound = res_5.next_key; - auto more2_res_5 = plugin.get_table_rows(params); + auto more2_res_5 = plugin.get_table_rows(params, fc::time_point::maximum()); float128_t more2_secldouble_expected_value = ui64_to_f128(7); BOOST_REQUIRE(more2_res_5.rows.size() > 0); float128_t more2_secldouble_res_value = more2_res_5.rows[0].get_object()["secldouble"].as(); @@ -615,7 +615,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "2"; params.lower_bound = "2652d68fbbf6000c703b35fdc607b09cd8218cbeea1d108b5c9e84842cdd5ea5"; // This is hash of "thirdinput" - auto res_6 = plugin.get_table_rows(params); + auto res_6 = plugin.get_table_rows(params, fc::time_point::maximum()); checksum256_type sec256_expected_value = checksum256_type::hash(std::string("thirdinput")); BOOST_REQUIRE(res_6.rows.size() > 0); checksum256_type sec256_res_value = res_6.rows[0].get_object()["sec256"].as(); @@ -623,7 +623,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { BOOST_TEST(res_6.rows[0].get_object()["hash_input"].as() == std::string("thirdinput")); BOOST_TEST(res_6.next_key == "3cb93a80b47b9d70c5296be3817d34b48568893b31468e3a76337bb7d3d0c264"); params.lower_bound = res_6.next_key; - auto more2_res_6 = plugin.get_table_rows(params); + auto more2_res_6 = plugin.get_table_rows(params, fc::time_point::maximum()); checksum256_type more2_sec256_expected_value = checksum256_type::hash(std::string("secondinput")); BOOST_REQUIRE(more2_res_6.rows.size() > 0); checksum256_type more2_sec256_res_value = more2_res_6.rows[0].get_object()["sec256"].as(); @@ -635,7 +635,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "2"; params.lower_bound = "0x2652d68fbbf6000c703b35fdc607b09cd8218cbeea1d108b5c9e84842cdd5ea5"; // This is sha256 hash of "thirdinput" as number - auto res_7 = plugin.get_table_rows(params); + auto res_7 = plugin.get_table_rows(params, fc::time_point::maximum()); checksum256_type i256_expected_value = checksum256_type::hash(std::string("thirdinput")); BOOST_REQUIRE(res_7.rows.size() > 0); checksum256_type i256_res_value = res_7.rows[0].get_object()["sec256"].as(); @@ -643,7 +643,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { BOOST_TEST(res_7.rows[0].get_object()["hash_input"].as() == "thirdinput"); BOOST_TEST(res_7.next_key == "0x3cb93a80b47b9d70c5296be3817d34b48568893b31468e3a76337bb7d3d0c264"); params.lower_bound = res_7.next_key; - auto more2_res_7 = plugin.get_table_rows(params); + auto more2_res_7 = plugin.get_table_rows(params, fc::time_point::maximum()); checksum256_type more2_i256_expected_value = checksum256_type::hash(std::string("secondinput")); BOOST_REQUIRE(more2_res_7.rows.size() > 0); checksum256_type more2_i256_res_value = more2_res_7.rows[0].get_object()["sec256"].as(); @@ -655,7 +655,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { params.index_position = "3"; params.lower_bound = "ab4314638b573fdc39e5a7b107938ad1b5a16414"; // This is ripemd160 hash of "thirdinput" - auto res_8 = plugin.get_table_rows(params); + auto res_8 = plugin.get_table_rows(params, fc::time_point::maximum()); ripemd160 sec160_expected_value = ripemd160::hash(std::string("thirdinput")); BOOST_REQUIRE(res_8.rows.size() > 0); ripemd160 sec160_res_value = res_8.rows[0].get_object()["sec160"].as(); @@ -663,7 +663,7 @@ BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try { BOOST_TEST(res_8.rows[0].get_object()["hash_input"].as() == "thirdinput"); BOOST_TEST(res_8.next_key == "fb9d03d3012dc2a6c7b319f914542e3423550c2a"); params.lower_bound = res_8.next_key; - auto more2_res_8 = plugin.get_table_rows(params); + auto more2_res_8 = plugin.get_table_rows(params, fc::time_point::maximum()); ripemd160 more2_sec160_expected_value = ripemd160::hash(std::string("secondinput")); BOOST_REQUIRE(more2_res_8.rows.size() > 0); ripemd160 more2_sec160_res_value = more2_res_8.rows[0].get_object()["sec160"].as();