Skip to content

Commit

Permalink
Merge pull request #2499 from bitshares/pr-2467-partial-gs
Browse files Browse the repository at this point in the history
Implement alternative black swan response methods
  • Loading branch information
abitmore authored Sep 29, 2021
2 parents 4020353 + 5ba086c commit 83411b4
Show file tree
Hide file tree
Showing 38 changed files with 8,629 additions and 1,302 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.mac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
name: Build and test in macOS
strategy:
matrix:
os: [macos-10.15, macos-11.0]
os: [macos-10.15, macos-11]
runs-on: ${{ matrix.os }}
steps:
- name: Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.ubuntu-debug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
name: Build and test in Debug mode
strategy:
matrix:
os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04 ]
os: [ ubuntu-18.04, ubuntu-20.04 ]
runs-on: ${{ matrix.os }}
services:
elasticsearch:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.ubuntu-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
name: Build and test in Release mode
strategy:
matrix:
os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04 ]
os: [ ubuntu-18.04, ubuntu-20.04 ]
runs-on: ${{ matrix.os }}
services:
elasticsearch:
Expand Down
21 changes: 13 additions & 8 deletions .github/workflows/build-and-test.win.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ jobs:
name: Build required 3rd-party libraries
runs-on: ubuntu-latest
steps:
# Get OS version to be used in cache key - see https://github.com/actions/cache/issues/543
- run: |
echo "OS_VERSION=`lsb_release -sr`" >> $GITHUB_ENV
- name: Load Cache
id: cache-libs
uses: actions/cache@v1
uses: actions/cache@v2
with:
path: libs
key: mingw64-libs-${{ env.BOOST_VERSION }}_${{ env.CURL_VERSION }}_${{ env.OPENSSL_VERSION }}_${{ env.ZLIB_VERSION }}
key: mingw64-libs-${{ env.OS_VERSION }}-${{ env.BOOST_VERSION }}_${{ env.CURL_VERSION }}_${{ env.OPENSSL_VERSION }}_${{ env.ZLIB_VERSION }}
- name: Install dependencies
if: steps.cache-libs.outputs.cache-hit != 'true'
run: |
Expand Down Expand Up @@ -113,11 +116,13 @@ jobs:
- uses: actions/checkout@v2
with:
submodules: recursive
- run: |
echo "OS_VERSION=`lsb_release -sr`" >> $GITHUB_ENV
- name: Load external libraries
uses: actions/cache@v1
uses: actions/cache@v2
with:
path: libs
key: mingw64-libs-${{ env.BOOST_VERSION }}_${{ env.CURL_VERSION }}_${{ env.OPENSSL_VERSION }}_${{ env.ZLIB_VERSION }}
key: mingw64-libs-${{ env.OS_VERSION }}-${{ env.BOOST_VERSION }}_${{ env.CURL_VERSION }}_${{ env.OPENSSL_VERSION }}_${{ env.ZLIB_VERSION }}
- name: Configure
run: |
LIBS="`pwd`/libs"
Expand All @@ -138,13 +143,13 @@ jobs:
-D GRAPHENE_DISABLE_UNITY_BUILD=ON \
..
- name: Load Cache
uses: actions/cache@v1
uses: actions/cache@v2
with:
path: ccache
key: ccache-mingw64-${{ github.ref }}-${{ github.sha }}
key: ccache-mingw64-${{ env.OS_VERSION }}-${{ github.ref }}-${{ github.sha }}
restore-keys: |
ccache-mingw64-${{ github.ref }}-
ccache-mingw64-
ccache-mingw64-${{ env.OS_VERSION }}-${{ github.ref }}-
ccache-mingw64-${{ env.OS_VERSION }}-
- name: Build
run: |
export CCACHE_DIR="$GITHUB_WORKSPACE/ccache"
Expand Down
430 changes: 309 additions & 121 deletions libraries/chain/asset_evaluator.cpp

