Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix market ticker volume underflow issue #1885

Merged
merged 2 commits into from
Aug 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion libraries/plugins/market_history/market_history_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,8 @@ void market_history_plugin_impl::update_market_histories( const signed_block& b
}
else // if all data are rolled out
{
if( last_min_his_id != _meta->rolling_min_order_his_id ) // if rolled out some
if( !_meta->skip_min_order_his_id
|| last_min_his_id != _meta->rolling_min_order_his_id ) // if rolled out some
{
db.modify( *_meta, [&]( market_ticker_meta_object& mtm ) {
mtm.rolling_min_order_his_id = last_min_his_id;
Expand Down
118 changes: 118 additions & 0 deletions tests/tests/settle_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1501,4 +1501,122 @@ BOOST_AUTO_TEST_CASE( global_settle_rounding_test_after_hf_184 )
} FC_LOG_AND_RETHROW()
}

/**
* Test case to reproduce https://github.com/bitshares/bitshares-core/issues/1883.
* When there is only one fill_order object in the ticker rolling buffer, it should only be rolled out once.
*/
BOOST_AUTO_TEST_CASE( global_settle_ticker_test )
{
try {
generate_block();

const auto& meta_idx = db.get_index_type<simple_index<graphene::market_history::market_ticker_meta_object>>();
const auto& ticker_idx = db.get_index_type<graphene::market_history::market_ticker_index>().indices();
const auto& history_idx = db.get_index_type<graphene::market_history::history_index>().indices();

BOOST_CHECK_EQUAL( meta_idx.size(), 0 );
BOOST_CHECK_EQUAL( ticker_idx.size(), 0 );
BOOST_CHECK_EQUAL( history_idx.size(), 0 );

ACTORS((judge)(alice));

const auto& pmark = create_prediction_market("PMARK", judge_id);
const auto& core = asset_id_type()(db);

int64_t init_balance(1000000);
transfer(committee_account, judge_id, asset(init_balance));
transfer(committee_account, alice_id, asset(init_balance));

BOOST_TEST_MESSAGE( "Open position with equal collateral" );
borrow( alice, pmark.amount(1000), asset(1000) );

BOOST_TEST_MESSAGE( "Globally settling" );
force_global_settle( pmark, pmark.amount(1) / core.amount(1) );

generate_block();
fc::usleep(fc::milliseconds(200)); // sleep a while to execute callback in another thread

{
BOOST_CHECK_EQUAL( meta_idx.size(), 1 );
BOOST_CHECK_EQUAL( ticker_idx.size(), 1 );
BOOST_CHECK_EQUAL( history_idx.size(), 1 );

const auto& meta = *meta_idx.begin();
const auto& tick = *ticker_idx.begin();
const auto& hist = *history_idx.begin();

BOOST_CHECK( meta.rolling_min_order_his_id == hist.id );
BOOST_CHECK( meta.skip_min_order_his_id == false );

BOOST_CHECK( tick.base_volume == 1000 );
BOOST_CHECK( tick.quote_volume == 1000 );
}

generate_blocks( db.head_block_time() + 86000 ); // less than a day
fc::usleep(fc::milliseconds(200)); // sleep a while to execute callback in another thread

// nothing changes
{
BOOST_CHECK_EQUAL( meta_idx.size(), 1 );
BOOST_CHECK_EQUAL( ticker_idx.size(), 1 );
BOOST_CHECK_EQUAL( history_idx.size(), 1 );

const auto& meta = *meta_idx.begin();
const auto& tick = *ticker_idx.begin();
const auto& hist = *history_idx.begin();

BOOST_CHECK( meta.rolling_min_order_his_id == hist.id );
BOOST_CHECK( meta.skip_min_order_his_id == false );

BOOST_CHECK( tick.base_volume == 1000 );
BOOST_CHECK( tick.quote_volume == 1000 );
}

generate_blocks( db.head_block_time() + 4000 ); // now more than 24 hours
fc::usleep(fc::milliseconds(200)); // sleep a while to execute callback in another thread

// the history is rolled out, new 24h volume should be 0
{
BOOST_CHECK_EQUAL( meta_idx.size(), 1 );
BOOST_CHECK_EQUAL( ticker_idx.size(), 1 );
BOOST_CHECK_EQUAL( history_idx.size(), 1 );

const auto& meta = *meta_idx.begin();
const auto& tick = *ticker_idx.begin();
const auto& hist = *history_idx.begin();

BOOST_CHECK( meta.rolling_min_order_his_id == hist.id );
BOOST_CHECK( meta.skip_min_order_his_id == true ); // the order should be skipped on next roll

BOOST_CHECK( tick.base_volume == 0 );
BOOST_CHECK( tick.quote_volume == 0 );
}

generate_block();
fc::usleep(fc::milliseconds(200)); // sleep a while to execute callback in another thread

// nothing changes
{
BOOST_CHECK_EQUAL( meta_idx.size(), 1 );
BOOST_CHECK_EQUAL( ticker_idx.size(), 1 );
BOOST_CHECK_EQUAL( history_idx.size(), 1 );

const auto& meta = *meta_idx.begin();
const auto& tick = *ticker_idx.begin();
const auto& hist = *history_idx.begin();

BOOST_CHECK( meta.rolling_min_order_his_id == hist.id );
BOOST_CHECK( meta.skip_min_order_his_id == true );

BOOST_CHECK( tick.base_volume == 0 );
BOOST_CHECK( tick.quote_volume == 0 );
}


} catch( const fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}

BOOST_AUTO_TEST_SUITE_END()