From 8bf19fe4fc23d8dc6c78b0368f0f2828744669b9 Mon Sep 17 00:00:00 2001 From: kevin Heifner Date: Fri, 7 Nov 2025 15:44:37 -0600 Subject: [PATCH] Combine resource_limits_object and resource_usage_object into resource_object. Create a separate resource_pending_object for pending state. --- libraries/chain/deep_mind.cpp | 46 ++++++++++++-- .../chain/include/sysio/chain/deep_mind.hpp | 10 +-- .../sysio/chain/resource_limits_private.hpp | 54 +++++++--------- libraries/chain/include/sysio/chain/types.hpp | 4 +- libraries/chain/resource_limits.cpp | 58 ++++++++---------- libraries/state_history/create_deltas.cpp | 16 ++--- .../sysio/state_history/serialization.hpp | 46 ++++++++------ unittests/auth_tests.cpp | 6 +- unittests/snapshots/snap_v6.bin.gz | Bin 9490 -> 9484 bytes unittests/snapshots/snap_v6.bin.json.gz | Bin 29046 -> 29028 bytes unittests/snapshots/snap_v6.json.gz | Bin 28738 -> 28726 bytes unittests/state_history_tests.cpp | 13 +++- 12 files changed, 140 insertions(+), 113 deletions(-) diff --git a/libraries/chain/deep_mind.cpp b/libraries/chain/deep_mind.cpp index 634aabe6e6..6a149cdd2a 100644 --- a/libraries/chain/deep_mind.cpp +++ b/libraries/chain/deep_mind.cpp @@ -242,22 +242,57 @@ namespace sysio::chain { ("data", state) ); } - void deep_mind_handler::on_newaccount_resource_limits(const resource_limits::resource_limits_object& limits, const resource_limits::resource_usage_object& usage) - { + + // maintain expected format + struct resource_limits_object { + account_name owner; //< owner should not be changed within a chainbase modifier lambda + + int64_t net_weight = -1; + int64_t cpu_weight = -1; + int64_t ram_bytes = -1; + }; + struct resource_usage_object { + account_name owner; //< owner should not be changed within a chainbase modifier lambda + + resource_limits::usage_accumulator net_usage; + resource_limits::usage_accumulator cpu_usage; + uint64_t ram_usage = 0; + }; + + void deep_mind_handler::on_newaccount_resource_limits(const resource_limits::resource_object& obj) + { + resource_limits_object limits{ + .owner = obj.owner, + .net_weight = obj.net_weight, + .cpu_weight = obj.cpu_weight, + .ram_bytes = obj.ram_bytes, + }; fc_dlog(_logger, "RLIMIT_OP ACCOUNT_LIMITS INS ${data}", ("data", limits) ); + resource_usage_object usage{ + .owner = obj.owner, + .net_usage = obj.net_usage, + .cpu_usage = obj.cpu_usage, + .ram_usage = obj.ram_usage, + }; fc_dlog(_logger, "RLIMIT_OP ACCOUNT_USAGE INS ${data}", ("data", usage) ); } - void deep_mind_handler::on_update_account_usage(const resource_limits::resource_usage_object& usage) + void deep_mind_handler::on_update_account_usage(const resource_limits::resource_object& obj) { + resource_usage_object usage{ + .owner = obj.owner, + .net_usage = obj.net_usage, + .cpu_usage = obj.cpu_usage, + .ram_usage = obj.ram_usage, + }; fc_dlog(_logger, "RLIMIT_OP ACCOUNT_USAGE UPD ${data}", ("data", usage) ); } - void deep_mind_handler::on_set_account_limits(const resource_limits::resource_limits_object& limits) + void deep_mind_handler::on_set_account_limits(const resource_limits::resource_pending_object& limits) { fc_dlog(_logger, "RLIMIT_OP ACCOUNT_LIMITS UPD ${data}", ("data", limits) @@ -311,3 +346,6 @@ namespace sysio::chain { } } + +FC_REFLECT(sysio::chain::resource_limits_object, (owner)(net_weight)(cpu_weight)(ram_bytes)); +FC_REFLECT(sysio::chain::resource_usage_object, (owner)(net_usage)(cpu_usage)(ram_usage)); diff --git a/libraries/chain/include/sysio/chain/deep_mind.hpp b/libraries/chain/include/sysio/chain/deep_mind.hpp index 73893f6ce8..3323d7f142 100644 --- a/libraries/chain/include/sysio/chain/deep_mind.hpp +++ b/libraries/chain/include/sysio/chain/deep_mind.hpp @@ -19,8 +19,8 @@ struct ram_trace; namespace resource_limits { class resource_limits_config_object; class resource_limits_state_object; - struct resource_limits_object; - struct resource_usage_object; + struct resource_object; + struct resource_pending_object; } #define RAM_EVENT_ID( FORMAT, ... ) \ @@ -76,9 +76,9 @@ class deep_mind_handler void on_init_resource_limits(const resource_limits::resource_limits_config_object& config, const resource_limits::resource_limits_state_object& state); void on_update_resource_limits_config(const resource_limits::resource_limits_config_object& config); void on_update_resource_limits_state(const resource_limits::resource_limits_state_object& state); - void on_newaccount_resource_limits(const resource_limits::resource_limits_object& limits, const resource_limits::resource_usage_object& usage); - void on_update_account_usage(const resource_limits::resource_usage_object& usage); - void on_set_account_limits(const resource_limits::resource_limits_object& limits); + void on_newaccount_resource_limits(const resource_limits::resource_object& limits); + void on_update_account_usage(const resource_limits::resource_object& usage); + void on_set_account_limits(const resource_limits::resource_pending_object& limits); // The trace is consumed by the next ram_event or ram_correction void on_ram_trace(std::string&& event_id, const char* family, const char* operation, const char* legacy_tag); void on_ram_event(account_name account, uint64_t new_usage, int64_t delta); diff --git a/libraries/chain/include/sysio/chain/resource_limits_private.hpp b/libraries/chain/include/sysio/chain/resource_limits_private.hpp index f8bc0a55c0..55d196b171 100644 --- a/libraries/chain/include/sysio/chain/resource_limits_private.hpp +++ b/libraries/chain/include/sysio/chain/resource_limits_private.hpp @@ -190,57 +190,47 @@ namespace sysio { namespace chain { namespace resource_limits { using usage_accumulator = impl::exponential_moving_average_accumulator<>; - /** - * Every account that authorizes a transaction is billed for the full size of that transaction. This object - * tracks the average usage of that account. - */ - struct resource_limits_object : public chainbase::object { - - OBJECT_CTOR(resource_limits_object) + struct resource_object : public chainbase::object { + OBJECT_CTOR(resource_object) id_type id; account_name owner; //< owner should not be changed within a chainbase modifier lambda - bool pending = false; //< pending should not be changed within a chainbase modifier lambda int64_t net_weight = -1; int64_t cpu_weight = -1; int64_t ram_bytes = -1; + usage_accumulator net_usage; + usage_accumulator cpu_usage; + uint64_t ram_usage = 0; }; struct by_owner; - struct by_dirty; - using resource_limits_index = chainbase::shared_multi_index_container< - resource_limits_object, + using resource_index = chainbase::shared_multi_index_container< + resource_object, indexed_by< - ordered_unique, member>, - ordered_unique, - composite_key - > + ordered_unique, member>, + ordered_unique, member > > >; - struct resource_usage_object : public chainbase::object { - OBJECT_CTOR(resource_usage_object) + struct resource_pending_object : public chainbase::object { + OBJECT_CTOR(resource_pending_object) id_type id; account_name owner; //< owner should not be changed within a chainbase modifier lambda - usage_accumulator net_usage; - usage_accumulator cpu_usage; - - uint64_t ram_usage = 0; + int64_t net_weight = -1; + int64_t cpu_weight = -1; + int64_t ram_bytes = -1; }; - using resource_usage_index = chainbase::shared_multi_index_container< - resource_usage_object, + using resource_pending_index = chainbase::shared_multi_index_container< + resource_pending_object, indexed_by< - ordered_unique, member>, - ordered_unique, member > + ordered_unique, member>, + ordered_unique, member > > >; @@ -326,15 +316,15 @@ namespace sysio { namespace chain { namespace resource_limits { } } } /// sysio::chain::resource_limits -CHAINBASE_SET_INDEX_TYPE(sysio::chain::resource_limits::resource_limits_object, sysio::chain::resource_limits::resource_limits_index) -CHAINBASE_SET_INDEX_TYPE(sysio::chain::resource_limits::resource_usage_object, sysio::chain::resource_limits::resource_usage_index) +CHAINBASE_SET_INDEX_TYPE(sysio::chain::resource_limits::resource_object, sysio::chain::resource_limits::resource_index) +CHAINBASE_SET_INDEX_TYPE(sysio::chain::resource_limits::resource_pending_object, sysio::chain::resource_limits::resource_pending_index) CHAINBASE_SET_INDEX_TYPE(sysio::chain::resource_limits::resource_limits_config_object, sysio::chain::resource_limits::resource_limits_config_index) CHAINBASE_SET_INDEX_TYPE(sysio::chain::resource_limits::resource_limits_state_object, sysio::chain::resource_limits::resource_limits_state_index) FC_REFLECT(sysio::chain::resource_limits::usage_accumulator, (last_ordinal)(value_ex)(consumed)) // @ignore pending -FC_REFLECT(sysio::chain::resource_limits::resource_limits_object, (owner)(net_weight)(cpu_weight)(ram_bytes)) -FC_REFLECT(sysio::chain::resource_limits::resource_usage_object, (owner)(net_usage)(cpu_usage)(ram_usage)) +FC_REFLECT(sysio::chain::resource_limits::resource_object, (owner)(net_weight)(cpu_weight)(ram_bytes)(net_usage)(cpu_usage)(ram_usage)) +FC_REFLECT(sysio::chain::resource_limits::resource_pending_object, (owner)(net_weight)(cpu_weight)(ram_bytes)) FC_REFLECT(sysio::chain::resource_limits::resource_limits_config_object, (cpu_limit_parameters)(net_limit_parameters)(account_cpu_usage_average_window)(account_net_usage_average_window)) FC_REFLECT(sysio::chain::resource_limits::resource_limits_state_object, (average_block_net_usage)(average_block_cpu_usage)(pending_net_usage)(pending_cpu_usage)(total_net_weight)(total_cpu_weight)(total_ram_bytes)(virtual_net_limit)(virtual_cpu_limit)) diff --git a/libraries/chain/include/sysio/chain/types.hpp b/libraries/chain/include/sysio/chain/types.hpp index 509c845207..061ec9d1fe 100644 --- a/libraries/chain/include/sysio/chain/types.hpp +++ b/libraries/chain/include/sysio/chain/types.hpp @@ -165,8 +165,8 @@ namespace sysio::chain { UNUSED_proxy_vote_object_type, UNUSED_scope_sequence_object_type, table_id_object_type, - resource_limits_object_type, - resource_usage_object_type, + resource_object_type, + resource_pending_object_type, resource_limits_state_object_type, resource_limits_config_object_type, account_history_object_type, ///< Defined by history_plugin diff --git a/libraries/chain/resource_limits.cpp b/libraries/chain/resource_limits.cpp index 5cc868e761..28574db3a1 100644 --- a/libraries/chain/resource_limits.cpp +++ b/libraries/chain/resource_limits.cpp @@ -12,8 +12,8 @@ namespace sysio { namespace chain { namespace resource_limits { using resource_index_set = index_set< - resource_limits_index, - resource_usage_index, + resource_index, + resource_pending_index, resource_limits_state_index, resource_limits_config_index >; @@ -96,15 +96,12 @@ void resource_limits_manager::read_from_snapshot( const snapshot_reader_ptr& sna } void resource_limits_manager::initialize_account(const account_name& account, bool is_trx_transient) { - const auto& limits = _db.create([&]( resource_limits_object& bl ) { + const auto& usage = _db.create([&]( resource_object& bl ) { bl.owner = account; }); - const auto& usage = _db.create([&]( resource_usage_object& bu ) { - bu.owner = account; - }); if (auto dm_logger = _get_deep_mind_logger(is_trx_transient)) { - dm_logger->on_newaccount_resource_limits(limits, usage); + dm_logger->on_newaccount_resource_limits(usage); } } @@ -129,7 +126,7 @@ void resource_limits_manager::set_block_parameters(const elastic_limit_parameter void resource_limits_manager::update_account_usage(const accounts_billing_t& accounts, uint32_t time_slot ) { const auto& config = _db.get(); for(const auto& a: accounts | std::views::keys) { - const auto& usage = _db.get( a ); + const auto& usage = _db.get( a ); _db.modify( usage, [&]( auto& bu ){ bu.net_usage.add( 0, time_slot, config.account_net_usage_average_window ); bu.cpu_usage.add( 0, time_slot, config.account_cpu_usage_average_window ); @@ -143,7 +140,7 @@ void resource_limits_manager::add_transaction_usage(const accounts_billing_t& ac for( const auto& [a, billing] : accounts ) { - const auto& usage = _db.get( a ); + const auto& usage = _db.get( a ); int64_t unused; int64_t net_weight; int64_t cpu_weight; @@ -215,7 +212,7 @@ void resource_limits_manager::add_pending_ram_usage( const account_name account, } // wlog("Adding pending RAM usage of ${ram_delta} to account ${account}", ("ram_delta", ram_delta)("account", account)); - const auto& usage = _db.get( account ); + const auto& usage = _db.get( account ); SYS_ASSERT( ram_delta <= 0 || UINT64_MAX - usage.ram_usage >= (uint64_t)ram_delta, transaction_exception, "Ram usage delta would overflow UINT64_MAX"); @@ -234,7 +231,7 @@ void resource_limits_manager::add_pending_ram_usage( const account_name account, void resource_limits_manager::verify_account_ram_usage( const account_name account )const { int64_t ram_bytes; int64_t net_weight; int64_t cpu_weight; get_account_limits( account, ram_bytes, net_weight, cpu_weight ); - const auto& usage = _db.get( account ); + const auto& usage = _db.get( account ); if( ram_bytes >= 0 ) { SYS_ASSERT( usage.ram_usage <= static_cast(ram_bytes), ram_usage_exceeded, @@ -244,26 +241,24 @@ void resource_limits_manager::verify_account_ram_usage( const account_name accou } int64_t resource_limits_manager::get_account_ram_usage( const account_name& name )const { - return _db.get( name ).ram_usage; + return _db.get( name ).ram_usage; } bool resource_limits_manager::set_account_limits( const account_name& account, int64_t ram_bytes, int64_t net_weight, int64_t cpu_weight, bool is_trx_transient) { - //const auto& usage = _db.get( account ); /* - * Since we need to delay these until the next resource limiting boundary, these are created in a "pending" - * state or adjusted in an existing "pending" state. The chain controller will collapse "pending" state into + * Since we need to delay these until the next resource limiting boundary, these are created in a "pending" object + * or adjusted in an existing "pending" object. The chain controller will collapse "pending" objects into * the actual state at the next appropriate boundary. */ - auto find_or_create_pending_limits = [&]() -> const resource_limits_object& { - const auto* pending_limits = _db.find( boost::make_tuple(true, account) ); + auto find_or_create_pending_limits = [&]() -> const resource_pending_object& { + const auto* pending_limits = _db.find( account ); if (pending_limits == nullptr) { - const auto& limits = _db.get( boost::make_tuple(false, account)); - return _db.create([&](resource_limits_object& pending_limits){ + const auto& limits = _db.get( account ); + return _db.create([&](resource_pending_object& pending_limits){ pending_limits.owner = limits.owner; pending_limits.ram_bytes = limits.ram_bytes; pending_limits.net_weight = limits.net_weight; pending_limits.cpu_weight = limits.cpu_weight; - pending_limits.pending = true; }); } else { return *pending_limits; @@ -288,7 +283,7 @@ bool resource_limits_manager::set_account_limits( const account_name& account, i */ } - _db.modify( limits, [&]( resource_limits_object& pending_limits ){ + _db.modify( limits, [&]( resource_pending_object& pending_limits ){ pending_limits.ram_bytes = ram_bytes; pending_limits.net_weight = net_weight; pending_limits.cpu_weight = cpu_weight; @@ -302,13 +297,13 @@ bool resource_limits_manager::set_account_limits( const account_name& account, i } void resource_limits_manager::get_account_limits( const account_name& account, int64_t& ram_bytes, int64_t& net_weight, int64_t& cpu_weight ) const { - const auto* pending_buo = _db.find( boost::make_tuple(true, account) ); + const auto* pending_buo = _db.find( account ); if (pending_buo) { ram_bytes = pending_buo->ram_bytes; net_weight = pending_buo->net_weight; cpu_weight = pending_buo->cpu_weight; } else { - const auto& buo = _db.get( boost::make_tuple( false, account ) ); + const auto& buo = _db.get( account ); ram_bytes = buo.ram_bytes; net_weight = buo.net_weight; cpu_weight = buo.cpu_weight; @@ -316,7 +311,7 @@ void resource_limits_manager::get_account_limits( const account_name& account, i } bool resource_limits_manager::is_unlimited_cpu( const account_name& account ) const { - const auto* buo = _db.find( boost::make_tuple(false, account) ); + const auto* buo = _db.find( account ); if (buo) { return buo->cpu_weight == -1; } @@ -324,7 +319,7 @@ bool resource_limits_manager::is_unlimited_cpu( const account_name& account ) co } void resource_limits_manager::process_account_limit_updates() { - auto& multi_index = _db.get_mutable_index(); + auto& multi_index = _db.get_mutable_index(); auto& by_owner_index = multi_index.indices().get(); // convenience local lambda to reduce clutter @@ -345,13 +340,10 @@ void resource_limits_manager::process_account_limit_updates() { const auto& state = _db.get(); _db.modify(state, [&](resource_limits_state_object& rso){ while(!by_owner_index.empty()) { - const auto& itr = by_owner_index.lower_bound(boost::make_tuple(true)); - if (itr == by_owner_index.end() || itr->pending!= true) { - break; - } + const auto& itr = by_owner_index.begin(); - const auto& actual_entry = _db.get(boost::make_tuple(false, itr->owner)); - _db.modify(actual_entry, [&](resource_limits_object& rlo){ + const auto& actual_entry = _db.get(itr->owner); + _db.modify(actual_entry, [&](resource_object& rlo){ update_state_and_value(rso.total_ram_bytes, rlo.ram_bytes, itr->ram_bytes, "ram_bytes"); update_state_and_value(rso.total_cpu_weight, rlo.cpu_weight, itr->cpu_weight, "cpu_weight"); update_state_and_value(rso.total_net_weight, rlo.net_weight, itr->net_weight, "net_weight"); @@ -432,7 +424,7 @@ std::pair resource_limits_manager::get_account_cpu_limit_ex( const account_name& name, uint32_t greylist_limit, const std::optional& current_time) const { const auto& state = _db.get(); - const auto& usage = _db.get(name); + const auto& usage = _db.get(name); const auto& config = _db.get(); int64_t cpu_weight, x, y; @@ -494,7 +486,7 @@ std::pair resource_limits_manager::get_account_net_limit_ex( const account_name& name, uint32_t greylist_limit, const std::optional& current_time) const { const auto& config = _db.get(); const auto& state = _db.get(); - const auto& usage = _db.get(name); + const auto& usage = _db.get(name); int64_t net_weight, x, y; get_account_limits( name, x, net_weight, y ); diff --git a/libraries/state_history/create_deltas.cpp b/libraries/state_history/create_deltas.cpp index f8f7279898..2b8e495709 100644 --- a/libraries/state_history/create_deltas.cpp +++ b/libraries/state_history/create_deltas.cpp @@ -13,14 +13,6 @@ bool include_delta(const chain::table_id_object& old, const chain::table_id_obje return old.payer != curr.payer; } -bool include_delta(const chain::resource_limits::resource_limits_object& old, - const chain::resource_limits::resource_limits_object& curr) { - return // - old.net_weight != curr.net_weight || // - old.cpu_weight != curr.cpu_weight || // - old.ram_bytes != curr.ram_bytes; -} - bool include_delta(const chain::resource_limits::resource_limits_state_object& old, const chain::resource_limits::resource_limits_state_object& curr) { return // @@ -151,7 +143,7 @@ void pack_deltas(boost::iostreams::filtering_ostreambuf& obuf, const chainbase:: chain::index256_index*, chain::index_double_index*, chain::index_long_double_index*, chain::global_property_multi_index*, chain::protocol_state_multi_index*, chain::permission_index*, chain::permission_link_index*, - chain::resource_limits::resource_limits_index*, chain::resource_limits::resource_usage_index*, + chain::resource_limits::resource_index*, chain::resource_limits::resource_limits_state_index*, chain::resource_limits::resource_limits_config_index*>()); @@ -175,8 +167,10 @@ void pack_deltas(boost::iostreams::filtering_ostreambuf& obuf, const chainbase:: process_table(ds, "permission", db.get_index(), pack_row); process_table(ds, "permission_link", db.get_index(), pack_row); - process_table(ds, "resource_limits", db.get_index(), pack_row); - process_table(ds, "resource_usage", db.get_index(), pack_row); + auto pack_resource_limit_row = [&](auto& ds, auto& row) { fc::raw::pack(ds, make_history_serial_wrapper(db, row, history_serial_wrapper_enum_t::resource_limits)); }; + process_table(ds, "resource_limits", db.get_index(), pack_resource_limit_row); + auto pack_resource_usage_row = [&](auto& ds, auto& row) { fc::raw::pack(ds, make_history_serial_wrapper(db, row, history_serial_wrapper_enum_t::resource_usage)); }; + process_table(ds, "resource_usage", db.get_index(), pack_resource_usage_row); process_table(ds, "resource_limits_state", db.get_index(), pack_row); process_table(ds, "resource_limits_config", db.get_index(), diff --git a/libraries/state_history/include/sysio/state_history/serialization.hpp b/libraries/state_history/include/sysio/state_history/serialization.hpp index 5b8ef6e43b..440e3ee061 100644 --- a/libraries/state_history/include/sysio/state_history/serialization.hpp +++ b/libraries/state_history/include/sysio/state_history/serialization.hpp @@ -15,6 +15,12 @@ #include +enum class history_serial_wrapper_enum_t { + none, + resource_limits, + resource_usage +}; + template struct history_serial_wrapper_stateless { const T& obj; @@ -22,6 +28,7 @@ struct history_serial_wrapper_stateless { template struct history_serial_wrapper : public history_serial_wrapper_stateless { + history_serial_wrapper_enum_t type = history_serial_wrapper_enum_t::none; const chainbase::database& db; }; @@ -31,8 +38,9 @@ history_serial_wrapper_stateless> make_history_serial_wrapper(co } template -history_serial_wrapper> make_history_serial_wrapper(const chainbase::database& db, const T& obj) { - return {{obj}, db}; +history_serial_wrapper> make_history_serial_wrapper(const chainbase::database& db, const T& obj, + history_serial_wrapper_enum_t type = history_serial_wrapper_enum_t::none) { + return {{obj}, type, db}; } template @@ -473,14 +481,22 @@ datastream& operator<<(datastream& ds, const history_serial_wrapper_stat } template -datastream& operator<<(datastream& ds, const history_serial_wrapper_stateless& obj) { - SYS_ASSERT(!obj.obj.pending, sysio::chain::plugin_exception, - "accepted_block sent while resource_limits_object in pending state"); - fc::raw::pack(ds, fc::unsigned_int(0)); - fc::raw::pack(ds, as_type(obj.obj.owner.to_uint64_t())); - fc::raw::pack(ds, as_type(obj.obj.net_weight)); - fc::raw::pack(ds, as_type(obj.obj.cpu_weight)); - fc::raw::pack(ds, as_type(obj.obj.ram_bytes)); +datastream& operator<<(datastream& ds, const history_serial_wrapper& obj) { + if (obj.type == history_serial_wrapper_enum_t::resource_limits) { + fc::raw::pack(ds, fc::unsigned_int(0)); + fc::raw::pack(ds, as_type(obj.obj.owner.to_uint64_t())); + fc::raw::pack(ds, as_type(obj.obj.net_weight)); + fc::raw::pack(ds, as_type(obj.obj.cpu_weight)); + fc::raw::pack(ds, as_type(obj.obj.ram_bytes)); + } else if (obj.type == history_serial_wrapper_enum_t::resource_usage) { + fc::raw::pack(ds, fc::unsigned_int(0)); + fc::raw::pack(ds, as_type(obj.obj.owner.to_uint64_t())); + fc::raw::pack(ds, make_history_serial_wrapper(as_type(obj.obj.net_usage))); + fc::raw::pack(ds, make_history_serial_wrapper(as_type(obj.obj.cpu_usage))); + fc::raw::pack(ds, as_type(obj.obj.ram_usage)); + } else { + SYS_ASSERT(false, sysio::chain::plugin_exception, "Unexpected type in history_serial_wrapper"); + } return ds; } @@ -493,16 +509,6 @@ datastream& operator<<(datastream& ds, const history_serial_wrapper_stat return ds; } -template -datastream& operator<<(datastream& ds, const history_serial_wrapper& obj) { - fc::raw::pack(ds, fc::unsigned_int(0)); - fc::raw::pack(ds, as_type(obj.obj.owner.to_uint64_t())); - fc::raw::pack(ds, make_history_serial_wrapper(as_type(obj.obj.net_usage))); - fc::raw::pack(ds, make_history_serial_wrapper(as_type(obj.obj.cpu_usage))); - fc::raw::pack(ds, as_type(obj.obj.ram_usage)); - return ds; -} - template datastream& operator<<(datastream& ds, const history_serial_wrapper& obj) { fc::raw::pack(ds, fc::unsigned_int(0)); diff --git a/unittests/auth_tests.cpp b/unittests/auth_tests.cpp index cfef64443f..ece4690eb0 100644 --- a/unittests/auth_tests.cpp +++ b/unittests/auth_tests.cpp @@ -440,7 +440,7 @@ try { const chainbase::database &db = chain.control->db(); - using resource_usage_object = sysio::chain::resource_limits::resource_usage_object; + using resource_object = sysio::chain::resource_limits::resource_object; using by_owner = sysio::chain::resource_limits::by_owner; auto create_acc = [&](account_name a) { @@ -472,9 +472,9 @@ try { create_acc(acc2); - const auto &usage = db.get(acc1); + const auto &usage = db.get(acc1); - const auto &usage2 = db.get(acc1a); + const auto &usage2 = db.get(acc1a); BOOST_TEST(usage.cpu_usage.average() > 0U); BOOST_TEST(usage.net_usage.average() > 0U); diff --git a/unittests/snapshots/snap_v6.bin.gz b/unittests/snapshots/snap_v6.bin.gz index 8fac3be1395c6c8900c9b6d755aa78a939eda8d7..fe7d31a8b9abd8573f6ba864109de7395b252bd8 100644 GIT binary patch literal 9484 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 literal 9490 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 fu8B$}H0fvjfcpY-nhEHp;m{ICBHzjI>X delta 6426 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 z zU{*&YGR?hBS(q6wJG<7%y*kTcQKJlEutsmK!8~^V7PggQMc7z@>Cn*%Q3gUEl`-@D z(&Yix`r_z6z2LlE!d{{I+x7OxgNTcVSVrTjCPfCC^UON$^Y~#fyI z(ZJNIW+O_aNy$3bS16uox-`Bu@C0zf)E;Ir1-LOLAAPk?41akDZW zpg!*EN`BTr7M9b5^`$Q63kA{mO|@LCvd76@qlOWS+J-#{#elY^EE~Xry$!Dq+I5J8 zkuCvLgX}}f$#NnFWqdm~dj)Bp=mFl%^^7lRPLb*30o0c|iR?=H$?{J1Ijr5$wLI9e z@r6C7-PCEY7)$OZ!kPZ9cCB)lfxe-(ge&K0df{sFUGMq20GMH3r^l|BwT@RL3d2BTIeFn+{C z+(mN}w`MFGKIP#_6LUK8lxCv?i*z+}%j$VlqKICHkvrV`bC*r+a@^CY+igO=FHJy78-vY3Z&) zh*p(SEl_aGsScIMR8LB*>rYq{&iY-`V{lx)CWNjgn##ssY`O6Fz`FmB3G zUeljE>|ZmKc8T4oWA1x(Vb7|8Cw^huQLOe}F!o?T>B5+2nN}(l&G9!kvd(Hht_$W? zSN+$!fE>up30x_hvf!qWR2?Ch>^nY$#jlUrE%#a~NlL{rfCkh%;VS#EJ$1D^mQI6= zHUAa{HZVtC2K*DXn@5@X=Lqv4%=$J8qn#TOHaaFUsaSN zuyd+a*u7O8Emf6gN?b&rtaC1Ht1K8&$uh8R{ktx_jY#gYA{AdclhDqxG$%6au)B`M zcZP<(tprx(i>J;0ES8Mw6iDRuzRBBj^9eq<&@d}UCQtU_{_UC;iJe+*UO$ty{U=L_ zJGwa`|!b`5&34 zL!+>@Kd-M)v;V<>TwVE%neXT0w5TR_XU5mr3PXuVSF47PRU&gXuL+s7oEn!u0zC0i z&4~wwj0Q>6;iH&ik;;|m`nfM`zTAV{6wCSnCi?MS)muHg$kMvi={3(`;3&oOHx_)Ie c@S!fxk!g9FX_A@#W%%{C7m;^A4f@yr0~@bZ5dZ)H diff --git a/unittests/snapshots/snap_v6.json.gz b/unittests/snapshots/snap_v6.json.gz index 024ddae1ab96fd7e9c6d9f5479c5a4ab446abefa..ac8461e3859ec1ed9854851e4fa5280b1b712406 100644 GIT binary patch delta 6385 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 kI$HtfoKlf#4AOHXW delta 6415 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 S;KohhAJPW%%t(yiKmI>NuSksm diff --git a/unittests/state_history_tests.cpp b/unittests/state_history_tests.cpp index 2c9d2b1d7c..5a0a00ed76 100644 --- a/unittests/state_history_tests.cpp +++ b/unittests/state_history_tests.cpp @@ -85,7 +85,7 @@ class table_deltas_tester : public tester { } template - vector deserialize_data(deltas_vector::iterator &it) { + static vector deserialize_data(deltas_vector::iterator &it) { vector result; for(size_t i=0; i < it->rows.obj.size(); i++) { sysio::input_stream stream{it->rows.obj[i].second.data(), it->rows.obj[i].second.size()}; @@ -410,7 +410,10 @@ BOOST_AUTO_TEST_CASE(test_deltas_contract) { name="resource_limits"; it = std::find_if(v.begin(), v.end(), find_by_name); - BOOST_REQUIRE(it==v.end()); + BOOST_REQUIRE(it!=v.end()); // updated by onblock in start_block + BOOST_REQUIRE_EQUAL(it->rows.obj.size(), 1u); + auto resources = table_deltas_tester::deserialize_data(it); + BOOST_REQUIRE_EQUAL(resources[0].owner.to_string(), config::system_account_name.to_string()); main.create_account("newacc"_n, config::system_account_name, false, false, false, false); @@ -423,6 +426,10 @@ BOOST_AUTO_TEST_CASE(test_deltas_contract) { name="resource_limits"; it = std::find_if(v.begin(), v.end(), find_by_name); BOOST_REQUIRE(it!=v.end()); + BOOST_REQUIRE_EQUAL(it->rows.obj.size(), 2u); + resources = table_deltas_tester::deserialize_data(it); + BOOST_REQUIRE_EQUAL(resources[0].owner.to_string(), config::system_account_name.to_string()); + BOOST_REQUIRE_EQUAL(resources[1].owner.to_string(), "newacc"); main.produce_block(); @@ -434,7 +441,7 @@ BOOST_AUTO_TEST_CASE(test_deltas_contract) { name="resource_limits"; it = std::find_if(v.begin(), v.end(), find_by_name); - BOOST_REQUIRE(it==v.end()); + BOOST_REQUIRE(it!=v.end()); // updated by onblock in start_block } BOOST_AUTO_TEST_CASE(test_deltas_contract_several_rows){