From 9d3bcbb56928c215868ff89a5d56850451ca6d5e Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Mon, 28 Sep 2015 12:10:20 -0400 Subject: [PATCH] Provide objects to trace budget computations --- libraries/app/api.cpp | 1 + libraries/chain/db_init.cpp | 2 + libraries/chain/db_maint.cpp | 46 ++++++++-- .../graphene/chain/budget_record_object.hpp | 84 +++++++++++++++++++ .../chain/include/graphene/chain/database.hpp | 4 +- .../include/graphene/chain/protocol/types.hpp | 7 +- 6 files changed, 133 insertions(+), 11 deletions(-) create mode 100644 libraries/chain/include/graphene/chain/budget_record_object.hpp diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 8e5b92df..4ec4f5b8 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -293,6 +293,7 @@ namespace graphene { namespace app { } case impl_account_transaction_history_object_type:{ } case impl_chain_property_object_type: { } case impl_witness_schedule_object_type: { + } case impl_budget_record_object_type: { } } } diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index eb01d668..ffbca39e 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -194,6 +195,7 @@ void database::initialize_indexes() add_index< primary_index> >(); add_index< primary_index > >(); add_index< primary_index > >(); + add_index< primary_index > >(); } void database::init_genesis(const genesis_state_type& genesis_state) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index b6a4ae98..bd7074ca 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -271,17 +271,25 @@ void database::update_active_committee_members() }); } FC_CAPTURE_AND_RETHROW() } -share_type database::get_max_budget( fc::time_point_sec now )const +void database::initialize_budget_record( fc::time_point_sec now, budget_record& rec )const { const dynamic_global_property_object& dpo = get_dynamic_global_properties(); const asset_object& core = asset_id_type(0)(*this); const asset_dynamic_data_object& core_dd = core.dynamic_asset_data_id(*this); + rec.from_initial_reserve = core.reserved(*this); + rec.from_accumulated_fees = core_dd.accumulated_fees; + rec.from_unused_witness_budget = dpo.witness_budget; + if( (dpo.last_budget_time == fc::time_point_sec()) || (now <= dpo.last_budget_time) ) - return share_type(0); + { + rec.time_since_last_budget = 0; + return; + } int64_t dt = (now - dpo.last_budget_time).to_seconds(); + rec.time_since_last_budget = uint64_t( dt ); // We'll consider accumulated_fees to be reserved at the BEGINNING // of the maintenance interval. However, for speed we only @@ -289,7 +297,7 @@ share_type database::get_max_budget( fc::time_point_sec now )const // end of the maintenance interval. Thus the accumulated_fees // are available for the budget at this point, but not included // in core.reserved(). - share_type reserve = core.reserved(*this) + core_dd.accumulated_fees; + share_type reserve = rec.from_initial_reserve + core_dd.accumulated_fees; // Similarly, we consider leftover witness_budget to be burned // at the BEGINNING of the maintenance interval. reserve += dpo.witness_budget; @@ -304,11 +312,11 @@ share_type database::get_max_budget( fc::time_point_sec now )const budget_u128 >>= GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS; share_type budget; if( budget_u128 < reserve.value ) - budget = share_type(budget_u128.to_uint64()); + rec.total_budget = share_type(budget_u128.to_uint64()); else - budget = reserve; + rec.total_budget = reserve; - return budget; + return; } /** @@ -342,10 +350,14 @@ void database::process_budget() // blocks_to_maint > 0 because time_to_maint > 0, // which means numerator is at least equal to block_interval - share_type available_funds = get_max_budget(now); + budget_record rec; + initialize_budget_record( now, rec ); + share_type available_funds = rec.total_budget; share_type witness_budget = gpo.parameters.witness_pay_per_block.value * blocks_to_maint; + rec.requested_witness_budget = witness_budget; witness_budget = std::min(witness_budget, available_funds); + rec.witness_budget = witness_budget; available_funds -= witness_budget; fc::uint128_t worker_budget_u128 = gpo.parameters.worker_budget_per_day.value; @@ -357,17 +369,27 @@ void database::process_budget() worker_budget = available_funds; else worker_budget = worker_budget_u128.to_uint64(); + rec.worker_budget = worker_budget; available_funds -= worker_budget; share_type leftover_worker_funds = worker_budget; pay_workers(leftover_worker_funds); + rec.leftover_worker_funds = leftover_worker_funds; available_funds += leftover_worker_funds; + rec.supply_delta = rec.witness_budget + + rec.worker_budget + - rec.leftover_worker_funds + - rec.from_accumulated_fees + - rec.from_unused_witness_budget; + share_type unused_prev_witness_budget = dpo.witness_budget; modify(core, [&]( asset_dynamic_data_object& _core ) { - _core.current_supply = (_core.current_supply - + witness_budget + _core.current_supply = (_core.current_supply + rec.supply_delta ); + + assert( rec.supply_delta == + witness_budget + worker_budget - leftover_worker_funds - _core.accumulated_fees @@ -384,6 +406,12 @@ void database::process_budget() _dpo.last_budget_time = now; }); + create< budget_record_object >( [&]( budget_record_object& _rec ) + { + _rec.time = head_block_time(); + _rec.record = rec; + }); + // available_funds is money we could spend, but don't want to. // we simply let it evaporate back into the reserve. } diff --git a/libraries/chain/include/graphene/chain/budget_record_object.hpp b/libraries/chain/include/graphene/chain/budget_record_object.hpp new file mode 100644 index 00000000..679889f7 --- /dev/null +++ b/libraries/chain/include/graphene/chain/budget_record_object.hpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015, Cryptonomex, Inc. + * All rights reserved. + * + * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and + * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, + * are permitted until September 8, 2015, provided that the following conditions are met: + * + * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#pragma once +#include +#include +#include + +namespace graphene { namespace chain { + +struct budget_record +{ + uint64_t time_since_last_budget = 0; + + // sources of budget + share_type from_initial_reserve = 0; + share_type from_accumulated_fees = 0; + share_type from_unused_witness_budget = 0; + + // witness budget requested by the committee + share_type requested_witness_budget = 0; + + // funds that can be released from reserve at maximum rate + share_type total_budget = 0; + + // sinks of budget, should sum up to total_budget + share_type witness_budget = 0; + share_type worker_budget = 0; + + // unused budget + share_type leftover_worker_funds = 0; + + // change in supply due to budget operations + share_type supply_delta = 0; +}; + +class budget_record_object; + +class budget_record_object : public graphene::db::abstract_object +{ + public: + static const uint8_t space_id = implementation_ids; + static const uint8_t type_id = impl_budget_record_object_type; + + fc::time_point_sec time; + budget_record record; +}; + +} } + +FC_REFLECT( + graphene::chain::budget_record, + (time_since_last_budget) + (from_initial_reserve) + (from_accumulated_fees) + (from_unused_witness_budget) + (requested_witness_budget) + (total_budget) + (witness_budget) + (worker_budget) + (leftover_worker_funds) + (supply_delta) +) + +FC_REFLECT_DERIVED( + graphene::chain::budget_record_object, + (graphene::db::object), + (time) + (record) +) diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 9829d0ab..e5a436ef 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -40,6 +40,8 @@ namespace graphene { namespace chain { using graphene::db::abstract_object; using graphene::db::object; + struct budget_record; + /** * @class database * @brief tracks the blockchain state in an extensible manner @@ -432,7 +434,7 @@ namespace graphene { namespace chain { //////////////////// db_maint.cpp //////////////////// - share_type get_max_budget( fc::time_point_sec now )const; + void initialize_budget_record( fc::time_point_sec now, budget_record& rec )const; void process_budget(); void pay_workers( share_type& budget ); void perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props); diff --git a/libraries/chain/include/graphene/chain/protocol/types.hpp b/libraries/chain/include/graphene/chain/protocol/types.hpp index 8cd52866..e06f7600 100644 --- a/libraries/chain/include/graphene/chain/protocol/types.hpp +++ b/libraries/chain/include/graphene/chain/protocol/types.hpp @@ -142,7 +142,8 @@ namespace graphene { namespace chain { impl_account_transaction_history_object_type, impl_blinded_balance_object_type, impl_chain_property_object_type, - impl_witness_schedule_object_type + impl_witness_schedule_object_type, + impl_budget_record_object_type }; //typedef fc::unsigned_int object_id_type; @@ -189,6 +190,7 @@ namespace graphene { namespace chain { class account_transaction_history_object; class chain_property_object; class witness_schedule_object; + class budget_record_object; typedef object_id< implementation_ids, impl_global_property_object_type, global_property_object> global_property_id_type; typedef object_id< implementation_ids, impl_dynamic_global_property_object_type, dynamic_global_property_object> dynamic_global_property_id_type; @@ -204,6 +206,7 @@ namespace graphene { namespace chain { account_transaction_history_object> account_transaction_history_id_type; typedef object_id< implementation_ids, impl_chain_property_object_type, chain_property_object> chain_property_id_type; typedef object_id< implementation_ids, impl_witness_schedule_object_type, witness_schedule_object> witness_schedule_id_type; + typedef object_id< implementation_ids, impl_budget_record_object_type, budget_record_object > budget_record_id_type; typedef fc::array symbol_type; typedef fc::ripemd160 block_id_type; @@ -281,6 +284,7 @@ FC_REFLECT_ENUM( graphene::chain::impl_object_type, (impl_blinded_balance_object_type) (impl_chain_property_object_type) (impl_witness_schedule_object_type) + (impl_budget_record_object_type) ) FC_REFLECT_TYPENAME( graphene::chain::share_type ) @@ -307,6 +311,7 @@ FC_REFLECT_TYPENAME( graphene::chain::account_statistics_id_type ) FC_REFLECT_TYPENAME( graphene::chain::transaction_obj_id_type ) FC_REFLECT_TYPENAME( graphene::chain::block_summary_id_type ) FC_REFLECT_TYPENAME( graphene::chain::account_transaction_history_id_type ) +FC_REFLECT_TYPENAME( graphene::chain::budget_record_id_type ) FC_REFLECT( graphene::chain::void_t, ) FC_REFLECT_ENUM( graphene::chain::asset_issuer_permission_flags, (charge_market_fee)(white_list)(transfer_restricted)(override_authority)(disable_force_settle)(global_settle)(disable_confidential) )