Improve account maintenance performance (#130)
* Improve account maintenance performance * merge fixes * Fixed merge issue * Fixed indentations and extra ';'
This commit is contained in:
parent
50b80e9155
commit
0bcfaa385b
13 changed files with 228 additions and 103 deletions
|
|
@ -162,33 +162,39 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio
|
|||
if( referrer_percent > GRAPHENE_100_PERCENT )
|
||||
referrer_percent = GRAPHENE_100_PERCENT;
|
||||
}
|
||||
const auto& global_properties = d.get_global_properties();
|
||||
|
||||
const auto& new_acnt_object = db().create<account_object>( [&]( account_object& obj ){
|
||||
obj.registrar = o.registrar;
|
||||
obj.referrer = o.referrer;
|
||||
obj.lifetime_referrer = o.referrer(db()).lifetime_referrer;
|
||||
const auto& new_acnt_object = d.create<account_object>( [&o,&d,&global_properties,referrer_percent]( account_object& obj )
|
||||
{
|
||||
obj.registrar = o.registrar;
|
||||
obj.referrer = o.referrer;
|
||||
obj.lifetime_referrer = o.referrer(d).lifetime_referrer;
|
||||
|
||||
auto& params = db().get_global_properties().parameters;
|
||||
obj.network_fee_percentage = params.network_percent_of_fee;
|
||||
obj.lifetime_referrer_fee_percentage = params.lifetime_referrer_percent_of_fee;
|
||||
obj.referrer_rewards_percentage = referrer_percent;
|
||||
const auto& params = global_properties.parameters;
|
||||
obj.network_fee_percentage = params.network_percent_of_fee;
|
||||
obj.lifetime_referrer_fee_percentage = params.lifetime_referrer_percent_of_fee;
|
||||
obj.referrer_rewards_percentage = referrer_percent;
|
||||
|
||||
obj.name = o.name;
|
||||
obj.owner = o.owner;
|
||||
obj.active = o.active;
|
||||
obj.options = o.options;
|
||||
obj.statistics = db().create<account_statistics_object>([&](account_statistics_object& s){s.owner = obj.id;}).id;
|
||||
obj.name = o.name;
|
||||
obj.owner = o.owner;
|
||||
obj.active = o.active;
|
||||
obj.options = o.options;
|
||||
obj.statistics = d.create<account_statistics_object>([&obj](account_statistics_object& s){
|
||||
s.owner = obj.id;
|
||||
s.name = obj.name;
|
||||
s.is_voting = obj.options.is_voting();
|
||||
}).id;
|
||||
|
||||
if( o.extensions.value.owner_special_authority.valid() )
|
||||
obj.owner_special_authority = *(o.extensions.value.owner_special_authority);
|
||||
if( o.extensions.value.active_special_authority.valid() )
|
||||
obj.active_special_authority = *(o.extensions.value.active_special_authority);
|
||||
if( o.extensions.value.buyback_options.valid() )
|
||||
{
|
||||
obj.allowed_assets = o.extensions.value.buyback_options->markets;
|
||||
obj.allowed_assets->emplace( o.extensions.value.buyback_options->asset_to_buy );
|
||||
}
|
||||
obj.affiliate_distributions = o.extensions.value.affiliate_distributions;
|
||||
if( o.extensions.value.owner_special_authority.valid() )
|
||||
obj.owner_special_authority = *(o.extensions.value.owner_special_authority);
|
||||
if( o.extensions.value.active_special_authority.valid() )
|
||||
obj.active_special_authority = *(o.extensions.value.active_special_authority);
|
||||
if( o.extensions.value.buyback_options.valid() )
|
||||
{
|
||||
obj.allowed_assets = o.extensions.value.buyback_options->markets;
|
||||
obj.allowed_assets->emplace( o.extensions.value.buyback_options->asset_to_buy );
|
||||
}
|
||||
obj.affiliate_distributions = o.extensions.value.affiliate_distributions;
|
||||
});
|
||||
|
||||
if( has_small_percent )
|
||||
|
|
@ -200,17 +206,18 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio
|
|||
wlog( "Affected account object is ${o}", ("o", new_acnt_object) );
|
||||
}
|
||||
|
||||
const auto& dynamic_properties = db().get_dynamic_global_properties();
|
||||
db().modify(dynamic_properties, [](dynamic_global_property_object& p) {
|
||||
const auto& dynamic_properties = d.get_dynamic_global_properties();
|
||||
d.modify(dynamic_properties, [](dynamic_global_property_object& p) {
|
||||
++p.accounts_registered_this_interval;
|
||||
});
|
||||
|
||||
const auto& global_properties = db().get_global_properties();
|
||||
if( dynamic_properties.accounts_registered_this_interval %
|
||||
global_properties.parameters.accounts_per_fee_scale == 0 )
|
||||
db().modify(global_properties, [&dynamic_properties](global_property_object& p) {
|
||||
if( dynamic_properties.accounts_registered_this_interval % global_properties.parameters.accounts_per_fee_scale == 0
|
||||
&& global_properties.parameters.account_fee_scale_bitshifts != 0 )
|
||||
{
|
||||
d.modify(global_properties, [&dynamic_properties](global_property_object& p) {
|
||||
p.parameters.current_fees->get<account_create_operation>().basic_fee <<= p.parameters.account_fee_scale_bitshifts;
|
||||
});
|
||||
}
|
||||
|
||||
if( o.extensions.value.owner_special_authority.valid()
|
||||
|| o.extensions.value.active_special_authority.valid() )
|
||||
|
|
@ -280,18 +287,24 @@ void_result account_update_evaluator::do_apply( const account_update_operation&
|
|||
{ try {
|
||||
database& d = db();
|
||||
|
||||
bool sa_before = acnt->has_special_authority();
|
||||
|
||||
// update account statistics
|
||||
if( o.new_options.valid() )
|
||||
{
|
||||
d.modify( acnt->statistics( d ), [&]( account_statistics_object& aso )
|
||||
{
|
||||
if(o.new_options->is_voting() != acnt->options.is_voting())
|
||||
aso.is_voting = !aso.is_voting;
|
||||
|
||||
if((o.new_options->votes != acnt->options.votes ||
|
||||
o.new_options->voting_account != acnt->options.voting_account))
|
||||
o.new_options->voting_account != acnt->options.voting_account))
|
||||
aso.last_vote_time = d.head_block_time();
|
||||
} );
|
||||
}
|
||||
|
||||
bool sa_before, sa_after;
|
||||
d.modify( *acnt, [&](account_object& a){
|
||||
// update account object
|
||||
d.modify( *acnt, [&o](account_object& a){
|
||||
if( o.owner )
|
||||
{
|
||||
a.owner = *o.owner;
|
||||
|
|
@ -303,7 +316,6 @@ void_result account_update_evaluator::do_apply( const account_update_operation&
|
|||
a.top_n_control_flags = 0;
|
||||
}
|
||||
if( o.new_options ) a.options = *o.new_options;
|
||||
sa_before = a.has_special_authority();
|
||||
if( o.extensions.value.owner_special_authority.valid() )
|
||||
{
|
||||
a.owner_special_authority = *(o.extensions.value.owner_special_authority);
|
||||
|
|
@ -314,9 +326,10 @@ void_result account_update_evaluator::do_apply( const account_update_operation&
|
|||
a.active_special_authority = *(o.extensions.value.active_special_authority);
|
||||
a.top_n_control_flags = 0;
|
||||
}
|
||||
sa_after = a.has_special_authority();
|
||||
});
|
||||
|
||||
bool sa_after = acnt->has_special_authority();
|
||||
|
||||
if( sa_before & (!sa_after) )
|
||||
{
|
||||
const auto& sa_idx = d.get_index_type< special_authority_index >().indices().get<by_account>();
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ void account_balance_object::adjust_balance(const asset& delta)
|
|||
{
|
||||
assert(delta.asset_id == asset_type);
|
||||
balance += delta.amount;
|
||||
if( asset_type == asset_id_type() ) // CORE asset
|
||||
maintenance_flag = true;
|
||||
}
|
||||
|
||||
void account_statistics_object::process_fees(const account_object& a, database& d) const
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@ void database::adjust_balance(account_id_type account, asset delta )
|
|||
b.owner = account;
|
||||
b.asset_type = delta.asset_id;
|
||||
b.balance = delta.amount.value;
|
||||
if( b.asset_type == asset_id_type() ) // CORE asset
|
||||
b.maintenance_flag = true;
|
||||
});
|
||||
} else {
|
||||
if( delta.amount < 0 )
|
||||
|
|
@ -223,10 +225,15 @@ void database::deposit_cashback(const account_object& acct, share_type amount, b
|
|||
|
||||
if( new_vbid.valid() )
|
||||
{
|
||||
modify( acct, [&]( account_object& _acct )
|
||||
modify( acct, [&new_vbid]( account_object& _acct )
|
||||
{
|
||||
_acct.cashback_vb = *new_vbid;
|
||||
} );
|
||||
|
||||
modify( acct.statistics( *this ), []( account_statistics_object& aso )
|
||||
{
|
||||
aso.has_cashback_vb = true;
|
||||
} );
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ void database::debug_dump()
|
|||
const asset_dynamic_data_object& core_asset_data = db.get_core_asset().dynamic_asset_data_id(db);
|
||||
|
||||
const auto& balance_index = db.get_index_type<account_balance_index>().indices();
|
||||
const simple_index<account_statistics_object>& statistics_index = db.get_index_type<simple_index<account_statistics_object>>();
|
||||
const auto& statistics_index = db.get_index_type<account_stats_index>().indices();
|
||||
map<asset_id_type,share_type> total_balances;
|
||||
map<asset_id_type,share_type> total_debts;
|
||||
share_type core_in_orders;
|
||||
|
|
|
|||
|
|
@ -141,4 +141,13 @@ const std::vector<uint32_t> database::get_winner_numbers( asset_id_type for_asse
|
|||
return result;
|
||||
}
|
||||
|
||||
const account_statistics_object& database::get_account_stats_by_owner( account_id_type owner )const
|
||||
{
|
||||
auto& idx = get_index_type<account_stats_index>().indices().get<by_owner>();
|
||||
auto itr = idx.find( owner );
|
||||
FC_ASSERT( itr != idx.end(), "Can not find account statistics object for owner ${a}", ("a",owner) );
|
||||
return *itr;
|
||||
}
|
||||
|
||||
|
||||
} }
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ void database::initialize_indexes()
|
|||
add_index< primary_index<asset_dividend_data_object_index > >();
|
||||
add_index< primary_index<simple_index<global_property_object >> >();
|
||||
add_index< primary_index<simple_index<dynamic_global_property_object >> >();
|
||||
add_index< primary_index<simple_index<account_statistics_object >> >();
|
||||
add_index< primary_index<account_stats_index > >();
|
||||
add_index< primary_index<simple_index<asset_dynamic_data_object >> >();
|
||||
add_index< primary_index<flat_index< block_summary_object >> >();
|
||||
add_index< primary_index<simple_index<chain_property_object > > >();
|
||||
|
|
@ -355,12 +355,19 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
n.owner.weight_threshold = 1;
|
||||
n.active.weight_threshold = 1;
|
||||
n.name = "committee-account";
|
||||
n.statistics = create<account_statistics_object>( [&](account_statistics_object& s){ s.owner = n.id; }).id;
|
||||
n.statistics = create<account_statistics_object>( [&n](account_statistics_object& s){
|
||||
s.owner = n.id;
|
||||
s.name = n.name;
|
||||
s.core_in_balance = GRAPHENE_MAX_SHARE_SUPPLY;
|
||||
}).id;
|
||||
});
|
||||
FC_ASSERT(committee_account.get_id() == GRAPHENE_COMMITTEE_ACCOUNT);
|
||||
FC_ASSERT(create<account_object>([this](account_object& a) {
|
||||
a.name = "witness-account";
|
||||
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
|
||||
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
|
||||
s.owner = a.id;
|
||||
s.name = a.name;
|
||||
}).id;
|
||||
a.owner.weight_threshold = 1;
|
||||
a.active.weight_threshold = 1;
|
||||
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_WITNESS_ACCOUNT;
|
||||
|
|
@ -370,7 +377,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
}).get_id() == GRAPHENE_WITNESS_ACCOUNT);
|
||||
FC_ASSERT(create<account_object>([this](account_object& a) {
|
||||
a.name = "relaxed-committee-account";
|
||||
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
|
||||
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
|
||||
s.owner = a.id;
|
||||
s.name = a.name;
|
||||
}).id;
|
||||
a.owner.weight_threshold = 1;
|
||||
a.active.weight_threshold = 1;
|
||||
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_RELAXED_COMMITTEE_ACCOUNT;
|
||||
|
|
@ -380,7 +390,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
}).get_id() == GRAPHENE_RELAXED_COMMITTEE_ACCOUNT);
|
||||
FC_ASSERT(create<account_object>([this](account_object& a) {
|
||||
a.name = "null-account";
|
||||
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
|
||||
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
|
||||
s.owner = a.id;
|
||||
s.name = a.name;
|
||||
}).id;
|
||||
a.owner.weight_threshold = 1;
|
||||
a.active.weight_threshold = 1;
|
||||
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_NULL_ACCOUNT;
|
||||
|
|
@ -390,7 +403,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
}).get_id() == GRAPHENE_NULL_ACCOUNT);
|
||||
FC_ASSERT(create<account_object>([this](account_object& a) {
|
||||
a.name = "temp-account";
|
||||
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
|
||||
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
|
||||
s.owner = a.id;
|
||||
s.name = a.name;
|
||||
}).id;
|
||||
a.owner.weight_threshold = 0;
|
||||
a.active.weight_threshold = 0;
|
||||
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_TEMP_ACCOUNT;
|
||||
|
|
@ -400,7 +416,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
}).get_id() == GRAPHENE_TEMP_ACCOUNT);
|
||||
FC_ASSERT(create<account_object>([this](account_object& a) {
|
||||
a.name = "proxy-to-self";
|
||||
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
|
||||
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
|
||||
s.owner = a.id;
|
||||
s.name = a.name;
|
||||
}).id;
|
||||
a.owner.weight_threshold = 1;
|
||||
a.active.weight_threshold = 1;
|
||||
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_NULL_ACCOUNT;
|
||||
|
|
@ -410,7 +429,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
}).get_id() == GRAPHENE_PROXY_TO_SELF_ACCOUNT);
|
||||
FC_ASSERT(create<account_object>([this](account_object& a) {
|
||||
a.name = "default-dividend-distribution";
|
||||
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
|
||||
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
|
||||
s.owner = a.id;
|
||||
s.name = a.name;
|
||||
}).id;
|
||||
a.owner.weight_threshold = 1;
|
||||
a.active.weight_threshold = 1;
|
||||
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_PROXY_TO_SELF_ACCOUNT;
|
||||
|
|
@ -424,9 +446,12 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
uint64_t id = get_index<account_object>().get_next_id().instance();
|
||||
if( id >= genesis_state.immutable_parameters.num_special_accounts )
|
||||
break;
|
||||
const account_object& acct = create<account_object>([&](account_object& a) {
|
||||
const account_object& acct = create<account_object>([this,id](account_object& a) {
|
||||
a.name = "special-account-" + std::to_string(id);
|
||||
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
|
||||
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
|
||||
s.owner = a.id;
|
||||
s.name = a.name;
|
||||
}).id;
|
||||
a.owner.weight_threshold = 1;
|
||||
a.active.weight_threshold = 1;
|
||||
a.registrar = a.lifetime_referrer = a.referrer = account_id_type(id);
|
||||
|
|
@ -440,12 +465,12 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
|
||||
// Create core asset
|
||||
const asset_dynamic_data_object& dyn_asset =
|
||||
create<asset_dynamic_data_object>([&](asset_dynamic_data_object& a) {
|
||||
create<asset_dynamic_data_object>([](asset_dynamic_data_object& a) {
|
||||
a.current_supply = GRAPHENE_MAX_SHARE_SUPPLY;
|
||||
});
|
||||
|
||||
const asset_dividend_data_object& div_asset =
|
||||
create<asset_dividend_data_object>([&](asset_dividend_data_object& a) {
|
||||
create<asset_dividend_data_object>([&genesis_state](asset_dividend_data_object& a) {
|
||||
a.options.minimum_distribution_interval = 3*24*60*60;
|
||||
a.options.minimum_fee_percentage = 10*GRAPHENE_1_PERCENT;
|
||||
a.options.next_payout_time = genesis_state.initial_timestamp + fc::days(1);
|
||||
|
|
@ -454,7 +479,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
});
|
||||
|
||||
const asset_object& core_asset =
|
||||
create<asset_object>( [&]( asset_object& a ) {
|
||||
create<asset_object>( [&genesis_state,&div_asset,&dyn_asset]( asset_object& a ) {
|
||||
a.symbol = GRAPHENE_SYMBOL;
|
||||
a.options.max_supply = genesis_state.max_core_supply;
|
||||
a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS;
|
||||
|
|
@ -512,10 +537,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
if( id >= genesis_state.immutable_parameters.num_special_assets )
|
||||
break;
|
||||
const asset_dynamic_data_object& dyn_asset =
|
||||
create<asset_dynamic_data_object>([&](asset_dynamic_data_object& a) {
|
||||
create<asset_dynamic_data_object>([](asset_dynamic_data_object& a) {
|
||||
a.current_supply = 0;
|
||||
});
|
||||
const asset_object& asset_obj = create<asset_object>( [&]( asset_object& a ) {
|
||||
const asset_object& asset_obj = create<asset_object>( [id,&dyn_asset]( asset_object& a ) {
|
||||
a.symbol = "SPECIAL" + std::to_string( id );
|
||||
a.options.max_supply = 0;
|
||||
a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS;
|
||||
|
|
@ -679,7 +704,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
cop.active = cop.owner;
|
||||
account_id_type owner_account_id = apply_operation(genesis_eval_state, cop).get<object_id_type>();
|
||||
|
||||
modify( owner_account_id(*this).statistics(*this), [&]( account_statistics_object& o ) {
|
||||
modify( owner_account_id(*this).statistics(*this), [&collateral_rec]( account_statistics_object& o ) {
|
||||
o.total_core_in_orders = collateral_rec.collateral;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -76,12 +76,44 @@ vector<std::reference_wrapper<const typename Index::object_type>> database::sort
|
|||
return refs;
|
||||
}
|
||||
|
||||
template<class... Types>
|
||||
void database::perform_account_maintenance(std::tuple<Types...> helpers)
|
||||
template<class Type>
|
||||
void database::perform_account_maintenance(Type tally_helper)
|
||||
{
|
||||
const auto& idx = get_index_type<account_index>().indices().get<by_name>();
|
||||
for( const account_object& a : idx )
|
||||
detail::for_each(helpers, a, detail::gen_seq<sizeof...(Types)>());
|
||||
const auto& bal_idx = get_index_type< account_balance_index >().indices().get< by_maintenance_flag >();
|
||||
if( bal_idx.begin() != bal_idx.end() )
|
||||
{
|
||||
auto bal_itr = bal_idx.rbegin();
|
||||
while( bal_itr->maintenance_flag )
|
||||
{
|
||||
const account_balance_object& bal_obj = *bal_itr;
|
||||
|
||||
modify( get_account_stats_by_owner( bal_obj.owner ), [&bal_obj](account_statistics_object& aso) {
|
||||
aso.core_in_balance = bal_obj.balance;
|
||||
});
|
||||
|
||||
modify( bal_obj, []( account_balance_object& abo ) {
|
||||
abo.maintenance_flag = false;
|
||||
});
|
||||
|
||||
bal_itr = bal_idx.rbegin();
|
||||
}
|
||||
}
|
||||
|
||||
const auto& stats_idx = get_index_type< account_stats_index >().indices().get< by_maintenance_seq >();
|
||||
auto stats_itr = stats_idx.lower_bound( true );
|
||||
|
||||
while( stats_itr != stats_idx.end() )
|
||||
{
|
||||
const account_statistics_object& acc_stat = *stats_itr;
|
||||
const account_object& acc_obj = acc_stat.owner( *this );
|
||||
++stats_itr;
|
||||
|
||||
if( acc_stat.has_some_core_voting() )
|
||||
tally_helper( acc_obj, acc_stat );
|
||||
|
||||
if( acc_stat.has_pending_fees() )
|
||||
acc_stat.process_fees( acc_obj, *this );
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief A visitor for @ref worker_type which calls pay_worker on the worker within
|
||||
|
|
@ -1464,7 +1496,8 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
|||
#endif
|
||||
}
|
||||
|
||||
void operator()(const account_object& stake_account) {
|
||||
void operator()( const account_object& stake_account, const account_statistics_object& stats )
|
||||
{
|
||||
if( props.parameters.count_non_member_votes || stake_account.is_member(d.head_block_time()) )
|
||||
{
|
||||
// There may be a difference between the account whose stake is voting and the one specifying opinions.
|
||||
|
|
@ -1537,23 +1570,8 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
|||
}
|
||||
}
|
||||
} tally_helper(*this, gpo);
|
||||
struct process_fees_helper {
|
||||
database& d;
|
||||
const global_property_object& props;
|
||||
|
||||
process_fees_helper(database& d, const global_property_object& gpo)
|
||||
: d(d), props(gpo) {}
|
||||
|
||||
void operator()(const account_object& a) {
|
||||
a.statistics(d).process_fees(a, d);
|
||||
}
|
||||
} fee_helper(*this, gpo);
|
||||
|
||||
perform_account_maintenance(std::tie(
|
||||
tally_helper,
|
||||
fee_helper
|
||||
));
|
||||
|
||||
|
||||
perform_account_maintenance( tally_helper );
|
||||
struct clear_canary {
|
||||
clear_canary(vector<uint64_t>& target): target(target){}
|
||||
~clear_canary() { target.clear(); }
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ namespace graphene { namespace chain {
|
|||
|
||||
account_id_type owner;
|
||||
|
||||
string name; ///< redundantly store account name here for better maintenance performance
|
||||
|
||||
/**
|
||||
* Keep the most recent operation as a root pointer to a linked list of the transaction history.
|
||||
*/
|
||||
|
|
@ -62,6 +64,19 @@ namespace graphene { namespace chain {
|
|||
*/
|
||||
share_type total_core_in_orders;
|
||||
|
||||
share_type core_in_balance = 0; ///< redundantly store core balance here for better maintenance performance
|
||||
|
||||
bool has_cashback_vb = false; ///< redundantly store this for better maintenance performance
|
||||
|
||||
bool is_voting = false; ///< redundately store whether this account is voting for better maintenance performance
|
||||
|
||||
|
||||
/// Whether this account owns some CORE asset and is voting
|
||||
inline bool has_some_core_voting() const
|
||||
{
|
||||
return is_voting && ( total_core_in_orders > 0 || core_in_balance > 0 || has_cashback_vb );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks the total fees paid by this account for the purpose of calculating bulk discounts.
|
||||
*/
|
||||
|
|
@ -87,6 +102,12 @@ namespace graphene { namespace chain {
|
|||
*/
|
||||
time_point_sec last_vote_time;
|
||||
|
||||
/// Whether this account has pending fees, no matter vested or not
|
||||
inline bool has_pending_fees() const { return pending_fees > 0 || pending_vested_fees > 0; }
|
||||
|
||||
/// Whether need to process this account during the maintenance interval
|
||||
inline bool need_maintenance() const { return has_some_core_voting() || has_pending_fees(); }
|
||||
|
||||
/// @brief Split up and pay out @ref pending_fees and @ref pending_vested_fees
|
||||
void process_fees(const account_object& a, database& d) const;
|
||||
|
||||
|
|
@ -112,6 +133,7 @@ namespace graphene { namespace chain {
|
|||
account_id_type owner;
|
||||
asset_id_type asset_type;
|
||||
share_type balance;
|
||||
bool maintenance_flag = false; ///< Whether need to process this balance object in maintenance interval
|
||||
|
||||
asset get_balance()const { return asset(balance, asset_type); }
|
||||
void adjust_balance(const asset& delta);
|
||||
|
|
@ -388,6 +410,9 @@ namespace graphene { namespace chain {
|
|||
};
|
||||
|
||||
struct by_asset_balance;
|
||||
struct by_maintenance_flag;
|
||||
struct by_account_asset;
|
||||
|
||||
/**
|
||||
* @ingroup object_index
|
||||
*/
|
||||
|
|
@ -395,6 +420,15 @@ namespace graphene { namespace chain {
|
|||
account_balance_object,
|
||||
indexed_by<
|
||||
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
||||
ordered_non_unique< tag<by_maintenance_flag>,
|
||||
member< account_balance_object, bool, &account_balance_object::maintenance_flag > >,
|
||||
ordered_unique< tag<by_account_asset>,
|
||||
composite_key<
|
||||
account_balance_object,
|
||||
member<account_balance_object, account_id_type, &account_balance_object::owner>,
|
||||
member<account_balance_object, asset_id_type, &account_balance_object::asset_type>
|
||||
>
|
||||
>,
|
||||
ordered_unique< tag<by_asset_balance>,
|
||||
composite_key<
|
||||
account_balance_object,
|
||||
|
|
@ -434,26 +468,6 @@ namespace graphene { namespace chain {
|
|||
*/
|
||||
typedef generic_index<account_object, account_multi_index_type> account_index;
|
||||
|
||||
struct by_owner;
|
||||
struct by_maintenance_seq;
|
||||
|
||||
/**
|
||||
* @ingroup object_index
|
||||
*/
|
||||
typedef multi_index_container<
|
||||
account_statistics_object,
|
||||
indexed_by<
|
||||
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
||||
ordered_unique< tag<by_owner>,
|
||||
member< account_statistics_object, account_id_type, &account_statistics_object::owner > >
|
||||
>
|
||||
> account_stats_multi_index_type;
|
||||
|
||||
/**
|
||||
* @ingroup object_index
|
||||
*/
|
||||
typedef generic_index<account_statistics_object, account_stats_multi_index_type> account_stats_index;
|
||||
|
||||
struct by_dividend_payout_account{}; // use when calculating pending payouts
|
||||
struct by_dividend_account_payout{}; // use when doing actual payouts
|
||||
struct by_account_dividend_payout{}; // use in get_full_accounts()
|
||||
|
|
@ -497,6 +511,33 @@ namespace graphene { namespace chain {
|
|||
*/
|
||||
typedef generic_index<pending_dividend_payout_balance_for_holder_object, pending_dividend_payout_balance_for_holder_object_multi_index_type> pending_dividend_payout_balance_for_holder_object_index;
|
||||
|
||||
struct by_owner;
|
||||
struct by_maintenance_seq;
|
||||
|
||||
/**
|
||||
* @ingroup object_index
|
||||
*/
|
||||
typedef multi_index_container<
|
||||
account_statistics_object,
|
||||
indexed_by<
|
||||
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
||||
ordered_unique< tag<by_owner>,
|
||||
member< account_statistics_object, account_id_type, &account_statistics_object::owner > >,
|
||||
ordered_unique< tag<by_maintenance_seq>,
|
||||
composite_key<
|
||||
account_statistics_object,
|
||||
const_mem_fun<account_statistics_object, bool, &account_statistics_object::need_maintenance>,
|
||||
member<account_statistics_object, string, &account_statistics_object::name>
|
||||
>
|
||||
>
|
||||
>
|
||||
> account_stats_multi_index_type;
|
||||
|
||||
/**
|
||||
* @ingroup object_index
|
||||
*/
|
||||
typedef generic_index<account_statistics_object, account_stats_multi_index_type> account_stats_index;
|
||||
|
||||
}}
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::account_object,
|
||||
|
|
@ -513,14 +554,17 @@ FC_REFLECT_DERIVED( graphene::chain::account_object,
|
|||
|
||||
FC_REFLECT_DERIVED( graphene::chain::account_balance_object,
|
||||
(graphene::db::object),
|
||||
(owner)(asset_type)(balance) )
|
||||
(owner)(asset_type)(balance)(maintenance_flag) )
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::account_statistics_object,
|
||||
(graphene::chain::object),
|
||||
(owner)
|
||||
(owner)(name)
|
||||
(most_recent_op)
|
||||
(total_ops)(removed_ops)
|
||||
(total_core_in_orders)
|
||||
(core_in_balance)
|
||||
(has_cashback_vb)
|
||||
(is_voting)
|
||||
(lifetime_fees_paid)
|
||||
(pending_fees)(pending_vested_fees)
|
||||
(last_vote_time)
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@
|
|||
#define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4
|
||||
#define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3
|
||||
|
||||
#define GRAPHENE_CURRENT_DB_VERSION "PPY2.2"
|
||||
#define GRAPHENE_CURRENT_DB_VERSION "PPY2.3"
|
||||
|
||||
#define GRAPHENE_IRREVERSIBLE_THRESHOLD (70 * GRAPHENE_1_PERCENT)
|
||||
|
||||
|
|
|
|||
|
|
@ -276,6 +276,7 @@ namespace graphene { namespace chain {
|
|||
const dynamic_global_property_object& get_dynamic_global_properties()const;
|
||||
const node_property_object& get_node_properties()const;
|
||||
const fee_schedule& current_fee_schedule()const;
|
||||
const account_statistics_object& get_account_stats_by_owner( account_id_type owner )const;
|
||||
const std::vector<uint32_t> get_winner_numbers( asset_id_type for_asset, uint32_t count_members, uint8_t count_winners ) const;
|
||||
std::vector<uint32_t> get_seeds( asset_id_type for_asset, uint8_t count_winners )const;
|
||||
uint64_t get_random_bits( uint64_t bound );
|
||||
|
|
@ -526,8 +527,8 @@ namespace graphene { namespace chain {
|
|||
public:
|
||||
double calculate_vesting_factor(const account_object& stake_account);
|
||||
|
||||
template<class... Types>
|
||||
void perform_account_maintenance(std::tuple<Types...> helpers);
|
||||
template<class Type>
|
||||
void perform_account_maintenance(Type tally_helper);
|
||||
///@}
|
||||
///@}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,12 @@ namespace graphene { namespace chain {
|
|||
/// account's balance of core asset.
|
||||
flat_set<vote_id_type> votes;
|
||||
extensions_type extensions;
|
||||
|
||||
/// Whether this account is voting
|
||||
inline bool is_voting() const
|
||||
{
|
||||
return ( voting_account != GRAPHENE_PROXY_TO_SELF_ACCOUNT || !votes.empty() );
|
||||
}
|
||||
|
||||
void validate()const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ void database_fixture::verify_asset_supplies( const database& db )
|
|||
const asset_dynamic_data_object& core_asset_data = db.get_core_asset().dynamic_asset_data_id(db);
|
||||
BOOST_CHECK(core_asset_data.fee_pool == 0);
|
||||
|
||||
const simple_index<account_statistics_object>& statistics_index = db.get_index_type<simple_index<account_statistics_object>>();
|
||||
const auto& statistics_index = db.get_index_type<account_stats_index>().indices();
|
||||
const auto& balance_index = db.get_index_type<account_balance_index>().indices();
|
||||
const auto& settle_index = db.get_index_type<force_settlement_index>().indices();
|
||||
const auto& tournaments_index = db.get_index_type<tournament_index>().indices();
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(last_voting_date)
|
|||
// we are going to vote for this witness
|
||||
auto witness1 = witness_id_type(1)(db);
|
||||
|
||||
auto stats_obj = alice_id(db).statistics(db);
|
||||
auto stats_obj = db.get_account_stats_by_owner(alice_id);
|
||||
BOOST_CHECK_EQUAL(stats_obj.last_vote_time.sec_since_epoch(), 0);
|
||||
|
||||
// alice votes
|
||||
|
|
@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE(last_voting_date)
|
|||
auto now = db.head_block_time().sec_since_epoch();
|
||||
|
||||
// last_vote_time is updated for alice
|
||||
stats_obj = alice_id(db).statistics(db);
|
||||
stats_obj = db.get_account_stats_by_owner(alice_id);
|
||||
BOOST_CHECK_EQUAL(stats_obj.last_vote_time.sec_since_epoch(), now);
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
|
|
|||
Loading…
Reference in a new issue