diff --git a/plugins/chain_plugin/CMakeLists.txt b/plugins/chain_plugin/CMakeLists.txt index 2699292ddda..85603ef92e2 100644 --- a/plugins/chain_plugin/CMakeLists.txt +++ b/plugins/chain_plugin/CMakeLists.txt @@ -4,7 +4,7 @@ add_library( chain_plugin chain_plugin.cpp ${HEADERS} ) -target_link_libraries( chain_plugin eosio_chain appbase ) -target_include_directories( chain_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/../chain_interface/include" "${CMAKE_CURRENT_SOURCE_DIR}/../../libraries/appbase/include") +target_link_libraries( chain_plugin producer_plugin eosio_chain appbase ) +target_include_directories( chain_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/../chain_interface/include" "${CMAKE_CURRENT_SOURCE_DIR}/../../libraries/appbase/include" "${CMAKE_CURRENT_SOURCE_DIR}/../producer_plugin/include") add_subdirectory( test ) diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index b43f6dd100a..a5cd15e9cee 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -185,6 +186,7 @@ class chain_plugin_impl { fc::optional _account_query_db; + const producer_plugin* producer_plug; }; chain_plugin::chain_plugin() @@ -1144,6 +1146,9 @@ void chain_plugin::plugin_startup() EOS_ASSERT( my->chain_config->read_mode != db_read_mode::IRREVERSIBLE || !accept_transactions(), plugin_config_exception, "read-mode = irreversible. transactions should not be enabled by enable_accept_transactions" ); try { + my->producer_plug = app().find_plugin(); + EOS_ASSERT(my->producer_plug, plugin_exception, "Failed to find producer_plugin"); + auto shutdown = [](){ return app().is_quiting(); }; if (my->snapshot_path) { auto infile = std::ifstream(my->snapshot_path->generic_string(), (std::ios::in | std::ios::binary)); @@ -1212,7 +1217,7 @@ void chain_apis::read_write::validate() const { } 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()); + return chain_apis::read_only(chain(), my->_account_query_db, get_abi_serializer_max_time(), my->producer_plug); } @@ -2436,6 +2441,12 @@ read_only::get_account_results read_only::get_account( const get_account_params& result.cpu_limit = rm.get_account_cpu_limit_ex( result.account_name, greylist_limit).first; result.ram_usage = rm.get_account_ram_usage( result.account_name ); + if ( producer_plug ) { // producer_plug is null when called from chain_plugin_tests.cpp and get_table_tests.cpp + account_resource_limit subjective_cpu_bill_limit; + subjective_cpu_bill_limit.used = producer_plug->get_subjective_bill( result.account_name, fc::time_point::now() ); + result.subjective_cpu_bill_limit = subjective_cpu_bill_limit; + } + const auto& permissions = d.get_index(); auto perm = permissions.lower_bound( boost::make_tuple( params.account_name ) ); while( perm != permissions.end() && perm->owner == params.account_name ) { 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 dc8a55bd4ee..db80a8262b9 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp @@ -42,6 +42,8 @@ namespace eosio { using chain::abi_def; using chain::abi_serializer; +class producer_plugin; + namespace chain_apis { struct empty{}; @@ -83,12 +85,14 @@ class read_only { const fc::optional& aqdb; const fc::microseconds abi_serializer_max_time; bool shorten_abi_errors = true; + const producer_plugin* producer_plug; public: static const string KEYi64; - read_only(const controller& db, const fc::optional& aqdb, const fc::microseconds& abi_serializer_max_time) - : db(db), aqdb(aqdb), abi_serializer_max_time(abi_serializer_max_time) {} + read_only(const controller& db, const fc::optional& aqdb, const fc::microseconds& abi_serializer_max_time, const producer_plugin* producer_plug) + : db(db), aqdb(aqdb), abi_serializer_max_time(abi_serializer_max_time), producer_plug(producer_plug) { + } void validate() const {} @@ -167,6 +171,8 @@ class read_only { fc::variant refund_request; fc::variant voter_info; fc::variant rex_info; + + optional subjective_cpu_bill_limit; }; struct get_account_params { @@ -798,7 +804,7 @@ FC_REFLECT( eosio::chain_apis::read_only::get_scheduled_transactions_result, (tr FC_REFLECT( eosio::chain_apis::read_only::get_account_results, (account_name)(head_block_num)(head_block_time)(privileged)(last_code_update)(created) (core_liquid_balance)(ram_quota)(net_weight)(cpu_weight)(net_limit)(cpu_limit)(ram_usage)(permissions) - (total_resources)(self_delegated_bandwidth)(refund_request)(voter_info)(rex_info) ) + (total_resources)(self_delegated_bandwidth)(refund_request)(voter_info)(rex_info)(subjective_cpu_bill_limit) ) // @swap code_hash FC_REFLECT( eosio::chain_apis::read_only::get_code_results, (account_name)(code_hash)(wast)(wasm)(abi) ) FC_REFLECT( eosio::chain_apis::read_only::get_code_hash_results, (account_name)(code_hash) ) diff --git a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp index efa7be2ee83..d3abdb02733 100644 --- a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp +++ b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp @@ -81,6 +81,7 @@ class producer_plugin : public appbase::plugin { bool is_producer_key(const chain::public_key_type& key) const; chain::signature_type sign_compact(const chain::public_key_type& key, const fc::sha256& digest) const; + uint32_t get_subjective_bill( const account_name& first_auth, const fc::time_point& now ) const; virtual void plugin_initialize(const boost::program_options::variables_map& options); virtual void plugin_startup(); diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index b33e3264cd8..68395bc9aab 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -731,6 +731,11 @@ bool producer_plugin::is_producer_key(const chain::public_key_type& key) const return false; } +uint32_t producer_plugin::get_subjective_bill( const account_name& first_auth, const fc::time_point& now ) const +{ + return my->_subjective_billing.get_subjective_bill( first_auth, now ); +} + chain::signature_type producer_plugin::sign_compact(const chain::public_key_type& key, const fc::sha256& digest) const { if(key != chain::public_key_type()) { diff --git a/programs/cleos/main.cpp b/programs/cleos/main.cpp index 3cf0df39943..2b5c6650e1b 100644 --- a/programs/cleos/main.cpp +++ b/programs/cleos/main.cpp @@ -2304,13 +2304,18 @@ void get_account( const string& accountName, const string& coresym, bool json_fo } } - std::cout << std::fixed << setprecision(3); std::cout << indent << std::left << std::setw(11) << "used:" << std::right << std::setw(18) << to_pretty_time( res.cpu_limit.used ) << "\n"; std::cout << indent << std::left << std::setw(11) << "available:" << std::right << std::setw(18) << to_pretty_time( res.cpu_limit.available ) << "\n"; std::cout << indent << std::left << std::setw(11) << "limit:" << std::right << std::setw(18) << to_pretty_time( res.cpu_limit.max ) << "\n"; std::cout << std::endl; + if( res.subjective_cpu_bill_limit.valid() ) { + std::cout << "subjective cpu bandwidth:" << std::endl; + std::cout << indent << std::left << std::setw(11) << "used:" << std::right << std::setw(18) << to_pretty_time( (res.subjective_cpu_bill_limit)->used ) << "\n"; + std::cout << std::endl; + } + if( res.refund_request.is_object() ) { auto obj = res.refund_request.get_object(); auto request_time = fc::time_point_sec::from_iso_string( obj["request_time"].as_string() ); diff --git a/tests/chain_plugin_tests.cpp b/tests/chain_plugin_tests.cpp index 36a0beb6871..30f5d857c7f 100644 --- a/tests/chain_plugin_tests.cpp +++ b/tests/chain_plugin_tests.cpp @@ -89,7 +89,7 @@ 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(), {}); // block should be decoded successfully std::string block_str = json::to_pretty_string(plugin.get_block(param)); diff --git a/tests/get_table_tests.cpp b/tests/get_table_tests.cpp index 3e48272e4be..531e43a4b36 100644 --- a/tests/get_table_tests.cpp +++ b/tests/get_table_tests.cpp @@ -89,7 +89,7 @@ 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(), {}); eosio::chain_apis::read_only::get_table_by_scope_params param{N(eosio.token), N(accounts), "inita", "", 10}; eosio::chain_apis::read_only::get_table_by_scope_result result = plugin.read_only::get_table_by_scope(param); @@ -194,7 +194,7 @@ 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(), {}); eosio::chain_apis::read_only::get_table_rows_params p; p.code = N(eosio.token); p.scope = "inita"; @@ -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(), {}); eosio::chain_apis::read_only::get_table_rows_params p; p.code = N(eosio); p.scope = "eosio"; @@ -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(), {}); chain_apis::read_only::get_table_rows_params params{ .json=true, .code=N(test),