Large diffs are not rendered by default.

50 changes: 27 additions & 23 deletions libraries/chain/asset_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ using namespace graphene::chain;

share_type asset_bitasset_data_object::max_force_settlement_volume(share_type current_supply) const
{
if( options.maximum_force_settlement_volume == 0 )
if( 0 == options.maximum_force_settlement_volume )
return 0;
if( options.maximum_force_settlement_volume == GRAPHENE_100_PERCENT )
if( GRAPHENE_100_PERCENT == options.maximum_force_settlement_volume )
return current_supply + force_settled_volume;

fc::uint128_t volume = current_supply.value;
Expand All @@ -49,66 +49,67 @@ void graphene::chain::asset_bitasset_data_object::update_median_feeds( time_poin
{
bool after_core_hardfork_1270 = ( next_maintenance_time > HARDFORK_CORE_1270_TIME ); // call price caching issue
current_feed_publication_time = current_time;
vector<std::reference_wrapper<const price_feed_with_icr>> current_feeds;
vector<std::reference_wrapper<const price_feed_with_icr>> effective_feeds;
// find feeds that were alive at current_time
for( const pair<account_id_type, pair<time_point_sec,price_feed_with_icr>>& f : feeds )
{
if( (current_time - f.second.first).to_seconds() < options.feed_lifetime_sec &&
f.second.first != time_point_sec() )
{
current_feeds.emplace_back(f.second.second);
effective_feeds.emplace_back(f.second.second);
current_feed_publication_time = std::min(current_feed_publication_time, f.second.first);
}
}

// If there are no valid feeds, or the number available is less than the minimum to calculate a median...
if( current_feeds.size() < options.minimum_feeds )
if( effective_feeds.size() < options.minimum_feeds )
{
//... 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 = price_feed_with_icr();
median_feed = price_feed_with_icr();
if( after_core_hardfork_1270 )
{
// update data derived from MCR, ICR and etc
refresh_cache();
}
return;
}
if( current_feeds.size() == 1 )

if( 1u == effective_feeds.size() )
{
if( current_feed.core_exchange_rate != current_feeds.front().get().core_exchange_rate )
if( median_feed.core_exchange_rate != effective_feeds.front().get().core_exchange_rate )
feed_cer_updated = true;
current_feed = current_feeds.front();
median_feed = effective_feeds.front();
// Note: perhaps can defer updating current_maintenance_collateralization for better performance
if( after_core_hardfork_1270 )
{
const auto& exts = options.extensions.value;
if( exts.maintenance_collateral_ratio.valid() )
current_feed.maintenance_collateral_ratio = *exts.maintenance_collateral_ratio;
median_feed.maintenance_collateral_ratio = *exts.maintenance_collateral_ratio;
if( exts.maximum_short_squeeze_ratio.valid() )
current_feed.maximum_short_squeeze_ratio = *exts.maximum_short_squeeze_ratio;
median_feed.maximum_short_squeeze_ratio = *exts.maximum_short_squeeze_ratio;
if( exts.initial_collateral_ratio.valid() )
current_feed.initial_collateral_ratio = *exts.initial_collateral_ratio;
median_feed.initial_collateral_ratio = *exts.initial_collateral_ratio;
// update data derived from MCR, ICR and etc
refresh_cache();
}
return;
}

// *** Begin Median Calculations ***
price_feed_with_icr median_feed;
const auto median_itr = current_feeds.begin() + current_feeds.size() / 2;
price_feed_with_icr tmp_median_feed;
const auto median_itr = effective_feeds.begin() + ( effective_feeds.size() / 2 );
#define CALCULATE_MEDIAN_VALUE(r, data, field_name) \
std::nth_element( current_feeds.begin(), median_itr, current_feeds.end(), \
std::nth_element( effective_feeds.begin(), median_itr, effective_feeds.end(), \
[](const price_feed_with_icr& a, const price_feed_with_icr& b) { \
return a.field_name < b.field_name; \
}); \
median_feed.field_name = median_itr->get().field_name;
tmp_median_feed.field_name = median_itr->get().field_name;

#define CHECK_AND_CALCULATE_MEDIAN_VALUE(r, data, field_name) \
if( options.extensions.value.field_name.valid() ) { \
median_feed.field_name = *options.extensions.value.field_name; \
tmp_median_feed.field_name = *options.extensions.value.field_name; \
} else { \
CALCULATE_MEDIAN_VALUE(r, data, field_name); \
}
Expand All @@ -120,9 +121,9 @@ void graphene::chain::asset_bitasset_data_object::update_median_feeds( time_poin
#undef CALCULATE_MEDIAN_VALUE
// *** End Median Calculations ***

if( current_feed.core_exchange_rate != median_feed.core_exchange_rate )
if( median_feed.core_exchange_rate != tmp_median_feed.core_exchange_rate )
feed_cer_updated = true;
current_feed = median_feed;
median_feed = tmp_median_feed;
// Note: perhaps can defer updating current_maintenance_collateralization for better performance
if( after_core_hardfork_1270 )
{
Expand All @@ -133,14 +134,14 @@ void graphene::chain::asset_bitasset_data_object::update_median_feeds( time_poin

void asset_bitasset_data_object::refresh_cache()
{
current_maintenance_collateralization = current_feed.maintenance_collateralization();
if( current_feed.initial_collateral_ratio > current_feed.maintenance_collateral_ratio ) // if ICR is above MCR
current_initial_collateralization = current_feed.calculate_initial_collateralization();
current_maintenance_collateralization = median_feed.maintenance_collateralization();
if( median_feed.initial_collateral_ratio > median_feed.maintenance_collateral_ratio ) // if ICR is above MCR
current_initial_collateralization = median_feed.get_initial_collateralization();
else // if ICR is not above MCR
current_initial_collateralization = current_maintenance_collateralization;
}

price price_feed_with_icr::calculate_initial_collateralization()const
price price_feed_with_icr::get_initial_collateralization()const
{
if( settlement_price.is_null() )
return price();
Expand Down Expand Up @@ -223,6 +224,7 @@ FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::asset_dynamic_data_object, (gra
FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::asset_bitasset_data_object, (graphene::db::object),
(asset_id)
(feeds)
(median_feed)
(current_feed)
(current_feed_publication_time)
(current_maintenance_collateralization)
Expand All @@ -232,6 +234,8 @@ FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::asset_bitasset_data_object, (gr
(is_prediction_market)
(settlement_price)
(settlement_fund)
(individual_settlement_debt)
(individual_settlement_fund)
(asset_cer_updated)
(feed_cer_updated)
)
Expand Down
46 changes: 46 additions & 0 deletions libraries/chain/db_getter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@

#include <graphene/chain/database.hpp>

#include <graphene/chain/hardfork.hpp>

#include <graphene/chain/asset_object.hpp>
#include <graphene/chain/chain_property_object.hpp>
#include <graphene/chain/global_property_object.hpp>
#include <graphene/chain/market_object.hpp>
#include <graphene/chain/custom_authority_object.hpp>

namespace graphene { namespace chain {
Expand Down Expand Up @@ -146,4 +149,47 @@ const witness_schedule_object& database::get_witness_schedule_object()const
return *_p_witness_schedule_obj;
}

const limit_order_object* database::find_settled_debt_order( const asset_id_type& a )const
{
const auto& limit_index = get_index_type<limit_order_index>().indices().get<by_is_settled_debt>();
auto itr = limit_index.lower_bound( std::make_tuple( true, a ) );
if( itr != limit_index.end() && itr->receive_asset_id() == a )
return &(*itr);
return nullptr;
}

const call_order_object* database::find_least_collateralized_short( const asset_bitasset_data_object& bitasset,
bool force_by_collateral_index )const
{
bool find_by_collateral = true;
if( !force_by_collateral_index )
// core-1270 hard fork : call price caching issue
find_by_collateral = ( get_dynamic_global_properties().next_maintenance_time > HARDFORK_CORE_1270_TIME );

const call_order_object* call_ptr = nullptr; // place holder

auto call_min = price::min( bitasset.options.short_backing_asset, bitasset.asset_id );

if( !find_by_collateral ) // before core-1270 hard fork, check with call_price
{
const auto& call_price_index = get_index_type<call_order_index>().indices().get<by_price>();
auto call_itr = call_price_index.lower_bound( call_min );
if( call_itr != call_price_index.end() ) // found a call order
call_ptr = &(*call_itr);
}
else // after core-1270 hard fork, check with collateralization
{
// Note: it is safe to check here even if there is no call order due to individual settlements
const auto& call_collateral_index = get_index_type<call_order_index>().indices().get<by_collateral>();
auto call_itr = call_collateral_index.lower_bound( call_min );
if( call_itr != call_collateral_index.end() ) // found a call order
call_ptr = &(*call_itr);
}
if( !call_ptr ) // not found
return nullptr;
if( call_ptr->debt_type() != bitasset.asset_id ) // call order is of another asset
return nullptr;
return call_ptr;
}

} }
26 changes: 7 additions & 19 deletions libraries/chain/db_maint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -991,19 +991,11 @@ void process_hf_2103( database& db )
}
}

void update_median_feeds(database& db)
static void update_bitasset_current_feeds(database& db)
{
time_point_sec head_time = db.head_block_time();
time_point_sec next_maint_time = db.get_dynamic_global_properties().next_maintenance_time;

const auto update_bitasset = [head_time, next_maint_time]( asset_bitasset_data_object &o )
for( const auto& bitasset : db.get_index_type<asset_bitasset_data_index>().indices() )
{
o.update_median_feeds( head_time, next_maint_time );
};

for( const auto& d : db.get_index_type<asset_bitasset_data_index>().indices() )
{
db.modify( d, update_bitasset );
db.update_bitasset_current_feed( bitasset );
}
}

Expand All @@ -1027,8 +1019,6 @@ void update_median_feeds(database& db)
// feeds were found.
void process_hf_868_890( database& db, bool skip_check_call_orders )
{
const auto next_maint_time = db.get_dynamic_global_properties().next_maintenance_time;
const auto head_time = db.head_block_time();
// for each market issued asset
const auto& asset_idx = db.get_index_type<asset_index>().indices().get<by_type>();
for( auto asset_itr = asset_idx.lower_bound(true); asset_itr != asset_idx.end(); ++asset_itr )
Expand Down Expand Up @@ -1074,11 +1064,9 @@ void process_hf_868_890( database& db, bool skip_check_call_orders )
} // end loop of each feed

// always update the median feed due to https://github.com/bitshares/bitshares-core/issues/890
db.modify( bitasset_data, [head_time,next_maint_time]( asset_bitasset_data_object &obj ) {
obj.update_median_feeds( head_time, next_maint_time );
// NOTE: Normally we should call check_call_orders() after called update_median_feeds(), but for
// mainnet actually check_call_orders() would do nothing, so we skipped it for better performance.
});
db.update_bitasset_current_feed( bitasset_data );
// NOTE: Normally we should call check_call_orders() after called update_bitasset_current_feed(), but for
// mainnet actually check_call_orders() would do nothing, so we skipped it for better performance.

} // for each market issued asset
}
Expand Down Expand Up @@ -1497,7 +1485,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
if( to_update_and_match_call_orders_for_hf_1270 )
{
update_call_orders_hf_1270(*this);
update_median_feeds(*this);
update_bitasset_current_feeds(*this);
match_call_orders(*this);
}

Expand Down
Loading

0 comments on commit 83411b4

Please sign in to comment.