Merge pull request #116 from peerplays-network/GRPH-81

[GRPH-81] Different performance optimization
This commit is contained in:
Alfredo Garcia 2019-11-20 13:36:41 -03:00 committed by GitHub
commit e7e08169c8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 293 additions and 126 deletions

View file

@ -59,8 +59,8 @@ void account_statistics_object::process_fees(const account_object& a, database&
// Check the referrer -- if he's no longer a member, pay to the lifetime referrer instead. // Check the referrer -- if he's no longer a member, pay to the lifetime referrer instead.
// No need to check the registrar; registrars are required to be lifetime members. // No need to check the registrar; registrars are required to be lifetime members.
if( account.referrer(d).is_basic_account(d.head_block_time()) ) if( account.referrer(d).is_basic_account(d.head_block_time()) )
d.modify(account, [](account_object& a) { d.modify( account, [](account_object& acc) {
a.referrer = a.lifetime_referrer; acc.referrer = acc.lifetime_referrer;
}); });
share_type network_cut = cut_fee(core_fee_total, account.network_fee_percentage); share_type network_cut = cut_fee(core_fee_total, account.network_fee_percentage);
@ -76,8 +76,8 @@ void account_statistics_object::process_fees(const account_object& a, database&
share_type lifetime_cut = cut_fee(core_fee_total, account.lifetime_referrer_fee_percentage); share_type lifetime_cut = cut_fee(core_fee_total, account.lifetime_referrer_fee_percentage);
share_type referral = core_fee_total - network_cut - lifetime_cut; share_type referral = core_fee_total - network_cut - lifetime_cut;
d.modify(asset_dynamic_data_id_type()(d), [network_cut](asset_dynamic_data_object& d) { d.modify( d.get_core_dynamic_data(), [network_cut](asset_dynamic_data_object& addo) {
d.accumulated_fees += network_cut; addo.accumulated_fees += network_cut;
}); });
// Potential optimization: Skip some of this math and object lookups by special casing on the account type. // Potential optimization: Skip some of this math and object lookups by special casing on the account type.

View file

@ -133,33 +133,36 @@ void asset_create_evaluator::pay_fee()
object_id_type asset_create_evaluator::do_apply( const asset_create_operation& op ) object_id_type asset_create_evaluator::do_apply( const asset_create_operation& op )
{ try { { try {
database& d = db();
// includes changes from bitshares. (https://github.com/bitshares/bitshares-core/issues/429) // includes changes from bitshares. (https://github.com/bitshares/bitshares-core/issues/429)
bool hf_429 = fee_is_odd && db().head_block_time() > HARDFORK_CORE_429_TIME; bool hf_429 = fee_is_odd && db().head_block_time() > HARDFORK_CORE_429_TIME;
const asset_dynamic_data_object& dyn_asset = const asset_dynamic_data_object& dyn_asset =
db().create<asset_dynamic_data_object>( [&]( asset_dynamic_data_object& a ) { d.create<asset_dynamic_data_object>( [hf_429,this]( asset_dynamic_data_object& a ) {
a.current_supply = 0; a.current_supply = 0;
a.fee_pool = core_fee_paid - (hf_429 ? 1 : 0); a.fee_pool = core_fee_paid - (hf_429 ? 1 : 0);
}); });
if( fee_is_odd && !hf_429 ) if( fee_is_odd && !hf_429 )
{ {
const auto& core_dd = db().get<asset_object>( asset_id_type() ).dynamic_data( db() ); const auto& core_dd = d.get_core_asset().dynamic_data( d );
db().modify( core_dd, [=]( asset_dynamic_data_object& dd ) { d.modify( core_dd, []( asset_dynamic_data_object& dd ) {
dd.current_supply++; dd.current_supply++;
}); });
} }
auto next_asset_id = d.get_index_type<asset_index>().get_next_id();
asset_bitasset_data_id_type bit_asset_id; asset_bitasset_data_id_type bit_asset_id;
if( op.bitasset_opts.valid() ) if( op.bitasset_opts.valid() )
bit_asset_id = db().create<asset_bitasset_data_object>( [&]( asset_bitasset_data_object& a ) { bit_asset_id = d.create<asset_bitasset_data_object>( [&]( asset_bitasset_data_object& a ) {
a.options = *op.bitasset_opts; a.options = *op.bitasset_opts;
a.is_prediction_market = op.is_prediction_market; a.is_prediction_market = op.is_prediction_market;
a.asset_id = next_asset_id;
}).id; }).id;
auto next_asset_id = db().get_index_type<asset_index>().get_next_id();
const asset_object& new_asset = const asset_object& new_asset =
db().create<asset_object>( [&]( asset_object& a ) { d.create<asset_object>( [&]( asset_object& a ) {
a.issuer = op.issuer; a.issuer = op.issuer;
a.symbol = op.symbol; a.symbol = op.symbol;
a.precision = op.precision; a.precision = op.precision;
@ -175,7 +178,7 @@ object_id_type asset_create_evaluator::do_apply( const asset_create_operation& o
if( op.bitasset_opts.valid() ) if( op.bitasset_opts.valid() )
a.bitasset_data_id = bit_asset_id; a.bitasset_data_id = bit_asset_id;
}); });
assert( new_asset.id == next_asset_id ); FC_ASSERT( new_asset.id == next_asset_id );
return new_asset.id; return new_asset.id;
} FC_CAPTURE_AND_RETHROW( (op) ) } } FC_CAPTURE_AND_RETHROW( (op) ) }
@ -281,33 +284,36 @@ void lottery_asset_create_evaluator::pay_fee()
object_id_type lottery_asset_create_evaluator::do_apply( const lottery_asset_create_operation& op ) object_id_type lottery_asset_create_evaluator::do_apply( const lottery_asset_create_operation& op )
{ try { { try {
database& d = db();
// includes changes from bitshares. (https://github.com/bitshares/bitshares-core/issues/429) // includes changes from bitshares. (https://github.com/bitshares/bitshares-core/issues/429)
bool hf_429 = fee_is_odd && db().head_block_time() > HARDFORK_CORE_429_TIME; bool hf_429 = fee_is_odd && d.head_block_time() > HARDFORK_CORE_429_TIME;
const asset_dynamic_data_object& dyn_asset = const asset_dynamic_data_object& dyn_asset =
db().create<asset_dynamic_data_object>( [&]( asset_dynamic_data_object& a ) { d.create<asset_dynamic_data_object>( [&]( asset_dynamic_data_object& a ) {
a.current_supply = 0; a.current_supply = 0;
a.fee_pool = core_fee_paid - (hf_429 ? 1 : 0); a.fee_pool = core_fee_paid - (hf_429 ? 1 : 0);
}); });
if( fee_is_odd && !hf_429 ) if( fee_is_odd && !hf_429 )
{ {
const auto& core_dd = db().get<asset_object>( asset_id_type() ).dynamic_data( db() ); const auto& core_dd = d.get<asset_object>( asset_id_type() ).dynamic_data( db() );
db().modify( core_dd, [=]( asset_dynamic_data_object& dd ) { d.modify( core_dd, [=]( asset_dynamic_data_object& dd ) {
dd.current_supply++; dd.current_supply++;
}); });
} }
auto next_asset_id = d.get_index_type<asset_index>().get_next_id();
asset_bitasset_data_id_type bit_asset_id; asset_bitasset_data_id_type bit_asset_id;
if( op.bitasset_opts.valid() ) if( op.bitasset_opts.valid() )
bit_asset_id = db().create<asset_bitasset_data_object>( [&]( asset_bitasset_data_object& a ) { bit_asset_id = d.create<asset_bitasset_data_object>( [&op,next_asset_id]( asset_bitasset_data_object& a ) {
a.options = *op.bitasset_opts; a.options = *op.bitasset_opts;
a.is_prediction_market = op.is_prediction_market; a.is_prediction_market = op.is_prediction_market;
a.asset_id = next_asset_id;
}).id; }).id;
auto next_asset_id = db().get_index_type<asset_index>().get_next_id();
const asset_object& new_asset = const asset_object& new_asset =
db().create<asset_object>( [&]( asset_object& a ) { d.create<asset_object>( [&op,next_asset_id,&dyn_asset,bit_asset_id,&d]( asset_object& a ) {
a.issuer = op.issuer; a.issuer = op.issuer;
a.symbol = op.symbol; a.symbol = op.symbol;
a.precision = op.precision; a.precision = op.precision;
@ -316,7 +322,7 @@ object_id_type lottery_asset_create_evaluator::do_apply( const lottery_asset_cre
a.lottery_options = op.extensions; a.lottery_options = op.extensions;
//a.lottery_options->balance = asset( 0, a.lottery_options->ticket_price.asset_id ); //a.lottery_options->balance = asset( 0, a.lottery_options->ticket_price.asset_id );
a.lottery_options->owner = a.id; a.lottery_options->owner = a.id;
db().create<lottery_balance_object>([&](lottery_balance_object& lbo) { d.create<lottery_balance_object>([&a](lottery_balance_object& lbo) {
lbo.lottery_id = a.id; lbo.lottery_id = a.id;
}); });
if( a.options.core_exchange_rate.base.asset_id.instance.value == 0 ) if( a.options.core_exchange_rate.base.asset_id.instance.value == 0 )
@ -327,7 +333,7 @@ object_id_type lottery_asset_create_evaluator::do_apply( const lottery_asset_cre
if( op.bitasset_opts.valid() ) if( op.bitasset_opts.valid() )
a.bitasset_data_id = bit_asset_id; a.bitasset_data_id = bit_asset_id;
}); });
assert( new_asset.id == next_asset_id ); FC_ASSERT( new_asset.id == next_asset_id, "Unexpected object database error, object id mismatch" );
return new_asset.id; return new_asset.id;
} FC_CAPTURE_AND_RETHROW( (op) ) } } FC_CAPTURE_AND_RETHROW( (op) ) }
@ -354,7 +360,7 @@ void_result asset_issue_evaluator::do_apply( const asset_issue_operation& o )
{ try { { try {
db().adjust_balance( o.issue_to_account, o.asset_to_issue ); db().adjust_balance( o.issue_to_account, o.asset_to_issue );
db().modify( *asset_dyn_data, [&]( asset_dynamic_data_object& data ){ db().modify( *asset_dyn_data, [&o]( asset_dynamic_data_object& data ){
data.current_supply += o.asset_to_issue.amount; data.current_supply += o.asset_to_issue.amount;
}); });
@ -386,7 +392,7 @@ void_result asset_reserve_evaluator::do_apply( const asset_reserve_operation& o
{ try { { try {
db().adjust_balance( o.payer, -o.amount_to_reserve ); db().adjust_balance( o.payer, -o.amount_to_reserve );
db().modify( *asset_dyn_data, [&]( asset_dynamic_data_object& data ){ db().modify( *asset_dyn_data, [&o]( asset_dynamic_data_object& data ){
data.current_supply -= o.amount_to_reserve.amount; data.current_supply -= o.amount_to_reserve.amount;
}); });
@ -408,7 +414,7 @@ void_result asset_fund_fee_pool_evaluator::do_apply(const asset_fund_fee_pool_op
{ try { { try {
db().adjust_balance(o.from_account, -o.amount); db().adjust_balance(o.from_account, -o.amount);
db().modify( *asset_dyn_data, [&]( asset_dynamic_data_object& data ) { db().modify( *asset_dyn_data, [&o]( asset_dynamic_data_object& data ) {
data.fee_pool += o.amount; data.fee_pool += o.amount;
}); });
@ -483,7 +489,21 @@ void_result asset_update_evaluator::do_apply(const asset_update_operation& o)
d.cancel_order(*itr); d.cancel_order(*itr);
} }
d.modify(*asset_to_update, [&](asset_object& a) { // For market-issued assets, if core change rate changed, update flag in bitasset data
if( asset_to_update->is_market_issued()
&& asset_to_update->options.core_exchange_rate != o.new_options.core_exchange_rate )
{
const auto& bitasset = asset_to_update->bitasset_data(d);
if( !bitasset.asset_cer_updated )
{
d.modify( bitasset, [](asset_bitasset_data_object& b)
{
b.asset_cer_updated = true;
});
}
}
d.modify(*asset_to_update, [&o](asset_object& a) {
if( o.new_issuer ) if( o.new_issuer )
a.issuer = *o.new_issuer; a.issuer = *o.new_issuer;
a.options = o.new_options; a.options = o.new_options;

View file

@ -61,12 +61,15 @@ void asset_bitasset_data_object::update_median_feeds(time_point_sec current_time
if( current_feeds.size() < options.minimum_feeds ) if( current_feeds.size() < options.minimum_feeds )
{ {
//... don't calculate a median, and set a null feed //... don't calculate a median, and set a null feed
feed_cer_updated = false; // new median cer is null, won't update asset_object anyway, set to false for better performance
current_feed_publication_time = current_time; current_feed_publication_time = current_time;
current_feed = price_feed(); current_feed = price_feed();
return; return;
} }
if( current_feeds.size() == 1 ) if( current_feeds.size() == 1 )
{ {
if( current_feed.core_exchange_rate != current_feeds.front().get().core_exchange_rate )
feed_cer_updated = true;
current_feed = std::move(current_feeds.front()); current_feed = std::move(current_feeds.front());
return; return;
} }
@ -85,6 +88,8 @@ void asset_bitasset_data_object::update_median_feeds(time_point_sec current_time
#undef CALCULATE_MEDIAN_VALUE #undef CALCULATE_MEDIAN_VALUE
// *** End Median Calculations *** // *** End Median Calculations ***
if( current_feed.core_exchange_rate != median_feed.core_exchange_rate )
feed_cer_updated = true;
current_feed = median_feed; current_feed = median_feed;
} }

View file

@ -210,7 +210,7 @@ void database::deposit_cashback(const account_object& acct, share_type amount, b
acct.get_id() == GRAPHENE_TEMP_ACCOUNT ) acct.get_id() == GRAPHENE_TEMP_ACCOUNT )
{ {
// The blockchain's accounts do not get cashback; it simply goes to the reserve pool. // The blockchain's accounts do not get cashback; it simply goes to the reserve pool.
modify(get(asset_id_type()).dynamic_asset_data_id(*this), [amount](asset_dynamic_data_object& d) { modify( get_core_dynamic_data(), [amount](asset_dynamic_data_object& d) {
d.current_supply -= amount; d.current_supply -= amount;
}); });
return; return;

View file

@ -592,7 +592,7 @@ void database::_apply_block( const signed_block& next_block )
const witness_object& signing_witness = validate_block_header(skip, next_block); const witness_object& signing_witness = validate_block_header(skip, next_block);
const auto& global_props = get_global_properties(); const auto& global_props = get_global_properties();
const auto& dynamic_global_props = get<dynamic_global_property_object>(dynamic_global_property_id_type()); const auto& dynamic_global_props = get_dynamic_global_properties();
bool maint_needed = (dynamic_global_props.next_maintenance_time <= next_block.timestamp); bool maint_needed = (dynamic_global_props.next_maintenance_time <= next_block.timestamp);
_current_block_num = next_block_num; _current_block_num = next_block_num;
@ -600,6 +600,8 @@ void database::_apply_block( const signed_block& next_block )
_current_op_in_trx = 0; _current_op_in_trx = 0;
_current_virtual_op = 0; _current_virtual_op = 0;
_issue_453_affected_assets.clear();
for( const auto& trx : next_block.transactions ) for( const auto& trx : next_block.transactions )
{ {
/* We do not need to push the undo state for each transaction /* We do not need to push the undo state for each transaction
@ -638,7 +640,8 @@ void database::_apply_block( const signed_block& next_block )
clear_expired_transactions(); clear_expired_transactions();
clear_expired_proposals(); clear_expired_proposals();
clear_expired_orders(); clear_expired_orders();
update_expired_feeds(); update_expired_feeds(); // this will update expired feeds and some core exchange rates
update_core_exchange_rates(); // this will update remaining core exchange rates
update_withdraw_permissions(); update_withdraw_permissions();
update_tournaments(); update_tournaments();
update_betting_markets(next_block.timestamp); update_betting_markets(next_block.timestamp);

View file

@ -37,22 +37,27 @@ namespace graphene { namespace chain {
const asset_object& database::get_core_asset() const const asset_object& database::get_core_asset() const
{ {
return get(asset_id_type()); return *_p_core_asset_obj;
}
const asset_dynamic_data_object& database::get_core_dynamic_data() const
{
return *_p_core_dynamic_data_obj;
} }
const global_property_object& database::get_global_properties()const const global_property_object& database::get_global_properties()const
{ {
return get( global_property_id_type() ); return *_p_global_prop_obj;
} }
const chain_property_object& database::get_chain_properties()const const chain_property_object& database::get_chain_properties()const
{ {
return get( chain_property_id_type() ); return *_p_chain_property_obj;
} }
const dynamic_global_property_object& database::get_dynamic_global_properties() const const dynamic_global_property_object& database::get_dynamic_global_properties() const
{ {
return get( dynamic_global_property_id_type() ); return *_p_dyn_global_prop_obj;
} }
const fee_schedule& database::current_fee_schedule()const const fee_schedule& database::current_fee_schedule()const
@ -62,17 +67,17 @@ const fee_schedule& database::current_fee_schedule()const
time_point_sec database::head_block_time()const time_point_sec database::head_block_time()const
{ {
return get( dynamic_global_property_id_type() ).time; return get_dynamic_global_properties().time;
} }
uint32_t database::head_block_num()const uint32_t database::head_block_num()const
{ {
return get( dynamic_global_property_id_type() ).head_block_number; return get_dynamic_global_properties().head_block_number;
} }
block_id_type database::head_block_id()const block_id_type database::head_block_id()const
{ {
return get( dynamic_global_property_id_type() ).head_block_id; return get_dynamic_global_properties().head_block_id;
} }
decltype( chain_parameters::block_interval ) database::block_interval( )const decltype( chain_parameters::block_interval ) database::block_interval( )const
@ -149,5 +154,9 @@ const account_statistics_object& database::get_account_stats_by_owner( account_i
return *itr; return *itr;
} }
const witness_schedule_object& database::get_witness_schedule_object()const
{
return *_p_witness_schedule_obj;
}
} } } }

View file

@ -492,9 +492,12 @@ void database::init_genesis(const genesis_state_type& genesis_state)
a.options.core_exchange_rate.quote.asset_id = asset_id_type(0); a.options.core_exchange_rate.quote.asset_id = asset_id_type(0);
a.dynamic_asset_data_id = dyn_asset.id; a.dynamic_asset_data_id = dyn_asset.id;
a.dividend_data_id = div_asset.id; a.dividend_data_id = div_asset.id;
}); });
assert( asset_id_type(core_asset.id) == asset().asset_id ); FC_ASSERT( dyn_asset.id == asset_dynamic_data_id_type() );
assert( get_balance(account_id_type(), asset_id_type()) == asset(dyn_asset.current_supply) ); FC_ASSERT( asset_id_type(core_asset.id) == asset().asset_id );
FC_ASSERT( get_balance(account_id_type(), asset_id_type()) == asset(dyn_asset.current_supply) );
_p_core_asset_obj = &core_asset;
_p_core_dynamic_data_obj = &dyn_asset;
#ifdef _DEFAULT_DIVIDEND_ASSET #ifdef _DEFAULT_DIVIDEND_ASSET
// Create default dividend asset // Create default dividend asset
@ -527,7 +530,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
a.dynamic_asset_data_id = dyn_asset1.id; a.dynamic_asset_data_id = dyn_asset1.id;
a.dividend_data_id = div_asset1.id; a.dividend_data_id = div_asset1.id;
}); });
assert( default_asset.id == asset_id_type(1) ); FC_ASSERT( default_asset.id == asset_id_type(1) );
#endif #endif
// Create more special assets // Create more special assets
@ -560,14 +563,14 @@ void database::init_genesis(const genesis_state_type& genesis_state)
chain_id_type chain_id = genesis_state.compute_chain_id(); chain_id_type chain_id = genesis_state.compute_chain_id();
// Create global properties // Create global properties
create<global_property_object>([&](global_property_object& p) { _p_global_prop_obj = & create<global_property_object>([&genesis_state](global_property_object& p) {
p.parameters = genesis_state.initial_parameters; p.parameters = genesis_state.initial_parameters;
// Set fees to zero initially, so that genesis initialization needs not pay them // Set fees to zero initially, so that genesis initialization needs not pay them
// We'll fix it at the end of the function // We'll fix it at the end of the function
p.parameters.current_fees->zero_all_fees(); p.parameters.current_fees->zero_all_fees();
}); });
create<dynamic_global_property_object>([&](dynamic_global_property_object& p) { _p_dyn_global_prop_obj = & create<dynamic_global_property_object>([&genesis_state](dynamic_global_property_object& p) {
p.time = genesis_state.initial_timestamp; p.time = genesis_state.initial_timestamp;
p.dynamic_flags = 0; p.dynamic_flags = 0;
p.witness_budget = 0; p.witness_budget = 0;
@ -580,7 +583,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
FC_ASSERT( (genesis_state.immutable_parameters.min_witness_count & 1) == 1, "min_witness_count must be odd" ); FC_ASSERT( (genesis_state.immutable_parameters.min_witness_count & 1) == 1, "min_witness_count must be odd" );
FC_ASSERT( (genesis_state.immutable_parameters.min_committee_member_count & 1) == 1, "min_committee_member_count must be odd" ); FC_ASSERT( (genesis_state.immutable_parameters.min_committee_member_count & 1) == 1, "min_committee_member_count must be odd" );
create<chain_property_object>([&](chain_property_object& p) _p_chain_property_obj = & create<chain_property_object>([chain_id,&genesis_state](chain_property_object& p)
{ {
p.chain_id = chain_id; p.chain_id = chain_id;
p.immutable_parameters = genesis_state.immutable_parameters; p.immutable_parameters = genesis_state.immutable_parameters;
@ -920,7 +923,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
}); });
// Set active witnesses // Set active witnesses
modify(get_global_properties(), [&](global_property_object& p) { modify(get_global_properties(), [&genesis_state](global_property_object& p) {
for( uint32_t i = 1; i <= genesis_state.initial_active_witnesses; ++i ) for( uint32_t i = 1; i <= genesis_state.initial_active_witnesses; ++i )
{ {
p.active_witnesses.insert(witness_id_type(i)); p.active_witnesses.insert(witness_id_type(i));
@ -928,10 +931,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
}); });
// Initialize witness schedule // Initialize witness schedule
#ifndef NDEBUG _p_witness_schedule_obj = & create<witness_schedule_object>([this](witness_schedule_object& _wso)
const witness_schedule_object& wso =
#endif
create<witness_schedule_object>([&](witness_schedule_object& _wso)
{ {
// for scheduled // for scheduled
memset(_wso.rng_seed.begin(), 0, _wso.rng_seed.size()); memset(_wso.rng_seed.begin(), 0, _wso.rng_seed.size());
@ -955,19 +955,13 @@ void database::init_genesis(const genesis_state_type& genesis_state)
for( const witness_id_type& wid : get_global_properties().active_witnesses ) for( const witness_id_type& wid : get_global_properties().active_witnesses )
_wso.current_shuffled_witnesses.push_back( wid ); _wso.current_shuffled_witnesses.push_back( wid );
}); });
assert( wso.id == witness_schedule_id_type() ); FC_ASSERT( _p_witness_schedule_obj->id == witness_schedule_id_type() );
// Enable fees // Enable fees
modify(get_global_properties(), [&genesis_state](global_property_object& p) { modify(get_global_properties(), [&genesis_state](global_property_object& p) {
p.parameters.current_fees = genesis_state.initial_parameters.current_fees; p.parameters.current_fees = genesis_state.initial_parameters.current_fees;
}); });
// Create witness scheduler
//create<witness_schedule_object>([&]( witness_schedule_object& wso )
//{
// for( const witness_id_type& wid : get_global_properties().active_witnesses )
// wso.current_shuffled_witnesses.push_back( wid );
//});
// Create FBA counters // Create FBA counters
create<fba_accumulator_object>([&]( fba_accumulator_object& acc ) create<fba_accumulator_object>([&]( fba_accumulator_object& acc )

View file

@ -151,12 +151,13 @@ void database::update_worker_votes()
void database::pay_workers( share_type& budget ) void database::pay_workers( share_type& budget )
{ {
const auto head_time = head_block_time();
// ilog("Processing payroll! Available budget is ${b}", ("b", budget)); // ilog("Processing payroll! Available budget is ${b}", ("b", budget));
vector<std::reference_wrapper<const worker_object>> active_workers; vector<std::reference_wrapper<const worker_object>> active_workers;
get_index_type<worker_index>().inspect_all_objects([this, &active_workers](const object& o) { // TODO optimization: add by_expiration index to avoid iterating through all objects
get_index_type<worker_index>().inspect_all_objects([head_time, &active_workers](const object& o) {
const worker_object& w = static_cast<const worker_object&>(o); const worker_object& w = static_cast<const worker_object&>(o);
auto now = head_block_time(); if( w.is_active(head_time) && w.approving_stake() > 0 )
if( w.is_active(now) && w.approving_stake() > 0 )
active_workers.emplace_back(w); active_workers.emplace_back(w);
}); });
@ -170,17 +171,22 @@ void database::pay_workers( share_type& budget )
return wa.id < wb.id; return wa.id < wb.id;
}); });
const auto last_budget_time = get_dynamic_global_properties().last_budget_time;
const auto passed_time_ms = head_time - last_budget_time;
const auto passed_time_count = passed_time_ms.count();
const auto day_count = fc::days(1).count();
for( uint32_t i = 0; i < active_workers.size() && budget > 0; ++i ) for( uint32_t i = 0; i < active_workers.size() && budget > 0; ++i )
{ {
const worker_object& active_worker = active_workers[i]; const worker_object& active_worker = active_workers[i];
share_type requested_pay = active_worker.daily_pay; share_type requested_pay = active_worker.daily_pay;
if( head_block_time() - get_dynamic_global_properties().last_budget_time != fc::days(1) )
{ // Note: if there is a good chance that passed_time_count == day_count,
fc::uint128 pay(requested_pay.value); // for better performance, can avoid the 128 bit calculation by adding a check.
pay *= (head_block_time() - get_dynamic_global_properties().last_budget_time).count(); // Since it's not the case on BitShares mainnet, we're not using a check here.
pay /= fc::days(1).count(); fc::uint128 pay(requested_pay.value);
requested_pay = pay.to_uint64(); pay *= passed_time_count;
} pay /= day_count;
requested_pay = pay.to_uint64();
share_type actual_pay = std::min(budget, requested_pay); share_type actual_pay = std::min(budget, requested_pay);
//ilog(" ==> Paying ${a} to worker ${w}", ("w", active_worker.id)("a", actual_pay)); //ilog(" ==> Paying ${a} to worker ${w}", ("w", active_worker.id)("a", actual_pay));
@ -391,8 +397,8 @@ void database::update_active_committee_members()
void database::initialize_budget_record( fc::time_point_sec now, budget_record& rec )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 dynamic_global_property_object& dpo = get_dynamic_global_properties();
const asset_object& core = asset_id_type(0)(*this); const asset_object& core = get_core_asset();
const asset_dynamic_data_object& core_dd = core.dynamic_asset_data_id(*this); const asset_dynamic_data_object& core_dd = get_core_dynamic_data();
rec.from_initial_reserve = core.reserved(*this); rec.from_initial_reserve = core.reserved(*this);
rec.from_accumulated_fees = core_dd.accumulated_fees; rec.from_accumulated_fees = core_dd.accumulated_fees;
@ -445,8 +451,7 @@ void database::process_budget()
{ {
const global_property_object& gpo = get_global_properties(); const global_property_object& gpo = get_global_properties();
const dynamic_global_property_object& dpo = get_dynamic_global_properties(); const dynamic_global_property_object& dpo = get_dynamic_global_properties();
const asset_dynamic_data_object& core = const asset_dynamic_data_object& core = get_core_dynamic_data();
asset_id_type(0)(*this).dynamic_asset_data_id(*this);
fc::time_point_sec now = head_block_time(); fc::time_point_sec now = head_block_time();
int64_t time_to_maint = (dpo.next_maintenance_time - now).to_seconds(); int64_t time_to_maint = (dpo.next_maintenance_time - now).to_seconds();
@ -606,8 +611,7 @@ void split_fba_balance(
if( fba.accumulated_fba_fees == 0 ) if( fba.accumulated_fba_fees == 0 )
return; return;
const asset_object& core = asset_id_type(0)(db); const asset_dynamic_data_object& core_dd = db.get_core_dynamic_data();
const asset_dynamic_data_object& core_dd = core.dynamic_asset_data_id(db);
if( !fba.is_configured(db) ) if( !fba.is_configured(db) )
{ {
@ -1619,9 +1623,10 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
update_active_committee_members(); update_active_committee_members();
update_worker_votes(); update_worker_votes();
modify(gpo, [this](global_property_object& p) { const dynamic_global_property_object& dgpo = get_dynamic_global_properties();
modify(gpo, [&dgpo](global_property_object& p) {
// Remove scaling of account registration fee // Remove scaling of account registration fee
const auto& dgpo = get_dynamic_global_properties();
p.parameters.current_fees->get<account_create_operation>().basic_fee >>= p.parameters.account_fee_scale_bitshifts * p.parameters.current_fees->get<account_create_operation>().basic_fee >>= p.parameters.account_fee_scale_bitshifts *
(dgpo.accounts_registered_this_interval / p.parameters.accounts_per_fee_scale); (dgpo.accounts_registered_this_interval / p.parameters.accounts_per_fee_scale);
@ -1648,7 +1653,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
} }
}); });
auto next_maintenance_time = get<dynamic_global_property_object>(dynamic_global_property_id_type()).next_maintenance_time; auto next_maintenance_time = dgpo.next_maintenance_time;
auto maintenance_interval = gpo.parameters.maintenance_interval; auto maintenance_interval = gpo.parameters.maintenance_interval;
if( next_maintenance_time <= next_block.timestamp ) if( next_maintenance_time <= next_block.timestamp )
@ -1678,8 +1683,6 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
} }
} }
const dynamic_global_property_object& dgpo = get_dynamic_global_properties();
if( (dgpo.next_maintenance_time < HARDFORK_613_TIME) && (next_maintenance_time >= HARDFORK_613_TIME) ) if( (dgpo.next_maintenance_time < HARDFORK_613_TIME) && (next_maintenance_time >= HARDFORK_613_TIME) )
deprecate_annual_members(*this); deprecate_annual_members(*this);

View file

@ -24,6 +24,9 @@
#include <graphene/chain/database.hpp> #include <graphene/chain/database.hpp>
#include <graphene/chain/chain_property_object.hpp>
#include <graphene/chain/witness_schedule_object.hpp>
#include <graphene/chain/special_authority_object.hpp>
#include <graphene/chain/operation_history_object.hpp> #include <graphene/chain/operation_history_object.hpp>
#include <graphene/chain/protocol/fee_schedule.hpp> #include <graphene/chain/protocol/fee_schedule.hpp>
@ -176,7 +179,7 @@ void database::wipe(const fc::path& data_dir, bool include_blocks)
{ {
ilog("Wiping database", ("include_blocks", include_blocks)); ilog("Wiping database", ("include_blocks", include_blocks));
if (_opened) { if (_opened) {
close(); close(false);
} }
object_database::wipe(data_dir); object_database::wipe(data_dir);
if( include_blocks ) if( include_blocks )
@ -214,6 +217,15 @@ void database::open(
if( !find(global_property_id_type()) ) if( !find(global_property_id_type()) )
init_genesis(genesis_loader()); init_genesis(genesis_loader());
else
{
_p_core_asset_obj = &get( asset_id_type() );
_p_core_dynamic_data_obj = &get( asset_dynamic_data_id_type() );
_p_global_prop_obj = &get( global_property_id_type() );
_p_chain_property_obj = &get( chain_property_id_type() );
_p_dyn_global_prop_obj = &get( dynamic_global_property_id_type() );
_p_witness_schedule_obj = &get( witness_schedule_id_type() );
}
fc::optional<block_id_type> last_block = _block_id_to_block.last_id(); fc::optional<block_id_type> last_block = _block_id_to_block.last_id();
if( last_block.valid() ) if( last_block.valid() )

View file

@ -426,14 +426,16 @@ bool database::fill_order(const force_settlement_object& settle, const asset& pa
* *
* @return true if a margin call was executed. * @return true if a margin call was executed.
*/ */
bool database::check_call_orders(const asset_object& mia, bool enable_black_swan) bool database::check_call_orders( const asset_object& mia, bool enable_black_swan, bool for_new_limit_order,
const asset_bitasset_data_object* bitasset_ptr )
{ try { { try {
if( !mia.is_market_issued() ) return false; if( !mia.is_market_issued() ) return false;
if( check_for_blackswan( mia, enable_black_swan ) ) const asset_bitasset_data_object& bitasset = ( bitasset_ptr ? *bitasset_ptr : mia.bitasset_data(*this) );
if( check_for_blackswan( mia, enable_black_swan, &bitasset ) )
return false; return false;
const asset_bitasset_data_object& bitasset = mia.bitasset_data(*this);
if( bitasset.is_prediction_market ) return false; if( bitasset.is_prediction_market ) return false;
if( bitasset.current_feed.settlement_price.is_null() ) return false; if( bitasset.current_feed.settlement_price.is_null() ) return false;
@ -464,7 +466,12 @@ bool database::check_call_orders(const asset_object& mia, bool enable_black_swan
bool filled_limit = false; bool filled_limit = false;
bool margin_called = false; bool margin_called = false;
while( !check_for_blackswan( mia, enable_black_swan ) && call_itr != call_end ) auto head_time = head_block_time();
auto head_num = head_block_num();
bool after_hardfork_436 = ( head_time > HARDFORK_436_TIME );
while( !check_for_blackswan( mia, enable_black_swan, &bitasset ) && call_itr != call_end )
{ {
bool filled_call = false; bool filled_call = false;
price match_price; price match_price;
@ -481,7 +488,7 @@ bool database::check_call_orders(const asset_object& mia, bool enable_black_swan
// would be margin called, but there is no matching order #436 // would be margin called, but there is no matching order #436
bool feed_protected = ( bitasset.current_feed.settlement_price > ~call_itr->call_price ); bool feed_protected = ( bitasset.current_feed.settlement_price > ~call_itr->call_price );
if( feed_protected && (head_block_time() > HARDFORK_436_TIME) ) if( feed_protected && after_hardfork_436 )
return margin_called; return margin_called;
// would be margin called, but there is no matching order // would be margin called, but there is no matching order
@ -506,7 +513,8 @@ bool database::check_call_orders(const asset_object& mia, bool enable_black_swan
if( usd_to_buy * match_price > call_itr->get_collateral() ) if( usd_to_buy * match_price > call_itr->get_collateral() )
{ {
elog( "black swan detected" ); elog( "black swan detected on asset ${symbol} (${id}) at block ${b}",
("id",mia.id)("symbol",mia.symbol)("b",head_num) );
edump((enable_black_swan)); edump((enable_black_swan));
FC_ASSERT( enable_black_swan ); FC_ASSERT( enable_black_swan );
globally_settle_asset(mia, bitasset.current_feed.settlement_price ); globally_settle_asset(mia, bitasset.current_feed.settlement_price );

View file

@ -45,7 +45,7 @@ namespace graphene { namespace chain {
void database::update_global_dynamic_data( const signed_block& b, const uint32_t missed_blocks ) void database::update_global_dynamic_data( const signed_block& b, const uint32_t missed_blocks )
{ {
const dynamic_global_property_object& _dgp = dynamic_global_property_id_type(0)(*this); const dynamic_global_property_object& _dgp = get_dynamic_global_properties();
const global_property_object& gpo = get_global_properties(); const global_property_object& gpo = get_global_properties();
// dynamic global properties updating // dynamic global properties updating
@ -121,6 +121,7 @@ void database::update_last_irreversible_block()
const global_property_object& gpo = get_global_properties(); const global_property_object& gpo = get_global_properties();
const dynamic_global_property_object& dpo = get_dynamic_global_properties(); const dynamic_global_property_object& dpo = get_dynamic_global_properties();
// TODO for better performance, move this to db_maint, because only need to do it once per maintenance interval
vector< const witness_object* > wit_objs; vector< const witness_object* > wit_objs;
wit_objs.reserve( gpo.active_witnesses.size() ); wit_objs.reserve( gpo.active_witnesses.size() );
for( const witness_id_type& wid : gpo.active_witnesses ) for( const witness_id_type& wid : gpo.active_witnesses )
@ -237,11 +238,12 @@ void database::clear_expired_proposals()
* *
* A black swan occurs if MAX(HB,SP) <= LC * A black swan occurs if MAX(HB,SP) <= LC
*/ */
bool database::check_for_blackswan( const asset_object& mia, bool enable_black_swan ) bool database::check_for_blackswan( const asset_object& mia, bool enable_black_swan,
const asset_bitasset_data_object* bitasset_ptr )
{ {
if( !mia.is_market_issued() ) return false; if( !mia.is_market_issued() ) return false;
const asset_bitasset_data_object& bitasset = mia.bitasset_data(*this); const asset_bitasset_data_object& bitasset = ( bitasset_ptr ? *bitasset_ptr : mia.bitasset_data(*this) );
if( bitasset.has_settlement() ) return true; // already force settled if( bitasset.has_settlement() ) return true; // already force settled
auto settle_price = bitasset.current_feed.settlement_price; auto settle_price = bitasset.current_feed.settlement_price;
if( settle_price.is_null() ) return false; // no feed if( settle_price.is_null() ) return false; // no feed
@ -466,32 +468,84 @@ void database::clear_expired_orders()
void database::update_expired_feeds() void database::update_expired_feeds()
{ {
auto& asset_idx = get_index_type<asset_index>().indices().get<by_type>(); const auto head_time = head_block_time();
auto itr = asset_idx.lower_bound( true /** market issued */ ); bool after_hardfork_615 = ( head_time >= HARDFORK_615_TIME );
while( itr != asset_idx.end() )
{
const asset_object& a = *itr;
++itr;
assert( a.is_market_issued() );
const asset_bitasset_data_object& b = a.bitasset_data(*this); const auto& idx = get_index_type<asset_bitasset_data_index>().indices().get<by_feed_expiration>();
bool feed_is_expired; auto itr = idx.begin();
if( head_block_time() < HARDFORK_615_TIME ) while( itr != idx.end() && itr->feed_is_expired( head_time ) )
feed_is_expired = b.feed_is_expired_before_hardfork_615( head_block_time() ); {
else const asset_bitasset_data_object& b = *itr;
feed_is_expired = b.feed_is_expired( head_block_time() ); ++itr; // not always process begin() because old code skipped updating some assets before hf 615
if( feed_is_expired ) bool update_cer = false; // for better performance, to only update bitasset once, also check CER in this function
const asset_object* asset_ptr = nullptr;
// update feeds, check margin calls
if( after_hardfork_615 || b.feed_is_expired_before_hardfork_615( head_time ) )
{ {
modify(b, [this](asset_bitasset_data_object& a) { auto old_median_feed = b.current_feed;
a.update_median_feeds(head_block_time()); modify( b, [head_time,&update_cer]( asset_bitasset_data_object& abdo )
{
abdo.update_median_feeds( head_time );
if( abdo.need_to_update_cer() )
{
update_cer = true;
abdo.asset_cer_updated = false;
abdo.feed_cer_updated = false;
}
}); });
check_call_orders(b.current_feed.settlement_price.base.asset_id(*this)); if( !b.current_feed.settlement_price.is_null() && !( b.current_feed == old_median_feed ) ) // `==` check is safe here
{
asset_ptr = &b.asset_id( *this );
check_call_orders( *asset_ptr, true, false, &b );
}
} }
if( !b.current_feed.core_exchange_rate.is_null() && // update CER
a.options.core_exchange_rate != b.current_feed.core_exchange_rate ) if( update_cer )
modify(a, [&b](asset_object& a) { {
a.options.core_exchange_rate = b.current_feed.core_exchange_rate; if( !asset_ptr )
asset_ptr = &b.asset_id( *this );
if( asset_ptr->options.core_exchange_rate != b.current_feed.core_exchange_rate )
{
modify( *asset_ptr, [&b]( asset_object& ao )
{
ao.options.core_exchange_rate = b.current_feed.core_exchange_rate;
});
}
}
} // for each asset whose feed is expired
// process assets affected by bitshares-core issue 453 before hard fork 615
if( !after_hardfork_615 )
{
for( asset_id_type a : _issue_453_affected_assets )
{
check_call_orders( a(*this) );
}
}
}
void database::update_core_exchange_rates()
{
const auto& idx = get_index_type<asset_bitasset_data_index>().indices().get<by_cer_update>();
if( idx.begin() != idx.end() )
{
for( auto itr = idx.rbegin(); itr->need_to_update_cer(); itr = idx.rbegin() )
{
const asset_bitasset_data_object& b = *itr;
const asset_object& a = b.asset_id( *this );
if( a.options.core_exchange_rate != b.current_feed.core_exchange_rate )
{
modify( a, [&b]( asset_object& ao )
{
ao.options.core_exchange_rate = b.current_feed.core_exchange_rate;
});
}
modify( b, []( asset_bitasset_data_object& abdo )
{
abdo.asset_cer_updated = false;
abdo.feed_cer_updated = false;
}); });
}
} }
} }

View file

@ -38,14 +38,14 @@ witness_id_type database::get_scheduled_witness( uint32_t slot_num )const
if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SHUFFLED_ALGORITHM) if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SHUFFLED_ALGORITHM)
{ {
const dynamic_global_property_object& dpo = get_dynamic_global_properties(); const dynamic_global_property_object& dpo = get_dynamic_global_properties();
const witness_schedule_object& wso = witness_schedule_id_type()(*this); const witness_schedule_object& wso = get_witness_schedule_object();;
uint64_t current_aslot = dpo.current_aslot + slot_num; uint64_t current_aslot = dpo.current_aslot + slot_num;
return wso.current_shuffled_witnesses[ current_aslot % wso.current_shuffled_witnesses.size() ]; return wso.current_shuffled_witnesses[ current_aslot % wso.current_shuffled_witnesses.size() ];
} }
if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM && if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM &&
slot_num != 0 ) slot_num != 0 )
{ {
const witness_schedule_object& wso = witness_schedule_id_type()(*this); const witness_schedule_object& wso = get_witness_schedule_object();;
// ask the near scheduler who goes in the given slot // ask the near scheduler who goes in the given slot
bool slot_is_near = wso.scheduler.get_slot(slot_num-1, wid); bool slot_is_near = wso.scheduler.get_slot(slot_num-1, wid);
if(! slot_is_near) if(! slot_is_near)
@ -113,7 +113,7 @@ uint32_t database::get_slot_at_time(fc::time_point_sec when)const
void database::update_witness_schedule() void database::update_witness_schedule()
{ {
const witness_schedule_object& wso = witness_schedule_id_type()(*this); const witness_schedule_object& wso = get_witness_schedule_object();
const global_property_object& gpo = get_global_properties(); const global_property_object& gpo = get_global_properties();
if( head_block_num() % gpo.active_witnesses.size() == 0 ) if( head_block_num() % gpo.active_witnesses.size() == 0 )
@ -148,7 +148,7 @@ void database::update_witness_schedule()
vector<witness_id_type> database::get_near_witness_schedule()const vector<witness_id_type> database::get_near_witness_schedule()const
{ {
const witness_schedule_object& wso = witness_schedule_id_type()(*this); const witness_schedule_object& wso = get_witness_schedule_object();
vector<witness_id_type> result; vector<witness_id_type> result;
result.reserve(wso.scheduler.size()); result.reserve(wso.scheduler.size());
@ -165,7 +165,7 @@ void database::update_witness_schedule(const signed_block& next_block)
{ {
auto start = fc::time_point::now(); auto start = fc::time_point::now();
const global_property_object& gpo = get_global_properties(); const global_property_object& gpo = get_global_properties();
const witness_schedule_object& wso = get(witness_schedule_id_type()); const witness_schedule_object& wso = get_witness_schedule_object();
uint32_t schedule_needs_filled = gpo.active_witnesses.size(); uint32_t schedule_needs_filled = gpo.active_witnesses.size();
uint32_t schedule_slot = get_slot_at_time(next_block.timestamp); uint32_t schedule_slot = get_slot_at_time(next_block.timestamp);
@ -252,7 +252,7 @@ uint32_t database::witness_participation_rate()const
} }
if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM) if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM)
{ {
const witness_schedule_object& wso = get(witness_schedule_id_type()); const witness_schedule_object& wso = get_witness_schedule_object();
return uint64_t(GRAPHENE_100_PERCENT) * wso.recent_slots_filled.popcount() / 128; return uint64_t(GRAPHENE_100_PERCENT) * wso.recent_slots_filled.popcount() / 128;
} }
return 0; return 0;

View file

@ -193,6 +193,9 @@ namespace graphene { namespace chain {
static const uint8_t space_id = implementation_ids; static const uint8_t space_id = implementation_ids;
static const uint8_t type_id = impl_asset_bitasset_data_type; static const uint8_t type_id = impl_asset_bitasset_data_type;
/// The asset this object belong to
asset_id_type asset_id;
/// The tunable options for BitAssets are stored in this field. /// The tunable options for BitAssets are stored in this field.
bitasset_options options; bitasset_options options;
@ -230,6 +233,18 @@ namespace graphene { namespace chain {
share_type settlement_fund; share_type settlement_fund;
///@} ///@}
/// Track whether core_exchange_rate in corresponding asset_object has updated
bool asset_cer_updated = false;
/// Track whether core exchange rate in current feed has updated
bool feed_cer_updated = false;
/// Whether need to update core_exchange_rate in asset_object
bool need_to_update_cer() const
{
return ( ( feed_cer_updated || asset_cer_updated ) && !current_feed.core_exchange_rate.is_null() );
}
/// The time when @ref current_feed would expire /// The time when @ref current_feed would expire
time_point_sec feed_expiration_time()const time_point_sec feed_expiration_time()const
{ {
@ -247,14 +262,34 @@ namespace graphene { namespace chain {
void update_median_feeds(time_point_sec current_time); void update_median_feeds(time_point_sec current_time);
}; };
// key extractor for short backing asset
struct bitasset_short_backing_asset_extractor
{
typedef asset_id_type result_type;
result_type operator() (const asset_bitasset_data_object& obj) const
{
return obj.options.short_backing_asset;
}
};
struct by_short_backing_asset;
struct by_feed_expiration; struct by_feed_expiration;
struct by_cer_update;
typedef multi_index_container< typedef multi_index_container<
asset_bitasset_data_object, asset_bitasset_data_object,
indexed_by< indexed_by<
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >, ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
ordered_non_unique< tag<by_feed_expiration>, ordered_non_unique< tag<by_short_backing_asset>, bitasset_short_backing_asset_extractor >,
const_mem_fun< asset_bitasset_data_object, time_point_sec, &asset_bitasset_data_object::feed_expiration_time > ordered_unique< tag<by_feed_expiration>,
> composite_key< asset_bitasset_data_object,
const_mem_fun< asset_bitasset_data_object, time_point_sec, &asset_bitasset_data_object::feed_expiration_time >,
member< asset_bitasset_data_object, asset_id_type, &asset_bitasset_data_object::asset_id >
>
>,
ordered_non_unique< tag<by_cer_update>,
const_mem_fun< asset_bitasset_data_object, bool, &asset_bitasset_data_object::need_to_update_cer >
>
> >
> asset_bitasset_data_object_multi_index_type; > asset_bitasset_data_object_multi_index_type;
//typedef flat_index<asset_bitasset_data_object> asset_bitasset_data_index; //typedef flat_index<asset_bitasset_data_object> asset_bitasset_data_index;
@ -481,6 +516,7 @@ FC_REFLECT_DERIVED( graphene::chain::asset_dynamic_data_object, (graphene::db::o
(current_supply)(sweeps_tickets_sold)(confidential_supply)(accumulated_fees)(fee_pool) ) (current_supply)(sweeps_tickets_sold)(confidential_supply)(accumulated_fees)(fee_pool) )
FC_REFLECT_DERIVED( graphene::chain::asset_bitasset_data_object, (graphene::db::object), FC_REFLECT_DERIVED( graphene::chain::asset_bitasset_data_object, (graphene::db::object),
(asset_id)
(feeds) (feeds)
(current_feed) (current_feed)
(current_feed_publication_time) (current_feed_publication_time)
@ -489,6 +525,8 @@ FC_REFLECT_DERIVED( graphene::chain::asset_bitasset_data_object, (graphene::db::
(is_prediction_market) (is_prediction_market)
(settlement_price) (settlement_price)
(settlement_fund) (settlement_fund)
(asset_cer_updated)
(feed_cer_updated)
) )
FC_REFLECT_DERIVED( graphene::chain::asset_dividend_data_object, (graphene::db::object), FC_REFLECT_DERIVED( graphene::chain::asset_dividend_data_object, (graphene::db::object),

View file

@ -271,6 +271,7 @@ namespace graphene { namespace chain {
const chain_id_type& get_chain_id()const; const chain_id_type& get_chain_id()const;
const asset_object& get_core_asset()const; const asset_object& get_core_asset()const;
const asset_dynamic_data_object& get_core_dynamic_data()const;
const chain_property_object& get_chain_properties()const; const chain_property_object& get_chain_properties()const;
const global_property_object& get_global_properties()const; const global_property_object& get_global_properties()const;
const dynamic_global_property_object& get_dynamic_global_properties()const; const dynamic_global_property_object& get_dynamic_global_properties()const;
@ -280,6 +281,7 @@ namespace graphene { namespace chain {
const std::vector<uint32_t> get_winner_numbers( asset_id_type for_asset, uint32_t count_members, uint8_t count_winners ) 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; std::vector<uint32_t> get_seeds( asset_id_type for_asset, uint8_t count_winners )const;
uint64_t get_random_bits( uint64_t bound ); uint64_t get_random_bits( uint64_t bound );
const witness_schedule_object& get_witness_schedule_object()const;
time_point_sec head_block_time()const; time_point_sec head_block_time()const;
uint32_t head_block_num()const; uint32_t head_block_num()const;
@ -437,7 +439,8 @@ namespace graphene { namespace chain {
bool fill_order( const call_order_object& order, const asset& pays, const asset& receives ); bool fill_order( const call_order_object& order, const asset& pays, const asset& receives );
bool fill_order( const force_settlement_object& settle, const asset& pays, const asset& receives ); bool fill_order( const force_settlement_object& settle, const asset& pays, const asset& receives );
bool check_call_orders( const asset_object& mia, bool enable_black_swan = true ); bool check_call_orders( const asset_object& mia, bool enable_black_swan = true, bool for_new_limit_order = false,
const asset_bitasset_data_object* bitasset_ptr = nullptr );
// helpers to fill_order // helpers to fill_order
void pay_order( const account_object& receiver, const asset& receives, const asset& pays ); void pay_order( const account_object& receiver, const asset& receives, const asset& pays );
@ -446,7 +449,7 @@ namespace graphene { namespace chain {
asset pay_market_fees( const asset_object& recv_asset, const asset& receives ); asset pay_market_fees( const asset_object& recv_asset, const asset& receives );
///@} ///@{
/** /**
* This method validates transactions without adding it to the pending state. * This method validates transactions without adding it to the pending state.
* @return true if the transaction would validate * @return true if the transaction would validate
@ -505,11 +508,13 @@ namespace graphene { namespace chain {
void clear_expired_proposals(); void clear_expired_proposals();
void clear_expired_orders(); void clear_expired_orders();
void update_expired_feeds(); void update_expired_feeds();
void update_core_exchange_rates();
void update_maintenance_flag( bool new_maintenance_flag ); void update_maintenance_flag( bool new_maintenance_flag );
void update_withdraw_permissions(); void update_withdraw_permissions();
void update_tournaments(); void update_tournaments();
void update_betting_markets(fc::time_point_sec current_block_time); void update_betting_markets(fc::time_point_sec current_block_time);
bool check_for_blackswan( const asset_object& mia, bool enable_black_swan = true ); bool check_for_blackswan( const asset_object& mia, bool enable_black_swan = true,
const asset_bitasset_data_object* bitasset_ptr = nullptr );
///Steps performed only at maintenance intervals ///Steps performed only at maintenance intervals
///@{ ///@{
@ -584,6 +589,18 @@ namespace graphene { namespace chain {
* database::close() has not been called, or failed during execution. * database::close() has not been called, or failed during execution.
*/ */
bool _opened = false; bool _opened = false;
/// Tracks assets affected by bitshares-core issue #453 before hard fork #615 in one block
flat_set<asset_id_type> _issue_453_affected_assets;
/// Pointers to core asset object and global objects who will have immutable addresses after created
///@{
const asset_object* _p_core_asset_obj = nullptr;
const asset_dynamic_data_object* _p_core_dynamic_data_obj = nullptr;
const global_property_object* _p_global_prop_obj = nullptr;
const dynamic_global_property_object* _p_dyn_global_prop_obj = nullptr;
const chain_property_object* _p_chain_property_obj = nullptr;
const witness_schedule_object* _p_witness_schedule_obj = nullptr;
///@}
}; };
namespace detail namespace detail

View file

@ -130,7 +130,11 @@ namespace graphene { namespace chain {
return ~(asset( cp.numerator().convert_to<int64_t>(), debt.asset_id ) / asset( cp.denominator().convert_to<int64_t>(), collateral.asset_id )); return ~(asset( cp.numerator().convert_to<int64_t>(), debt.asset_id ) / asset( cp.denominator().convert_to<int64_t>(), collateral.asset_id ));
} FC_CAPTURE_AND_RETHROW( (debt)(collateral)(collateral_ratio) ) } } FC_CAPTURE_AND_RETHROW( (debt)(collateral)(collateral_ratio) ) }
bool price::is_null() const { return *this == price(); } bool price::is_null() const
{
// Effectively same as "return *this == price();" but perhaps faster
return ( base.asset_id == asset_id_type() && quote.asset_id == asset_id_type() );
}
void price::validate() const void price::validate() const
{ try { { try {

View file

@ -106,7 +106,7 @@ object_id_type worker_create_evaluator::do_apply(const worker_create_evaluator::
void refund_worker_type::pay_worker(share_type pay, database& db) void refund_worker_type::pay_worker(share_type pay, database& db)
{ {
total_burned += pay; total_burned += pay;
db.modify(db.get(asset_id_type()).dynamic_data(db), [pay](asset_dynamic_data_object& d) { db.modify( db.get_core_dynamic_data(), [pay](asset_dynamic_data_object& d) {
d.current_supply -= pay; d.current_supply -= pay;
}); });
} }