31 #include <graphene/chain/hardfork.hpp> 42 namespace graphene {
namespace chain {
44 void database::update_global_dynamic_data(
const signed_block& b,
const uint32_t missed_blocks )
49 modify( _dgp, [&b,
this,missed_blocks]( dynamic_global_property_object& dgp ){
50 const uint32_t block_num = b.block_num();
51 if( BOOST_UNLIKELY( block_num == 1 ) )
52 dgp.recently_missed_count = 0;
53 else if( !_checkpoints.empty() && _checkpoints.rbegin()->first >= block_num )
54 dgp.recently_missed_count = 0;
55 else if( missed_blocks )
59 else if( dgp.recently_missed_count > 0 )
60 dgp.recently_missed_count--;
62 dgp.head_block_number = block_num;
63 dgp.head_block_id = b.id();
64 dgp.time = b.timestamp;
65 dgp.current_witness = b.witness;
66 dgp.recent_slots_filled = (
67 (dgp.recent_slots_filled << 1)
68 + 1) << missed_blocks;
69 dgp.current_aslot += missed_blocks+1;
75 "The database does not have enough undo history to support a blockchain with so many missed blocks. " 76 "Please add a checkpoint if you would like to continue applying blocks beyond this point.",
77 (
"last_irreversible_block_num",_dgp.last_irreversible_block_num)(
"head", _dgp.head_block_number)
82 _fork_db.
set_max_size( _dgp.head_block_number - _dgp.last_irreversible_block_num + 1 );
85 void database::update_signing_witness(
const witness_object& signing_witness,
const signed_block& new_block)
89 uint64_t new_block_aslot = dpo.current_aslot +
get_slot_at_time( new_block.timestamp );
91 share_type witness_pay = std::min( gpo.parameters.witness_pay_per_block, dpo.witness_budget );
93 modify( dpo, [&]( dynamic_global_property_object& _dpo )
95 _dpo.witness_budget -= witness_pay;
100 modify( signing_witness, [&]( witness_object& _wit )
102 _wit.last_aslot = new_block_aslot;
103 _wit.last_confirmed_block_num = new_block.block_num();
107 void database::update_last_irreversible_block()
113 vector< const witness_object* > wit_objs;
114 wit_objs.reserve( gpo.active_witnesses.size() );
115 for(
const witness_id_type& wid : gpo.active_witnesses )
116 wit_objs.push_back( &(wid(*
this)) );
127 std::nth_element( wit_objs.begin(), wit_objs.begin() + offset, wit_objs.end(),
128 [](
const witness_object* a,
const witness_object* b )
130 return a->last_confirmed_block_num < b->last_confirmed_block_num;
133 uint32_t new_last_irreversible_block_num = wit_objs[offset]->last_confirmed_block_num;
135 if( new_last_irreversible_block_num > dpo.last_irreversible_block_num )
137 modify( dpo, [&]( dynamic_global_property_object& _dpo )
139 _dpo.last_irreversible_block_num = new_last_irreversible_block_num;
144 void database::clear_expired_transactions()
149 impl_transaction_history_object_type));
150 const auto& dedupe_index = transaction_idx.indices().get<by_expiration>();
151 while( (!dedupe_index.empty()) && (
head_block_time() > dedupe_index.begin()->trx.expiration) )
152 transaction_idx.remove(*dedupe_index.begin());
155 void database::clear_expired_proposals()
157 const auto& proposal_expiration_index = get_index_type<proposal_index>().indices().get<by_expiration>();
158 while( !proposal_expiration_index.empty() && proposal_expiration_index.begin()->expiration_time <=
head_block_time() )
160 const proposal_object& proposal = *proposal_expiration_index.begin();
161 processed_transaction result;
163 if( proposal.is_authorized_to_execute(*
this) )
170 elog(
"Failed to apply proposed transaction on its expiration. Deleting it.\n${proposal}\n${error}",
178 static optional<price> get_derived_current_feed_price(
const database& db,
179 const asset_bitasset_data_object& bitasset )
181 optional<price> result;
183 if( bitasset.median_feed.settlement_price.is_null() )
185 if( bitasset.current_feed.settlement_price.is_null() )
188 return bitasset.median_feed.settlement_price;
192 const auto bsrm = bitasset.get_black_swan_response_method();
193 if( bsrm_type::no_settlement == bsrm )
196 const call_order_object* call_ptr = db.find_least_collateralized_short( bitasset,
true );
200 auto least_collateral = call_ptr->collateralization();
202 bitasset.current_feed.maximum_short_squeeze_ratio );
203 result = std::max( bitasset.median_feed.settlement_price, lowest_callable_feed_price );
206 result = bitasset.median_feed.settlement_price;
208 else if( bsrm_type::individual_settlement_to_fund == bsrm && bitasset.individual_settlement_debt > 0 )
211 price fund_price = asset( bitasset.individual_settlement_debt, bitasset.asset_id )
212 / asset( bitasset.individual_settlement_fund, bitasset.options.short_backing_asset );
213 auto lowest_callable_feed_price = fund_price * bitasset.get_margin_call_order_ratio();
214 result = std::max( bitasset.median_feed.settlement_price, lowest_callable_feed_price );
217 result = bitasset.median_feed.settlement_price;
220 if( result.valid() && (*result) == bitasset.current_feed.settlement_price )
231 if( skip_median_update )
233 if( bsrm_type::no_settlement != bsrm && bsrm_type::individual_settlement_to_fund != bsrm )
242 new_current_feed_price = get_derived_current_feed_price( *
this, bitasset );
243 if( !new_current_feed_price.
valid() )
249 modify( bitasset, [
this, skip_median_update, &new_current_feed_price, &bsrm]
252 if( !skip_median_update )
258 if( bsrm_type::no_settlement == bsrm || bsrm_type::individual_settlement_to_fund == bsrm )
259 new_current_feed_price = get_derived_current_feed_price( *
this, abdo );
261 if( new_current_feed_price.
valid() )
266 void database::clear_expired_orders()
272 bool before_core_hardfork_606 = ( maint_time <= HARDFORK_CORE_606_TIME );
274 auto& limit_index = get_index_type<limit_order_index>().indices().get<
by_expiration>();
275 while( !limit_index.empty() && limit_index.begin()->expiration <= head_time )
281 if( before_core_hardfork_606 )
294 void database::clear_expired_force_settlements()
305 const auto& settlement_index = get_index_type<force_settlement_index>().indices().get<
by_expiration>();
306 if( settlement_index.empty() )
312 const bool before_core_hardfork_184 = ( maint_time <= HARDFORK_CORE_184_TIME );
313 const bool before_core_hardfork_342 = ( maint_time <= HARDFORK_CORE_342_TIME );
315 asset_id_type current_asset = settlement_index.begin()->settlement_asset_id();
316 const asset_object* mia_object_ptr = &
get(current_asset);
319 asset max_settlement_volume;
320 price settlement_fill_price;
321 price settlement_price;
322 bool current_asset_finished =
false;
324 auto next_asset = [¤t_asset, &mia_object_ptr, &mia_ptr, ¤t_asset_finished, &settlement_index,
this] {
325 const auto bound = settlement_index.upper_bound(current_asset);
326 if( bound == settlement_index.end() )
328 current_asset = bound->settlement_asset_id();
329 mia_object_ptr = &
get(current_asset);
330 mia_ptr = &mia_object_ptr->bitasset_data(*
this);
331 current_asset_finished =
false;
336 for(
auto itr = settlement_index.lower_bound(current_asset);
337 itr != settlement_index.end();
338 itr = settlement_index.lower_bound(current_asset) )
341 auto settle_order_id = settle_order.
id;
346 mia_object_ptr = &
get(current_asset);
347 mia_ptr = &mia_object_ptr->bitasset_data(*
this);
356 ilog(
"Canceling a force settlement because of black swan" );
371 ilog(
"Canceling a force settlement in ${asset} because settlement price is null",
372 (
"asset", mia_object.
symbol));
378 ilog(
"Canceling a force settlement in ${asset} because settlement offset is 100%",
379 (
"asset", mia_object.
symbol));
385 if( max_settlement_volume.
asset_id != current_asset )
397 if( settlement_fill_price.
base.
asset_id != current_asset )
402 if( before_core_hardfork_342 )
404 auto& pays = settle_order.
balance;
406 receives.
amount =
static_cast<uint64_t
>( ( fc::uint128_t(receives.amount.value) *
410 settlement_price = pays / receives;
412 else if( settlement_price.
base.
asset_id != current_asset )
413 settlement_price = settlement_fill_price;
417 while( settled < max_settlement_volume &&
find_object(settle_order_id) )
421 wlog(
"0 settlement detected" );
430 wlog(
"No debt position found when processing force settlement ${o}", (
"o",settle_order) );
436 asset max_settlement = max_settlement_volume - settled;
438 asset new_settled = match( settle_order, *call_ptr, settlement_price, mia,
439 max_settlement, settlement_fill_price );
440 if( !before_core_hardfork_184 && new_settled.
amount == 0 )
443 current_asset_finished = (
nullptr !=
find_object( settle_order_id ) );
446 settled += new_settled;
460 catch (
const black_swan_exception& e ) {
461 wlog(
"Cancelling a settle_order since it may trigger a black swan: ${o}, ${e}",
462 (
"o", settle_order)(
"e", e.to_detail_string()) );
476 void database::update_expired_feeds()
479 bool after_hardfork_615 = ( head_time >= HARDFORK_615_TIME );
480 bool after_core_hardfork_2582 = HARDFORK_CORE_2582_PASSED( head_time );
482 const auto& idx = get_index_type<asset_bitasset_data_index>().indices().get<by_feed_expiration>();
483 auto itr = idx.begin();
484 while( itr != idx.end() && itr->feed_is_expired( head_time ) )
528 if( !after_hardfork_615 )
530 for( asset_id_type a : _issue_453_affected_assets )
537 void database::update_core_exchange_rates()
539 const auto& idx = get_index_type<asset_bitasset_data_index>().indices().get<by_cer_update>();
540 if( idx.begin() != idx.end() )
542 for(
auto itr = idx.rbegin(); itr->need_to_update_cer(); itr = idx.rbegin() )
562 void database::update_maintenance_flag(
bool new_maintenance_flag )
569 | (new_maintenance_flag ? (uint32_t)maintenance_flag : 0U);
574 void database::update_withdraw_permissions()
576 auto& permit_index = get_index_type<withdraw_permission_index>().indices().get<
by_expiration>();
577 while( !permit_index.empty() && permit_index.begin()->expiration <=
head_block_time() )
578 remove(*permit_index.begin());
581 void database::clear_expired_htlcs()
583 const auto& htlc_idx = get_index_type<htlc_index>().indices().get<
by_expiration>();
584 while ( htlc_idx.begin() != htlc_idx.end()
585 && htlc_idx.begin()->conditions.time_lock.expiration <=
head_block_time() )
606 auto& idx = get_index_type<ticket_index>().indices().get<by_next_update>();
607 while( !idx.empty() && idx.begin()->next_auto_update_time <=
head_block_time() )
639 if( ticket.
value == 0 )
646 delta_forever_value = ticket.
value - old_value;
654 delta_forever_value = ticket.
value;
656 delta_other_value = -old_value;
660 delta_other_value = ticket.
value - old_value;
665 modify( stat, [delta_inactive_amount,delta_forever_amount,delta_forever_value,
681 if( total_delta_pob != 0 || total_delta_inactive != 0 )
693 void database::update_credit_offers_and_deals()
698 const auto& offer_idx = get_index_type<credit_offer_index>().indices().get<by_auto_disable_time>();
699 auto offer_itr = offer_idx.lower_bound(
true );
700 auto offer_itr_end = offer_idx.upper_bound( boost::make_tuple(
true, head_time ) );
701 while( offer_itr != offer_itr_end )
711 const auto& deal_idx = get_index_type<credit_deal_index>().indices().get<by_latest_repay_time>();
712 const auto& deal_summary_idx = get_index_type<credit_deal_summary_index>().indices().get<by_offer_borrower>();
713 auto deal_itr_end = deal_idx.upper_bound( head_time );
714 for(
auto deal_itr = deal_idx.begin(); deal_itr != deal_itr_end; deal_itr = deal_idx.begin() )
726 auto summ_itr = deal_summary_idx.find( boost::make_tuple( deal.
offer_id, deal.
borrower ) );
727 if( summ_itr == deal_summary_idx.end() )
730 elog(
"Error: unable to find the credit deal summary object for credit deal ${d}",
share_type total_debt_amount
How much funds borrowed.
share_type total_core_pol
Total amount of core token in other tickets.
A credit offer is a fund that can be used by other accounts who provide certain collateral.
bool has_settlement() const
account_id_type offer_owner
Owner of the credit offer, redundant info for ease of querying.
#define GRAPHENE_COLLATERAL_RATIO_DENOM
asset_id_type asset_id
The asset this object belong to.
void modify(const T &obj, const Lambda &m)
share_type collateral_amount
How much funds in collateral.
ticket_type
Type of a ticket.
void adjust_balance(account_id_type account, asset delta)
Adjust a particular account's balance in a given asset by a delta.
condition_info conditions
database object to store HTLCs
contains properties that only apply to bitassets (market issued assets)
black_swan_response_type
Defines how a BitAsset would respond to black swan events.
share_type force_settled_volume
This is the volume of this asset which has been force-settled this maintanence interval.
void set_max_size(uint32_t s)
boost::rational< int32_t > ratio_type
time_point_sec head_block_time() const
A credit deal describes the details of a borrower's borrowing of funds from a credit offer...
Maintains global state information (committee_member list, current fees)This is an implementation det...
bitasset_options::black_swan_response_type get_black_swan_response_method() const
Get the effective black swan response method of this bitasset.
tracks debt and call price information
uint16_t force_settlement_offset_percent
This is the percent to adjust the feed price in the short's favor in the event of a forced settlement...
A credit deal summary describes the summary of a borrower's borrowing of funds from a credit offer...
processed_transaction push_proposal(const proposal_object &proposal)
Used to generate a useful error report when an exception is thrown.At each level in the stack where t...
share_type max_force_settlement_volume(share_type current_supply) const
Calculate the maximum force settlement volume per maintenance interval, given the current share suppl...
#define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT
const asset_dynamic_data_object & dynamic_data(const DB &db) const
account_id_type borrower
Borrower.
index & get_mutable_index()
share_type total_pol_value
Total value of tickets whose current type is not lock_forever.
bool enabled
Whether this offer is available.
time_point_sec settlement_date
generic_index< transaction_history_object, transaction_multi_index_type > transaction_index
provides stack-based nullable value similar to boost::optional
void auto_update(ticket_version version)
Update the ticket when it's time.
const asset_bitasset_data_object & bitasset_data(const DB &db) const
asset amount(share_type a) const
Helper function to get an asset object with the given amount in this asset's type.
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, bool mute_exceptions=false, bool skip_matching_settle_orders=false)
void update_median_feeds(time_point_sec current_time, time_point_sec next_maintenance_time)
share_type total_balance
Total size of the fund.
void set_max_size(size_t new_max_size)
#define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT
uint32_t push_applied_operation(const operation &op, bool is_virtual=true)
uint32_t get_slot_at_time(fc::time_point_sec when) const
bool feed_cer_updated
Track whether core exchange rate in current feed has updated.
object_id< SpaceID, TypeID > get_id() const
asset amount
The token type and amount in the ticket.
share_type total_pob_value
Total value of tickets whose current type is lock_forever.
void deposit_witness_pay(const witness_object &wit, share_type amount)
helper to handle witness pay
#define GRAPHENE_IRREVERSIBLE_THRESHOLD
The price struct stores asset prices in the BitShares system.
#define GRAPHENE_100_PERCENT
asset_id_type debt_asset
Asset type of the debt, redundant info for ease of querying.
void cancel_limit_order(const limit_order_object &order, bool create_virtual_op=true, bool skip_cancel_fee=false)
share_type total_core_inactive
Total amount of core token in inactive lock_forever tickets.
string symbol
Ticker symbol for this asset, i.e. "USD".
tracks bitassets scheduled for force settlement at some point in the future.
ticket_type current_type
The current type of the ticket.
#define FC_CAPTURE_AND_RETHROW(...)
price_feed_with_icr current_feed
This is the currently active price feed, calculated from median_feed and other parameters.
A credit deal expired without being fully repaid.
bool need_to_update_cer() const
Whether need to update core_exchange_rate in asset_object.
const node_property_object & get_node_properties() const
void update_bitasset_current_feed(const asset_bitasset_data_object &bitasset, bool skip_median_update=false)
share_type total_inactive
share_type debt_amount
How much funds borrowed.
ticket_status status
The status of the ticket.
time_point_sec next_maintenance_time
std::string to_detail_string(log_level ll=log_level::all) const
flat_set< object_id_type > removed_objects
tracks the parameters of an assetAll assets have a globally unique symbol name that controls how they...
safe< int64_t > share_type
const account_statistics_object & get_account_stats_by_owner(account_id_type owner) const
const call_order_object * find_least_collateralized_short(const asset_bitasset_data_object &bitasset, bool force_by_collateral_index) const
credit_offer_id_type offer_id
ID of the credit offer.
bitasset_options options
The tunable options for BitAssets are stored in this field.
generic_operation_result process_tickets()
flat_set< object_id_type > updated_objects
asset_id_type collateral_asset
Asset type of the collateral.
uint32_t fee_rate
Fee rate, the demominator is GRAPHENE_FEE_RATE_DENOM.
#define GRAPHENE_ASSERT(expr, exc_type, FORMAT,...)
asset_id_type settlement_asset_id() const
const dynamic_global_property_object & get_dynamic_global_properties() const
const object * find_object(const object_id_type &id) const
share_type current_supply
The number of shares currently in existence.
ticket_version
Version of a ticket.
account_id_type account
The account who owns the ticket.
bool asset_cer_updated
Track whether core_exchange_rate in corresponding asset_object has updated.
a ticket for governance voting
bool feed_is_expired_before_hf_615(time_point_sec current_time) const
share_type value
The current value of the ticket.
void cancel_settle_order(const force_settlement_object &order)
share_type total_core_pob
Total amount of core token in active lock_forever tickets.
#define GRAPHENE_MAX_UNDO_HISTORY
price_feed_with_icr median_feed
This is the median of values from the currently active feeds.
an offer to sell an amount of an asset at a specified exchange rate by a certain timeThe objects are ...
const global_property_object & get_global_properties() const
bool margin_call_params_equal(const price_feed &b) const
price core_exchange_rate
Price at which automatically exchanging this asset for CORE from fee pool occurs (used for paying fee...