From 61d85ded0c3d44e919be0a80902362a16c023b78 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Wed, 20 Feb 2019 18:31:44 -0600 Subject: [PATCH 001/127] Progress #1604: Basic implementation Define and implement the limit_order_update_operation. Still needs testing. --- .../graphene/chain/market_evaluator.hpp | 13 ++++- .../graphene/chain/protocol/market.hpp | 31 +++++++++++ libraries/chain/market_evaluator.cpp | 52 +++++++++++++++++++ libraries/chain/protocol/market.cpp | 15 +++++- 4 files changed, 109 insertions(+), 2 deletions(-) diff --git a/libraries/chain/include/graphene/chain/market_evaluator.hpp b/libraries/chain/include/graphene/chain/market_evaluator.hpp index 96a4ac07ed..04ced229c3 100644 --- a/libraries/chain/include/graphene/chain/market_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/market_evaluator.hpp @@ -63,6 +63,17 @@ namespace graphene { namespace chain { const asset_object* _receive_asset = nullptr; }; + class limit_order_update_evaluator : public evaluator + { + public: + using operation_type = limit_order_update_operation; + + void_result do_evaluate(const limit_order_update_operation& o); + void_result do_apply(const limit_order_update_operation& o); + + const limit_order_object* _order = nullptr; + }; + class limit_order_cancel_evaluator : public evaluator { public: @@ -71,7 +82,7 @@ namespace graphene { namespace chain { void_result do_evaluate( const limit_order_cancel_operation& o ); asset do_apply( const limit_order_cancel_operation& o ); - const limit_order_object* _order; + const limit_order_object* _order = nullptr; }; class call_order_update_evaluator : public evaluator diff --git a/libraries/chain/include/graphene/chain/protocol/market.hpp b/libraries/chain/include/graphene/chain/protocol/market.hpp index 55438d7cc5..b5b58a89af 100644 --- a/libraries/chain/include/graphene/chain/protocol/market.hpp +++ b/libraries/chain/include/graphene/chain/protocol/market.hpp @@ -73,6 +73,35 @@ namespace graphene { namespace chain { price get_price()const { return amount_to_sell / min_to_receive; } }; + /** + * @ingroup operations + * Used to update an existing limit order. + * + * Charges a higher fee if @ref delta_amount_to_sell is set, as this requires updating + * the account balance as well as the order object. + */ + struct limit_order_update_operation : public base_operation + { + struct fee_parameters_type { + uint64_t price_fee = GRAPHENE_BLOCKCHAIN_PRECISION / 2; + uint64_t amount_fee = GRAPHENE_BLOCKCHAIN_PRECISION; + }; + + asset fee; + account_id_type seller; + limit_order_id_type order; + optional new_price; + optional delta_amount_to_sell; + optional new_expiration; + + extensions_type extensions; + + account_id_type fee_payer() { return seller; } + void validate() const; + share_type calculate_fee(const fee_parameters_type& k) const { + return delta_amount_to_sell? k.amount_fee : k.price_fee; + } + }; /** * @ingroup operations @@ -219,6 +248,7 @@ namespace graphene { namespace chain { } } // graphene::chain FC_REFLECT( graphene::chain::limit_order_create_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::limit_order_update_operation::fee_parameters_type, (price_fee)(amount_fee) ) FC_REFLECT( graphene::chain::limit_order_cancel_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::call_order_update_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::bid_collateral_operation::fee_parameters_type, (fee) ) @@ -230,6 +260,7 @@ FC_REFLECT( graphene::chain::call_order_update_operation::options_type, (target_ FC_REFLECT_TYPENAME( graphene::chain::call_order_update_operation::extensions_type ) FC_REFLECT( graphene::chain::limit_order_create_operation,(fee)(seller)(amount_to_sell)(min_to_receive)(expiration)(fill_or_kill)(extensions)) +FC_REFLECT( graphene::chain::limit_order_update_operation,(fee)(seller)(order)(new_price)(delta_amount_to_sell)(new_expiration)(extensions)) FC_REFLECT( graphene::chain::limit_order_cancel_operation,(fee)(fee_paying_account)(order)(extensions) ) FC_REFLECT( graphene::chain::call_order_update_operation, (fee)(funding_account)(delta_collateral)(delta_debt)(extensions) ) FC_REFLECT( graphene::chain::fill_order_operation, (fee)(order_id)(account_id)(pays)(receives)(fill_price)(is_maker) ) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 270c7d3fc6..7040fc9a47 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -124,6 +124,58 @@ object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_o return order_id; } FC_CAPTURE_AND_RETHROW( (op) ) } +void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_operation& o) +{ try { + const database& d = db(); + _order = &o.order(d); + + // Check this is my order + FC_ASSERT(o.seller == _order->seller, "Cannot update someone else's order"); + + // Check new price is compatible + if (o.new_price) + FC_ASSERT(o.new_price->base.asset_id == _order->sell_price.base.asset_id && + o.new_price->quote.asset_id == _order->sell_price.quote.asset_id, + "Cannot update limit order with incompatible price"); + + // Check delta asset is compatible + if (o.delta_amount_to_sell) { + const auto& delta = *o.delta_amount_to_sell; + FC_ASSERT(delta.asset_id == _order->sell_price.base.asset_id, + "Cannot update limit order with incompatible asset"); + if (delta.amount > 0) + FC_ASSERT(d.get_balance(o.seller, delta.asset_id) > delta, + "Insufficient balance to increase order amount"); + else + FC_ASSERT(_order->for_sale > -delta.amount, + "Cannot deduct more from order than order contains"); + } + + // Check expiration is in the future + if (o.new_expiration) + FC_ASSERT(*o.new_expiration >= d.head_block_time(), + "Cannot update limit order with past expiration"); +} FC_CAPTURE_AND_RETHROW((o)) } + +void_result limit_order_update_evaluator::do_apply(const limit_order_update_operation& o) +{ try { + database& d = db(); + + // Adjust account balance + if (o.delta_amount_to_sell) + d.adjust_balance(o.seller, *o.delta_amount_to_sell); + + // Update order + d.modify(*_order, [&o](limit_order_object& loo) { + if (o.new_price) + loo.sell_price = *o.new_price; + if (o.delta_amount_to_sell) + loo.for_sale += o.delta_amount_to_sell->amount; + if (o.new_expiration) + loo.expiration = *o.new_expiration; + }); +} FC_CAPTURE_AND_RETHROW((o)) } + void_result limit_order_cancel_evaluator::do_evaluate(const limit_order_cancel_operation& o) { try { database& d = db(); diff --git a/libraries/chain/protocol/market.cpp b/libraries/chain/protocol/market.cpp index fd12fa4e7d..31cb800622 100644 --- a/libraries/chain/protocol/market.cpp +++ b/libraries/chain/protocol/market.cpp @@ -33,6 +33,17 @@ void limit_order_create_operation::validate()const FC_ASSERT( min_to_receive.amount > 0 ); } +void limit_order_update_operation::validate() const +{ + FC_ASSERT(fee.amount >= 0, "Fee must not be negative"); + FC_ASSERT(new_price || delta_amount_to_sell || new_expiration, + "Cannot update limit order if nothing is specified to update"); + if (new_price) + new_price->validate(); + if (delta_amount_to_sell) + FC_ASSERT(delta_amount_to_sell->amount != 0, "Cannot change limit order amount by zero"); +} + void limit_order_cancel_operation::validate()const { FC_ASSERT( fee.amount >= 0 ); @@ -54,4 +65,6 @@ void bid_collateral_operation::validate()const FC_ASSERT( debt_covered.amount == 0 || (debt_covered.amount > 0 && additional_collateral.amount > 0) ); } FC_CAPTURE_AND_RETHROW((*this)) } -} } // graphene::chain +} + +} // graphene::chain From f6bbe4ba6065f6329a2fff8c3879139d2789a06b Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Thu, 21 Feb 2019 18:21:37 -0600 Subject: [PATCH 002/127] Progress #1604: Tests and Fixes Some major facepalms in here... haha! but overall, it's looking good. --- libraries/chain/db_init.cpp | 1 + libraries/chain/db_notify.cpp | 4 + .../graphene/chain/market_evaluator.hpp | 2 +- .../graphene/chain/protocol/market.hpp | 2 +- .../graphene/chain/protocol/operations.hpp | 3 +- libraries/chain/market_evaluator.cpp | 71 ++++++++------ libraries/chain/protocol/market.cpp | 10 +- tests/common/database_fixture.cpp | 31 ++++++- tests/common/database_fixture.hpp | 8 ++ tests/tests/operation_tests.cpp | 92 +++++++++++++++++++ 10 files changed, 183 insertions(+), 41 deletions(-) diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 884a7b3c91..dd68b87af6 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -147,6 +147,7 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); + register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index 39ff36ff4f..7d0854d82f 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -43,6 +43,10 @@ struct get_impacted_account_visitor { _impacted.insert( op.fee_payer() ); // seller } + void operator()(const limit_order_update_operation& op) + { + _impacted.insert(op.fee_payer()); // seller + } void operator()( const limit_order_cancel_operation& op ) { _impacted.insert( op.fee_payer() ); // fee_paying_account diff --git a/libraries/chain/include/graphene/chain/market_evaluator.hpp b/libraries/chain/include/graphene/chain/market_evaluator.hpp index 04ced229c3..5d994bb7bf 100644 --- a/libraries/chain/include/graphene/chain/market_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/market_evaluator.hpp @@ -63,7 +63,7 @@ namespace graphene { namespace chain { const asset_object* _receive_asset = nullptr; }; - class limit_order_update_evaluator : public evaluator + class limit_order_update_evaluator : public evaluator { public: using operation_type = limit_order_update_operation; diff --git a/libraries/chain/include/graphene/chain/protocol/market.hpp b/libraries/chain/include/graphene/chain/protocol/market.hpp index b5b58a89af..abb1dee59a 100644 --- a/libraries/chain/include/graphene/chain/protocol/market.hpp +++ b/libraries/chain/include/graphene/chain/protocol/market.hpp @@ -96,7 +96,7 @@ namespace graphene { namespace chain { extensions_type extensions; - account_id_type fee_payer() { return seller; } + account_id_type fee_payer() const { return seller; } void validate() const; share_type calculate_fee(const fee_parameters_type& k) const { return delta_amount_to_sell? k.amount_fee : k.price_fee; diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index de2cfa7fd9..2a88dd816e 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -95,7 +95,8 @@ namespace graphene { namespace chain { bid_collateral_operation, execute_bid_operation, // VIRTUAL asset_claim_pool_operation, - asset_update_issuer_operation + asset_update_issuer_operation, + limit_order_update_operation > operation; /// @} // operations group diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 7040fc9a47..e16cda398a 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -126,35 +126,37 @@ object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_o void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_operation& o) { try { - const database& d = db(); - _order = &o.order(d); - - // Check this is my order - FC_ASSERT(o.seller == _order->seller, "Cannot update someone else's order"); - - // Check new price is compatible - if (o.new_price) - FC_ASSERT(o.new_price->base.asset_id == _order->sell_price.base.asset_id && - o.new_price->quote.asset_id == _order->sell_price.quote.asset_id, - "Cannot update limit order with incompatible price"); - - // Check delta asset is compatible - if (o.delta_amount_to_sell) { - const auto& delta = *o.delta_amount_to_sell; - FC_ASSERT(delta.asset_id == _order->sell_price.base.asset_id, - "Cannot update limit order with incompatible asset"); - if (delta.amount > 0) - FC_ASSERT(d.get_balance(o.seller, delta.asset_id) > delta, - "Insufficient balance to increase order amount"); - else - FC_ASSERT(_order->for_sale > -delta.amount, - "Cannot deduct more from order than order contains"); - } - - // Check expiration is in the future - if (o.new_expiration) - FC_ASSERT(*o.new_expiration >= d.head_block_time(), - "Cannot update limit order with past expiration"); + const database& d = db(); + _order = &o.order(d); + + // Check this is my order + FC_ASSERT(o.seller == _order->seller, "Cannot update someone else's order"); + + // Check new price is compatible + if (o.new_price) + FC_ASSERT(o.new_price->base.asset_id == _order->sell_price.base.asset_id && + o.new_price->quote.asset_id == _order->sell_price.quote.asset_id, + "Cannot update limit order with incompatible price"); + + // Check delta asset is compatible + if (o.delta_amount_to_sell) { + const auto& delta = *o.delta_amount_to_sell; + FC_ASSERT(delta.asset_id == _order->sell_price.base.asset_id, + "Cannot update limit order with incompatible asset"); + if (delta.amount > 0) + FC_ASSERT(d.get_balance(o.seller, delta.asset_id) > delta, + "Insufficient balance to increase order amount"); + else + FC_ASSERT(_order->for_sale > -delta.amount, + "Cannot deduct more from order than order contains"); + } + + // Check expiration is in the future + if (o.new_expiration) + FC_ASSERT(*o.new_expiration >= d.head_block_time(), + "Cannot update limit order with past expiration"); + + return void_result(); } FC_CAPTURE_AND_RETHROW((o)) } void_result limit_order_update_evaluator::do_apply(const limit_order_update_operation& o) @@ -162,8 +164,13 @@ void_result limit_order_update_evaluator::do_apply(const limit_order_update_oper database& d = db(); // Adjust account balance + const auto& seller_stats = o.seller(d).statistics(d); + if (o.delta_amount_to_sell && o.delta_amount_to_sell->asset_id == asset_id_type()) + db().modify(seller_stats, [&o](account_statistics_object& bal) { + bal.total_core_in_orders += o.delta_amount_to_sell->amount; + }); if (o.delta_amount_to_sell) - d.adjust_balance(o.seller, *o.delta_amount_to_sell); + d.adjust_balance(o.seller, -*o.delta_amount_to_sell); // Update order d.modify(*_order, [&o](limit_order_object& loo) { @@ -174,6 +181,10 @@ void_result limit_order_update_evaluator::do_apply(const limit_order_update_oper if (o.new_expiration) loo.expiration = *o.new_expiration; }); + + // TODO: check if order is at front of book and price moved in favor of buyer; if so, trigger matching + + return void_result(); } FC_CAPTURE_AND_RETHROW((o)) } void_result limit_order_cancel_evaluator::do_evaluate(const limit_order_cancel_operation& o) diff --git a/libraries/chain/protocol/market.cpp b/libraries/chain/protocol/market.cpp index 31cb800622..d368eb4a0b 100644 --- a/libraries/chain/protocol/market.cpp +++ b/libraries/chain/protocol/market.cpp @@ -34,15 +34,15 @@ void limit_order_create_operation::validate()const } void limit_order_update_operation::validate() const -{ +{ try { FC_ASSERT(fee.amount >= 0, "Fee must not be negative"); FC_ASSERT(new_price || delta_amount_to_sell || new_expiration, - "Cannot update limit order if nothing is specified to update"); + "Cannot update limit order if nothing is specified to update"); if (new_price) - new_price->validate(); + new_price->validate(); if (delta_amount_to_sell) - FC_ASSERT(delta_amount_to_sell->amount != 0, "Cannot change limit order amount by zero"); -} + FC_ASSERT(delta_amount_to_sell->amount != 0, "Cannot change limit order amount by zero"); +} FC_CAPTURE_AND_RETHROW((*this)) } void limit_order_cancel_operation::validate()const { diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 5b0b994f97..df1c18a1bd 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -751,7 +751,7 @@ const limit_order_object* database_fixture::create_sell_order( const account_obj buy_order.amount_to_sell = amount; buy_order.min_to_receive = recv; buy_order.expiration = order_expiration; - trx.operations.push_back(buy_order); + trx.operations = {buy_order}; for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op, fee_core_exchange_rate); trx.validate(); auto processed = PUSH_TX(db, trx, ~0); @@ -760,17 +760,42 @@ const limit_order_object* database_fixture::create_sell_order( const account_obj return db.find( processed.operation_results[0].get() ); } +void database_fixture::update_limit_order(const limit_order_object& order, + fc::optional new_price, + fc::optional delta_amount, + fc::optional new_expiration) { + limit_order_update_operation update_order; + update_order.seller = order.seller; + update_order.order = order.id; + update_order.new_price = new_price; + update_order.delta_amount_to_sell = delta_amount; + update_order.new_expiration = new_expiration; + trx.operations = {update_order}; + for(auto& op : trx.operations) db.current_fee_schedule().set_fee(op); + trx.validate(); + auto processed = PUSH_TX(db, trx, ~0); + trx.operations.clear(); + verify_asset_supplies(db); +} + +void database_fixture::update_limit_order(limit_order_id_type order_id, + fc::optional new_price, + fc::optional delta_amount, + fc::optional new_expiration) { + update_limit_order(order_id(db), new_price, delta_amount, new_expiration); +} + asset database_fixture::cancel_limit_order( const limit_order_object& order ) { limit_order_cancel_operation cancel_order; cancel_order.fee_paying_account = order.seller; cancel_order.order = order.id; - trx.operations.push_back(cancel_order); + trx.operations = {cancel_order}; for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); trx.validate(); auto processed = PUSH_TX(db, trx, ~0); trx.operations.clear(); - verify_asset_supplies(db); + verify_asset_supplies(db); return processed.operation_results[0].get(); } diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index dac219d69e..f76bbcea4d 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -331,6 +331,14 @@ struct database_fixture { const limit_order_object* create_sell_order( const account_object& user, const asset& amount, const asset& recv, const time_point_sec order_expiration = time_point_sec::maximum(), const price& fee_core_exchange_rate = price::unit_price() ); + void update_limit_order(const limit_order_object& order, + fc::optional new_price = {}, + fc::optional delta_amount = {}, + fc::optional new_expiration = {}); + void update_limit_order(limit_order_id_type order_id, + fc::optional new_price = {}, + fc::optional delta_amount = {}, + fc::optional new_expiration = {}); asset cancel_limit_order( const limit_order_object& order ); void transfer( account_id_type from, account_id_type to, const asset& amount, const asset& fee = asset() ); void transfer( const account_object& from, const account_object& to, const asset& amount, const asset& fee = asset() ); diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index b2edab15ad..5176b4f414 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -80,6 +80,98 @@ BOOST_AUTO_TEST_CASE( feed_limit_logic_test ) } } +BOOST_AUTO_TEST_CASE(limit_order_update_test) +{ + try { + ACTORS((nathan)); + const auto& bitusd = create_bitasset("USDBIT", nathan.id); + const auto& munee = create_user_issued_asset("MUNEE"); + const auto& core = asset_id_type()(db); + + update_feed_producers(bitusd, {nathan_id}); + price_feed current_feed; + current_feed.settlement_price = bitusd.amount(200) / core.amount(100); + current_feed.maintenance_collateral_ratio = 1750; + publish_feed(bitusd, nathan, current_feed); + + transfer(committee_account, nathan_id, asset(1500)); + issue_uia(nathan, munee.amount(100)); + borrow(nathan_id, bitusd.amount(100), asset(500)); + + auto expiration = db.head_block_time() + 1000; + auto sell_price = price(asset(500), bitusd.amount(1000)); + limit_order_id_type order_id = create_sell_order(nathan, asset(500), bitusd.amount(1000), expiration)->id; + BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 500); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + + // Cannot update order without changing anything + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id), fc::assert_exception); + // Cannot update order to use inverted price assets + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(bitusd.amount(2), asset(1))), fc::assert_exception); + // Cannot update order to use different assets + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(bitusd.amount(2), munee.amount(1))), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(munee.amount(2), bitusd.amount(1))), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(2), munee.amount(1))), fc::assert_exception); + // Cannot update order to expire in the past + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, db.head_block_time() - 10), fc::assert_exception); + // Cannot update order to add more funds than seller has + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(501)), fc::assert_exception); + // Cannot update order to remove more funds than order has + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(-501)), fc::assert_exception); + // Cannot update order to remove all funds in order + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(-500)), fc::assert_exception); + // Cannot update order to add or remove different kind of funds + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, bitusd.amount(50)), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, bitusd.amount(-50)), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, munee.amount(50)), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, munee.amount(-50)), fc::assert_exception); + + // Try changing price + sell_price.base = asset(501); + update_limit_order(order_id, sell_price); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + sell_price.base = asset(500); + sell_price.quote = bitusd.amount(999); + update_limit_order(order_id, sell_price); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + sell_price.quote = bitusd.amount(1000); + update_limit_order(order_id, sell_price); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + + // Try changing expiration + expiration += 50; + update_limit_order(order_id, {}, {}, expiration); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + expiration -= 100; + update_limit_order(order_id, {}, {}, expiration); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + + // Try adding funds + update_limit_order(order_id, {}, asset(50)); + BOOST_REQUIRE_EQUAL(order_id(db).amount_for_sale().amount.value, 550); + BOOST_REQUIRE_EQUAL(db.get_balance(nathan_id, core.get_id()).amount.value, 450); + + // Try removing funds + update_limit_order(order_id, {}, asset(-100)); + BOOST_REQUIRE_EQUAL(order_id(db).amount_for_sale().amount.value, 450); + BOOST_REQUIRE_EQUAL(db.get_balance(nathan_id, core.get_id()).amount.value, 550); + + // Try changing everything at once + expiration += 50; + sell_price.base = asset(499); + sell_price.quote = bitusd.amount(1001); + update_limit_order(order_id, sell_price, 50, expiration); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + BOOST_REQUIRE_EQUAL(order_id(db).amount_for_sale().amount.value, 500); + BOOST_REQUIRE_EQUAL(db.get_balance(nathan_id, core.get_id()).amount.value, 500); + } catch (fc::exception& e) { + edump((e.to_detail_string())); + throw; + } +} + BOOST_AUTO_TEST_CASE( call_order_update_test ) { try { From 5484c9f9efd103eb0a899ee9e65460f464163e9f Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Fri, 22 Feb 2019 13:33:21 -0600 Subject: [PATCH 003/127] Ref #1604: Add matching logic Add logic to match an updated limit order if the price is changed to be higher than the previous top-of-book price. I believe this completes #1604 --- .../graphene/chain/market_evaluator.hpp | 1 + libraries/chain/market_evaluator.cpp | 26 ++++++++--- libraries/chain/protocol/market.cpp | 4 +- tests/tests/operation_tests.cpp | 44 +++++++++++++++++++ 4 files changed, 65 insertions(+), 10 deletions(-) diff --git a/libraries/chain/include/graphene/chain/market_evaluator.hpp b/libraries/chain/include/graphene/chain/market_evaluator.hpp index 5d994bb7bf..cfc9e361dd 100644 --- a/libraries/chain/include/graphene/chain/market_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/market_evaluator.hpp @@ -72,6 +72,7 @@ namespace graphene { namespace chain { void_result do_apply(const limit_order_update_operation& o); const limit_order_object* _order = nullptr; + bool should_match_orders = false; }; class limit_order_cancel_evaluator : public evaluator diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index e16cda398a..e194c2d217 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -132,11 +132,21 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o // Check this is my order FC_ASSERT(o.seller == _order->seller, "Cannot update someone else's order"); - // Check new price is compatible - if (o.new_price) - FC_ASSERT(o.new_price->base.asset_id == _order->sell_price.base.asset_id && - o.new_price->quote.asset_id == _order->sell_price.quote.asset_id, + // Check new price is compatible, and determine whether it becomes the best offer on the market + if (o.new_price) { + auto base_id = o.new_price->base.asset_id; + auto quote_id = o.new_price->quote.asset_id; + FC_ASSERT(base_id == _order->sell_price.base.asset_id && quote_id == _order->sell_price.quote.asset_id, "Cannot update limit order with incompatible price"); + const auto& order_index = d.get_index_type().indices().get(); + auto top_of_book = order_index.upper_bound(boost::make_tuple(price::max(base_id, quote_id))); + FC_ASSERT(top_of_book->sell_price.base.asset_id == base_id && top_of_book->sell_price.quote.asset_id == quote_id, + "Paradox: attempting to update an order in a market that has no orders? There's a logic error somewhere."); + + // If the new price of our order is greater than the price of the order at the top of the book, we should match orders at the end. + // Otherwise, we can skip matching because there's no way this change could trigger orders to fill. + should_match_orders = (*o.new_price > top_of_book->sell_price); + } // Check delta asset is compatible if (o.delta_amount_to_sell) { @@ -156,7 +166,7 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o FC_ASSERT(*o.new_expiration >= d.head_block_time(), "Cannot update limit order with past expiration"); - return void_result(); + return {}; } FC_CAPTURE_AND_RETHROW((o)) } void_result limit_order_update_evaluator::do_apply(const limit_order_update_operation& o) @@ -182,9 +192,11 @@ void_result limit_order_update_evaluator::do_apply(const limit_order_update_oper loo.expiration = *o.new_expiration; }); - // TODO: check if order is at front of book and price moved in favor of buyer; if so, trigger matching + // Perform order matching if necessary + if (should_match_orders) + d.apply_order(*_order); - return void_result(); + return {}; } FC_CAPTURE_AND_RETHROW((o)) } void_result limit_order_cancel_evaluator::do_evaluate(const limit_order_cancel_operation& o) diff --git a/libraries/chain/protocol/market.cpp b/libraries/chain/protocol/market.cpp index d368eb4a0b..ec02edf6f6 100644 --- a/libraries/chain/protocol/market.cpp +++ b/libraries/chain/protocol/market.cpp @@ -65,6 +65,4 @@ void bid_collateral_operation::validate()const FC_ASSERT( debt_covered.amount == 0 || (debt_covered.amount > 0 && additional_collateral.amount > 0) ); } FC_CAPTURE_AND_RETHROW((*this)) } -} - -} // graphene::chain +} } // graphene::chain diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 5176b4f414..986cf7ae4e 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -172,6 +172,50 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) } } +BOOST_AUTO_TEST_CASE(limit_order_update_match_test) +{ + try { + ACTORS((nathan)); + const auto& munee = create_user_issued_asset("MUNEE"); + + transfer(committee_account, nathan_id, asset(10000)); + issue_uia(nathan, munee.amount(1000)); + + auto expiration = db.head_block_time() + 1000; + limit_order_id_type order_id_1 = create_sell_order(nathan, asset(999), munee.amount(100), expiration)->id; + limit_order_id_type order_id_2 = create_sell_order(nathan, munee.amount(100), asset(1001), expiration)->id; + + update_limit_order(order_id_1, price(asset(1001), munee.amount(100)), asset(1)); + BOOST_REQUIRE_EQUAL(db.find(order_id_1), nullptr); + BOOST_REQUIRE_EQUAL(db.find(order_id_2)->amount_for_sale().amount.value, 1); + } catch (fc::exception& e) { + edump((e.to_detail_string())); + throw; + } +} + +BOOST_AUTO_TEST_CASE(limit_order_update_match_test_2) +{ + try { + ACTORS((nathan)); + const auto& munee = create_user_issued_asset("MUNEE"); + + transfer(committee_account, nathan_id, asset(10000)); + issue_uia(nathan, munee.amount(1000)); + + auto expiration = db.head_block_time() + 1000; + limit_order_id_type order_id_1 = create_sell_order(nathan, asset(999), munee.amount(100), expiration)->id; + limit_order_id_type order_id_2 = create_sell_order(nathan, munee.amount(100), asset(1001), expiration)->id; + + update_limit_order(order_id_2, price(munee.amount(100), asset(999))); + BOOST_REQUIRE_EQUAL(db.find(order_id_1), nullptr); + BOOST_REQUIRE_EQUAL(db.find(order_id_2), nullptr); + } catch (fc::exception& e) { + edump((e.to_detail_string())); + throw; + } +} + BOOST_AUTO_TEST_CASE( call_order_update_test ) { try { From 3d24f7c6106ed8b6b900921509419b8c74bc78bf Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Tue, 26 Feb 2019 14:59:30 -0600 Subject: [PATCH 004/127] Progress #1604: Add dust check Add dust check to limit order update logic, and test --- libraries/chain/market_evaluator.cpp | 11 +++++++++++ tests/tests/operation_tests.cpp | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index e194c2d217..85ac8c28f1 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -161,6 +161,17 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o "Cannot deduct more from order than order contains"); } + // Check dust + if (o.new_price || (o.delta_amount_to_sell && o.delta_amount_to_sell->amount < 0)) { + auto new_price = o.new_price? *o.new_price : _order->sell_price; + auto new_amount = _order->amount_for_sale(); + if (o.delta_amount_to_sell) + new_amount += *o.delta_amount_to_sell; + auto new_amount_to_receive = new_amount * new_price; + + FC_ASSERT(new_amount_to_receive.amount > 0, "Cannot update limit order: order becomes too small; cancel order instead"); + } + // Check expiration is in the future if (o.new_expiration) FC_ASSERT(*o.new_expiration >= d.head_block_time(), diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 986cf7ae4e..5661d977ea 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -172,6 +172,27 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) } } +BOOST_AUTO_TEST_CASE(limit_order_update_dust_test) +{ + try { + ACTORS((nathan)); + const auto& munee = create_user_issued_asset("MUNEE"); + + transfer(committee_account, nathan_id, asset(10000)); + issue_uia(nathan, munee.amount(1000)); + + auto expiration = db.head_block_time() + 1000; + limit_order_id_type order_id = create_sell_order(nathan, asset(1000), munee.amount(100), expiration)->id; + + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(-995)), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(1000000), munee.amount(100))), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(2000), munee.amount(100)), asset(-985)), fc::assert_exception); + } catch (fc::exception& e) { + edump((e.to_detail_string())); + throw; + } +} + BOOST_AUTO_TEST_CASE(limit_order_update_match_test) { try { From 073ecbeca03c07b32e4079a1b831183bb6444167 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Tue, 26 Feb 2019 16:37:05 -0600 Subject: [PATCH 005/127] Progress #1604: Add hardfork guards --- libraries/chain/hardfork.d/CORE_1604.hf | 4 ++++ libraries/chain/market_evaluator.cpp | 1 + libraries/chain/proposal_evaluator.cpp | 4 ++++ tests/tests/operation_tests.cpp | 8 ++++++++ 4 files changed, 17 insertions(+) create mode 100644 libraries/chain/hardfork.d/CORE_1604.hf diff --git a/libraries/chain/hardfork.d/CORE_1604.hf b/libraries/chain/hardfork.d/CORE_1604.hf new file mode 100644 index 0000000000..97185b5983 --- /dev/null +++ b/libraries/chain/hardfork.d/CORE_1604.hf @@ -0,0 +1,4 @@ +// bitshares-core issue #1604 Operation to modify existing limit order +#ifndef HARDFORK_CORE_1604_TIME +#define HARDFORK_CORE_1604_TIME (fc::time_point_sec(1893456000)) // Jan 1 00:00:00 2030 (Not yet scheduled) +#endif diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 85ac8c28f1..bc1475a22e 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -127,6 +127,7 @@ object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_o void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_operation& o) { try { const database& d = db(); + FC_ASSERT(d.head_block_time() > HARDFORK_CORE_1604_TIME, "Operation has not activated yet"); _order = &o.order(d); // Check this is my order diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index 348629d9ba..59e3212a97 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -42,6 +42,10 @@ struct proposal_operation_hardfork_visitor void operator()(const T &v) const {} // TODO review and cleanup code below after hard fork + // hf_1604 + void operator()(const graphene::chain::limit_order_update_operation &) const { + FC_ASSERT(block_time > HARDFORK_CORE_1604_TIME, "Operation is not enabled yet"); + } // hf_834 void operator()(const graphene::chain::call_order_update_operation &v) const { if (next_maintenance_time <= HARDFORK_CORE_834_TIME) { diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 5661d977ea..7cb0fe617a 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -88,6 +88,8 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) const auto& munee = create_user_issued_asset("MUNEE"); const auto& core = asset_id_type()(db); + generate_blocks(HARDFORK_CORE_1604_TIME + 10); + update_feed_producers(bitusd, {nathan_id}); price_feed current_feed; current_feed.settlement_price = bitusd.amount(200) / core.amount(100); @@ -178,6 +180,8 @@ BOOST_AUTO_TEST_CASE(limit_order_update_dust_test) ACTORS((nathan)); const auto& munee = create_user_issued_asset("MUNEE"); + generate_blocks(HARDFORK_CORE_1604_TIME + 10); + transfer(committee_account, nathan_id, asset(10000)); issue_uia(nathan, munee.amount(1000)); @@ -199,6 +203,8 @@ BOOST_AUTO_TEST_CASE(limit_order_update_match_test) ACTORS((nathan)); const auto& munee = create_user_issued_asset("MUNEE"); + generate_blocks(HARDFORK_CORE_1604_TIME + 10); + transfer(committee_account, nathan_id, asset(10000)); issue_uia(nathan, munee.amount(1000)); @@ -221,6 +227,8 @@ BOOST_AUTO_TEST_CASE(limit_order_update_match_test_2) ACTORS((nathan)); const auto& munee = create_user_issued_asset("MUNEE"); + generate_blocks(HARDFORK_CORE_1604_TIME + 10); + transfer(committee_account, nathan_id, asset(10000)); issue_uia(nathan, munee.amount(1000)); From a34c8559ea651fc6dc8cf211ac198cc31d3c6e0c Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Tue, 26 Feb 2019 17:31:39 -0600 Subject: [PATCH 006/127] Ref #1604: Another test case --- tests/tests/operation_tests.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 7cb0fe617a..01ca9ea395 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -111,6 +111,9 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) GRAPHENE_REQUIRE_THROW(update_limit_order(order_id), fc::assert_exception); // Cannot update order to use inverted price assets GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(bitusd.amount(2), asset(1))), fc::assert_exception); + // Cannot update order to use negative price + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(-1), bitusd.amount(2))), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(1), bitusd.amount(-2))), fc::assert_exception); // Cannot update order to use different assets GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(bitusd.amount(2), munee.amount(1))), fc::assert_exception); GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(munee.amount(2), bitusd.amount(1))), fc::assert_exception); From fba5bacf1587ac8450412a5dd8477a8ed219c698 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Wed, 27 Feb 2019 17:04:21 -0600 Subject: [PATCH 007/127] Progress #1604: Do not allow sooner expiration Updating an order's expiration must make it expire later than before, not the same or sooner. --- libraries/chain/market_evaluator.cpp | 4 ++-- tests/tests/operation_tests.cpp | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index bc1475a22e..3d91340485 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -175,8 +175,8 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o // Check expiration is in the future if (o.new_expiration) - FC_ASSERT(*o.new_expiration >= d.head_block_time(), - "Cannot update limit order with past expiration"); + FC_ASSERT(*o.new_expiration > _order->expiration, + "Cannot update limit order to expire sooner; new expiration must be later than old one."); return {}; } FC_CAPTURE_AND_RETHROW((o)) } diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 01ca9ea395..6b19ff4783 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -148,9 +148,11 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) expiration += 50; update_limit_order(order_id, {}, {}, expiration); BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); - expiration -= 100; - update_limit_order(order_id, {}, {}, expiration); - BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + // Cannot make expiration same as before + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, expiration), fc::assert_exception); + // Cannot make expiration sooner; only later + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, expiration - 100), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, expiration - 1), fc::assert_exception); // Try adding funds update_limit_order(order_id, {}, asset(50)); From 8a82d92291b71cdeecb03f81794b50a9b3f7e6b0 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Wed, 27 Feb 2019 17:54:01 -0600 Subject: [PATCH 008/127] Add fee_schedule::exists() I pulled this out of a2192ec21e9d95372dc5e3d790bbc698bfb32a0c because I needed it separated from the rest of that commit. --- .../chain/include/graphene/chain/protocol/fee_schedule.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp b/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp index 07855b4d7e..ee422eacf0 100644 --- a/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp +++ b/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp @@ -140,6 +140,12 @@ namespace graphene { namespace chain { { return fee_helper().get(parameters); } + template + const bool exists()const + { + auto itr = parameters.find(typename Operation::fee_parameters_type()); + return itr != parameters.end(); + } /** * @note must be sorted by fee_parameters.which() and have no duplicates From 61809464c52d76971dcc93ec178f19e665217b95 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Wed, 27 Feb 2019 17:55:04 -0600 Subject: [PATCH 009/127] Ref #1604: Add missing hardfork guard Guard against the comittee setting fees for the operation which is not yet defined. --- libraries/chain/proposal_evaluator.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index 59e3212a97..57b72257a3 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -96,6 +96,11 @@ struct proposal_operation_hardfork_visitor FC_ASSERT(!"Virtual operation"); } } + void operator()(const graphene::chain::committee_member_update_global_parameters_operation &op) const { + if (block_time < HARDFORK_CORE_1604_TIME) + FC_ASSERT(!op.new_parameters.current_fees->exists(), + "Cannot set fees for limit_order_update_operation before its hardfork time"); + } // loop and self visit in proposals void operator()(const graphene::chain::proposal_create_operation &v) const { for (const op_wrapper &op : v.proposed_ops) From 55dc688a3784638fbad5e0b09aac313e4ab3c4f1 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Mon, 7 Oct 2019 09:55:24 -0500 Subject: [PATCH 010/127] Eliminate variable fee --- .../chain/include/graphene/chain/protocol/market.hpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libraries/chain/include/graphene/chain/protocol/market.hpp b/libraries/chain/include/graphene/chain/protocol/market.hpp index abb1dee59a..9e4bca208b 100644 --- a/libraries/chain/include/graphene/chain/protocol/market.hpp +++ b/libraries/chain/include/graphene/chain/protocol/market.hpp @@ -76,15 +76,11 @@ namespace graphene { namespace chain { /** * @ingroup operations * Used to update an existing limit order. - * - * Charges a higher fee if @ref delta_amount_to_sell is set, as this requires updating - * the account balance as well as the order object. */ struct limit_order_update_operation : public base_operation { struct fee_parameters_type { - uint64_t price_fee = GRAPHENE_BLOCKCHAIN_PRECISION / 2; - uint64_t amount_fee = GRAPHENE_BLOCKCHAIN_PRECISION; + uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION / 2; }; asset fee; @@ -99,7 +95,7 @@ namespace graphene { namespace chain { account_id_type fee_payer() const { return seller; } void validate() const; share_type calculate_fee(const fee_parameters_type& k) const { - return delta_amount_to_sell? k.amount_fee : k.price_fee; + return k.fee; } }; @@ -248,7 +244,7 @@ namespace graphene { namespace chain { } } // graphene::chain FC_REFLECT( graphene::chain::limit_order_create_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::limit_order_update_operation::fee_parameters_type, (price_fee)(amount_fee) ) +FC_REFLECT( graphene::chain::limit_order_update_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::limit_order_cancel_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::call_order_update_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::bid_collateral_operation::fee_parameters_type, (fee) ) From f7b2547f1ff93d8ef520ba0a4ad8e3bb583ad616 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 17 Dec 2021 11:48:17 +0000 Subject: [PATCH 011/127] Update SonarScanner config for hardfork branch --- sonar-project.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonar-project.properties b/sonar-project.properties index 9fe1699f22..e89c5b5771 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,7 +3,7 @@ sonar.organization=bitshares-on-github sonar.projectKey=bitshares_bitshares-core sonar.projectName=BitShares-Core sonar.projectDescription=BitShares Blockchain implementation and command-line interface -sonar.projectVersion=6.1.x +sonar.projectVersion=7.0.x sonar.host.url=https://sonarcloud.io @@ -26,4 +26,4 @@ sonar.cfamily.cache.path=sonar_cache # Decide which tree the current build belongs to in SonarCloud. # Managed by the `set_sonar_branch*` script(s) when building with CI. -sonar.branch.target=develop +sonar.branch.target=hardfork From b304021924353feb696df7a60acb06d48a2ba94b Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 2 Dec 2022 09:28:50 +0000 Subject: [PATCH 012/127] Update sonar.branch.target for develop branch --- sonar-project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonar-project.properties b/sonar-project.properties index 9cd8574e9f..3703c0108d 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -23,4 +23,4 @@ sonar.cfamily.cache.path=sonar_cache # Decide which tree the current build belongs to in SonarCloud. # Managed by the `set_sonar_branch*` script(s) when building with CI. -sonar.branch.target=master +sonar.branch.target=develop From 456fe1959eec4e16f73a0fa01a6d49ac98fc0c3c Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 3 Dec 2022 09:34:01 +0000 Subject: [PATCH 013/127] Refactor login_api::login(), fix code smells --- libraries/app/api.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 4556d42972..3fd6f92d33 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -59,21 +59,19 @@ namespace graphene { namespace app { return uint32_t(1); // Note: hard code it here for backward compatibility FC_ASSERT( o_user.valid() && o_password.valid(), "Must provide both user and password" ); - string user = *o_user; - optional< api_access_info > acc = _app.get_api_access_info( user ); - if( !acc.valid() ) + optional< api_access_info > acc = _app.get_api_access_info( *o_user ); + if( !acc ) return logout(); if( acc->password_hash_b64 != "*" ) { - std::string password_salt = fc::base64_decode( acc->password_salt_b64 ); std::string acc_password_hash = fc::base64_decode( acc->password_hash_b64 ); - - string password = *o_password; - fc::sha256 hash_obj = fc::sha256::hash( password + password_salt ); - if( hash_obj.data_size() != acc_password_hash.length() ) + if( fc::sha256::data_size() != acc_password_hash.length() ) return logout(); - if( memcmp( hash_obj.data(), acc_password_hash.c_str(), hash_obj.data_size() ) != 0 ) + + std::string password_salt = fc::base64_decode( acc->password_salt_b64 ); + fc::sha256 hash_obj = fc::sha256::hash( *o_password + password_salt ); + if( memcmp( hash_obj.data(), acc_password_hash.data(), fc::sha256::data_size() ) != 0 ) return logout(); } From 9757d824aa4c8c2975e81168239c71fff7be9c4b Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 4 Dec 2022 01:17:22 +0000 Subject: [PATCH 014/127] Update default value of market hist plugin options --- .../plugins/market_history/market_history_plugin.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/plugins/market_history/market_history_plugin.cpp b/libraries/plugins/market_history/market_history_plugin.cpp index 382ed4fc62..839117de85 100644 --- a/libraries/plugins/market_history/market_history_plugin.cpp +++ b/libraries/plugins/market_history/market_history_plugin.cpp @@ -744,12 +744,14 @@ void market_history_plugin::plugin_set_program_options( ) { cli.add_options() - ("bucket-size", boost::program_options::value()->default_value("[60,300,900,1800,3600,14400,86400]"), + ("bucket-size", + // 1m, 5m, 15m, 1h, 4h, 1d, 1w + boost::program_options::value()->default_value("[60,300,900,3600,14400,86400,604800]"), "Track market history by grouping orders into buckets of equal size measured " "in seconds specified as a JSON array of numbers") - ("history-per-size", boost::program_options::value()->default_value(1000), + ("history-per-size", boost::program_options::value()->default_value(1500), "How far back in time to track history for each bucket size, " - "measured in the number of buckets (default: 1000)") + "measured in the number of buckets (default: 1500)") ("max-order-his-records-per-market", boost::program_options::value()->default_value(1000), "Will only store this amount of matched orders for each market in order history for querying, " "or those meet the other option, which has more data (default: 1000). " From d64b0dc07bcbbe08b219260f5975e2a2648ab6ac Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 4 Dec 2022 01:44:28 +0000 Subject: [PATCH 015/127] Update default Docker config about market history --- docker/default_config.ini | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docker/default_config.ini b/docker/default_config.ini index c15db1e715..10fe5a9817 100644 --- a/docker/default_config.ini +++ b/docker/default_config.ini @@ -213,13 +213,10 @@ max-ops-per-account = 100 # ============================================================================== # Track market history by grouping orders into buckets of equal size measured in seconds specified as a JSON array of numbers -# bucket-size = [15,60,300,3600,86400] -bucket-size = [60,300,900,1800,3600,14400,86400] -# for 1 min, 5 mins, 30 mins, 1h, 4 hs and 1 day. i think this should be the default. -# https://github.com/bitshares/bitshares-core/issues/465 +bucket-size = [60,300,900,3600,14400,86400,604800] # How far back in time to track history for each bucket size, measured in the number of buckets (default: 1000) -history-per-size = 1000 +history-per-size = 1500 # Will only store this amount of matched orders for each market in order history for querying, or those meet the other option, which has more data (default: 1000) max-order-his-records-per-market = 1000 From 95c5a53251a29428b78cbee674739a49f4a4bfeb Mon Sep 17 00:00:00 2001 From: litepresence Date: Sun, 4 Dec 2022 09:55:57 -0500 Subject: [PATCH 016/127] delinting `rewind` is reserved prefix increment `dropped_count, i, next_block_num` for efficiency increment from method call `fetch_by_number()` could cause undefined behavior parenthesis added for explicit operator precedence order of operations clarified max 1 nested break --- libraries/chain/db_management.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/libraries/chain/db_management.cpp b/libraries/chain/db_management.cpp index d78051ecc1..98e754fd51 100644 --- a/libraries/chain/db_management.cpp +++ b/libraries/chain/db_management.cpp @@ -65,7 +65,7 @@ void database::reindex( fc::path data_dir ) ilog( "reindexing blockchain" ); auto start = fc::time_point::now(); const auto last_block_num = last_block->block_num(); - uint32_t undo_point = last_block_num < GRAPHENE_MAX_UNDO_HISTORY ? 0 : last_block_num - GRAPHENE_MAX_UNDO_HISTORY; + uint32_t undo_point = last_block_num < GRAPHENE_MAX_UNDO_HISTORY ? 0 : (last_block_num - GRAPHENE_MAX_UNDO_HISTORY); ilog( "Replaying blocks, starting at ${next}...", ("next",head_block_num() + 1) ); if( head_block_num() >= undo_point ) @@ -88,10 +88,11 @@ void database::reindex( fc::path data_dir ) if( next_block_num <= last_block_num && blocks.size() < 20 ) { const size_t processed_block_size = _block_id_to_block.blocks_current_position(); - fc::optional< signed_block > block = _block_id_to_block.fetch_by_number( next_block_num++ ); + fc::optional< signed_block > block = _block_id_to_block.fetch_by_number( next_block_num ); + ++next_block_num; if( block.valid() ) { - if( block->timestamp >= last_block->timestamp - gpo.parameters.maximum_time_until_expiration ) + if( block->timestamp >= (last_block->timestamp - gpo.parameters.maximum_time_until_expiration) ) skip &= (uint32_t)(~skip_transaction_dupe_check); blocks.emplace( processed_block_size, std::move(*block), fc::future() ); std::get<2>(blocks.back()) = precompute_parallel( std::get<1>(blocks.back()), skip ); @@ -104,13 +105,12 @@ void database::reindex( fc::path data_dir ) { fc::optional< block_id_type > last_id = _block_id_to_block.last_id(); // this can trigger if we attempt to e.g. read a file that has block #2 but no block #1 - if( !last_id.valid() ) - break; + // OR // we've caught up to the gap - if( block_header::num_from_id( *last_id ) <= i ) + if( !last_id.valid() || block_header::num_from_id( *last_id ) <= i ) break; _block_id_to_block.remove( *last_id ); - dropped_count++; + ++dropped_count; } wlog( "Dropped ${n} blocks from after the gap", ("n", dropped_count) ); next_block_num = last_block_num + 1; // don't load more blocks @@ -128,8 +128,8 @@ void database::reindex( fc::path data_dir ) size_t current_pos = std::get<0>(blocks.front()); if( current_pos > total_block_size ) total_block_size = current_pos; - bysize << std::fixed << std::setprecision(5) << double(current_pos) / total_block_size * 100; - bynum << std::fixed << std::setprecision(5) << double(i)*100/last_block_num; + bysize << std::fixed << std::setprecision(5) << (100 * double(current_pos) / total_block_size); + bynum << std::fixed << std::setprecision(5) << (100 * double(i) / last_block_num); ilog( " [by size: ${size}% ${processed} of ${total}] [by num: ${num}% ${i} of ${last}]", ("size", bysize.str()) @@ -154,7 +154,7 @@ void database::reindex( fc::path data_dir ) push_block( block, skip ); } blocks.pop(); - i++; + ++i; } } _undo_db.enable(); @@ -227,17 +227,16 @@ void database::open( FC_CAPTURE_LOG_AND_RETHROW( (data_dir) ) } -void database::close(bool rewind) +void database::close(bool rewinding) { if (!_opened) return; - // TODO: Save pending tx's on close() clear_pending(); // pop all of the blocks that we can given our undo history, this should // throw when there is no more undo history to pop - if( rewind ) + if( rewinding ) { try { From 216da753c1e76953cf833d9253473ab9b281f4bb Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 9 Dec 2022 10:56:39 +0000 Subject: [PATCH 017/127] Use ES 8.5.3 in Github Actions, remove Ubuntu 18 --- .../workflows/build-and-test.ubuntu-debug.yml | 25 +++++++++++++------ .../build-and-test.ubuntu-release.yml | 25 +++++++++++++------ .github/workflows/sonar-scan.yml | 15 ++++++----- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build-and-test.ubuntu-debug.yml b/.github/workflows/build-and-test.ubuntu-debug.yml index 9c626766ca..0157b871c1 100644 --- a/.github/workflows/build-and-test.ubuntu-debug.yml +++ b/.github/workflows/build-and-test.ubuntu-debug.yml @@ -8,12 +8,24 @@ jobs: name: Build and test in Debug mode strategy: matrix: - os: [ ubuntu-18.04, ubuntu-20.04 ] + os: [ ubuntu-20.04 ] runs-on: ${{ matrix.os }} services: - elasticsearch: - image: docker://elasticsearch:7.17.7 - options: --env discovery.type=single-node --publish 9200:9200 --publish 9300:9300 + elasticsearch8: + image: elastic/elasticsearch:8.5.3 + options: >- + --env discovery.type=single-node + --env xpack.security.enabled=false + --env xpack.security.http.ssl.enabled=false + --env action.destructive_requires_name=false + --env cluster.routing.allocation.disk.threshold_enabled=false + --publish 9200:9200 + elasticsearch7: + image: elastic/elasticsearch:7.17.8 + options: >- + --env discovery.type=single-node + --env cluster.routing.allocation.disk.threshold_enabled=false + --publish 9201:9200 steps: - name: Install dependencies run: | @@ -105,9 +117,8 @@ jobs: _build/tests/app_test -l test_suite df -h rm -rf /tmp/graphene* - curl -XPUT -H "Content-Type: application/json" http://localhost:9200/_cluster/settings \ - -d '{ "transient": { "cluster.routing.allocation.disk.threshold_enabled": false } }' - echo + _build/tests/es_test -l test_suite + export GRAPHENE_TESTING_ES_URL=http://127.0.0.1:9201/ _build/tests/es_test -l test_suite df -h rm -rf /tmp/graphene* diff --git a/.github/workflows/build-and-test.ubuntu-release.yml b/.github/workflows/build-and-test.ubuntu-release.yml index a2bd68ebe9..98e72a201d 100644 --- a/.github/workflows/build-and-test.ubuntu-release.yml +++ b/.github/workflows/build-and-test.ubuntu-release.yml @@ -8,12 +8,24 @@ jobs: name: Build and test in Release mode strategy: matrix: - os: [ ubuntu-18.04, ubuntu-20.04 ] + os: [ ubuntu-20.04 ] runs-on: ${{ matrix.os }} services: - elasticsearch: - image: docker://elasticsearch:7.17.7 - options: --env discovery.type=single-node --publish 9200:9200 --publish 9300:9300 + elasticsearch8: + image: elastic/elasticsearch:8.5.3 + options: >- + --env discovery.type=single-node + --env xpack.security.enabled=false + --env xpack.security.http.ssl.enabled=false + --env action.destructive_requires_name=false + --env cluster.routing.allocation.disk.threshold_enabled=false + --publish 9200:9200 + elasticsearch7: + image: elastic/elasticsearch:7.17.8 + options: >- + --env discovery.type=single-node + --env cluster.routing.allocation.disk.threshold_enabled=false + --publish 9201:9200 steps: - name: Install dependencies run: | @@ -73,9 +85,8 @@ jobs: - name: Unit-Tests run: | _build/tests/app_test -l test_suite - curl -XPUT -H "Content-Type: application/json" http://localhost:9200/_cluster/settings \ - -d '{ "transient": { "cluster.routing.allocation.disk.threshold_enabled": false } }' - echo + _build/tests/es_test -l test_suite + export GRAPHENE_TESTING_ES_URL=http://127.0.0.1:9201/ _build/tests/es_test -l test_suite libraries/fc/tests/run-parallel-tests.sh _build/tests/chain_test -l test_suite _build/tests/cli_test -l test_suite diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index eca0b916ba..eb8ad9f34a 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -11,9 +11,15 @@ jobs: os: [ ubuntu-20.04 ] runs-on: ${{ matrix.os }} services: - elasticsearch: - image: docker://elasticsearch:7.17.7 - options: --env discovery.type=single-node --publish 9200:9200 --publish 9300:9300 + elasticsearch8: + image: elastic/elasticsearch:8.5.3 + options: >- + --env discovery.type=single-node + --env xpack.security.enabled=false + --env xpack.security.http.ssl.enabled=false + --env action.destructive_requires_name=false + --env cluster.routing.allocation.disk.threshold_enabled=false + --publish 9200:9200 steps: - name: Download and install latest SonarScanner CLI tool run: | @@ -167,9 +173,6 @@ jobs: df -h echo "Cleanup" rm -rf /tmp/graphene* - curl -XPUT -H "Content-Type: application/json" http://localhost:9200/_cluster/settings \ - -d '{ "transient": { "cluster.routing.allocation.disk.threshold_enabled": false } }' - echo _build/tests/es_test -l test_suite df -h echo "Cleanup" From 93d70aba14d05ad2efaaa785a879c108bf0b34d5 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 7 Jan 2023 22:05:30 +0000 Subject: [PATCH 018/127] Fix ElasticSearch version 8 compatibility Since ES version 8, cannot specify a type when using the Search API or the Count API. --- .../elasticsearch/elasticsearch_plugin.cpp | 6 ++++-- tests/elasticsearch/main.cpp | 20 +++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index 62e4a10312..205bbf78f3 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -630,7 +630,8 @@ operation_history_object elasticsearch_plugin::get_operation_by_id( const operat } )"; - const auto response = my->es->query( my->_options.index_prefix + "*/_doc/_search", query ); + const auto uri = my->_options.index_prefix + ( my->is_es_version_7_or_above ? "*/_search" : "*/_doc/_search" ); + const auto response = my->es->query( uri, query ); variant variant_response = fc::json::from_string(response); const auto source = variant_response["hits"]["hits"][size_t(0)]["_source"]; return fromEStoOperation(source); @@ -677,7 +678,8 @@ vector elasticsearch_plugin::get_account_history( if( !my->es->check_status() ) return result; - const auto response = my->es->query( my->_options.index_prefix + "*/_doc/_search", query ); + const auto uri = my->_options.index_prefix + ( my->is_es_version_7_or_above ? "*/_search" : "*/_doc/_search" ); + const auto response = my->es->query( uri, query ); variant variant_response = fc::json::from_string(response); diff --git a/tests/elasticsearch/main.cpp b/tests/elasticsearch/main.cpp index 6fb4fbb266..ba370680fe 100644 --- a/tests/elasticsearch/main.cpp +++ b/tests/elasticsearch/main.cpp @@ -71,7 +71,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) { generate_block(); string query = "{ \"query\" : { \"bool\" : { \"must\" : [{\"match_all\": {}}] } } }"; - es.endpoint = es.index_prefix + "*/_doc/_count"; + es.endpoint = es.index_prefix + "*/_count"; es.query = query; string res; @@ -85,7 +85,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) { return (total == "5"); }); - es.endpoint = es.index_prefix + "*/_doc/_search"; + es.endpoint = es.index_prefix + "*/_search"; res = graphene::utilities::simpleQuery(es); j = fc::json::from_string(res); auto first_id = j["hits"]["hits"][size_t(0)]["_id"].as_string(); @@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) { auto willie = create_account("willie"); generate_block(); - es.endpoint = es.index_prefix + "*/_doc/_count"; + es.endpoint = es.index_prefix + "*/_count"; fc::wait_for( ES_WAIT_TIME, [&]() { res = graphene::utilities::simpleQuery(es); @@ -197,7 +197,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) { generate_block(); - es.endpoint = es.index_prefix + "*/_doc/_count"; + es.endpoint = es.index_prefix + "*/_count"; fc::wait_for( ES_WAIT_TIME, [&]() { res = graphene::utilities::simpleQuery(es); j = fc::json::from_string(res); @@ -241,7 +241,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_objects) { generate_block(); string query = "{ \"query\" : { \"bool\" : { \"must\" : [{\"match_all\": {}}] } } }"; - es.endpoint = es.index_prefix + "*/_doc/_count"; + es.endpoint = es.index_prefix + "*/_count"; es.query = query; string res; @@ -255,14 +255,14 @@ BOOST_AUTO_TEST_CASE(elasticsearch_objects) { return (total == "2"); }); - es.endpoint = es.index_prefix + "asset/_doc/_search"; + es.endpoint = es.index_prefix + "asset/_search"; res = graphene::utilities::simpleQuery(es); j = fc::json::from_string(res); auto first_id = j["hits"]["hits"][size_t(0)]["_source"]["symbol"].as_string(); BOOST_CHECK_EQUAL(first_id, "USD"); auto bitasset_data_id = j["hits"]["hits"][size_t(0)]["_source"]["bitasset_data_id"].as_string(); - es.endpoint = es.index_prefix + "bitasset/_doc/_search"; + es.endpoint = es.index_prefix + "bitasset/_search"; es.query = "{ \"query\" : { \"bool\": { \"must\" : [{ \"term\": { \"object_id\": \"" + bitasset_data_id + "\"}}] } } }"; res = graphene::utilities::simpleQuery(es); @@ -275,7 +275,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_objects) { db.get_dynamic_global_properties().next_maintenance_time ); generate_block(); - es.endpoint = es.index_prefix + "limitorder/_doc/_count"; + es.endpoint = es.index_prefix + "limitorder/_count"; es.query = ""; fc::wait_for( ES_WAIT_TIME, [&]() { res = graphene::utilities::getEndPoint(es); @@ -293,7 +293,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_objects) { generate_blocks( db.get_dynamic_global_properties().next_maintenance_time ); generate_block(); - es.endpoint = es.index_prefix + "budget/_doc/_count"; + es.endpoint = es.index_prefix + "budget/_count"; es.query = ""; fc::wait_for( ES_WAIT_TIME, [&]() { res = graphene::utilities::getEndPoint(es); @@ -307,7 +307,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_objects) { return (total == "1"); // new record inserted at the first maintenance block }); - es.endpoint = es.index_prefix + "limitorder/_doc/_count"; + es.endpoint = es.index_prefix + "limitorder/_count"; es.query = ""; fc::wait_for( ES_WAIT_TIME, [&]() { res = graphene::utilities::getEndPoint(es); From eab0b0435467de306e4756bd6ff35394cfc3719d Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 7 Jan 2023 22:15:40 +0000 Subject: [PATCH 019/127] Check response content when deleting, add logging --- tests/common/elasticsearch.cpp | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/tests/common/elasticsearch.cpp b/tests/common/elasticsearch.cpp index 1393f35872..bdef7cb02d 100644 --- a/tests/common/elasticsearch.cpp +++ b/tests/common/elasticsearch.cpp @@ -48,7 +48,6 @@ bool checkES(ES& es) if(doCurl(curl_request).empty()) return false; return true; - } std::string getESVersion(ES& es) @@ -100,10 +99,29 @@ bool deleteAll(ES& es) curl_request.type = "DELETE"; auto curl_response = doCurl(curl_request); - if(curl_response.empty()) + if( curl_response.empty() ) + { + wlog( "Empty ES response" ); + return false; + } + + // Check errors in response + try + { + fc::variant j = fc::json::from_string(curl_response); + if( j.is_object() && j.get_object().contains("error") ) + { + wlog( "ES returned an error: ${r}", ("r", curl_response) ); + return false; + } + } + catch( const fc::exception& e ) + { + wlog( "Error while checking ES response ${r}", ("r", curl_response) ); + wdump( (e.to_detail_string()) ); return false; - else - return true; + } + return true; } std::string getEndPoint(ES& es) @@ -147,6 +165,12 @@ std::string doCurl(CurlRequest& curl) curl_easy_setopt(curl.handler, CURLOPT_USERPWD, curl.auth.c_str()); curl_easy_perform(curl.handler); + long code; + curl_easy_getinfo( curl.handler, CURLINFO_RESPONSE_CODE, &code ); + + if( 200 != code ) + wlog( "doCurl response [${code}] ${msg}", ("code", ((int64_t)code))("msg", CurlReadBuffer) ); + return CurlReadBuffer; } From 20a3800b0ad42d1b8f5263d805764b7f95bd4b49 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 7 Jan 2023 22:43:35 +0000 Subject: [PATCH 020/127] Remove the elasticsearch_suite test case since it tests almost nothing. --- tests/common/database_fixture.cpp | 3 +-- tests/elasticsearch/main.cpp | 33 ------------------------------- 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index a863964479..8a8997390a 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -407,7 +407,6 @@ std::shared_ptr database_fixture_base::in } // load ES or AH, but not both if(fixture.current_test_name == "elasticsearch_account_history" || - fixture.current_test_name == "elasticsearch_suite" || fixture.current_test_name == "elasticsearch_history_api") { fixture.app.register_plugin(true); @@ -429,7 +428,7 @@ std::shared_ptr database_fixture_base::in fixture.app.register_plugin(true); } - if(fixture.current_test_name == "elasticsearch_objects" || fixture.current_test_name == "elasticsearch_suite") { + if( fixture.current_test_name == "elasticsearch_objects" ) { fixture.app.register_plugin(true); fc::set_option( options, "es-objects-elasticsearch-url", GRAPHENE_TESTING_ES_URL ); diff --git a/tests/elasticsearch/main.cpp b/tests/elasticsearch/main.cpp index ba370680fe..e5a7bc34bd 100644 --- a/tests/elasticsearch/main.cpp +++ b/tests/elasticsearch/main.cpp @@ -329,39 +329,6 @@ BOOST_AUTO_TEST_CASE(elasticsearch_objects) { } } -BOOST_AUTO_TEST_CASE(elasticsearch_suite) { - try { - - CURL *curl; // curl handler - curl = curl_easy_init(); - curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); - - graphene::utilities::ES es; - es.curl = curl; - es.elasticsearch_url = GRAPHENE_TESTING_ES_URL; - es.index_prefix = es_index_prefix; - auto delete_account_history = graphene::utilities::deleteAll(es); - BOOST_REQUIRE(delete_account_history); // require successful deletion - - graphene::utilities::ES es_obj; - es_obj.curl = curl; - es_obj.elasticsearch_url = GRAPHENE_TESTING_ES_URL; - es_obj.index_prefix = es_obj_index_prefix; - auto delete_objects = graphene::utilities::deleteAll(es_obj); - BOOST_REQUIRE(delete_objects); // require successful deletion - - if(delete_account_history && delete_objects) { // all records deleted - - - } - // Note: this test case ends too quickly, sometimes causing an memory access violation on cleanup - } - catch (fc::exception &e) { - edump((e.to_detail_string())); - throw; - } -} - BOOST_AUTO_TEST_CASE(elasticsearch_history_api) { try { CURL *curl; // curl handler From ec9d712b246dc65af913de59aab50aaf2fc4907d Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 8 Jan 2023 09:51:46 +0000 Subject: [PATCH 021/127] Add tests for es_plugin::get_operation_by_id() --- tests/elasticsearch/main.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/elasticsearch/main.cpp b/tests/elasticsearch/main.cpp index e5a7bc34bd..bba0ce1889 100644 --- a/tests/elasticsearch/main.cpp +++ b/tests/elasticsearch/main.cpp @@ -357,8 +357,8 @@ BOOST_AUTO_TEST_CASE(elasticsearch_history_api) { generate_block(); + // Test history APIs graphene::app::history_api hist_api(app); - app.enable_plugin("elasticsearch"); // f(A, 0, 4, 9) = { 5, 3, 1, 0 } auto histories = hist_api.get_account_history( @@ -652,6 +652,16 @@ BOOST_AUTO_TEST_CASE(elasticsearch_history_api) { BOOST_CHECK_EQUAL(histories[2].id.instance(), 3u); BOOST_CHECK_EQUAL(histories[3].id.instance(), 1u); BOOST_CHECK_EQUAL(histories[4].id.instance(), 0u); + + // Ugly test to cover elasticsearch_plugin::get_operation_by_id() + if( !app.elasticsearch_thread ) + app.elasticsearch_thread = std::make_shared("elasticsearch"); + auto es_plugin = app.get_plugin< graphene::elasticsearch::elasticsearch_plugin >("elasticsearch"); + auto his_obj7 = app.elasticsearch_thread->async([&es_plugin]() { + return es_plugin->get_operation_by_id( operation_history_id_type(7) ); + }, "thread invoke for method " BOOST_PP_STRINGIZE(method_name)).wait(); + BOOST_REQUIRE( his_obj7.op.is_type() ); + BOOST_CHECK_EQUAL( his_obj7.op.get().name, "alice" ); } } catch (fc::exception &e) { From 3cf8df8959d12399b1fafa7e6d7dd6e79d25fbde Mon Sep 17 00:00:00 2001 From: abitmore Date: Mon, 9 Jan 2023 09:03:17 +0000 Subject: [PATCH 022/127] Add logging about ElasticSearch version detection --- libraries/utilities/elasticsearch.cpp | 3 ++- tests/common/elasticsearch.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/utilities/elasticsearch.cpp b/libraries/utilities/elasticsearch.cpp index 7393a701ed..8113dbc3dc 100644 --- a/libraries/utilities/elasticsearch.cpp +++ b/libraries/utilities/elasticsearch.cpp @@ -211,13 +211,14 @@ std::string es_client::get_version() const fc::variant content = fc::json::from_string( response.content ); return content["version"]["number"].as_string(); -} FC_CAPTURE_AND_RETHROW() } +} FC_CAPTURE_LOG_AND_RETHROW( (base_url) ) } void es_client::check_version_7_or_above( bool& result ) const noexcept { static const int64_t version_7 = 7; try { const auto es_version = get_version(); + ilog( "ES version detected: ${v}", ("v", es_version) ); auto dot_pos = es_version.find('.'); result = ( std::stoi(es_version.substr(0,dot_pos)) >= version_7 ); } diff --git a/tests/common/elasticsearch.cpp b/tests/common/elasticsearch.cpp index bdef7cb02d..44bcd0ff41 100644 --- a/tests/common/elasticsearch.cpp +++ b/tests/common/elasticsearch.cpp @@ -68,6 +68,7 @@ void checkESVersion7OrAbove(ES& es, bool& result) noexcept static const int64_t version_7 = 7; try { const auto es_version = graphene::utilities::getESVersion(es); + ilog( "ES version detected: ${v}", ("v", es_version) ); auto dot_pos = es_version.find('.'); result = ( std::stoi(es_version.substr(0,dot_pos)) >= version_7 ); } From 994839076f94964196530247355d42047be78e11 Mon Sep 17 00:00:00 2001 From: Abit Date: Mon, 9 Jan 2023 18:47:40 +0100 Subject: [PATCH 023/127] Limit Java heap size for ES services to 512M in CI and stop using extra swap file --- .github/workflows/build-and-test.ubuntu-debug.yml | 7 ++----- .github/workflows/build-and-test.ubuntu-release.yml | 4 ++++ .github/workflows/sonar-scan.yml | 6 +----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-and-test.ubuntu-debug.yml b/.github/workflows/build-and-test.ubuntu-debug.yml index 0157b871c1..41b957daa4 100644 --- a/.github/workflows/build-and-test.ubuntu-debug.yml +++ b/.github/workflows/build-and-test.ubuntu-debug.yml @@ -14,6 +14,7 @@ jobs: elasticsearch8: image: elastic/elasticsearch:8.5.3 options: >- + --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node --env xpack.security.enabled=false --env xpack.security.http.ssl.enabled=false @@ -23,6 +24,7 @@ jobs: elasticsearch7: image: elastic/elasticsearch:7.17.8 options: >- + --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node --env cluster.routing.allocation.disk.threshold_enabled=false --publish 9201:9200 @@ -63,11 +65,6 @@ jobs: pwd df -h . free - sudo dd if=/dev/zero of=/swapfile bs=1024 count=4M - sudo chmod 600 /swapfile - sudo mkswap /swapfile - sudo swapon /swapfile - free mkdir -p _build sudo mkdir -p /_build/libraries /_build/programs /_build/tests /mnt/_build sudo chmod a+rwx /_build/libraries /_build/programs /_build/tests diff --git a/.github/workflows/build-and-test.ubuntu-release.yml b/.github/workflows/build-and-test.ubuntu-release.yml index 98e72a201d..3c43237b9b 100644 --- a/.github/workflows/build-and-test.ubuntu-release.yml +++ b/.github/workflows/build-and-test.ubuntu-release.yml @@ -14,6 +14,7 @@ jobs: elasticsearch8: image: elastic/elasticsearch:8.5.3 options: >- + --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node --env xpack.security.enabled=false --env xpack.security.http.ssl.enabled=false @@ -23,6 +24,7 @@ jobs: elasticsearch7: image: elastic/elasticsearch:7.17.8 options: >- + --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node --env cluster.routing.allocation.disk.threshold_enabled=false --publish 9201:9200 @@ -57,6 +59,8 @@ jobs: submodules: recursive - name: Configure run: | + df -h + free mkdir -p _build pushd _build export -n BOOST_ROOT BOOST_INCLUDEDIR BOOST_LIBRARYDIR diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index eb8ad9f34a..482ead8c47 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -14,6 +14,7 @@ jobs: elasticsearch8: image: elastic/elasticsearch:8.5.3 options: >- + --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node --env xpack.security.enabled=false --env xpack.security.http.ssl.enabled=false @@ -76,11 +77,6 @@ jobs: pwd df -h . free - sudo dd if=/dev/zero of=/swapfile bs=1024 count=4M - sudo chmod 600 /swapfile - sudo mkswap /swapfile - sudo swapon /swapfile - free mkdir -p _build sudo mkdir -p /_build/libraries /_build/programs /mnt/_build/tests sudo chmod a+rwx /_build/libraries /_build/programs /mnt/_build/tests From 40a13a1a687930b4f320ea7e994490ccaa87676e Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 10 Jan 2023 03:45:28 +0000 Subject: [PATCH 024/127] Use make -j2 or -j3 in Github Actions workflows --- .github/workflows/build-and-test.mac.yml | 2 +- .github/workflows/build-and-test.ubuntu-debug.yml | 14 +++++++------- .../workflows/build-and-test.ubuntu-release.yml | 2 +- .github/workflows/sonar-scan.yml | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-and-test.mac.yml b/.github/workflows/build-and-test.mac.yml index edc02f659c..de5dcd5e8a 100644 --- a/.github/workflows/build-and-test.mac.yml +++ b/.github/workflows/build-and-test.mac.yml @@ -42,7 +42,7 @@ jobs: run: | export CCACHE_DIR="$GITHUB_WORKSPACE/ccache" mkdir -p "$CCACHE_DIR" - make -j 2 -C _build witness_node cli_wallet app_test cli_test chain_test + make -j 3 -C _build witness_node cli_wallet app_test cli_test chain_test df -h - name: Unit-Tests run: | diff --git a/.github/workflows/build-and-test.ubuntu-debug.yml b/.github/workflows/build-and-test.ubuntu-debug.yml index 41b957daa4..b361866f8c 100644 --- a/.github/workflows/build-and-test.ubuntu-debug.yml +++ b/.github/workflows/build-and-test.ubuntu-debug.yml @@ -98,13 +98,13 @@ jobs: export CCACHE_DIR="$GITHUB_WORKSPACE/ccache" mkdir -p "$CCACHE_DIR" df -h - make -j 1 -C _build chain_test - make -j 1 -C _build cli_test - make -j 1 -C _build app_test - make -j 1 -C _build es_test - make -j 1 -C _build cli_wallet - make -j 1 -C _build witness_node - make -j 1 -C _build + make -j 2 -C _build chain_test + make -j 2 -C _build cli_test + make -j 2 -C _build app_test + make -j 2 -C _build es_test + make -j 2 -C _build cli_wallet + make -j 2 -C _build witness_node + make -j 2 -C _build df -h du -hs _build/libraries/* _build/programs/* _build/tests/* du -hs _build/* diff --git a/.github/workflows/build-and-test.ubuntu-release.yml b/.github/workflows/build-and-test.ubuntu-release.yml index 3c43237b9b..1976ce317c 100644 --- a/.github/workflows/build-and-test.ubuntu-release.yml +++ b/.github/workflows/build-and-test.ubuntu-release.yml @@ -84,7 +84,7 @@ jobs: run: | export CCACHE_DIR="$GITHUB_WORKSPACE/ccache" mkdir -p "$CCACHE_DIR" - make -j 1 -C _build + make -j 2 -C _build df -h - name: Unit-Tests run: | diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index 482ead8c47..0118fef10d 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -119,7 +119,7 @@ jobs: export CCACHE_DIR="$GITHUB_WORKSPACE/ccache" mkdir -p "$CCACHE_DIR" df -h - programs/build_helpers/make_with_sonar bw-output -j 1 -C _build \ + programs/build_helpers/make_with_sonar bw-output -j 2 -C _build \ witness_node cli_wallet js_operation_serializer get_dev_key network_mapper \ app_test chain_test cli_test es_test df -h From 5aaef870188a42d992b1352d514b46132c37b15f Mon Sep 17 00:00:00 2001 From: Abit Date: Wed, 11 Jan 2023 02:37:00 +0100 Subject: [PATCH 025/127] Update project description and a link --- sonar-project.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonar-project.properties b/sonar-project.properties index 3703c0108d..7227dc8a73 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -2,12 +2,12 @@ sonar.organization=bitshares-on-github sonar.projectKey=bitshares_bitshares-core sonar.projectName=BitShares-Core -sonar.projectDescription=BitShares Blockchain implementation and command-line interface +sonar.projectDescription=BitShares Blockchain node and command-line wallet sonar.projectVersion=6.1.x sonar.host.url=https://sonarcloud.io -sonar.links.homepage=https://bitshares.org +sonar.links.homepage=https://bitshares.github.io sonar.links.ci=https://github.com/bitshares/bitshares-core/actions sonar.links.issue=https://github.com/bitshares/bitshares-core/issues sonar.links.scm=https://github.com/bitshares/bitshares-core/tree/master From ff39fb5b7a646c6dbd649083dcbfa95f9e14a75c Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 22 Jan 2023 13:50:32 +0000 Subject: [PATCH 026/127] Allow settling more than indvd fund when no feed --- libraries/chain/asset_evaluator.cpp | 8 +- libraries/chain/hardfork.d/CORE_2587.hf | 6 + tests/tests/bsrm_indvd_settlement_tests.cpp | 202 ++++++++++++++++++++ 3 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 libraries/chain/hardfork.d/CORE_2587.hf diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index 5e23ece291..f9ca0a2145 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -1341,13 +1341,16 @@ operation_result asset_settle_evaluator::do_apply(const asset_settle_evaluator:: // Process the rest const auto& head_time = d.head_block_time(); - const auto& maint_time = d.get_dynamic_global_properties().next_maintenance_time; - d.adjust_balance( op.account, -to_settle ); bool after_core_hardfork_2582 = HARDFORK_CORE_2582_PASSED( head_time ); // Price feed issues if( after_core_hardfork_2582 && 0 == to_settle.amount ) return result; + bool after_core_hardfork_2587 = HARDFORK_CORE_2587_PASSED( head_time ); + if( after_core_hardfork_2587 && bitasset.current_feed.settlement_price.is_null() ) + return result; + + d.adjust_balance( op.account, -to_settle ); const auto& settle = d.create( [&op,&to_settle,&head_time,&bitasset](force_settlement_object& s) { s.owner = op.account; @@ -1357,6 +1360,7 @@ operation_result asset_settle_evaluator::do_apply(const asset_settle_evaluator:: result.value.new_objects = flat_set({ settle.id }); + const auto& maint_time = d.get_dynamic_global_properties().next_maintenance_time; if( HARDFORK_CORE_2481_PASSED( maint_time ) ) { d.apply_force_settlement( settle, bitasset, *asset_to_settle ); diff --git a/libraries/chain/hardfork.d/CORE_2587.hf b/libraries/chain/hardfork.d/CORE_2587.hf new file mode 100644 index 0000000000..cc98fa4f26 --- /dev/null +++ b/libraries/chain/hardfork.d/CORE_2587.hf @@ -0,0 +1,6 @@ +// bitshares-core issue #2587 settle more than total debt in individual settlement fund when no sufficient price feeds +#ifndef HARDFORK_CORE_2587_TIME +// Jan 1 2030, midnight; this is a dummy date until a hardfork date is scheduled +#define HARDFORK_CORE_2587_TIME (fc::time_point_sec( 1893456000 )) +#define HARDFORK_CORE_2587_PASSED(head_block_time) (head_block_time >= HARDFORK_CORE_2587_TIME) +#endif diff --git a/tests/tests/bsrm_indvd_settlement_tests.cpp b/tests/tests/bsrm_indvd_settlement_tests.cpp index 26e567d3ad..0d85638f9d 100644 --- a/tests/tests/bsrm_indvd_settlement_tests.cpp +++ b/tests/tests/bsrm_indvd_settlement_tests.cpp @@ -816,6 +816,208 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_disable_force_settle_tes } FC_CAPTURE_AND_RETHROW() } +/// Tests individual settlement to fund : if there is no sufficient price feeds, +/// * before core-2587 hard fork, cannot settle an amount more than the fund, +/// * after core-2587 hard fork, can settle an amount more than the fund: only pay from the fund, no settle order. +BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_no_feed ) +{ try { + + // Advance to core-2467 hard fork + auto mi = db.get_global_properties().parameters.maintenance_interval; + generate_blocks(HARDFORK_CORE_2467_TIME - mi); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + { + set_expiration( db, trx ); + + ACTORS((sam)(feeder)(borrower)(borrower2)(seller)); + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( sam, asset(init_amount) ); + fund( feeder, asset(init_amount) ); + + using bsrm_type = bitasset_options::black_swan_response_type; + uint8_t bsrm_value = static_cast(bsrm_type::individual_settlement_to_fund); + + // Create asset + asset_id_type samcoin_id = create_user_issued_asset( "SAMCOIN", sam_id(db), charge_market_fee, + price(asset(1, asset_id_type(1)), asset(1)), + 2, 100 ).get_id(); // fee 1% + issue_uia( borrower, asset(init_amount, samcoin_id) ); + issue_uia( borrower2, asset(init_amount, samcoin_id) ); + + asset_create_operation acop; + acop.issuer = sam_id; + acop.symbol = "SAMMPA"; + acop.precision = 2; + acop.common_options.core_exchange_rate = price(asset(1,asset_id_type(1)),asset(1)); + acop.common_options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; + acop.common_options.market_fee_percent = 100; // 1% + acop.common_options.flags = charge_market_fee; + acop.common_options.issuer_permissions = ASSET_ISSUER_PERMISSION_ENABLE_BITS_MASK; + acop.bitasset_opts = bitasset_options(); + acop.bitasset_opts->minimum_feeds = 1; + acop.bitasset_opts->feed_lifetime_sec = 300; + acop.bitasset_opts->short_backing_asset = samcoin_id; + acop.bitasset_opts->extensions.value.black_swan_response_method = bsrm_value; + acop.bitasset_opts->extensions.value.margin_call_fee_ratio = 11; + acop.bitasset_opts->extensions.value.force_settle_fee_percent = 300; + + trx.operations.clear(); + trx.operations.push_back( acop ); + processed_transaction ptx = PUSH_TX(db, trx, ~0); + const asset_object& mpa = db.get(ptx.operation_results[0].get()); + asset_id_type mpa_id = mpa.get_id(); + + BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() + == bsrm_type::individual_settlement_to_fund ); + + // add a price feed publisher and publish a feed + update_feed_producers( mpa_id, { feeder_id } ); + + price_feed f; + f.settlement_price = price( asset(100,mpa_id), asset(1,samcoin_id) ); + f.core_exchange_rate = price( asset(100,mpa_id), asset(1) ); + f.maintenance_collateral_ratio = 1850; + f.maximum_short_squeeze_ratio = 1250; + + uint16_t feed_icr = 1900; + + publish_feed( mpa_id, feeder_id, f, feed_icr ); + + BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); + + // borrowers borrow some + // undercollateralization price = 100000:2000 * 1250:1000 = 100000:1600 + const call_order_object* call_ptr = borrow( borrower, asset(100000, mpa_id), asset(2000, samcoin_id) ); + BOOST_REQUIRE( call_ptr ); + call_order_id_type call_id = call_ptr->get_id(); + + // undercollateralization price = 100000:2500 * 1250:1000 = 100000:2000 + const call_order_object* call2_ptr = borrow( borrower2, asset(100000, mpa_id), asset(2500, samcoin_id) ); + BOOST_REQUIRE( call2_ptr ); + call_order_id_type call2_id = call2_ptr->get_id(); + + // Transfer funds to sellers + transfer( borrower, seller, asset(100000,mpa_id) ); + transfer( borrower2, seller, asset(100000,mpa_id) ); + + BOOST_CHECK_EQUAL( call_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call_id(db).collateral.value, 2000 ); + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 2500 ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 200000 ); + BOOST_CHECK_EQUAL( get_balance( seller_id, samcoin_id ), 0 ); + + // publish a new feed so that borrower's debt position is undercollateralized + f.settlement_price = price( asset(100000,mpa_id), asset(1650,samcoin_id) ); + publish_feed( mpa_id, feeder_id, f, feed_icr ); + // call pays price = 100000:1650 * 1000:1250 = 100000:2062.5 = 48.484848485 + // call match price = 100000:1650 * 1000:1239 = 100000:2048.75 = 48.915303153 + + // check + BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); + + // call: margin call fee deducted = round_down(2000*11/1250) = 17, + // fund receives 2000 - 17 = 1983 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1983 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 100000 ); + + BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price + == price( asset(100000*1239,mpa_id), asset(1983*1000,samcoin_id) ) ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); + + BOOST_CHECK( !db.find( call_id ) ); + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 2500 ); + + // let the feed expire + { + generate_blocks( db.head_block_time() + fc::seconds(350) ); + set_expiration( db, trx ); + + BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price.is_null() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price.is_null() ); + + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); + + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1983 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 100000 ); + + BOOST_CHECK( !db.find( call_id ) ); + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 2500 ); + } + + // Before core-2587 hard fork, unable to settle more than the fund when no feed + BOOST_CHECK_THROW( force_settle( seller, asset(100001,mpa_id) ), fc::exception ); + + // Advance to core-2587 hard fork + generate_blocks(HARDFORK_CORE_2587_TIME - mi); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + set_expiration( db, trx ); + + // able to settle more than the fund + auto result = force_settle( seller_id(db), asset(100001,mpa_id) ); + auto op_result = result.get().value; + + auto check_result = [&] + { + // seller gets 1983, market fee 19, finally gets 1964 + // seller pays 100000 + BOOST_CHECK( !op_result.new_objects.valid() ); // no delayed force settlement + BOOST_REQUIRE( op_result.paid.valid() && 1U == op_result.paid->size() ); + BOOST_CHECK( *op_result.paid->begin() == asset( 100000, mpa_id ) ); + BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() ); + BOOST_CHECK( *op_result.received->begin() == asset( 1964, samcoin_id ) ); + BOOST_REQUIRE( op_result.fees.valid() && 1U == op_result.fees->size() ); + BOOST_CHECK( *op_result.fees->begin() == asset( 19, samcoin_id ) ); + // fund is now empty + + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); + + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); + + BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price.is_null() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price.is_null() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); + + BOOST_CHECK( !db.find( call_id ) ); + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 2500 ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 100000 ); // 200000 - 100000 + BOOST_CHECK_EQUAL( get_balance( seller_id, samcoin_id ), 1964 ); + + // Unable to settle when the fund is empty and no feed + BOOST_CHECK_THROW( force_settle( seller, asset(1000,mpa_id) ), fc::exception ); + }; + + check_result(); + + BOOST_TEST_MESSAGE( "Generate a block" ); + generate_block(); + + check_result(); + + } + +} FC_CAPTURE_AND_RETHROW() } + /// Tests individual settlement to fund : settles when price drops, and how taker orders would match after that BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_test ) { try { From eb0e5ce354963e36258eff1f310f17ff52eed23b Mon Sep 17 00:00:00 2001 From: Abit Date: Thu, 26 Jan 2023 21:17:13 +0100 Subject: [PATCH 027/127] Fix network_mapper 1. crash when a node_id is invalid 2. hang when a peer does not respond --- programs/network_mapper/network_mapper.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/programs/network_mapper/network_mapper.cpp b/programs/network_mapper/network_mapper.cpp index f623a46d06..2ec167b005 100644 --- a/programs/network_mapper/network_mapper.cpp +++ b/programs/network_mapper/network_mapper.cpp @@ -22,6 +22,7 @@ class peer_probe : public graphene::net::peer_connection_delegate bool _done = false; graphene::net::peer_connection_ptr _connection = graphene::net::peer_connection::make_shared(this); fc::promise::ptr _probe_complete_promise = fc::promise::create("probe_complete"); + fc::future _timeout_handler; fc::ip::endpoint _remote; graphene::net::node_id_t _node_id; @@ -50,6 +51,15 @@ class peer_probe : public graphene::net::peer_connection_delegate chain_id, fc::variant_object()); + constexpr uint16_t timeout = 180; // seconds + _timeout_handler = fc::schedule( [this]() { + wlog( "Communication with peer ${remote} took too long, closing connection", ("remote", _remote) ); + wdump( (_peers)(_peers.size()) ); + _timeout_handler = fc::future(); + _we_closed_connection = true; + _connection->close_connection(); + }, fc::time_point::now() + fc::seconds(timeout), "timeout_handler" ); + _connection->send_message(hello); } catch( const fc::exception& e ) { ilog( "Got exception when connecting to peer ${endpoint} ${e}", @@ -156,8 +166,9 @@ class peer_probe : public graphene::net::peer_connection_delegate { // Note: In rare cases, the peer may neither send us an address_message nor close the connection, // causing us to wait forever. - // We tolerate it, because this program (network_mapper) is not critical. + // In this case the timeout handler will close the connection. _done = true; + _timeout_handler.cancel(); _probe_complete_promise->set_value(); } @@ -230,7 +241,7 @@ int main(int argc, char** argv) const auto& update_info_by_address_info = [ &address_info_by_node_id, &my_node_id, &nodes_already_visited, &nodes_to_visit_set, &nodes_to_visit ] ( const graphene::net::address_info& info ) { - if (info.node_id == my_node_id) // We should not be in the list, just be defensive here + if( info.node_id == graphene::net::node_id_t(my_node_id) ) // We should not be in the list, be defensive return; if (nodes_already_visited.find(info.remote_endpoint) == nodes_already_visited.end() && nodes_to_visit_set.find(info.remote_endpoint) == nodes_to_visit_set.end()) @@ -361,7 +372,8 @@ int main(int argc, char** argv) constexpr uint16_t pair_depth = 2; for (auto& node_and_connections : connections_by_node_id) for (const graphene::net::address_info& this_connection : node_and_connections.second) - if( this_connection.node_id != my_node_id ) // We should not be in the list, just be defensive here + if( this_connection.node_id != graphene::net::node_id_t(my_node_id) ) // We should not be in the list, + // just be defensive here dot_stream << " \"" << fc::variant( node_and_connections.first, pair_depth ).as_string() << "\" -- \"" << fc::variant( this_connection.node_id, 1 ).as_string() << "\";\n"; From 715b21278ccf2391d33a141863506d87074f9cd4 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 24 Jan 2023 19:18:31 +0000 Subject: [PATCH 028/127] Add liquidity_pool_update_operation --- libraries/chain/db_init.cpp | 1 + libraries/chain/db_notify.cpp | 4 ++ libraries/chain/hardfork.d/CORE_2604.hf | 6 +++ .../graphene/chain/hardfork_visitor.hpp | 4 ++ .../chain/liquidity_pool_evaluator.hpp | 11 ++++++ libraries/chain/liquidity_pool_evaluator.cpp | 38 +++++++++++++++++++ libraries/chain/proposal_evaluator.cpp | 7 ++++ .../market_history/market_history_plugin.cpp | 5 +++ .../graphene/protocol/liquidity_pool.hpp | 25 ++++++++++++ .../include/graphene/protocol/operations.hpp | 3 +- libraries/protocol/liquidity_pool.cpp | 12 ++++++ 11 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 libraries/chain/hardfork.d/CORE_2604.hf diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 527902aa52..d64c4abc7a 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -133,6 +133,7 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); + register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index 1e43bcdc00..c33b4f331b 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -326,6 +326,10 @@ struct get_impacted_account_visitor { _impacted.insert( op.fee_payer() ); // account } + void operator()( const liquidity_pool_update_operation& op ) + { + _impacted.insert( op.fee_payer() ); // account + } void operator()( const liquidity_pool_deposit_operation& op ) { _impacted.insert( op.fee_payer() ); // account diff --git a/libraries/chain/hardfork.d/CORE_2604.hf b/libraries/chain/hardfork.d/CORE_2604.hf new file mode 100644 index 0000000000..b71dc39551 --- /dev/null +++ b/libraries/chain/hardfork.d/CORE_2604.hf @@ -0,0 +1,6 @@ +// bitshares-core issue #2604 Allow updating liquidity pool fee rates with certain restrictions +#ifndef HARDFORK_CORE_2604_TIME +// Jan 1 2030, midnight; this is a dummy date until a hardfork date is scheduled +#define HARDFORK_CORE_2604_TIME (fc::time_point_sec( 1893456000 )) +#define HARDFORK_CORE_2604_PASSED(head_block_time) (head_block_time >= HARDFORK_CORE_2604_TIME) +#endif diff --git a/libraries/chain/include/graphene/chain/hardfork_visitor.hpp b/libraries/chain/include/graphene/chain/hardfork_visitor.hpp index fb284f78db..58af053493 100644 --- a/libraries/chain/include/graphene/chain/hardfork_visitor.hpp +++ b/libraries/chain/include/graphene/chain/hardfork_visitor.hpp @@ -54,6 +54,7 @@ struct hardfork_visitor { protocol::liquidity_pool_deposit_operation, protocol::liquidity_pool_withdraw_operation, protocol::liquidity_pool_exchange_operation >; + using liquidity_pool_update_op = fc::typelist::list< protocol::liquidity_pool_update_operation >; using samet_fund_ops = fc::typelist::list< protocol::samet_fund_create_operation, protocol::samet_fund_delete_operation, protocol::samet_fund_update_operation, @@ -90,6 +91,9 @@ struct hardfork_visitor { template std::enable_if_t(), bool> visit() { return HARDFORK_CORE_2362_PASSED(now); } + template + std::enable_if_t(), bool> + visit() { return HARDFORK_CORE_2604_PASSED(now); } /// @} /// typelist::runtime::dispatch adaptor diff --git a/libraries/chain/include/graphene/chain/liquidity_pool_evaluator.hpp b/libraries/chain/include/graphene/chain/liquidity_pool_evaluator.hpp index e7de47be76..ad9a653220 100644 --- a/libraries/chain/include/graphene/chain/liquidity_pool_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/liquidity_pool_evaluator.hpp @@ -55,6 +55,17 @@ namespace graphene { namespace chain { const asset_object* _share_asset = nullptr; }; + class liquidity_pool_update_evaluator : public evaluator + { + public: + using operation_type = liquidity_pool_update_operation; + + void_result do_evaluate( const liquidity_pool_update_operation& op ); + void_result do_apply( const liquidity_pool_update_operation& op ) const; + + const liquidity_pool_object* _pool = nullptr; + }; + class liquidity_pool_deposit_evaluator : public evaluator { public: diff --git a/libraries/chain/liquidity_pool_evaluator.cpp b/libraries/chain/liquidity_pool_evaluator.cpp index d0c6d14e9d..07b273f5f6 100644 --- a/libraries/chain/liquidity_pool_evaluator.cpp +++ b/libraries/chain/liquidity_pool_evaluator.cpp @@ -114,6 +114,44 @@ generic_operation_result liquidity_pool_delete_evaluator::do_apply(const liquidi return result; } FC_CAPTURE_AND_RETHROW( (op) ) } +void_result liquidity_pool_update_evaluator::do_evaluate(const liquidity_pool_update_operation& op) +{ try { + const database& d = db(); + const auto block_time = d.head_block_time(); + + FC_ASSERT( HARDFORK_CORE_2604_PASSED(block_time), "Not allowed until the LP hardfork" ); + + _pool = &op.pool(d); + + const asset_object* _share_asset = &_pool->share_asset(d); + + FC_ASSERT( _share_asset->issuer == op.account, "The account is not the owner of the liquidity pool" ); + + if( op.taker_fee_percent.valid() ) + { + FC_ASSERT( 0 == _pool->withdrawal_fee_percent + || ( op.withdrawal_fee_percent.valid() && 0 == *op.withdrawal_fee_percent ), + "Taker fee percent can only be updated if withdrawal fee percent is zero or " + "withdrawal fee percent is to be updated to zero at the same time" ); + } + + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + +void_result liquidity_pool_update_evaluator::do_apply(const liquidity_pool_update_operation& op) const +{ try { + database& d = db(); + + d.modify( *_pool, [&op](liquidity_pool_object& obj) { + if( op.taker_fee_percent.valid() ) + obj.taker_fee_percent = *op.taker_fee_percent; + if( op.withdrawal_fee_percent.valid() ) + obj.withdrawal_fee_percent = *op.withdrawal_fee_percent; + }); + + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + void_result liquidity_pool_deposit_evaluator::do_evaluate(const liquidity_pool_deposit_operation& op) { try { const database& d = db(); diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index 0e16e1d904..1e39c02539 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -205,6 +205,10 @@ struct proposal_operation_hardfork_visitor FC_ASSERT(!op.new_parameters.current_fees->exists(), "Unable to define fees for credit offer operations prior to the core-2362 hardfork"); } + if (!HARDFORK_CORE_2604_PASSED(block_time)) { + FC_ASSERT(!op.new_parameters.current_fees->exists(), + "Unable to define fees for liquidity pool update operation prior to the core-2604 hardfork"); + } } void operator()(const graphene::chain::htlc_create_operation &op) const { FC_ASSERT( block_time >= HARDFORK_CORE_1468_TIME, "Not allowed until hardfork 1468" ); @@ -246,6 +250,9 @@ struct proposal_operation_hardfork_visitor void operator()(const graphene::chain::liquidity_pool_delete_operation&) const { FC_ASSERT( HARDFORK_LIQUIDITY_POOL_PASSED(block_time), "Not allowed until the LP hardfork" ); } + void operator()(const graphene::chain::liquidity_pool_update_operation&) const { + FC_ASSERT( HARDFORK_CORE_2604_PASSED(block_time), "Not allowed until the core-2604 hardfork" ); + } void operator()(const graphene::chain::liquidity_pool_deposit_operation&) const { FC_ASSERT( HARDFORK_LIQUIDITY_POOL_PASSED(block_time), "Not allowed until the LP hardfork" ); } diff --git a/libraries/plugins/market_history/market_history_plugin.cpp b/libraries/plugins/market_history/market_history_plugin.cpp index 839117de85..b4dfa9dba9 100644 --- a/libraries/plugins/market_history/market_history_plugin.cpp +++ b/libraries/plugins/market_history/market_history_plugin.cpp @@ -511,6 +511,11 @@ struct get_liquidity_pool_id_visitor return o.pool; } + result_type operator()( const liquidity_pool_update_operation& o )const + { + return o.pool; + } + result_type operator()( const liquidity_pool_deposit_operation& o )const { return o.pool; diff --git a/libraries/protocol/include/graphene/protocol/liquidity_pool.hpp b/libraries/protocol/include/graphene/protocol/liquidity_pool.hpp index 712090de3c..8cc0ef26ba 100644 --- a/libraries/protocol/include/graphene/protocol/liquidity_pool.hpp +++ b/libraries/protocol/include/graphene/protocol/liquidity_pool.hpp @@ -67,6 +67,26 @@ namespace graphene { namespace protocol { void validate()const; }; + /** + * @brief Update a liquidity pool + * @ingroup operations + */ + struct liquidity_pool_update_operation : public base_operation + { + struct fee_parameters_type { uint64_t fee = 0; }; + + asset fee; ///< Operation fee + account_id_type account; ///< The account who owns the liquidity pool + liquidity_pool_id_type pool; ///< ID of the liquidity pool + optional taker_fee_percent; ///< Taker fee percent + optional withdrawal_fee_percent; ///< Withdrawal fee percent + + extensions_type extensions; ///< Unused. Reserved for future use. + + account_id_type fee_payer()const { return account; } + void validate()const; + }; + /** * @brief Deposit to a liquidity pool * @ingroup operations @@ -135,6 +155,7 @@ namespace graphene { namespace protocol { FC_REFLECT( graphene::protocol::liquidity_pool_create_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::protocol::liquidity_pool_delete_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::liquidity_pool_update_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::protocol::liquidity_pool_deposit_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::protocol::liquidity_pool_withdraw_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::protocol::liquidity_pool_exchange_operation::fee_parameters_type, (fee) ) @@ -144,6 +165,8 @@ FC_REFLECT( graphene::protocol::liquidity_pool_create_operation, (taker_fee_percent)(withdrawal_fee_percent)(extensions) ) FC_REFLECT( graphene::protocol::liquidity_pool_delete_operation, (fee)(account)(pool)(extensions) ) +FC_REFLECT( graphene::protocol::liquidity_pool_update_operation, + (fee)(account)(pool)(taker_fee_percent)(withdrawal_fee_percent)(extensions) ) FC_REFLECT( graphene::protocol::liquidity_pool_deposit_operation, (fee)(account)(pool)(amount_a)(amount_b)(extensions) ) FC_REFLECT( graphene::protocol::liquidity_pool_withdraw_operation, @@ -153,12 +176,14 @@ FC_REFLECT( graphene::protocol::liquidity_pool_exchange_operation, GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_create_operation::fee_parameters_type ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_delete_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_update_operation::fee_parameters_type ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_deposit_operation::fee_parameters_type ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_withdraw_operation::fee_parameters_type ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_exchange_operation::fee_parameters_type ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_delete_operation ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_update_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_deposit_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_withdraw_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_exchange_operation ) diff --git a/libraries/protocol/include/graphene/protocol/operations.hpp b/libraries/protocol/include/graphene/protocol/operations.hpp index 0b32f7e5da..798c400593 100644 --- a/libraries/protocol/include/graphene/protocol/operations.hpp +++ b/libraries/protocol/include/graphene/protocol/operations.hpp @@ -127,7 +127,8 @@ namespace graphene { namespace protocol { /* 71 */ credit_offer_update_operation, /* 72 */ credit_offer_accept_operation, /* 73 */ credit_deal_repay_operation, - /* 74 */ credit_deal_expired_operation // VIRTUAL + /* 74 */ credit_deal_expired_operation, // VIRTUAL + /* 75 */ liquidity_pool_update_operation >; /// @} // operations group diff --git a/libraries/protocol/liquidity_pool.cpp b/libraries/protocol/liquidity_pool.cpp index 956273609d..a2e290227b 100644 --- a/libraries/protocol/liquidity_pool.cpp +++ b/libraries/protocol/liquidity_pool.cpp @@ -42,6 +42,16 @@ void liquidity_pool_delete_operation::validate()const FC_ASSERT( fee.amount >= 0, "Fee should not be negative" ); } +void liquidity_pool_update_operation::validate()const +{ + FC_ASSERT( fee.amount >= 0, "Fee should not be negative" ); + FC_ASSERT( taker_fee_percent.valid() || withdrawal_fee_percent.valid(), "Should update something" ); + if( taker_fee_percent.valid() ) + FC_ASSERT( *taker_fee_percent <= GRAPHENE_100_PERCENT, "Taker fee percent should not exceed 100%" ); + if( withdrawal_fee_percent.valid() ) + FC_ASSERT( 0 == *withdrawal_fee_percent, "Withdrawal fee percent can only be updated to zero" ); +} + void liquidity_pool_deposit_operation::validate()const { FC_ASSERT( fee.amount >= 0, "Fee should not be negative" ); @@ -69,12 +79,14 @@ void liquidity_pool_exchange_operation::validate()const GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_create_operation::fee_parameters_type ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_delete_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_update_operation::fee_parameters_type ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_deposit_operation::fee_parameters_type ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_withdraw_operation::fee_parameters_type ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_exchange_operation::fee_parameters_type ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_create_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_delete_operation ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_update_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_deposit_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_withdraw_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_exchange_operation ) From cd10dc5c670aabb393d346cea0f7c358ab2583d8 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 27 Jan 2023 14:03:46 +0000 Subject: [PATCH 029/127] Add tests for liquidity_pool_update_operation --- tests/common/database_fixture.cpp | 29 +++++ tests/common/database_fixture.hpp | 7 ++ tests/tests/liquidity_pool_tests.cpp | 158 +++++++++++++++++++++++++++ 3 files changed, 194 insertions(+) diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 8a8997390a..714e4ededb 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -1533,6 +1533,35 @@ generic_operation_result database_fixture_base::delete_liquidity_pool( account_i return op_result.get(); } +liquidity_pool_update_operation database_fixture_base::make_liquidity_pool_update_op( account_id_type account, + liquidity_pool_id_type pool, + optional taker_fee_percent, + optional withdrawal_fee_percent )const +{ + liquidity_pool_update_operation op; + op.account = account; + op.pool = pool; + op.taker_fee_percent = taker_fee_percent; + op.withdrawal_fee_percent = withdrawal_fee_percent; + return op; +} + +void database_fixture_base::update_liquidity_pool( account_id_type account, + liquidity_pool_id_type pool, + optional taker_fee_percent, + optional withdrawal_fee_percent ) +{ + liquidity_pool_update_operation op = make_liquidity_pool_update_op( account, pool, taker_fee_percent, + withdrawal_fee_percent ); + trx.operations.clear(); + trx.operations.push_back( op ); + + for( auto& o : trx.operations ) db.current_fee_schedule().set_fee(o); + trx.validate(); + set_expiration( db, trx ); + PUSH_TX(db, trx, ~0); +} + liquidity_pool_deposit_operation database_fixture_base::make_liquidity_pool_deposit_op( account_id_type account, liquidity_pool_id_type pool, const asset& amount_a, const asset& amount_b )const diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index 340031b38e..0ee63be250 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -440,6 +440,13 @@ struct database_fixture_base { liquidity_pool_delete_operation make_liquidity_pool_delete_op( account_id_type account, liquidity_pool_id_type pool )const; generic_operation_result delete_liquidity_pool( account_id_type account, liquidity_pool_id_type pool ); + liquidity_pool_update_operation make_liquidity_pool_update_op( account_id_type account, + liquidity_pool_id_type pool, + optional taker_fee_percent, + optional withdrawal_fee_percent )const; + void update_liquidity_pool( account_id_type account, liquidity_pool_id_type pool, + optional taker_fee_percent, + optional withdrawal_fee_percent ); liquidity_pool_deposit_operation make_liquidity_pool_deposit_op( account_id_type account, liquidity_pool_id_type pool, const asset& amount_a, const asset& amount_b )const; diff --git a/tests/tests/liquidity_pool_tests.cpp b/tests/tests/liquidity_pool_tests.cpp index d0c9d1c085..2f40bf744c 100644 --- a/tests/tests/liquidity_pool_tests.cpp +++ b/tests/tests/liquidity_pool_tests.cpp @@ -94,6 +94,164 @@ BOOST_AUTO_TEST_CASE( liquidity_pool_hardfork_time_test ) } } +BOOST_AUTO_TEST_CASE( liquidity_pool_update_hardfork_time_test ) +{ + try { + + // Proceeds to a recent hard fork + generate_blocks( HARDFORK_LIQUIDITY_POOL_TIME ); + set_expiration( db, trx ); + + ACTORS((sam)); + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( sam, asset(init_amount) ); + + const asset_object& core = asset_id_type()(db); + const asset_object& usd = create_user_issued_asset( "MYUSD" ); + const asset_object& lpa = create_user_issued_asset( "LPATEST", sam, charge_market_fee ); + + const liquidity_pool_object& lpo = create_liquidity_pool( sam_id, core.get_id(), usd.get_id(), lpa.get_id(), + 0, 0 ); + + // Before the hard fork, unable to update a liquidity pool + // or update with proposals + BOOST_CHECK_THROW( update_liquidity_pool( sam_id, lpo.get_id(), 1, 0 ), fc::exception ); + + liquidity_pool_update_operation updop = make_liquidity_pool_update_op( sam_id, lpo.get_id(), 1, 0 ); + BOOST_CHECK_THROW( propose( updop ), fc::exception ); + + } catch (fc::exception& e) { + edump((e.to_detail_string())); + throw; + } +} + +BOOST_AUTO_TEST_CASE( liquidity_pool_update_test ) +{ + try { + + // Pass the hard fork time + generate_blocks( HARDFORK_CORE_2604_TIME ); + set_expiration( db, trx ); + + ACTORS((sam)(ted)); + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( sam, asset(init_amount) ); + fund( ted, asset(init_amount) ); + + const asset_object& core = asset_id_type()(db); + const asset_object& usd = create_user_issued_asset( "MYUSD" ); + issue_uia( sam, usd.amount(init_amount) ); + issue_uia( ted, usd.amount(init_amount) ); + + const asset_object& lpa1 = create_user_issued_asset( "LPATEST1", sam, charge_market_fee ); + const asset_object& lpa2 = create_user_issued_asset( "LPATEST2", ted, charge_market_fee ); + + const liquidity_pool_object& lpo1 = create_liquidity_pool( sam_id, core.get_id(), usd.get_id(), lpa1.get_id(), + 0, 0 ); + + BOOST_CHECK( lpo1.asset_a == core.id ); + BOOST_CHECK( lpo1.asset_b == usd.id ); + BOOST_CHECK( lpo1.balance_a == 0 ); + BOOST_CHECK( lpo1.balance_b == 0 ); + BOOST_CHECK( lpo1.share_asset == lpa1.id ); + BOOST_CHECK( lpo1.taker_fee_percent == 0 ); + BOOST_CHECK( lpo1.withdrawal_fee_percent == 0 ); + BOOST_CHECK( lpo1.virtual_value == 0 ); + + deposit_to_liquidity_pool( sam_id, lpo1.get_id(), asset(10), asset( 20, usd.get_id() ) ); + + BOOST_CHECK( lpo1.asset_a == core.id ); + BOOST_CHECK( lpo1.asset_b == usd.id ); + BOOST_CHECK( lpo1.balance_a == 10 ); + BOOST_CHECK( lpo1.balance_b == 20 ); + BOOST_CHECK( lpo1.share_asset == lpa1.id ); + BOOST_CHECK( lpo1.taker_fee_percent == 0 ); + BOOST_CHECK( lpo1.withdrawal_fee_percent == 0 ); + BOOST_CHECK( lpo1.virtual_value == 200 ); + + const liquidity_pool_object& lpo2 = create_liquidity_pool( ted_id, core.get_id(), usd.get_id(), lpa2.get_id(), + 1, 2 ); + + BOOST_CHECK( lpo2.asset_a == core.id ); + BOOST_CHECK( lpo2.asset_b == usd.id ); + BOOST_CHECK( lpo2.balance_a == 0 ); + BOOST_CHECK( lpo2.balance_b == 0 ); + BOOST_CHECK( lpo2.share_asset == lpa2.id ); + BOOST_CHECK( lpo2.taker_fee_percent == 1 ); + BOOST_CHECK( lpo2.withdrawal_fee_percent == 2 ); + BOOST_CHECK( lpo2.virtual_value == 0 ); + + // Able to propose + { + liquidity_pool_update_operation updop = make_liquidity_pool_update_op( sam_id, lpo1.get_id(), 1, 0 ); + propose( updop ); + } + + // Unable to update a liquidity pool with invalid data + // update nothing + BOOST_CHECK_THROW( update_liquidity_pool( sam_id, lpo1.get_id(), {}, {} ), fc::exception ); + BOOST_CHECK_THROW( propose( make_liquidity_pool_update_op( sam_id, lpo1.get_id(), {}, {} ) ), fc::exception ); + // non-zero withdrawal fee + BOOST_CHECK_THROW( update_liquidity_pool( sam_id, lpo1.get_id(), {}, 1 ), fc::exception ); + BOOST_CHECK_THROW( propose( make_liquidity_pool_update_op( sam_id, lpo1.get_id(), {}, 1 ) ), fc::exception ); + BOOST_CHECK_THROW( update_liquidity_pool( sam_id, lpo1.get_id(), 0, 1 ), fc::exception ); + BOOST_CHECK_THROW( propose( make_liquidity_pool_update_op( sam_id, lpo1.get_id(), 0, 1 ) ), fc::exception ); + // taker fee exceeds 100% + BOOST_CHECK_THROW( update_liquidity_pool( sam_id, lpo1.get_id(), 10001, {} ), fc::exception ); + BOOST_CHECK_THROW( update_liquidity_pool( sam_id, lpo1.get_id(), 10001, 0 ), fc::exception ); + BOOST_CHECK_THROW( propose( make_liquidity_pool_update_op( sam_id, lpo1.get_id(), 10001, {} ) ), fc::exception); + BOOST_CHECK_THROW( propose( make_liquidity_pool_update_op( sam_id, lpo1.get_id(), 10001, 0 ) ), fc::exception ); + // Owner mismatch (able to propose) + BOOST_CHECK_THROW( update_liquidity_pool( ted_id, lpo1.get_id(), 1, {} ), fc::exception ); + propose( make_liquidity_pool_update_op( ted_id, lpo1.get_id(), 1, {} ) ); + // Updating taker fee when withdrawal fee is non-zero (able to propose) + BOOST_CHECK_THROW( update_liquidity_pool( ted_id, lpo2.get_id(), 1, {} ), fc::exception ); + propose( make_liquidity_pool_update_op( ted_id, lpo2.get_id(), 1, {} ) ); + + // Sam is able to update lpo1 + update_liquidity_pool( sam_id, lpo1.get_id(), 2, 0 ); + BOOST_CHECK( lpo1.asset_a == core.id ); + BOOST_CHECK( lpo1.asset_b == usd.id ); + BOOST_CHECK( lpo1.balance_a == 10 ); + BOOST_CHECK( lpo1.balance_b == 20 ); + BOOST_CHECK( lpo1.share_asset == lpa1.id ); + BOOST_CHECK( lpo1.taker_fee_percent == 2 ); + BOOST_CHECK( lpo1.withdrawal_fee_percent == 0 ); + BOOST_CHECK( lpo1.virtual_value == 200 ); + + update_liquidity_pool( sam_id, lpo1.get_id(), 1, {} ); + BOOST_CHECK( lpo1.asset_a == core.id ); + BOOST_CHECK( lpo1.asset_b == usd.id ); + BOOST_CHECK( lpo1.balance_a == 10 ); + BOOST_CHECK( lpo1.balance_b == 20 ); + BOOST_CHECK( lpo1.share_asset == lpa1.id ); + BOOST_CHECK( lpo1.taker_fee_percent == 1 ); + BOOST_CHECK( lpo1.withdrawal_fee_percent == 0 ); + BOOST_CHECK( lpo1.virtual_value == 200 ); + + // Sam is able to update lpo2 if to update its withdrawal fee to 0 + update_liquidity_pool( ted_id, lpo2.get_id(), 2, 0 ); + + BOOST_CHECK( lpo2.asset_a == core.id ); + BOOST_CHECK( lpo2.asset_b == usd.id ); + BOOST_CHECK( lpo2.balance_a == 0 ); + BOOST_CHECK( lpo2.balance_b == 0 ); + BOOST_CHECK( lpo2.share_asset == lpa2.id ); + BOOST_CHECK( lpo2.taker_fee_percent == 2 ); + BOOST_CHECK( lpo2.withdrawal_fee_percent == 0 ); + BOOST_CHECK( lpo2.virtual_value == 0 ); + + generate_block(); + + } catch (fc::exception& e) { + edump((e.to_detail_string())); + throw; + } +} + BOOST_AUTO_TEST_CASE( liquidity_pool_create_delete_proposal_test ) { try { From 865ae5d986a13e98ea04bc79a9fcc1b58062e5b8 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 28 Jan 2023 11:46:48 +0000 Subject: [PATCH 030/127] Update default fee of lp_update_op --- libraries/protocol/include/graphene/protocol/liquidity_pool.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/protocol/include/graphene/protocol/liquidity_pool.hpp b/libraries/protocol/include/graphene/protocol/liquidity_pool.hpp index 8cc0ef26ba..0bbed4a288 100644 --- a/libraries/protocol/include/graphene/protocol/liquidity_pool.hpp +++ b/libraries/protocol/include/graphene/protocol/liquidity_pool.hpp @@ -73,7 +73,7 @@ namespace graphene { namespace protocol { */ struct liquidity_pool_update_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 0; }; + struct fee_parameters_type { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee account_id_type account; ///< The account who owns the liquidity pool From 011b523cb67f39a80316506f4c61e88ad98aff03 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 28 Jan 2023 12:14:05 +0000 Subject: [PATCH 031/127] Update an assertion message --- libraries/chain/liquidity_pool_evaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/liquidity_pool_evaluator.cpp b/libraries/chain/liquidity_pool_evaluator.cpp index 07b273f5f6..553910b056 100644 --- a/libraries/chain/liquidity_pool_evaluator.cpp +++ b/libraries/chain/liquidity_pool_evaluator.cpp @@ -119,7 +119,7 @@ void_result liquidity_pool_update_evaluator::do_evaluate(const liquidity_pool_up const database& d = db(); const auto block_time = d.head_block_time(); - FC_ASSERT( HARDFORK_CORE_2604_PASSED(block_time), "Not allowed until the LP hardfork" ); + FC_ASSERT( HARDFORK_CORE_2604_PASSED(block_time), "Not allowed until the core-2604 hardfork" ); _pool = &op.pool(d); From 9e6325fea3ce464751082239360fc5020d80db34 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 29 Jan 2023 12:13:41 +0000 Subject: [PATCH 032/127] Pay force-settlement from settlement funds at MCOP --- libraries/chain/asset_evaluator.cpp | 44 +++++++++++++++++++++++-- libraries/chain/hardfork.d/CORE_2591.hf | 6 ++++ 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 libraries/chain/hardfork.d/CORE_2591.hf diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index f9ca0a2145..4359bc4222 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -1193,6 +1193,31 @@ void_result asset_settle_evaluator::do_evaluate(const asset_settle_evaluator::op return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } +static optional pay_collateral_fees( database& d, + const asset& pays, + const asset& settled_amount, + const asset_object& asset_to_settle, + const asset_bitasset_data_object& bitasset ) +{ + const auto& head_time = d.head_block_time(); + bool after_core_hardfork_2591 = HARDFORK_CORE_2591_PASSED( head_time ); // Tighter peg (fill settlement at MCOP) + if( after_core_hardfork_2591 && !bitasset.current_feed.settlement_price.is_null() ) + { + price fill_price = bitasset.get_margin_call_order_price(); + try + { + asset settled_amount_by_mcop = pays.multiply_and_round_up( fill_price ); // Throws fc::exception if overflow + if( settled_amount_by_mcop < settled_amount ) + { + asset collateral_fees = settled_amount - settled_amount_by_mcop; + asset_to_settle.accumulate_fee( d, collateral_fees ); + return collateral_fees; + } + } FC_CAPTURE_AND_LOG( (pays)(settled_amount)(fill_price) ) // Catch and log the exception + } + return optional(); +} + static extendable_operation_result pay_settle_from_gs_fund( database& d, const asset_settle_evaluator::operation_type& op, const account_object* fee_paying_account, @@ -1229,12 +1254,19 @@ static extendable_operation_result pay_settle_from_gs_fund( database& d, d.adjust_balance( op.account, -pays ); asset issuer_fees( 0, bitasset.options.short_backing_asset ); + optional collateral_fees; + if( settled_amount.amount > 0 ) { d.modify( bitasset, [&settled_amount]( asset_bitasset_data_object& obj ){ obj.settlement_fund -= settled_amount.amount; }); + // Calculate and pay collateral fees after HF core-2591 + collateral_fees = pay_collateral_fees( d, pays, settled_amount, asset_to_settle, bitasset ); + if( collateral_fees.valid() ) + settled_amount -= *collateral_fees; + // The account who settles pays market fees to the issuer of the collateral asset after HF core-1780 // // TODO Check whether the HF check can be removed after the HF. @@ -1259,7 +1291,8 @@ static extendable_operation_result pay_settle_from_gs_fund( database& d, result.value.paid = vector({ pays }); result.value.received = vector({ settled_amount }); - result.value.fees = vector({ issuer_fees }); + result.value.fees = collateral_fees.valid() ? vector({ *collateral_fees, issuer_fees }) + : vector({ issuer_fees }); return result; } @@ -1288,6 +1321,12 @@ static extendable_operation_result pay_settle_from_individual_pool( database& d, d.modify( asset_to_settle.dynamic_asset_data_id(d), [&pays]( asset_dynamic_data_object& obj ){ obj.current_supply -= pays.amount; }); + + // Calculate and pay collateral fees after HF core-2591 + optional collateral_fees = pay_collateral_fees( d, pays, settled_amount, asset_to_settle, bitasset ); + if( collateral_fees.valid() ) + settled_amount -= *collateral_fees; + auto issuer_fees = d.pay_market_fees( fee_paying_account, settled_amount.asset_id(d), settled_amount, false ); settled_amount -= issuer_fees; @@ -1310,7 +1349,8 @@ static extendable_operation_result pay_settle_from_individual_pool( database& d, result.value.paid = vector({ pays }); result.value.received = vector({ settled_amount }); - result.value.fees = vector({ issuer_fees }); + result.value.fees = collateral_fees.valid() ? vector({ *collateral_fees, issuer_fees }) + : vector({ issuer_fees }); return result; } diff --git a/libraries/chain/hardfork.d/CORE_2591.hf b/libraries/chain/hardfork.d/CORE_2591.hf new file mode 100644 index 0000000000..2dc9031d7d --- /dev/null +++ b/libraries/chain/hardfork.d/CORE_2591.hf @@ -0,0 +1,6 @@ +// bitshares-core issue #2591 Tighter peg when collateral price rises and settlement fund or settlement order exists +#ifndef HARDFORK_CORE_2591_TIME +// Jan 1 2030, midnight; this is a dummy date until a hardfork date is scheduled +#define HARDFORK_CORE_2591_TIME (fc::time_point_sec( 1893456000 )) +#define HARDFORK_CORE_2591_PASSED(head_block_time) (head_block_time >= HARDFORK_CORE_2591_TIME) +#endif From 6572b08d9ac816e098354fe2ca911d1805784550 Mon Sep 17 00:00:00 2001 From: abitmore Date: Mon, 30 Jan 2023 17:56:28 +0000 Subject: [PATCH 033/127] Add tests for price paid by indvd settlement fund --- tests/tests/bsrm_indvd_settlement_tests.cpp | 523 +++++++++++++++++++- 1 file changed, 516 insertions(+), 7 deletions(-) diff --git a/tests/tests/bsrm_indvd_settlement_tests.cpp b/tests/tests/bsrm_indvd_settlement_tests.cpp index 0d85638f9d..895a58eb4e 100644 --- a/tests/tests/bsrm_indvd_settlement_tests.cpp +++ b/tests/tests/bsrm_indvd_settlement_tests.cpp @@ -555,7 +555,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_test ) } // for i -} FC_CAPTURE_AND_RETHROW() } +} FC_LOG_AND_RETHROW() } /// Tests individual settlement to fund : if disable_force_settle flag is set, /// * able to settle if the fund is not empty, @@ -814,7 +814,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_disable_force_settle_tes } // for i -} FC_CAPTURE_AND_RETHROW() } +} FC_LOG_AND_RETHROW() } /// Tests individual settlement to fund : if there is no sufficient price feeds, /// * before core-2587 hard fork, cannot settle an amount more than the fund, @@ -1016,7 +1016,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_no_feed ) } -} FC_CAPTURE_AND_RETHROW() } +} FC_LOG_AND_RETHROW() } /// Tests individual settlement to fund : settles when price drops, and how taker orders would match after that BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_test ) @@ -1163,8 +1163,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_test ) BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == price( asset(100000*1239,mpa_id), asset(1983*1000) ) ); BOOST_CHECK( mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); - // call pays price = 100000:1983 * 1239:1250 = 49.984871407 - // call match price = 100000:1983 = 50.428643469 + // call pays price (MSSP) = 100000:1983 * 1239:1250 = 49.984871407 + // call match price (MCOP) = 100000:1983 = 50.428643469 BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK_EQUAL( call2_id(db).debt.value, 100000 ); @@ -1210,7 +1210,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_test ) BOOST_CHECK_EQUAL( get_balance( seller2_id, mpa_id ), 200000 ); BOOST_CHECK_EQUAL( get_balance( seller2_id, asset_id_type() ), 0 ); - // seller sells more, this order is below MSSP so will not be matched right now + // seller sells more, this order is below MCOP so will not be matched right now limit_ptr = create_sell_order( seller, asset(100000,mpa_id), asset(2000) ); // the limit order is not filled BOOST_REQUIRE( limit_ptr ); @@ -1334,7 +1334,516 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_test ) } // for i -} FC_CAPTURE_LOG_AND_RETHROW( (0) ) } +} FC_LOG_AND_RETHROW() } + +/// Tests individual settlement to fund: +/// * Before hf core-2591, forced-settlements are filled at individual settlement fund price +/// * After hf core-2591, forced-settlements are filled at margin call order price (MCOP) +BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_price_test ) +{ try { + + // Advance to a recent hard fork + generate_blocks(HARDFORK_CORE_2582_TIME); + generate_block(); + + // multiple passes, + // i == 0 : before hf core-2591, settle less than the amount of debt in fund + // i == 1 : before hf core-2591, settle exactly the amount of debt in fund + // i == 2 : before hf core-2591, settle more than the amount of debt in fund + // i == 3 : after hf core-2591, settle less than the amount of debt in fund + // i == 4 : after hf core-2591, settle exactly the amount of debt in fund + // i == 5 : after hf core-2591, settle more than the amount of debt in fund + for( int i = 0; i < 6; ++ i ) + { + idump( (i) ); + + if( 3 == i ) + { + // Advance to core-2591 hard fork + generate_blocks(HARDFORK_CORE_2591_TIME); + generate_block(); + } + + set_expiration( db, trx ); + + ACTORS((sam)(feeder)(borrower)(borrower2)(borrower3)(borrower4)(borrower5)(seller)(seller2)); + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( sam, asset(init_amount) ); + fund( feeder, asset(init_amount) ); + fund( borrower, asset(init_amount) ); + fund( borrower2, asset(init_amount) ); + fund( borrower3, asset(init_amount) ); + fund( borrower4, asset(init_amount) ); + fund( borrower5, asset(init_amount) ); + + using bsrm_type = bitasset_options::black_swan_response_type; + uint8_t bsrm_value = static_cast(bsrm_type::individual_settlement_to_fund); + + // Create asset + asset_create_operation acop; + acop.issuer = sam_id; + acop.symbol = "SAMMPA"; + acop.precision = 2; + acop.common_options.core_exchange_rate = price(asset(1,asset_id_type(1)),asset(1)); + acop.common_options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; + acop.common_options.market_fee_percent = 100; // 1% + acop.common_options.flags = charge_market_fee; + acop.common_options.issuer_permissions = ASSET_ISSUER_PERMISSION_ENABLE_BITS_MASK; + acop.bitasset_opts = bitasset_options(); + acop.bitasset_opts->minimum_feeds = 1; + acop.bitasset_opts->extensions.value.black_swan_response_method = bsrm_value; + acop.bitasset_opts->extensions.value.margin_call_fee_ratio = 11; + + trx.operations.clear(); + trx.operations.push_back( acop ); + processed_transaction ptx = PUSH_TX(db, trx, ~0); + const asset_object& mpa = db.get(ptx.operation_results[0].get()); + asset_id_type mpa_id = mpa.get_id(); + + BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() + == bsrm_type::individual_settlement_to_fund ); + + // add a price feed publisher and publish a feed + update_feed_producers( mpa_id, { feeder_id } ); + + price_feed f; + f.settlement_price = price( asset(100,mpa_id), asset(1) ); + f.core_exchange_rate = price( asset(100,mpa_id), asset(1) ); + f.maintenance_collateral_ratio = 1850; + f.maximum_short_squeeze_ratio = 1250; + + uint16_t feed_icr = 1900; + + publish_feed( mpa_id, feeder_id, f, feed_icr ); + + BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); + + // borrowers borrow some + // undercollateralization price = 100000:2000 * 1250:1000 = 100000:1600 + const call_order_object* call_ptr = borrow( borrower, asset(100000, mpa_id), asset(2000) ); + BOOST_REQUIRE( call_ptr ); + call_order_id_type call_id = call_ptr->get_id(); + + // undercollateralization price = 100000:2100 * 1250:1000 = 100000:1680 + const call_order_object* call2_ptr = borrow( borrower2, asset(100000, mpa_id), asset(2100) ); + BOOST_REQUIRE( call2_ptr ); + call_order_id_type call2_id = call2_ptr->get_id(); + + // undercollateralization price = 100000:2200 * 1250:1000 = 100000:1760 + const call_order_object* call3_ptr = borrow( borrower3, asset(100000, mpa_id), asset(2200) ); + BOOST_REQUIRE( call3_ptr ); + call_order_id_type call3_id = call3_ptr->get_id(); + + // undercollateralization price = 100000:2500 * 1250:1000 = 100000:2000 + const call_order_object* call4_ptr = borrow( borrower4, asset(100000, mpa_id), asset(2500) ); + BOOST_REQUIRE( call4_ptr ); + call_order_id_type call4_id = call4_ptr->get_id(); + + // Transfer funds to sellers + transfer( borrower, seller, asset(100000,mpa_id) ); + transfer( borrower2, seller, asset(100000,mpa_id) ); + transfer( borrower3, seller2, asset(100000,mpa_id) ); + transfer( borrower4, seller2, asset(100000,mpa_id) ); + + BOOST_CHECK_EQUAL( call_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call_id(db).collateral.value, 2000 ); + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 2100 ); + BOOST_CHECK_EQUAL( call3_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call3_id(db).collateral.value, 2200 ); + BOOST_CHECK_EQUAL( call4_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call4_id(db).collateral.value, 2500 ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 200000 ); + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 0 ); + BOOST_CHECK_EQUAL( get_balance( seller2_id, mpa_id ), 200000 ); + BOOST_CHECK_EQUAL( get_balance( seller2_id, asset_id_type() ), 0 ); + + // publish a new feed so that borrower's debt position is undercollateralized + f.settlement_price = price( asset(100000,mpa_id), asset(1650) ); + publish_feed( mpa_id, feeder_id, f, feed_icr ); + // call pays price = 100000:1650 * 1000:1250 = 100000:2062.5 = 48.484848485 + // call match price = 100000:1650 * 1000:1239 = 100000:2048.75 = 48.915303153 + + // check + BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); + + // call: margin call fee deducted = round_down(2000*11/1250) = 17, + // fund receives 2000 - 17 = 1983 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1983 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 100000 ); + + BOOST_CHECK( mpa_id(db).dynamic_data(db).accumulated_collateral_fees == 17 ); + + BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price + == price( asset(100000*1239,mpa_id), asset(1983*1000) ) ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); + // call pays price (MSSP) = 100000:1983 * 1239:1250 = 49.984871407 + // call match price (MCOP) = 100000:1983 = 50.428643469 + + BOOST_CHECK( !db.find( call_id ) ); + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 2100 ); + BOOST_CHECK_EQUAL( call3_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call3_id(db).collateral.value, 2200 ); + BOOST_CHECK_EQUAL( call4_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call4_id(db).collateral.value, 2500 ); + + // borrower5 is unable to borrow if CR <= real ICR + // for median_feed: 1650 * 1.9 = 3135 + // for current_feed: 1983 * 1.9 / 1.239 = 3040.9 + BOOST_CHECK_THROW( borrow( borrower5, asset(100000, mpa_id), asset(3135) ), fc::exception ); + const call_order_object* call5_ptr = borrow( borrower5, asset(100000, mpa_id), asset(3136) ); + BOOST_REQUIRE( call5_ptr ); + call_order_id_type call5_id = call5_ptr->get_id(); + + BOOST_CHECK_EQUAL( call5_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call5_id(db).collateral.value, 3136 ); + + // seller sells some + const limit_order_object* limit_ptr = create_sell_order( seller, asset(80000,mpa_id), asset(100) ); + // the limit order is filled + BOOST_CHECK( !limit_ptr ); + + // call2 is partially filled + // limit order gets round_down(80000*(1983/100000)) = 1586 + // limit order pays round_up(1586*(100000/1983)) = 79980 + // call2 gets 79980 + // call2 pays round_down(79980*(1983/100000)*(1250/1239)) = 1600, margin call fee = 14 + BOOST_CHECK( !db.find( call_id ) ); + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 20020 ); // 100000 - 79980 + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 500 ); // 2100 - 1600 + // 20020 / 500 = 40.04 + BOOST_CHECK_EQUAL( call3_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call3_id(db).collateral.value, 2200 ); + // 100000 / 2200 = 45.454545455 + BOOST_CHECK_EQUAL( call4_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call4_id(db).collateral.value, 2500 ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 120020 ); // 200000 - 79980 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 1586 ); + BOOST_CHECK_EQUAL( get_balance( seller2_id, mpa_id ), 200000 ); + BOOST_CHECK_EQUAL( get_balance( seller2_id, asset_id_type() ), 0 ); + + BOOST_CHECK( mpa_id(db).dynamic_data(db).accumulated_collateral_fees == 31 ); // 17 + 14 + + // seller sells more, this order is below MCOP so will not be matched right now + limit_ptr = create_sell_order( seller, asset(100000,mpa_id), asset(2000) ); + // the limit order is not filled + BOOST_REQUIRE( limit_ptr ); + limit_order_id_type limit_id = limit_ptr->get_id(); + + BOOST_CHECK_EQUAL( limit_ptr->for_sale.value, 100000 ); + + // unable to settle too little amount + BOOST_CHECK_THROW( force_settle( seller2, asset(50,mpa_id) ), fc::exception ); + + // publish a new feed so that current_feed is no longer capped + f.settlement_price = price( asset(100000,mpa_id), asset(1450) ); + publish_feed( mpa_id, feeder_id, f, feed_icr ); + // call pays price (MSSP) = 100000:1450 * 1000:1250 = 10000000:181250 = 55.172413793 + // call match price (MCOP) = 100000:1450 * 1000:1239 = 10000000:179655 = 55.662241518 + + // check + BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); + + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1983 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 100000 ); + + BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); + + const auto& get_amount_to_settle = [&]() { + switch(i) { + case 0: + case 3: + return 90000; + case 1: + case 4: + return 100000; + case 2: + case 5: + default: + return 110000; + } + }; + + // seller2 settles + share_type amount_to_settle = get_amount_to_settle(); + auto result = force_settle( seller2, asset(amount_to_settle, mpa_id) ); + auto op_result = result.get().value; + + auto check_result = [&] + { + force_settlement_id_type settle_id; + if( 0 == i ) + { + BOOST_CHECK( !op_result.new_objects.valid() ); // force settlement order not created + + // receives = round_down(90000 * 1983 / 100000) = 1784 + // pays = round_up(1784 * 100000 / 1983) = 89965 + // settlement fund = 1983 - 1784 = 199 + // settlement debt = 100000 - 89965 = 10035 + BOOST_REQUIRE( op_result.paid.valid() && 1U == op_result.paid->size() ); + BOOST_CHECK( *op_result.paid->begin() == asset( 89965, mpa_id ) ); + BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() ); + BOOST_CHECK( *op_result.received->begin() == asset( 1784 ) ); + + BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 199 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 10035 ); + + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 20020 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 500 ); + // 20020 / 500 = 40.04 + BOOST_CHECK_EQUAL( call3_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call3_id(db).collateral.value, 2200 ); + // 100000 / 2200 = 45.454545455 + + BOOST_REQUIRE( db.find(limit_id) ); + BOOST_CHECK_EQUAL( limit_id(db).for_sale.value, 100000 ); + + BOOST_CHECK( mpa_id(db).dynamic_data(db).accumulated_collateral_fees == 31 ); // 17 + 14 + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 20020 ); // 200000 - 79980 - 100000 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 1586 ); + BOOST_CHECK_EQUAL( get_balance( seller2_id, mpa_id ), 110035 ); // 200000 - 89965 + BOOST_CHECK_EQUAL( get_balance( seller2_id, asset_id_type() ), 1784 ); + } + else if( 1 == i ) + { + BOOST_CHECK( !op_result.new_objects.valid() ); // force settlement order not created + + BOOST_REQUIRE( op_result.paid.valid() && 1U == op_result.paid->size() ); + BOOST_CHECK( *op_result.paid->begin() == asset( 100000, mpa_id ) ); + BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() ); + BOOST_CHECK( *op_result.received->begin() == asset( 1983 ) ); + + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); + + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 20020 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 500 ); + // 20020 / 500 = 40.04 + BOOST_CHECK_EQUAL( call3_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call3_id(db).collateral.value, 2200 ); + // 100000 / 2200 = 45.454545455 + + BOOST_REQUIRE( db.find(limit_id) ); + BOOST_CHECK_EQUAL( limit_id(db).for_sale.value, 100000 ); + + BOOST_CHECK( mpa_id(db).dynamic_data(db).accumulated_collateral_fees == 31 ); // 17 + 14 + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 20020 ); // 200000 - 79980 - 100000 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 1586 ); + BOOST_CHECK_EQUAL( get_balance( seller2_id, mpa_id ), 100000 ); // 200000 - 100000 + BOOST_CHECK_EQUAL( get_balance( seller2_id, asset_id_type() ), 1983 ); + } + else if( 2 == i ) + { + // force settlement order created + BOOST_REQUIRE( op_result.new_objects.valid() && 1U == op_result.new_objects->size() ); + settle_id = *op_result.new_objects->begin(); + + BOOST_REQUIRE( op_result.paid.valid() && 1U == op_result.paid->size() ); + BOOST_CHECK( *op_result.paid->begin() == asset( 100000, mpa_id ) ); + BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() ); + BOOST_CHECK( *op_result.received->begin() == asset( 1983 ) ); + + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); + + // settle order is matched with call3 + // settle order is smaller + BOOST_CHECK( !db.find(settle_id) ); + // settle order gets round_down((110000-100000) * (1450/100000) * (1239/1000)) = 179 + // settle order pays round_up(179 * (100000/1450) * (1000/1239)) = 9964 + // call3 gets 9964 + // call3 pays round_down(9964 * (1450/100000) * (1250/1000)) = 180, margin call fee = 1 + // call3 is now (100000-9964):(2200-180) = 90036:2020 + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 20020 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 500 ); + // 20020 / 500 = 40.04 + BOOST_CHECK_EQUAL( call3_id(db).debt.value, 90036 ); + BOOST_CHECK_EQUAL( call3_id(db).collateral.value, 2020 ); + // 90036 / 2020 = 44.572277228 + + BOOST_REQUIRE( db.find(limit_id) ); + BOOST_CHECK_EQUAL( limit_id(db).for_sale.value, 100000 ); + + BOOST_CHECK( mpa_id(db).dynamic_data(db).accumulated_collateral_fees == 32 ); // 17 + 14 + 1 + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 20020 ); // 200000 - 79980 - 100000 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 1586 ); + BOOST_CHECK_EQUAL( get_balance( seller2_id, mpa_id ), 90036 ); // 200000 - 100000 - 9964 + BOOST_CHECK_EQUAL( get_balance( seller2_id, asset_id_type() ), 2162 ); // 1983 + 179 + + BOOST_CHECK_EQUAL( get_balance( borrower_id, asset_id_type() ), init_amount - 2000 ); + BOOST_CHECK_EQUAL( get_balance( borrower2_id, asset_id_type() ), init_amount - 2100 ); + BOOST_CHECK_EQUAL( get_balance( borrower3_id, asset_id_type() ), init_amount - 2200 ); + BOOST_CHECK_EQUAL( get_balance( borrower4_id, asset_id_type() ), init_amount - 2500 ); + BOOST_CHECK_EQUAL( get_balance( borrower5_id, asset_id_type() ), init_amount - 3136 ); + } + else if( 3 == i ) + { + BOOST_CHECK( !op_result.new_objects.valid() ); // force settlement order not created + + // settlement fund pays = round_down(90000 * 1983 / 100000) = 1784 + // seller2 pays = round_up(1784 * 100000 / 1983) = 89965 + // settlement fund = 1983 - 1784 = 199 + // settlement debt = 100000 - 89965 = 10035 + // seller2 would receive = round_up(89965 * 179655 / 10000000 ) = 1617 (<1784, so ok) + // collateral fee = 1784 - 1617 = 167 + BOOST_REQUIRE( op_result.paid.valid() && 1U == op_result.paid->size() ); + BOOST_CHECK( *op_result.paid->begin() == asset( 89965, mpa_id ) ); + BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() ); + BOOST_CHECK( *op_result.received->begin() == asset( 1617 ) ); + BOOST_REQUIRE( op_result.fees.valid() && 2U == op_result.fees->size() ); + BOOST_CHECK( *op_result.fees->begin() == asset( 167 ) ); + + BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 199 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 10035 ); + + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 20020 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 500 ); + // 20020 / 500 = 40.04 + BOOST_CHECK_EQUAL( call3_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call3_id(db).collateral.value, 2200 ); + // 100000 / 2200 = 45.454545455 + + BOOST_REQUIRE( db.find(limit_id) ); + BOOST_CHECK_EQUAL( limit_id(db).for_sale.value, 100000 ); + + BOOST_CHECK( mpa_id(db).dynamic_data(db).accumulated_collateral_fees == 198 ); // 17 + 14 + 167 + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 20020 ); // 200000 - 79980 - 100000 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 1586 ); + BOOST_CHECK_EQUAL( get_balance( seller2_id, mpa_id ), 110035 ); // 200000 - 89965 + BOOST_CHECK_EQUAL( get_balance( seller2_id, asset_id_type() ), 1617 ); + } + else if( 4 == i ) + { + BOOST_CHECK( !op_result.new_objects.valid() ); // force settlement order not created + + // settlement fund pays = 1983 + // seller2 pays = 100000 + // settlement fund = 0 + // settlement debt = 0 + // seller2 would receive = round_up(100000 * 179655 / 10000000 ) = 1797 (<1983, so ok) + // collateral fee = 1983 - 1797 = 186 + BOOST_REQUIRE( op_result.paid.valid() && 1U == op_result.paid->size() ); + BOOST_CHECK( *op_result.paid->begin() == asset( 100000, mpa_id ) ); + BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() ); + BOOST_CHECK( *op_result.received->begin() == asset( 1797 ) ); + BOOST_REQUIRE( op_result.fees.valid() && 2U == op_result.fees->size() ); + BOOST_CHECK( *op_result.fees->begin() == asset( 186 ) ); + + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); + + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 20020 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 500 ); + // 20020 / 500 = 40.04 + BOOST_CHECK_EQUAL( call3_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call3_id(db).collateral.value, 2200 ); + // 100000 / 2200 = 45.454545455 + + BOOST_REQUIRE( db.find(limit_id) ); + BOOST_CHECK_EQUAL( limit_id(db).for_sale.value, 100000 ); + + BOOST_CHECK( mpa_id(db).dynamic_data(db).accumulated_collateral_fees == 217 ); // 17 + 14 + 186 + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 20020 ); // 200000 - 79980 - 100000 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 1586 ); + BOOST_CHECK_EQUAL( get_balance( seller2_id, mpa_id ), 100000 ); // 200000 - 100000 + BOOST_CHECK_EQUAL( get_balance( seller2_id, asset_id_type() ), 1797 ); + } + else if( 5 == i ) + { + // force settlement order created + BOOST_REQUIRE( op_result.new_objects.valid() && 1U == op_result.new_objects->size() ); + settle_id = *op_result.new_objects->begin(); + + // settlement fund pays = 1983 + // seller2 pays = 100000 + // settlement fund = 0 + // settlement debt = 0 + // seller2 would receive = round_up(100000 * 179655 / 10000000 ) = 1797 (<1983, so ok) + // collateral fee = 1983 - 1797 = 186 + BOOST_REQUIRE( op_result.paid.valid() && 1U == op_result.paid->size() ); + BOOST_CHECK( *op_result.paid->begin() == asset( 100000, mpa_id ) ); + BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() ); + BOOST_CHECK( *op_result.received->begin() == asset( 1797 ) ); + BOOST_REQUIRE( op_result.fees.valid() && 2U == op_result.fees->size() ); + BOOST_CHECK( *op_result.fees->begin() == asset( 186 ) ); + + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); + + // settle order is matched with call3 + // settle order is smaller + BOOST_CHECK( !db.find(settle_id) ); + // settle order gets round_down((110000-100000) * (1450/100000) * (1239/1000)) = 179 + // settle order pays round_up(179 * (100000/1450) * (1000/1239)) = 9964 + // call3 gets 9964 + // call3 pays round_down(9964 * (1450/100000) * (1250/1000)) = 180, margin call fee = 1 + // call3 is now (100000-9964):(2200-180) = 90036:2020 + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 20020 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 500 ); + // 20020 / 500 = 40.04 + BOOST_CHECK_EQUAL( call3_id(db).debt.value, 90036 ); + BOOST_CHECK_EQUAL( call3_id(db).collateral.value, 2020 ); + // 90036 / 2020 = 44.572277228 + + BOOST_REQUIRE( db.find(limit_id) ); + BOOST_CHECK_EQUAL( limit_id(db).for_sale.value, 100000 ); + + BOOST_CHECK( mpa_id(db).dynamic_data(db).accumulated_collateral_fees == 218 ); // 17 + 14 + 186 + 1 + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 20020 ); // 200000 - 79980 - 100000 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 1586 ); + BOOST_CHECK_EQUAL( get_balance( seller2_id, mpa_id ), 90036 ); // 200000 - 100000 - 9964 + BOOST_CHECK_EQUAL( get_balance( seller2_id, asset_id_type() ), 1976 ); // 1797 + 179 + + BOOST_CHECK_EQUAL( get_balance( borrower_id, asset_id_type() ), init_amount - 2000 ); + BOOST_CHECK_EQUAL( get_balance( borrower2_id, asset_id_type() ), init_amount - 2100 ); + BOOST_CHECK_EQUAL( get_balance( borrower3_id, asset_id_type() ), init_amount - 2200 ); + BOOST_CHECK_EQUAL( get_balance( borrower4_id, asset_id_type() ), init_amount - 2500 ); + BOOST_CHECK_EQUAL( get_balance( borrower5_id, asset_id_type() ), init_amount - 3136 ); + } + + }; + + check_result(); + + BOOST_TEST_MESSAGE( "Generate a block" ); + generate_block(); + + check_result(); + + // reset + db.pop_block(); + + } // for i + +} FC_LOG_AND_RETHROW() } /// Tests individual settlement to order : settles when price drops, and how orders are being matched after settled BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_taking_test ) From 822adcd1763d9d8fbe8672b6874bbf4ec6209ff5 Mon Sep 17 00:00:00 2001 From: Abit Date: Tue, 31 Jan 2023 23:29:54 +0100 Subject: [PATCH 034/127] Bump docker/build-push-action from 3 to 4 --- .github/workflows/build-docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index a1a5d134ef..7c54f7c195 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -46,14 +46,14 @@ jobs: password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Push to DockerHub (for branches) if: env.DOCKER_PUSH_TAG != '' && env.DOCKER_PUSH_TAG_SHORT == '' - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: context: . push: true tags: ${{ secrets.DOCKERHUB_REPO_PATH }}:${{ env.DOCKER_PUSH_TAG }} - name: Push to DockerHub (for tags) if: env.DOCKER_PUSH_TAG != '' && env.DOCKER_PUSH_TAG_SHORT != '' - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: context: . push: true From 7b928911f32eaf436644f151c4d8d9b5e76cdb2a Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 3 Feb 2023 20:02:04 +0000 Subject: [PATCH 035/127] Use ES version 8.6.1 and 7.17.9 in Github Actions --- .github/workflows/build-and-test.ubuntu-debug.yml | 4 ++-- .github/workflows/build-and-test.ubuntu-release.yml | 4 ++-- .github/workflows/sonar-scan.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-and-test.ubuntu-debug.yml b/.github/workflows/build-and-test.ubuntu-debug.yml index b361866f8c..8946b3e036 100644 --- a/.github/workflows/build-and-test.ubuntu-debug.yml +++ b/.github/workflows/build-and-test.ubuntu-debug.yml @@ -12,7 +12,7 @@ jobs: runs-on: ${{ matrix.os }} services: elasticsearch8: - image: elastic/elasticsearch:8.5.3 + image: elastic/elasticsearch:8.6.1 options: >- --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node @@ -22,7 +22,7 @@ jobs: --env cluster.routing.allocation.disk.threshold_enabled=false --publish 9200:9200 elasticsearch7: - image: elastic/elasticsearch:7.17.8 + image: elastic/elasticsearch:7.17.9 options: >- --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node diff --git a/.github/workflows/build-and-test.ubuntu-release.yml b/.github/workflows/build-and-test.ubuntu-release.yml index 1976ce317c..c149e28901 100644 --- a/.github/workflows/build-and-test.ubuntu-release.yml +++ b/.github/workflows/build-and-test.ubuntu-release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ${{ matrix.os }} services: elasticsearch8: - image: elastic/elasticsearch:8.5.3 + image: elastic/elasticsearch:8.6.1 options: >- --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node @@ -22,7 +22,7 @@ jobs: --env cluster.routing.allocation.disk.threshold_enabled=false --publish 9200:9200 elasticsearch7: - image: elastic/elasticsearch:7.17.8 + image: elastic/elasticsearch:7.17.9 options: >- --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index 0118fef10d..c83b9857a4 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -12,7 +12,7 @@ jobs: runs-on: ${{ matrix.os }} services: elasticsearch8: - image: elastic/elasticsearch:8.5.3 + image: elastic/elasticsearch:8.6.1 options: >- --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node From 1ea6578c09d94d6f2d4cbfda92189bc6064852b1 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 3 Feb 2023 22:11:01 +0000 Subject: [PATCH 036/127] Add tests for price paid by global settlement fund --- tests/tests/settle_tests.cpp | 200 +++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) diff --git a/tests/tests/settle_tests.cpp b/tests/tests/settle_tests.cpp index 5fef6aeede..397092fcbe 100644 --- a/tests/tests/settle_tests.cpp +++ b/tests/tests/settle_tests.cpp @@ -1888,6 +1888,206 @@ BOOST_AUTO_TEST_CASE( market_fee_of_instant_settle_order_after_hardfork_1780 ) } FC_LOG_AND_RETHROW() } +/// Tests instant settlement: +/// * After hf core-2591, forced-settlements are filled at margin call order price (MCOP) when applicable +BOOST_AUTO_TEST_CASE( collateral_fee_of_instant_settlement_test ) +{ try { + + // Advance to a recent hard fork + generate_blocks(HARDFORK_CORE_2582_TIME); + generate_block(); + + // multiple passes, + // i == 0 : before hf core-2591, extreme feed price + // i == 1 : before hf core-2591, normal feed price + // i == 2 : before hf core-2591, normal feed price, and price recovers after GS + // i == 3 : after hf core-2591, extreme feed price + // i == 4 : after hf core-2591, normal feed price + // i == 5 : after hf core-2591, normal feed price, and price recovers after GS + for( int i = 0; i < 6; ++ i ) + { + idump( (i) ); + + if( 3 == i ) + { + // Advance to core-2591 hard fork + generate_blocks(HARDFORK_CORE_2591_TIME); + generate_block(); + } + + set_expiration( db, trx ); + + ACTORS((sam)(feeder)(borrower)(seller)); + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( sam, asset(init_amount) ); + fund( feeder, asset(init_amount) ); + fund( borrower, asset(init_amount) ); + + using bsrm_type = bitasset_options::black_swan_response_type; + + // Create asset + asset_create_operation acop; + acop.issuer = sam_id; + acop.symbol = "SAMMPA"; + acop.precision = 2; + acop.common_options.core_exchange_rate = price(asset(1,asset_id_type(1)),asset(1)); + acop.common_options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; + acop.common_options.market_fee_percent = 100; // 1% + acop.common_options.flags = charge_market_fee; + acop.common_options.issuer_permissions = ASSET_ISSUER_PERMISSION_ENABLE_BITS_MASK; + acop.bitasset_opts = bitasset_options(); + acop.bitasset_opts->minimum_feeds = 1; + acop.bitasset_opts->extensions.value.margin_call_fee_ratio = 11; + + trx.operations.clear(); + trx.operations.push_back( acop ); + processed_transaction ptx = PUSH_TX(db, trx, ~0); + const asset_object& mpa = db.get(ptx.operation_results[0].get()); + asset_id_type mpa_id = mpa.get_id(); + + BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() + == bsrm_type::global_settlement ); + + // add a price feed publisher and publish a feed + update_feed_producers( mpa_id, { feeder_id } ); + + price_feed f; + f.settlement_price = price( asset(100,mpa_id), asset(1) ); + f.core_exchange_rate = price( asset(100,mpa_id), asset(1) ); + f.maintenance_collateral_ratio = 1850; + f.maximum_short_squeeze_ratio = 1250; + + uint16_t feed_icr = 1900; + + publish_feed( mpa_id, feeder_id, f, feed_icr ); + + BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); + + // borrowers borrow some + // undercollateralization price = 100000:2000 * 1250:1000 = 100000:1600 + const call_order_object* call_ptr = borrow( borrower, asset(100000, mpa_id), asset(2000) ); + BOOST_REQUIRE( call_ptr ); + call_order_id_type call_id = call_ptr->get_id(); + + // Transfer funds to sellers + transfer( borrower, seller, asset(100000,mpa_id) ); + + BOOST_CHECK_EQUAL( call_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call_id(db).collateral.value, 2000 ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 100000 ); + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 0 ); + + // publish a new feed so that borrower's debt position is undercollateralized + if( 0 == i || 3 == i ) + f.settlement_price = price( asset(1,mpa_id), asset(GRAPHENE_MAX_SHARE_SUPPLY) ); + else + f.settlement_price = price( asset(100,mpa_id), asset(2) ); + publish_feed( mpa_id, feeder_id, f, feed_icr ); + + // check + BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); + + // fund receives 1600 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).settlement_fund.value, 1600 ); + + BOOST_CHECK( mpa_id(db).dynamic_data(db).accumulated_collateral_fees == 400 ); + + BOOST_CHECK( mpa_id(db).bitasset_data(db).settlement_price + == price( asset(100000,mpa_id), asset(1600) ) ); + + BOOST_CHECK( !db.find( call_id ) ); + + if( 2 == i || 5 == i ) + { + // price recovers + f.settlement_price = price( asset(100,mpa_id), asset(1) ); + // call pays price (MSSP) = 100:1 * 1000:1250 = 100000:1250 = 80 + // call match price (MCOP) = 100:1 * 1000:1239 = 100000:1239 = 80.710250202 + publish_feed( mpa_id, feeder_id, f, feed_icr ); + } + + // seller settles + share_type amount_to_settle = 56789; + auto result = force_settle( seller, asset(amount_to_settle, mpa_id) ); + auto op_result = result.get().value; + + auto check_result = [&] + { + BOOST_CHECK( !op_result.new_objects.valid() ); // force settlement order not created + + if( 5 == i ) + { + // settlement fund pays = round_down(56789 * 1600 / 100000) = 908 + // seller pays = round_up(908 * 100000 / 1600) = 56750 + // settlement fund = 1600 - 908 = 692 + // settlement debt = 100000 - 56750 = 43250 + // seller would receive = round_up(56750 * 1239 / 10000 ) = 704 (<908, so ok) + // collateral fee = 908 - 704 = 204 + BOOST_REQUIRE( op_result.paid.valid() && 1U == op_result.paid->size() ); + BOOST_CHECK( *op_result.paid->begin() == asset( 56750, mpa_id ) ); + BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() ); + BOOST_CHECK( *op_result.received->begin() == asset( 704 ) ); + BOOST_REQUIRE( op_result.fees.valid() && 2U == op_result.fees->size() ); + BOOST_CHECK( *op_result.fees->begin() == asset( 204 ) ); + + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).settlement_fund.value, 692 ); + + BOOST_CHECK( mpa_id(db).dynamic_data(db).accumulated_collateral_fees == 604 ); // 400 + 204 + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 43250 ); + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 704 ); + } + else + { + // receives = round_down(56789 * 1600 / 100000) = 908 + // pays = round_up(908 * 100000 / 1600) = 56750 + // settlement fund = 1600 - 908 = 692 + // settlement debt = 100000 - 56750 = 43250 + BOOST_REQUIRE( op_result.paid.valid() && 1U == op_result.paid->size() ); + BOOST_CHECK( *op_result.paid->begin() == asset( 56750, mpa_id ) ); + BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() ); + BOOST_CHECK( *op_result.received->begin() == asset( 908 ) ); + BOOST_REQUIRE( op_result.fees.valid() && 1U == op_result.fees->size() ); + BOOST_CHECK( *op_result.fees->begin() == asset( 0 ) ); + + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).settlement_fund.value, 692 ); + + BOOST_CHECK( mpa_id(db).dynamic_data(db).accumulated_collateral_fees == 400 ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 43250 ); + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 908 ); + } + + }; + + check_result(); + + BOOST_TEST_MESSAGE( "Generate a block" ); + generate_block(); + + check_result(); + + // reset + db.pop_block(); + + } // for i + +} 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. From 2f1e5074ce8f3ff85ce2fe8e427e19f6c25f8418 Mon Sep 17 00:00:00 2001 From: Abit Date: Sat, 4 Feb 2023 17:08:30 +0100 Subject: [PATCH 037/127] Bump another docker/build-push-action from 3 to 4 --- .github/workflows/build-docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index 7c54f7c195..ef9d249e4a 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -34,7 +34,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Build only - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: context: . load: true From 247bb8f15199ff606a3c7ca2c8e5c9944ab19707 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 22 Feb 2023 17:50:01 +0000 Subject: [PATCH 038/127] Refactor limit_order_obj for indvd_settle_to_order --- libraries/chain/db_market.cpp | 18 ++++++++++++------ .../chain/include/graphene/chain/config.hpp | 2 +- .../include/graphene/chain/market_object.hpp | 2 ++ libraries/chain/market_object.cpp | 2 +- tests/common/database_fixture.cpp | 2 ++ 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index 05c78c0b54..74073caeca 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -368,9 +368,11 @@ void database::individually_settle( const asset_bitasset_data_object& bitasset, if( limit_ptr ) { modify( *limit_ptr, [&order,&fund_receives]( limit_order_object& obj ) { - obj.for_sale += fund_receives.amount; - obj.sell_price.base.amount = obj.for_sale; - obj.sell_price.quote.amount += order.debt; + obj.settled_debt_amount += order.debt; + obj.settled_collateral_amount += fund_receives.amount; + obj.for_sale = obj.settled_collateral_amount; + obj.sell_price.base.amount = obj.settled_collateral_amount; + obj.sell_price.quote.amount = obj.settled_debt_amount; } ); } else @@ -381,6 +383,8 @@ void database::individually_settle( const asset_bitasset_data_object& bitasset, obj.for_sale = fund_receives.amount; obj.sell_price = fund_receives / order_debt; obj.is_settled_debt = true; + obj.settled_debt_amount = order_debt.amount; + obj.settled_collateral_amount = fund_receives.amount; } ); } // Note: CORE asset in settled debt is not counted in account_stats.total_core_in_orders @@ -1135,9 +1139,11 @@ database::match_result_type database::match_limit_settled_debt( const limit_orde else { modify( maker, [&order_receives,&call_receives]( limit_order_object& obj ) { - obj.for_sale -= order_receives.amount; - obj.sell_price.base.amount = obj.for_sale; - obj.sell_price.quote.amount -= call_receives.amount; + obj.settled_debt_amount -= call_receives.amount; + obj.settled_collateral_amount -= order_receives.amount; + obj.for_sale = obj.settled_collateral_amount; + obj.sell_price.base.amount = obj.settled_collateral_amount; + obj.sell_price.quote.amount = obj.settled_debt_amount; }); } diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 5390eb2270..99ff16488f 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -32,7 +32,7 @@ #define GRAPHENE_MAX_NESTED_OBJECTS (200) -const std::string GRAPHENE_CURRENT_DB_VERSION = "20220930"; +const std::string GRAPHENE_CURRENT_DB_VERSION = "20230222"; #define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4 #define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3 diff --git a/libraries/chain/include/graphene/chain/market_object.hpp b/libraries/chain/include/graphene/chain/market_object.hpp index 724be9c25b..81366299b8 100644 --- a/libraries/chain/include/graphene/chain/market_object.hpp +++ b/libraries/chain/include/graphene/chain/market_object.hpp @@ -51,6 +51,8 @@ class limit_order_object : public abstract_object get_market()const { diff --git a/libraries/chain/market_object.cpp b/libraries/chain/market_object.cpp index 42ec31d5d0..39db71cb3c 100644 --- a/libraries/chain/market_object.cpp +++ b/libraries/chain/market_object.cpp @@ -309,7 +309,7 @@ share_type call_order_object::get_max_debt_to_cover( price match_price, FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::limit_order_object, (graphene::db::object), (expiration)(seller)(for_sale)(sell_price)(deferred_fee)(deferred_paid_fee) - (is_settled_debt) + (is_settled_debt)(settled_debt_amount)(settled_collateral_amount) ) FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::call_order_object, (graphene::db::object), diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 714e4ededb..0489577c0f 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -582,6 +582,8 @@ void database_fixture_base::verify_asset_supplies( const database& db ) { total_debts[o.receive_asset_id()] += o.sell_price.quote.amount; BOOST_CHECK_EQUAL( o.sell_price.base.amount.value, for_sale.amount.value ); + BOOST_CHECK_EQUAL( o.settled_collateral_amount.value, for_sale.amount.value ); + BOOST_CHECK_EQUAL( o.sell_price.quote.amount.value, o.settled_debt_amount.value ); } } for( const call_order_object& o : db.get_index_type().indices() ) From dd7bbe332ca3f52b242170de8d2de6aca8226393 Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 23 Feb 2023 19:47:46 +0000 Subject: [PATCH 039/127] Update settled-debt order when median feed updated --- libraries/chain/db_update.cpp | 59 +++++++++++++++++++++++++++++-- tests/common/database_fixture.cpp | 12 ++++--- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index e13b51a9dc..67122ac917 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -222,6 +222,52 @@ static optional get_derived_current_feed_price( const database& db, return result; } +// Helper function to update the limit order which is the individual settlement fund of the specified asset +static void update_settled_debt_order( database& db, const asset_bitasset_data_object& bitasset ) +{ + // To avoid unexpected price fluctuations, do not update the order if no sufficient price feeds + if( bitasset.current_feed.settlement_price.is_null() ) + return; + + const limit_order_object* limit_ptr = db.find_settled_debt_order( bitasset.asset_id ); + if( !limit_ptr ) + return; + + bool sell_all = true; + share_type for_sale; + + // Note: bitasset.get_margin_call_order_price() is in debt/collateral + price sell_price = ~bitasset.get_margin_call_order_price(); + asset settled_debt( limit_ptr->settled_debt_amount, limit_ptr->receive_asset_id() ); + try + { + for_sale = settled_debt.multiply_and_round_up( sell_price ).amount; // may overflow + if( for_sale <= limit_ptr->settled_collateral_amount ) // "=" is for the consistency of order matching logic + sell_all = false; + } + catch( const fc::exception& e ) // catch the overflow + { + // do nothing + dlog( e.to_detail_string() ); + } + + // TODO Potential optimization: to avoid unnecessary database update, check before update + db.modify( *limit_ptr, [sell_all, &sell_price, &for_sale]( limit_order_object& obj ) + { + if( sell_all ) + { + obj.for_sale = obj.settled_collateral_amount; + obj.sell_price.base.amount = obj.settled_collateral_amount; + obj.sell_price.quote.amount = obj.settled_debt_amount; + } + else + { + obj.for_sale = for_sale; + obj.sell_price = sell_price; + } + } ); +} + void database::update_bitasset_current_feed( const asset_bitasset_data_object& bitasset, bool skip_median_update ) { // For better performance, if nothing to update, we return @@ -245,13 +291,14 @@ void database::update_bitasset_current_feed( const asset_bitasset_data_object& b } } + const auto& head_time = head_block_time(); + // We need to update the database - modify( bitasset, [this, skip_median_update, &new_current_feed_price, &bsrm] + modify( bitasset, [this, skip_median_update, &head_time, &new_current_feed_price, &bsrm] ( asset_bitasset_data_object& abdo ) { if( !skip_median_update ) { - const auto& head_time = head_block_time(); const auto& maint_time = get_dynamic_global_properties().next_maintenance_time; abdo.update_median_feeds( head_time, maint_time ); abdo.current_feed = abdo.median_feed; @@ -261,6 +308,14 @@ void database::update_bitasset_current_feed( const asset_bitasset_data_object& b if( new_current_feed_price.valid() ) abdo.current_feed.settlement_price = *new_current_feed_price; } ); + + // Update individual settlement order price + if( !skip_median_update + && bsrm_type::individual_settlement_to_order == bsrm + && HARDFORK_CORE_2591_PASSED( head_time ) ) // Tighter peg (fill individual settlement order at MCOP) + { + update_settled_debt_order( *this, bitasset ); + } } void database::clear_expired_orders() diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 0489577c0f..bbeb62832a 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -575,16 +575,18 @@ void database_fixture_base::verify_asset_supplies( const database& db ) if( for_sale.asset_id == asset_id_type() && !o.is_settled_debt ) // Note: CORE asset in settled debt is not counted in account_stats.total_core_in_orders core_in_orders += for_sale.amount; - total_balances[for_sale.asset_id] += for_sale.amount; total_balances[asset_id_type()] += o.deferred_fee; total_balances[o.deferred_paid_fee.asset_id] += o.deferred_paid_fee.amount; if( o.is_settled_debt ) { - total_debts[o.receive_asset_id()] += o.sell_price.quote.amount; - BOOST_CHECK_EQUAL( o.sell_price.base.amount.value, for_sale.amount.value ); - BOOST_CHECK_EQUAL( o.settled_collateral_amount.value, for_sale.amount.value ); - BOOST_CHECK_EQUAL( o.sell_price.quote.amount.value, o.settled_debt_amount.value ); + total_balances[for_sale.asset_id] += o.settled_collateral_amount; + total_debts[o.receive_asset_id()] += o.settled_debt_amount; + BOOST_CHECK_LE( o.for_sale.value, o.settled_collateral_amount.value ); + auto settled_debt = asset( o.settled_debt_amount.value, o.receive_asset_id() ); + BOOST_CHECK_EQUAL( settled_debt.multiply_and_round_up( o.sell_price ).amount.value, o.for_sale.value ); } + else + total_balances[for_sale.asset_id] += for_sale.amount; } for( const call_order_object& o : db.get_index_type().indices() ) { From b1b716719acbe7d6545578bb6e2a32a480f4d634 Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 23 Feb 2023 22:12:44 +0000 Subject: [PATCH 040/127] Pay fee when settled-debt order is filled as maker --- libraries/chain/db_market.cpp | 59 +++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index 74073caeca..4a4330210b 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -1091,7 +1091,7 @@ database::match_result_type database::match_limit_settled_debt( const limit_orde bool maker_filled = false; auto usd_for_sale = taker.amount_for_sale(); - auto usd_to_buy = maker.sell_price.quote; + auto usd_to_buy = asset( maker.settled_debt_amount, maker.receive_asset_id() ); asset call_receives; asset order_receives; @@ -1121,16 +1121,36 @@ database::match_result_type database::match_limit_settled_debt( const limit_orde // seller, pays, receives, ... bool taker_filled = fill_limit_order( taker, call_receives, order_receives, cull_taker, match_price, false ); - // Reduce current supply + const auto& head_time = head_block_time(); + bool after_core_hardfork_2591 = HARDFORK_CORE_2591_PASSED( head_time ); // Tighter peg (fill debt order at MCOP) + + asset call_pays = order_receives; + if( maker_filled ) // Regardless of hf core-2591 + call_pays.amount = maker.settled_collateral_amount; + else if( maker.for_sale != maker.settled_collateral_amount ) // implies hf core-2591 + { + price settle_price = asset( maker.settled_collateral_amount, maker.sell_asset_id() ) + / asset( maker.settled_debt_amount, maker.receive_asset_id() ); + call_pays = call_receives * settle_price; // round down here, in favor of call order + } + if( call_pays < order_receives ) // be defensive, maybe unnecessary + { + wlog( "Unexpected scene: call_pays < order_receives" ); + call_pays = order_receives; + } + asset collateral_fee = call_pays - order_receives; + + // Reduce current supply, and accumulate collateral fees const asset_dynamic_data_object& mia_ddo = call_receives.asset_id(*this).dynamic_asset_data_id(*this); - modify( mia_ddo, [&call_receives]( asset_dynamic_data_object& ao ){ + modify( mia_ddo, [&call_receives,&collateral_fee]( asset_dynamic_data_object& ao ){ ao.current_supply -= call_receives.amount; + ao.accumulated_collateral_fees += collateral_fee.amount; }); // Push fill_order vitual operation // id, seller, pays, receives, ... - push_applied_operation( fill_order_operation( maker.id, maker.seller, order_receives, call_receives, - asset(0, call_receives.asset_id), match_price, true ) ); + push_applied_operation( fill_order_operation( maker.id, maker.seller, call_pays, call_receives, + collateral_fee, match_price, true ) ); // Update the maker order // Note: CORE asset in settled debt is not counted in account_stats.total_core_in_orders @@ -1138,13 +1158,32 @@ database::match_result_type database::match_limit_settled_debt( const limit_orde remove( maker ); else { - modify( maker, [&order_receives,&call_receives]( limit_order_object& obj ) { + modify( maker, [after_core_hardfork_2591,&call_pays,&call_receives]( limit_order_object& obj ) { obj.settled_debt_amount -= call_receives.amount; - obj.settled_collateral_amount -= order_receives.amount; - obj.for_sale = obj.settled_collateral_amount; - obj.sell_price.base.amount = obj.settled_collateral_amount; - obj.sell_price.quote.amount = obj.settled_debt_amount; + obj.settled_collateral_amount -= call_pays.amount; + if( after_core_hardfork_2591 ) + { + // Note: for simplicity, only update price when necessary + asset settled_debt( obj.settled_debt_amount, obj.receive_asset_id() ); + obj.for_sale = settled_debt.multiply_and_round_up( obj.sell_price ).amount; + if( obj.for_sale > obj.settled_collateral_amount ) // be defensive, maybe unnecessary + { + wlog( "Unexpected scene: obj.for_sale > obj.settled_collateral_amount" ); + obj.for_sale = obj.settled_collateral_amount; + obj.sell_price.base.amount = obj.settled_collateral_amount; + obj.sell_price.quote.amount = obj.settled_debt_amount; + } + } + else + { + obj.for_sale = obj.settled_collateral_amount; + obj.sell_price.base.amount = obj.settled_collateral_amount; + obj.sell_price.quote.amount = obj.settled_debt_amount; + } }); + // Note: + // After the price is updated, it is possible that the order can be matched with another order on the order + // book, which may then be matched with more other orders. For simplicity, we don't do more matching here. } match_result_type result = get_match_result( taker_filled, maker_filled ); From 51837737203834f979facfb305e9e0f20d1d79ab Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 23 Feb 2023 23:07:33 +0000 Subject: [PATCH 041/127] Check price when individually settling to order --- libraries/chain/db_market.cpp | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index 4a4330210b..572f09537a 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -364,15 +364,39 @@ void database::individually_settle( const asset_bitasset_data_object& bitasset, } else // settle to order { + const auto& head_time = head_block_time(); + bool after_core_hardfork_2591 = HARDFORK_CORE_2591_PASSED( head_time ); // Tighter peg (fill debt order at MCOP) + const limit_order_object* limit_ptr = find_settled_debt_order( bitasset.asset_id ); if( limit_ptr ) { - modify( *limit_ptr, [&order,&fund_receives]( limit_order_object& obj ) { + modify( *limit_ptr, [&order,&fund_receives,after_core_hardfork_2591,&bitasset]( limit_order_object& obj ) { obj.settled_debt_amount += order.debt; obj.settled_collateral_amount += fund_receives.amount; - obj.for_sale = obj.settled_collateral_amount; - obj.sell_price.base.amount = obj.settled_collateral_amount; - obj.sell_price.quote.amount = obj.settled_debt_amount; + // TODO fix duplicate code + bool sell_all = true; + if( after_core_hardfork_2591 ) + { + obj.sell_price = ~bitasset.get_margin_call_order_price(); + asset settled_debt( obj.settled_debt_amount, obj.receive_asset_id() ); + try + { + obj.for_sale = settled_debt.multiply_and_round_up( obj.sell_price ).amount; // may overflow + if( obj.for_sale <= obj.settled_collateral_amount ) // "=" for consistency of order matching logic + sell_all = false; + } + catch( fc::exception& e ) // catch the overflow + { + // do nothing + dlog( e.to_detail_string() ); + } + } + if( sell_all ) + { + obj.for_sale = obj.settled_collateral_amount; + obj.sell_price.base.amount = obj.settled_collateral_amount; + obj.sell_price.quote.amount = obj.settled_debt_amount; + } } ); } else From bd1b2fa2ae282b0674df72d9a5920c2ff29c4687 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 24 Feb 2023 19:24:56 +0000 Subject: [PATCH 042/127] Process settled-debt order in check_call_orders() --- libraries/chain/db_market.cpp | 153 +++++++++++++++++- .../chain/include/graphene/chain/database.hpp | 12 ++ 2 files changed, 157 insertions(+), 8 deletions(-) diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index 572f09537a..f0fbdf8d04 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -1014,12 +1014,7 @@ static database::match_result_type get_match_result( bool taker_filled, bool mak /** * Matches the two orders, the first parameter is taker, the second is maker. * - * @return a bit field indicating which orders were filled (and thus removed) - * - * 0 - no orders were matched - * 1 - taker was filled - * 2 - maker was filled - * 3 - both were filled + * @return which orders were filled (and thus removed) */ database::match_result_type database::match( const limit_order_object& taker, const limit_order_object& maker, const price& match_price ) @@ -1032,10 +1027,12 @@ database::match_result_type database::match( const limit_order_object& taker, co : match_limit_normal_limit( taker, maker, match_price ); } +/// Match a normal limit order with another normal limit order database::match_result_type database::match_limit_normal_limit( const limit_order_object& taker, const limit_order_object& maker, const price& match_price ) { FC_ASSERT( !maker.is_settled_debt, "Internal error: maker is settled debt" ); + FC_ASSERT( !taker.is_settled_debt, "Internal error: taker is settled debt" ); auto taker_for_sale = taker.amount_for_sale(); auto maker_for_sale = maker.amount_for_sale(); @@ -1105,11 +1102,12 @@ database::match_result_type database::match_limit_normal_limit( const limit_orde return result; } -// When matching a limit order against settled debt, the maker actually behaviors like a call order +/// When matching a limit order against settled debt, the maker actually behaviors like a call order database::match_result_type database::match_limit_settled_debt( const limit_order_object& taker, const limit_order_object& maker, const price& match_price ) { FC_ASSERT( maker.is_settled_debt, "Internal error: maker is not settled debt" ); + FC_ASSERT( !taker.is_settled_debt, "Internal error: taker is settled debt" ); bool cull_taker = false; bool maker_filled = false; @@ -1214,6 +1212,95 @@ database::match_result_type database::match_limit_settled_debt( const limit_orde return result; } +/// When matching a settled debt order against a limit order, the taker actually behaviors like a call order +// TODO fix duplicate code +database::match_result_type database::match_settled_debt_limit( const limit_order_object& taker, + const limit_order_object& maker, const price& match_price ) +{ + FC_ASSERT( !maker.is_settled_debt, "Internal error: maker is settled debt" ); + FC_ASSERT( taker.is_settled_debt, "Internal error: taker is not settled debt" ); + + bool taker_filled = false; + + auto usd_for_sale = maker.amount_for_sale(); + auto usd_to_buy = asset( taker.settled_debt_amount, taker.receive_asset_id() ); + + asset call_receives; + asset order_receives; + if( usd_to_buy > usd_for_sale ) + { // fill maker limit order + order_receives = usd_for_sale * match_price; // round down here, in favor of call order + + // Be here, the limit order won't be paying something for nothing, since if it would, it would have + // been cancelled elsewhere already (a maker limit order won't be paying something for nothing). + + call_receives = order_receives.multiply_and_round_up( match_price ); + } + else + { // fill taker "call order" + call_receives = usd_to_buy; + order_receives = call_receives.multiply_and_round_up( match_price ); // round up here, in favor of limit order + taker_filled = true; + } + + asset call_pays = order_receives; + if( taker_filled ) + call_pays.amount = taker.settled_collateral_amount; + else if( taker.for_sale != taker.settled_collateral_amount ) + { + price settle_price = asset( taker.settled_collateral_amount, taker.sell_asset_id() ) + / asset( taker.settled_debt_amount, taker.receive_asset_id() ); + call_pays = call_receives * settle_price; // round down here, in favor of call order + } + if( call_pays < order_receives ) // be defensive, maybe unnecessary + { + wlog( "Unexpected scene: call_pays < order_receives" ); + call_pays = order_receives; + } + asset collateral_fee = call_pays - order_receives; + + // Reduce current supply, and accumulate collateral fees + const asset_dynamic_data_object& mia_ddo = call_receives.asset_id(*this).dynamic_asset_data_id(*this); + modify( mia_ddo, [&call_receives,&collateral_fee]( asset_dynamic_data_object& ao ){ + ao.current_supply -= call_receives.amount; + ao.accumulated_collateral_fees += collateral_fee.amount; + }); + + // Push fill_order vitual operation + // id, seller, pays, receives, ... + push_applied_operation( fill_order_operation( taker.id, taker.seller, call_pays, call_receives, + collateral_fee, match_price, false ) ); + + // Update the taker order + // Note: CORE asset in settled debt is not counted in account_stats.total_core_in_orders + if( taker_filled ) + remove( taker ); + else + { + modify( taker, [&call_pays,&call_receives]( limit_order_object& obj ) { + obj.settled_debt_amount -= call_receives.amount; + obj.settled_collateral_amount -= call_pays.amount; + // Note: for simplicity, only update price when necessary + asset settled_debt( obj.settled_debt_amount, obj.receive_asset_id() ); + obj.for_sale = settled_debt.multiply_and_round_up( obj.sell_price ).amount; + if( obj.for_sale > obj.settled_collateral_amount ) // be defensive, maybe unnecessary + { + wlog( "Unexpected scene: obj.for_sale > obj.settled_collateral_amount" ); + obj.for_sale = obj.settled_collateral_amount; + obj.sell_price.base.amount = obj.settled_collateral_amount; + obj.sell_price.quote.amount = obj.settled_debt_amount; + } + }); + } + + // seller, pays, receives, ... + bool maker_filled = fill_limit_order( maker, call_receives, order_receives, true, match_price, true ); + + match_result_type result = get_match_result( taker_filled, maker_filled ); + return result; +} + + database::match_result_type database::match( const limit_order_object& bid, const call_order_object& ask, const price& match_price, const asset_bitasset_data_object& bitasset, @@ -1930,8 +2017,11 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa if( settled_some ) // which implies that BSRM is individual settlement to fund or to order { call_collateral_itr = call_collateral_index.lower_bound( call_min ); - if( call_collateral_itr == call_collateral_end ) + if( call_collateral_itr == call_collateral_end ) // no call order left + { + check_settled_debt_order( bitasset ); return true; + } margin_called = true; if( bsrm_type::individual_settlement_to_fund == bsrm ) limit_end = limit_price_index.upper_bound( bitasset.get_margin_call_order_price() ); @@ -1945,7 +2035,10 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa ( after_hardfork_436 && bitasset.current_feed.settlement_price > ~call_order.call_price ) : ( bitasset.current_maintenance_collateralization < call_order.collateralization() ); if( feed_protected ) + { + check_settled_debt_order( bitasset ); return margin_called; + } // match call orders with limit orders if( limit_itr != limit_end ) @@ -2133,6 +2226,8 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa return margin_called; // If no force settlements, we return + // Note: there is no matching limit order due to MSSR, or no limit order at all, + // in either case, the settled debt order can't be matched auto settle_itr = settlement_index.lower_bound( bitasset.asset_id ); if( settle_itr == settlement_index.end() || settle_itr->balance.asset_id != bitasset.asset_id ) return margin_called; @@ -2154,6 +2249,7 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa } // else : no more force settlements, or feed protected, both will be handled in the next loop } // while there exists a call order + check_settled_debt_order( bitasset ); return margin_called; } FC_CAPTURE_AND_RETHROW() } @@ -2224,6 +2320,47 @@ bool database::match_force_settlements( const asset_bitasset_data_object& bitass return false; } +void database::check_settled_debt_order( const asset_bitasset_data_object& bitasset ) +{ + const auto& head_time = head_block_time(); + bool after_core_hardfork_2591 = HARDFORK_CORE_2591_PASSED( head_time ); // Tighter peg (fill debt order at MCOP) + if( !after_core_hardfork_2591 ) + return; + + using bsrm_type = bitasset_options::black_swan_response_type; + const auto bsrm = bitasset.get_black_swan_response_method(); + if( bsrm_type::individual_settlement_to_order != bsrm ) + return; + + const limit_order_object* limit_ptr = find_settled_debt_order( bitasset.asset_id ); + if( !limit_ptr ) + return; + + const limit_order_index& limit_index = get_index_type(); + const auto& limit_price_index = limit_index.indices().get(); + + // Looking for limit orders selling the most USD for the least CORE. + auto max_price = price::max( bitasset.asset_id, bitasset.options.short_backing_asset ); + // Stop when limit orders are selling too little USD for too much CORE. + auto min_price = ~limit_ptr->sell_price; + + // NOTE limit_price_index is sorted from greatest to least + auto limit_itr = limit_price_index.lower_bound( max_price ); + auto limit_end = limit_price_index.upper_bound( min_price ); + + bool finished = false; // whether the settled debt order is gone + while( !finished && limit_itr != limit_end ) + { + const limit_order_object& matching_limit_order = *limit_itr; + ++limit_itr; + price old_price = limit_ptr->sell_price; + finished = ( match_settled_debt_limit( *limit_ptr, matching_limit_order, matching_limit_order.sell_price ) + != match_result_type::only_maker_filled ); + if( !finished && old_price != limit_ptr->sell_price ) + limit_end = limit_price_index.upper_bound( ~limit_ptr->sell_price ); + } +} + void database::pay_order( const account_object& receiver, const asset& receives, const asset& pays ) { if( pays.asset_id == asset_id_type() ) diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 511a025615..2b79829810 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -396,6 +396,16 @@ namespace graphene { namespace chain { bool mute_exceptions = false, bool skip_matching_settle_orders = false ); + /** + * @brief Match the settled debt order of the specified asset as taker with other orders on the opposite side + * of the order book + * @param bitasset The bitasset data object + * + * Since the core-2591 hard fork, this function is called after processed all call orders in + * @ref check_call_orders(). + */ + void check_settled_debt_order( const asset_bitasset_data_object& bitasset ); + // Note: Ideally this should be private. // Now it is public because we use it in a non-member function in db_market.cpp . enum class match_result_type @@ -419,6 +429,8 @@ namespace graphene { namespace chain { const price& trade_price ); match_result_type match_limit_settled_debt( const limit_order_object& taker, const limit_order_object& maker, const price& trade_price ); + match_result_type match_settled_debt_limit( const limit_order_object& taker, const limit_order_object& maker, + const price& trade_price ); /*** * @brief Match limit order as taker to a call order as maker * @param taker the order that is removing liquidity from the book From dfc71def84e16d4e0deacc363c2bc98f96eb87e4 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 24 Feb 2023 19:49:07 +0000 Subject: [PATCH 043/127] Extend individual_settlement_test for core-2591 hf --- tests/tests/bsrm_indvd_settlement_tests.cpp | 34 +++++++++++++-------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/tests/tests/bsrm_indvd_settlement_tests.cpp b/tests/tests/bsrm_indvd_settlement_tests.cpp index 895a58eb4e..ba6ac18822 100644 --- a/tests/tests/bsrm_indvd_settlement_tests.cpp +++ b/tests/tests/bsrm_indvd_settlement_tests.cpp @@ -45,18 +45,28 @@ BOOST_AUTO_TEST_CASE( individual_settlement_test ) generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); // multiple passes, - // 0 : individual settlement to order - // 1, 2 : individual settlement to fund - for( int i = 0; i < 3; ++ i ) + // 0 : individual settlement to order, before hf core-2582 + // 1, 2 : individual settlement to fund, before hf core-2582 + // 3 : individual settlement to order, after hf core-2582 + // 4, 5 : individual settlement to fund, after hf core-2582 + // 6 : individual settlement to order, after hf core-2591 + // 7, 8 : individual settlement to fund, after hf core-2591 + for( int i = 0; i < 9; ++ i ) { idump( (i) ); - if( 1 == i ) + if( 3 == i ) { // Advance to core-2582 hard fork generate_blocks(HARDFORK_CORE_2582_TIME); generate_block(); } + else if( 6 == i ) + { + // Advance to core-2591 hard fork + generate_blocks(HARDFORK_CORE_2591_TIME); + generate_block(); + } set_expiration( db, trx ); @@ -72,8 +82,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_test ) fund( borrower5, asset(init_amount) ); using bsrm_type = bitasset_options::black_swan_response_type; - uint8_t bsrm_value = (i == 0) ? static_cast(bsrm_type::individual_settlement_to_order) - : static_cast(bsrm_type::individual_settlement_to_fund); + uint8_t bsrm_value = ( 0 == ( i % 3 ) ) ? static_cast(bsrm_type::individual_settlement_to_order) + : static_cast(bsrm_type::individual_settlement_to_fund); // Create asset asset_create_operation acop; @@ -96,10 +106,10 @@ BOOST_AUTO_TEST_CASE( individual_settlement_test ) const asset_object& mpa = db.get(ptx.operation_results[0].get()); asset_id_type mpa_id = mpa.get_id(); - if( 0 == i ) + if( 0 == ( i % 3 ) ) BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() == bsrm_type::individual_settlement_to_order ); - else if( 1 == i || 2 == i ) + else BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() == bsrm_type::individual_settlement_to_fund ); @@ -305,7 +315,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_test ) // fund gets round_up(605 * 1239/1250) = 600, margin call fee = 605 - 600 = 5 // fund debt = 30029 - if( 0 == i ) // to order + if( 0 == ( i % 3 ) ) // to order { // call2 is matched with sell_mid // the size is the same, consider call2 as smaller @@ -372,7 +382,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_test ) BOOST_CHECK_EQUAL( get_balance( seller4_id, mpa_id ), 980000 ); // no change BOOST_CHECK_EQUAL( get_balance( seller4_id, asset_id_type() ), 439 ); // 439 } - else if( 1 == i || 2 == i ) // to fund + else // to fund { // sell_mid price is 100000/2000 = 50 // call pays price is (100000/2000) * (1239:1250) = 49.56 @@ -478,7 +488,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_test ) check_result(); - if( 1 == i ) // additional tests + if( ( i >= 3 ) && ( 1 == ( i % 3 ) ) ) // additional tests, only pass after hf core-2582 { set_expiration( db, trx ); @@ -504,7 +514,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_test ) // reset db.pop_block(); } - else if( 2 == i ) // additional tests + else if( ( i >= 3 ) && ( 2 == ( i % 3 ) ) ) // additional tests. NOTE: infinity loop and OOM before hf core-2582 { set_expiration( db, trx ); From 5fc7ee1c508b4402fbe091f106d04185aff0af3a Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 24 Feb 2023 23:43:17 +0000 Subject: [PATCH 044/127] Update tests taking settled-debt order for hf 2591 --- tests/tests/bsrm_indvd_settlement_tests.cpp | 330 +++++++++++++++++--- 1 file changed, 279 insertions(+), 51 deletions(-) diff --git a/tests/tests/bsrm_indvd_settlement_tests.cpp b/tests/tests/bsrm_indvd_settlement_tests.cpp index ba6ac18822..8106638b55 100644 --- a/tests/tests/bsrm_indvd_settlement_tests.cpp +++ b/tests/tests/bsrm_indvd_settlement_tests.cpp @@ -1855,15 +1855,32 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_price_test ) } FC_LOG_AND_RETHROW() } -/// Tests individual settlement to order : settles when price drops, and how orders are being matched after settled -BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_taking_test ) -{ - try { +/// Tests individual settlement to order : settles when price drops, and the settled-debt order is matched as maker +/// * Before hf core-2591, the settled-debt order is filled at its own price (collateral amount / debt amount) +/// * After hf core-2591, the settled-debt order is filled at margin call order price (MCOP) +BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test ) +{ try { + + // Advance to core-2467 hard fork + auto mi = db.get_global_properties().parameters.maintenance_interval; + generate_blocks(HARDFORK_CORE_2467_TIME - mi); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + set_expiration( db, trx ); + + // multiple passes, + // i == 0 : before hf core-2591 + // i == 1 : after hf core-2591 + for( int i = 0; i < 2; ++i ) + { + idump( (i) ); + + if( 1 == i ) + { + // Advance to core-2591 hard fork + generate_blocks(HARDFORK_CORE_2591_TIME); + generate_block(); + } - // Advance to core-2467 hard fork - auto mi = db.get_global_properties().parameters.maintenance_interval; - generate_blocks(HARDFORK_CORE_2467_TIME - mi); - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); set_expiration( db, trx ); ACTORS((sam)(feeder)(borrower)(borrower2)(borrower3)(borrower4)(seller)); @@ -1977,8 +1994,12 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_taking_test ) // call: margin call fee deducted = round_down(2000*11/1250) = 17, // fund receives 2000 - 17 = 1983 + BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1983 ); BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 100000 ); + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 100000 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1983 ); + BOOST_CHECK( settled_debt->sell_price == asset(1983)/asset(100000,mpa_id) ); // order match price = 100000 / 1983 = 50.428643469 BOOST_CHECK( !db.find( call_id ) ); @@ -1989,6 +2010,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_taking_test ) BOOST_CHECK_EQUAL( call4_id(db).debt.value, 100000 ); BOOST_CHECK_EQUAL( call4_id(db).collateral.value, 2500 ); + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 17 ); + // seller sells some const limit_order_object* limit_ptr = create_sell_order( seller, asset(10000,mpa_id), asset(100) ); // the limit order is filled @@ -2007,12 +2030,21 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_taking_test ) BOOST_CHECK_EQUAL( call4_id(db).debt.value, 100000 ); BOOST_CHECK_EQUAL( call4_id(db).collateral.value, 2500 ); + // no change to the settled-debt order + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1983 ); BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 100000 ); + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 100000 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1983 ); + BOOST_CHECK( settled_debt->sell_price == asset(1983)/asset(100000,mpa_id) ); BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 390021 ); // 400000 - 9979 BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 204 ); + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 18 ); // 17 + 1 + // publish a new feed so that 2 other debt positions are undercollateralized f.settlement_price = price( asset(100000,mpa_id), asset(1800) ); publish_feed( mpa_id, feeder_id, f, feed_icr ); @@ -2034,10 +2066,18 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_taking_test ) // fund receives 1895 - 16 = 1879 // call3: margin call fee deducted = round_down(2200*11/1250) = 19, // fund receives 2200 - 19 = 2181 + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 6043 ); // 1983 + 1879 + 2181 BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290021 ); // 100000 + 90021 + 100000 + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK( settled_debt->sell_price == asset(6043)/asset(290021,mpa_id) ); // order match price = 290021 / 6043 = 47.992884329 + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 53 ); // 17 + 1 + 16 + 19 + // borrower buys at higher price const limit_order_object* buy_high = create_sell_order( borrower, asset(10), asset(100,mpa_id) ); BOOST_CHECK( buy_high ); @@ -2054,102 +2094,290 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_taking_test ) BOOST_CHECK_EQUAL( call4_id(db).debt.value, 100000 ); BOOST_CHECK_EQUAL( call4_id(db).collateral.value, 2500 ); - BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 6043 ); // no change - BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290021 ); // no change + // no change to the settled-debt order + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 6043 ); + BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290021 ); + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK( settled_debt->sell_price == asset(6043)/asset(290021,mpa_id) ); BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 389921 ); // 400000 - 9979 - 100 BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 214 ); // 204 + 10 - // publish a new feed so that the settled debt order is in the front of the order book + // publish a new feed so that + // * before hf core-2591, the settled debt order is in the front of the order book + // * after hf core-2591, the settled debt order is updated to be behind the margin call orders f.settlement_price = price( asset(100000,mpa_id), asset(1600) ); publish_feed( mpa_id, feeder_id, f, feed_icr ); // call pays price = 100000:1600 * 1000:1250 = 100000:2000 = 50 // call match price = 100000:1600 * 1000:1239 = 100000:1982.4 = 50.443906376 + if( 0 == i ) + { + // no change to the settled-debt order + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 6043 ); + BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290021 ); + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK( settled_debt->sell_price == asset(6043)/asset(290021,mpa_id) ); + } + else if( 1 == i ) + { + // the settled-debt order is updated + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 5750 ); // round_up(290021 * 19824 / 1000000) + BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290052 ); //round_down(5750*1000000/19824) + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK( settled_debt->sell_price == asset(19824)/asset(1000000,mpa_id) ); + } + // borrower buys at higher price buy_high = create_sell_order( borrower, asset(10), asset(100,mpa_id) ); BOOST_CHECK( buy_high ); buy_high_id = buy_high->get_id(); - // seller sells some, this will match buy_high, - // and when it matches the settled debt, it will be cancelled since it is too small + // seller sells some, this will match buy_high, then + // * before hf core-2591, when it matches the settled debt, it will be cancelled since it is too small + // * after hf core-2591, when it matches a call order, it will be cancelled since it is too small limit_ptr = create_sell_order( seller, asset(120,mpa_id), asset(1) ); // the limit order is filled BOOST_CHECK( !limit_ptr ); // buy_high is filled BOOST_CHECK( !db.find( buy_high_id ) ); - BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 6043 ); // no change - BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290021 ); // no change + if( 0 == i ) + { + // no change to the settled-debt order + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 6043 ); + BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290021 ); + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK( settled_debt->sell_price == asset(6043)/asset(290021,mpa_id) ); + } + else if( 1 == i ) + { + // no change to the settled-debt order + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 5750 ); + BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290052 ); + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK( settled_debt->sell_price == asset(19824)/asset(1000000,mpa_id) ); + } BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 389821 ); // 400000 - 9979 - 100 - 100 BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 224 ); // 204 + 10 + 10 + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 53 ); // 17 + 1 + 16 + 19 + // seller sells some limit_ptr = create_sell_order( seller, asset(10000,mpa_id), asset(100) ); // the limit order is filled BOOST_CHECK( !limit_ptr ); - // the settled debt is partially filled - // limit order receives = round_down(10000*6043/290021) = 208 - // settled debt receives = round_up(208*290021/6043) = 9983 - BOOST_CHECK( !db.find( call_id ) ); - BOOST_CHECK( !db.find( call2_id ) ); - BOOST_CHECK( !db.find( call3_id ) ); - BOOST_CHECK_EQUAL( call4_id(db).debt.value, 100000 ); - BOOST_CHECK_EQUAL( call4_id(db).collateral.value, 2500 ); + if( 0 == i ) + { + // the settled debt is partially filled + // limit order receives = round_down(10000*6043/290021) = 208 + // settled debt receives = round_up(208*290021/6043) = 9983 - BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 5835 ); // 6043 - 208 - BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 280038 ); // 290021 - 9983 + BOOST_CHECK( !db.find( call_id ) ); + BOOST_CHECK( !db.find( call2_id ) ); + BOOST_CHECK( !db.find( call3_id ) ); + BOOST_CHECK_EQUAL( call4_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call4_id(db).collateral.value, 2500 ); + + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 5835 ); // 6043 - 208 + BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 280038 ); // 290021 - 9983 + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 280038 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 5835 ); + BOOST_CHECK( settled_debt->sell_price == asset(5835)/asset(280038,mpa_id) ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 379838 ); // 400000 - 9979 - 100 - 100 - 9983 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 432 ); // 204 + 10 + 10 + 208 + + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 53 ); // no change + } + else if( 1 == i ) + { + // call4 is partially filled + // limit order gets round_down(10000*(1600/100000)*(1239/1000)) = 198 + // limit order pays round_up(198*(100000/1600)*(1000/1239)) = 9988 + // call4 gets 9988 + // call4 pays round_down(9988*(1600/100000)*(1250/1000)) = 199, margin call fee = 1 - BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 379838 ); // 400000 - 9979 - 100 - 100 - 9983 - BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 432 ); // 204 + 10 + 10 + 208 + BOOST_CHECK( !db.find( call_id ) ); + BOOST_CHECK( !db.find( call2_id ) ); + BOOST_CHECK( !db.find( call3_id ) ); + BOOST_CHECK_EQUAL( call4_id(db).debt.value, 90012 ); // 100000 - 9988 + BOOST_CHECK_EQUAL( call4_id(db).collateral.value, 2301 ); // 2500 - 199 + + // no change to the settled-debt order + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 5750 ); + BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290052 ); + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK( settled_debt->sell_price == asset(19824)/asset(1000000,mpa_id) ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 379833 ); // 400000 - 9979 - 100 - 100 - 9988 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 422 ); // 204 + 10 + 10 + 198 + + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 54 ); // 53 + 1 + } // seller sells some limit_ptr = create_sell_order( seller, asset(300000,mpa_id), asset(3000) ); // the limit order is filled BOOST_CHECK( !limit_ptr ); - auto final_check = [&] + auto check_result = [&] { BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); - // the settled debt is fully filled - BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); - // limit order reminder = 300000 - 280038 = 19962 - // call4 is partially filled - // limit order gets round_down(19962*(1600/100000)*(1239/1000)) = 395 - // limit order pays round_up(395*(100000/1600)*(1000/1239)) = 19926 - // call4 gets 19926 - // call4 pays round_down(19926*(1600/100000)*(1250/1000)) = 398, margin call fee = 3 + if( 0 == i ) + { + // the settled debt is fully filled + BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); + // limit order reminder = 300000 - 280038 = 19962 + // call4 is partially filled + // limit order gets round_down(19962*(1600/100000)*(1239/1000)) = 395 + // limit order pays round_up(395*(100000/1600)*(1000/1239)) = 19926 + // call4 gets 19926 + // call4 pays round_down(19926*(1600/100000)*(1250/1000)) = 398, margin call fee = 3 + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 79874 ); // 400000 - 9979 - 100 - 100 - 9983 + // - 280038 - 19926 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 6662 ); // 204 + 10 + 10 + 208 + 5835 + 395 + + BOOST_CHECK( !db.find( call_id ) ); + BOOST_CHECK( !db.find( call2_id ) ); + BOOST_CHECK( !db.find( call3_id ) ); + BOOST_CHECK_EQUAL( call4_id(db).debt.value, 80074 ); // 100000 - 19926 + BOOST_CHECK_EQUAL( call4_id(db).collateral.value, 2102 ); // 2500 - 398 - BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 79874 ); // 400000 - 9979 - 100 - 100 - 9983 - // - 280038 - 19926 - BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 6662 ); // 204 + 10 + 10 + 208 + 5835 + 395 + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 56 ); // 53 + 3 + } + else if( 1 == i ) + { + // call4 is fully filled + BOOST_CHECK( !db.find( call_id ) ); + BOOST_CHECK( !db.find( call2_id ) ); + BOOST_CHECK( !db.find( call3_id ) ); + BOOST_CHECK( !db.find( call4_id ) ); + // call4 gets 90012 + // limit order gets round_up(90012*(1600/100000)*(1239/1000)) = 1785 + // call4 pays round_up(90012*(1600/100000)*(1250/1000)) = 1801, margin call fee = 1801 - 1785 = 16 - BOOST_CHECK( !db.find( call_id ) ); - BOOST_CHECK( !db.find( call2_id ) ); - BOOST_CHECK( !db.find( call3_id ) ); - BOOST_CHECK_EQUAL( call4_id(db).debt.value, 80074 ); // 100000 - 19926 - BOOST_CHECK_EQUAL( call4_id(db).collateral.value, 2102 ); // 2500 - 398 + // limit order reminder = 300000 - 90012 = 209988 + // the settled debt is partially filled + // limit order receives = round_down(209988*19824/1000000) = 4162 + // settled debt receives = round_up(4162*1000000/19824) = 209948 + // settled debt pays = round_down(209948*6043/290021) = 4374, collateral fee = 4374 - 4162 = 212 + + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1588 ); // round_up( 80073 * 19824 / 1000000 ) + BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 80104 ); //rnd_down(1588*1000000/19824) + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 80073 ); // 290021 - 209948 + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1669 ); // 6043 - 4374 + BOOST_CHECK( settled_debt->sell_price == asset(19824)/asset(1000000,mpa_id) ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 79873 ); // 400000 - 9979 - 100 - 100 - 9988 + // - 90012 - 209948 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 6369 ); // 204 + 10 + 10 + 198 + 1785 + 4162 + + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 282 ); // 54 + 16 + 212 + } }; - final_check(); + check_result(); BOOST_TEST_MESSAGE( "Generate a block" ); generate_block(); - final_check(); + check_result(); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + if( 1 == i ) + { + + // undercollateralization price = 100000:5000 * 1250:1000 = 100000:4000 + const call_order_object* call5_ptr = borrow( borrower4_id(db), asset(100000, mpa_id), asset(5000) ); + BOOST_REQUIRE( call5_ptr ); + call_order_id_type call5_id = call5_ptr->get_id(); + + BOOST_CHECK_EQUAL( call5_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call5_id(db).collateral.value, 5000 ); + + transfer( borrower4_id(db), seller_id(db), asset(100000,mpa_id) ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 179873 ); // 79873 + 100000 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 6369 ); // no change + + // seller sells some + limit_ptr = create_sell_order( seller_id(db), asset(100000,mpa_id), asset(1000) ); + // the limit order is partially filled + BOOST_REQUIRE( limit_ptr ); + limit_order_id_type limit_id = limit_ptr->get_id(); + + auto check_result_1 = [&] + { + // the settled-debt order is fully filled + BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); + + // settled debt receives = 80073 + // limit order receives = round_up(80073*19824/1000000) = 1588 + // settled debt pays = 1669, collateral fee = 1669 - 1588 = 81 + + BOOST_CHECK_EQUAL( limit_id(db).for_sale.value, 19927 ); // 100000 - 80073 + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 79873 ); // 179873 - 100000 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 7957 ); // 6369 + 1588 + + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 363 ); // 282 + 81 + }; + + check_result_1(); + + BOOST_TEST_MESSAGE( "Generate a new block" ); + generate_block(); + + check_result_1(); + + // reset + db.pop_block(); + } + + // reset + db.pop_block(); + + } // for i + +} FC_LOG_AND_RETHROW() } /// Tests a scenario that force settlements get cancelled on expiration when there is no debt position /// due to individual settlement to order From 404c1ce1ade5a380a3ab1479166373379d69af99 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 24 Feb 2023 23:48:45 +0000 Subject: [PATCH 045/127] Update try-catch in a test case --- tests/tests/bsrm_indvd_settlement_tests.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/tests/bsrm_indvd_settlement_tests.cpp b/tests/tests/bsrm_indvd_settlement_tests.cpp index 8106638b55..bb43be4ec5 100644 --- a/tests/tests/bsrm_indvd_settlement_tests.cpp +++ b/tests/tests/bsrm_indvd_settlement_tests.cpp @@ -2382,8 +2382,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test /// Tests a scenario that force settlements get cancelled on expiration when there is no debt position /// due to individual settlement to order BOOST_AUTO_TEST_CASE( settle_order_cancel_due_to_no_debt_position ) -{ - try { +{ try { // Advance to core-2467 hard fork auto mi = db.get_global_properties().parameters.maintenance_interval; @@ -2553,10 +2552,6 @@ BOOST_AUTO_TEST_CASE( settle_order_cancel_due_to_no_debt_position ) BOOST_CHECK_EQUAL( get_balance( seller_id, mpa2_id ), 88900 ); // 100000 - 11100 BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 0 ); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_SUITE_END() From c390977317d18235c5f602a2898dc5932add909c Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 25 Feb 2023 21:08:47 +0000 Subject: [PATCH 046/127] Fix a number in comments in test cases --- tests/tests/bsrm_indvd_settlement_tests.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/tests/bsrm_indvd_settlement_tests.cpp b/tests/tests/bsrm_indvd_settlement_tests.cpp index bb43be4ec5..e0bca4c7f9 100644 --- a/tests/tests/bsrm_indvd_settlement_tests.cpp +++ b/tests/tests/bsrm_indvd_settlement_tests.cpp @@ -679,7 +679,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_disable_force_settle_tes f.settlement_price = price( asset(100000,mpa_id), asset(1650,samcoin_id) ); publish_feed( mpa_id, feeder_id, f, feed_icr ); // call pays price = 100000:1650 * 1000:1250 = 100000:2062.5 = 48.484848485 - // call match price = 100000:1650 * 1000:1239 = 100000:2048.75 = 48.915303153 + // call match price = 100000:1650 * 1000:1239 = 100000:2044.35 = 48.915303153 // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); @@ -929,7 +929,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_no_feed ) f.settlement_price = price( asset(100000,mpa_id), asset(1650,samcoin_id) ); publish_feed( mpa_id, feeder_id, f, feed_icr ); // call pays price = 100000:1650 * 1000:1250 = 100000:2062.5 = 48.484848485 - // call match price = 100000:1650 * 1000:1239 = 100000:2048.75 = 48.915303153 + // call match price = 100000:1650 * 1000:1239 = 100000:2044.35 = 48.915303153 // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); @@ -1157,7 +1157,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_test ) f.settlement_price = price( asset(100000,mpa_id), asset(1650) ); publish_feed( mpa_id, feeder_id, f, feed_icr ); // call pays price = 100000:1650 * 1000:1250 = 100000:2062.5 = 48.484848485 - // call match price = 100000:1650 * 1000:1239 = 100000:2048.75 = 48.915303153 + // call match price = 100000:1650 * 1000:1239 = 100000:2044.35 = 48.915303153 // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); @@ -1479,7 +1479,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_price_test ) f.settlement_price = price( asset(100000,mpa_id), asset(1650) ); publish_feed( mpa_id, feeder_id, f, feed_icr ); // call pays price = 100000:1650 * 1000:1250 = 100000:2062.5 = 48.484848485 - // call match price = 100000:1650 * 1000:1239 = 100000:2048.75 = 48.915303153 + // call match price = 100000:1650 * 1000:1239 = 100000:2044.35 = 48.915303153 // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); @@ -1982,7 +1982,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test f.settlement_price = price( asset(100000,mpa_id), asset(1650) ); publish_feed( mpa_id, feeder_id, f, feed_icr ); // call pays price = 100000:1650 * 1000:1250 = 100000:2062.5 = 48.484848485 - // call match price = 100000:1650 * 1000:1239 = 100000:2048.75 = 48.915303153 + // call match price = 100000:1650 * 1000:1239 = 100000:2044.35 = 48.915303153 // check BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); @@ -2490,7 +2490,7 @@ BOOST_AUTO_TEST_CASE( settle_order_cancel_due_to_no_debt_position ) f.settlement_price = price( asset(100000,mpa_id), asset(1650) ); publish_feed( mpa_id, feeder_id, f, feed_icr ); // call pays price = 100000:1650 * 1000:1250 = 100000:2062.5 = 48.484848485 - // call match price = 100000:1650 * 1000:1239 = 100000:2048.75 = 48.915303153 + // call match price = 100000:1650 * 1000:1239 = 100000:2044.35 = 48.915303153 // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); From 2b2ca4b0c63f3fc1fff9bcfe239d1011953c473d Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 25 Feb 2023 23:00:48 +0000 Subject: [PATCH 047/127] Add tests that settled-debt order matches as taker --- tests/tests/bsrm_indvd_settlement_tests.cpp | 478 ++++++++++++++++++++ 1 file changed, 478 insertions(+) diff --git a/tests/tests/bsrm_indvd_settlement_tests.cpp b/tests/tests/bsrm_indvd_settlement_tests.cpp index e0bca4c7f9..42681117c8 100644 --- a/tests/tests/bsrm_indvd_settlement_tests.cpp +++ b/tests/tests/bsrm_indvd_settlement_tests.cpp @@ -2379,6 +2379,484 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test } FC_LOG_AND_RETHROW() } +/// Tests individual settlement to order : +/// after hf core-2591, the settled-debt order is matched as taker when price feed is updated +BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_taker_test ) +{ try { + + // Advance to core-2467 hard fork + auto mi = db.get_global_properties().parameters.maintenance_interval; + generate_blocks(HARDFORK_CORE_2467_TIME - mi); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + set_expiration( db, trx ); + + // multiple passes, + // i == 0 : before hf core-2591 + // i >= 1 : after hf core-2591 + for( int i = 0; i < 6; ++i ) + { + idump( (i) ); + + if( 1 == i ) + { + // Advance to core-2591 hard fork + generate_blocks(HARDFORK_CORE_2591_TIME); + generate_block(); + } + + set_expiration( db, trx ); + + ACTORS((sam)(feeder)(borrower)(borrower2)(seller)(seller2)); + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( sam, asset(init_amount) ); + fund( feeder, asset(init_amount) ); + fund( borrower, asset(init_amount) ); + fund( borrower2, asset(init_amount) ); + + using bsrm_type = bitasset_options::black_swan_response_type; + uint8_t bsrm_value = static_cast(bsrm_type::individual_settlement_to_order); + + // Create asset + asset_create_operation acop; + acop.issuer = sam_id; + acop.symbol = "SAMMPA"; + acop.precision = 2; + acop.common_options.core_exchange_rate = price(asset(1,asset_id_type(1)),asset(1)); + acop.common_options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; + acop.common_options.market_fee_percent = 100; // 1% + acop.common_options.flags = charge_market_fee; + acop.common_options.issuer_permissions = ASSET_ISSUER_PERMISSION_ENABLE_BITS_MASK; + acop.bitasset_opts = bitasset_options(); + acop.bitasset_opts->minimum_feeds = 1; + acop.bitasset_opts->extensions.value.black_swan_response_method = bsrm_value; + acop.bitasset_opts->extensions.value.margin_call_fee_ratio = 11; + + trx.operations.clear(); + trx.operations.push_back( acop ); + processed_transaction ptx = PUSH_TX(db, trx, ~0); + const asset_object& mpa = db.get(ptx.operation_results[0].get()); + asset_id_type mpa_id = mpa.get_id(); + + BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() + == bsrm_type::individual_settlement_to_order ); + + // add a price feed publisher and publish a feed + update_feed_producers( mpa_id, { feeder_id } ); + + price_feed f; + f.settlement_price = price( asset(100,mpa_id), asset(1) ); + f.core_exchange_rate = price( asset(100,mpa_id), asset(1) ); + f.maintenance_collateral_ratio = 1850; + f.maximum_short_squeeze_ratio = 1250; + + uint16_t feed_icr = 1900; + + publish_feed( mpa_id, feeder_id, f, feed_icr ); + + BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); + + // borrowers borrow some + // undercollateralization price = 100000:2000 * 1250:1000 = 100000:1600 + const call_order_object* call_ptr = borrow( borrower, asset(100000, mpa_id), asset(2000) ); + BOOST_REQUIRE( call_ptr ); + call_order_id_type call_id = call_ptr->get_id(); + + // Transfer funds to sellers + transfer( borrower, seller, asset(100000,mpa_id) ); + + BOOST_CHECK_EQUAL( call_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call_id(db).collateral.value, 2000 ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 100000 ); + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 0 ); + + // publish a new feed so that borrower's debt position is undercollateralized + f.settlement_price = price( asset(100000,mpa_id), asset(1650) ); + publish_feed( mpa_id, feeder_id, f, feed_icr ); + // call pays price = 100000:1650 * 1000:1250 = 100000:2062.5 = 48.484848485 + // call match price = 100000:1650 * 1000:1239 = 100000:2044.35 = 48.915303153 + + // check + BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).has_individual_settlement() ); + const limit_order_object* settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + + // call: margin call fee deducted = round_down(2000*11/1250) = 17, + // fund receives 2000 - 17 = 1983 + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1983 ); + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 100000 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1983 ); + BOOST_CHECK( settled_debt->sell_price == asset(1983)/asset(100000,mpa_id) ); + // order match price = 100000 / 1983 = 50.428643469 + + BOOST_CHECK( !db.find( call_id ) ); + + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 17 ); + + // seller sells some + const limit_order_object* limit_ptr = create_sell_order( seller, asset(10000,mpa_id), asset(100) ); + // the limit order is filled + BOOST_CHECK( !limit_ptr ); + + // the settled debt is partially filled + // limit order receives = round_down(10000*1983/100000) = 198 + // settled debt receives = round_up(198*100000/1983) = 9985 + // settled debt pays = 198, collateral fee = 0 + + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1785 ); // 1983 - 198 + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 90015 ); // 100000 - 9985 + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1785 ); + if( 0 == i ) + BOOST_CHECK( settled_debt->sell_price == asset(1785)/asset(90015,mpa_id) ); + else + BOOST_CHECK( settled_debt->sell_price == asset(1983)/asset(100000,mpa_id) ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 90015 ); // 100000 - 9985 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 198 ); + + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 17 ); + + // publish a new feed (collateral price rises) + f.settlement_price = price( asset(200,mpa_id), asset(1) ); + publish_feed( mpa_id, feeder_id, f, feed_icr ); + // call pays price = 200:1 * 1000:1250 = 200000:1250 = 160 + // call match price = 200:1 * 1000:1239 = 200000:1239 = 161.420500404 + + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + if( 0 == i ) + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1785 ); + else + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 558 ); // round_up( 90015 * 1239 / 200000 ) + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 90015 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1785 ); + if( 0 == i ) + BOOST_CHECK( settled_debt->sell_price == asset(1785)/asset(90015,mpa_id) ); + else + BOOST_CHECK( settled_debt->sell_price == asset(1239)/asset(200000,mpa_id) ); + + // seller sells some + limit_ptr = create_sell_order( seller, asset(10000,mpa_id), asset(150) ); + if( 0 == i ) + { + // the limit order is filled + BOOST_CHECK( !limit_ptr ); + + // the settled debt is partially filled + // limit order receives = round_down(10000*1785/90015) = 198 + // settled debt receives = round_up(198*90015/1785) = 9985 + // settled debt pays = 198, collateral fee = 0 + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1587 ); // 1983 - 198 - 198 + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 80030 ); // 100000 - 9985 - 9985 + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1587 ); + BOOST_CHECK( settled_debt->sell_price == asset(1587)/asset(80030,mpa_id) ); + + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 17 ); + + BOOST_TEST_MESSAGE( "Generate a block" ); + generate_block(); + + // reset + db.pop_block(); + // this branch ends here + continue; + } + + // the limit order is not filled + BOOST_REQUIRE( limit_ptr ); + limit_order_id_type limit_id = limit_ptr->get_id(); + + BOOST_CHECK_EQUAL( limit_id(db).for_sale.value, 10000 ); + + // the settled-debt order is unchanged + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 558 ); + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 90015 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1785 ); + BOOST_CHECK( settled_debt->sell_price == asset(1239)/asset(200000,mpa_id) ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 80015 ); // 100000 - 9985 - 10000 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 198 ); + + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 17 ); + + call_order_id_type call2_id; + limit_order_id_type limit2_id; + if( 1 == i ) + { + // do nothing here so that there is no call order exists + // so the settled-debt order will match the limit order on the next price feed update + } + if( 2 == i ) + { + // create a small call order that will go undercollateralized on the next price feed update + // so the settled-debt order after merged the new call order will still be well collateralized + // and will match the limit order + // undercollateralization price = 10000:100 * 1250:1000 = 100000:800 + const call_order_object* call2_ptr = borrow( borrower2, asset(10000, mpa_id), asset(100) ); + BOOST_REQUIRE( call2_ptr ); + call2_id = call2_ptr->get_id(); + + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 10000 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 100 ); + } + else if( 3 == i ) + { + // create a huge call order that will go undercollateralized on the next price feed update + // so the settled-debt order after merged the new call order will be undercollateralized too + // and will not match the limit order + // undercollateralization price = 1000000:10000 * 1250:1000 = 100000:800 + const call_order_object* call2_ptr = borrow( borrower2, asset(1000000, mpa_id), asset(10000) ); + BOOST_REQUIRE( call2_ptr ); + call2_id = call2_ptr->get_id(); + + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 1000000 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 10000 ); + } + else if( 4 == i ) + { + // create a big call order that will be margin called on the next price feed update + // so the settled-debt order will have no limit order to match with + // undercollateralization price = 100000:2400 * 1250:1000 = 100000:1920 + const call_order_object* call2_ptr = borrow( borrower2, asset(100000, mpa_id), asset(2400) ); + BOOST_REQUIRE( call2_ptr ); + call2_id = call2_ptr->get_id(); + + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 2400 ); + } + else if( 5 == i ) + { + // create a big call order that will not be margin called on the next price feed update + // so the settled-debt order will match the limit order + // undercollateralization price = 100000:5000 * 1250:1000 = 100000:4000 + const call_order_object* call2_ptr = borrow( borrower2, asset(100000, mpa_id), asset(5000) ); + BOOST_REQUIRE( call2_ptr ); + call2_id = call2_ptr->get_id(); + + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 5000 ); + + // Transfer funds to sellers + transfer( borrower2, seller2, asset(100000,mpa_id) ); + + BOOST_CHECK_EQUAL( get_balance( seller2_id, mpa_id ), 100000 ); + BOOST_CHECK_EQUAL( get_balance( seller2_id, asset_id_type() ), 0 ); + + // seller2 sells some + const limit_order_object* limit2_ptr = create_sell_order( seller2, asset(100000,mpa_id), asset(1550) ); + BOOST_REQUIRE( limit2_ptr ); + limit2_id = limit2_ptr->get_id(); + + BOOST_CHECK_EQUAL( limit2_id(db).for_sale.value, 100000 ); + + BOOST_CHECK_EQUAL( get_balance( seller2_id, mpa_id ), 0 ); // 100000 - 100000 + BOOST_CHECK_EQUAL( get_balance( seller2_id, asset_id_type() ), 0 ); + } + + // publish a new feed (collateral price drops) + f.settlement_price = price( asset(100000,mpa_id), asset(1350) ); + publish_feed( mpa_id, feeder_id, f, feed_icr ); + // call pays price (MSSP) = 100000:1350 * 1000:1250 = 100000:1687.5 = 59.259259259 + // call match price (MCOP) = 100000:1350 * 1000:1239 = 100000:1672.65 = 59.78537052 + + auto check_result = [&] + { + BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + + // the settled-debt order was: + // settled_debt_amount = 90015 + // settled_collateral_amount = 1785 + + // the limit order was selling 10000 MPA for 150 CORE + + if( 1 == i ) + { + // the settled-debt order is matched with the limit order + // the limit order is fully filled + BOOST_CHECK( !db.find( limit_id ) ); + + // the settled-debt order is partially filled, match price is 10000:150 + // limit order receives = 150 + // settled debt receives = 10000 + // settled debt pays = round_down(10000*1785/90015) = 198, collateral fee = 198 - 150 = 48 + + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1339 ); // round_up( 80015 * 167265 / 10000000 ) + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 80015 ); // 90015 - 10000 + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1587 ); // 1785 - 198 + BOOST_CHECK( settled_debt->sell_price == asset(167265)/asset(10000000,mpa_id) ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 80015 ); // 100000 - 9985 - 10000 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 348 ); // 198 + 150 + + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 65 ); // 17 + 48 + } + else if( 2 == i ) + { + // call2 is individually settled + BOOST_CHECK( !db.find( call2_id ) ); + + // margin call fee deducted = round_down(100*11/1250) = 0, + // fund receives 100, collateral = 1785 + 100 = 1885 + // fund debt = 90015 + 10000 = 100015 + // fund price = 100015 / 2785 = 53.058355438 < MCOP 59.78537052 + + // the settled-debt order is matched with the limit order + // the limit order is fully filled + BOOST_CHECK( !db.find( limit_id ) ); + + // the settled-debt order is partially filled, match price is 10000:150 + // limit order receives = 150 + // settled debt receives = 10000 + // settled debt pays = round_down(10000*1885/100015) = 188, collateral fee = 188 - 150 = 38 + + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1506 ); // round_up( 90015 * 167265 / 10000000 ) + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 90015 ); // 90015 - 10000 + 10000 + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1697 ); // 1785 + 100 - 188 + BOOST_CHECK( settled_debt->sell_price == asset(167265)/asset(10000000,mpa_id) ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 80015 ); // 100000 - 9985 - 10000 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 348 ); // 198 + 150 + + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 55 ); // 17 + 38 + } + else if( 3 == i ) + { + // call2 is individually settled + BOOST_CHECK( !db.find( call2_id ) ); + + // margin call fee deducted = round_down(10000*11/1250) = 88, + // fund receives 10000 - 88 = 9912, collateral = 1785 + 9912 = 11697 + // fund debt = 90015 + 1000000 = 1090015 + // fund price = 1090015 / 11697 = 93.187569462 > MCOP 59.78537052 + + // the settled-debt order can't be matched with the limit order + + BOOST_REQUIRE( db.find( limit_id ) ); + BOOST_CHECK_EQUAL( limit_id(db).for_sale.value, 10000 ); // no change + + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 11697 ); + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 1090015 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 11697 ); + BOOST_CHECK( settled_debt->sell_price == asset(11697)/asset(1090015,mpa_id) ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 80015 ); // no change + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 198 ); // no change + + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 105 ); // 17 + 88 + } + else if( 4 == i ) + { + // call2 is margin called, matched with the limit order + // the limit order is fully filled + BOOST_CHECK( !db.find( limit_id ) ); + + // call2 is partially filled + // limit order receives = 150 + // call2 receives = 10000 + // margin call fee = round_down(150*11/1250) = 1 + // call2 pays 150 + 1 = 151 + + BOOST_REQUIRE( db.find( call2_id ) ); + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 90000 ); // 100000 - 10000 + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 2249 ); // 2400 - 151 + + // the settled-debt order is not matched + + settled_debt = db.find_settled_debt_order(mpa_id); + BOOST_REQUIRE( settled_debt ); + BOOST_CHECK( settled_debt->is_settled_debt ); + BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1506 ); // round_up( 90015 * 167265 / 10000000 ) + BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 90015 ); + BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1785 ); + BOOST_CHECK( settled_debt->sell_price == asset(167265)/asset(10000000,mpa_id) ); + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 80015 ); // 100000 - 9985 - 10000 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 348 ); // 198 + 150 + + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 18 ); // 17 + 1 + } + else if( 5 == i ) + { + // call2 is unchanged + BOOST_REQUIRE( db.find( call2_id ) ); + BOOST_CHECK_EQUAL( call2_id(db).debt.value, 100000 ); + BOOST_CHECK_EQUAL( call2_id(db).collateral.value, 5000 ); + + // the settled-debt order is matched with the limit order + // the limit order is fully filled + BOOST_CHECK( !db.find( limit_id ) ); + + // the settled-debt order is partially filled, match price is 10000:150 + // limit order receives = 150 + // settled debt receives = 10000, settled_debt = 90015 - 10000 = 80015 + // settled debt pays = round_down(10000*1785/90015) = 198, collateral fee = 198 - 150 = 48 + // settled_collateral = 1785 - 198 = 1587 + + // then, the settled-debt order is matched with limit2 + // the settled-debt order is fully filled, match price is 10000:155 + // settled debt receives = 80015 + // limit2 receives = round_up(80015*155/10000) = 1241 + // settled debt pays = 1587, collateral fee = 1587 - 1241 = 346 + + BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); + + BOOST_CHECK_EQUAL( limit2_id(db).for_sale.value, 19985 ); // 100000 - 80015 + + BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 80015 ); // 100000 - 9985 - 10000 + BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 348 ); // 198 + 150 + + BOOST_CHECK_EQUAL( get_balance( seller2_id, mpa_id ), 0 ); // 100000 - 100000 + BOOST_CHECK_EQUAL( get_balance( seller2_id, asset_id_type() ), 1241 ); + + BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 411 ); // 17 + 48 + 346 + } + }; + + check_result(); + + BOOST_TEST_MESSAGE( "Generate a block" ); + generate_block(); + + check_result(); + + // reset + db.pop_block(); + + } // for i + +} FC_LOG_AND_RETHROW() } + /// Tests a scenario that force settlements get cancelled on expiration when there is no debt position /// due to individual settlement to order BOOST_AUTO_TEST_CASE( settle_order_cancel_due_to_no_debt_position ) From 8afc448e13f896eabb898acf81b3084c9fe455fb Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 10 Mar 2023 12:20:54 +0000 Subject: [PATCH 048/127] Skip prediction markets when paying collateral fee --- libraries/chain/asset_evaluator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index 4359bc4222..b56de7601a 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -1201,7 +1201,8 @@ static optional pay_collateral_fees( database& d, { const auto& head_time = d.head_block_time(); bool after_core_hardfork_2591 = HARDFORK_CORE_2591_PASSED( head_time ); // Tighter peg (fill settlement at MCOP) - if( after_core_hardfork_2591 && !bitasset.current_feed.settlement_price.is_null() ) + if( after_core_hardfork_2591 && !bitasset.is_prediction_market + && !bitasset.current_feed.settlement_price.is_null() ) { price fill_price = bitasset.get_margin_call_order_price(); try From eb45cc109fede31a484bd10c04b1f342a02ff361 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 10 Mar 2023 12:45:20 +0000 Subject: [PATCH 049/127] Fix global settlement when have settled-debt order --- libraries/chain/db_market.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index f0fbdf8d04..7e3d9bba87 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -319,7 +319,7 @@ void database::globally_settle_asset_impl( const asset_object& mia, const limit_order_object* limit_ptr = find_settled_debt_order( bitasset.asset_id ); if( limit_ptr ) { - collateral_gathered.amount += limit_ptr->for_sale; + collateral_gathered.amount += limit_ptr->settled_collateral_amount; remove( *limit_ptr ); } From 08a55e63c465eaf51ff9f631e2ffea311a869951 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 12 Mar 2023 21:46:15 +0000 Subject: [PATCH 050/127] Update manual_gs_test for core-2591 hard fork --- tests/tests/bsrm_basic_tests.cpp | 34 ++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/tests/tests/bsrm_basic_tests.cpp b/tests/tests/bsrm_basic_tests.cpp index d6047adcc3..dac4a9b089 100644 --- a/tests/tests/bsrm_basic_tests.cpp +++ b/tests/tests/bsrm_basic_tests.cpp @@ -1364,11 +1364,21 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) using bsrm_type = bitasset_options::black_swan_response_type; - // Several passes for each BSRM type - for( uint8_t i = 0; i <= 3; ++i ) + // Several passes, for each BSRM type, before and after core-2591 hf + for( uint8_t i = 0; i < 8; ++i ) { - idump( (i) ); + uint8_t bsrm = i % 4; + + idump( (i)(bsrm) ); + + if( 4 == i ) + { + // Advance to core-2591 hard fork + generate_blocks(HARDFORK_CORE_2591_TIME); + generate_block(); + } + set_expiration( db, trx ); ACTORS((sam)(feeder)(borrower)(borrower2)); auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; @@ -1387,7 +1397,7 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) acop.common_options.issuer_permissions = ASSET_ISSUER_PERMISSION_ENABLE_BITS_MASK; acop.bitasset_opts = bitasset_options(); acop.bitasset_opts->minimum_feeds = 1; - acop.bitasset_opts->extensions.value.black_swan_response_method = i; + acop.bitasset_opts->extensions.value.black_swan_response_method = bsrm; acop.bitasset_opts->extensions.value.margin_call_fee_ratio = 11; trx.operations.clear(); @@ -1396,7 +1406,7 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) const asset_object& mpa = db.get(ptx.operation_results[0].get()); asset_id_type mpa_id = mpa.get_id(); - BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() == static_cast(i) ); + BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() == static_cast(bsrm) ); BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); @@ -1431,7 +1441,7 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) const auto& check_result = [&] { BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); - switch( static_cast(i) ) + switch( static_cast(bsrm) ) { case bsrm_type::global_settlement: BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() @@ -1505,11 +1515,15 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) check_result(); + // publish a new feed (collateral price rises) + f.settlement_price = price( asset(1000,mpa_id), asset(15) ); + publish_feed( mpa_id, feeder_id, f, feed_icr ); + // globally settle - if( bsrm_type::no_settlement == static_cast(i) ) + if( bsrm_type::no_settlement == static_cast(bsrm) ) force_global_settle( mpa_id(db), price( asset(1000,mpa_id), asset(18) ) ); - else if( bsrm_type::individual_settlement_to_fund == static_cast(i) - || bsrm_type::individual_settlement_to_order == static_cast(i) ) + else if( bsrm_type::individual_settlement_to_fund == static_cast(bsrm) + || bsrm_type::individual_settlement_to_order == static_cast(bsrm) ) force_global_settle( mpa_id(db), price( asset(1000,mpa_id), asset(22) ) ); // check @@ -1526,7 +1540,7 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); - switch( static_cast(i) ) + switch( static_cast(bsrm) ) { case bsrm_type::global_settlement: break; From 338de923e8facc0dfb7a6b088a00c81d6a73f2a3 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 12 Mar 2023 23:05:41 +0000 Subject: [PATCH 051/127] Add tests for PM instant-settlement price --- tests/tests/settle_tests.cpp | 103 +++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/tests/tests/settle_tests.cpp b/tests/tests/settle_tests.cpp index 397092fcbe..97ba4a7ea6 100644 --- a/tests/tests/settle_tests.cpp +++ b/tests/tests/settle_tests.cpp @@ -2088,6 +2088,109 @@ BOOST_AUTO_TEST_CASE( collateral_fee_of_instant_settlement_test ) } FC_LOG_AND_RETHROW() } +/// Tests instant settlement: +/// * After hf core-2591, for prediction markets, forced-settlements are NOT filled at margin call order price (MCOP) +BOOST_AUTO_TEST_CASE( pm_instant_settlement_price_test ) +{ try { + + // Advance to a recent hard fork + generate_blocks(HARDFORK_CORE_2582_TIME); + generate_block(); + + // multiple passes, + // i == 0 : before hf core-2591 + // i == 1 : after hf core-2591 + for( int i = 0; i < 2; ++ i ) + { + idump( (i) ); + + if( 1 == i ) + { + // Advance to core-2591 hard fork + generate_blocks(HARDFORK_CORE_2591_TIME); + generate_block(); + } + + set_expiration( db, trx ); + + ACTORS((judge)(alice)(feeder)); + + const auto& pmark = create_prediction_market("PMARK", judge_id); + const auto& core = asset_id_type()(db); + + asset_id_type pm_id = pmark.get_id(); + + 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_CHECK_EQUAL( get_balance( alice_id, pm_id ), 1000 ); + BOOST_CHECK_EQUAL( get_balance( alice_id, asset_id_type() ), init_balance - 1000 ); + + // add a price feed publisher and publish a feed + update_feed_producers( pm_id, { feeder_id } ); + + price_feed f; + f.settlement_price = price( asset(100,pm_id), asset(1) ); + f.core_exchange_rate = price( asset(100,pm_id), asset(1) ); + f.maintenance_collateral_ratio = 1850; + f.maximum_short_squeeze_ratio = 1250; + + uint16_t feed_icr = 1900; + + publish_feed( pm_id, feeder_id, f, feed_icr ); + + BOOST_CHECK_EQUAL( get_balance( alice_id, pm_id ), 1000 ); + BOOST_CHECK_EQUAL( get_balance( alice_id, asset_id_type() ), init_balance - 1000 ); + + BOOST_TEST_MESSAGE( "Globally settling" ); + force_global_settle( pmark, pmark.amount(1) / core.amount(1) ); + + BOOST_CHECK_EQUAL( get_balance( alice_id, pm_id ), 1000 ); + BOOST_CHECK_EQUAL( get_balance( alice_id, asset_id_type() ), init_balance - 1000 ); + + // alice settles + auto result = force_settle( alice, asset(300, pm_id) ); + auto op_result = result.get().value; + + BOOST_CHECK( !op_result.new_objects.valid() ); // force settlement order not created + + BOOST_REQUIRE( op_result.paid.valid() && 1U == op_result.paid->size() ); + BOOST_CHECK( *op_result.paid->begin() == asset( 300, pm_id ) ); + BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() ); + BOOST_CHECK( *op_result.received->begin() == asset( 300 ) ); + BOOST_REQUIRE( op_result.fees.valid() && 1U == op_result.fees->size() ); + BOOST_CHECK( *op_result.fees->begin() == asset( 0 ) ); + + auto check_result = [&] + { + BOOST_CHECK( !pm_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( pm_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK_EQUAL( pm_id(db).bitasset_data(db).settlement_fund.value, 700 ); + + BOOST_CHECK_EQUAL( pm_id(db).dynamic_data(db).accumulated_collateral_fees.value, 0 ); + + BOOST_CHECK_EQUAL( get_balance( alice_id, pm_id ), 700 ); + BOOST_CHECK_EQUAL( get_balance( alice_id, asset_id_type() ), init_balance - 700 ); + }; + + check_result(); + + BOOST_TEST_MESSAGE( "Generate a block" ); + generate_block(); + + check_result(); + + // reset + db.pop_block(); + + } // for i + +} 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. From 3b8913b7ceb777179bd7fd30ace4fdd302d5e0ec Mon Sep 17 00:00:00 2001 From: Abit Date: Sun, 19 Mar 2023 02:44:55 +0100 Subject: [PATCH 052/127] Save the result of virtual limit_order_cancel op --- libraries/chain/db_market.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index 05c78c0b54..397312cd90 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -593,7 +593,10 @@ void database::cancel_limit_order( const limit_order_object& order, bool create_ } if( create_virtual_op ) - push_applied_operation( vop ); + { + auto op_id = push_applied_operation( vop ); + set_applied_operation_result( op_id, refunded ); + } remove(order); } From e60d9e1910e0b9b7449adf389d41b6b2551bf571 Mon Sep 17 00:00:00 2001 From: Abit Date: Sun, 19 Mar 2023 12:47:12 +0100 Subject: [PATCH 053/127] Bump DB_VERSION --- libraries/chain/include/graphene/chain/config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 5390eb2270..e905050d7c 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -32,7 +32,7 @@ #define GRAPHENE_MAX_NESTED_OBJECTS (200) -const std::string GRAPHENE_CURRENT_DB_VERSION = "20220930"; +const std::string GRAPHENE_CURRENT_DB_VERSION = "20230319"; #define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4 #define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3 From 778fa645e1600b87021f7f51634272692f6e590d Mon Sep 17 00:00:00 2001 From: Abit Date: Sun, 19 Mar 2023 03:09:06 +0100 Subject: [PATCH 054/127] Add `is_virtual` field in account history in ES --- libraries/plugins/elasticsearch/elasticsearch_plugin.cpp | 1 + .../include/graphene/elasticsearch/elasticsearch_plugin.hpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index 205bbf78f3..776046f3cf 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -272,6 +272,7 @@ void elasticsearch_plugin_impl::doOperationHistory( const optional trx_in_block; os.op_in_trx = oho->op_in_trx; os.virtual_op = oho->virtual_op; + os.is_virtual = oho->is_virtual; os.fee_payer = oho->op.visit( get_fee_payer_visitor() ); if(_options.operation_string) diff --git a/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp b/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp index 797fe3b8c0..e2ad5bf483 100644 --- a/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp +++ b/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp @@ -83,6 +83,7 @@ struct operation_history_struct { uint16_t trx_in_block; uint16_t op_in_trx; uint32_t virtual_op; + bool is_virtual; account_id_type fee_payer; std::string op; std::string operation_result; @@ -147,7 +148,7 @@ struct bulk_struct { FC_REFLECT_ENUM( graphene::elasticsearch::mode, (only_save)(only_query)(all) ) FC_REFLECT( graphene::elasticsearch::operation_history_struct, - (trx_in_block)(op_in_trx)(virtual_op)(fee_payer) + (trx_in_block)(op_in_trx)(virtual_op)(is_virtual)(fee_payer) (op)(operation_result)(op_object)(operation_result_object) ) FC_REFLECT( graphene::elasticsearch::block_struct, (block_num)(block_time)(trx_id) ) FC_REFLECT( graphene::elasticsearch::fee_struct, (asset)(asset_name)(amount)(amount_units) ) From 56b8d19a8b2d0d04f4d53e27085e2c1be34f039e Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 19 Mar 2023 12:12:17 +0000 Subject: [PATCH 055/127] Fix missing data in es_plugin::get_account_history Data in these fields was missing from the return value: * is_virtual * block_time --- libraries/plugins/elasticsearch/elasticsearch_plugin.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index 776046f3cf..14529fb3fb 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -612,6 +612,9 @@ static operation_history_object fromEStoOperation(const variant& source) result.trx_in_block = source["operation_history"]["trx_in_block"].as_uint64(); result.op_in_trx = source["operation_history"]["op_in_trx"].as_uint64(); result.trx_in_block = source["operation_history"]["virtual_op"].as_uint64(); + result.is_virtual = source["operation_history"]["is_virtual"].as_bool(); + + result.block_time = fc::time_point_sec::from_iso_string( source["block_data"]["block_time"].as_string() ); return result; } From 637a414815a404effc09eba8d7e0a63776da8436 Mon Sep 17 00:00:00 2001 From: Abit Date: Sun, 19 Mar 2023 17:12:24 +0100 Subject: [PATCH 056/127] Update license year to 2023 --- LICENSE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index dab0004a09..0b8ebaf47b 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2015-2022 Cryptonomex Inc. and +Copyright (c) 2015-2023 Cryptonomex Inc. and contributors (see CONTRIBUTORS.txt) The MIT License From 40be62a0b0bafcfa9596a267f8c7db47400f3088 Mon Sep 17 00:00:00 2001 From: Abit Date: Sun, 19 Mar 2023 15:47:12 +0100 Subject: [PATCH 057/127] Add tests for virtual limit_order_cancel op result --- tests/tests/history_api_tests.cpp | 41 +++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/tests/tests/history_api_tests.cpp b/tests/tests/history_api_tests.cpp index c1a5f31a75..4608e4b3a1 100644 --- a/tests/tests/history_api_tests.cpp +++ b/tests/tests/history_api_tests.cpp @@ -138,8 +138,8 @@ BOOST_AUTO_TEST_CASE(get_account_history) { } } -BOOST_AUTO_TEST_CASE(get_account_history_virtual_operation_test) { - try { +BOOST_AUTO_TEST_CASE(get_account_history_virtual_operation_test) +{ try { graphene::app::history_api hist_api(app); asset_id_type usd_id = create_user_issued_asset("USD").get_id(); @@ -164,11 +164,38 @@ BOOST_AUTO_TEST_CASE(get_account_history_virtual_operation_test) { BOOST_CHECK( histories.front().block_time == db.head_block_time() ); BOOST_CHECK( histories.front().is_virtual ); - } catch (fc::exception &e) { - edump((e.to_detail_string())); - throw; - } -} + // Create a limit order that expires in 300 seconds + create_sell_order( dan_id, asset(10, usd_id), asset(10), db.head_block_time() + 300 ); + + generate_block(); + fc::usleep(fc::milliseconds(100)); + + auto order_create_op_id = operation::tag::value; + + histories = hist_api.get_account_history("dan", operation_history_id_type(), + 100, operation_history_id_type()); + + BOOST_REQUIRE_GT( histories.size(), 0 ); + BOOST_CHECK_EQUAL( histories.front().op.which(), order_create_op_id ); + BOOST_CHECK( histories.front().block_time == db.head_block_time() ); + BOOST_CHECK( !histories.front().is_virtual ); + + // Let the limit order expire + generate_blocks( db.head_block_time() + 300 ); + generate_block(); + fc::usleep(fc::milliseconds(100)); + + auto order_cancel_op_id = operation::tag::value; + + histories = hist_api.get_account_history("dan", operation_history_id_type(), + 100, operation_history_id_type()); + + BOOST_REQUIRE_GT( histories.size(), 0 ); + BOOST_CHECK_EQUAL( histories.front().op.which(), order_cancel_op_id ); + BOOST_CHECK( histories.front().is_virtual ); + BOOST_CHECK( histories.front().result.is_type() ); + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(get_account_history_notify_all_on_creation) { try { From bfa0401bdcba8bc52e6668766ecdb4b62e3919ab Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 19 Mar 2023 17:03:36 +0000 Subject: [PATCH 058/127] Add tests for es_plugin::get_acc_his missing data --- tests/elasticsearch/main.cpp | 49 +++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/tests/elasticsearch/main.cpp b/tests/elasticsearch/main.cpp index bba0ce1889..5794d7f433 100644 --- a/tests/elasticsearch/main.cpp +++ b/tests/elasticsearch/main.cpp @@ -129,6 +129,8 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) { BOOST_CHECK_EQUAL(last_transfer_amount, "300"); auto last_transfer_payer = j["_source"]["operation_history"]["fee_payer"].as_string(); BOOST_CHECK_EQUAL(last_transfer_payer, "1.2.0"); + auto is_virtual = j["_source"]["operation_history"]["is_virtual"].as_bool(); + BOOST_CHECK( !is_virtual ); // To test credit offers generate_blocks( HARDFORK_CORE_2362_TIME ); @@ -375,6 +377,9 @@ BOOST_AUTO_TEST_CASE(elasticsearch_history_api) { BOOST_CHECK_EQUAL(histories[2].id.instance(), 1u); BOOST_CHECK_EQUAL(histories[3].id.instance(), 0u); + BOOST_CHECK( !histories[0].is_virtual ); + BOOST_CHECK( histories[0].block_time == db.head_block_time() ); + // f(A, 0, 4, 6) = { 5, 3, 1, 0 } histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 4, operation_history_id_type(6)); BOOST_REQUIRE_EQUAL(histories.size(), 4u); @@ -627,7 +632,8 @@ BOOST_AUTO_TEST_CASE(elasticsearch_history_api) { BOOST_CHECK_EQUAL(histories.size(), 0u); // create a new account C = alice { 7 } - create_account("alice"); + auto alice = create_account("alice"); + account_id_type alice_id = alice.get_id(); generate_block(); @@ -662,6 +668,47 @@ BOOST_AUTO_TEST_CASE(elasticsearch_history_api) { }, "thread invoke for method " BOOST_PP_STRINGIZE(method_name)).wait(); BOOST_REQUIRE( his_obj7.op.is_type() ); BOOST_CHECK_EQUAL( his_obj7.op.get().name, "alice" ); + + // Test virtual operation + + // Prepare funds + transfer( account_id_type()(db), alice_id(db), asset(100) ); + // Create a limit order that expires in 300 seconds + create_sell_order( alice_id, asset(1), asset(1, asset_id_type(1)), db.head_block_time() + 300 ); + + generate_block(); + + // f(C, 0, 4, 0) = { 9, 8, 7 } + fc::wait_for( ES_WAIT_TIME, [&]() { + histories = hist_api.get_account_history( + "alice", operation_history_id_type(0), 4, operation_history_id_type(0)); + return (histories.size() == 3u); + }); + BOOST_REQUIRE_EQUAL(histories.size(), 3u); + BOOST_CHECK( histories[0].op.is_type() ); + BOOST_CHECK( !histories[0].is_virtual ); + BOOST_CHECK( histories[0].block_time == db.head_block_time() ); + BOOST_CHECK( histories[1].op.is_type() ); + BOOST_CHECK( !histories[1].is_virtual ); + + // Let the limit order expire + generate_blocks( db.head_block_time() + 300 ); + generate_block(); + + // f(C, 0, 4, 0) = { 10, 9, 8, 7 } + fc::wait_for( ES_WAIT_TIME, [&]() { + histories = hist_api.get_account_history( + "alice", operation_history_id_type(0), 4, operation_history_id_type(0)); + return (histories.size() == 4u); + }); + BOOST_REQUIRE_EQUAL(histories.size(), 4u); + BOOST_CHECK( histories[0].op.is_type() ); + BOOST_CHECK( histories[0].is_virtual ); + BOOST_CHECK( histories[1].op.is_type() ); + BOOST_CHECK( !histories[1].is_virtual ); + BOOST_CHECK( histories[2].op.is_type() ); + BOOST_CHECK( !histories[2].is_virtual ); + } } catch (fc::exception &e) { From c3a1e40bafba4e3f7f3f6add361e57474733e0ba Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 19 Mar 2023 18:26:10 +0000 Subject: [PATCH 059/127] Set a timeout for running unit tests in Github CI --- .github/workflows/build-and-test.mac.yml | 1 + .github/workflows/build-and-test.ubuntu-debug.yml | 1 + .github/workflows/build-and-test.ubuntu-release.yml | 1 + .github/workflows/sonar-scan.yml | 1 + 4 files changed, 4 insertions(+) diff --git a/.github/workflows/build-and-test.mac.yml b/.github/workflows/build-and-test.mac.yml index de5dcd5e8a..bf43b5baae 100644 --- a/.github/workflows/build-and-test.mac.yml +++ b/.github/workflows/build-and-test.mac.yml @@ -45,6 +45,7 @@ jobs: make -j 3 -C _build witness_node cli_wallet app_test cli_test chain_test df -h - name: Unit-Tests + timeout-minutes: 15 run: | _build/tests/app_test -l test_suite libraries/fc/tests/run-parallel-tests.sh _build/tests/chain_test -l test_suite diff --git a/.github/workflows/build-and-test.ubuntu-debug.yml b/.github/workflows/build-and-test.ubuntu-debug.yml index 8946b3e036..35a506108c 100644 --- a/.github/workflows/build-and-test.ubuntu-debug.yml +++ b/.github/workflows/build-and-test.ubuntu-debug.yml @@ -110,6 +110,7 @@ jobs: du -hs _build/* du -hs /_build/* - name: Unit-Tests + timeout-minutes: 15 run: | _build/tests/app_test -l test_suite df -h diff --git a/.github/workflows/build-and-test.ubuntu-release.yml b/.github/workflows/build-and-test.ubuntu-release.yml index c149e28901..d85aed7b6b 100644 --- a/.github/workflows/build-and-test.ubuntu-release.yml +++ b/.github/workflows/build-and-test.ubuntu-release.yml @@ -87,6 +87,7 @@ jobs: make -j 2 -C _build df -h - name: Unit-Tests + timeout-minutes: 15 run: | _build/tests/app_test -l test_suite _build/tests/es_test -l test_suite diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index c83b9857a4..8356303fda 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -164,6 +164,7 @@ jobs: rm -rf _build/programs/genesis_util/get_dev_key df -h - name: Unit-Tests + timeout-minutes: 15 run: | _build/tests/app_test -l test_suite df -h From 887203c4da09dcb82ffb0327d37f0fca157f8470 Mon Sep 17 00:00:00 2001 From: abitmore Date: Mon, 20 Mar 2023 00:12:42 +0000 Subject: [PATCH 060/127] Bump DB_VERSION --- libraries/chain/include/graphene/chain/config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index e905050d7c..c7d322801c 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -32,7 +32,7 @@ #define GRAPHENE_MAX_NESTED_OBJECTS (200) -const std::string GRAPHENE_CURRENT_DB_VERSION = "20230319"; +const std::string GRAPHENE_CURRENT_DB_VERSION = "20230320"; #define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4 #define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3 From bba9b4a1b675d3da9d02327c12de87baf25701c9 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 19 Mar 2023 04:15:06 +0000 Subject: [PATCH 061/127] Implement credit deal auto-repayment --- libraries/chain/credit_offer_evaluator.cpp | 40 +++++++++++- libraries/chain/db_init.cpp | 1 + libraries/chain/db_notify.cpp | 4 ++ libraries/chain/db_update.cpp | 65 +++++++++++++++++++ libraries/chain/hardfork.d/CORE_2595.hf | 6 ++ .../chain/include/graphene/chain/config.hpp | 2 +- .../graphene/chain/credit_offer_evaluator.hpp | 11 ++++ .../graphene/chain/credit_offer_object.hpp | 1 + .../graphene/chain/hardfork_visitor.hpp | 5 ++ libraries/chain/proposal_evaluator.cpp | 13 +++- libraries/chain/small_objects.cpp | 1 + libraries/protocol/credit_offer.cpp | 19 ++++++ .../graphene/protocol/credit_offer.hpp | 59 ++++++++++++++++- .../include/graphene/protocol/operations.hpp | 3 +- 14 files changed, 224 insertions(+), 6 deletions(-) create mode 100644 libraries/chain/hardfork.d/CORE_2595.hf diff --git a/libraries/chain/credit_offer_evaluator.cpp b/libraries/chain/credit_offer_evaluator.cpp index d9413f547b..cbbb64464f 100644 --- a/libraries/chain/credit_offer_evaluator.cpp +++ b/libraries/chain/credit_offer_evaluator.cpp @@ -229,6 +229,13 @@ void_result credit_offer_update_evaluator::do_apply( const credit_offer_update_o void_result credit_offer_accept_evaluator::do_evaluate(const credit_offer_accept_operation& op) { try { const database& d = db(); + const auto block_time = d.head_block_time(); + + if( !HARDFORK_CORE_2595_PASSED(block_time) ) + { + FC_ASSERT( !op.extensions.value.auto_repay.valid(), + "auto_repay unavailable until the core-2595 hardfork"); + } _offer = &op.offer_id(d); @@ -325,6 +332,7 @@ extendable_operation_result credit_offer_accept_evaluator::do_apply( const credi obj.collateral_amount = op.collateral.amount; obj.fee_rate = _offer->fee_rate; obj.latest_repay_time = repay_time; + obj.auto_repay = ( op.extensions.value.auto_repay.valid() ? *op.extensions.value.auto_repay : 0 ); }); if( _deal_summary != nullptr ) @@ -377,7 +385,7 @@ void_result credit_deal_repay_evaluator::do_evaluate(const credit_deal_repay_ope // Note: the result can be larger than 64 bit, but since we don't store it, it is allowed auto required_fee = ( ( ( fc::uint128_t( op.repay_amount.amount.value ) * _deal->fee_rate ) - + GRAPHENE_FEE_RATE_DENOM ) - 1 ) / GRAPHENE_FEE_RATE_DENOM; // Round up + + GRAPHENE_FEE_RATE_DENOM ) - 1 ) / GRAPHENE_FEE_RATE_DENOM; // Round up FC_ASSERT( fc::uint128_t(op.credit_fee.amount.value) >= required_fee, "Insuffient credit fee, requires ${r}, offered ${p}", @@ -442,6 +450,9 @@ extendable_operation_result credit_deal_repay_evaluator::do_apply( const credit_ } else // to partially repay { + // Note: + // Due to rounding, it is possible that the account is paying too much debt asset for too little collateral, + // in extreme cases, the amount to release can be zero. auto amount_to_release = ( fc::uint128_t( op.repay_amount.amount.value ) * _deal->collateral_amount.value ) / _deal->debt_amount.value; // Round down FC_ASSERT( amount_to_release < fc::uint128_t( _deal->collateral_amount.value ), "Internal error" ); @@ -461,4 +472,31 @@ extendable_operation_result credit_deal_repay_evaluator::do_apply( const credit_ return result; } FC_CAPTURE_AND_RETHROW( (op) ) } +void_result credit_deal_update_evaluator::do_evaluate(const credit_deal_update_operation& op) +{ try { + const database& d = db(); + const auto block_time = d.head_block_time(); + + FC_ASSERT( HARDFORK_CORE_2595_PASSED(block_time), "Not allowed until the core-2595 hardfork" ); + + _deal = &op.deal_id(d); + + FC_ASSERT( _deal->borrower == op.account, "A credit deal can only be updated by the borrower" ); + + FC_ASSERT( _deal->auto_repay != op.auto_repay, "The automatic repayment type does not change" ); + + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + +void_result credit_deal_update_evaluator::do_apply( const credit_deal_update_operation& op) const +{ try { + database& d = db(); + + d.modify( *_deal, [&op]( credit_deal_object& obj ){ + obj.auto_repay = op.auto_repay; + }); + + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + } } // graphene::chain diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index d64c4abc7a..08ecf2f9b7 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -147,6 +147,7 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); + register_evaluator(); } void database::initialize_indexes() diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index c33b4f331b..899f77db1c 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -387,6 +387,10 @@ struct get_impacted_account_visitor _impacted.insert( op.offer_owner ); _impacted.insert( op.borrower ); } + void operator()( const credit_deal_update_operation& op ) + { + _impacted.insert( op.fee_payer() ); // account + } }; } // namespace detail diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index 67122ac917..4ca0ade75c 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -770,6 +770,71 @@ void database::update_credit_offers_and_deals() { const credit_deal_object& deal = *deal_itr; + // Note: automatic repayment fails if the borrower became unauthorized by the debt asset or the collateral asset + using repay_type = credit_deal_auto_repayment_type; + if( static_cast(repay_type::no_auto_repayment) != deal.auto_repay ) + { + credit_deal_repay_operation op; + op.account = deal.borrower; + op.deal_id = deal.get_id(); + // Amounts + // Note: the result can be larger than 64 bit + auto required_fee = ( ( ( fc::uint128_t( deal.debt_amount.value ) * deal.fee_rate ) + + GRAPHENE_FEE_RATE_DENOM ) - 1 ) / GRAPHENE_FEE_RATE_DENOM; // Round up + fc::uint128_t total_required = required_fee + deal.debt_amount.value; + auto balance = get_balance( deal.borrower, deal.debt_asset ); + if( static_cast(repay_type::only_full_repayment) == deal.auto_repay + || fc::uint128_t( balance.amount.value ) >= total_required ) + { // if only full repayment or account balance is sufficient + op.repay_amount = asset( deal.debt_amount, deal.debt_asset ); + op.credit_fee = asset( static_cast( required_fee ), deal.debt_asset ); + } + else // Allow partial repayment + { + fc::uint128_t debt_to_repay = ( fc::uint128_t( balance.amount.value ) * GRAPHENE_FEE_RATE_DENOM ) + / ( GRAPHENE_FEE_RATE_DENOM + deal.fee_rate ); // Round down + fc::uint128_t collateral_to_release = ( debt_to_repay * deal.collateral_amount.value ) + / deal.debt_amount.value; // Round down + debt_to_repay = ( ( ( collateral_to_release * deal.debt_amount.value ) + deal.collateral_amount.value ) + - 1 ) / deal.collateral_amount.value; // Round up + fc::uint128_t fee_to_pay = ( ( ( debt_to_repay * deal.fee_rate ) + + GRAPHENE_FEE_RATE_DENOM ) - 1 ) / GRAPHENE_FEE_RATE_DENOM; // Round up + op.repay_amount = asset( static_cast( debt_to_repay ), deal.debt_asset ); + op.credit_fee = asset( static_cast( fee_to_pay ), deal.debt_asset ); + } + + auto deal_copy = deal; // Make a copy for logging + + transaction_evaluation_state eval_state(this); + eval_state.skip_fee_schedule_check = true; + + size_t old_applied_ops_size = _applied_ops.size(); + auto old_op_in_trx = _current_op_in_trx; + auto old_vop = _current_virtual_op; + try + { + auto temp_session = _undo_db.start_undo_session(); + apply_operation( eval_state, op ); // This is a virtual operation + temp_session.merge(); + } + catch( const fc::exception& e ) + { + // We can in fact get here, + // e.g. if asset issuer of debt/collateral asset blacklists/whitelists the account, + // or insufficient account balance + wlog( "Automatic repayment ${op} for credit deal ${credit_deal} failed at block ${n}; " + "account balance was ${balance}; exception was ${e}", + ("op", op)("credit_deal", deal_copy) + ("n", head_block_num())("balance", balance)("e", e.to_detail_string()) ); + _current_virtual_op = old_vop; + _current_op_in_trx = old_op_in_trx; + _applied_ops.resize( old_applied_ops_size ); + } + + if( !find( op.deal_id ) ) // The credit deal is fully repaid + continue; + } + // Update offer // Note: offer balance can be zero after updated. TODO remove zero-balance offers after a period const credit_offer_object& offer = deal.offer_id(*this); diff --git a/libraries/chain/hardfork.d/CORE_2595.hf b/libraries/chain/hardfork.d/CORE_2595.hf new file mode 100644 index 0000000000..e5192b242a --- /dev/null +++ b/libraries/chain/hardfork.d/CORE_2595.hf @@ -0,0 +1,6 @@ +// bitshares-core issue #2595 Credit deal auto-repayment +#ifndef HARDFORK_CORE_2595_TIME +// Jan 1 2030, midnight; this is a dummy date until a hardfork date is scheduled +#define HARDFORK_CORE_2595_TIME (fc::time_point_sec( 1893456000 )) +#define HARDFORK_CORE_2595_PASSED(head_block_time) (head_block_time >= HARDFORK_CORE_2595_TIME) +#endif diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index c7d322801c..5d96e58654 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -32,7 +32,7 @@ #define GRAPHENE_MAX_NESTED_OBJECTS (200) -const std::string GRAPHENE_CURRENT_DB_VERSION = "20230320"; +const std::string GRAPHENE_CURRENT_DB_VERSION = "20230322"; #define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4 #define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3 diff --git a/libraries/chain/include/graphene/chain/credit_offer_evaluator.hpp b/libraries/chain/include/graphene/chain/credit_offer_evaluator.hpp index 359e3a686d..e5e730a190 100644 --- a/libraries/chain/include/graphene/chain/credit_offer_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/credit_offer_evaluator.hpp @@ -84,4 +84,15 @@ namespace graphene { namespace chain { const credit_deal_object* _deal = nullptr; }; + class credit_deal_update_evaluator : public evaluator + { + public: + using operation_type = credit_deal_update_operation; + + void_result do_evaluate( const credit_deal_update_operation& op ); + void_result do_apply( const credit_deal_update_operation& op ) const; + + const credit_deal_object* _deal = nullptr; + }; + } } // graphene::chain diff --git a/libraries/chain/include/graphene/chain/credit_offer_object.hpp b/libraries/chain/include/graphene/chain/credit_offer_object.hpp index a8d427e7ce..79b1f13a07 100644 --- a/libraries/chain/include/graphene/chain/credit_offer_object.hpp +++ b/libraries/chain/include/graphene/chain/credit_offer_object.hpp @@ -113,6 +113,7 @@ class credit_deal_object : public abstract_object; + using credit_deal_update_op = fc::typelist::list< protocol::credit_deal_update_operation >; + fc::time_point_sec now; /// @note using head block time for all operations @@ -92,6 +94,9 @@ struct hardfork_visitor { std::enable_if_t(), bool> visit() { return HARDFORK_CORE_2362_PASSED(now); } template + std::enable_if_t(), bool> + visit() { return HARDFORK_CORE_2595_PASSED(now); } + template std::enable_if_t(), bool> visit() { return HARDFORK_CORE_2604_PASSED(now); } /// @} diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index 1e39c02539..37eb48d967 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -205,6 +205,10 @@ struct proposal_operation_hardfork_visitor FC_ASSERT(!op.new_parameters.current_fees->exists(), "Unable to define fees for credit offer operations prior to the core-2362 hardfork"); } + if (!HARDFORK_CORE_2595_PASSED(block_time)) { + FC_ASSERT(!op.new_parameters.current_fees->exists(), + "Unable to define fees for credit deal update operation prior to the core-2595 hardfork"); + } if (!HARDFORK_CORE_2604_PASSED(block_time)) { FC_ASSERT(!op.new_parameters.current_fees->exists(), "Unable to define fees for liquidity pool update operation prior to the core-2604 hardfork"); @@ -286,13 +290,20 @@ struct proposal_operation_hardfork_visitor void operator()(const graphene::chain::credit_offer_update_operation&) const { FC_ASSERT( HARDFORK_CORE_2362_PASSED(block_time), "Not allowed until the core-2362 hardfork" ); } - void operator()(const graphene::chain::credit_offer_accept_operation&) const { + void operator()(const graphene::chain::credit_offer_accept_operation& op) const { FC_ASSERT( HARDFORK_CORE_2362_PASSED(block_time), "Not allowed until the core-2362 hardfork" ); + if( !HARDFORK_CORE_2595_PASSED(block_time) ) { + FC_ASSERT( !op.extensions.value.auto_repay.valid(), + "auto_repay unavailable until the core-2595 hardfork"); + } } void operator()(const graphene::chain::credit_deal_repay_operation&) const { FC_ASSERT( HARDFORK_CORE_2362_PASSED(block_time), "Not allowed until the core-2362 hardfork" ); } // Note: credit_deal_expired_operation is a virtual operation thus no need to add code here + void operator()(const graphene::chain::credit_deal_update_operation&) const { + FC_ASSERT( HARDFORK_CORE_2595_PASSED(block_time), "Not allowed until the core-2595 hardfork" ); + } // loop and self visit in proposals void operator()(const graphene::chain::proposal_create_operation &v) const { diff --git a/libraries/chain/small_objects.cpp b/libraries/chain/small_objects.cpp index 291eac1230..c914850b96 100644 --- a/libraries/chain/small_objects.cpp +++ b/libraries/chain/small_objects.cpp @@ -234,6 +234,7 @@ FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::credit_deal_object, (graphene:: (collateral_amount) (fee_rate) (latest_repay_time) + (auto_repay) ) FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::credit_deal_summary_object, (graphene::db::object), diff --git a/libraries/protocol/credit_offer.cpp b/libraries/protocol/credit_offer.cpp index b8131b3a5f..8f6ebf2130 100644 --- a/libraries/protocol/credit_offer.cpp +++ b/libraries/protocol/credit_offer.cpp @@ -146,6 +146,12 @@ void credit_offer_accept_operation::validate()const FC_ASSERT( fee.amount >= 0, "Fee should not be negative" ); FC_ASSERT( borrow_amount.amount > 0, "Amount to borrow should be positive" ); FC_ASSERT( collateral.amount > 0, "Collateral amount should be positive" ); + if( extensions.value.auto_repay.valid() ) + { + constexpr auto cdar_count = static_cast( credit_deal_auto_repayment_type::CDAR_TYPE_COUNT ); + FC_ASSERT( *extensions.value.auto_repay < cdar_count, + "auto_repay should be less than ${c}", ("c",cdar_count) ); + } } void credit_deal_repay_operation::validate()const @@ -157,6 +163,15 @@ void credit_deal_repay_operation::validate()const "Asset type of repay amount and credit fee should be the same" ); } +void credit_deal_update_operation::validate()const +{ + FC_ASSERT( fee.amount >= 0, "Fee should not be negative" ); + + constexpr auto cdar_count = static_cast( credit_deal_auto_repayment_type::CDAR_TYPE_COUNT ); + FC_ASSERT( auto_repay < cdar_count, + "auto_repay should be less than ${c}", ("c",cdar_count) ); +} + } } // graphene::protocol GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_create_operation::fee_parameters_type ) @@ -164,6 +179,9 @@ GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_dele GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_update_operation::fee_parameters_type ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_accept_operation::fee_parameters_type ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_repay_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_update_operation::fee_parameters_type ) + +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_accept_operation::ext ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_create_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_delete_operation ) @@ -171,3 +189,4 @@ GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_upda GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_accept_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_repay_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_expired_operation ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_update_operation ) diff --git a/libraries/protocol/include/graphene/protocol/credit_offer.hpp b/libraries/protocol/include/graphene/protocol/credit_offer.hpp index 3e9fe72244..4227ec774f 100644 --- a/libraries/protocol/include/graphene/protocol/credit_offer.hpp +++ b/libraries/protocol/include/graphene/protocol/credit_offer.hpp @@ -115,12 +115,31 @@ namespace graphene { namespace protocol { share_type calculate_fee(const fee_parameters_type& k)const; }; + /// Defines automatic repayment types + enum class credit_deal_auto_repayment_type + { + /// Do not repay automatically + no_auto_repayment = 0, + /// Automatically repay fully when and only when the account balance is sufficient + only_full_repayment = 1, + /// Automatically repay as much as possible using available account balance + allow_partial_repayment = 2, + /// Total number of available automatic repayment types + CDAR_TYPE_COUNT = 3 + }; + /** - * @brief Accept a creadit offer and create a credit deal + * @brief Accept a credit offer, thereby creating a credit deal * @ingroup operations */ struct credit_offer_accept_operation : public base_operation { + struct ext + { + /// After the core-2595 hard fork, the account can specify whether and how to automatically repay + fc::optional auto_repay; + }; + struct fee_parameters_type { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee @@ -131,7 +150,7 @@ namespace graphene { namespace protocol { uint32_t max_fee_rate = 0; ///< The maximum acceptable fee rate uint32_t min_duration_seconds = 0; ///< The minimum acceptable duration - extensions_type extensions; ///< Unused. Reserved for future use. + extension extensions; ///< Extensions account_id_type fee_payer()const { return borrower; } void validate()const override; @@ -189,6 +208,25 @@ namespace graphene { namespace protocol { share_type calculate_fee(const fee_parameters_type&)const { return 0; } }; + /** + * @brief Update a credit deal + * @ingroup operations + */ + struct credit_deal_update_operation : public base_operation + { + struct fee_parameters_type { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + + asset fee; ///< Operation fee + account_id_type account; ///< The account who owns the credit deal + credit_deal_id_type deal_id; ///< ID of the credit deal + uint8_t auto_repay; ///< The specified automatic repayment type + + extensions_type extensions; ///< Unused. Reserved for future use. + + account_id_type fee_payer()const { return account; } + void validate()const override; + }; + } } // graphene::protocol FC_REFLECT( graphene::protocol::credit_offer_create_operation::fee_parameters_type, (fee)(price_per_kbyte) ) @@ -197,6 +235,7 @@ FC_REFLECT( graphene::protocol::credit_offer_update_operation::fee_parameters_ty FC_REFLECT( graphene::protocol::credit_offer_accept_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::protocol::credit_deal_repay_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::protocol::credit_deal_expired_operation::fee_parameters_type, ) // VIRTUAL +FC_REFLECT( graphene::protocol::credit_deal_update_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::protocol::credit_offer_create_operation, (fee) @@ -235,6 +274,10 @@ FC_REFLECT( graphene::protocol::credit_offer_update_operation, (extensions) ) +FC_REFLECT( graphene::protocol::credit_offer_accept_operation::ext, + (auto_repay) + ) + FC_REFLECT( graphene::protocol::credit_offer_accept_operation, (fee) (borrower) @@ -266,12 +309,23 @@ FC_REFLECT( graphene::protocol::credit_deal_expired_operation, (fee_rate) ) +FC_REFLECT( graphene::protocol::credit_deal_update_operation, + (fee) + (account) + (deal_id) + (auto_repay) + (extensions) + ) + +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_accept_operation::ext ) + GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_create_operation::fee_parameters_type ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_delete_operation::fee_parameters_type ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_update_operation::fee_parameters_type ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_accept_operation::fee_parameters_type ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_repay_operation::fee_parameters_type ) // Note: credit_deal_expired_operation is virtual so no external serialization for its fee_parameters_type +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_update_operation::fee_parameters_type ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_delete_operation ) @@ -279,3 +333,4 @@ GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_update GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_accept_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_repay_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_expired_operation ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_update_operation ) diff --git a/libraries/protocol/include/graphene/protocol/operations.hpp b/libraries/protocol/include/graphene/protocol/operations.hpp index 798c400593..4cc722baef 100644 --- a/libraries/protocol/include/graphene/protocol/operations.hpp +++ b/libraries/protocol/include/graphene/protocol/operations.hpp @@ -128,7 +128,8 @@ namespace graphene { namespace protocol { /* 72 */ credit_offer_accept_operation, /* 73 */ credit_deal_repay_operation, /* 74 */ credit_deal_expired_operation, // VIRTUAL - /* 75 */ liquidity_pool_update_operation + /* 75 */ liquidity_pool_update_operation, + /* 76 */ credit_deal_update_operation >; /// @} // operations group From cb4bc4a89a0206455147953b13a9392e600ef36e Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 22 Mar 2023 09:20:16 +0000 Subject: [PATCH 062/127] Add tests for credit deal auto-repayment --- tests/common/database_fixture.cpp | 36 ++- tests/common/database_fixture.hpp | 10 +- tests/tests/credit_offer_tests.cpp | 424 +++++++++++++++++++++++++++-- 3 files changed, 441 insertions(+), 29 deletions(-) diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index bbeb62832a..b05dc8a0fe 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -1921,7 +1921,8 @@ void database_fixture_base::update_credit_offer( account_id_type account, credit credit_offer_accept_operation database_fixture_base::make_credit_offer_accept_op( account_id_type account, credit_offer_id_type offer_id, const asset& borrow_amount, const asset& collateral, - uint32_t max_fee_rate, uint32_t min_duration )const + uint32_t max_fee_rate, uint32_t min_duration, + const optional& auto_repay )const { credit_offer_accept_operation op; op.borrower = account; @@ -1930,16 +1931,18 @@ credit_offer_accept_operation database_fixture_base::make_credit_offer_accept_op op.collateral = collateral; op.max_fee_rate = max_fee_rate; op.min_duration_seconds = min_duration; + op.extensions.value.auto_repay = auto_repay; return op; } const credit_deal_object& database_fixture_base::borrow_from_credit_offer( account_id_type account, credit_offer_id_type offer_id, const asset& borrow_amount, const asset& collateral, - uint32_t max_fee_rate, uint32_t min_duration ) + uint32_t max_fee_rate, uint32_t min_duration, + const optional& auto_repay ) { credit_offer_accept_operation op = make_credit_offer_accept_op( account, offer_id, borrow_amount, collateral, - max_fee_rate, min_duration ); + max_fee_rate, min_duration, auto_repay ); trx.operations.clear(); trx.operations.push_back( op ); @@ -1988,6 +1991,33 @@ extendable_operation_result_dtl database_fixture_base::repay_credit_deal( return op_result.get().value; } +credit_deal_update_operation database_fixture_base::make_credit_deal_update_op( + account_id_type account, credit_deal_id_type deal_id, + uint8_t auto_repay )const +{ + credit_deal_update_operation op; + op.account = account; + op.deal_id = deal_id; + op.auto_repay = auto_repay; + return op; +} + +void database_fixture_base::update_credit_deal( + account_id_type account, credit_deal_id_type deal_id, + uint8_t auto_repay ) +{ + credit_deal_update_operation op = make_credit_deal_update_op( account, deal_id, auto_repay ); + trx.operations.clear(); + trx.operations.push_back( op ); + + for( auto& o : trx.operations ) db.current_fee_schedule().set_fee(o); + trx.validate(); + set_expiration( db, trx ); + PUSH_TX(db, trx, ~0); + trx.operations.clear(); + verify_asset_supplies(db); +} + void database_fixture_base::enable_fees() { diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index 0ee63be250..87be2e8fef 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -222,6 +222,7 @@ struct database_fixture_base { bool hf2467 = false; // Note: used by hf core-2281 too, assuming hf core-2281 and core-2467 occur at the same time bool hf2481 = false; bool bsip77 = false; + bool hf2595 = false; string es_index_prefix; ///< Index prefix for elasticsearch plugin string es_obj_index_prefix; ///< Index prefix for es_objects plugin @@ -526,17 +527,22 @@ struct database_fixture_base { account_id_type account, credit_offer_id_type offer_id, const asset& borrow_amount, const asset& collateral, uint32_t max_fee_rate = GRAPHENE_FEE_RATE_DENOM, - uint32_t min_duration = 0 )const; + uint32_t min_duration = 0, const optional& auto_repay = {} )const; const credit_deal_object& borrow_from_credit_offer( account_id_type account, credit_offer_id_type offer_id, const asset& borrow_amount, const asset& collateral, uint32_t max_fee_rate = GRAPHENE_FEE_RATE_DENOM, - uint32_t min_duration = 0 ); + uint32_t min_duration = 0, const optional& auto_repay = {} ); credit_deal_repay_operation make_credit_deal_repay_op( account_id_type account, credit_deal_id_type deal_id, const asset& repay_amount, const asset& credit_fee )const; extendable_operation_result_dtl repay_credit_deal( account_id_type account, credit_deal_id_type deal_id, const asset& repay_amount, const asset& credit_fee ); + credit_deal_update_operation make_credit_deal_update_op( + account_id_type account, credit_deal_id_type deal_id, + uint8_t auto_repay )const; + void update_credit_deal( account_id_type account, credit_deal_id_type deal_id, + uint8_t auto_repay ); /** * NOTE: This modifies the database directly. You will probably have to call this each time you diff --git a/tests/tests/credit_offer_tests.cpp b/tests/tests/credit_offer_tests.cpp index 1c3e0a11aa..e6c8941b95 100644 --- a/tests/tests/credit_offer_tests.cpp +++ b/tests/tests/credit_offer_tests.cpp @@ -38,8 +38,7 @@ using namespace graphene::chain::test; BOOST_FIXTURE_TEST_SUITE( credit_offer_tests, database_fixture ) BOOST_AUTO_TEST_CASE( credit_offer_hardfork_time_test ) -{ - try { +{ try { // Proceeds to a recent hard fork generate_blocks( HARDFORK_CORE_2262_TIME ); @@ -107,17 +106,95 @@ BOOST_AUTO_TEST_CASE( credit_offer_hardfork_time_test ) set_expiration( db, trx ); BOOST_CHECK_THROW( PUSH_TX(db, trx, ~0), fc::exception ); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } + +BOOST_AUTO_TEST_CASE( credit_deal_auto_repay_hardfork_time_test ) +{ try { + + // Proceeds to a recent hard fork + generate_blocks( HARDFORK_CORE_2362_TIME ); + set_expiration( db, trx ); + + ACTORS((ray)(sam)(ted)); + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( ray, asset(init_amount) ); + fund( sam, asset(init_amount) ); + + const asset_object& core = asset_id_type()(db); + asset_id_type core_id; + + const asset_object& usd = create_user_issued_asset( "MYUSD", ted, white_list ); + asset_id_type usd_id = usd.get_id(); + issue_uia( ray, usd.amount(init_amount) ); + issue_uia( sam, usd.amount(init_amount) ); + + const asset_object& eur = create_user_issued_asset( "MYEUR", sam, white_list ); + asset_id_type eur_id = eur.get_id(); + issue_uia( ray, eur.amount(init_amount) ); + issue_uia( sam, eur.amount(init_amount) ); + + // create a credit offer + auto disable_time1 = db.head_block_time() + fc::minutes(20); // 20 minutes after init + + flat_map collateral_map1; + collateral_map1[usd_id] = price( asset(1), asset(2, usd_id) ); + collateral_map1[eur_id] = price( asset(1), asset(1, eur_id) ); + + const credit_offer_object& coo1 = create_credit_offer( sam_id, core.get_id(), 10000, 30000, 3600, 0, true, + disable_time1, collateral_map1, {} ); + credit_offer_id_type co1_id = coo1.get_id(); + + // Before the hard fork, unable to borrow with the "auto-repay" extension field enabled + // or propose to do so + BOOST_CHECK_THROW( borrow_from_credit_offer( ray_id, co1_id, asset(100), + asset(200, usd_id), GRAPHENE_FEE_RATE_DENOM, 0, 0 ), + fc::exception ); + BOOST_CHECK_THROW( borrow_from_credit_offer( ray_id, co1_id, asset(100), + asset(200, usd_id), GRAPHENE_FEE_RATE_DENOM, 0, 1 ), + fc::exception ); + BOOST_CHECK_THROW( borrow_from_credit_offer( ray_id, co1_id, asset(100), + asset(200, usd_id), GRAPHENE_FEE_RATE_DENOM, 0, 2 ), + fc::exception ); + + credit_offer_accept_operation accop = make_credit_offer_accept_op( ray_id, co1_id, asset(100), + asset(200, usd_id), GRAPHENE_FEE_RATE_DENOM, 0, 0 ); + BOOST_CHECK_THROW( propose( accop ), fc::exception ); + + accop = make_credit_offer_accept_op( ray_id, co1_id, asset(100), + asset(200, usd_id), GRAPHENE_FEE_RATE_DENOM, 0, 1 ); + BOOST_CHECK_THROW( propose( accop ), fc::exception ); + + accop = make_credit_offer_accept_op( ray_id, co1_id, asset(100), + asset(200, usd_id), GRAPHENE_FEE_RATE_DENOM, 0, 2 ); + BOOST_CHECK_THROW( propose( accop ), fc::exception ); + + // borrow + BOOST_TEST_MESSAGE( "Ray borrows" ); + const credit_deal_object& cdo11 = borrow_from_credit_offer( ray_id, co1_id, asset(100), + asset(200, usd_id), GRAPHENE_FEE_RATE_DENOM, 0, {} ); + credit_deal_id_type cd11_id = cdo11.get_id(); + + BOOST_CHECK_EQUAL( cd11_id(db).auto_repay, 0U ); + + // Before the hard fork, unable to update a credit deal + // or update with proposals + BOOST_CHECK_THROW( update_credit_deal( sam_id, cd11_id, 1 ), fc::exception ); + + credit_deal_update_operation updop = make_credit_deal_update_op( sam_id, cd11_id, 1 ); + BOOST_CHECK_THROW( propose( updop ), fc::exception ); + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( credit_offer_crud_and_proposal_test ) { try { // Pass the hard fork time - generate_blocks( HARDFORK_CORE_2362_TIME ); + if( hf2595 ) + generate_blocks( HARDFORK_CORE_2595_TIME ); + else + generate_blocks( HARDFORK_CORE_2362_TIME ); + set_expiration( db, trx ); ACTORS((sam)(ted)(por)); @@ -669,17 +746,16 @@ BOOST_AUTO_TEST_CASE( credit_offer_crud_and_proposal_test ) generate_block(); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( credit_offer_borrow_repay_test ) { try { // Pass the hard fork time - generate_blocks( HARDFORK_CORE_2362_TIME ); + if( hf2595 ) + generate_blocks( HARDFORK_CORE_2595_TIME ); + else + generate_blocks( HARDFORK_CORE_2362_TIME ); set_expiration( db, trx ); ACTORS((ray)(sam)(ted)(por)); @@ -801,7 +877,7 @@ BOOST_AUTO_TEST_CASE( credit_offer_borrow_repay_test ) check_balances(); - // Unable to borrow : the credit offer is disabled + // Unable to borrow : the credit offer does not exist credit_offer_id_type tmp_co_id; BOOST_CHECK_THROW( borrow_from_credit_offer( ray_id, tmp_co_id, asset(100), asset(200, usd_id) ), fc::exception ); @@ -1766,12 +1842,316 @@ BOOST_AUTO_TEST_CASE( credit_offer_borrow_repay_test ) generate_block(); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } +} FC_LOG_AND_RETHROW() } + +BOOST_AUTO_TEST_CASE( credit_offer_crud_and_proposal_test_after_hf2595 ) +{ + hf2595 = true; + INVOKE( credit_offer_crud_and_proposal_test ); } +BOOST_AUTO_TEST_CASE( credit_offer_borrow_repay_test_after_hf2595 ) +{ + hf2595 = true; + INVOKE( credit_offer_borrow_repay_test ); +} + +BOOST_AUTO_TEST_CASE( credit_deal_auto_repay_test ) +{ try { + + // Pass the hard fork time + generate_blocks( HARDFORK_CORE_2595_TIME ); + set_expiration( db, trx ); + + ACTORS((ray)(sam)(ted)(por)(np1)(np2)(np3)(np4)(np5)); + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( por, asset(init_amount) ); + fund( np4, asset(init_amount) ); + fund( np5, asset(init_amount) ); + + asset_id_type core_id; + + const asset_object& usd = create_user_issued_asset( "MYUSD", ted, white_list ); + asset_id_type usd_id = usd.get_id(); + issue_uia( sam, usd.amount(init_amount) ); + + const asset_object& eur = create_user_issued_asset( "MYEUR", sam, white_list ); + asset_id_type eur_id = eur.get_id(); + issue_uia( ray, eur.amount(init_amount) ); + issue_uia( np1, eur.amount(init_amount) ); + issue_uia( np2, eur.amount(init_amount) ); + issue_uia( np3, eur.amount(init_amount) ); + + const asset_object& jpy = create_user_issued_asset( "MYJPY", ted, white_list ); + asset_id_type jpy_id = jpy.get_id(); + issue_uia( sam, jpy.amount(init_amount * 100) ); + + BOOST_CHECK_EQUAL( db.get_balance( sam_id, core_id ).amount.value, 0 ); + BOOST_CHECK_EQUAL( db.get_balance( sam_id, usd_id ).amount.value, init_amount ); + BOOST_CHECK_EQUAL( db.get_balance( sam_id, eur_id ).amount.value, 0 ); + BOOST_CHECK_EQUAL( db.get_balance( sam_id, jpy_id ).amount.value, init_amount * 100 ); + + // create a credit offer + auto disable_time1 = db.head_block_time() + fc::minutes(20); // 20 minutes after init + + flat_map collateral_map1; + collateral_map1[core_id] = price( asset(19, usd_id), asset(23, core_id) ); + collateral_map1[eur_id] = price( asset(19, usd_id), asset(17, eur_id) ); + + const credit_offer_object& coo1 = create_credit_offer( sam_id, usd_id, 10000, 30000, 3600, 0, true, + disable_time1, collateral_map1, {} ); + credit_offer_id_type co1_id = coo1.get_id(); + + // create another credit offer with a very high fee rate + flat_map collateral_map2; + collateral_map2[core_id] = price( asset(init_amount, jpy_id), asset(1, core_id) ); + + const credit_offer_object& coo2 = create_credit_offer( sam_id, jpy_id, init_amount * 100, + 1000 * GRAPHENE_FEE_RATE_DENOM, 3600, 0, true, + disable_time1, collateral_map2, {} ); + credit_offer_id_type co2_id = coo2.get_id(); + + BOOST_CHECK_EQUAL( db.get_balance( sam_id, core_id ).amount.value, 0 ); + BOOST_CHECK_EQUAL( db.get_balance( sam_id, usd_id ).amount.value, init_amount - 10000 ); + BOOST_CHECK_EQUAL( db.get_balance( sam_id, eur_id ).amount.value, 0 ); + BOOST_CHECK_EQUAL( db.get_balance( sam_id, jpy_id ).amount.value, 0 ); + + // Unable to accept offer with an invalid auto-repayment type + BOOST_CHECK_THROW( borrow_from_credit_offer( ray_id, co1_id, asset(190, usd_id), + asset(170, eur_id), GRAPHENE_FEE_RATE_DENOM, 0, 3 ), + fc::exception ); + // Unable to accept offer with a proposal with an invalid auto-repayment type + credit_offer_accept_operation accop = make_credit_offer_accept_op( ray_id, co1_id, asset(190, usd_id), + asset(170, eur_id), GRAPHENE_FEE_RATE_DENOM, 0, 3 ); + BOOST_CHECK_THROW( propose( accop ), fc::exception ); + + // Able to accept offer with a valid auto-repayment type + const credit_deal_object& cdo11 = borrow_from_credit_offer( ray_id, co1_id, asset(190, usd_id), + asset(170, eur_id), GRAPHENE_FEE_RATE_DENOM, 0, 2 ); + credit_deal_id_type cd11_id = cdo11.get_id(); + + BOOST_CHECK_EQUAL( cd11_id(db).auto_repay, 2U ); + + // Unable to update the deal with an invalid auto-repayment type + BOOST_CHECK_THROW( update_credit_deal( ray_id, cd11_id, 3 ), fc::exception ); + // Unable to propose an update with an invalid auto-repayment type + credit_deal_update_operation updop = make_credit_deal_update_op( ray_id, cd11_id, 3 ); + BOOST_CHECK_THROW( propose( updop ), fc::exception ); + + // Unable to update the deal if nothing would change + BOOST_CHECK_THROW( update_credit_deal( ray_id, cd11_id, 2 ), fc::exception ); + // Unable to update a deal if it does not exist + BOOST_CHECK_THROW( update_credit_deal( ray_id, cd11_id + 100, 1 ), fc::exception ); + // Unable to update a deal if the account is not the owner + BOOST_CHECK_THROW( update_credit_deal( sam_id, cd11_id, 1 ), fc::exception ); + + // Able to propose an update with a valid auto-repayment type + updop = make_credit_deal_update_op( sam_id, cd11_id + 100, 2 ); + propose( updop ); + + // Able to update a deal with valid data + update_credit_deal( ray_id, cd11_id, 1 ); + BOOST_CHECK_EQUAL( cd11_id(db).auto_repay, 1U ); + update_credit_deal( ray_id, cd11_id, 0 ); + BOOST_CHECK_EQUAL( cd11_id(db).auto_repay, 0U ); + update_credit_deal( ray_id, cd11_id, 2 ); + BOOST_CHECK_EQUAL( cd11_id(db).auto_repay, 2U ); + + // People borrow more + const credit_deal_object& cdo12 = borrow_from_credit_offer( por_id, co1_id, asset(190, usd_id), + asset(310), GRAPHENE_FEE_RATE_DENOM, 0, 1 ); + credit_deal_id_type cd12_id = cdo12.get_id(); + + BOOST_CHECK_EQUAL( cd12_id(db).auto_repay, 1U ); + + const credit_deal_object& cdo13 = borrow_from_credit_offer( np1_id, co1_id, asset(190, usd_id), + asset(170, eur_id), GRAPHENE_FEE_RATE_DENOM, 0, 0 ); + credit_deal_id_type cd13_id = cdo13.get_id(); + + BOOST_CHECK_EQUAL( cd13_id(db).auto_repay, 0U ); + + const credit_deal_object& cdo14 = borrow_from_credit_offer( np2_id, co1_id, asset(190, usd_id), + asset(170, eur_id), GRAPHENE_FEE_RATE_DENOM, 0, 2 ); + credit_deal_id_type cd14_id = cdo14.get_id(); + + BOOST_CHECK_EQUAL( cd14_id(db).auto_repay, 2U ); + + const credit_deal_object& cdo15 = borrow_from_credit_offer( np3_id, co1_id, asset(190, usd_id), + asset(170, eur_id), GRAPHENE_FEE_RATE_DENOM, 0, 2 ); + credit_deal_id_type cd15_id = cdo15.get_id(); + + BOOST_CHECK_EQUAL( cd15_id(db).auto_repay, 2U ); + + const credit_deal_object& cdo16 = borrow_from_credit_offer( ray_id, co1_id, asset(190, usd_id), + asset(170, eur_id), GRAPHENE_FEE_RATE_DENOM, 0, 1 ); + credit_deal_id_type cd16_id = cdo16.get_id(); + + BOOST_CHECK_EQUAL( cd16_id(db).auto_repay, 1U ); + + const credit_deal_object& cdo17 = borrow_from_credit_offer( ray_id, co1_id, asset(190, usd_id), + asset(170, eur_id), GRAPHENE_FEE_RATE_DENOM, 0, 2 ); + credit_deal_id_type cd17_id = cdo17.get_id(); + + BOOST_CHECK_EQUAL( cd17_id(db).auto_repay, 2U ); + + BOOST_CHECK_EQUAL( db.get_balance( ray_id, usd_id ).amount.value, 190 * 3 ); + BOOST_CHECK_EQUAL( db.get_balance( ray_id, eur_id ).amount.value, init_amount - 170 * 3 ); + BOOST_CHECK_EQUAL( db.get_balance( por_id, usd_id ).amount.value, 190 ); + BOOST_CHECK_EQUAL( db.get_balance( por_id, core_id ).amount.value, init_amount - 310 ); + BOOST_CHECK_EQUAL( db.get_balance( np1_id, usd_id ).amount.value, 190 ); + BOOST_CHECK_EQUAL( db.get_balance( np1_id, eur_id ).amount.value, init_amount - 170 ); + BOOST_CHECK_EQUAL( db.get_balance( np2_id, usd_id ).amount.value, 190 ); + BOOST_CHECK_EQUAL( db.get_balance( np2_id, eur_id ).amount.value, init_amount - 170 ); + BOOST_CHECK_EQUAL( db.get_balance( np3_id, usd_id ).amount.value, 190 ); + BOOST_CHECK_EQUAL( db.get_balance( np3_id, eur_id ).amount.value, init_amount - 170 ); + + BOOST_CHECK_EQUAL( co1_id(db).total_balance.value, 10000 ); + BOOST_CHECK_EQUAL( co1_id(db).current_balance.value, 8670 ); // 10000 - 190 * 7 + + const credit_deal_object& cdo21 = borrow_from_credit_offer( np4_id, co2_id, + asset(init_amount * 99, jpy_id), + asset(99), GRAPHENE_FEE_RATE_DENOM * 1000, 0, 1 ); + credit_deal_id_type cd21_id = cdo21.get_id(); + + BOOST_CHECK_EQUAL( cd21_id(db).auto_repay, 1U ); + + const credit_deal_object& cdo22 = borrow_from_credit_offer( np5_id, co2_id, + asset(init_amount, jpy_id), + asset(1), GRAPHENE_FEE_RATE_DENOM * 1000, 0, 2 ); + credit_deal_id_type cd22_id = cdo22.get_id(); + + BOOST_CHECK_EQUAL( cd22_id(db).auto_repay, 2U ); + + BOOST_CHECK_EQUAL( db.get_balance( np4_id, jpy_id ).amount.value, init_amount * 99 ); + BOOST_CHECK_EQUAL( db.get_balance( np4_id, core_id ).amount.value, init_amount - 99 ); + BOOST_CHECK_EQUAL( db.get_balance( np5_id, jpy_id ).amount.value, init_amount ); + BOOST_CHECK_EQUAL( db.get_balance( np5_id, core_id ).amount.value, init_amount - 1 ); + + BOOST_CHECK_EQUAL( co2_id(db).total_balance.value, init_amount * 100 ); + BOOST_CHECK_EQUAL( co2_id(db).current_balance.value, 0 ); + + // Setup blacklists + { + BOOST_TEST_MESSAGE( "Setting up EUR blacklisting" ); + asset_update_operation uop; + uop.asset_to_update = eur.id; + uop.issuer = sam_id; + uop.new_options = eur.options; + // The EUR blacklist is managed by Sam + uop.new_options.blacklist_authorities.insert(sam_id); + trx.operations.clear(); + trx.operations.push_back(uop); + PUSH_TX( db, trx, ~0 ); + + // Upgrade Sam so that he can manage the blacklist + upgrade_to_lifetime_member( sam_id ); + + // Add np2 to the EUR blacklist + account_whitelist_operation wop; + wop.authorizing_account = sam_id; + wop.account_to_list = np2_id; + wop.new_listing = account_whitelist_operation::black_listed; + trx.operations.clear(); + trx.operations.push_back(wop); + PUSH_TX( db, trx, ~0 ); + } + { + BOOST_TEST_MESSAGE( "Setting up USD blacklisting" ); + asset_update_operation uop; + uop.asset_to_update = usd.id; + uop.issuer = ted_id; + uop.new_options = usd.options; + // The USD blacklist is managed by Ted + uop.new_options.blacklist_authorities.insert(ted_id); + trx.operations.clear(); + trx.operations.push_back(uop); + PUSH_TX( db, trx, ~0 ); + + // Upgrade Ted so that he can manage the blacklist + upgrade_to_lifetime_member( ted_id ); + + // Add np3 to the USD blacklist + account_whitelist_operation wop; + wop.authorizing_account = ted_id; + wop.account_to_list = np3_id; + wop.new_listing = account_whitelist_operation::black_listed; + trx.operations.clear(); + trx.operations.push_back(wop); + PUSH_TX( db, trx, ~0 ); + } + + // Let the credit deals expire + generate_blocks( db.head_block_time() + 3600 ); + generate_block(); + + BOOST_CHECK( !db.find( cd11_id ) ); + BOOST_CHECK( !db.find( cd12_id ) ); + BOOST_CHECK( !db.find( cd13_id ) ); + BOOST_CHECK( !db.find( cd14_id ) ); + BOOST_CHECK( !db.find( cd15_id ) ); + BOOST_CHECK( !db.find( cd16_id ) ); + BOOST_CHECK( !db.find( cd17_id ) ); + BOOST_CHECK( !db.find( cd21_id ) ); + BOOST_CHECK( !db.find( cd22_id ) ); + + // Ray fully repaid cd11, fee = round_up(190 * 3 / 100) = 6 + // Por is unable to repay cd12 due to insufficient balance + // Np1 decided to not pay cd13 + // Np2 failed to repay cd14 due to blacklisting + // Np3 is blacklisted by the collateral asset (EUR), however it doesn't affect the repayment for cd15 + // Balance was 190 + // cd15 debt was 190, collateral was 170 + // To repay: round_down(190 * 100 / 103) = 184 + // Collateral released = round_down(184 * 170 / 190) = 164 + // Updated repay amount = round_up(164 * 190 / 170) = 184 + // Fee = round_up(184 * 3 / 100) = 6 + // Total Pays = 184 + 6 = 190 + // New balance = 190 - 190 = 0 + // cd17 unpaid debt = 190 - 184 = 6, unreleased collateral = 170 - 164 = 6 + // Ray fully repaid cd16, fee = round_up(190 * 3 / 100) = 6 + // Ray partially repaid cd17 + // Balance was 190 - 6 * 2 = 178 + // cd17 debt was 190, collateral was 170 + // To repay: round_down(178 * 100 / 103) = 172 + // Collateral released = round_down(172 * 170 / 190) = 153 + // Updated repay amount = round_up(153 * 190 / 170) = 171 + // Fee = round_up(171 * 3 / 100) = 6 + // Total Pays = 171 + 6 = 177 + // New balance = 178 - 177 = 1 + // cd17 unpaid debt = 190 - 171 = 19, unreleased collateral = 170 - 153 = 17 + // Np4 is unable to repay cd21 due to amount overflow or insufficient balance + // Np5 did not repay cd22 because no collateral will be returned on partial repayment + + BOOST_CHECK_EQUAL( co1_id(db).total_balance.value, 9429 ); // 10000 - 190 * 3 - 6 - 19 + 6 * 4 + BOOST_CHECK_EQUAL( co1_id(db).current_balance.value, 9429 ); + + BOOST_CHECK_EQUAL( co2_id(db).total_balance.value, 0 ); + BOOST_CHECK_EQUAL( co2_id(db).current_balance.value, 0 ); + + BOOST_CHECK_EQUAL( db.get_balance( sam_id, core_id ).amount.value, 310 + 99 + 1 ); // cd13, cd21, cd22 + BOOST_CHECK_EQUAL( db.get_balance( sam_id, usd_id ).amount.value, init_amount - 10000 ); // no change + BOOST_CHECK_EQUAL( db.get_balance( sam_id, eur_id ).amount.value, 170 * 2 + 6 + 17 ); // cd12, cd14, cd15, cd17 + BOOST_CHECK_EQUAL( db.get_balance( sam_id, jpy_id ).amount.value, 0 ); // no change + + BOOST_CHECK_EQUAL( db.get_balance( ray_id, usd_id ).amount.value, 1 ); + BOOST_CHECK_EQUAL( db.get_balance( ray_id, eur_id ).amount.value, init_amount - 17 ); + BOOST_CHECK_EQUAL( db.get_balance( por_id, usd_id ).amount.value, 190 ); + BOOST_CHECK_EQUAL( db.get_balance( por_id, core_id ).amount.value, init_amount - 310 ); + BOOST_CHECK_EQUAL( db.get_balance( np1_id, usd_id ).amount.value, 190 ); + BOOST_CHECK_EQUAL( db.get_balance( np1_id, eur_id ).amount.value, init_amount - 170 ); + BOOST_CHECK_EQUAL( db.get_balance( np2_id, usd_id ).amount.value, 0 ); + BOOST_CHECK_EQUAL( db.get_balance( np2_id, eur_id ).amount.value, init_amount - 6 ); + BOOST_CHECK_EQUAL( db.get_balance( np3_id, usd_id ).amount.value, 190 ); + BOOST_CHECK_EQUAL( db.get_balance( np3_id, eur_id ).amount.value, init_amount - 170 ); + + BOOST_CHECK_EQUAL( db.get_balance( np4_id, jpy_id ).amount.value, init_amount * 99 ); + BOOST_CHECK_EQUAL( db.get_balance( np4_id, core_id ).amount.value, init_amount - 99 ); + BOOST_CHECK_EQUAL( db.get_balance( np5_id, jpy_id ).amount.value, init_amount ); + BOOST_CHECK_EQUAL( db.get_balance( np5_id, core_id ).amount.value, init_amount - 1 ); + +} FC_LOG_AND_RETHROW() } + BOOST_AUTO_TEST_CASE( credit_offer_apis_test ) { try { @@ -1992,10 +2372,6 @@ BOOST_AUTO_TEST_CASE( credit_offer_apis_test ) BOOST_CHECK( deals[2].id == cd21_id ); BOOST_CHECK( deals[3].id == cd51_id ); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_SUITE_END() From 57048165c805d9b74eebdc7186d18a63aa127af7 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 22 Mar 2023 17:46:58 +0000 Subject: [PATCH 063/127] Optimize processing of virutal operations --- libraries/chain/db_block.cpp | 25 +++++++++++++++++++ libraries/chain/db_update.cpp | 13 ++-------- .../chain/include/graphene/chain/database.hpp | 5 ++++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index 92440e4dbe..0551fd79a6 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -783,6 +783,31 @@ operation_result database::apply_operation( transaction_evaluation_state& eval_s return result; } FC_CAPTURE_AND_RETHROW( (op) ) } +operation_result database::try_push_virtual_operation( transaction_evaluation_state& eval_state, const operation& op ) +{ + operation_validate( op ); + + // Note: these variables could be updated during the apply_operation() call + size_t old_applied_ops_size = _applied_ops.size(); + auto old_vop = _current_virtual_op; + + try + { + auto temp_session = _undo_db.start_undo_session(); + auto result = apply_operation( eval_state, op ); // This is a virtual operation + temp_session.merge(); + return result; + } + catch( const fc::exception& e ) + { + wlog( "Failed to push virtual operation ${op} at block ${n}; exception was ${e}", + ("op", op)("n", head_block_num())("e", e.to_detail_string()) ); + _current_virtual_op = old_vop; + _applied_ops.resize( old_applied_ops_size ); + throw; + } +} + const witness_object& database::validate_block_header( uint32_t skip, const signed_block& next_block )const { FC_ASSERT( head_block_id() == next_block.previous, "", ("head_block_id",head_block_id())("next.prev",next_block.previous) ); diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index 4ca0ade75c..5c9192c29b 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -808,27 +808,18 @@ void database::update_credit_offers_and_deals() transaction_evaluation_state eval_state(this); eval_state.skip_fee_schedule_check = true; - size_t old_applied_ops_size = _applied_ops.size(); - auto old_op_in_trx = _current_op_in_trx; - auto old_vop = _current_virtual_op; try { - auto temp_session = _undo_db.start_undo_session(); - apply_operation( eval_state, op ); // This is a virtual operation - temp_session.merge(); + try_push_virtual_operation( eval_state, op ); } catch( const fc::exception& e ) { // We can in fact get here, - // e.g. if asset issuer of debt/collateral asset blacklists/whitelists the account, - // or insufficient account balance + // e.g. if the debt asset issuer blacklisted the account, or account balance is insufficient wlog( "Automatic repayment ${op} for credit deal ${credit_deal} failed at block ${n}; " "account balance was ${balance}; exception was ${e}", ("op", op)("credit_deal", deal_copy) ("n", head_block_num())("balance", balance)("e", e.to_detail_string()) ); - _current_virtual_op = old_vop; - _current_op_in_trx = old_op_in_trx; - _applied_ops.resize( old_applied_ops_size ); } if( !find( op.deal_id ) ) // The credit deal is fully repaid diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 2b79829810..cb5c800385 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -703,6 +703,11 @@ namespace graphene { namespace chain { void _apply_block( const signed_block& next_block ); processed_transaction _apply_transaction( const signed_transaction& trx ); + /// Validate, evaluate and apply a virtual operation using a temporary undo_database session, + /// if fail, rewind any changes made + operation_result try_push_virtual_operation( transaction_evaluation_state& eval_state, + const operation& op ); + ///Steps involved in applying a new block ///@{ From 68efc09e45c0e778ca63694306ba667ae7860c93 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 22 Mar 2023 17:53:31 +0000 Subject: [PATCH 064/127] Fix _current_virtual_op in push_proposal --- libraries/chain/db_block.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index 0551fd79a6..2e2cbf8491 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -335,6 +335,7 @@ processed_transaction database::push_proposal(const proposal_object& proposal) processed_transaction ptrx(proposal.proposed_transaction); eval_state._trx = &ptrx; size_t old_applied_ops_size = _applied_ops.size(); + auto old_vop = _current_virtual_op; try { push_proposal_nesting_guard guard( _push_proposal_nesting_depth, *this ); @@ -360,6 +361,7 @@ processed_transaction database::push_proposal(const proposal_object& proposal) } else { + _current_virtual_op = old_vop; _applied_ops.resize( old_applied_ops_size ); } wlog( "${e}", ("e",e.to_detail_string() ) ); From e8fac66f14307bab3a4a09d00660858ca7f5efab Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 22 Mar 2023 18:21:31 +0000 Subject: [PATCH 065/127] Add tests for credit deal auto-repayment history --- tests/tests/credit_offer_tests.cpp | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tests/tests/credit_offer_tests.cpp b/tests/tests/credit_offer_tests.cpp index e6c8941b95..b171e081d4 100644 --- a/tests/tests/credit_offer_tests.cpp +++ b/tests/tests/credit_offer_tests.cpp @@ -2150,6 +2150,63 @@ BOOST_AUTO_TEST_CASE( credit_deal_auto_repay_test ) BOOST_CHECK_EQUAL( db.get_balance( np5_id, jpy_id ).amount.value, init_amount ); BOOST_CHECK_EQUAL( db.get_balance( np5_id, core_id ).amount.value, init_amount - 1 ); + // Check history API + graphene::app::history_api hist_api(app); + + // np5's last 2 operations are credit_deal_expired_op and credit_offer_accept_op + auto histories = hist_api.get_relative_account_history( "np5", 0, 2, 0 ); + BOOST_REQUIRE_EQUAL( histories.size(), 2U ); + BOOST_CHECK( histories[0].op.is_type() ); + BOOST_CHECK( histories[0].is_virtual ); + BOOST_CHECK( histories[1].op.is_type() ); + BOOST_CHECK( !histories[1].is_virtual ); + + // np4's last 2 operations are credit_deal_expired_op and credit_offer_accept_op + histories = hist_api.get_relative_account_history( "np4", 0, 2, 0 ); + BOOST_REQUIRE_EQUAL( histories.size(), 2U ); + BOOST_CHECK( histories[0].op.is_type() ); + BOOST_CHECK( histories[0].is_virtual ); + BOOST_CHECK( histories[1].op.is_type() ); + BOOST_CHECK( !histories[1].is_virtual ); + + // np2's last 4 operations are credit_deal_expired_op, credit_deal_repay_op, account_whitelist_op, + // and credit_offer_accept_op + histories = hist_api.get_relative_account_history( "np2", 0, 4, 0 ); + BOOST_REQUIRE_EQUAL( histories.size(), 4U ); + BOOST_CHECK( histories[0].op.is_type() ); + BOOST_CHECK( histories[0].is_virtual ); + BOOST_CHECK( histories[1].op.is_type() ); + BOOST_CHECK( histories[1].is_virtual ); + BOOST_CHECK( histories[2].op.is_type() ); + BOOST_CHECK( !histories[2].is_virtual ); + BOOST_CHECK( histories[3].op.is_type() ); + BOOST_CHECK( !histories[3].is_virtual ); + + // ray's last 10 operations are 1 * credit_deal_expired_op, 3 * credit_deal_repay_op, 2 * credit_offer_accept_op, + // 3 * credit_offer_update_op, 1 * credit_accept_op + histories = hist_api.get_relative_account_history( "ray", 0, 10, 0 ); + BOOST_REQUIRE_EQUAL( histories.size(), 10U ); + BOOST_CHECK( histories[0].op.is_type() ); + BOOST_CHECK( histories[0].is_virtual ); + BOOST_CHECK( histories[1].op.is_type() ); + BOOST_CHECK( histories[1].is_virtual ); + BOOST_CHECK( histories[2].op.is_type() ); + BOOST_CHECK( histories[2].is_virtual ); + BOOST_CHECK( histories[3].op.is_type() ); + BOOST_CHECK( histories[3].is_virtual ); + BOOST_CHECK( histories[4].op.is_type() ); + BOOST_CHECK( !histories[4].is_virtual ); + BOOST_CHECK( histories[5].op.is_type() ); + BOOST_CHECK( !histories[5].is_virtual ); + BOOST_CHECK( histories[6].op.is_type() ); + BOOST_CHECK( !histories[6].is_virtual ); + BOOST_CHECK( histories[7].op.is_type() ); + BOOST_CHECK( !histories[7].is_virtual ); + BOOST_CHECK( histories[8].op.is_type() ); + BOOST_CHECK( !histories[8].is_virtual ); + BOOST_CHECK( histories[9].op.is_type() ); + BOOST_CHECK( !histories[9].is_virtual ); + } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( credit_offer_apis_test ) From 8a64036cfbbaed90662b75d16a4dc15ea01233cc Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 22 Mar 2023 20:16:02 +0000 Subject: [PATCH 066/127] Update params in credit deal auto-repayment tests so that some tests are closer to overflow --- tests/tests/credit_offer_tests.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/tests/credit_offer_tests.cpp b/tests/tests/credit_offer_tests.cpp index b171e081d4..8476ecfc47 100644 --- a/tests/tests/credit_offer_tests.cpp +++ b/tests/tests/credit_offer_tests.cpp @@ -1885,12 +1885,12 @@ BOOST_AUTO_TEST_CASE( credit_deal_auto_repay_test ) const asset_object& jpy = create_user_issued_asset( "MYJPY", ted, white_list ); asset_id_type jpy_id = jpy.get_id(); - issue_uia( sam, jpy.amount(init_amount * 100) ); + issue_uia( sam, jpy.amount(init_amount * 1000) ); BOOST_CHECK_EQUAL( db.get_balance( sam_id, core_id ).amount.value, 0 ); BOOST_CHECK_EQUAL( db.get_balance( sam_id, usd_id ).amount.value, init_amount ); BOOST_CHECK_EQUAL( db.get_balance( sam_id, eur_id ).amount.value, 0 ); - BOOST_CHECK_EQUAL( db.get_balance( sam_id, jpy_id ).amount.value, init_amount * 100 ); + BOOST_CHECK_EQUAL( db.get_balance( sam_id, jpy_id ).amount.value, init_amount * 1000 ); // create a credit offer auto disable_time1 = db.head_block_time() + fc::minutes(20); // 20 minutes after init @@ -1907,8 +1907,8 @@ BOOST_AUTO_TEST_CASE( credit_deal_auto_repay_test ) flat_map collateral_map2; collateral_map2[core_id] = price( asset(init_amount, jpy_id), asset(1, core_id) ); - const credit_offer_object& coo2 = create_credit_offer( sam_id, jpy_id, init_amount * 100, - 1000 * GRAPHENE_FEE_RATE_DENOM, 3600, 0, true, + const credit_offer_object& coo2 = create_credit_offer( sam_id, jpy_id, init_amount * 1000, + 4000 * GRAPHENE_FEE_RATE_DENOM, 3600, 0, true, disable_time1, collateral_map2, {} ); credit_offer_id_type co2_id = coo2.get_id(); @@ -2010,25 +2010,25 @@ BOOST_AUTO_TEST_CASE( credit_deal_auto_repay_test ) BOOST_CHECK_EQUAL( co1_id(db).current_balance.value, 8670 ); // 10000 - 190 * 7 const credit_deal_object& cdo21 = borrow_from_credit_offer( np4_id, co2_id, - asset(init_amount * 99, jpy_id), - asset(99), GRAPHENE_FEE_RATE_DENOM * 1000, 0, 1 ); + asset(init_amount * 999, jpy_id), + asset(999), GRAPHENE_FEE_RATE_DENOM * 4000, 0, 1 ); credit_deal_id_type cd21_id = cdo21.get_id(); BOOST_CHECK_EQUAL( cd21_id(db).auto_repay, 1U ); const credit_deal_object& cdo22 = borrow_from_credit_offer( np5_id, co2_id, asset(init_amount, jpy_id), - asset(1), GRAPHENE_FEE_RATE_DENOM * 1000, 0, 2 ); + asset(1), GRAPHENE_FEE_RATE_DENOM * 4000, 0, 2 ); credit_deal_id_type cd22_id = cdo22.get_id(); BOOST_CHECK_EQUAL( cd22_id(db).auto_repay, 2U ); - BOOST_CHECK_EQUAL( db.get_balance( np4_id, jpy_id ).amount.value, init_amount * 99 ); - BOOST_CHECK_EQUAL( db.get_balance( np4_id, core_id ).amount.value, init_amount - 99 ); + BOOST_CHECK_EQUAL( db.get_balance( np4_id, jpy_id ).amount.value, init_amount * 999 ); + BOOST_CHECK_EQUAL( db.get_balance( np4_id, core_id ).amount.value, init_amount - 999 ); BOOST_CHECK_EQUAL( db.get_balance( np5_id, jpy_id ).amount.value, init_amount ); BOOST_CHECK_EQUAL( db.get_balance( np5_id, core_id ).amount.value, init_amount - 1 ); - BOOST_CHECK_EQUAL( co2_id(db).total_balance.value, init_amount * 100 ); + BOOST_CHECK_EQUAL( co2_id(db).total_balance.value, init_amount * 1000 ); BOOST_CHECK_EQUAL( co2_id(db).current_balance.value, 0 ); // Setup blacklists @@ -2129,7 +2129,7 @@ BOOST_AUTO_TEST_CASE( credit_deal_auto_repay_test ) BOOST_CHECK_EQUAL( co2_id(db).total_balance.value, 0 ); BOOST_CHECK_EQUAL( co2_id(db).current_balance.value, 0 ); - BOOST_CHECK_EQUAL( db.get_balance( sam_id, core_id ).amount.value, 310 + 99 + 1 ); // cd13, cd21, cd22 + BOOST_CHECK_EQUAL( db.get_balance( sam_id, core_id ).amount.value, 310 + 999 + 1 ); // cd13, cd21, cd22 BOOST_CHECK_EQUAL( db.get_balance( sam_id, usd_id ).amount.value, init_amount - 10000 ); // no change BOOST_CHECK_EQUAL( db.get_balance( sam_id, eur_id ).amount.value, 170 * 2 + 6 + 17 ); // cd12, cd14, cd15, cd17 BOOST_CHECK_EQUAL( db.get_balance( sam_id, jpy_id ).amount.value, 0 ); // no change @@ -2145,8 +2145,8 @@ BOOST_AUTO_TEST_CASE( credit_deal_auto_repay_test ) BOOST_CHECK_EQUAL( db.get_balance( np3_id, usd_id ).amount.value, 190 ); BOOST_CHECK_EQUAL( db.get_balance( np3_id, eur_id ).amount.value, init_amount - 170 ); - BOOST_CHECK_EQUAL( db.get_balance( np4_id, jpy_id ).amount.value, init_amount * 99 ); - BOOST_CHECK_EQUAL( db.get_balance( np4_id, core_id ).amount.value, init_amount - 99 ); + BOOST_CHECK_EQUAL( db.get_balance( np4_id, jpy_id ).amount.value, init_amount * 999 ); + BOOST_CHECK_EQUAL( db.get_balance( np4_id, core_id ).amount.value, init_amount - 999 ); BOOST_CHECK_EQUAL( db.get_balance( np5_id, jpy_id ).amount.value, init_amount ); BOOST_CHECK_EQUAL( db.get_balance( np5_id, core_id ).amount.value, init_amount - 1 ); From 52d676a8bb5f8fb576e81d13e45540cd6944f95a Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 22 Mar 2023 20:26:19 +0000 Subject: [PATCH 067/127] Try to fix MinGW build with -Wa,-mbig-obj --- libraries/wallet/CMakeLists.txt | 12 +++++++++++- libraries/wallet/wallet_voting.cpp | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libraries/wallet/CMakeLists.txt b/libraries/wallet/CMakeLists.txt index 09a72fc118..cd5bfef7f0 100644 --- a/libraries/wallet/CMakeLists.txt +++ b/libraries/wallet/CMakeLists.txt @@ -50,8 +50,18 @@ target_link_libraries( graphene_wallet PRIVATE graphene_app graphene_chain graph ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) target_include_directories( graphene_db PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) +set( GRAPHENE_WALLET_BIG_FILES + wallet.cpp + wallet_api_impl.cpp + wallet_voting.cpp + ) + if(MSVC) - set_source_files_properties( wallet.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) + set_source_files_properties( ${GRAPHENE_WALLET_BIG_FILES} PROPERTIES COMPILE_FLAGS "/bigobj" ) +else( MSVC ) + if( MINGW ) + set_source_files_properties( ${GRAPHENE_WALLET_BIG_FILES} PROPERTIES COMPILE_FLAGS -Wa,-mbig-obj ) + endif( MINGW ) endif(MSVC) install( TARGETS diff --git a/libraries/wallet/wallet_voting.cpp b/libraries/wallet/wallet_voting.cpp index 3d30af356f..1b791f931a 100644 --- a/libraries/wallet/wallet_voting.cpp +++ b/libraries/wallet/wallet_voting.cpp @@ -24,7 +24,7 @@ #include "wallet_api_impl.hpp" #include -/**** +/* * Methods to handle voting / workers / committee */ From bf5934f3a481f4cc8f73a0407b98fd58f22e9f5d Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 22 Mar 2023 23:18:38 +0000 Subject: [PATCH 068/127] Set VERBOSE=1 when making with MinGW in CI --- .github/workflows/build-and-test.win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-and-test.win.yml b/.github/workflows/build-and-test.win.yml index 2419ff10c3..9bc785a168 100644 --- a/.github/workflows/build-and-test.win.yml +++ b/.github/workflows/build-and-test.win.yml @@ -154,4 +154,4 @@ jobs: run: | export CCACHE_DIR="$GITHUB_WORKSPACE/ccache" mkdir -p "$CCACHE_DIR" - make -j 2 -C _build witness_node cli_wallet + make VERBOSE=1 -j 2 -C _build witness_node cli_wallet From d069614135b3e7a3661a0ebb64ee0dc6b4d4b4f4 Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 23 Mar 2023 20:30:58 +0000 Subject: [PATCH 069/127] Rename fee_parameters_type to fee_params_t to get around MinGW build "string table overflow" issue --- libraries/protocol/account.cpp | 16 ++-- libraries/protocol/assert.cpp | 4 +- libraries/protocol/asset_ops.cpp | 32 +++---- libraries/protocol/committee_member.cpp | 6 +- libraries/protocol/confidential.cpp | 10 +-- libraries/protocol/credit_offer.cpp | 16 ++-- libraries/protocol/custom.cpp | 4 +- libraries/protocol/custom_authority.cpp | 4 +- libraries/protocol/fee_schedule_calc.cpp | 6 +- libraries/protocol/htlc.cpp | 12 +-- .../include/graphene/protocol/account.hpp | 36 ++++---- .../include/graphene/protocol/assert.hpp | 8 +- .../include/graphene/protocol/asset_ops.hpp | 90 +++++++++---------- .../include/graphene/protocol/balance.hpp | 6 +- .../graphene/protocol/committee_member.hpp | 18 ++-- .../graphene/protocol/confidential.hpp | 22 ++--- .../graphene/protocol/credit_offer.hpp | 48 +++++----- .../include/graphene/protocol/custom.hpp | 8 +- .../graphene/protocol/custom_authority.hpp | 18 ++-- .../include/graphene/protocol/fba.hpp | 6 +- .../graphene/protocol/fee_schedule.hpp | 82 ++++++++--------- .../include/graphene/protocol/htlc.hpp | 36 ++++---- .../graphene/protocol/liquidity_pool.hpp | 36 ++++---- .../include/graphene/protocol/market.hpp | 36 ++++---- .../include/graphene/protocol/proposal.hpp | 22 ++--- .../include/graphene/protocol/samet_fund.hpp | 30 +++---- .../include/graphene/protocol/ticket.hpp | 12 +-- .../include/graphene/protocol/transfer.hpp | 16 ++-- .../include/graphene/protocol/vesting.hpp | 12 +-- .../graphene/protocol/withdraw_permission.hpp | 26 +++--- .../include/graphene/protocol/witness.hpp | 12 +-- .../include/graphene/protocol/worker.hpp | 6 +- libraries/protocol/liquidity_pool.cpp | 12 +-- libraries/protocol/market.cpp | 8 +- libraries/protocol/proposal.cpp | 10 +-- libraries/protocol/samet_fund.cpp | 10 +-- libraries/protocol/small_ops.cpp | 4 +- libraries/protocol/ticket.cpp | 4 +- libraries/protocol/transfer.cpp | 8 +- libraries/protocol/withdraw_permission.cpp | 10 +-- libraries/protocol/witness.cpp | 4 +- libraries/protocol/worker.cpp | 2 +- tests/common/database_fixture.cpp | 8 +- tests/tests/bsip85_tests.cpp | 2 +- tests/tests/fee_tests.cpp | 52 +++++------ tests/tests/htlc_tests.cpp | 8 +- tests/tests/operation_tests.cpp | 2 +- tests/tests/pob_tests.cpp | 8 +- 48 files changed, 424 insertions(+), 424 deletions(-) diff --git a/libraries/protocol/account.cpp b/libraries/protocol/account.cpp index 9b77d8eca6..f290066d38 100644 --- a/libraries/protocol/account.cpp +++ b/libraries/protocol/account.cpp @@ -170,7 +170,7 @@ void account_options::validate() const "May not specify fewer witnesses or committee members than the number voted for."); } -share_type account_create_operation::calculate_fee( const fee_parameters_type& k )const +share_type account_create_operation::calculate_fee( const fee_params_t& k )const { auto core_fee_required = k.basic_fee; @@ -215,7 +215,7 @@ void account_create_operation::validate()const } } -share_type account_update_operation::calculate_fee( const fee_parameters_type& k )const +share_type account_update_operation::calculate_fee( const fee_params_t& k )const { auto core_fee_required = k.fee; if( new_options ) @@ -260,7 +260,7 @@ void account_update_operation::validate()const validate_special_authority( *extensions.value.active_special_authority ); } -share_type account_upgrade_operation::calculate_fee(const fee_parameters_type& k) const +share_type account_upgrade_operation::calculate_fee(const fee_params_t& k) const { if( upgrade_to_lifetime_member ) return k.membership_lifetime_fee; @@ -280,11 +280,11 @@ void account_transfer_operation::validate()const } } // graphene::protocol GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_options ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_create_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_whitelist_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_update_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_upgrade_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_transfer_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_create_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_whitelist_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_update_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_upgrade_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_transfer_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_create_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_whitelist_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::account_update_operation ) diff --git a/libraries/protocol/assert.cpp b/libraries/protocol/assert.cpp index 2199b314d8..7acd7661c6 100644 --- a/libraries/protocol/assert.cpp +++ b/libraries/protocol/assert.cpp @@ -61,12 +61,12 @@ void assert_operation::validate()const * The fee for assert operations is proportional to their size, * but cheaper than a data fee because they require no storage */ -share_type assert_operation::calculate_fee(const fee_parameters_type& k)const +share_type assert_operation::calculate_fee(const fee_params_t& k)const { return k.fee * predicates.size(); } } } // namespace graphene::protocol -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::assert_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::assert_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::assert_operation ) diff --git a/libraries/protocol/asset_ops.cpp b/libraries/protocol/asset_ops.cpp index 09a7bab33c..38dd1bd307 100644 --- a/libraries/protocol/asset_ops.cpp +++ b/libraries/protocol/asset_ops.cpp @@ -74,12 +74,12 @@ bool is_valid_symbol( const string& symbol ) return true; } -share_type asset_issue_operation::calculate_fee(const fee_parameters_type& k)const +share_type asset_issue_operation::calculate_fee(const fee_params_t& k)const { return k.fee + calculate_data_fee( fc::raw::pack_size(memo), k.price_per_kbyte ); } -share_type asset_create_operation::calculate_fee( const asset_create_operation::fee_parameters_type& param, +share_type asset_create_operation::calculate_fee( const asset_create_operation::fee_params_t& param, const optional& sub_asset_creation_fee )const { share_type core_fee_required = param.long_symbol; @@ -157,7 +157,7 @@ void asset_update_issuer_operation::validate()const FC_ASSERT( issuer != new_issuer ); } -share_type asset_update_operation::calculate_fee(const asset_update_operation::fee_parameters_type& k)const +share_type asset_update_operation::calculate_fee(const asset_update_operation::fee_params_t& k)const { return k.fee + calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte ); } @@ -363,20 +363,20 @@ GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::additional_asset_ GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_operation::ext ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_publish_feed_operation::ext ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_create_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_global_settle_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_settle_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_fund_fee_pool_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_claim_pool_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_claim_fees_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_create_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_global_settle_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_settle_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_fund_fee_pool_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_claim_pool_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_claim_fees_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_claim_fees_operation::additional_options_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_issuer_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_bitasset_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_feed_producers_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_publish_feed_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_issue_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_reserve_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_issuer_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_bitasset_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_feed_producers_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_publish_feed_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_issue_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_reserve_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_create_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::asset_global_settle_operation ) diff --git a/libraries/protocol/committee_member.cpp b/libraries/protocol/committee_member.cpp index d48372c944..0f9751b856 100644 --- a/libraries/protocol/committee_member.cpp +++ b/libraries/protocol/committee_member.cpp @@ -49,9 +49,9 @@ void committee_member_update_global_parameters_operation::validate() const } } // graphene::protocol -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_create_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_global_parameters_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_create_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_global_parameters_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_create_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_global_parameters_operation ) diff --git a/libraries/protocol/confidential.cpp b/libraries/protocol/confidential.cpp index 43a8b0587e..f05c85f450 100644 --- a/libraries/protocol/confidential.cpp +++ b/libraries/protocol/confidential.cpp @@ -61,7 +61,7 @@ void transfer_to_blind_operation::validate()const } } -share_type transfer_to_blind_operation::calculate_fee( const fee_parameters_type& k )const +share_type transfer_to_blind_operation::calculate_fee( const fee_params_t& k )const { return k.fee + outputs.size() * k.price_per_output; } @@ -134,7 +134,7 @@ void blind_transfer_operation::validate()const FC_ASSERT( fc::ecc::verify_sum( in, out, net_public ), "", ("net_public", net_public) ); } FC_CAPTURE_AND_RETHROW( (*this) ) } -share_type blind_transfer_operation::calculate_fee( const fee_parameters_type& k )const +share_type blind_transfer_operation::calculate_fee( const fee_params_t& k )const { return k.fee + outputs.size() * k.price_per_output; } @@ -156,9 +156,9 @@ stealth_confirmation::stealth_confirmation( const std::string& base58 ) } } // graphene::protocol -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_to_blind_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_from_blind_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::blind_transfer_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_to_blind_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_from_blind_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::blind_transfer_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_to_blind_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_from_blind_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::blind_transfer_operation ) diff --git a/libraries/protocol/credit_offer.cpp b/libraries/protocol/credit_offer.cpp index 8f6ebf2130..27943bff63 100644 --- a/libraries/protocol/credit_offer.cpp +++ b/libraries/protocol/credit_offer.cpp @@ -76,7 +76,7 @@ void credit_offer_create_operation::validate()const validate_acceptable_borrowers( acceptable_borrowers ); } -share_type credit_offer_create_operation::calculate_fee( const fee_parameters_type& schedule )const +share_type credit_offer_create_operation::calculate_fee( const fee_params_t& schedule )const { share_type core_fee_required = schedule.fee; core_fee_required += calculate_data_fee( fc::raw::pack_size(*this), schedule.price_per_kbyte ); @@ -134,7 +134,7 @@ void credit_offer_update_operation::validate()const "Should change something - at least one of the optional data fields should be present" ); } -share_type credit_offer_update_operation::calculate_fee( const fee_parameters_type& schedule )const +share_type credit_offer_update_operation::calculate_fee( const fee_params_t& schedule )const { share_type core_fee_required = schedule.fee; core_fee_required += calculate_data_fee( fc::raw::pack_size(*this), schedule.price_per_kbyte ); @@ -174,12 +174,12 @@ void credit_deal_update_operation::validate()const } } // graphene::protocol -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_create_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_delete_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_update_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_accept_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_repay_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_update_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_create_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_delete_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_update_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_accept_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_repay_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_update_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_accept_operation::ext ) diff --git a/libraries/protocol/custom.cpp b/libraries/protocol/custom.cpp index 22ea61f72b..07165b4bec 100644 --- a/libraries/protocol/custom.cpp +++ b/libraries/protocol/custom.cpp @@ -31,12 +31,12 @@ void custom_operation::validate()const { FC_ASSERT( fee.amount > 0 ); } -share_type custom_operation::calculate_fee(const fee_parameters_type& k)const +share_type custom_operation::calculate_fee(const fee_params_t& k)const { return k.fee + calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte ); } } } -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::custom_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::custom_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::custom_operation ) diff --git a/libraries/protocol/custom_authority.cpp b/libraries/protocol/custom_authority.cpp index f7217d01f2..45eff2ab52 100644 --- a/libraries/protocol/custom_authority.cpp +++ b/libraries/protocol/custom_authority.cpp @@ -29,7 +29,7 @@ namespace graphene { namespace protocol { -share_type custom_authority_create_operation::calculate_fee(const fee_parameters_type& k)const { +share_type custom_authority_create_operation::calculate_fee(const fee_params_t& k)const { share_type core_fee_required = k.basic_fee; // Note: practically the `*` won't cause an integer overflow, because k.price_per_byte is 32 bit // and the results of pack_size() won't be too big @@ -58,7 +58,7 @@ void custom_authority_create_operation::validate()const { get_restriction_predicate(restrictions, operation_type); } -share_type custom_authority_update_operation::calculate_fee(const fee_parameters_type& k)const { +share_type custom_authority_update_operation::calculate_fee(const fee_params_t& k)const { share_type core_fee_required = k.basic_fee; // Note: practically the `*` won't cause an integer overflow, because k.price_per_byte is 32 bit // and the results of pack_size() won't be too big diff --git a/libraries/protocol/fee_schedule_calc.cpp b/libraries/protocol/fee_schedule_calc.cpp index ccb976da4c..e92710f106 100644 --- a/libraries/protocol/fee_schedule_calc.cpp +++ b/libraries/protocol/fee_schedule_calc.cpp @@ -48,7 +48,7 @@ namespace graphene { namespace protocol { auto itr = param.parameters.find(params); if( itr != param.parameters.end() ) params = *itr; - return op.calculate_fee( params.get() ).value; + return op.calculate_fee( params.get() ).value; } } }; @@ -57,7 +57,7 @@ namespace graphene { namespace protocol { uint64_t calc_fee_visitor::operator()(const htlc_create_operation& op)const { //TODO: refactor for performance (see https://github.com/bitshares/bitshares-core/issues/2150) - transfer_operation::fee_parameters_type t; + transfer_operation::fee_params_t t; if (param.exists()) t = param.get(); return op.calculate_fee( param.get(), t.price_per_kbyte).value; @@ -70,7 +70,7 @@ namespace graphene { namespace protocol { optional sub_asset_creation_fee; if( param.exists() && param.exists() ) sub_asset_creation_fee = param.get().fee; - asset_create_operation::fee_parameters_type old_asset_creation_fee_params; + asset_create_operation::fee_params_t old_asset_creation_fee_params; if( param.exists() ) old_asset_creation_fee_params = param.get(); return op.calculate_fee( old_asset_creation_fee_params, sub_asset_creation_fee ).value; diff --git a/libraries/protocol/htlc.cpp b/libraries/protocol/htlc.cpp index 5694ec5a26..13d91f6c72 100644 --- a/libraries/protocol/htlc.cpp +++ b/libraries/protocol/htlc.cpp @@ -34,7 +34,7 @@ namespace graphene { namespace protocol { FC_ASSERT( amount.amount > 0, "HTLC amount should be greater than zero" ); } - share_type htlc_create_operation::calculate_fee( const fee_parameters_type& fee_params, + share_type htlc_create_operation::calculate_fee( const fee_params_t& fee_params, uint32_t fee_per_kb )const { uint64_t days = ( claim_period_seconds + SECONDS_PER_DAY - 1 ) / SECONDS_PER_DAY; @@ -50,7 +50,7 @@ namespace graphene { namespace protocol { FC_ASSERT( fee.amount >= 0, "Fee amount should not be negative" ); } - share_type htlc_redeem_operation::calculate_fee( const fee_parameters_type& fee_params )const + share_type htlc_redeem_operation::calculate_fee( const fee_params_t& fee_params )const { uint64_t kb = ( preimage.size() + 1023 ) / 1024; uint64_t product = kb * fee_params.fee_per_kb; @@ -62,7 +62,7 @@ namespace graphene { namespace protocol { FC_ASSERT( fee.amount >= 0 , "Fee amount should not be negative"); } - share_type htlc_extend_operation::calculate_fee( const fee_parameters_type& fee_params )const + share_type htlc_extend_operation::calculate_fee( const fee_params_t& fee_params )const { uint32_t days = ( seconds_to_add + SECONDS_PER_DAY - 1 ) / SECONDS_PER_DAY; uint64_t per_day_fee = fee_params.fee_per_day * days; @@ -71,10 +71,10 @@ namespace graphene { namespace protocol { } } } -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_create_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_create_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_create_operation::additional_options_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_redeem_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_extend_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_redeem_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_extend_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_create_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_redeem_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_redeemed_operation ) diff --git a/libraries/protocol/include/graphene/protocol/account.hpp b/libraries/protocol/include/graphene/protocol/account.hpp index b7ab4c10c6..800201654f 100644 --- a/libraries/protocol/include/graphene/protocol/account.hpp +++ b/libraries/protocol/include/graphene/protocol/account.hpp @@ -88,7 +88,7 @@ namespace graphene { namespace protocol { optional< buyback_account_options > buyback_options; }; - struct fee_parameters_type + struct fee_params_t { uint64_t basic_fee = 5*GRAPHENE_BLOCKCHAIN_PRECISION; ///< the cost to register the cheapest non-free account uint64_t premium_fee = 2000*GRAPHENE_BLOCKCHAIN_PRECISION; ///< the cost to register the cheapest non-free account @@ -114,7 +114,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return registrar; } void validate()const; - share_type calculate_fee(const fee_parameters_type& )const; + share_type calculate_fee(const fee_params_t& )const; void get_required_active_authorities( flat_set& a )const { @@ -142,7 +142,7 @@ namespace graphene { namespace protocol { optional< special_authority > active_special_authority; }; - struct fee_parameters_type + struct fee_params_t { share_type fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; uint32_t price_per_kbyte = GRAPHENE_BLOCKCHAIN_PRECISION; @@ -163,7 +163,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return account; } void validate()const; - share_type calculate_fee( const fee_parameters_type& k )const; + share_type calculate_fee( const fee_params_t& k )const; bool is_owner_update()const { return owner || extensions.value.owner_special_authority.valid(); } @@ -196,7 +196,7 @@ namespace graphene { namespace protocol { */ struct account_whitelist_operation : public base_operation { - struct fee_parameters_type { share_type fee = 300000; }; + struct fee_params_t { share_type fee = 300000; }; enum account_listing { no_listing = 0x0, ///< No opinion is specified about this account white_listed = 0x1, ///< This account is whitelisted, but not blacklisted @@ -234,7 +234,7 @@ namespace graphene { namespace protocol { */ struct account_upgrade_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t membership_annual_fee = 2000 * GRAPHENE_BLOCKCHAIN_PRECISION; uint64_t membership_lifetime_fee = 10000 * GRAPHENE_BLOCKCHAIN_PRECISION; ///< the cost to upgrade to a lifetime member }; @@ -248,7 +248,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return account_to_upgrade; } void validate()const; - share_type calculate_fee( const fee_parameters_type& k )const; + share_type calculate_fee( const fee_params_t& k )const; }; /** @@ -266,7 +266,7 @@ namespace graphene { namespace protocol { */ struct account_transfer_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; account_id_type account_id; @@ -302,20 +302,20 @@ FC_REFLECT( graphene::protocol::account_upgrade_operation, FC_REFLECT( graphene::protocol::account_whitelist_operation, (fee)(authorizing_account)(account_to_list)(new_listing)(extensions)) -FC_REFLECT( graphene::protocol::account_create_operation::fee_parameters_type, (basic_fee)(premium_fee)(price_per_kbyte) ) -FC_REFLECT( graphene::protocol::account_whitelist_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::account_update_operation::fee_parameters_type, (fee)(price_per_kbyte) ) -FC_REFLECT( graphene::protocol::account_upgrade_operation::fee_parameters_type, (membership_annual_fee)(membership_lifetime_fee) ) -FC_REFLECT( graphene::protocol::account_transfer_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::account_create_operation::fee_params_t, (basic_fee)(premium_fee)(price_per_kbyte) ) +FC_REFLECT( graphene::protocol::account_whitelist_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::account_update_operation::fee_params_t, (fee)(price_per_kbyte) ) +FC_REFLECT( graphene::protocol::account_upgrade_operation::fee_params_t, (membership_annual_fee)(membership_lifetime_fee) ) +FC_REFLECT( graphene::protocol::account_transfer_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::account_transfer_operation, (fee)(account_id)(new_owner)(extensions) ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_options ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_create_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_whitelist_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_update_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_upgrade_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_transfer_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_create_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_whitelist_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_update_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_upgrade_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_transfer_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_whitelist_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::account_update_operation ) diff --git a/libraries/protocol/include/graphene/protocol/assert.hpp b/libraries/protocol/include/graphene/protocol/assert.hpp index fead1a7031..5c0e4105ba 100644 --- a/libraries/protocol/include/graphene/protocol/assert.hpp +++ b/libraries/protocol/include/graphene/protocol/assert.hpp @@ -92,7 +92,7 @@ namespace graphene { namespace protocol { */ struct assert_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; account_id_type fee_paying_account; @@ -102,17 +102,17 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return fee_paying_account; } void validate()const; - share_type calculate_fee(const fee_parameters_type& k)const; + share_type calculate_fee(const fee_params_t& k)const; }; } } // graphene::protocol -FC_REFLECT( graphene::protocol::assert_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::assert_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::account_name_eq_lit_predicate, (account_id)(name) ) FC_REFLECT( graphene::protocol::asset_symbol_eq_lit_predicate, (asset_id)(symbol) ) FC_REFLECT( graphene::protocol::block_id_predicate, (id) ) FC_REFLECT_TYPENAME( graphene::protocol::predicate ) FC_REFLECT( graphene::protocol::assert_operation, (fee)(fee_paying_account)(predicates)(required_auths)(extensions) ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::assert_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::assert_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::assert_operation ) diff --git a/libraries/protocol/include/graphene/protocol/asset_ops.hpp b/libraries/protocol/include/graphene/protocol/asset_ops.hpp index 43eec5564d..afca254425 100644 --- a/libraries/protocol/include/graphene/protocol/asset_ops.hpp +++ b/libraries/protocol/include/graphene/protocol/asset_ops.hpp @@ -191,7 +191,7 @@ namespace graphene { namespace protocol { */ struct asset_create_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t symbol3 = 500000 * GRAPHENE_BLOCKCHAIN_PRECISION; uint64_t symbol4 = 300000 * GRAPHENE_BLOCKCHAIN_PRECISION; uint64_t long_symbol = 5000 * GRAPHENE_BLOCKCHAIN_PRECISION; @@ -221,7 +221,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return issuer; } void validate()const; - share_type calculate_fee( const fee_parameters_type& k, + share_type calculate_fee( const fee_params_t& k, const optional& sub_asset_creation_fee )const; }; @@ -237,7 +237,7 @@ namespace graphene { namespace protocol { */ struct asset_global_settle_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; account_id_type issuer; ///< must equal issuer of @ref asset_to_settle @@ -266,7 +266,7 @@ namespace graphene { namespace protocol { */ struct asset_settle_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { /** this fee should be high to encourage small settlement requests to * be performed on the market rather than via forced settlement. * @@ -292,7 +292,7 @@ namespace graphene { namespace protocol { */ struct asset_settle_cancel_operation : public base_operation { - struct fee_parameters_type { }; + struct fee_params_t { }; asset_settle_cancel_operation() = default; asset_settle_cancel_operation( const force_settlement_id_type& fsid, const account_id_type& aid, @@ -312,7 +312,7 @@ namespace graphene { namespace protocol { */ void validate() const { FC_ASSERT( !"Virtual operation"); } - share_type calculate_fee(const fee_parameters_type& params)const + share_type calculate_fee(const fee_params_t& params)const { return 0; } }; @@ -321,7 +321,7 @@ namespace graphene { namespace protocol { */ struct asset_fund_fee_pool_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< core asset account_id_type from_account; @@ -360,7 +360,7 @@ namespace graphene { namespace protocol { fc::optional skip_core_exchange_rate; }; - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION; uint32_t price_per_kbyte = 10; }; @@ -378,7 +378,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return issuer; } void validate()const; - share_type calculate_fee(const fee_parameters_type& k)const; + share_type calculate_fee(const fee_params_t& k)const; }; /** @@ -397,7 +397,7 @@ namespace graphene { namespace protocol { */ struct asset_update_bitasset_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; account_id_type issuer; @@ -429,7 +429,7 @@ namespace graphene { namespace protocol { */ struct asset_update_feed_producers_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; account_id_type issuer; @@ -467,7 +467,7 @@ namespace graphene { namespace protocol { fc::optional initial_collateral_ratio; // BSIP-77 }; - struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< paid for by publisher account_id_type publisher; @@ -484,7 +484,7 @@ namespace graphene { namespace protocol { */ struct asset_issue_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; uint32_t price_per_kbyte = GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -501,7 +501,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return issuer; } void validate()const; - share_type calculate_fee(const fee_parameters_type& k)const; + share_type calculate_fee(const fee_params_t& k)const; }; /** @@ -512,7 +512,7 @@ namespace graphene { namespace protocol { */ struct asset_reserve_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; account_id_type payer; @@ -528,7 +528,7 @@ namespace graphene { namespace protocol { */ struct asset_claim_fees_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -564,7 +564,7 @@ namespace graphene { namespace protocol { */ struct asset_update_issuer_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -600,7 +600,7 @@ namespace graphene { namespace protocol { */ struct asset_claim_pool_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -617,11 +617,11 @@ namespace graphene { namespace protocol { } } // graphene::protocol FC_REFLECT( graphene::protocol::asset_claim_fees_operation, (fee)(issuer)(amount_to_claim)(extensions) ) -FC_REFLECT( graphene::protocol::asset_claim_fees_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::asset_claim_fees_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::asset_claim_fees_operation::additional_options_type, (claim_from_asset_id) ) FC_REFLECT( graphene::protocol::asset_claim_pool_operation, (fee)(issuer)(asset_id)(amount_to_claim)(extensions) ) -FC_REFLECT( graphene::protocol::asset_claim_pool_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::asset_claim_pool_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::asset_options, (max_supply) @@ -663,20 +663,20 @@ FC_REFLECT( graphene::protocol::additional_asset_options, FC_REFLECT( graphene::protocol::asset_update_operation::ext, (new_precision)(skip_core_exchange_rate) ) FC_REFLECT( graphene::protocol::asset_publish_feed_operation::ext, (initial_collateral_ratio) ) -FC_REFLECT( graphene::protocol::asset_create_operation::fee_parameters_type, +FC_REFLECT( graphene::protocol::asset_create_operation::fee_params_t, (symbol3)(symbol4)(long_symbol)(price_per_kbyte) ) -FC_REFLECT( graphene::protocol::asset_global_settle_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::asset_settle_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::asset_settle_cancel_operation::fee_parameters_type, ) -FC_REFLECT( graphene::protocol::asset_fund_fee_pool_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::asset_update_operation::fee_parameters_type, (fee)(price_per_kbyte) ) -FC_REFLECT( graphene::protocol::asset_update_issuer_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::asset_update_bitasset_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::asset_update_feed_producers_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::asset_publish_feed_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::asset_issue_operation::fee_parameters_type, (fee)(price_per_kbyte) ) -FC_REFLECT( graphene::protocol::asset_reserve_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::asset_global_settle_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::asset_settle_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::asset_settle_cancel_operation::fee_params_t, ) +FC_REFLECT( graphene::protocol::asset_fund_fee_pool_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::asset_update_operation::fee_params_t, (fee)(price_per_kbyte) ) +FC_REFLECT( graphene::protocol::asset_update_issuer_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::asset_update_bitasset_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::asset_update_feed_producers_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::asset_publish_feed_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::asset_issue_operation::fee_params_t, (fee)(price_per_kbyte) ) +FC_REFLECT( graphene::protocol::asset_reserve_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::asset_create_operation, @@ -735,21 +735,21 @@ GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::additional_asset_op GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_operation::ext ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_publish_feed_operation::ext ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_create_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_global_settle_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_settle_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_fund_fee_pool_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_claim_pool_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_claim_fees_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_create_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_global_settle_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_settle_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_fund_fee_pool_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_claim_pool_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_claim_fees_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_claim_fees_operation::additional_options_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_issuer_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_bitasset_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_issuer_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_update_bitasset_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( - graphene::protocol::asset_update_feed_producers_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_publish_feed_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_issue_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_reserve_operation::fee_parameters_type ) + graphene::protocol::asset_update_feed_producers_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_publish_feed_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_issue_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_reserve_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::asset_global_settle_operation ) diff --git a/libraries/protocol/include/graphene/protocol/balance.hpp b/libraries/protocol/include/graphene/protocol/balance.hpp index 825bcce95d..457ccdd889 100644 --- a/libraries/protocol/include/graphene/protocol/balance.hpp +++ b/libraries/protocol/include/graphene/protocol/balance.hpp @@ -39,7 +39,7 @@ namespace graphene { namespace protocol { */ struct balance_claim_operation : public base_operation { - struct fee_parameters_type {}; + struct fee_params_t {}; asset fee; account_id_type deposit_to_account; @@ -48,7 +48,7 @@ namespace graphene { namespace protocol { asset total_claimed; account_id_type fee_payer()const { return deposit_to_account; } - share_type calculate_fee(const fee_parameters_type& )const { return 0; } + share_type calculate_fee(const fee_params_t& )const { return 0; } void validate()const; void get_required_authorities( vector& a )const { @@ -58,7 +58,7 @@ namespace graphene { namespace protocol { } } // graphene::protocol -FC_REFLECT( graphene::protocol::balance_claim_operation::fee_parameters_type, ) +FC_REFLECT( graphene::protocol::balance_claim_operation::fee_params_t, ) FC_REFLECT( graphene::protocol::balance_claim_operation, (fee)(deposit_to_account)(balance_to_claim)(balance_owner_key)(total_claimed) ) diff --git a/libraries/protocol/include/graphene/protocol/committee_member.hpp b/libraries/protocol/include/graphene/protocol/committee_member.hpp index 2bd563800e..501dce9d88 100644 --- a/libraries/protocol/include/graphene/protocol/committee_member.hpp +++ b/libraries/protocol/include/graphene/protocol/committee_member.hpp @@ -37,7 +37,7 @@ namespace graphene { namespace protocol { */ struct committee_member_create_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 5000 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 5000 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; /// The account which owns the committee_member. This account pays the fee for this operation. @@ -57,7 +57,7 @@ namespace graphene { namespace protocol { */ struct committee_member_update_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; /// The committee member to update. @@ -83,7 +83,7 @@ namespace graphene { namespace protocol { */ struct committee_member_update_global_parameters_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; chain_parameters new_parameters; @@ -96,9 +96,9 @@ namespace graphene { namespace protocol { } } // graphene::protocol -FC_REFLECT( graphene::protocol::committee_member_create_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::committee_member_update_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::committee_member_update_global_parameters_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::committee_member_create_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::committee_member_update_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::committee_member_update_global_parameters_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::committee_member_create_operation, (fee)(committee_member_account)(url) ) @@ -106,9 +106,9 @@ FC_REFLECT( graphene::protocol::committee_member_update_operation, (fee)(committee_member)(committee_member_account)(new_url) ) FC_REFLECT( graphene::protocol::committee_member_update_global_parameters_operation, (fee)(new_parameters) ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_create_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_global_parameters_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_create_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_global_parameters_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_global_parameters_operation ) diff --git a/libraries/protocol/include/graphene/protocol/confidential.hpp b/libraries/protocol/include/graphene/protocol/confidential.hpp index 5015b98002..8e9b528fad 100644 --- a/libraries/protocol/include/graphene/protocol/confidential.hpp +++ b/libraries/protocol/include/graphene/protocol/confidential.hpp @@ -149,7 +149,7 @@ struct blind_output */ struct transfer_to_blind_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 5*GRAPHENE_BLOCKCHAIN_PRECISION; ///< the cost to register the cheapest non-free account uint32_t price_per_output = 5*GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -163,7 +163,7 @@ struct transfer_to_blind_operation : public base_operation account_id_type fee_payer()const { return from; } void validate()const; - share_type calculate_fee(const fee_parameters_type& )const; + share_type calculate_fee(const fee_params_t& )const; }; /** @@ -172,7 +172,7 @@ struct transfer_to_blind_operation : public base_operation */ struct transfer_from_blind_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 5*GRAPHENE_BLOCKCHAIN_PRECISION; ///< the cost to register the cheapest non-free account }; @@ -237,7 +237,7 @@ struct transfer_from_blind_operation : public base_operation */ struct blind_transfer_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 5*GRAPHENE_BLOCKCHAIN_PRECISION; ///< the cost to register the cheapest non-free account uint32_t price_per_output = 5*GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -249,7 +249,7 @@ struct blind_transfer_operation : public base_operation /** graphene TEMP account */ account_id_type fee_payer()const; void validate()const; - share_type calculate_fee( const fee_parameters_type& k )const; + share_type calculate_fee( const fee_params_t& k )const; void get_required_authorities( vector& a )const { @@ -280,13 +280,13 @@ FC_REFLECT( graphene::protocol::transfer_from_blind_operation, (fee)(amount)(to)(blinding_factor)(inputs) ) FC_REFLECT( graphene::protocol::blind_transfer_operation, (fee)(inputs)(outputs) ) -FC_REFLECT( graphene::protocol::transfer_to_blind_operation::fee_parameters_type, (fee)(price_per_output) ) -FC_REFLECT( graphene::protocol::transfer_from_blind_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::blind_transfer_operation::fee_parameters_type, (fee)(price_per_output) ) +FC_REFLECT( graphene::protocol::transfer_to_blind_operation::fee_params_t, (fee)(price_per_output) ) +FC_REFLECT( graphene::protocol::transfer_from_blind_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::blind_transfer_operation::fee_params_t, (fee)(price_per_output) ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_to_blind_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_from_blind_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::blind_transfer_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_to_blind_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_from_blind_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::blind_transfer_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_to_blind_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_from_blind_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::blind_transfer_operation ) diff --git a/libraries/protocol/include/graphene/protocol/credit_offer.hpp b/libraries/protocol/include/graphene/protocol/credit_offer.hpp index 4227ec774f..a54178ce77 100644 --- a/libraries/protocol/include/graphene/protocol/credit_offer.hpp +++ b/libraries/protocol/include/graphene/protocol/credit_offer.hpp @@ -35,7 +35,7 @@ namespace graphene { namespace protocol { */ struct credit_offer_create_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; uint32_t price_per_kbyte = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -60,7 +60,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return owner_account; } void validate()const override; - share_type calculate_fee(const fee_parameters_type& k)const; + share_type calculate_fee(const fee_params_t& k)const; }; /** @@ -69,7 +69,7 @@ namespace graphene { namespace protocol { */ struct credit_offer_delete_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 0; }; + struct fee_params_t { uint64_t fee = 0; }; asset fee; ///< Operation fee account_id_type owner_account; ///< The account who owns the credit offer @@ -87,7 +87,7 @@ namespace graphene { namespace protocol { */ struct credit_offer_update_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; uint32_t price_per_kbyte = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -112,7 +112,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return owner_account; } void validate()const override; - share_type calculate_fee(const fee_parameters_type& k)const; + share_type calculate_fee(const fee_params_t& k)const; }; /// Defines automatic repayment types @@ -140,7 +140,7 @@ namespace graphene { namespace protocol { fc::optional auto_repay; }; - struct fee_parameters_type { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee account_id_type borrower; ///< The account who accepts the offer @@ -162,7 +162,7 @@ namespace graphene { namespace protocol { */ struct credit_deal_repay_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee account_id_type account; ///< The account who repays to the credit offer @@ -183,7 +183,7 @@ namespace graphene { namespace protocol { */ struct credit_deal_expired_operation : public base_operation { - struct fee_parameters_type {}; + struct fee_params_t {}; credit_deal_expired_operation() = default; @@ -205,7 +205,7 @@ namespace graphene { namespace protocol { void validate()const override { FC_ASSERT( !"virtual operation" ); } /// This is a virtual operation; there is no fee - share_type calculate_fee(const fee_parameters_type&)const { return 0; } + share_type calculate_fee(const fee_params_t&)const { return 0; } }; /** @@ -214,7 +214,7 @@ namespace graphene { namespace protocol { */ struct credit_deal_update_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee account_id_type account; ///< The account who owns the credit deal @@ -229,13 +229,13 @@ namespace graphene { namespace protocol { } } // graphene::protocol -FC_REFLECT( graphene::protocol::credit_offer_create_operation::fee_parameters_type, (fee)(price_per_kbyte) ) -FC_REFLECT( graphene::protocol::credit_offer_delete_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::credit_offer_update_operation::fee_parameters_type, (fee)(price_per_kbyte) ) -FC_REFLECT( graphene::protocol::credit_offer_accept_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::credit_deal_repay_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::credit_deal_expired_operation::fee_parameters_type, ) // VIRTUAL -FC_REFLECT( graphene::protocol::credit_deal_update_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::credit_offer_create_operation::fee_params_t, (fee)(price_per_kbyte) ) +FC_REFLECT( graphene::protocol::credit_offer_delete_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::credit_offer_update_operation::fee_params_t, (fee)(price_per_kbyte) ) +FC_REFLECT( graphene::protocol::credit_offer_accept_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::credit_deal_repay_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::credit_deal_expired_operation::fee_params_t, ) // VIRTUAL +FC_REFLECT( graphene::protocol::credit_deal_update_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::credit_offer_create_operation, (fee) @@ -319,13 +319,13 @@ FC_REFLECT( graphene::protocol::credit_deal_update_operation, GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_accept_operation::ext ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_create_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_delete_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_update_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_accept_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_repay_operation::fee_parameters_type ) -// Note: credit_deal_expired_operation is virtual so no external serialization for its fee_parameters_type -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_update_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_create_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_delete_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_update_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_accept_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_repay_operation::fee_params_t ) +// Note: credit_deal_expired_operation is virtual so no external serialization for its fee_params_t +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_deal_update_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::credit_offer_delete_operation ) diff --git a/libraries/protocol/include/graphene/protocol/custom.hpp b/libraries/protocol/include/graphene/protocol/custom.hpp index 59ef3757db..49c552069b 100644 --- a/libraries/protocol/include/graphene/protocol/custom.hpp +++ b/libraries/protocol/include/graphene/protocol/custom.hpp @@ -37,7 +37,7 @@ namespace graphene { namespace protocol { */ struct custom_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; uint32_t price_per_kbyte = 10; }; @@ -50,7 +50,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return payer; } void validate()const; - share_type calculate_fee(const fee_parameters_type& k)const; + share_type calculate_fee(const fee_params_t& k)const; void get_required_active_authorities( flat_set& auths )const { auths.insert( required_auths.begin(), required_auths.end() ); } @@ -58,8 +58,8 @@ namespace graphene { namespace protocol { } } // namespace graphene::protocol -FC_REFLECT( graphene::protocol::custom_operation::fee_parameters_type, (fee)(price_per_kbyte) ) +FC_REFLECT( graphene::protocol::custom_operation::fee_params_t, (fee)(price_per_kbyte) ) FC_REFLECT( graphene::protocol::custom_operation, (fee)(payer)(required_auths)(id)(data) ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::custom_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::custom_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::custom_operation ) diff --git a/libraries/protocol/include/graphene/protocol/custom_authority.hpp b/libraries/protocol/include/graphene/protocol/custom_authority.hpp index 7448c84aee..54aa929285 100644 --- a/libraries/protocol/include/graphene/protocol/custom_authority.hpp +++ b/libraries/protocol/include/graphene/protocol/custom_authority.hpp @@ -34,7 +34,7 @@ namespace graphene { namespace protocol { * @ingroup operations */ struct custom_authority_create_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t basic_fee = GRAPHENE_BLOCKCHAIN_PRECISION; uint32_t price_per_byte = GRAPHENE_BLOCKCHAIN_PRECISION / 10; }; @@ -60,7 +60,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return account; } void validate()const; - share_type calculate_fee(const fee_parameters_type& k)const; + share_type calculate_fee(const fee_params_t& k)const; }; /** @@ -68,7 +68,7 @@ namespace graphene { namespace protocol { * @ingroup operations */ struct custom_authority_update_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t basic_fee = GRAPHENE_BLOCKCHAIN_PRECISION; uint32_t price_per_byte = GRAPHENE_BLOCKCHAIN_PRECISION / 10; }; @@ -96,7 +96,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return account; } void validate()const; - share_type calculate_fee(const fee_parameters_type& k)const; + share_type calculate_fee(const fee_params_t& k)const; }; @@ -105,7 +105,7 @@ namespace graphene { namespace protocol { * @ingroup operations */ struct custom_authority_delete_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; /// Operation fee asset fee; @@ -118,14 +118,14 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return account; } void validate()const; - share_type calculate_fee(const fee_parameters_type& k)const { return k.fee; } + share_type calculate_fee(const fee_params_t& k)const { return k.fee; } }; } } // graphene::protocol -FC_REFLECT(graphene::protocol::custom_authority_create_operation::fee_parameters_type, (basic_fee)(price_per_byte)) -FC_REFLECT(graphene::protocol::custom_authority_update_operation::fee_parameters_type, (basic_fee)(price_per_byte)) -FC_REFLECT(graphene::protocol::custom_authority_delete_operation::fee_parameters_type, (fee)) +FC_REFLECT(graphene::protocol::custom_authority_create_operation::fee_params_t, (basic_fee)(price_per_byte)) +FC_REFLECT(graphene::protocol::custom_authority_update_operation::fee_params_t, (basic_fee)(price_per_byte)) +FC_REFLECT(graphene::protocol::custom_authority_delete_operation::fee_params_t, (fee)) FC_REFLECT(graphene::protocol::custom_authority_create_operation, (fee)(account)(enabled)(valid_from)(valid_to)(operation_type)(auth)(restrictions)(extensions)) diff --git a/libraries/protocol/include/graphene/protocol/fba.hpp b/libraries/protocol/include/graphene/protocol/fba.hpp index 0c58c2eb53..3330c8a655 100644 --- a/libraries/protocol/include/graphene/protocol/fba.hpp +++ b/libraries/protocol/include/graphene/protocol/fba.hpp @@ -29,7 +29,7 @@ namespace graphene { namespace protocol { struct fba_distribute_operation : public base_operation { - struct fee_parameters_type {}; + struct fee_params_t {}; asset fee; // always zero account_id_type account_id; @@ -39,12 +39,12 @@ struct fba_distribute_operation : public base_operation account_id_type fee_payer()const { return account_id; } void validate()const { FC_ASSERT( false ); } - share_type calculate_fee(const fee_parameters_type& k)const { return 0; } + share_type calculate_fee(const fee_params_t& k)const { return 0; } }; } } -FC_REFLECT( graphene::protocol::fba_distribute_operation::fee_parameters_type, ) +FC_REFLECT( graphene::protocol::fba_distribute_operation::fee_params_t, ) FC_REFLECT( graphene::protocol::fba_distribute_operation, (fee)(account_id)(fba_id)(amount) ) diff --git a/libraries/protocol/include/graphene/protocol/fee_schedule.hpp b/libraries/protocol/include/graphene/protocol/fee_schedule.hpp index f3adc6840c..45f72b50d3 100644 --- a/libraries/protocol/include/graphene/protocol/fee_schedule.hpp +++ b/libraries/protocol/include/graphene/protocol/fee_schedule.hpp @@ -30,48 +30,48 @@ namespace graphene { namespace protocol { template struct transform_to_fee_parameters> { - using type = fc::static_variant< typename T::fee_parameters_type... >; + using type = fc::static_variant< typename T::fee_params_t... >; }; using fee_parameters = transform_to_fee_parameters::type; template class fee_helper { public: - const typename Operation::fee_parameters_type& cget(const fee_parameters::flat_set_type& parameters)const + const typename Operation::fee_params_t& cget(const fee_parameters::flat_set_type& parameters)const { - auto itr = parameters.find( typename Operation::fee_parameters_type() ); + auto itr = parameters.find( typename Operation::fee_params_t() ); FC_ASSERT( itr != parameters.end() ); - return itr->template get(); + return itr->template get(); } }; template<> class fee_helper { public: - const account_create_operation::fee_parameters_type& cget(const fee_parameters::flat_set_type& parameters)const + const account_create_operation::fee_params_t& cget(const fee_parameters::flat_set_type& parameters)const { - auto itr = parameters.find( account_create_operation::fee_parameters_type() ); + auto itr = parameters.find( account_create_operation::fee_params_t() ); FC_ASSERT( itr != parameters.end() ); - return itr->get(); + return itr->get(); } - typename account_create_operation::fee_parameters_type& get(fee_parameters::flat_set_type& parameters)const + typename account_create_operation::fee_params_t& get(fee_parameters::flat_set_type& parameters)const { - auto itr = parameters.find( account_create_operation::fee_parameters_type() ); + auto itr = parameters.find( account_create_operation::fee_params_t() ); FC_ASSERT( itr != parameters.end() ); - return itr->get(); + return itr->get(); } }; template<> class fee_helper { public: - const bid_collateral_operation::fee_parameters_type& cget(const fee_parameters::flat_set_type& parameters)const + const bid_collateral_operation::fee_params_t& cget(const fee_parameters::flat_set_type& parameters)const { - auto itr = parameters.find( bid_collateral_operation::fee_parameters_type() ); + auto itr = parameters.find( bid_collateral_operation::fee_params_t() ); if ( itr != parameters.end() ) - return itr->get(); + return itr->get(); - static bid_collateral_operation::fee_parameters_type bid_collateral_dummy; + static bid_collateral_operation::fee_params_t bid_collateral_dummy; bid_collateral_dummy.fee = fee_helper().cget(parameters).fee; return bid_collateral_dummy; } @@ -80,13 +80,13 @@ namespace graphene { namespace protocol { template<> class fee_helper { public: - const asset_update_issuer_operation::fee_parameters_type& cget(const fee_parameters::flat_set_type& parameters)const + const asset_update_issuer_operation::fee_params_t& cget(const fee_parameters::flat_set_type& parameters)const { - auto itr = parameters.find( asset_update_issuer_operation::fee_parameters_type() ); + auto itr = parameters.find( asset_update_issuer_operation::fee_params_t() ); if ( itr != parameters.end() ) - return itr->get(); + return itr->get(); - static asset_update_issuer_operation::fee_parameters_type dummy; + static asset_update_issuer_operation::fee_params_t dummy; dummy.fee = fee_helper().cget(parameters).fee; return dummy; } @@ -95,13 +95,13 @@ namespace graphene { namespace protocol { template<> class fee_helper { public: - const asset_claim_pool_operation::fee_parameters_type& cget(const fee_parameters::flat_set_type& parameters)const + const asset_claim_pool_operation::fee_params_t& cget(const fee_parameters::flat_set_type& parameters)const { - auto itr = parameters.find( asset_claim_pool_operation::fee_parameters_type() ); + auto itr = parameters.find( asset_claim_pool_operation::fee_params_t() ); if ( itr != parameters.end() ) - return itr->get(); + return itr->get(); - static asset_claim_pool_operation::fee_parameters_type asset_claim_pool_dummy; + static asset_claim_pool_operation::fee_params_t asset_claim_pool_dummy; asset_claim_pool_dummy.fee = fee_helper().cget(parameters).fee; return asset_claim_pool_dummy; } @@ -110,9 +110,9 @@ namespace graphene { namespace protocol { template<> class fee_helper { public: - const ticket_create_operation::fee_parameters_type& cget(const fee_parameters::flat_set_type& parameters)const + const ticket_create_operation::fee_params_t& cget(const fee_parameters::flat_set_type& parameters)const { - static ticket_create_operation::fee_parameters_type param; + static ticket_create_operation::fee_params_t param; return param; } }; @@ -120,9 +120,9 @@ namespace graphene { namespace protocol { template<> class fee_helper { public: - const ticket_update_operation::fee_parameters_type& cget(const fee_parameters::flat_set_type& parameters)const + const ticket_update_operation::fee_params_t& cget(const fee_parameters::flat_set_type& parameters)const { - static ticket_update_operation::fee_parameters_type param; + static ticket_update_operation::fee_params_t param; return param; } }; @@ -130,13 +130,13 @@ namespace graphene { namespace protocol { template<> class fee_helper { public: - const htlc_create_operation::fee_parameters_type& cget(const fee_parameters::flat_set_type& parameters)const + const htlc_create_operation::fee_params_t& cget(const fee_parameters::flat_set_type& parameters)const { - auto itr = parameters.find( htlc_create_operation::fee_parameters_type() ); + auto itr = parameters.find( htlc_create_operation::fee_params_t() ); if ( itr != parameters.end() ) - return itr->get(); + return itr->get(); - static htlc_create_operation::fee_parameters_type htlc_create_operation_fee_dummy; + static htlc_create_operation::fee_params_t htlc_create_operation_fee_dummy; return htlc_create_operation_fee_dummy; } }; @@ -144,26 +144,26 @@ namespace graphene { namespace protocol { template<> class fee_helper { public: - const htlc_redeem_operation::fee_parameters_type& cget(const fee_parameters::flat_set_type& parameters)const + const htlc_redeem_operation::fee_params_t& cget(const fee_parameters::flat_set_type& parameters)const { - auto itr = parameters.find( htlc_redeem_operation::fee_parameters_type() ); + auto itr = parameters.find( htlc_redeem_operation::fee_params_t() ); if ( itr != parameters.end() ) - return itr->get(); + return itr->get(); - static htlc_redeem_operation::fee_parameters_type htlc_redeem_operation_fee_dummy; + static htlc_redeem_operation::fee_params_t htlc_redeem_operation_fee_dummy; return htlc_redeem_operation_fee_dummy; } }; template<> class fee_helper { public: - const htlc_extend_operation::fee_parameters_type& cget(const fee_parameters::flat_set_type& parameters)const + const htlc_extend_operation::fee_params_t& cget(const fee_parameters::flat_set_type& parameters)const { - auto itr = parameters.find( htlc_extend_operation::fee_parameters_type() ); + auto itr = parameters.find( htlc_extend_operation::fee_params_t() ); if ( itr != parameters.end() ) - return itr->get(); + return itr->get(); - static htlc_extend_operation::fee_parameters_type htlc_extend_operation_fee_dummy; + static htlc_extend_operation::fee_params_t htlc_extend_operation_fee_dummy; return htlc_extend_operation_fee_dummy; } }; @@ -198,19 +198,19 @@ namespace graphene { namespace protocol { void validate()const {} template - const typename Operation::fee_parameters_type& get()const + const typename Operation::fee_params_t& get()const { return fee_helper().cget(parameters); } template - typename Operation::fee_parameters_type& get() + typename Operation::fee_params_t& get() { return fee_helper().get(parameters); } template bool exists()const { - auto itr = parameters.find(typename Operation::fee_parameters_type()); + auto itr = parameters.find(typename Operation::fee_params_t()); return itr != parameters.end(); } diff --git a/libraries/protocol/include/graphene/protocol/htlc.hpp b/libraries/protocol/include/graphene/protocol/htlc.hpp index 606b2f383f..99da62d854 100644 --- a/libraries/protocol/include/graphene/protocol/htlc.hpp +++ b/libraries/protocol/include/graphene/protocol/htlc.hpp @@ -44,7 +44,7 @@ namespace graphene { namespace protocol { struct htlc_create_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; uint64_t fee_per_day = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -84,12 +84,12 @@ namespace graphene { namespace protocol { /**** * @brief calculates the fee to be paid for this operation */ - share_type calculate_fee(const fee_parameters_type& fee_params, uint32_t fee_per_kb)const; + share_type calculate_fee(const fee_params_t& fee_params, uint32_t fee_per_kb)const; }; struct htlc_redeem_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; uint64_t fee_per_kb = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -118,7 +118,7 @@ namespace graphene { namespace protocol { /**** * @brief calculates the fee to be paid for this operation */ - share_type calculate_fee(const fee_parameters_type& fee_params)const; + share_type calculate_fee(const fee_params_t& fee_params)const; }; /** @@ -126,7 +126,7 @@ namespace graphene { namespace protocol { */ struct htlc_redeemed_operation : public base_operation { - struct fee_parameters_type {}; + struct fee_params_t {}; htlc_redeemed_operation() {} htlc_redeemed_operation( htlc_id_type htlc_id, account_id_type from, account_id_type to, @@ -138,7 +138,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return to; } void validate()const { FC_ASSERT( !"virtual operation" ); } - share_type calculate_fee(const fee_parameters_type& k)const { return 0; } + share_type calculate_fee(const fee_params_t& k)const { return 0; } htlc_id_type htlc_id; account_id_type from, to, redeemer; @@ -152,7 +152,7 @@ namespace graphene { namespace protocol { struct htlc_extend_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; uint64_t fee_per_day = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -181,12 +181,12 @@ namespace graphene { namespace protocol { /**** * @brief calculates the fee to be paid for this operation */ - share_type calculate_fee(const fee_parameters_type& fee_params)const; + share_type calculate_fee(const fee_params_t& fee_params)const; }; struct htlc_refund_operation : public base_operation { - struct fee_parameters_type {}; + struct fee_params_t {}; htlc_refund_operation(){} htlc_refund_operation( const htlc_id_type& htlc_id, @@ -199,7 +199,7 @@ namespace graphene { namespace protocol { void validate()const { FC_ASSERT( !"virtual operation" ); } /// This is a virtual operation; there is no fee - share_type calculate_fee(const fee_parameters_type& k)const { return 0; } + share_type calculate_fee(const fee_params_t& k)const { return 0; } asset fee; @@ -216,12 +216,12 @@ namespace graphene { namespace protocol { FC_REFLECT_TYPENAME( graphene::protocol::htlc_hash ) -FC_REFLECT( graphene::protocol::htlc_create_operation::fee_parameters_type, (fee) (fee_per_day) ) +FC_REFLECT( graphene::protocol::htlc_create_operation::fee_params_t, (fee) (fee_per_day) ) FC_REFLECT( graphene::protocol::htlc_create_operation::additional_options_type, (memo)) -FC_REFLECT( graphene::protocol::htlc_redeem_operation::fee_parameters_type, (fee) (fee_per_kb) ) -FC_REFLECT( graphene::protocol::htlc_redeemed_operation::fee_parameters_type, ) // VIRTUAL -FC_REFLECT( graphene::protocol::htlc_extend_operation::fee_parameters_type, (fee) (fee_per_day)) -FC_REFLECT( graphene::protocol::htlc_refund_operation::fee_parameters_type, ) // VIRTUAL +FC_REFLECT( graphene::protocol::htlc_redeem_operation::fee_params_t, (fee) (fee_per_kb) ) +FC_REFLECT( graphene::protocol::htlc_redeemed_operation::fee_params_t, ) // VIRTUAL +FC_REFLECT( graphene::protocol::htlc_extend_operation::fee_params_t, (fee) (fee_per_day)) +FC_REFLECT( graphene::protocol::htlc_refund_operation::fee_params_t, ) // VIRTUAL FC_REFLECT( graphene::protocol::htlc_create_operation, (fee)(from)(to)(amount)(preimage_hash)(preimage_size)(claim_period_seconds)(extensions)) @@ -232,10 +232,10 @@ FC_REFLECT( graphene::protocol::htlc_extend_operation, (fee)(htlc_id)(update_iss FC_REFLECT( graphene::protocol::htlc_refund_operation, (fee)(htlc_id)(to)(original_htlc_recipient)(htlc_amount)(htlc_preimage_hash)(htlc_preimage_size)) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_create_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_create_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_create_operation::additional_options_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_redeem_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_extend_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_redeem_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_extend_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_redeem_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::htlc_redeemed_operation ) diff --git a/libraries/protocol/include/graphene/protocol/liquidity_pool.hpp b/libraries/protocol/include/graphene/protocol/liquidity_pool.hpp index 0bbed4a288..ad11c33b55 100644 --- a/libraries/protocol/include/graphene/protocol/liquidity_pool.hpp +++ b/libraries/protocol/include/graphene/protocol/liquidity_pool.hpp @@ -33,7 +33,7 @@ namespace graphene { namespace protocol { */ struct liquidity_pool_create_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 50 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 50 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee account_id_type account; ///< The account who creates the liquidity pool @@ -55,7 +55,7 @@ namespace graphene { namespace protocol { */ struct liquidity_pool_delete_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 0; }; + struct fee_params_t { uint64_t fee = 0; }; asset fee; ///< Operation fee account_id_type account; ///< The account who owns the liquidity pool @@ -73,7 +73,7 @@ namespace graphene { namespace protocol { */ struct liquidity_pool_update_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee account_id_type account; ///< The account who owns the liquidity pool @@ -93,7 +93,7 @@ namespace graphene { namespace protocol { */ struct liquidity_pool_deposit_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION / 10; }; + struct fee_params_t { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION / 10; }; asset fee; ///< Operation fee account_id_type account; ///< The account who deposits to the liquidity pool @@ -113,7 +113,7 @@ namespace graphene { namespace protocol { */ struct liquidity_pool_withdraw_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 5 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 5 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee account_id_type account; ///< The account who withdraws from the liquidity pool @@ -137,7 +137,7 @@ namespace graphene { namespace protocol { */ struct liquidity_pool_exchange_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee account_id_type account; ///< The account who exchanges with the liquidity pool @@ -153,12 +153,12 @@ namespace graphene { namespace protocol { } } // graphene::protocol -FC_REFLECT( graphene::protocol::liquidity_pool_create_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::liquidity_pool_delete_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::liquidity_pool_update_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::liquidity_pool_deposit_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::liquidity_pool_withdraw_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::liquidity_pool_exchange_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::liquidity_pool_create_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::liquidity_pool_delete_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::liquidity_pool_update_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::liquidity_pool_deposit_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::liquidity_pool_withdraw_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::liquidity_pool_exchange_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::liquidity_pool_create_operation, (fee)(account)(asset_a)(asset_b)(share_asset) @@ -174,12 +174,12 @@ FC_REFLECT( graphene::protocol::liquidity_pool_withdraw_operation, FC_REFLECT( graphene::protocol::liquidity_pool_exchange_operation, (fee)(account)(pool)(amount_to_sell)(min_to_receive)(extensions) ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_create_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_delete_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_update_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_deposit_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_withdraw_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_exchange_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_create_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_delete_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_update_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_deposit_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_withdraw_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_exchange_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_delete_operation ) diff --git a/libraries/protocol/include/graphene/protocol/market.hpp b/libraries/protocol/include/graphene/protocol/market.hpp index b5dfd413aa..02e83cfdc2 100644 --- a/libraries/protocol/include/graphene/protocol/market.hpp +++ b/libraries/protocol/include/graphene/protocol/market.hpp @@ -47,7 +47,7 @@ namespace graphene { namespace protocol { */ struct limit_order_create_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 5 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 5 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; account_id_type seller; @@ -82,7 +82,7 @@ namespace graphene { namespace protocol { */ struct limit_order_cancel_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 0; }; + struct fee_params_t { uint64_t fee = 0; }; asset fee; limit_order_id_type order; @@ -120,7 +120,7 @@ namespace graphene { namespace protocol { }; /** this is slightly more expensive than limit orders, this pricing impacts prediction markets */ - struct fee_parameters_type { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; account_id_type funding_account; ///< pays fee, collateral, and cover @@ -143,7 +143,7 @@ namespace graphene { namespace protocol { */ struct fill_order_operation : public base_operation { - struct fee_parameters_type {}; + struct fee_params_t {}; fill_order_operation(){} fill_order_operation( object_id_type o, account_id_type a, asset p, asset r, asset f, price fp, bool m ) @@ -167,7 +167,7 @@ namespace graphene { namespace protocol { void validate()const { FC_ASSERT( !"virtual operation" ); } /// This is a virtual operation; there is no fee - share_type calculate_fee(const fee_parameters_type& k)const { return 0; } + share_type calculate_fee(const fee_params_t& k)const { return 0; } }; /** @@ -179,7 +179,7 @@ namespace graphene { namespace protocol { struct bid_collateral_operation : public base_operation { /** should be equivalent to call_order_update fee */ - struct fee_parameters_type { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; account_id_type bidder; ///< pays fee and additional collateral @@ -199,7 +199,7 @@ namespace graphene { namespace protocol { */ struct execute_bid_operation : public base_operation { - struct fee_parameters_type {}; + struct fee_params_t {}; execute_bid_operation(){} execute_bid_operation( account_id_type a, asset d, asset c ) @@ -214,16 +214,16 @@ namespace graphene { namespace protocol { void validate()const { FC_ASSERT( !"virtual operation" ); } /// This is a virtual operation; there is no fee - share_type calculate_fee(const fee_parameters_type& k)const { return 0; } + share_type calculate_fee(const fee_params_t& k)const { return 0; } }; } } // graphene::protocol -FC_REFLECT( graphene::protocol::limit_order_create_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::limit_order_cancel_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::call_order_update_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::bid_collateral_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::fill_order_operation::fee_parameters_type, ) // VIRTUAL -FC_REFLECT( graphene::protocol::execute_bid_operation::fee_parameters_type, ) // VIRTUAL +FC_REFLECT( graphene::protocol::limit_order_create_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::limit_order_cancel_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::call_order_update_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::bid_collateral_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::fill_order_operation::fee_params_t, ) // VIRTUAL +FC_REFLECT( graphene::protocol::execute_bid_operation::fee_params_t, ) // VIRTUAL FC_REFLECT( graphene::protocol::call_order_update_operation::options_type, (target_collateral_ratio) ) @@ -241,10 +241,10 @@ FC_REFLECT( graphene::protocol::execute_bid_operation, (fee)(bidder)(debt)(collateral) ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::call_order_update_operation::options_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_create_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_cancel_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::call_order_update_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::bid_collateral_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_create_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_cancel_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::call_order_update_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::bid_collateral_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_cancel_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::call_order_update_operation ) diff --git a/libraries/protocol/include/graphene/protocol/proposal.hpp b/libraries/protocol/include/graphene/protocol/proposal.hpp index a1a7b27e1f..6d3ce173a2 100644 --- a/libraries/protocol/include/graphene/protocol/proposal.hpp +++ b/libraries/protocol/include/graphene/protocol/proposal.hpp @@ -69,7 +69,7 @@ namespace graphene { namespace protocol { */ struct proposal_create_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; uint32_t price_per_kbyte = 10; }; @@ -95,7 +95,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return fee_paying_account; } void validate()const; - share_type calculate_fee(const fee_parameters_type& k)const; + share_type calculate_fee(const fee_params_t& k)const; }; /** @@ -118,7 +118,7 @@ namespace graphene { namespace protocol { */ struct proposal_update_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; uint32_t price_per_kbyte = 10; }; @@ -136,7 +136,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return fee_paying_account; } void validate()const; - share_type calculate_fee(const fee_parameters_type& k)const; + share_type calculate_fee(const fee_params_t& k)const; void get_required_authorities( vector& )const; void get_required_active_authorities( flat_set& )const; void get_required_owner_authorities( flat_set& )const; @@ -155,7 +155,7 @@ namespace graphene { namespace protocol { */ struct proposal_delete_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; account_id_type fee_paying_account; bool using_owner_authority = false; @@ -170,9 +170,9 @@ namespace graphene { namespace protocol { }} // graphene::protocol -FC_REFLECT( graphene::protocol::proposal_create_operation::fee_parameters_type, (fee)(price_per_kbyte) ) -FC_REFLECT( graphene::protocol::proposal_update_operation::fee_parameters_type, (fee)(price_per_kbyte) ) -FC_REFLECT( graphene::protocol::proposal_delete_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::proposal_create_operation::fee_params_t, (fee)(price_per_kbyte) ) +FC_REFLECT( graphene::protocol::proposal_update_operation::fee_params_t, (fee)(price_per_kbyte) ) +FC_REFLECT( graphene::protocol::proposal_delete_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::proposal_create_operation, (fee)(fee_paying_account)(expiration_time) (proposed_ops)(review_period_seconds)(extensions) ) @@ -181,9 +181,9 @@ FC_REFLECT( graphene::protocol::proposal_update_operation, (fee)(fee_paying_acco (key_approvals_to_add)(key_approvals_to_remove)(extensions) ) FC_REFLECT( graphene::protocol::proposal_delete_operation, (fee)(fee_paying_account)(using_owner_authority)(proposal)(extensions) ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::proposal_create_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::proposal_update_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::proposal_delete_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::proposal_create_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::proposal_update_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::proposal_delete_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::proposal_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::proposal_update_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::proposal_delete_operation ) diff --git a/libraries/protocol/include/graphene/protocol/samet_fund.hpp b/libraries/protocol/include/graphene/protocol/samet_fund.hpp index e7c4bcfe1f..95dfac6c3f 100644 --- a/libraries/protocol/include/graphene/protocol/samet_fund.hpp +++ b/libraries/protocol/include/graphene/protocol/samet_fund.hpp @@ -35,7 +35,7 @@ namespace graphene { namespace protocol { */ struct samet_fund_create_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee account_id_type owner_account; ///< Owner of the fund @@ -55,7 +55,7 @@ namespace graphene { namespace protocol { */ struct samet_fund_delete_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 0; }; + struct fee_params_t { uint64_t fee = 0; }; asset fee; ///< Operation fee account_id_type owner_account; ///< The account who owns the SameT Fund object @@ -73,7 +73,7 @@ namespace graphene { namespace protocol { */ struct samet_fund_update_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee account_id_type owner_account; ///< Owner of the fund @@ -93,7 +93,7 @@ namespace graphene { namespace protocol { */ struct samet_fund_borrow_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee account_id_type borrower; ///< The account who borrows from the fund @@ -112,7 +112,7 @@ namespace graphene { namespace protocol { */ struct samet_fund_repay_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 1 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee account_id_type account; ///< The account who repays to the SameT Fund @@ -128,11 +128,11 @@ namespace graphene { namespace protocol { } } // graphene::protocol -FC_REFLECT( graphene::protocol::samet_fund_create_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::samet_fund_delete_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::samet_fund_update_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::samet_fund_borrow_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::samet_fund_repay_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::samet_fund_create_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::samet_fund_delete_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::samet_fund_update_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::samet_fund_borrow_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::samet_fund_repay_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::samet_fund_create_operation, (fee)(owner_account)(asset_type)(balance)(fee_rate)(extensions) ) @@ -145,11 +145,11 @@ FC_REFLECT( graphene::protocol::samet_fund_borrow_operation, FC_REFLECT( graphene::protocol::samet_fund_repay_operation, (fee)(account)(fund_id)(repay_amount)(fund_fee)(extensions) ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::samet_fund_create_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::samet_fund_delete_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::samet_fund_update_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::samet_fund_borrow_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::samet_fund_repay_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::samet_fund_create_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::samet_fund_delete_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::samet_fund_update_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::samet_fund_borrow_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::samet_fund_repay_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::samet_fund_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::samet_fund_delete_operation ) diff --git a/libraries/protocol/include/graphene/protocol/ticket.hpp b/libraries/protocol/include/graphene/protocol/ticket.hpp index a4b761febc..774689014c 100644 --- a/libraries/protocol/include/graphene/protocol/ticket.hpp +++ b/libraries/protocol/include/graphene/protocol/ticket.hpp @@ -46,7 +46,7 @@ namespace graphene { namespace protocol { */ struct ticket_create_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 50 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 50 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee account_id_type account; ///< The account who creates the ticket @@ -65,7 +65,7 @@ namespace graphene { namespace protocol { */ struct ticket_update_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 50 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 50 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; ///< Operation fee ticket_id_type ticket; ///< The ticket to update @@ -84,16 +84,16 @@ namespace graphene { namespace protocol { FC_REFLECT_ENUM( graphene::protocol::ticket_type, (liquid)(lock_180_days)(lock_360_days)(lock_720_days)(lock_forever)(TICKET_TYPE_COUNT) ) -FC_REFLECT( graphene::protocol::ticket_create_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::ticket_update_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::ticket_create_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::ticket_update_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::ticket_create_operation, (fee)(account)(target_type)(amount)(extensions) ) FC_REFLECT( graphene::protocol::ticket_update_operation, (fee)(ticket)(account)(target_type)(amount_for_new_target)(extensions) ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::ticket_create_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::ticket_update_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::ticket_create_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::ticket_update_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::ticket_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::ticket_update_operation ) diff --git a/libraries/protocol/include/graphene/protocol/transfer.hpp b/libraries/protocol/include/graphene/protocol/transfer.hpp index 2125ed4eb6..7117cd0610 100644 --- a/libraries/protocol/include/graphene/protocol/transfer.hpp +++ b/libraries/protocol/include/graphene/protocol/transfer.hpp @@ -44,7 +44,7 @@ namespace graphene { namespace protocol { */ struct transfer_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; uint32_t price_per_kbyte = 10 * GRAPHENE_BLOCKCHAIN_PRECISION; /// only required for large memos. }; @@ -63,7 +63,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return from; } void validate()const; - share_type calculate_fee(const fee_parameters_type& k)const; + share_type calculate_fee(const fee_params_t& k)const; }; /** @@ -76,7 +76,7 @@ namespace graphene { namespace protocol { */ struct override_transfer_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; uint32_t price_per_kbyte = 10; /// only required for large memos. }; @@ -96,18 +96,18 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return issuer; } void validate()const; - share_type calculate_fee(const fee_parameters_type& k)const; + share_type calculate_fee(const fee_params_t& k)const; }; }} // graphene::protocol -FC_REFLECT( graphene::protocol::transfer_operation::fee_parameters_type, (fee)(price_per_kbyte) ) -FC_REFLECT( graphene::protocol::override_transfer_operation::fee_parameters_type, (fee)(price_per_kbyte) ) +FC_REFLECT( graphene::protocol::transfer_operation::fee_params_t, (fee)(price_per_kbyte) ) +FC_REFLECT( graphene::protocol::override_transfer_operation::fee_params_t, (fee)(price_per_kbyte) ) FC_REFLECT( graphene::protocol::override_transfer_operation, (fee)(issuer)(from)(to)(amount)(memo)(extensions) ) FC_REFLECT( graphene::protocol::transfer_operation, (fee)(from)(to)(amount)(memo)(extensions) ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::override_transfer_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::override_transfer_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::transfer_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::override_transfer_operation ) diff --git a/libraries/protocol/include/graphene/protocol/vesting.hpp b/libraries/protocol/include/graphene/protocol/vesting.hpp index a733506d1d..f632569d29 100644 --- a/libraries/protocol/include/graphene/protocol/vesting.hpp +++ b/libraries/protocol/include/graphene/protocol/vesting.hpp @@ -73,7 +73,7 @@ namespace graphene { namespace protocol { */ struct vesting_balance_create_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; account_id_type creator; ///< Who provides funds initially @@ -100,7 +100,7 @@ namespace graphene { namespace protocol { */ struct vesting_balance_withdraw_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 20*GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 20*GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; vesting_balance_id_type vesting_balance; @@ -118,8 +118,8 @@ namespace graphene { namespace protocol { } } // graphene::protocol -FC_REFLECT( graphene::protocol::vesting_balance_create_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::vesting_balance_withdraw_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::vesting_balance_create_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::vesting_balance_withdraw_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::vesting_balance_create_operation, (fee)(creator)(owner)(amount)(policy) ) FC_REFLECT( graphene::protocol::vesting_balance_withdraw_operation, (fee)(vesting_balance)(owner)(amount) ) @@ -129,7 +129,7 @@ FC_REFLECT(graphene::protocol::cdd_vesting_policy_initializer, (start_claim)(ves FC_REFLECT_EMPTY( graphene::protocol::instant_vesting_policy_initializer ) FC_REFLECT_TYPENAME( graphene::protocol::vesting_policy_initializer ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::vesting_balance_create_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::vesting_balance_withdraw_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::vesting_balance_create_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::vesting_balance_withdraw_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::vesting_balance_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::vesting_balance_withdraw_operation ) diff --git a/libraries/protocol/include/graphene/protocol/withdraw_permission.hpp b/libraries/protocol/include/graphene/protocol/withdraw_permission.hpp index a5d01b79ef..9398681c29 100644 --- a/libraries/protocol/include/graphene/protocol/withdraw_permission.hpp +++ b/libraries/protocol/include/graphene/protocol/withdraw_permission.hpp @@ -49,7 +49,7 @@ namespace graphene { namespace protocol { */ struct withdraw_permission_create_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; /// The account authorizing withdrawals from its balances @@ -82,7 +82,7 @@ namespace graphene { namespace protocol { */ struct withdraw_permission_update_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; /// This account pays the fee. Must match permission_to_update->withdraw_from_account @@ -119,7 +119,7 @@ namespace graphene { namespace protocol { */ struct withdraw_permission_claim_operation : public base_operation { - struct fee_parameters_type { + struct fee_params_t { uint64_t fee = 20*GRAPHENE_BLOCKCHAIN_PRECISION; uint32_t price_per_kbyte = 10; }; @@ -139,7 +139,7 @@ namespace graphene { namespace protocol { account_id_type fee_payer()const { return withdraw_to_account; } void validate()const; - share_type calculate_fee(const fee_parameters_type& k)const; + share_type calculate_fee(const fee_params_t& k)const; }; /** @@ -152,7 +152,7 @@ namespace graphene { namespace protocol { */ struct withdraw_permission_delete_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 0; }; + struct fee_params_t { uint64_t fee = 0; }; asset fee; /// Must match withdrawal_permission->withdraw_from_account. This account pays the fee. @@ -168,10 +168,10 @@ namespace graphene { namespace protocol { } } // graphene::protocol -FC_REFLECT( graphene::protocol::withdraw_permission_create_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::withdraw_permission_update_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::protocol::withdraw_permission_claim_operation::fee_parameters_type, (fee)(price_per_kbyte) ) -FC_REFLECT( graphene::protocol::withdraw_permission_delete_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::withdraw_permission_create_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::withdraw_permission_update_operation::fee_params_t, (fee) ) +FC_REFLECT( graphene::protocol::withdraw_permission_claim_operation::fee_params_t, (fee)(price_per_kbyte) ) +FC_REFLECT( graphene::protocol::withdraw_permission_delete_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::withdraw_permission_create_operation, (fee)(withdraw_from_account)(authorized_account) @@ -186,10 +186,10 @@ FC_REFLECT( graphene::protocol::withdraw_permission_delete_operation, (fee)(withdraw_from_account)(authorized_account) (withdrawal_permission) ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_create_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_update_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_claim_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_delete_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_create_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_update_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_claim_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_delete_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_update_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_claim_operation ) diff --git a/libraries/protocol/include/graphene/protocol/witness.hpp b/libraries/protocol/include/graphene/protocol/witness.hpp index 89efe54f70..5c176d29fd 100644 --- a/libraries/protocol/include/graphene/protocol/witness.hpp +++ b/libraries/protocol/include/graphene/protocol/witness.hpp @@ -36,7 +36,7 @@ namespace graphene { namespace protocol { */ struct witness_create_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 5000 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 5000 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; /// The account which owns the witness. This account pays the fee for this operation. @@ -54,7 +54,7 @@ namespace graphene { namespace protocol { */ struct witness_update_operation : public base_operation { - struct fee_parameters_type + struct fee_params_t { share_type fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -77,13 +77,13 @@ namespace graphene { namespace protocol { } } // graphene::protocol -FC_REFLECT( graphene::protocol::witness_create_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::witness_create_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::witness_create_operation, (fee)(witness_account)(url)(block_signing_key) ) -FC_REFLECT( graphene::protocol::witness_update_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::witness_update_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::witness_update_operation, (fee)(witness)(witness_account)(new_url)(new_signing_key) ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::witness_create_operation::fee_parameters_type ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::witness_update_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::witness_create_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::witness_update_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::witness_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::witness_update_operation ) diff --git a/libraries/protocol/include/graphene/protocol/worker.hpp b/libraries/protocol/include/graphene/protocol/worker.hpp index 1dfc472d77..ee1244a8f4 100644 --- a/libraries/protocol/include/graphene/protocol/worker.hpp +++ b/libraries/protocol/include/graphene/protocol/worker.hpp @@ -78,7 +78,7 @@ namespace graphene { namespace protocol { */ struct worker_create_operation : public base_operation { - struct fee_parameters_type { uint64_t fee = 5000*GRAPHENE_BLOCKCHAIN_PRECISION; }; + struct fee_params_t { uint64_t fee = 5000*GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; account_id_type owner; @@ -102,9 +102,9 @@ FC_REFLECT( graphene::protocol::burn_worker_initializer, ) FC_REFLECT( graphene::protocol::refund_worker_initializer, ) FC_REFLECT_TYPENAME( graphene::protocol::worker_initializer ) -FC_REFLECT( graphene::protocol::worker_create_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::protocol::worker_create_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::worker_create_operation, (fee)(owner)(work_begin_date)(work_end_date)(daily_pay)(name)(url)(initializer) ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::worker_create_operation::fee_parameters_type ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::worker_create_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::worker_create_operation ) diff --git a/libraries/protocol/liquidity_pool.cpp b/libraries/protocol/liquidity_pool.cpp index a2e290227b..36574ece5c 100644 --- a/libraries/protocol/liquidity_pool.cpp +++ b/libraries/protocol/liquidity_pool.cpp @@ -77,12 +77,12 @@ void liquidity_pool_exchange_operation::validate()const } } // graphene::protocol -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_create_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_delete_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_update_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_deposit_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_withdraw_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_exchange_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_create_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_delete_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_update_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_deposit_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_withdraw_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_exchange_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_create_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::liquidity_pool_delete_operation ) diff --git a/libraries/protocol/market.cpp b/libraries/protocol/market.cpp index 8e8fc721e2..a6b4eb54e3 100644 --- a/libraries/protocol/market.cpp +++ b/libraries/protocol/market.cpp @@ -59,10 +59,10 @@ void bid_collateral_operation::validate()const } } // graphene::protocol GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::call_order_update_operation::options_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_create_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_cancel_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::call_order_update_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::bid_collateral_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_create_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_cancel_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::call_order_update_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::bid_collateral_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_create_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_cancel_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::call_order_update_operation ) diff --git a/libraries/protocol/proposal.cpp b/libraries/protocol/proposal.cpp index 22d66d44f1..55432cdd5c 100644 --- a/libraries/protocol/proposal.cpp +++ b/libraries/protocol/proposal.cpp @@ -43,7 +43,7 @@ void proposal_create_operation::validate() const for( const auto& op : proposed_ops ) operation_validate( op.op ); } -share_type proposal_create_operation::calculate_fee(const fee_parameters_type& k) const +share_type proposal_create_operation::calculate_fee(const fee_params_t& k) const { return k.fee + calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte ); } @@ -76,7 +76,7 @@ void proposal_delete_operation::validate() const FC_ASSERT( fee.amount >= 0 ); } -share_type proposal_update_operation::calculate_fee(const fee_parameters_type& k) const +share_type proposal_update_operation::calculate_fee(const fee_params_t& k) const { return k.fee + calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte ); } @@ -108,9 +108,9 @@ void proposal_update_operation::get_required_owner_authorities( flat_set= 0 ); } -share_type withdraw_permission_claim_operation::calculate_fee(const fee_parameters_type& k)const +share_type withdraw_permission_claim_operation::calculate_fee(const fee_params_t& k)const { share_type core_fee_required = k.fee; if( memo ) @@ -69,10 +69,10 @@ void withdraw_permission_delete_operation::validate() const } } // graphene::protocol -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_create_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_update_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_claim_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_delete_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_create_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_update_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_claim_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_delete_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_create_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_update_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::withdraw_permission_claim_operation ) diff --git a/libraries/protocol/witness.cpp b/libraries/protocol/witness.cpp index 5085156fe7..c8e2c9ee91 100644 --- a/libraries/protocol/witness.cpp +++ b/libraries/protocol/witness.cpp @@ -42,7 +42,7 @@ void witness_update_operation::validate() const } } // graphene::protocol -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::witness_create_operation::fee_parameters_type ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::witness_update_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::witness_create_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::witness_update_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::witness_create_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::witness_update_operation ) diff --git a/libraries/protocol/worker.cpp b/libraries/protocol/worker.cpp index 9b6a5d475c..195639b7e1 100644 --- a/libraries/protocol/worker.cpp +++ b/libraries/protocol/worker.cpp @@ -39,5 +39,5 @@ void worker_create_operation::validate() const } } -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::worker_create_operation::fee_parameters_type ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::worker_create_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::worker_create_operation ) diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index b05dc8a0fe..5678d04daa 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -2225,24 +2225,24 @@ flat_map< uint64_t, graphene::chain::fee_parameters > database_fixture_base::get { flat_map ret_val; - htlc_create_operation::fee_parameters_type create_param; + htlc_create_operation::fee_params_t create_param; create_param.fee_per_day = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; create_param.fee = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; ret_val[((operation)htlc_create_operation()).which()] = create_param; - htlc_redeem_operation::fee_parameters_type redeem_param; + htlc_redeem_operation::fee_params_t redeem_param; redeem_param.fee = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; redeem_param.fee_per_kb = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; ret_val[((operation)htlc_redeem_operation()).which()] = redeem_param; - htlc_extend_operation::fee_parameters_type extend_param; + htlc_extend_operation::fee_params_t extend_param; extend_param.fee = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; extend_param.fee_per_day = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; ret_val[((operation)htlc_extend_operation()).which()] = extend_param; // set the transfer kb fee to something other than default, to verify we're looking // at the correct fee - transfer_operation::fee_parameters_type transfer_param; + transfer_operation::fee_params_t transfer_param; transfer_param.price_per_kbyte *= 2; ret_val[ ((operation)transfer_operation()).which() ] = transfer_param; diff --git a/tests/tests/bsip85_tests.cpp b/tests/tests/bsip85_tests.cpp index fc76ec70fd..57bad258cb 100644 --- a/tests/tests/bsip85_tests.cpp +++ b/tests/tests/bsip85_tests.cpp @@ -156,7 +156,7 @@ BOOST_AUTO_TEST_CASE( bsip85_maker_fee_discount_test ) int64_t core_maker_refund = usd_maker_refund == 0 ? 0 : core_create_fee * 1123 / 10000; fee_parameters::flat_set_type new_fees; - limit_order_create_operation::fee_parameters_type create_fee_params; + limit_order_create_operation::fee_params_t create_fee_params; create_fee_params.fee = order_create_fee; new_fees.insert( create_fee_params ); diff --git a/tests/tests/fee_tests.cpp b/tests/tests/fee_tests.cpp index f8d13323c7..ce0aa3e7d1 100644 --- a/tests/tests/fee_tests.cpp +++ b/tests/tests/fee_tests.cpp @@ -758,8 +758,8 @@ BOOST_AUTO_TEST_CASE( fee_refund_test ) enable_fees(); /* change_fees({ - limit_order_create_operation::fee_parameters_type { order_create_fee }, - limit_order_cancel_operation::fee_parameters_type { order_cancel_fee } + limit_order_create_operation::fee_params_t { order_create_fee }, + limit_order_cancel_operation::fee_params_t { order_cancel_fee } }); */ // C++ -- The above commented out statement doesn't work, I don't know why @@ -767,12 +767,12 @@ BOOST_AUTO_TEST_CASE( fee_refund_test ) { fee_parameters::flat_set_type new_fees; { - limit_order_create_operation::fee_parameters_type create_fee_params; + limit_order_create_operation::fee_params_t create_fee_params; create_fee_params.fee = order_create_fee; new_fees.insert( create_fee_params ); } { - limit_order_cancel_operation::fee_parameters_type cancel_fee_params; + limit_order_cancel_operation::fee_params_t cancel_fee_params; cancel_fee_params.fee = order_cancel_fee; new_fees.insert( cancel_fee_params ); } @@ -884,17 +884,17 @@ BOOST_AUTO_TEST_CASE( non_core_fee_refund_test ) fee_parameters::flat_set_type new_fees; { - limit_order_create_operation::fee_parameters_type create_fee_params; + limit_order_create_operation::fee_params_t create_fee_params; create_fee_params.fee = order_create_fee; new_fees.insert( create_fee_params ); } { - limit_order_cancel_operation::fee_parameters_type cancel_fee_params; + limit_order_cancel_operation::fee_params_t cancel_fee_params; cancel_fee_params.fee = order_cancel_fee; new_fees.insert( cancel_fee_params ); } { - transfer_operation::fee_parameters_type transfer_fee_params; + transfer_operation::fee_params_t transfer_fee_params; transfer_fee_params.fee = 0; transfer_fee_params.price_per_kbyte = 0; new_fees.insert( transfer_fee_params ); @@ -1271,17 +1271,17 @@ BOOST_AUTO_TEST_CASE( hf445_fee_refund_cross_test ) fee_parameters::flat_set_type new_fees; { - limit_order_create_operation::fee_parameters_type create_fee_params; + limit_order_create_operation::fee_params_t create_fee_params; create_fee_params.fee = order_create_fee; new_fees.insert( create_fee_params ); } { - limit_order_cancel_operation::fee_parameters_type cancel_fee_params; + limit_order_cancel_operation::fee_params_t cancel_fee_params; cancel_fee_params.fee = order_cancel_fee; new_fees.insert( cancel_fee_params ); } { - transfer_operation::fee_parameters_type transfer_fee_params; + transfer_operation::fee_params_t transfer_fee_params; transfer_fee_params.fee = 0; transfer_fee_params.price_per_kbyte = 0; new_fees.insert( transfer_fee_params ); @@ -1782,23 +1782,23 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) fee_parameters::flat_set_type new_fees1; fee_parameters::flat_set_type new_fees2; { - limit_order_create_operation::fee_parameters_type create_fee_params; + limit_order_create_operation::fee_params_t create_fee_params; create_fee_params.fee = order_create_fee; new_fees1.insert( create_fee_params ); new_fees2.insert( create_fee_params ); } { - limit_order_cancel_operation::fee_parameters_type cancel_fee_params; + limit_order_cancel_operation::fee_params_t cancel_fee_params; cancel_fee_params.fee = order_cancel_fee1; new_fees1.insert( cancel_fee_params ); } { - limit_order_cancel_operation::fee_parameters_type cancel_fee_params; + limit_order_cancel_operation::fee_params_t cancel_fee_params; cancel_fee_params.fee = order_cancel_fee2; new_fees2.insert( cancel_fee_params ); } { - transfer_operation::fee_parameters_type transfer_fee_params; + transfer_operation::fee_params_t transfer_fee_params; transfer_fee_params.fee = 0; transfer_fee_params.price_per_kbyte = 0; new_fees1.insert( transfer_fee_params ); @@ -2338,17 +2338,17 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_cross_test ) fee_parameters::flat_set_type new_fees; { - limit_order_create_operation::fee_parameters_type create_fee_params; + limit_order_create_operation::fee_params_t create_fee_params; create_fee_params.fee = order_create_fee; new_fees.insert( create_fee_params ); } { - limit_order_cancel_operation::fee_parameters_type cancel_fee_params; + limit_order_cancel_operation::fee_params_t cancel_fee_params; cancel_fee_params.fee = order_cancel_fee; new_fees.insert( cancel_fee_params ); } { - transfer_operation::fee_parameters_type transfer_fee_params; + transfer_operation::fee_params_t transfer_fee_params; transfer_fee_params.fee = 0; transfer_fee_params.price_per_kbyte = 0; new_fees.insert( transfer_fee_params ); @@ -3640,13 +3640,13 @@ BOOST_AUTO_TEST_CASE( stealth_fba_test ) BOOST_AUTO_TEST_CASE( defaults_test ) { try { fee_schedule schedule; - const limit_order_create_operation::fee_parameters_type default_order_fee {}; + const limit_order_create_operation::fee_params_t default_order_fee {}; // no fees set yet -> default asset fee = schedule.calculate_fee( limit_order_create_operation() ); BOOST_CHECK_EQUAL( (int64_t)default_order_fee.fee, fee.amount.value ); - limit_order_create_operation::fee_parameters_type new_order_fee; new_order_fee.fee = 123; + limit_order_create_operation::fee_params_t new_order_fee; new_order_fee.fee = 123; // set fee + check schedule.parameters.insert( new_order_fee ); fee = schedule.calculate_fee( limit_order_create_operation() ); @@ -3654,8 +3654,8 @@ BOOST_AUTO_TEST_CASE( defaults_test ) // bid_collateral fee defaults to call_order_update fee // call_order_update fee is unset -> default - const call_order_update_operation::fee_parameters_type default_short_fee {}; - call_order_update_operation::fee_parameters_type new_short_fee; new_short_fee.fee = 123; + const call_order_update_operation::fee_params_t default_short_fee {}; + call_order_update_operation::fee_params_t new_short_fee; new_short_fee.fee = 123; fee = schedule.calculate_fee( bid_collateral_operation() ); BOOST_CHECK_EQUAL( (int64_t)default_short_fee.fee, fee.amount.value ); @@ -3665,7 +3665,7 @@ BOOST_AUTO_TEST_CASE( defaults_test ) BOOST_CHECK_EQUAL( (int64_t)new_short_fee.fee, fee.amount.value ); // set bid_collateral fee + check - bid_collateral_operation::fee_parameters_type new_bid_fee; new_bid_fee.fee = 124; + bid_collateral_operation::fee_params_t new_bid_fee; new_bid_fee.fee = 124; schedule.parameters.insert( new_bid_fee ); fee = schedule.calculate_fee( bid_collateral_operation() ); BOOST_CHECK_EQUAL( (int64_t)new_bid_fee.fee, fee.amount.value ); @@ -3681,7 +3681,7 @@ BOOST_AUTO_TEST_CASE( sub_asset_creation_fee_test ) { try { fee_schedule schedule; - asset_create_operation::fee_parameters_type default_ac_fee; + asset_create_operation::fee_params_t default_ac_fee; asset_create_operation op; op.symbol = "TEST.SUB"; @@ -3697,7 +3697,7 @@ BOOST_AUTO_TEST_CASE( sub_asset_creation_fee_test ) BOOST_CHECK_EQUAL( fee.amount.value, expected_fee ); // set fee + check - asset_create_operation::fee_parameters_type ac_fee; + asset_create_operation::fee_params_t ac_fee; ac_fee.long_symbol = 100100; ac_fee.symbol4 = 2000200; ac_fee.symbol3 = 30000300; @@ -3713,7 +3713,7 @@ BOOST_AUTO_TEST_CASE( sub_asset_creation_fee_test ) // set fee for account_transfer_operation, no change on asset creation fee BOOST_TEST_MESSAGE("Testing our fee schedule without sub-asset creation fee enabled"); - account_transfer_operation::fee_parameters_type at_fee; + account_transfer_operation::fee_params_t at_fee; at_fee.fee = 5500; schedule.parameters.insert( at_fee ); @@ -3723,7 +3723,7 @@ BOOST_AUTO_TEST_CASE( sub_asset_creation_fee_test ) // enable sub-asset creation fee BOOST_TEST_MESSAGE("Testing our fee schedule with sub-asset creation fee enabled"); - schedule.parameters.insert( ticket_create_operation::fee_parameters_type() ); + schedule.parameters.insert( ticket_create_operation::fee_params_t() ); expected_fee = at_fee.fee + expected_data_fee; diff --git a/tests/tests/htlc_tests.cpp b/tests/tests/htlc_tests.cpp index 833b7feebf..8a844657d5 100644 --- a/tests/tests/htlc_tests.cpp +++ b/tests/tests/htlc_tests.cpp @@ -803,7 +803,7 @@ BOOST_AUTO_TEST_CASE( htlc_hardfork_test ) .parameters.extensions.value.updatable_htlc_options->max_preimage_size, 2048u); const graphene::chain::fee_schedule& current_fee_schedule = *(db.get_global_properties().parameters.current_fees); - const htlc_create_operation::fee_parameters_type& htlc_fee + const htlc_create_operation::fee_params_t& htlc_fee = current_fee_schedule.get(); BOOST_CHECK_EQUAL(htlc_fee.fee, 2 * GRAPHENE_BLOCKCHAIN_PRECISION); @@ -904,7 +904,7 @@ BOOST_AUTO_TEST_CASE( fee_calculations ) { // create { - htlc_create_operation::fee_parameters_type create_fee; + htlc_create_operation::fee_params_t create_fee; create_fee.fee = 2; create_fee.fee_per_day = 2; htlc_create_operation create; @@ -920,7 +920,7 @@ BOOST_AUTO_TEST_CASE( fee_calculations ) } // redeem { - htlc_redeem_operation::fee_parameters_type redeem_fee; + htlc_redeem_operation::fee_params_t redeem_fee; redeem_fee.fee_per_kb = 2; redeem_fee.fee = 2; htlc_redeem_operation redeem; @@ -938,7 +938,7 @@ BOOST_AUTO_TEST_CASE( fee_calculations ) } // extend { - htlc_extend_operation::fee_parameters_type extend_fee; + htlc_extend_operation::fee_params_t extend_fee; extend_fee.fee = 2; extend_fee.fee_per_day = 2; htlc_extend_operation extend; diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 88f3d9e012..54014695ce 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -2927,7 +2927,7 @@ BOOST_AUTO_TEST_CASE( witness_pay_test ) PUSH_TX( db, trx ); auto pay_fee_time = db.head_block_time().sec_since_epoch(); trx.clear(); - BOOST_CHECK( get_balance(*nathan, *core) == 20000*prec - account_upgrade_operation::fee_parameters_type().membership_lifetime_fee );; + BOOST_CHECK( get_balance(*nathan, *core) == 20000*prec - account_upgrade_operation::fee_params_t().membership_lifetime_fee );; generate_block(); nathan = &get_account("nathan"); diff --git a/tests/tests/pob_tests.cpp b/tests/tests/pob_tests.cpp index 872e6cf342..4de88be106 100644 --- a/tests/tests/pob_tests.cpp +++ b/tests/tests/pob_tests.cpp @@ -121,11 +121,11 @@ BOOST_AUTO_TEST_CASE( validation_and_basic_logic_test ) { auto& fee_params = gpo.parameters.get_mutable_fees().parameters; - auto itr = fee_params.find( ticket_create_operation::fee_parameters_type() ); - itr->get().fee = 1; + auto itr = fee_params.find( ticket_create_operation::fee_params_t() ); + itr->get().fee = 1; - itr = fee_params.find( ticket_update_operation::fee_parameters_type() ); - itr->get().fee = 2; + itr = fee_params.find( ticket_update_operation::fee_params_t() ); + itr->get().fee = 2; }); int64_t expected_balance = init_amount; From b7a5d682a2b4afe2fc5b37f0bad1a843b02ca25c Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 23 Mar 2023 22:36:37 +0000 Subject: [PATCH 070/127] Update a comment --- libraries/chain/db_update.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index 5c9192c29b..f3cfe14f36 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -770,7 +770,8 @@ void database::update_credit_offers_and_deals() { const credit_deal_object& deal = *deal_itr; - // Note: automatic repayment fails if the borrower became unauthorized by the debt asset or the collateral asset + // Process automatic repayment + // Note: an automatic repayment may fail, in which case we consider the credit deal past due without repayment using repay_type = credit_deal_auto_repayment_type; if( static_cast(repay_type::no_auto_repayment) != deal.auto_repay ) { From 2ca1d99be27e58afdcf796a24e1bff3a3f2f74a0 Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 23 Mar 2023 23:02:25 +0000 Subject: [PATCH 071/127] Update a comment --- tests/tests/credit_offer_tests.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/tests/credit_offer_tests.cpp b/tests/tests/credit_offer_tests.cpp index 8476ecfc47..474b3e3139 100644 --- a/tests/tests/credit_offer_tests.cpp +++ b/tests/tests/credit_offer_tests.cpp @@ -2182,8 +2182,9 @@ BOOST_AUTO_TEST_CASE( credit_deal_auto_repay_test ) BOOST_CHECK( histories[3].op.is_type() ); BOOST_CHECK( !histories[3].is_virtual ); - // ray's last 10 operations are 1 * credit_deal_expired_op, 3 * credit_deal_repay_op, 2 * credit_offer_accept_op, - // 3 * credit_offer_update_op, 1 * credit_accept_op + // ray's last 10 operations are 1 * credit_deal_expired_op, 3 * credit_deal_repay_op, + // 2 * credit_offer_accept_op, + // 3 * credit_deal_update_op, 1 * credit_accept_op histories = hist_api.get_relative_account_history( "ray", 0, 10, 0 ); BOOST_REQUIRE_EQUAL( histories.size(), 10U ); BOOST_CHECK( histories[0].op.is_type() ); From a89307c553054bb760912e2d851bedec891903dd Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 24 Mar 2023 11:29:44 +0000 Subject: [PATCH 072/127] Wrap long lines --- libraries/protocol/committee_member.cpp | 4 +++- .../include/graphene/protocol/committee_member.hpp | 14 ++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libraries/protocol/committee_member.cpp b/libraries/protocol/committee_member.cpp index 0f9751b856..fb67743b0b 100644 --- a/libraries/protocol/committee_member.cpp +++ b/libraries/protocol/committee_member.cpp @@ -51,7 +51,9 @@ void committee_member_update_global_parameters_operation::validate() const GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_create_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_operation::fee_params_t ) -GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_global_parameters_operation::fee_params_t ) +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( + graphene::protocol::committee_member_update_global_parameters_operation::fee_params_t ) + GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_create_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_global_parameters_operation ) diff --git a/libraries/protocol/include/graphene/protocol/committee_member.hpp b/libraries/protocol/include/graphene/protocol/committee_member.hpp index 501dce9d88..3fdfb1c53b 100644 --- a/libraries/protocol/include/graphene/protocol/committee_member.hpp +++ b/libraries/protocol/include/graphene/protocol/committee_member.hpp @@ -32,8 +32,8 @@ namespace graphene { namespace protocol { * @brief Create a committee_member object, as a bid to hold a committee_member seat on the network. * @ingroup operations * - * Accounts which wish to become committee_members may use this operation to create a committee_member object which stakeholders may - * vote on to approve its position as a committee_member. + * Accounts which wish to become committee_members may use this operation to create a committee_member object + * which stakeholders may vote on to approve its position as a committee_member. */ struct committee_member_create_operation : public base_operation { @@ -74,9 +74,9 @@ namespace graphene { namespace protocol { * @brief Used by committee_members to update the global parameters of the blockchain. * @ingroup operations * - * This operation allows the committee_members to update the global parameters on the blockchain. These control various - * tunable aspects of the chain, including block and maintenance intervals, maximum data sizes, the fees charged by - * the network, etc. + * This operation allows the committee_members to update the global parameters on the blockchain. + * These control various tunable aspects of the chain, including block and maintenance intervals, + * maximum data sizes, the fees charged by the network, etc. * * This operation may only be used in a proposed transaction, and a proposed transaction which contains this * operation must have a review period specified in the current global parameters before it may be accepted. @@ -108,7 +108,9 @@ FC_REFLECT( graphene::protocol::committee_member_update_global_parameters_operat GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_create_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_operation::fee_params_t ) -GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_global_parameters_operation::fee_params_t ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( + graphene::protocol::committee_member_update_global_parameters_operation::fee_params_t ) + GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::committee_member_update_global_parameters_operation ) From 9c0ad9b9c09d2dd49ad9e1c8e6cfad993773c4d2 Mon Sep 17 00:00:00 2001 From: Massimo Paladin Date: Fri, 24 Mar 2023 15:54:41 +0100 Subject: [PATCH 073/127] Remove SonarCloud cache and threads configurtion as it is now by default --- .github/workflows/sonar-scan.yml | 2 -- sonar-project.properties | 3 --- 2 files changed, 5 deletions(-) diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index 8356303fda..230a275c4e 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -109,7 +109,6 @@ jobs: with: path: | ccache - sonar_cache key: sonar-${{ env.OS_VERSION }}-${{ github.ref }}-${{ github.sha }} restore-keys: | sonar-${{ env.OS_VERSION }}-${{ github.ref }}- @@ -185,7 +184,6 @@ jobs: df -h - name: Prepare for scanning with SonarScanner run: | - mkdir -p sonar_cache find _build/libraries/[acdenptuw]*/CMakeFiles/*.dir \ _build/libraries/plugins/*/CMakeFiles/*.dir \ -type d -print \ diff --git a/sonar-project.properties b/sonar-project.properties index 7227dc8a73..41f5a2a82f 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -17,9 +17,6 @@ sonar.exclusions=programs/build_helper/**/*,libraries/fc/**/*,libraries/egenesis sonar.sources=libraries,programs sonar.cfamily.build-wrapper-output=bw-output sonar.cfamily.gcov.reportsPath=. -sonar.cfamily.threads=2 -sonar.cfamily.cache.enabled=true -sonar.cfamily.cache.path=sonar_cache # Decide which tree the current build belongs to in SonarCloud. # Managed by the `set_sonar_branch*` script(s) when building with CI. From 5d59c9e6d6808e8419ca7f37a6dbd74ce9652d67 Mon Sep 17 00:00:00 2001 From: Abit Date: Sat, 25 Mar 2023 00:39:37 +0100 Subject: [PATCH 074/127] Add comments --- sonar-project.properties | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonar-project.properties b/sonar-project.properties index 41f5a2a82f..8796e257ec 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -12,7 +12,11 @@ sonar.links.ci=https://github.com/bitshares/bitshares-core/actions sonar.links.issue=https://github.com/bitshares/bitshares-core/issues sonar.links.scm=https://github.com/bitshares/bitshares-core/tree/master +# Note: +# According to docs, sonar.tests is ignored by the C/C++/Objective-C analyzer. +# See https://docs.sonarcloud.io/advanced-setup/languages/c-c-objective-c/#language-specific-properties sonar.tests=tests + sonar.exclusions=programs/build_helper/**/*,libraries/fc/**/*,libraries/egenesis/egenesis_full.cpp sonar.sources=libraries,programs sonar.cfamily.build-wrapper-output=bw-output From b46de5d23cdad135a87eaa3bd1564e795cd8523d Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 29 Mar 2023 13:56:07 +0000 Subject: [PATCH 075/127] Use gcovr to process code coverage data for better coverage reporting, including branch coverage --- .github/workflows/sonar-scan.yml | 21 +++++---------------- sonar-project.properties | 7 ++++++- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index 230a275c4e..14bd6508e5 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -50,6 +50,7 @@ jobs: sudo apt-get install -y --allow-downgrades openssl=${openssl_ver} libssl-dev=${libssl_ver} sudo apt-get install -y \ ccache \ + gcovr \ parallel \ libboost-thread-dev \ libboost-iostreams-dev \ @@ -184,23 +185,11 @@ jobs: df -h - name: Prepare for scanning with SonarScanner run: | - find _build/libraries/[acdenptuw]*/CMakeFiles/*.dir \ - _build/libraries/plugins/*/CMakeFiles/*.dir \ - -type d -print \ - | while read d; do \ - tmpd="${d:7}"; \ - srcd="${tmpd/CMakeFiles*.dir/.}"; \ - gcov -o "$d" "${srcd}"/*.[ch][px][px] \ - "${srcd}"/include/graphene/*/*.[ch][px][px] ; \ - done >/dev/null - find _build/programs/[cdgjsw]*/CMakeFiles/*.dir \ - -type d -print \ - | while read d; do \ - tmpd="${d:7}"; \ - srcd="${tmpd/CMakeFiles*.dir/.}"; \ - gcov -o "$d" "${srcd}"/*.[ch][px][px] ; \ - done >/dev/null programs/build_helpers/set_sonar_branch_for_github_actions sonar-project.properties + pushd _build + gcovr --version + gcovr --exclude-unreachable-branches --sonarqube ../coverage.xml -r .. + popd - name: Scan with SonarScanner env: # to get access to secrets.SONAR_TOKEN, provide GITHUB_TOKEN diff --git a/sonar-project.properties b/sonar-project.properties index 8796e257ec..c6b9acde72 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -20,7 +20,12 @@ sonar.tests=tests sonar.exclusions=programs/build_helper/**/*,libraries/fc/**/*,libraries/egenesis/egenesis_full.cpp sonar.sources=libraries,programs sonar.cfamily.build-wrapper-output=bw-output -sonar.cfamily.gcov.reportsPath=. + +# Note: +# It is hard to get the gcov sensor working, but gcovr works. +# See https://community.sonarsource.com/t/code-coverage-incorrect-for-c-gcov-project/41837/5 +#sonar.cfamily.gcov.reportsPath=. +sonar.coverageReportPaths=coverage.xml # Decide which tree the current build belongs to in SonarCloud. # Managed by the `set_sonar_branch*` script(s) when building with CI. From 11b2a81dfb1b2f2a6e80a10075067eed25ac8e9c Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 29 Mar 2023 19:43:10 +0000 Subject: [PATCH 076/127] Bump FC --- libraries/fc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fc b/libraries/fc index 4d024a83b7..2405393e40 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 4d024a83b774da0e186c0c6c070e695f563da373 +Subproject commit 2405393e40219b8ff3a87ccbcc3de14e32886dda From f927efc45a9b7fcb12eeb500595754663797d8f5 Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 30 Mar 2023 09:41:47 +0000 Subject: [PATCH 077/127] Fix macOS build Type "long" is not reflected in macOS, so avoid using it implicitly in tests --- tests/cli/main.cpp | 4 ++-- tests/tests/settle_tests.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/cli/main.cpp b/tests/cli/main.cpp index 41b3b632c8..585b2dd416 100644 --- a/tests/cli/main.cpp +++ b/tests/cli/main.cpp @@ -1246,8 +1246,8 @@ BOOST_FIXTURE_TEST_CASE( cli_confidential_tx_test, cli_fixture ) // then confirm that balances are received, and then analyze the range // prooofs to make sure the mantissa length does not reveal approximate // balance (issue #480). - std::map to_list = {{"alice",100000000000}, - {"bob", 1000000000}}; + std::map to_list = {{"alice",100000000000LL}, + {"bob", 1000000000LL}}; vector bconfs; auto core_asset = W.get_asset("1.3.0"); BOOST_TEST_MESSAGE("Sending blind transactions to alice and bob"); diff --git a/tests/tests/settle_tests.cpp b/tests/tests/settle_tests.cpp index 5fef6aeede..2d879f1351 100644 --- a/tests/tests/settle_tests.cpp +++ b/tests/tests/settle_tests.cpp @@ -1551,7 +1551,7 @@ BOOST_AUTO_TEST_CASE( create_bitassets ) transfer( committee_account, rachelregistrar_id, asset( 10000000 ) ); transfer( committee_account, rachelreferrer_id, asset( 10000000 ) ); transfer( committee_account, rachel.get_id(), asset( 10000000) ); - transfer( committee_account, paul_id, asset( 10000000000 ) ); + transfer( committee_account, paul_id, asset( 10000000000LL ) ); asset_update_operation op; op.issuer = biteur.issuer; From 4f66004e7b259486e4c15dbd1167f50490ca8a4b Mon Sep 17 00:00:00 2001 From: Abit Date: Thu, 30 Mar 2023 15:44:20 +0200 Subject: [PATCH 078/127] Update sonar.projectVersion to 6.2.x --- sonar-project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonar-project.properties b/sonar-project.properties index c6b9acde72..482a903b81 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,7 +3,7 @@ sonar.organization=bitshares-on-github sonar.projectKey=bitshares_bitshares-core sonar.projectName=BitShares-Core sonar.projectDescription=BitShares Blockchain node and command-line wallet -sonar.projectVersion=6.1.x +sonar.projectVersion=6.2.x sonar.host.url=https://sonarcloud.io From d1da353d40b76dd010e2e62a573238a3d42186c3 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 31 Mar 2023 01:33:32 +0000 Subject: [PATCH 079/127] Remove mostly useless try/catch wrappers --- libraries/chain/credit_offer_evaluator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/chain/credit_offer_evaluator.cpp b/libraries/chain/credit_offer_evaluator.cpp index cbbb64464f..7c1ef6edcf 100644 --- a/libraries/chain/credit_offer_evaluator.cpp +++ b/libraries/chain/credit_offer_evaluator.cpp @@ -473,7 +473,7 @@ extendable_operation_result credit_deal_repay_evaluator::do_apply( const credit_ } FC_CAPTURE_AND_RETHROW( (op) ) } void_result credit_deal_update_evaluator::do_evaluate(const credit_deal_update_operation& op) -{ try { +{ const database& d = db(); const auto block_time = d.head_block_time(); @@ -486,10 +486,10 @@ void_result credit_deal_update_evaluator::do_evaluate(const credit_deal_update_o FC_ASSERT( _deal->auto_repay != op.auto_repay, "The automatic repayment type does not change" ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} void_result credit_deal_update_evaluator::do_apply( const credit_deal_update_operation& op) const -{ try { +{ database& d = db(); d.modify( *_deal, [&op]( credit_deal_object& obj ){ @@ -497,6 +497,6 @@ void_result credit_deal_update_evaluator::do_apply( const credit_deal_update_ope }); return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} } } // graphene::chain From 5366a79cc8bfb094ef8581a8cd612714d2493480 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 31 Mar 2023 15:38:54 +0000 Subject: [PATCH 080/127] Call gcovr with --exclude-throw-branches in CI For branch coverage, exclude branches that the compiler generates for exception handling, to generate more "sensible" coverage reports. --- .github/workflows/sonar-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index 14bd6508e5..805be71753 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -188,7 +188,7 @@ jobs: programs/build_helpers/set_sonar_branch_for_github_actions sonar-project.properties pushd _build gcovr --version - gcovr --exclude-unreachable-branches --sonarqube ../coverage.xml -r .. + gcovr --exclude-unreachable-branches --exclude-throw-branches --sonarqube ../coverage.xml -r .. popd - name: Scan with SonarScanner env: From 3da7891d2aeb77fe9bf9f2938c81dba740a662f6 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 31 Mar 2023 16:57:55 +0000 Subject: [PATCH 081/127] Exclude programs and tests from coverage reports --- .github/workflows/sonar-scan.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index 805be71753..bb591b1df4 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -188,7 +188,10 @@ jobs: programs/build_helpers/set_sonar_branch_for_github_actions sonar-project.properties pushd _build gcovr --version - gcovr --exclude-unreachable-branches --exclude-throw-branches --sonarqube ../coverage.xml -r .. + gcovr --exclude-unreachable-branches --exclude-throw-branches \ + --exclude '\.\./programs/' \ + --exclude '\.\./tests/' \ + --sonarqube ../coverage.xml -r .. popd - name: Scan with SonarScanner env: From 3fc4de4c0bfbd2a07dbbe9ac3c23565b5e495b97 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 19 Apr 2023 12:54:09 +0000 Subject: [PATCH 082/127] Add fee_change_test --- tests/tests/fee_tests.cpp | 92 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/tests/tests/fee_tests.cpp b/tests/tests/fee_tests.cpp index ce0aa3e7d1..fa3c952bf5 100644 --- a/tests/tests/fee_tests.cpp +++ b/tests/tests/fee_tests.cpp @@ -3907,4 +3907,96 @@ BOOST_AUTO_TEST_CASE( issue_433_indirect_test ) } } +BOOST_AUTO_TEST_CASE( fee_change_test ) +{ try { + + // At the beginning, the fee schedule is all zero + const auto& check_zero_fees = [&]() { + BOOST_REQUIRE( db.get_global_properties().parameters.current_fees ); + BOOST_CHECK_EQUAL( db.get_global_properties().parameters.current_fees->scale, 0 ); + BOOST_REQUIRE( !db.get_global_properties().parameters.current_fees->parameters.empty() ); + BOOST_CHECK_EQUAL( db.get_global_properties().parameters.current_fees->parameters.begin()->get< + transfer_operation::fee_params_t>().fee, 0 ); + }; + + check_zero_fees(); + + { + // Try to set default fees, it should fail, because some operations aren't available + proposal_create_operation cop = proposal_create_operation::committee_proposal( + db.get_global_properties().parameters, db.head_block_time() ); + cop.fee_paying_account = GRAPHENE_TEMP_ACCOUNT; + cop.expiration_time = db.head_block_time() + *cop.review_period_seconds + 10; + committee_member_update_global_parameters_operation cmuop; + cmuop.new_parameters = db.get_global_properties().parameters; + cmuop.new_parameters.get_mutable_fees() = fee_schedule::get_default(); + cop.proposed_ops.emplace_back( cmuop ); + trx.operations.push_back( cop ); + + // It should fail + GRAPHENE_CHECK_THROW( PUSH_TX(db, trx, ~0), fc::exception ); + trx.clear(); + } + + // The fee schedule is still all zero + check_zero_fees(); + + // Pass the BSIP-40 hardfork + generate_blocks( HARDFORK_BSIP_40_TIME ); + set_expiration( db, trx ); + + // The fee schedule is still all zero + check_zero_fees(); + + { + // Try to set default fees, it should succeed + proposal_create_operation cop = proposal_create_operation::committee_proposal( + db.get_global_properties().parameters, db.head_block_time() ); + cop.fee_paying_account = GRAPHENE_TEMP_ACCOUNT; + cop.expiration_time = db.head_block_time() + *cop.review_period_seconds + 10; + committee_member_update_global_parameters_operation cmuop; + cmuop.new_parameters = db.get_global_properties().parameters; + cmuop.new_parameters.get_mutable_fees() = fee_schedule::get_default(); + cop.proposed_ops.emplace_back( cmuop ); + trx.operations.push_back( cop ); + + // It should fail + processed_transaction ptx = PUSH_TX(db, trx, ~0); + trx.clear(); + proposal_id_type prop_id { ptx.operation_results[0].get() }; + + // The fee schedule is still all zero + check_zero_fees(); + + // Approve the proposal + proposal_update_operation uop; + uop.fee_paying_account = GRAPHENE_TEMP_ACCOUNT; + uop.active_approvals_to_add = { get_account("init0").get_id(), get_account("init1").get_id(), + get_account("init2").get_id(), get_account("init3").get_id(), + get_account("init4").get_id(), get_account("init5").get_id(), + get_account("init6").get_id(), get_account("init7").get_id() }; + trx.operations.push_back(uop); + PUSH_TX(db, trx, ~0); + + // The fee schedule is still all zero + check_zero_fees(); + + generate_blocks( prop_id( db ).expiration_time + 5 ); + generate_blocks( db.get_dynamic_global_properties().next_maintenance_time ); + generate_block(); + + // The fee schedule is no longer all zero + BOOST_REQUIRE( db.get_global_properties().parameters.current_fees ); + BOOST_CHECK_EQUAL( db.get_global_properties().parameters.current_fees->scale, GRAPHENE_100_PERCENT ); + BOOST_REQUIRE( !db.get_global_properties().parameters.current_fees->parameters.empty() ); + BOOST_CHECK_EQUAL( db.get_global_properties().parameters.current_fees->parameters.begin()->get< + transfer_operation::fee_params_t>().fee, transfer_operation::fee_params_t().fee ); + BOOST_CHECK( transfer_operation::fee_params_t().fee != 0 ); + + idump( (db.get_global_properties()) ); + + } + +} FC_LOG_AND_RETHROW() } + BOOST_AUTO_TEST_SUITE_END() From a03b4ce5d994fb91b438f3eddb21ee0424a84a6c Mon Sep 17 00:00:00 2001 From: abitmore Date: Mon, 8 May 2023 08:36:21 +0000 Subject: [PATCH 083/127] Fix issues about limit_order_update_evaluator --- .../graphene/chain/market_evaluator.hpp | 3 +- libraries/chain/market_evaluator.cpp | 71 ++++++++++++++----- libraries/chain/proposal_evaluator.cpp | 4 +- .../include/graphene/protocol/market.hpp | 5 +- tests/tests/operation_tests.cpp | 19 ++--- 5 files changed, 68 insertions(+), 34 deletions(-) diff --git a/libraries/chain/include/graphene/chain/market_evaluator.hpp b/libraries/chain/include/graphene/chain/market_evaluator.hpp index b222730c74..d2371e1db7 100644 --- a/libraries/chain/include/graphene/chain/market_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/market_evaluator.hpp @@ -65,8 +65,9 @@ namespace graphene { namespace chain { using operation_type = limit_order_update_operation; void_result do_evaluate(const limit_order_update_operation& o); - void_result do_apply(const limit_order_update_operation& o); + void_result do_apply(const limit_order_update_operation& o) const; + private: const limit_order_object* _order = nullptr; bool should_match_orders = false; }; diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 7d2a1ebb79..b2c09f03b8 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -137,7 +137,7 @@ object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_o void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_operation& o) { try { const database& d = db(); - FC_ASSERT(d.head_block_time() >= HARDFORK_CORE_1604_TIME, "Operation has not activated yet"); + FC_ASSERT( HARDFORK_CORE_1604_PASSED( d.head_block_time() ) , "Operation has not activated yet"); _order = &o.order(d); // Check this is my order @@ -150,11 +150,15 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o FC_ASSERT(base_id == _order->sell_price.base.asset_id && quote_id == _order->sell_price.quote.asset_id, "Cannot update limit order with incompatible price"); const auto& order_index = d.get_index_type().indices().get(); - auto top_of_book = order_index.upper_bound(boost::make_tuple(price::max(base_id, quote_id))); - FC_ASSERT(top_of_book->sell_price.base.asset_id == base_id && top_of_book->sell_price.quote.asset_id == quote_id, - "Paradox: attempting to update an order in a market that has no orders? There's a logic error somewhere."); - - // If the new price of our order is greater than the price of the order at the top of the book, we should match orders at the end. + auto top_of_book = order_index.lower_bound( price::max(base_id, quote_id) ); + FC_ASSERT( top_of_book != order_index.end() + && top_of_book->sell_price.base.asset_id == base_id + && top_of_book->sell_price.quote.asset_id == quote_id, + "Paradox: attempting to update an order in a market that has no orders? " + "There's a logic error somewhere." ); + + // If the new price of our order is greater than the price of the order at the top of the book, + // we should match orders at the end. // Otherwise, we can skip matching because there's no way this change could trigger orders to fill. should_match_orders = (*o.new_price > top_of_book->sell_price); } @@ -165,7 +169,7 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o FC_ASSERT(delta.asset_id == _order->sell_price.base.asset_id, "Cannot update limit order with incompatible asset"); if (delta.amount > 0) - FC_ASSERT(d.get_balance(o.seller, delta.asset_id) > delta, + FC_ASSERT(d.get_balance(o.seller, delta.asset_id) >= delta, "Insufficient balance to increase order amount"); else FC_ASSERT(_order->for_sale > -delta.amount, @@ -180,29 +184,60 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o new_amount += *o.delta_amount_to_sell; auto new_amount_to_receive = new_amount * new_price; - FC_ASSERT(new_amount_to_receive.amount > 0, "Cannot update limit order: order becomes too small; cancel order instead"); + FC_ASSERT( new_amount_to_receive.amount > 0, + "Cannot update limit order: order becomes too small; cancel order instead" ); } // Check expiration is in the future if (o.new_expiration) - FC_ASSERT(*o.new_expiration > _order->expiration, - "Cannot update limit order to expire sooner; new expiration must be later than old one."); + FC_ASSERT( *o.new_expiration >= d.head_block_time(), "Cannot update limit order to expire in the past." ); + + // Check asset authorization + // TODO refactor to fix duplicate code (see limit_order_create) + const auto sell_asset_id = _order->sell_asset_id(); + const auto receive_asset_id = _order->receive_asset_id(); + const auto& sell_asset = sell_asset_id(d); + const auto& receive_asset = receive_asset_id(d); + const auto& seller = *this->fee_paying_account; + + if( !sell_asset.options.whitelist_markets.empty() ) + { + FC_ASSERT( sell_asset.options.whitelist_markets.find( receive_asset_id ) + != sell_asset.options.whitelist_markets.end(), + "This market has not been whitelisted by the selling asset" ); + } + if( !sell_asset.options.blacklist_markets.empty() ) + { + FC_ASSERT( sell_asset.options.blacklist_markets.find( receive_asset_id ) + == sell_asset.options.blacklist_markets.end(), + "This market has been blacklisted by the selling asset" ); + } + + FC_ASSERT( is_authorized_asset( d, seller, sell_asset ), + "The account is not allowed to transact the selling asset" ); + + FC_ASSERT( is_authorized_asset( d, seller, receive_asset ), + "The account is not allowed to transact the receiving asset" ); return {}; } FC_CAPTURE_AND_RETHROW((o)) } -void_result limit_order_update_evaluator::do_apply(const limit_order_update_operation& o) +void_result limit_order_update_evaluator::do_apply(const limit_order_update_operation& o) const { try { database& d = db(); // Adjust account balance - const auto& seller_stats = o.seller(d).statistics(d); - if (o.delta_amount_to_sell && o.delta_amount_to_sell->asset_id == asset_id_type()) - db().modify(seller_stats, [&o](account_statistics_object& bal) { - bal.total_core_in_orders += o.delta_amount_to_sell->amount; - }); - if (o.delta_amount_to_sell) - d.adjust_balance(o.seller, -*o.delta_amount_to_sell); + if( o.delta_amount_to_sell ) + { + d.adjust_balance( o.seller, -*o.delta_amount_to_sell ); + if( o.delta_amount_to_sell->asset_id == asset_id_type() ) + { + const auto& seller_stats = d.get_account_stats_by_owner( o.seller ); + d.modify( seller_stats, [&o]( account_statistics_object& bal ) { + bal.total_core_in_orders += o.delta_amount_to_sell->amount; + }); + } + } // Update order d.modify(*_order, [&o](limit_order_object& loo) { diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index c024850a14..164cb12529 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -72,7 +72,7 @@ struct proposal_operation_hardfork_visitor // TODO review and cleanup code below after hard fork // hf_1604 void operator()(const graphene::chain::limit_order_update_operation &) const { - FC_ASSERT(block_time >= HARDFORK_CORE_1604_TIME, "Operation is not enabled yet"); + FC_ASSERT( HARDFORK_CORE_1604_PASSED(block_time), "Operation is not enabled yet" ); } void operator()(const graphene::chain::asset_create_operation &v) const { @@ -149,7 +149,7 @@ struct proposal_operation_hardfork_visitor FC_ASSERT(!op.new_parameters.current_fees->exists()); FC_ASSERT(!op.new_parameters.current_fees->exists()); } - if (block_time < HARDFORK_CORE_1604_TIME) { + if (!HARDFORK_CORE_1604_PASSED(block_time)) { FC_ASSERT(!op.new_parameters.current_fees->exists(), "Cannot set fees for limit_order_update_operation before its hardfork time"); } diff --git a/libraries/protocol/include/graphene/protocol/market.hpp b/libraries/protocol/include/graphene/protocol/market.hpp index e727b33e68..ad3a965df3 100644 --- a/libraries/protocol/include/graphene/protocol/market.hpp +++ b/libraries/protocol/include/graphene/protocol/market.hpp @@ -93,10 +93,7 @@ namespace graphene { namespace protocol { extensions_type extensions; account_id_type fee_payer() const { return seller; } - void validate() const; - share_type calculate_fee(const fee_params_t& k) const { - return k.fee; - } + void validate() const override; }; /** diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 1bb1c3ec5c..48d1360c0e 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -117,8 +117,10 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(-1), bitusd.amount(2))), fc::assert_exception); GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(1), bitusd.amount(-2))), fc::assert_exception); // Cannot update order to use different assets - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(bitusd.amount(2), munee.amount(1))), fc::assert_exception); - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(munee.amount(2), bitusd.amount(1))), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(bitusd.amount(2), munee.amount(1))), + fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(munee.amount(2), bitusd.amount(1))), + fc::assert_exception); GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(2), munee.amount(1))), fc::assert_exception); // Cannot update order to expire in the past GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, db.head_block_time() - 10), fc::assert_exception); @@ -150,11 +152,8 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) expiration += 50; update_limit_order(order_id, {}, {}, expiration); BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); - // Cannot make expiration same as before - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, expiration), fc::assert_exception); - // Cannot make expiration sooner; only later - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, expiration - 100), fc::assert_exception); - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, expiration - 1), fc::assert_exception); + // Cannot change expiration to a time in the past + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, db.head_block_time() - 1 ), fc::assert_exception); // Try adding funds update_limit_order(order_id, {}, asset(50)); @@ -198,8 +197,10 @@ BOOST_AUTO_TEST_CASE(limit_order_update_dust_test) limit_order_id_type order_id = create_sell_order(nathan, asset(1000), munee.amount(100), expiration)->get_id(); GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(-995)), fc::assert_exception); - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(1000000), munee.amount(100))), fc::assert_exception); - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(2000), munee.amount(100)), asset(-985)), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(1000000), munee.amount(100))), + fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(2000), munee.amount(100)), asset(-985)), + fc::assert_exception); } catch (fc::exception& e) { edump((e.to_detail_string())); throw; From 44e6de415aa2efc91f848fc5c630ef9514fb83a3 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 9 May 2023 13:59:58 +0000 Subject: [PATCH 084/127] Do not allow inappropriate price manipulation --- libraries/chain/market_evaluator.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index b2c09f03b8..99491a759b 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -149,6 +149,14 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o auto quote_id = o.new_price->quote.asset_id; FC_ASSERT(base_id == _order->sell_price.base.asset_id && quote_id == _order->sell_price.quote.asset_id, "Cannot update limit order with incompatible price"); + + // Do not allow inappropriate price manipulation + auto max_amount_for_sale = std::max( _order->for_sale, _order->sell_price.base.amount ); + if( o.delta_amount_to_sell ) + max_amount_for_sale += o.delta_amount_to_sell->amount; + FC_ASSERT( o.new_price->base.amount <= max_amount_for_sale, + "The base amount in the new price cannot be greater than the estimated maximum amount for sale" ); + const auto& order_index = d.get_index_type().indices().get(); auto top_of_book = order_index.lower_bound( price::max(base_id, quote_id) ); FC_ASSERT( top_of_book != order_index.end() From 2387df36c1f9ddbe6e6df94478a68164f2953ba3 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 9 May 2023 14:07:13 +0000 Subject: [PATCH 085/127] Remove redundant checks for order matching --- .../include/graphene/chain/market_evaluator.hpp | 1 - libraries/chain/market_evaluator.cpp | 15 +-------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/libraries/chain/include/graphene/chain/market_evaluator.hpp b/libraries/chain/include/graphene/chain/market_evaluator.hpp index d2371e1db7..61684a765d 100644 --- a/libraries/chain/include/graphene/chain/market_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/market_evaluator.hpp @@ -69,7 +69,6 @@ namespace graphene { namespace chain { private: const limit_order_object* _order = nullptr; - bool should_match_orders = false; }; class limit_order_cancel_evaluator : public evaluator diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 99491a759b..0bfd099470 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -157,18 +157,6 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o FC_ASSERT( o.new_price->base.amount <= max_amount_for_sale, "The base amount in the new price cannot be greater than the estimated maximum amount for sale" ); - const auto& order_index = d.get_index_type().indices().get(); - auto top_of_book = order_index.lower_bound( price::max(base_id, quote_id) ); - FC_ASSERT( top_of_book != order_index.end() - && top_of_book->sell_price.base.asset_id == base_id - && top_of_book->sell_price.quote.asset_id == quote_id, - "Paradox: attempting to update an order in a market that has no orders? " - "There's a logic error somewhere." ); - - // If the new price of our order is greater than the price of the order at the top of the book, - // we should match orders at the end. - // Otherwise, we can skip matching because there's no way this change could trigger orders to fill. - should_match_orders = (*o.new_price > top_of_book->sell_price); } // Check delta asset is compatible @@ -258,8 +246,7 @@ void_result limit_order_update_evaluator::do_apply(const limit_order_update_oper }); // Perform order matching if necessary - if (should_match_orders) - d.apply_order(*_order); + d.apply_order(*_order); return {}; } FC_CAPTURE_AND_RETHROW((o)) } From 2b3bcd3bf94a8cf786a88b8489816d3068378c24 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 9 May 2023 14:15:35 +0000 Subject: [PATCH 086/127] Remove redundant checks for account balance --- libraries/chain/market_evaluator.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 0bfd099470..56e4ed584b 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -164,12 +164,10 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o const auto& delta = *o.delta_amount_to_sell; FC_ASSERT(delta.asset_id == _order->sell_price.base.asset_id, "Cannot update limit order with incompatible asset"); - if (delta.amount > 0) - FC_ASSERT(d.get_balance(o.seller, delta.asset_id) >= delta, - "Insufficient balance to increase order amount"); - else + if (delta.amount < 0) FC_ASSERT(_order->for_sale > -delta.amount, - "Cannot deduct more from order than order contains"); + "Cannot deduct all or more from order than order contains"); + // Note: if the delta amount is positive, account balance will be checked when calling adjust_balance() } // Check dust From e8e9d0dc2d5be3802a7865671133431634f4c4fd Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 9 May 2023 14:30:57 +0000 Subject: [PATCH 087/127] Simplify try-catch wrappers in tests --- tests/tests/operation_tests.cpp | 432 ++++++++++---------------------- 1 file changed, 139 insertions(+), 293 deletions(-) diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 48d1360c0e..b8711d84b0 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -50,8 +50,8 @@ using namespace graphene::chain::test; BOOST_FIXTURE_TEST_SUITE( operation_tests, database_fixture ) BOOST_AUTO_TEST_CASE( feed_limit_logic_test ) -{ - try { +{ try { + asset usd(1000,asset_id_type(1)); asset core(1000,asset_id_type(0)); price_feed feed; @@ -74,15 +74,11 @@ BOOST_AUTO_TEST_CASE( feed_limit_logic_test ) BOOST_CHECK( usd * feed.maintenance_price() < usd * feed.max_short_squeeze_price() ); */ - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(limit_order_update_test) -{ - try { +{ try { + ACTORS((nathan)); generate_blocks(HARDFORK_CORE_1604_TIME + 10); @@ -174,15 +170,12 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); BOOST_REQUIRE_EQUAL(order_id(db).amount_for_sale().amount.value, 500); BOOST_REQUIRE_EQUAL(db.get_balance(nathan_id, core.get_id()).amount.value, 500); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(limit_order_update_dust_test) -{ - try { +{ try { + ACTORS((nathan)); generate_blocks(HARDFORK_CORE_1604_TIME + 10); @@ -201,15 +194,12 @@ BOOST_AUTO_TEST_CASE(limit_order_update_dust_test) fc::assert_exception); GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(2000), munee.amount(100)), asset(-985)), fc::assert_exception); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(limit_order_update_match_test) -{ - try { +{ try { + ACTORS((nathan)); generate_blocks(HARDFORK_CORE_1604_TIME + 10); @@ -227,15 +217,12 @@ BOOST_AUTO_TEST_CASE(limit_order_update_match_test) update_limit_order(order_id_1, price(asset(1001), munee.amount(100)), asset(1)); BOOST_REQUIRE( !db.find(order_id_1) ); BOOST_REQUIRE_EQUAL(db.find(order_id_2)->amount_for_sale().amount.value, 1); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(limit_order_update_match_test_2) -{ - try { +{ try { + ACTORS((nathan)); generate_blocks(HARDFORK_CORE_1604_TIME + 10); @@ -253,15 +240,11 @@ BOOST_AUTO_TEST_CASE(limit_order_update_match_test_2) update_limit_order(order_id_2, price(munee.amount(100), asset(999))); BOOST_REQUIRE( !db.find(order_id_1) ); BOOST_REQUIRE( !db.find(order_id_2) ); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( call_order_update_test ) -{ - try { +{ try { ACTORS((dan)(sam)); const auto& bitusd = create_bitasset("USDBIT", sam.get_id()); @@ -353,15 +336,10 @@ BOOST_AUTO_TEST_CASE( call_order_update_test ) BOOST_TEST_MESSAGE( "attempting change call price to be below minimum for debt/collateral ratio" ); GRAPHENE_REQUIRE_THROW( cover( dan, bitusd.amount(0), asset(0)), fc::exception ); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( old_call_order_update_test_after_hardfork_583 ) -{ - try { +{ try { auto hf_time = HARDFORK_CORE_583_TIME; if( bsip77 ) @@ -460,15 +438,11 @@ BOOST_AUTO_TEST_CASE( old_call_order_update_test_after_hardfork_583 ) BOOST_TEST_MESSAGE( "attempting change call price to be below minimum for debt/collateral ratio" ); GRAPHENE_REQUIRE_THROW( cover( dan, bitusd.amount(0), asset(0)), fc::exception ); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( call_order_update_asset_auth_test ) -{ - try { +{ try { + generate_blocks( HARDFORK_CORE_973_TIME - fc::days(1) ); set_expiration( db, trx ); @@ -617,15 +591,11 @@ BOOST_AUTO_TEST_CASE( call_order_update_asset_auth_test ) generate_block(); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( asset_settle_operation_asset_auth_test ) -{ - try { +{ try { + generate_blocks( HARDFORK_CORE_973_TIME - fc::days(1) ); set_expiration( db, trx ); @@ -783,15 +753,11 @@ BOOST_AUTO_TEST_CASE( asset_settle_operation_asset_auth_test ) generate_block(); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( bid_collateral_operation_asset_auth_test ) -{ - try { +{ try { + generate_blocks( HARDFORK_CORE_973_TIME - fc::days(1) ); set_expiration( db, trx ); @@ -944,14 +910,11 @@ BOOST_AUTO_TEST_CASE( bid_collateral_operation_asset_auth_test ) generate_block(); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( asset_settle_cancel_operation_test_after_hf588 ) -{ +{ try { + set_expiration( db, trx ); BOOST_TEST_MESSAGE( "Creating a proposal containing a asset_settle_cancel_operation" ); @@ -1004,15 +967,15 @@ BOOST_AUTO_TEST_CASE( asset_settle_cancel_operation_test_after_hf588 ) return false; }); } -} + +} FC_LOG_AND_RETHROW() } /// Test case for bsip77: /// * the "initial_collateral_ratio" parameter can only be set after the BSIP77 hard fork /// * the parameter should be within a range // TODO removed the hard fork part after the hard fork, keep the valid range part BOOST_AUTO_TEST_CASE( bsip77_hardfork_time_and_param_valid_range_test ) -{ - try { +{ try { // Proceeds to a recent hard fork generate_blocks( HARDFORK_CORE_583_TIME ); @@ -1192,11 +1155,7 @@ BOOST_AUTO_TEST_CASE( bsip77_hardfork_time_and_param_valid_range_test ) generate_block(); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( old_call_order_update_test_after_hardfork_bsip77_when_icr_not_set ) { @@ -1205,8 +1164,7 @@ BOOST_AUTO_TEST_CASE( old_call_order_update_test_after_hardfork_bsip77_when_icr_ } BOOST_AUTO_TEST_CASE( more_call_order_update_test ) -{ - try { +{ try { ACTORS((dan)(sam)(alice)(bob)); const auto& bitusd = create_bitasset("USDBIT", sam.get_id()); @@ -1300,16 +1258,10 @@ BOOST_AUTO_TEST_CASE( more_call_order_update_test ) BOOST_TEST_MESSAGE( "dan adding 1 core as collateral should not be allowed..." ); GRAPHENE_REQUIRE_THROW( borrow( dan, bitusd.amount(0), core.amount(1) ), fc::exception ); - - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( more_call_order_update_test_after_hardfork_583 ) -{ - try { +{ try { auto hf_time = HARDFORK_CORE_583_TIME; if( bsip77 ) @@ -1417,11 +1369,7 @@ BOOST_AUTO_TEST_CASE( more_call_order_update_test_after_hardfork_583 ) BOOST_TEST_MESSAGE( "dan borrow 2500 more usd wth 5003 more core should not be allowed..." ); GRAPHENE_REQUIRE_THROW( borrow( dan, bitusd.amount(2500), asset(5003) ), fc::exception ); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( more_call_order_update_test_after_hardfork_bsip77_when_icr_not_set ) { @@ -1430,8 +1378,7 @@ BOOST_AUTO_TEST_CASE( more_call_order_update_test_after_hardfork_bsip77_when_icr } BOOST_AUTO_TEST_CASE( more_call_order_update_test_after_hardfork_bsip77_when_icr_is_set ) -{ - try { +{ try { auto hf_time = HARDFORK_BSIP_77_TIME; generate_blocks( hf_time ); @@ -1624,15 +1571,10 @@ BOOST_AUTO_TEST_CASE( more_call_order_update_test_after_hardfork_bsip77_when_icr generate_block(); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( more_call_order_update_test_after_hardfork_bsip77_when_icr_is_fed ) -{ - try { +{ try { auto hf_time = HARDFORK_BSIP_77_TIME; generate_blocks( hf_time ); @@ -1807,14 +1749,11 @@ BOOST_AUTO_TEST_CASE( more_call_order_update_test_after_hardfork_bsip77_when_icr generate_block(); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( call_order_update_validation_test ) -{ +{ try { + call_order_update_operation op; // throw on default values @@ -1845,7 +1784,8 @@ BOOST_AUTO_TEST_CASE( call_order_update_validation_test ) op.extensions.value.target_collateral_ratio = 65535; op.validate(); // still valid -} + +} FC_LOG_AND_RETHROW() } /** * This test sets up a situation where a margin call will be executed and ensures that @@ -1863,6 +1803,7 @@ BOOST_AUTO_TEST_CASE( call_order_update_validation_test ) */ BOOST_AUTO_TEST_CASE( margin_call_limit_test ) { try { + ACTORS((buyer)(seller)(borrower)(borrower2)(feedproducer)); const auto& bitusd = create_bitasset("USDBIT", feedproducer_id); @@ -1923,14 +1864,12 @@ BOOST_AUTO_TEST_CASE( margin_call_limit_test ) // this should trigger margin call without protection from the price feed. order = create_sell_order( borrower2, bitusd.amount(1000), core.amount(1800) ); BOOST_CHECK( order != nullptr ); - } catch( const fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( prediction_market ) { try { + ACTORS((judge)(dan)(nathan)); const auto& pmark = create_prediction_market("PMARK", judge_id); @@ -1981,14 +1920,12 @@ BOOST_AUTO_TEST_CASE( prediction_market ) generate_block(~database::skip_transaction_dupe_check); generate_blocks( db.get_dynamic_global_properties().next_maintenance_time ); generate_block(); - } catch( const fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( prediction_market_resolves_to_0 ) { try { + ACTORS((judge)(dan)(nathan)); const auto& pmark = create_prediction_market("PMARK", judge_id); @@ -2019,18 +1956,15 @@ BOOST_AUTO_TEST_CASE( prediction_market_resolves_to_0 ) generate_block(~database::skip_transaction_dupe_check); generate_blocks( db.get_dynamic_global_properties().next_maintenance_time ); generate_block(); -} catch( const fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } /*** * Prediction markets should not suffer a black swan (Issue #460) */ BOOST_AUTO_TEST_CASE( prediction_market_black_swan ) -{ - try { +{ try { + ACTORS((judge)(dan)(nathan)); // progress to recent hardfork @@ -2081,15 +2015,12 @@ BOOST_AUTO_TEST_CASE( prediction_market_black_swan ) generate_block(~database::skip_transaction_dupe_check); generate_blocks( db.get_dynamic_global_properties().next_maintenance_time ); generate_block(); - } catch( const fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( create_account_test ) -{ - try { +{ try { + generate_blocks( HARDFORK_CORE_143_TIME ); set_expiration( db, trx ); trx.operations.push_back(make_account()); @@ -2161,15 +2092,11 @@ BOOST_AUTO_TEST_CASE( create_account_test ) BOOST_CHECK_EQUAL( nathan_id(db).creation_block_num, db.head_block_num() ); BOOST_CHECK( nathan_id(db).creation_time == db.head_block_time() ); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( update_account ) -{ - try { +{ try { + const account_object& nathan = create_account("nathan", init_account_pub_key); const fc::ecc::private_key nathan_new_key = fc::ecc::private_key::generate(); const public_key_type key_id = nathan_new_key.get_public_key(); @@ -2211,15 +2138,12 @@ BOOST_AUTO_TEST_CASE( update_account ) } BOOST_CHECK( nathan.is_lifetime_member() ); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( transfer_core_asset ) -{ - try { +{ try { + INVOKE(create_account_test); account_id_type committee_account; @@ -2259,15 +2183,11 @@ BOOST_AUTO_TEST_CASE( transfer_core_asset ) BOOST_CHECK_EQUAL(get_balance(nathan_account, asset_id_type()(db)), 8000 - fee.amount.value); BOOST_CHECK_EQUAL(get_balance(account_id_type()(db), asset_id_type()(db)), committee_balance.amount.value + 2000); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( create_committee_member ) -{ - try { +{ try { + committee_member_create_operation op; op.committee_member_account = account_id_type(); op.fee = asset(); @@ -2282,29 +2202,23 @@ BOOST_AUTO_TEST_CASE( create_committee_member ) const committee_member_object& d = committee_member_id(db); BOOST_CHECK(d.committee_member_account == account_id_type()); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( create_mia ) -{ - try { +{ try { + const asset_object& bitusd = create_bitasset( "USDBIT" ); BOOST_CHECK(bitusd.symbol == "USDBIT"); BOOST_CHECK(bitusd.bitasset_data(db).options.short_backing_asset == asset_id_type()); BOOST_CHECK(bitusd.dynamic_asset_data_id(db).current_supply == 0); GRAPHENE_REQUIRE_THROW( create_bitasset("USDBIT"), fc::exception); - } catch ( const fc::exception& e ) { - elog( "${e}", ("e", e.to_detail_string() ) ); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( update_mia ) -{ - try { +{ try { + INVOKE(create_mia); generate_block(); const asset_object& bit_usd = get_asset("USDBIT"); @@ -2351,16 +2265,12 @@ BOOST_AUTO_TEST_CASE( update_mia ) trx.operations.back() = op; PUSH_TX( db, trx, ~0 ); BOOST_CHECK(bit_usd.issuer == account_id_type()); - } catch ( const fc::exception& e ) { - elog( "${e}", ("e", e.to_detail_string() ) ); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( create_uia ) -{ - try { +{ try { + asset_id_type test_asset_id { db.get_index().get_next_id() }; asset_create_operation creator; creator.issuer = account_id_type(); @@ -2409,16 +2319,11 @@ BOOST_AUTO_TEST_CASE( create_uia ) BOOST_CHECK_EQUAL( test_asset_id(db).creation_block_num, db.head_block_num() ); BOOST_CHECK( test_asset_id(db).creation_time == db.head_block_time() ); - } catch(fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( update_uia ) -{ - using namespace graphene; - try { +{ try { + INVOKE(create_uia); const auto& test = get_asset(UIA_TEST_SYMBOL); const auto& nathan = create_account("nathan"); @@ -2478,7 +2383,7 @@ BOOST_AUTO_TEST_CASE( update_uia ) issue_op.issue_to_account = nathan.get_id(); trx.operations.push_back(issue_op); PUSH_TX(db, trx, ~0); - + BOOST_TEST_MESSAGE( "Make sure white_list can't be re-enabled (after tokens issued)" ); op.new_options.issuer_permissions = test.options.issuer_permissions; op.new_options.flags = test.options.flags; @@ -2492,18 +2397,11 @@ BOOST_AUTO_TEST_CASE( update_uia ) op.issuer = account_id_type(); GRAPHENE_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception); op.new_issuer.reset(); - } catch(fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( update_uia_issuer ) -{ - using namespace graphene; - using namespace graphene::chain; - using namespace graphene::chain::test; - try { +{ try { // Lambda for creating accounts with 2 different keys auto create_account_2_keys = [&]( const string name, @@ -2619,17 +2517,11 @@ BOOST_AUTO_TEST_CASE( update_uia_issuer ) BOOST_CHECK(test_id(db).issuer == bob_id); - } - catch( const fc::exception& e ) - { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( issue_uia ) -{ - try { +{ try { + INVOKE(create_uia); INVOKE(create_account_test); @@ -2661,15 +2553,12 @@ BOOST_AUTO_TEST_CASE( issue_uia ) BOOST_CHECK(test_dynamic_data.current_supply == 10000000); BOOST_CHECK(test_dynamic_data.accumulated_fees == 0); BOOST_CHECK(test_dynamic_data.fee_pool == 0); - } catch(fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( transfer_uia ) -{ - try { +{ try { + INVOKE(issue_uia); const asset_object& uia = *db.get_index_type().indices().get().find(UIA_TEST_SYMBOL); @@ -2690,15 +2579,12 @@ BOOST_AUTO_TEST_CASE( transfer_uia ) PUSH_TX( db, trx, ~0 ); BOOST_CHECK_EQUAL(get_balance(nathan, uia), 10000000 - 10000); BOOST_CHECK_EQUAL(get_balance(committee, uia), 10000); - } catch(fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( create_buy_uia_multiple_match_new ) { try { + INVOKE( issue_uia ); const asset_object& core_asset = get_asset( UIA_TEST_SYMBOL ); const asset_object& test_asset = get_asset( GRAPHENE_SYMBOL ); @@ -2729,16 +2615,12 @@ BOOST_AUTO_TEST_CASE( create_buy_uia_multiple_match_new ) BOOST_CHECK_EQUAL( get_balance( seller_account, test_asset ), 200 ); BOOST_CHECK_EQUAL( get_balance( buyer_account, core_asset ), 297 ); BOOST_CHECK_EQUAL( core_asset.dynamic_asset_data_id(db).accumulated_fees.value , 3 ); - } - catch ( const fc::exception& e ) - { - elog( "${e}", ("e", e.to_detail_string() ) ); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( create_buy_exact_match_uia ) { try { + INVOKE( issue_uia ); const asset_object& test_asset = get_asset( UIA_TEST_SYMBOL ); const asset_object& core_asset = get_asset( GRAPHENE_SYMBOL ); @@ -2769,17 +2651,13 @@ BOOST_AUTO_TEST_CASE( create_buy_exact_match_uia ) BOOST_CHECK_EQUAL( get_balance( seller_account, test_asset ), 99 ); BOOST_CHECK_EQUAL( get_balance( buyer_account, core_asset ), 100 ); BOOST_CHECK_EQUAL( test_asset.dynamic_asset_data_id(db).accumulated_fees.value , 1 ); - } - catch ( const fc::exception& e ) - { - elog( "${e}", ("e", e.to_detail_string() ) ); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( create_buy_uia_multiple_match_new_reverse ) { try { + INVOKE( issue_uia ); const asset_object& test_asset = get_asset( UIA_TEST_SYMBOL ); const asset_object& core_asset = get_asset( GRAPHENE_SYMBOL ); @@ -2810,16 +2688,12 @@ BOOST_AUTO_TEST_CASE( create_buy_uia_multiple_match_new_reverse ) BOOST_CHECK_EQUAL( get_balance( seller_account, test_asset ), 198 ); BOOST_CHECK_EQUAL( get_balance( buyer_account, core_asset ), 300 ); BOOST_CHECK_EQUAL( test_asset.dynamic_asset_data_id(db).accumulated_fees.value , 2 ); - } - catch ( const fc::exception& e ) - { - elog( "${e}", ("e", e.to_detail_string() ) ); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( create_buy_uia_multiple_match_new_reverse_fract ) { try { + INVOKE( issue_uia ); const asset_object& test_asset = get_asset( UIA_TEST_SYMBOL ); const asset_object& core_asset = get_asset( GRAPHENE_SYMBOL ); @@ -2853,18 +2727,12 @@ BOOST_AUTO_TEST_CASE( create_buy_uia_multiple_match_new_reverse_fract ) BOOST_CHECK_EQUAL( get_balance( buyer_account, core_asset ), 30 ); BOOST_CHECK_EQUAL( get_balance( seller_account, core_asset ), 0 ); BOOST_CHECK_EQUAL( test_asset.dynamic_asset_data_id(db).accumulated_fees.value , 2 ); - } - catch ( const fc::exception& e ) - { - elog( "${e}", ("e", e.to_detail_string() ) ); - throw; - } -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( uia_fees ) -{ - try { +{ try { + INVOKE( issue_uia ); enable_fees(); @@ -2923,14 +2791,12 @@ BOOST_AUTO_TEST_CASE( uia_fees ) BOOST_CHECK_EQUAL(get_balance(committee_account, test_asset), 200); BOOST_CHECK(asset_dynamic.accumulated_fees == fee.amount.value * 3); BOOST_CHECK(asset_dynamic.fee_pool == 1000*prec - core_fee.amount.value * 3); - } catch (fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( cancel_limit_order_test ) { try { + INVOKE( issue_uia ); const asset_object& test_asset = get_asset( UIA_TEST_SYMBOL ); const account_object& buyer_account = create_account( "buyer" ); @@ -2943,18 +2809,12 @@ BOOST_AUTO_TEST_CASE( cancel_limit_order_test ) auto refunded = cancel_limit_order( *sell_order ); BOOST_CHECK( refunded == asset(1000) ); BOOST_CHECK_EQUAL( get_balance(buyer_account, asset_id_type()(db)), 10000 ); - } - catch ( const fc::exception& e ) - { - elog( "${e}", ("e", e.to_detail_string() ) ); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( witness_feeds ) -{ - using namespace graphene::chain; - try { +{ try { + INVOKE( create_mia ); { auto& current = get_asset( "USDBIT" ); @@ -3004,11 +2864,8 @@ BOOST_AUTO_TEST_CASE( witness_feeds ) BOOST_CHECK_EQUAL(bitasset.current_feed.settlement_price.to_real(), 30.0 / GRAPHENE_BLOCKCHAIN_PRECISION); BOOST_CHECK(bitasset.current_feed.maintenance_collateral_ratio == GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO); - } catch (const fc::exception& e) { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } /** * Create an order that cannot be filled immediately and have the @@ -3016,6 +2873,7 @@ BOOST_AUTO_TEST_CASE( witness_feeds ) */ BOOST_AUTO_TEST_CASE( limit_order_fill_or_kill ) { try { + INVOKE(issue_uia); const account_object& nathan = get_account("nathan"); const asset_object& test = get_asset(UIA_TEST_SYMBOL); @@ -3033,6 +2891,7 @@ BOOST_AUTO_TEST_CASE( limit_order_fill_or_kill ) op.fill_or_kill = false; trx.operations.back() = op; PUSH_TX( db, trx, ~0 ); + } FC_LOG_AND_RETHROW() } /// Shameless code coverage plugging. Otherwise, these calls never happen. @@ -3165,9 +3024,8 @@ BOOST_AUTO_TEST_CASE( witness_pay_test ) * can be burned, and all supplies add up. */ BOOST_AUTO_TEST_CASE( reserve_asset_test ) -{ - try - { +{ try { + ACTORS((alice)(bob)(sam)(judge)); const auto& basset = create_bitasset("USDBIT", judge_id); const auto& uasset = create_user_issued_asset(UIA_TEST_SYMBOL); @@ -3238,25 +3096,19 @@ BOOST_AUTO_TEST_CASE( reserve_asset_test ) BOOST_CHECK_EQUAL( get_balance( alice, uasset ), init_balance - reserve_amount ); BOOST_CHECK_EQUAL( (uasset.reserved( db ) - initial_reserve).value, reserve_amount ); verify_asset_supplies(db); - } - catch (fc::exception& e) - { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( call_order_update_evaluator_test ) -{ - try - { +{ try { + ACTORS( (alice) (bob) ); transfer(committee_account, alice_id, asset(10000000 * GRAPHENE_BLOCKCHAIN_PRECISION)); const auto& core = asset_id_type()(db); // attempt to increase current supply beyond max_supply - const auto& bitjmj = create_bitasset( "JMJBIT", alice_id, 100, charge_market_fee, 2U, + const auto& bitjmj = create_bitasset( "JMJBIT", alice_id, 100, charge_market_fee, 2U, asset_id_type{}, GRAPHENE_MAX_SHARE_SUPPLY / 2 ); auto bitjmj_id = bitjmj.get_id(); share_type original_max_supply = bitjmj.options.max_supply; @@ -3291,7 +3143,7 @@ BOOST_AUTO_TEST_CASE( call_order_update_evaluator_test ) BOOST_REQUIRE_GT(newbitjmj.options.max_supply.value, original_max_supply.value); // now try with an asset after the hardfork - const auto& bitusd = create_bitasset( "USDBIT", alice_id, 100, charge_market_fee, 2U, + const auto& bitusd = create_bitasset( "USDBIT", alice_id, 100, charge_market_fee, 2U, asset_id_type{}, GRAPHENE_MAX_SHARE_SUPPLY / 2 ); { @@ -3350,17 +3202,16 @@ BOOST_AUTO_TEST_CASE( call_order_update_evaluator_test ) set_expiration( db, tx ); PUSH_TX( db, tx, database::skip_tapos_check | database::skip_transaction_signatures ); } - } FC_LOG_AND_RETHROW() -} + +} FC_LOG_AND_RETHROW() } /** * This test demonstrates how using the call_order_update_operation to * trigger a margin call is legal if there is a matching order. */ BOOST_AUTO_TEST_CASE( cover_with_collateral_test ) -{ - try - { +{ try { + ACTORS((alice)(bob)(sam)); const auto& bitusd = create_bitasset("USDBIT", sam_id); const auto& core = asset_id_type()(db); @@ -3428,13 +3279,8 @@ BOOST_AUTO_TEST_CASE( cover_with_collateral_test ) BOOST_CHECK( db.find( order1_id ) == nullptr ); BOOST_CHECK( db.find( order2_id ) == nullptr ); - } - catch (fc::exception& e) - { - edump((e.to_detail_string())); - throw; - } -} + +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( vesting_balance_create_test ) { try { From 136007ec09ea3a8e6a78688ebf0c6617a076b23d Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 10 May 2023 14:34:55 +0000 Subject: [PATCH 088/127] Update tests to adapt code changes --- tests/tests/operation_tests.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index b8711d84b0..1aa42f0372 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -134,6 +134,11 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) // Try changing price sell_price.base = asset(501); + // Cannot update base amount in the new price to be more than the amount for sale + GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, sell_price), fc::assert_exception ); + sell_price.base = asset(500); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + sell_price.base = asset(499); update_limit_order(order_id, sell_price); BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); sell_price.base = asset(500); @@ -214,7 +219,7 @@ BOOST_AUTO_TEST_CASE(limit_order_update_match_test) limit_order_id_type order_id_1 = create_sell_order(nathan, asset(999), munee.amount(100), expiration)->get_id(); limit_order_id_type order_id_2 = create_sell_order(nathan, munee.amount(100),asset(1001), expiration)->get_id(); - update_limit_order(order_id_1, price(asset(1001), munee.amount(100)), asset(1)); + update_limit_order(order_id_1, price(asset(1000), munee.amount(99)), asset(1)); BOOST_REQUIRE( !db.find(order_id_1) ); BOOST_REQUIRE_EQUAL(db.find(order_id_2)->amount_for_sale().amount.value, 1); From cf2fca680b0b4f559192f053b0f28b4eacb60d90 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 10 May 2023 16:26:00 +0000 Subject: [PATCH 089/127] Remove mostly useless try/catch wrappers --- libraries/chain/market_evaluator.cpp | 8 ++++---- libraries/protocol/market.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 56e4ed584b..5b49e51133 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -135,7 +135,7 @@ object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_o } FC_CAPTURE_AND_RETHROW( (op) ) } void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_operation& o) -{ try { +{ const database& d = db(); FC_ASSERT( HARDFORK_CORE_1604_PASSED( d.head_block_time() ) , "Operation has not activated yet"); _order = &o.order(d); @@ -214,10 +214,10 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o "The account is not allowed to transact the receiving asset" ); return {}; -} FC_CAPTURE_AND_RETHROW((o)) } +} void_result limit_order_update_evaluator::do_apply(const limit_order_update_operation& o) const -{ try { +{ database& d = db(); // Adjust account balance @@ -247,7 +247,7 @@ void_result limit_order_update_evaluator::do_apply(const limit_order_update_oper d.apply_order(*_order); return {}; -} FC_CAPTURE_AND_RETHROW((o)) } +} void_result limit_order_cancel_evaluator::do_evaluate(const limit_order_cancel_operation& o) { try { diff --git a/libraries/protocol/market.cpp b/libraries/protocol/market.cpp index 62a7593e1e..7f8472cdbc 100644 --- a/libraries/protocol/market.cpp +++ b/libraries/protocol/market.cpp @@ -36,7 +36,7 @@ void limit_order_create_operation::validate()const } void limit_order_update_operation::validate() const -{ try { +{ FC_ASSERT(fee.amount >= 0, "Fee must not be negative"); FC_ASSERT(new_price || delta_amount_to_sell || new_expiration, "Cannot update limit order if nothing is specified to update"); @@ -44,7 +44,7 @@ void limit_order_update_operation::validate() const new_price->validate(); if (delta_amount_to_sell) FC_ASSERT(delta_amount_to_sell->amount != 0, "Cannot change limit order amount by zero"); -} FC_CAPTURE_AND_RETHROW((*this)) } +} void limit_order_cancel_operation::validate()const { From 9160a7e9d08a08435185f048d9c03620ca1b8c82 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 10 May 2023 16:57:40 +0000 Subject: [PATCH 090/127] Add tests for limit_order_update_operation - hard fork time - proposals - order existence - order owner - zero delta --- tests/common/database_fixture.cpp | 16 ++++++++++ tests/common/database_fixture.hpp | 6 ++++ tests/tests/operation_tests.cpp | 51 ++++++++++++++++++++++++++++++- 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 8e2b8243a2..827ead14b9 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -1194,6 +1194,22 @@ const limit_order_object* database_fixture_base::create_sell_order( const accoun return db.find( processed.operation_results[0].get() ); } +limit_order_update_operation database_fixture_base::make_limit_order_update_op( + account_id_type seller_id, + limit_order_id_type order_id, + fc::optional new_price, + fc::optional delta_amount, + fc::optional new_expiration )const +{ + limit_order_update_operation update_order; + update_order.seller = seller_id; + update_order.order = order_id; + update_order.new_price = new_price; + update_order.delta_amount_to_sell = delta_amount; + update_order.new_expiration = new_expiration; + return update_order; +} + void database_fixture_base::update_limit_order(const limit_order_object& order, fc::optional new_price, fc::optional delta_amount, diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index 4e2c05a366..3f5d437bb8 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -417,6 +417,12 @@ struct database_fixture_base { const limit_order_object* create_sell_order( const account_object& user, const asset& amount, const asset& recv, const time_point_sec order_expiration = time_point_sec::maximum(), const price& fee_core_exchange_rate = price::unit_price() ); + limit_order_update_operation make_limit_order_update_op( + account_id_type seller_id, + limit_order_id_type order_id, + fc::optional new_price = {}, + fc::optional delta_amount = {}, + fc::optional new_expiration = {} )const; void update_limit_order(const limit_order_object& order, fc::optional new_price = {}, fc::optional delta_amount = {}, diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 1aa42f0372..01019e0387 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -76,11 +77,43 @@ BOOST_AUTO_TEST_CASE( feed_limit_logic_test ) } FC_LOG_AND_RETHROW() } -BOOST_AUTO_TEST_CASE(limit_order_update_test) +BOOST_AUTO_TEST_CASE( limit_order_update_hardfork_time_test ) { try { + // Proceeds to a recent hard fork + generate_blocks( HARDFORK_CORE_2362_TIME ); + generate_block(); + set_expiration( db, trx ); + ACTORS((nathan)); + const auto& munee = create_user_issued_asset("MUNEE"); + + transfer(committee_account, nathan_id, asset(1500)); + + auto expiration = db.head_block_time() + 1000; + auto sell_price = price(asset(500), munee.amount(1000)); + limit_order_id_type order_id = create_sell_order(nathan, asset(500), munee.amount(1000), expiration)->get_id(); + + BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 500); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + + // Cannot update order yet + sell_price.base = asset(499); + GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, sell_price), fc::assert_exception ); + + // Cannot propose + limit_order_update_operation louop = make_limit_order_update_op( nathan_id, order_id, sell_price ); + BOOST_CHECK_THROW( propose( louop ), fc::exception ); + +} FC_LOG_AND_RETHROW() } + +BOOST_AUTO_TEST_CASE(limit_order_update_test) +{ try { + + ACTORS((nathan)(dan)); + generate_blocks(HARDFORK_CORE_1604_TIME + 10); set_expiration( db, trx ); @@ -120,6 +153,8 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(2), munee.amount(1))), fc::assert_exception); // Cannot update order to expire in the past GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, db.head_block_time() - 10), fc::assert_exception); + // Cannot update order with a zero delta + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset()), fc::assert_exception); // Cannot update order to add more funds than seller has GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(501)), fc::assert_exception); // Cannot update order to remove more funds than order has @@ -132,6 +167,20 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, munee.amount(50)), fc::assert_exception); GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, munee.amount(-50)), fc::assert_exception); + // Cannot update someone else's order + limit_order_update_operation louop = make_limit_order_update_op( dan_id, order_id, {}, asset(-1) ); + trx.operations.clear(); + trx.operations.push_back( louop ); + GRAPHENE_REQUIRE_THROW( PUSH_TX(db, trx, ~0), fc::assert_exception ); + // Can propose + propose( louop ); + + // Cannot update an order which does not exist + louop = make_limit_order_update_op( nathan_id, order_id + 1, {}, asset(-1) ); + trx.operations.clear(); + trx.operations.push_back( louop ); + GRAPHENE_REQUIRE_THROW( PUSH_TX(db, trx, ~0), fc::assert_exception ); + // Try changing price sell_price.base = asset(501); // Cannot update base amount in the new price to be more than the amount for sale From c58db0b714164722cb2eb9bcf829af49431bbd05 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 10 May 2023 17:23:56 +0000 Subject: [PATCH 091/127] Fix potential dereferencing issues in tests --- tests/tests/operation_tests.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 01019e0387..80b7779cab 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -112,11 +112,11 @@ BOOST_AUTO_TEST_CASE( limit_order_update_hardfork_time_test ) BOOST_AUTO_TEST_CASE(limit_order_update_test) { try { - ACTORS((nathan)(dan)); - generate_blocks(HARDFORK_CORE_1604_TIME + 10); set_expiration( db, trx ); + ACTORS((nathan)(dan)); + const auto& bitusd = create_bitasset("USDBIT", nathan_id); const auto& munee = create_user_issued_asset("MUNEE"); const auto& core = asset_id_type()(db); @@ -230,11 +230,11 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) BOOST_AUTO_TEST_CASE(limit_order_update_dust_test) { try { - ACTORS((nathan)); - generate_blocks(HARDFORK_CORE_1604_TIME + 10); set_expiration( db, trx ); + ACTORS((nathan)); + const auto& munee = create_user_issued_asset("MUNEE"); transfer(committee_account, nathan_id, asset(10000)); @@ -254,11 +254,11 @@ BOOST_AUTO_TEST_CASE(limit_order_update_dust_test) BOOST_AUTO_TEST_CASE(limit_order_update_match_test) { try { - ACTORS((nathan)); - generate_blocks(HARDFORK_CORE_1604_TIME + 10); set_expiration( db, trx ); + ACTORS((nathan)); + const auto& munee = create_user_issued_asset("MUNEE"); transfer(committee_account, nathan_id, asset(10000)); @@ -277,11 +277,11 @@ BOOST_AUTO_TEST_CASE(limit_order_update_match_test) BOOST_AUTO_TEST_CASE(limit_order_update_match_test_2) { try { - ACTORS((nathan)); - generate_blocks(HARDFORK_CORE_1604_TIME + 10); set_expiration( db, trx ); + ACTORS((nathan)); + const auto& munee = create_user_issued_asset("MUNEE"); transfer(committee_account, nathan_id, asset(10000)); From 85bef43daa61e370c91c4e6ee23016a60097b5f4 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 10 May 2023 19:04:17 +0000 Subject: [PATCH 092/127] Add asset authorization tests for order_update op --- tests/tests/operation_tests.cpp | 192 ++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 80b7779cab..71e3a533df 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -225,6 +225,192 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) BOOST_REQUIRE_EQUAL(order_id(db).amount_for_sale().amount.value, 500); BOOST_REQUIRE_EQUAL(db.get_balance(nathan_id, core.get_id()).amount.value, 500); + generate_block(); + +} FC_LOG_AND_RETHROW() } + +BOOST_AUTO_TEST_CASE( limit_order_update_asset_authorization_test ) +{ try { + + generate_blocks(HARDFORK_CORE_1604_TIME + 10); + set_expiration( db, trx ); + + ACTORS((nathan)(dan)(whitey)(blacky)); + + const auto& munee = create_user_issued_asset("MUNEE", dan, white_list ); + const auto& noomo = create_user_issued_asset("NOOMO", dan, white_list ); + + issue_uia(nathan, munee.amount(100)); + issue_uia(nathan, noomo.amount(100)); + + auto expiration = db.head_block_time() + 1000; + auto sell_price = price( munee.amount(50), noomo.amount(60) ); + limit_order_id_type order_id = create_sell_order(nathan, munee.amount(50), noomo.amount(60), expiration) + ->get_id(); + BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 50); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + + // Can update order + update_limit_order(order_id, {}, munee.amount(-1)); + BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 49); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + + // Make a whitelist + { + BOOST_TEST_MESSAGE( "Setting up whitelisting" ); + asset_update_operation uop; + uop.asset_to_update = munee.id; + uop.issuer = dan_id; + uop.new_options = munee.options; + // The whitelist is managed by Whitey + uop.new_options.whitelist_authorities.insert(whitey_id); + trx.operations.clear(); + trx.operations.push_back(uop); + PUSH_TX( db, trx, ~0 ); + + // Upgrade Whitey so that he can manage the whitelist + upgrade_to_lifetime_member( whitey_id ); + + // Add Dan to the whitelist, but do not add others + account_whitelist_operation wop; + wop.authorizing_account = whitey_id; + wop.account_to_list = dan_id; + wop.new_listing = account_whitelist_operation::white_listed; + trx.operations.clear(); + trx.operations.push_back(wop); + PUSH_TX( db, trx, ~0 ); + + // Cannot update order + GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, {}, munee.amount(-1)), fc::assert_exception ); + BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 49); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + + // Add Nathan to the whitelist + wop.account_to_list = nathan_id; + wop.new_listing = account_whitelist_operation::white_listed; + trx.operations.clear(); + trx.operations.push_back(wop); + PUSH_TX( db, trx, ~0 ); + + // Can update order + update_limit_order(order_id, {}, munee.amount(-1)); + BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 48); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + } + + // Make a blacklist + { + BOOST_TEST_MESSAGE( "Setting up blacklisting" ); + asset_update_operation uop; + uop.asset_to_update = noomo.id; + uop.issuer = dan_id; + uop.new_options = noomo.options; + // The blacklist is managed by Blacky + uop.new_options.blacklist_authorities.insert(blacky_id); + trx.operations.clear(); + trx.operations.push_back(uop); + PUSH_TX( db, trx, ~0 ); + + // Upgrade Blacky so that he can manage the blacklist + upgrade_to_lifetime_member( blacky_id ); + + // Add Nathan to the blacklist, but do not add others + account_whitelist_operation wop; + wop.authorizing_account = blacky_id; + wop.account_to_list = nathan_id; + wop.new_listing = account_whitelist_operation::black_listed; + trx.operations.clear(); + trx.operations.push_back(wop); + PUSH_TX( db, trx, ~0 ); + + // Cannot update order + GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, {}, munee.amount(-1)), fc::assert_exception ); + BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 48); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + + // Clear blacklist + wop.new_listing = account_whitelist_operation::no_listing; + trx.operations.clear(); + trx.operations.push_back(wop); + PUSH_TX( db, trx, ~0 ); + + // Can update order + update_limit_order(order_id, {}, munee.amount(-1)); + BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 47); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + } + + // Make a market whitelist + { + BOOST_TEST_MESSAGE( "Setting up market whitelisting" ); + asset_update_operation uop; + uop.asset_to_update = munee.id; + uop.issuer = dan_id; + uop.new_options = munee.options; + uop.new_options.whitelist_markets.insert( asset_id_type() ); + trx.operations.clear(); + trx.operations.push_back(uop); + PUSH_TX( db, trx, ~0 ); + + // Cannot update order + GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, {}, munee.amount(-1)), fc::assert_exception ); + BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 47); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + + // Add Noomo to the whitelist + uop.new_options.whitelist_markets.insert( noomo.get_id() ); + trx.operations.clear(); + trx.operations.push_back(uop); + PUSH_TX( db, trx, ~0 ); + + // Can update order + update_limit_order(order_id, {}, munee.amount(-1)); + BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 46); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + } + + // Make a market blacklist + { + BOOST_TEST_MESSAGE( "Setting up market blacklisting" ); + asset_update_operation uop; + uop.asset_to_update = munee.id; + uop.issuer = dan_id; + uop.new_options = munee.options; + uop.new_options.whitelist_markets.clear(); + uop.new_options.blacklist_markets.insert( noomo.get_id() ); + trx.operations.clear(); + trx.operations.push_back(uop); + PUSH_TX( db, trx, ~0 ); + + // Cannot update order + GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, {}, munee.amount(-1)), fc::assert_exception ); + BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 46); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + + // Remove Noomo from the blacklist + uop.new_options.blacklist_markets.erase( noomo.get_id() ); + trx.operations.clear(); + trx.operations.push_back(uop); + PUSH_TX( db, trx, ~0 ); + + // Can update order + update_limit_order(order_id, {}, munee.amount(-1)); + BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 45); + BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); + BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); + } + + generate_block(); + } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(limit_order_update_dust_test) @@ -249,6 +435,8 @@ BOOST_AUTO_TEST_CASE(limit_order_update_dust_test) GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(2000), munee.amount(100)), asset(-985)), fc::assert_exception); + generate_block(); + } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(limit_order_update_match_test) @@ -272,6 +460,8 @@ BOOST_AUTO_TEST_CASE(limit_order_update_match_test) BOOST_REQUIRE( !db.find(order_id_1) ); BOOST_REQUIRE_EQUAL(db.find(order_id_2)->amount_for_sale().amount.value, 1); + generate_block(); + } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(limit_order_update_match_test_2) @@ -295,6 +485,8 @@ BOOST_AUTO_TEST_CASE(limit_order_update_match_test_2) BOOST_REQUIRE( !db.find(order_id_1) ); BOOST_REQUIRE( !db.find(order_id_2) ); + generate_block(); + } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( call_order_update_test ) From afcff0dab2507c4bf3d613fea2c68ceb4fcaf33f Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 10 May 2023 19:45:30 +0000 Subject: [PATCH 093/127] Update a comment and an assertion message --- libraries/chain/market_evaluator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 5b49e51133..bbdb23b5a5 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -143,7 +143,7 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o // Check this is my order FC_ASSERT(o.seller == _order->seller, "Cannot update someone else's order"); - // Check new price is compatible, and determine whether it becomes the best offer on the market + // Check new price is compatible and appropriate if (o.new_price) { auto base_id = o.new_price->base.asset_id; auto quote_id = o.new_price->quote.asset_id; @@ -184,7 +184,7 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o // Check expiration is in the future if (o.new_expiration) - FC_ASSERT( *o.new_expiration >= d.head_block_time(), "Cannot update limit order to expire in the past." ); + FC_ASSERT( *o.new_expiration >= d.head_block_time(), "Cannot update limit order to expire in the past" ); // Check asset authorization // TODO refactor to fix duplicate code (see limit_order_create) From dfce7c64a7b31f7d7ac61f38b2c064c3bbea5369 Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 11 May 2023 20:39:10 +0000 Subject: [PATCH 094/127] Update default order update fee --- libraries/protocol/include/graphene/protocol/market.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/protocol/include/graphene/protocol/market.hpp b/libraries/protocol/include/graphene/protocol/market.hpp index ad3a965df3..bfed55ba1e 100644 --- a/libraries/protocol/include/graphene/protocol/market.hpp +++ b/libraries/protocol/include/graphene/protocol/market.hpp @@ -80,7 +80,7 @@ namespace graphene { namespace protocol { struct limit_order_update_operation : public base_operation { struct fee_params_t { - uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION / 2; + uint64_t fee = ( GRAPHENE_BLOCKCHAIN_PRECISION * 3 ) / 8; }; asset fee; From 8898b5acbd89b658cfd358cd79d34bdf12cab1db Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 11 May 2023 22:24:08 +0000 Subject: [PATCH 095/127] Process operation fees --- .../graphene/chain/market_evaluator.hpp | 19 +++- libraries/chain/market_evaluator.cpp | 106 +++++++++++++++++- 2 files changed, 118 insertions(+), 7 deletions(-) diff --git a/libraries/chain/include/graphene/chain/market_evaluator.hpp b/libraries/chain/include/graphene/chain/market_evaluator.hpp index 61684a765d..6696f62c63 100644 --- a/libraries/chain/include/graphene/chain/market_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/market_evaluator.hpp @@ -42,14 +42,14 @@ namespace graphene { namespace chain { void_result do_evaluate( const limit_order_create_operation& o ); object_id_type do_apply( const limit_order_create_operation& o ) const; - /** override the default behavior defined by generic_evalautor + /** override the default behavior defined by generic_evaluator */ - virtual void convert_fee() override; + void convert_fee() override; - /** override the default behavior defined by generic_evalautor which is to + /** override the default behavior defined by generic_evaluator which is to * post the fee to fee_paying_account_stats.pending_fees */ - virtual void pay_fee() override; + void pay_fee() override; private: share_type _deferred_fee = 0; @@ -67,7 +67,18 @@ namespace graphene { namespace chain { void_result do_evaluate(const limit_order_update_operation& o); void_result do_apply(const limit_order_update_operation& o) const; + /** override the default behavior defined by generic_evaluator + */ + void convert_fee() override; + + /** override the default behavior defined by generic_evaluator which is to + * post the fee to fee_paying_account_stats.pending_fees + */ + void pay_fee() override; + private: + share_type _deferred_fee; + asset _deferred_paid_fee; const limit_order_object* _order = nullptr; }; diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index bbdb23b5a5..e7b1911674 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -33,6 +33,7 @@ #include #include +#include namespace graphene { namespace chain { void_result limit_order_create_evaluator::do_evaluate(const limit_order_create_operation& op) @@ -134,6 +135,23 @@ object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_o return order_id; } FC_CAPTURE_AND_RETHROW( (op) ) } +void limit_order_update_evaluator::convert_fee() +{ + if( !trx_state->skip_fee && fee_asset->get_id() != asset_id_type() ) + { + db().modify(*fee_asset_dyn_data, [this](asset_dynamic_data_object& addo) { + addo.fee_pool -= core_fee_paid; + }); + } +} + +void limit_order_update_evaluator::pay_fee() +{ + _deferred_fee = core_fee_paid; + if( fee_asset->get_id() != asset_id_type() ) + _deferred_paid_fee = fee_from_account; +} + void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_operation& o) { const database& d = db(); @@ -220,27 +238,109 @@ void_result limit_order_update_evaluator::do_apply(const limit_order_update_oper { database& d = db(); + const account_statistics_object* seller_acc_stats = nullptr; + // Adjust account balance if( o.delta_amount_to_sell ) { d.adjust_balance( o.seller, -*o.delta_amount_to_sell ); if( o.delta_amount_to_sell->asset_id == asset_id_type() ) { - const auto& seller_stats = d.get_account_stats_by_owner( o.seller ); - d.modify( seller_stats, [&o]( account_statistics_object& bal ) { + seller_acc_stats = &d.get_account_stats_by_owner( o.seller ); + d.modify( *seller_acc_stats, [&o]( account_statistics_object& bal ) { bal.total_core_in_orders += o.delta_amount_to_sell->amount; }); } } + // Process deferred fee in the order. + // Attempt to deduct a possibly discounted order cancellation fee, and refund the remainder. + // Only deduct fee if there is any fee deferred. + // TODO fix duplicate code (see database::cancel_limit_order()) + if( _order->deferred_fee > 0 ) + { + share_type deferred_fee = _order->deferred_fee; + asset deferred_paid_fee = _order->deferred_paid_fee; + const asset_dynamic_data_object* fee_asset_dyn_data = nullptr; + const auto& current_fees = d.current_fee_schedule(); + asset core_cancel_fee = current_fees.calculate_fee( limit_order_cancel_operation() ); + if( core_cancel_fee.amount > 0 ) + { + // maybe-discounted cancel_fee = limit_order_cancel_fee * limit_order_update_fee / limit_order_create_fee + asset core_create_fee = current_fees.calculate_fee( limit_order_create_operation() ); + fc::uint128_t fee128( core_cancel_fee.amount.value ); + if( core_create_fee.amount > 0 ) + { + asset core_update_fee = current_fees.calculate_fee( limit_order_update_operation() ); + fee128 *= core_update_fee.amount.value; + fee128 /= core_create_fee.amount.value; + } + // cap the fee + if( fee128 > static_cast( deferred_fee.value ) ) + fee128 = deferred_fee.value; + core_cancel_fee.amount = static_cast( fee128 ); + } + // if there is any CORE fee to deduct, redirect it to referral program + if( core_cancel_fee.amount > 0 ) + { + if( !seller_acc_stats ) + seller_acc_stats = &d.get_account_stats_by_owner( o.seller ); + d.modify( *seller_acc_stats, [&core_cancel_fee, &d]( account_statistics_object& obj ) { + obj.pay_fee( core_cancel_fee.amount, d.get_global_properties().parameters.cashback_vesting_threshold ); + } ); + deferred_fee -= core_cancel_fee.amount; + // handle originally paid fee if any: + // to_deduct = round_up( paid_fee * core_cancel_fee / deferred_core_fee_before_deduct ) + if( deferred_paid_fee.amount > 0 ) + { + fc::uint128_t fee128( deferred_paid_fee.amount.value ); + fee128 *= core_cancel_fee.amount.value; + // to round up + fee128 += _order->deferred_fee.value; + fee128 -= 1; + fee128 /= _order->deferred_fee.value; + share_type cancel_fee_amount = static_cast(fee128); + // cancel_fee should be positive, pay it to asset's accumulated_fees + fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); + d.modify( *fee_asset_dyn_data, [&cancel_fee_amount](asset_dynamic_data_object& addo) { + addo.accumulated_fees += cancel_fee_amount; + }); + // cancel_fee should be no more than deferred_paid_fee + deferred_paid_fee.amount -= cancel_fee_amount; + } + } + + // refund fee + if( 0 == _order->deferred_paid_fee.amount ) + { + // be here, order.create_time <= HARDFORK_CORE_604_TIME, or fee paid in CORE, or no fee to refund. + // if order was created before hard fork 604 then cancelled no matter before or after hard fork 604, + // see it as fee paid in CORE, deferred_fee should be refunded to order owner but not fee pool + d.adjust_balance( _order->seller, deferred_fee ); + } + else // need to refund fee in originally paid asset + { + d.adjust_balance( _order->seller, deferred_paid_fee ); + // be here, must have: fee_asset != CORE + if( !fee_asset_dyn_data ) + fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); + d.modify( *fee_asset_dyn_data, [&deferred_fee](asset_dynamic_data_object& addo) { + addo.fee_pool += deferred_fee; + }); + } + + } + // Update order - d.modify(*_order, [&o](limit_order_object& loo) { + d.modify(*_order, [&o,this](limit_order_object& loo) { if (o.new_price) loo.sell_price = *o.new_price; if (o.delta_amount_to_sell) loo.for_sale += o.delta_amount_to_sell->amount; if (o.new_expiration) loo.expiration = *o.new_expiration; + loo.deferred_fee = _deferred_fee; + loo.deferred_paid_fee = _deferred_paid_fee; }); // Perform order matching if necessary From 269a16d19fd29516c72ec6696d9ed5f5f913ccc8 Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 11 May 2023 22:58:26 +0000 Subject: [PATCH 096/127] Reduce log level of exceptions in order_update_op --- libraries/chain/exceptions.cpp | 4 ++ .../include/graphene/chain/exceptions.hpp | 4 ++ libraries/chain/market_evaluator.cpp | 13 ++++- libraries/net/node.cpp | 2 + tests/tests/operation_tests.cpp | 54 +++++++++---------- 5 files changed, 48 insertions(+), 29 deletions(-) diff --git a/libraries/chain/exceptions.cpp b/libraries/chain/exceptions.cpp index 05b3712583..1db241def5 100644 --- a/libraries/chain/exceptions.cpp +++ b/libraries/chain/exceptions.cpp @@ -84,6 +84,10 @@ namespace graphene { namespace chain { GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( insufficient_balance, limit_order_create, 6, "Insufficient balance" ) + GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( limit_order_update ); + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( nonexist_order, limit_order_update, 1, "Order does not exist" ) + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( owner_mismatch, limit_order_update, 2, "Order owned by someone else" ) + GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( limit_order_cancel ); GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( nonexist_order, limit_order_cancel, 1, "Order does not exist" ) GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( owner_mismatch, limit_order_cancel, 2, "Order owned by someone else" ) diff --git a/libraries/chain/include/graphene/chain/exceptions.hpp b/libraries/chain/include/graphene/chain/exceptions.hpp index 07d2968c1f..54d723d9fa 100644 --- a/libraries/chain/include/graphene/chain/exceptions.hpp +++ b/libraries/chain/include/graphene/chain/exceptions.hpp @@ -138,6 +138,10 @@ namespace graphene { namespace chain { GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( receiving_asset_unauthorized, limit_order_create, 5 ) GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( insufficient_balance, limit_order_create, 6 ) + GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_update ); + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( nonexist_order, limit_order_update, 1 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( owner_mismatch, limit_order_update, 2 ) + GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_cancel ); GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( nonexist_order, limit_order_cancel, 1 ) GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( owner_mismatch, limit_order_cancel, 2 ) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index e7b1911674..696180528a 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -156,10 +156,19 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o { const database& d = db(); FC_ASSERT( HARDFORK_CORE_1604_PASSED( d.head_block_time() ) , "Operation has not activated yet"); - _order = &o.order(d); + + _order = d.find( o.order ); + + GRAPHENE_ASSERT( _order != nullptr, + limit_order_update_nonexist_order, + "Limit order ${oid} does not exist, cannot update", + ("oid", o.order) ); // Check this is my order - FC_ASSERT(o.seller == _order->seller, "Cannot update someone else's order"); + GRAPHENE_ASSERT( o.seller == _order->seller, + limit_order_update_owner_mismatch, + "Limit order ${oid} is owned by someone else, cannot update", + ("oid", o.order) ); // Check new price is compatible and appropriate if (o.new_price) { diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index f69bb98cd2..759d46515e 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -3630,6 +3630,8 @@ namespace graphene { namespace net { namespace detail { case graphene::chain::limit_order_create_selling_asset_unauthorized::code_enum::code_value : case graphene::chain::limit_order_create_receiving_asset_unauthorized::code_enum::code_value : case graphene::chain::limit_order_create_insufficient_balance::code_enum::code_value : + case graphene::chain::limit_order_update_nonexist_order::code_enum::code_value : + case graphene::chain::limit_order_update_owner_mismatch::code_enum::code_value : case graphene::chain::limit_order_cancel_nonexist_order::code_enum::code_value : case graphene::chain::limit_order_cancel_owner_mismatch::code_enum::code_value : case graphene::chain::liquidity_pool_exchange_unfillable_price::code_enum::code_value : diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 71e3a533df..aad129cdb2 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -139,39 +139,39 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); // Cannot update order without changing anything - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id), fc::exception); // Cannot update order to use inverted price assets - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(bitusd.amount(2), asset(1))), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(bitusd.amount(2), asset(1))), fc::exception); // Cannot update order to use negative price - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(-1), bitusd.amount(2))), fc::assert_exception); - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(1), bitusd.amount(-2))), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(-1), bitusd.amount(2))), fc::exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(1), bitusd.amount(-2))), fc::exception); // Cannot update order to use different assets GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(bitusd.amount(2), munee.amount(1))), - fc::assert_exception); + fc::exception); GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(munee.amount(2), bitusd.amount(1))), - fc::assert_exception); - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(2), munee.amount(1))), fc::assert_exception); + fc::exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(2), munee.amount(1))), fc::exception); // Cannot update order to expire in the past - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, db.head_block_time() - 10), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, db.head_block_time() - 10), fc::exception); // Cannot update order with a zero delta - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset()), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset()), fc::exception); // Cannot update order to add more funds than seller has - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(501)), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(501)), fc::exception); // Cannot update order to remove more funds than order has - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(-501)), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(-501)), fc::exception); // Cannot update order to remove all funds in order - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(-500)), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(-500)), fc::exception); // Cannot update order to add or remove different kind of funds - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, bitusd.amount(50)), fc::assert_exception); - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, bitusd.amount(-50)), fc::assert_exception); - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, munee.amount(50)), fc::assert_exception); - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, munee.amount(-50)), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, bitusd.amount(50)), fc::exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, bitusd.amount(-50)), fc::exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, munee.amount(50)), fc::exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, munee.amount(-50)), fc::exception); // Cannot update someone else's order limit_order_update_operation louop = make_limit_order_update_op( dan_id, order_id, {}, asset(-1) ); trx.operations.clear(); trx.operations.push_back( louop ); - GRAPHENE_REQUIRE_THROW( PUSH_TX(db, trx, ~0), fc::assert_exception ); + GRAPHENE_REQUIRE_THROW( PUSH_TX(db, trx, ~0), fc::exception ); // Can propose propose( louop ); @@ -179,12 +179,12 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) louop = make_limit_order_update_op( nathan_id, order_id + 1, {}, asset(-1) ); trx.operations.clear(); trx.operations.push_back( louop ); - GRAPHENE_REQUIRE_THROW( PUSH_TX(db, trx, ~0), fc::assert_exception ); + GRAPHENE_REQUIRE_THROW( PUSH_TX(db, trx, ~0), fc::exception ); // Try changing price sell_price.base = asset(501); // Cannot update base amount in the new price to be more than the amount for sale - GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, sell_price), fc::assert_exception ); + GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, sell_price), fc::exception ); sell_price.base = asset(500); BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); sell_price.base = asset(499); @@ -203,7 +203,7 @@ BOOST_AUTO_TEST_CASE(limit_order_update_test) update_limit_order(order_id, {}, {}, expiration); BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); // Cannot change expiration to a time in the past - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, db.head_block_time() - 1 ), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, {}, db.head_block_time() - 1 ), fc::exception); // Try adding funds update_limit_order(order_id, {}, asset(50)); @@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE( limit_order_update_asset_authorization_test ) PUSH_TX( db, trx, ~0 ); // Cannot update order - GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, {}, munee.amount(-1)), fc::assert_exception ); + GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, {}, munee.amount(-1)), fc::exception ); BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 49); BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); @@ -328,7 +328,7 @@ BOOST_AUTO_TEST_CASE( limit_order_update_asset_authorization_test ) PUSH_TX( db, trx, ~0 ); // Cannot update order - GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, {}, munee.amount(-1)), fc::assert_exception ); + GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, {}, munee.amount(-1)), fc::exception ); BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 48); BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); @@ -359,7 +359,7 @@ BOOST_AUTO_TEST_CASE( limit_order_update_asset_authorization_test ) PUSH_TX( db, trx, ~0 ); // Cannot update order - GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, {}, munee.amount(-1)), fc::assert_exception ); + GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, {}, munee.amount(-1)), fc::exception ); BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 47); BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); @@ -391,7 +391,7 @@ BOOST_AUTO_TEST_CASE( limit_order_update_asset_authorization_test ) PUSH_TX( db, trx, ~0 ); // Cannot update order - GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, {}, munee.amount(-1)), fc::assert_exception ); + GRAPHENE_REQUIRE_THROW( update_limit_order(order_id, {}, munee.amount(-1)), fc::exception ); BOOST_REQUIRE_EQUAL(order_id(db).for_sale.value, 46); BOOST_REQUIRE_EQUAL(fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price)); BOOST_REQUIRE_EQUAL(order_id(db).expiration.sec_since_epoch(), expiration.sec_since_epoch()); @@ -429,11 +429,11 @@ BOOST_AUTO_TEST_CASE(limit_order_update_dust_test) auto expiration = db.head_block_time() + 1000; limit_order_id_type order_id = create_sell_order(nathan, asset(1000), munee.amount(100), expiration)->get_id(); - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(-995)), fc::assert_exception); + GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(-995)), fc::exception); GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(1000000), munee.amount(100))), - fc::assert_exception); + fc::exception); GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(2000), munee.amount(100)), asset(-985)), - fc::assert_exception); + fc::exception); generate_block(); From 032f125f2ef511bad354f6a3f8542feed165e26a Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 12 May 2023 08:24:31 +0000 Subject: [PATCH 097/127] Update a comment --- libraries/chain/market_evaluator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 696180528a..e33c990072 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -275,7 +275,8 @@ void_result limit_order_update_evaluator::do_apply(const limit_order_update_oper asset core_cancel_fee = current_fees.calculate_fee( limit_order_cancel_operation() ); if( core_cancel_fee.amount > 0 ) { - // maybe-discounted cancel_fee = limit_order_cancel_fee * limit_order_update_fee / limit_order_create_fee + // maybe-discounted cancel_fee calculation: + // limit_order_cancel_fee * limit_order_update_fee / limit_order_create_fee asset core_create_fee = current_fees.calculate_fee( limit_order_create_operation() ); fc::uint128_t fee128( core_cancel_fee.amount.value ); if( core_create_fee.amount > 0 ) From 663ecd939213b649e5da56af92c3008ec450bf89 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 12 May 2023 14:44:13 +0000 Subject: [PATCH 098/127] Move deferred fee processing code into a function --- .../graphene/chain/market_evaluator.hpp | 5 +- libraries/chain/market_evaluator.cpp | 168 +++++++++--------- 2 files changed, 91 insertions(+), 82 deletions(-) diff --git a/libraries/chain/include/graphene/chain/market_evaluator.hpp b/libraries/chain/include/graphene/chain/market_evaluator.hpp index 6696f62c63..26d90c2298 100644 --- a/libraries/chain/include/graphene/chain/market_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/market_evaluator.hpp @@ -65,7 +65,7 @@ namespace graphene { namespace chain { using operation_type = limit_order_update_operation; void_result do_evaluate(const limit_order_update_operation& o); - void_result do_apply(const limit_order_update_operation& o) const; + void_result do_apply(const limit_order_update_operation& o); /** override the default behavior defined by generic_evaluator */ @@ -77,9 +77,12 @@ namespace graphene { namespace chain { void pay_fee() override; private: + void process_deferred_fee(); + share_type _deferred_fee; asset _deferred_paid_fee; const limit_order_object* _order = nullptr; + const account_statistics_object* _seller_acc_stats = nullptr; }; class limit_order_cancel_evaluator : public evaluator diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index e33c990072..3763bc8dfe 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -243,104 +243,110 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o return {}; } -void_result limit_order_update_evaluator::do_apply(const limit_order_update_operation& o) const +void limit_order_update_evaluator::process_deferred_fee() { - database& d = db(); + // Attempt to deduct a possibly discounted order cancellation fee, and refund the remainder. + // Only deduct fee if there is any fee deferred. + // TODO fix duplicate code (see database::cancel_limit_order()) + if( _order->deferred_fee <= 0 ) + return; - const account_statistics_object* seller_acc_stats = nullptr; + database& d = db(); - // Adjust account balance - if( o.delta_amount_to_sell ) + share_type deferred_fee = _order->deferred_fee; + asset deferred_paid_fee = _order->deferred_paid_fee; + const asset_dynamic_data_object* fee_asset_dyn_data = nullptr; + const auto& current_fees = d.current_fee_schedule(); + asset core_cancel_fee = current_fees.calculate_fee( limit_order_cancel_operation() ); + if( core_cancel_fee.amount > 0 ) { - d.adjust_balance( o.seller, -*o.delta_amount_to_sell ); - if( o.delta_amount_to_sell->asset_id == asset_id_type() ) + // maybe-discounted cancel_fee calculation: + // limit_order_cancel_fee * limit_order_update_fee / limit_order_create_fee + asset core_create_fee = current_fees.calculate_fee( limit_order_create_operation() ); + fc::uint128_t fee128( core_cancel_fee.amount.value ); + if( core_create_fee.amount > 0 ) { - seller_acc_stats = &d.get_account_stats_by_owner( o.seller ); - d.modify( *seller_acc_stats, [&o]( account_statistics_object& bal ) { - bal.total_core_in_orders += o.delta_amount_to_sell->amount; - }); + asset core_update_fee = current_fees.calculate_fee( limit_order_update_operation() ); + fee128 *= core_update_fee.amount.value; + fee128 /= core_create_fee.amount.value; } + // cap the fee + if( fee128 > static_cast( deferred_fee.value ) ) + fee128 = deferred_fee.value; + core_cancel_fee.amount = static_cast( fee128 ); } - // Process deferred fee in the order. - // Attempt to deduct a possibly discounted order cancellation fee, and refund the remainder. - // Only deduct fee if there is any fee deferred. - // TODO fix duplicate code (see database::cancel_limit_order()) - if( _order->deferred_fee > 0 ) + // if there is any CORE fee to deduct, redirect it to referral program + if( core_cancel_fee.amount > 0 ) { - share_type deferred_fee = _order->deferred_fee; - asset deferred_paid_fee = _order->deferred_paid_fee; - const asset_dynamic_data_object* fee_asset_dyn_data = nullptr; - const auto& current_fees = d.current_fee_schedule(); - asset core_cancel_fee = current_fees.calculate_fee( limit_order_cancel_operation() ); - if( core_cancel_fee.amount > 0 ) + if( !_seller_acc_stats ) + _seller_acc_stats = &d.get_account_stats_by_owner( _order->seller ); + d.modify( *_seller_acc_stats, [&core_cancel_fee, &d]( account_statistics_object& obj ) { + obj.pay_fee( core_cancel_fee.amount, d.get_global_properties().parameters.cashback_vesting_threshold ); + } ); + deferred_fee -= core_cancel_fee.amount; + // handle originally paid fee if any: + // to_deduct = round_up( paid_fee * core_cancel_fee / deferred_core_fee_before_deduct ) + if( deferred_paid_fee.amount > 0 ) { - // maybe-discounted cancel_fee calculation: - // limit_order_cancel_fee * limit_order_update_fee / limit_order_create_fee - asset core_create_fee = current_fees.calculate_fee( limit_order_create_operation() ); - fc::uint128_t fee128( core_cancel_fee.amount.value ); - if( core_create_fee.amount > 0 ) - { - asset core_update_fee = current_fees.calculate_fee( limit_order_update_operation() ); - fee128 *= core_update_fee.amount.value; - fee128 /= core_create_fee.amount.value; - } - // cap the fee - if( fee128 > static_cast( deferred_fee.value ) ) - fee128 = deferred_fee.value; - core_cancel_fee.amount = static_cast( fee128 ); - } - // if there is any CORE fee to deduct, redirect it to referral program - if( core_cancel_fee.amount > 0 ) - { - if( !seller_acc_stats ) - seller_acc_stats = &d.get_account_stats_by_owner( o.seller ); - d.modify( *seller_acc_stats, [&core_cancel_fee, &d]( account_statistics_object& obj ) { - obj.pay_fee( core_cancel_fee.amount, d.get_global_properties().parameters.cashback_vesting_threshold ); - } ); - deferred_fee -= core_cancel_fee.amount; - // handle originally paid fee if any: - // to_deduct = round_up( paid_fee * core_cancel_fee / deferred_core_fee_before_deduct ) - if( deferred_paid_fee.amount > 0 ) - { - fc::uint128_t fee128( deferred_paid_fee.amount.value ); - fee128 *= core_cancel_fee.amount.value; - // to round up - fee128 += _order->deferred_fee.value; - fee128 -= 1; - fee128 /= _order->deferred_fee.value; - share_type cancel_fee_amount = static_cast(fee128); - // cancel_fee should be positive, pay it to asset's accumulated_fees - fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); - d.modify( *fee_asset_dyn_data, [&cancel_fee_amount](asset_dynamic_data_object& addo) { - addo.accumulated_fees += cancel_fee_amount; - }); - // cancel_fee should be no more than deferred_paid_fee - deferred_paid_fee.amount -= cancel_fee_amount; - } + fc::uint128_t fee128( deferred_paid_fee.amount.value ); + fee128 *= core_cancel_fee.amount.value; + // to round up + fee128 += _order->deferred_fee.value; + fee128 -= 1; + fee128 /= _order->deferred_fee.value; + share_type cancel_fee_amount = static_cast(fee128); + // cancel_fee should be positive, pay it to asset's accumulated_fees + fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); + d.modify( *fee_asset_dyn_data, [&cancel_fee_amount](asset_dynamic_data_object& addo) { + addo.accumulated_fees += cancel_fee_amount; + }); + // cancel_fee should be no more than deferred_paid_fee + deferred_paid_fee.amount -= cancel_fee_amount; } + } - // refund fee - if( 0 == _order->deferred_paid_fee.amount ) - { - // be here, order.create_time <= HARDFORK_CORE_604_TIME, or fee paid in CORE, or no fee to refund. - // if order was created before hard fork 604 then cancelled no matter before or after hard fork 604, - // see it as fee paid in CORE, deferred_fee should be refunded to order owner but not fee pool - d.adjust_balance( _order->seller, deferred_fee ); - } - else // need to refund fee in originally paid asset + // refund fee + if( 0 == _order->deferred_paid_fee.amount ) + { + // be here, order.create_time <= HARDFORK_CORE_604_TIME, or fee paid in CORE, or no fee to refund. + // if order was created before hard fork 604 then cancelled no matter before or after hard fork 604, + // see it as fee paid in CORE, deferred_fee should be refunded to order owner but not fee pool + d.adjust_balance( _order->seller, deferred_fee ); + } + else // need to refund fee in originally paid asset + { + d.adjust_balance( _order->seller, deferred_paid_fee ); + // be here, must have: fee_asset != CORE + if( !fee_asset_dyn_data ) + fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); + d.modify( *fee_asset_dyn_data, [&deferred_fee](asset_dynamic_data_object& addo) { + addo.fee_pool += deferred_fee; + }); + } + +} + +void_result limit_order_update_evaluator::do_apply(const limit_order_update_operation& o) +{ + database& d = db(); + + // Adjust account balance + if( o.delta_amount_to_sell ) + { + d.adjust_balance( o.seller, -*o.delta_amount_to_sell ); + if( o.delta_amount_to_sell->asset_id == asset_id_type() ) { - d.adjust_balance( _order->seller, deferred_paid_fee ); - // be here, must have: fee_asset != CORE - if( !fee_asset_dyn_data ) - fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); - d.modify( *fee_asset_dyn_data, [&deferred_fee](asset_dynamic_data_object& addo) { - addo.fee_pool += deferred_fee; + _seller_acc_stats = &d.get_account_stats_by_owner( o.seller ); + d.modify( *_seller_acc_stats, [&o]( account_statistics_object& bal ) { + bal.total_core_in_orders += o.delta_amount_to_sell->amount; }); } - } + // Process deferred fee in the order. + process_deferred_fee(); + // Update order d.modify(*_order, [&o,this](limit_order_object& loo) { if (o.new_price) From d3811108ea01ade99c7a9654482b87e11953f1fe Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 12 May 2023 15:48:14 +0000 Subject: [PATCH 099/127] Add tests for order_update fee if paid in CORE --- tests/tests/fee_tests.cpp | 78 +++++++++++++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/tests/tests/fee_tests.cpp b/tests/tests/fee_tests.cpp index fa3c952bf5..497ada3c6d 100644 --- a/tests/tests/fee_tests.cpp +++ b/tests/tests/fee_tests.cpp @@ -733,6 +733,7 @@ BOOST_AUTO_TEST_CASE( fee_refund_test ) issue_uia( bob_id, asset( bob_b0, usd_id ) ); int64_t order_create_fee = 537; + int64_t order_update_fee = 437; int64_t order_cancel_fee = 129; uint32_t skip = database::skip_witness_signature @@ -745,13 +746,19 @@ BOOST_AUTO_TEST_CASE( fee_refund_test ) generate_block( skip ); - for( int i=0; i<2; i++ ) + for( int i=0; i<5; i++ ) { if( i == 1 ) { generate_blocks( HARDFORK_445_TIME, true, skip ); generate_block( skip ); } + else if( i == 2 ) + { + generate_blocks( HARDFORK_CORE_1604_TIME, true, skip ); + generate_block( skip ); + } + // enable_fees() and change_fees() modifies DB directly, and results will be overwritten by block generation // so we have to do it every time we stop generating/popping blocks and start doing tx's @@ -771,6 +778,11 @@ BOOST_AUTO_TEST_CASE( fee_refund_test ) create_fee_params.fee = order_create_fee; new_fees.insert( create_fee_params ); } + { + limit_order_update_operation::fee_params_t update_fee_params; + update_fee_params.fee = order_update_fee; + new_fees.insert( update_fee_params ); + } { limit_order_cancel_operation::fee_params_t cancel_fee_params; cancel_fee_params.fee = order_cancel_fee; @@ -795,6 +807,21 @@ BOOST_AUTO_TEST_CASE( fee_refund_test ) BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_b0 - order_create_fee ); BOOST_CHECK_EQUAL( get_balance( bob_id, usd_id ), bob_b0 - 500 ); + int64_t update_net_fee = order_cancel_fee * order_update_fee / order_create_fee ; + int64_t bob_update_fees = 0; + if( i == 2 ) + { + // Bob updates order + update_limit_order( bo1_id, {}, asset(100, usd_id) ); + + bob_update_fees += update_net_fee; + + BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_b0 - 1000 - order_create_fee ); + BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_b0 ); + BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_b0 - bob_update_fees - order_update_fee ); + BOOST_CHECK_EQUAL( get_balance( bob_id, usd_id ), bob_b0 - 600 ); + } + // Bob cancels order cancel_limit_order( bo1_id(db) ); @@ -806,7 +833,7 @@ BOOST_AUTO_TEST_CASE( fee_refund_test ) BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_b0 - 1000 - order_create_fee ); BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_b0 ); - BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_b0 - cancel_net_fee ); + BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_b0 - bob_update_fees - cancel_net_fee ); BOOST_CHECK_EQUAL( get_balance( bob_id, usd_id ), bob_b0 ); // Alice cancels order @@ -814,27 +841,62 @@ BOOST_AUTO_TEST_CASE( fee_refund_test ) BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_b0 - cancel_net_fee ); BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_b0 ); - BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_b0 - cancel_net_fee ); + BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_b0 - bob_update_fees - cancel_net_fee ); BOOST_CHECK_EQUAL( get_balance( bob_id, usd_id ), bob_b0 ); // Check partial fill const limit_order_object* ao2 = create_sell_order( alice_id, asset(1000), asset(200, usd_id) ); + + BOOST_REQUIRE( ao2 != nullptr ); + + int64_t alice_update_fees = order_create_fee; + int64_t alice_update_amounts = 0; + if( i == 3 ) + { + // Alice updates order + update_limit_order( *ao2, {}, asset(100) ); + + alice_update_fees = update_net_fee + order_update_fee; + alice_update_amounts = 100; + + BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_b0 - cancel_net_fee - alice_update_fees + - 1000 - alice_update_amounts ); + BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_b0 ); + } + const limit_order_object* bo2 = create_sell_order( bob_id, asset(100, usd_id), asset(500) ); - BOOST_CHECK( ao2 != nullptr ); BOOST_CHECK( bo2 == nullptr ); - BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_b0 - cancel_net_fee - order_create_fee - 1000 ); + BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_b0 - cancel_net_fee - alice_update_fees + - 1000 - alice_update_amounts ); BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_b0 + 100 ); - BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_b0 - cancel_net_fee - order_create_fee + 500 ); + BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_b0 - bob_update_fees - cancel_net_fee + - order_create_fee + 500 ); BOOST_CHECK_EQUAL( get_balance( bob_id, usd_id ), bob_b0 - 100 ); + if( i == 4 ) + { + // Alice updates order + update_limit_order( *ao2, {}, asset(100) ); + + BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_b0 - cancel_net_fee - alice_update_fees + - 1000 - alice_update_amounts + - order_update_fee - 100 ); + BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_b0 + 100 ); + BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_b0 - bob_update_fees - cancel_net_fee + - order_create_fee + 500 ); + BOOST_CHECK_EQUAL( get_balance( bob_id, usd_id ), bob_b0 - 100 ); + } + // cancel Alice order, show that entire deferred_fee was consumed by partial match cancel_limit_order( *ao2 ); - BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_b0 - cancel_net_fee - order_create_fee - 500 - order_cancel_fee ); + BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_b0 - cancel_net_fee - alice_update_fees - 500 + - order_cancel_fee ); BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_b0 + 100 ); - BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_b0 - cancel_net_fee - order_create_fee + 500 ); + BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_b0 - bob_update_fees - cancel_net_fee + - order_create_fee + 500 ); BOOST_CHECK_EQUAL( get_balance( bob_id, usd_id ), bob_b0 - 100 ); // TODO: Check multiple fill From 1195df5a73232c4dec4a388ee2ee75c9ff6fb55f Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 12 May 2023 20:16:57 +0000 Subject: [PATCH 100/127] Add tests for order_update fee if not paid in CORE --- tests/common/database_fixture.cpp | 12 +- tests/common/database_fixture.hpp | 6 +- tests/tests/fee_tests.cpp | 334 +++++++++++++++++++++++++----- 3 files changed, 289 insertions(+), 63 deletions(-) diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 827ead14b9..9b0287903c 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -1213,7 +1213,9 @@ limit_order_update_operation database_fixture_base::make_limit_order_update_op( void database_fixture_base::update_limit_order(const limit_order_object& order, fc::optional new_price, fc::optional delta_amount, - fc::optional new_expiration) { + fc::optional new_expiration, + const price& fee_core_exchange_rate ) +{ limit_order_update_operation update_order; update_order.seller = order.seller; update_order.order = order.id; @@ -1221,7 +1223,7 @@ void database_fixture_base::update_limit_order(const limit_order_object& order, update_order.delta_amount_to_sell = delta_amount; update_order.new_expiration = new_expiration; trx.operations = {update_order}; - for(auto& op : trx.operations) db.current_fee_schedule().set_fee(op); + for(auto& op : trx.operations) db.current_fee_schedule().set_fee(op, fee_core_exchange_rate); trx.validate(); auto processed = PUSH_TX(db, trx, ~0); trx.operations.clear(); @@ -1231,8 +1233,10 @@ void database_fixture_base::update_limit_order(const limit_order_object& order, void database_fixture_base::update_limit_order(limit_order_id_type order_id, fc::optional new_price, fc::optional delta_amount, - fc::optional new_expiration) { - update_limit_order(order_id(db), new_price, delta_amount, new_expiration); + fc::optional new_expiration, + const price& fee_core_exchange_rate ) +{ + update_limit_order(order_id(db), new_price, delta_amount, new_expiration, fee_core_exchange_rate); } asset database_fixture_base::cancel_limit_order( const limit_order_object& order ) diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index 3f5d437bb8..2a876dde30 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -426,11 +426,13 @@ struct database_fixture_base { void update_limit_order(const limit_order_object& order, fc::optional new_price = {}, fc::optional delta_amount = {}, - fc::optional new_expiration = {}); + fc::optional new_expiration = {}, + const price& fee_core_exchange_rate = price::unit_price() ); void update_limit_order(limit_order_id_type order_id, fc::optional new_price = {}, fc::optional delta_amount = {}, - fc::optional new_expiration = {}); + fc::optional new_expiration = {}, + const price& fee_core_exchange_rate = price::unit_price() ); asset cancel_limit_order( const limit_order_object& order ); void transfer( account_id_type from, account_id_type to, const asset& amount, const asset& fee = asset() ); void transfer( const account_object& from, const account_object& to, const asset& amount, const asset& fee = asset() ); diff --git a/tests/tests/fee_tests.cpp b/tests/tests/fee_tests.cpp index 497ada3c6d..4af3568568 100644 --- a/tests/tests/fee_tests.cpp +++ b/tests/tests/fee_tests.cpp @@ -983,7 +983,8 @@ BOOST_AUTO_TEST_CASE( non_core_fee_refund_test ) // prepare params uint32_t blocks_generated = 0; time_point_sec max_exp = time_point_sec::maximum(); - time_point_sec exp = db.head_block_time(); // order will be accepted when pushing trx then expired at current block + time_point_sec exp = db.head_block_time(); // order will be accepted when pushing trx then + // expired at current block price cer( asset(1), asset(1, usd_id) ); const auto* usd_stat = &usd_id( db ).dynamic_asset_data_id( db ); @@ -1090,10 +1091,10 @@ BOOST_AUTO_TEST_CASE( non_core_fee_refund_test ) // Check partial fill const limit_order_object* ao2 = create_sell_order( alice_id, asset(1000), asset(200, usd_id), exp, cer ); - const limit_order_id_type ao2id = ao2->get_id(); + const limit_order_id_type ao2_id = ao2->get_id(); const limit_order_object* bo2 = create_sell_order( bob_id, asset(100, usd_id), asset(500) ); - BOOST_CHECK( db.find( ao2id ) != nullptr ); + BOOST_CHECK( db.find( ao2_id ) != nullptr ); BOOST_CHECK( bo2 == nullptr ); // data after order created @@ -1826,6 +1827,7 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) fund_fee_pool( committee_account( db ), usd_obj, pool_0 ); int64_t order_create_fee = 547; + int64_t order_update_fee = 487; int64_t order_cancel_fee; int64_t order_cancel_fee1 = 139; int64_t order_cancel_fee2 = 829; @@ -1849,6 +1851,12 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) new_fees1.insert( create_fee_params ); new_fees2.insert( create_fee_params ); } + { + limit_order_update_operation::fee_params_t update_fee_params; + update_fee_params.fee = order_update_fee; + new_fees1.insert( update_fee_params ); + new_fees2.insert( update_fee_params ); + } { limit_order_cancel_operation::fee_params_t cancel_fee_params; cancel_fee_params.fee = order_cancel_fee1; @@ -1867,13 +1875,14 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) new_fees2.insert( transfer_fee_params ); } - for( int i=0; i<12; i++ ) + for( int i=0; i<16; i++ ) { bool expire_order = ( i % 2 != 0 ); bool high_cancel_fee = ( i % 4 >= 2 ); bool before_hardfork_445 = ( i < 4 ); bool after_bsip26 = ( i >= 8 ); - idump( (before_hardfork_445)(after_bsip26)(expire_order)(high_cancel_fee) ); + bool after_core_hf1604 = ( i >= 12 ); + idump( (before_hardfork_445)(after_bsip26)(after_core_hf1604)(expire_order)(high_cancel_fee) ); if( i == 4 ) { BOOST_TEST_MESSAGE( "Hard fork 445" ); @@ -1886,6 +1895,12 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) generate_blocks( HARDFORK_CORE_604_TIME, true, skip ); generate_block( skip ); } + else if( i == 12 ) + { + BOOST_TEST_MESSAGE( "Hard fork core-1604" ); + generate_blocks( HARDFORK_CORE_1604_TIME, true, skip ); + generate_block( skip ); + } if( high_cancel_fee ) { @@ -1900,9 +1915,12 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) int64_t usd_create_fee = order_create_fee * cer_usd_amount / cer_core_amount; if( usd_create_fee * cer_core_amount != order_create_fee * cer_usd_amount ) usd_create_fee += 1; + int64_t usd_update_fee = order_update_fee * cer_usd_amount / cer_core_amount; + if( usd_update_fee * cer_core_amount != order_update_fee * cer_usd_amount ) usd_update_fee += 1; int64_t usd_cancel_fee = order_cancel_fee * cer_usd_amount / cer_core_amount; if( usd_cancel_fee * cer_core_amount != order_cancel_fee * cer_usd_amount ) usd_cancel_fee += 1; int64_t core_create_fee = usd_create_fee * cer_core_amount / cer_usd_amount; + int64_t core_update_fee = usd_update_fee * cer_core_amount / cer_usd_amount; int64_t core_cancel_fee = usd_cancel_fee * cer_core_amount / cer_usd_amount; BOOST_CHECK( core_cancel_fee >= order_cancel_fee ); @@ -1919,7 +1937,8 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) // prepare params uint32_t blocks_generated = 0; time_point_sec max_exp = time_point_sec::maximum(); - time_point_sec exp = db.head_block_time(); // order will be accepted when pushing trx then expired at current block + time_point_sec exp = db.head_block_time(); // order will be accepted when pushing trx then + // expired at current block price cer = usd_id( db ).options.core_exchange_rate; const auto* usd_stat = &usd_id( db ).dynamic_asset_data_id( db ); @@ -1966,6 +1985,15 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) accum_on_fill = 0; pool_refund = 0; } + // refund data related to order update + int64_t core_update_fee_refund_core = order_update_fee; + int64_t core_update_fee_refund_usd = 0; + int64_t usd_update_fee_refund_core = 0; + int64_t usd_update_fee_refund_usd = usd_update_fee; + int64_t accum_on_fill_after_update = usd_update_fee; + int64_t pool_refund_after_update = core_update_fee; + + int64_t update_net_fee = order_cancel_fee * order_update_fee / order_create_fee; // Check non-overlapping // Alice creates order @@ -1984,6 +2012,27 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) BOOST_CHECK_EQUAL( usd_stat->fee_pool.value, pool_b ); BOOST_CHECK_EQUAL( usd_stat->accumulated_fees.value, accum_b ); + // Alice updates order + if( after_core_hf1604 ) + { + BOOST_TEST_MESSAGE( "Update order ao1" ); + update_limit_order( ao1_id, {}, asset(100), {}, cer ); + + alice_bc -= 100; // delta + alice_bu -= usd_update_fee; // fee + pool_b -= core_update_fee; // pool fee + + alice_bc += order_create_fee; // refund + alice_bc -= std::min( order_create_fee, update_net_fee ); // charge a fee (adjusted cancel_fee, capped) + + BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_bc ); + BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_bu ); + BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_bc ); + BOOST_CHECK_EQUAL( get_balance( bob_id, usd_id ), bob_bu ); + BOOST_CHECK_EQUAL( usd_stat->fee_pool.value, pool_b ); + BOOST_CHECK_EQUAL( usd_stat->accumulated_fees.value, accum_b ); + } + // Alice cancels order if( !expire_order ) { @@ -2013,25 +2062,55 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) transfer( account_id_type(), bob_id, asset( bob_bu, usd_id) ); } - - if( !expire_order ) - alice_bc -= order_cancel_fee; // manual cancellation always need a fee - else if( before_hardfork_445 ) - { // do nothing: before hard fork 445, no fee on expired order - } - else if( !after_bsip26 ) + if( after_core_hf1604 ) { - // charge a cancellation fee in core, capped by deffered_fee which is order_create_fee - alice_bc -= std::min( order_cancel_fee, order_create_fee ); + if( !expire_order ) + alice_bc -= order_cancel_fee; // manual cancellation always need a fee + else // bsip26 + { + // when expired, should have core_update_fee in deferred, usd_update_fee in deferred_paid + + // charge a cancellation fee in core from fee_pool, capped by deffered + int64_t capped_core_cancel_fee = std::min( order_cancel_fee, core_update_fee ); + pool_b -= capped_core_cancel_fee; + + // charge a coresponding cancellation fee in usd from deffered_paid, round up, capped + int64_t capped_usd_cancel_fee = capped_core_cancel_fee * usd_update_fee / core_update_fee; + if( capped_usd_cancel_fee * core_update_fee != capped_core_cancel_fee * usd_update_fee ) + capped_usd_cancel_fee += 1; + if( capped_usd_cancel_fee > usd_update_fee ) + capped_usd_cancel_fee = usd_update_fee; + alice_bu -= capped_usd_cancel_fee; + + // cancellation fee goes to accumulated fees + accum_b += capped_usd_cancel_fee; + } + alice_bc += 100; // delta + alice_bc += usd_update_fee_refund_core; + alice_bu += usd_update_fee_refund_usd; + pool_b += pool_refund_after_update; } - else // bsip26 + else { - // charge a cancellation fee in core, capped by deffered_fee which is order_create_fee - alice_bc -= std::min( order_cancel_fee, order_create_fee ); + if( !expire_order ) + alice_bc -= order_cancel_fee; // manual cancellation always need a fee + else if( before_hardfork_445 ) + { // do nothing: before hard fork 445, no fee on expired order + } + else if( !after_bsip26 ) + { + // charge a cancellation fee in core, capped by deffered_fee which is order_create_fee + alice_bc -= std::min( order_cancel_fee, order_create_fee ); + } + else // bsip26 + { + // charge a cancellation fee in core, capped by deffered_fee which is order_create_fee + alice_bc -= std::min( order_cancel_fee, order_create_fee ); + } + alice_bc += core_fee_refund_core; + alice_bu += core_fee_refund_usd; } alice_bc += 1000; - alice_bc += core_fee_refund_core; - alice_bu += core_fee_refund_usd; BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_bc ); BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_bu ); @@ -2056,6 +2135,44 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) BOOST_CHECK_EQUAL( usd_stat->fee_pool.value, pool_b ); BOOST_CHECK_EQUAL( usd_stat->accumulated_fees.value, accum_b ); + // Bob updates order + if( after_core_hf1604 ) + { + BOOST_TEST_MESSAGE( "Update order bo1" ); + update_limit_order( bo1_id, {}, asset(100, usd_id) ); + + bob_bu -= 100; // delta + bob_bc -= order_update_fee; // fee + + // there should have core_create_fee in deferred, usd_create_fee in deferred_paid + + // refund + pool_b += core_create_fee; + bob_bu += usd_create_fee; + + // charge an adjusted cancellation fee in core from fee_pool, capped by deffered + int64_t capped_core_cancel_fee = std::min( update_net_fee, core_create_fee ); + pool_b -= capped_core_cancel_fee; + + // charge a coresponding cancellation fee in usd from deffered_paid, round up, capped + int64_t capped_usd_cancel_fee = capped_core_cancel_fee * usd_create_fee / core_create_fee; + if( capped_usd_cancel_fee * core_create_fee != capped_core_cancel_fee * usd_create_fee ) + capped_usd_cancel_fee += 1; + if( capped_usd_cancel_fee > usd_create_fee ) + capped_usd_cancel_fee = usd_create_fee; + bob_bu -= capped_usd_cancel_fee; + + // cancellation fee goes to accumulated fees + accum_b += capped_usd_cancel_fee; + + BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_bc ); + BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_bu ); + BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_bc ); + BOOST_CHECK_EQUAL( get_balance( bob_id, usd_id ), bob_bu ); + BOOST_CHECK_EQUAL( usd_stat->fee_pool.value, pool_b ); + BOOST_CHECK_EQUAL( usd_stat->accumulated_fees.value, accum_b ); + } + // Bob cancels order if( !expire_order ) { @@ -2085,22 +2202,93 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) transfer( account_id_type(), bob_id, asset( bob_bu, usd_id) ); } - if( !expire_order ) - bob_bc -= order_cancel_fee; // manual cancellation always need a fee - else if( before_hardfork_445 ) - { // do nothing: before hard fork 445, no fee on expired order + if( after_core_hf1604 ) + { + if( !expire_order ) + bob_bc -= order_cancel_fee; // manual cancellation always need a fee + else + { + // charge a cancellation fee in core, capped by deffered_fee which is order_update_fee + bob_bc -= std::min( order_cancel_fee, order_update_fee ); + } + bob_bu += 100; // delta + bob_bc += core_update_fee_refund_core; + bob_bu += core_update_fee_refund_usd; } - else if( !after_bsip26 ) + else { - // charge a cancellation fee in core, capped by deffered_fee which is core_create_fee - bob_bc -= std::min( order_cancel_fee, core_create_fee ); + if( !expire_order ) + bob_bc -= order_cancel_fee; // manual cancellation always need a fee + else if( before_hardfork_445 ) + { // do nothing: before hard fork 445, no fee on expired order + } + else if( !after_bsip26 ) + { + // charge a cancellation fee in core, capped by deffered_fee which is core_create_fee + bob_bc -= std::min( order_cancel_fee, core_create_fee ); + } + else // bsip26 + { + // when expired, should have core_create_fee in deferred, usd_create_fee in deferred_paid + + // charge a cancellation fee in core from fee_pool, capped by deffered + int64_t capped_core_cancel_fee = std::min( order_cancel_fee, core_create_fee ); + pool_b -= capped_core_cancel_fee; + + // charge a coresponding cancellation fee in usd from deffered_paid, round up, capped + int64_t capped_usd_cancel_fee = capped_core_cancel_fee * usd_create_fee / core_create_fee; + if( capped_usd_cancel_fee * core_create_fee != capped_core_cancel_fee * usd_create_fee ) + capped_usd_cancel_fee += 1; + if( capped_usd_cancel_fee > usd_create_fee ) + capped_usd_cancel_fee = usd_create_fee; + bob_bu -= capped_usd_cancel_fee; + + // cancellation fee goes to accumulated fees + accum_b += capped_usd_cancel_fee; + } + bob_bc += usd_fee_refund_core; + bob_bu += usd_fee_refund_usd; + pool_b += pool_refund; // bo1 } - else // bsip26 + bob_bu += 500; + + BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_bc ); + BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_bu ); + BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_bc ); + BOOST_CHECK_EQUAL( get_balance( bob_id, usd_id ), bob_bu ); + BOOST_CHECK_EQUAL( usd_stat->fee_pool.value, pool_b ); + BOOST_CHECK_EQUAL( usd_stat->accumulated_fees.value, accum_b ); + + + // Check partial fill + BOOST_TEST_MESSAGE( "Creating ao2" ); + const limit_order_object* ao2 = create_sell_order( alice_id, asset(1000), asset(200, usd_id), exp, cer ); + const limit_order_id_type ao2_id = ao2->get_id(); + + // data after order created + alice_bc -= 1000; + alice_bu -= usd_create_fee; + pool_b -= core_create_fee; + accum_b += accum_on_new; + + // Alice updates order + if( after_core_hf1604 ) { - // when expired, should have core_create_fee in deferred, usd_create_fee in deferred_paid + BOOST_TEST_MESSAGE( "Update order ao2" ); + update_limit_order( ao2_id, {}, asset(100), {}, cer ); + + alice_bc -= 100; // delta + alice_bu -= usd_update_fee; // fee + pool_b -= core_update_fee; // pool fee - // charge a cancellation fee in core from fee_pool, capped by deffered - int64_t capped_core_cancel_fee = std::min( order_cancel_fee, core_create_fee ); + // there should have core_create_fee in deferred, usd_create_fee in deferred_paid + + // refund + pool_b += core_create_fee; + alice_bu += usd_create_fee; + + // charge an adjusted cancellation fee in core from fee_pool, capped by deffered + int64_t capped_core_cancel_fee = std::min( update_net_fee, core_create_fee ); pool_b -= capped_core_cancel_fee; // charge a coresponding cancellation fee in usd from deffered_paid, round up, capped @@ -2109,45 +2297,75 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) capped_usd_cancel_fee += 1; if( capped_usd_cancel_fee > usd_create_fee ) capped_usd_cancel_fee = usd_create_fee; - bob_bu -= capped_usd_cancel_fee; + alice_bu -= capped_usd_cancel_fee; // cancellation fee goes to accumulated fees accum_b += capped_usd_cancel_fee; + + BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_bc ); + BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_bu ); + BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_bc ); + BOOST_CHECK_EQUAL( get_balance( bob_id, usd_id ), bob_bu ); + BOOST_CHECK_EQUAL( usd_stat->fee_pool.value, pool_b ); + BOOST_CHECK_EQUAL( usd_stat->accumulated_fees.value, accum_b ); } - bob_bc += usd_fee_refund_core; - bob_bu += 500; - bob_bu += usd_fee_refund_usd; - pool_b += pool_refund; // bo1 - BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_bc ); - BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_bu ); - BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_bc ); - BOOST_CHECK_EQUAL( get_balance( bob_id, usd_id ), bob_bu ); - BOOST_CHECK_EQUAL( usd_stat->fee_pool.value, pool_b ); - BOOST_CHECK_EQUAL( usd_stat->accumulated_fees.value, accum_b ); + // Alice updates order again + if( after_core_hf1604 ) + { + BOOST_TEST_MESSAGE( "Update order ao2 again" ); + update_limit_order( ao2_id, {}, asset(100), {}, cer ); + alice_bc -= 100; // delta + alice_bu -= usd_update_fee; // fee + pool_b -= core_update_fee; // pool fee - // Check partial fill - BOOST_TEST_MESSAGE( "Creating ao2, then be partially filled by bo2" ); - const limit_order_object* ao2 = create_sell_order( alice_id, asset(1000), asset(200, usd_id), exp, cer ); - const limit_order_id_type ao2id = ao2->get_id(); + // there should have core_update_fee in deferred, usd_update_fee in deferred_paid + + // refund + pool_b += core_update_fee; + alice_bu += usd_update_fee; + + // charge an adjusted cancellation fee in core from fee_pool, capped by deffered + int64_t capped_core_cancel_fee = std::min( update_net_fee, core_update_fee ); + pool_b -= capped_core_cancel_fee; + + // charge a coresponding cancellation fee in usd from deffered_paid, round up, capped + int64_t capped_usd_cancel_fee = capped_core_cancel_fee * usd_update_fee / core_update_fee; + if( capped_usd_cancel_fee * core_update_fee != capped_core_cancel_fee * usd_update_fee ) + capped_usd_cancel_fee += 1; + if( capped_usd_cancel_fee > usd_update_fee ) + capped_usd_cancel_fee = usd_update_fee; + alice_bu -= capped_usd_cancel_fee; + + // cancellation fee goes to accumulated fees + accum_b += capped_usd_cancel_fee; + + BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_bc ); + BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_bu ); + BOOST_CHECK_EQUAL( get_balance( bob_id, core_id ), bob_bc ); + BOOST_CHECK_EQUAL( get_balance( bob_id, usd_id ), bob_bu ); + BOOST_CHECK_EQUAL( usd_stat->fee_pool.value, pool_b ); + BOOST_CHECK_EQUAL( usd_stat->accumulated_fees.value, accum_b ); + } + + BOOST_TEST_MESSAGE( "Creating bo2, partially fill ao2" ); const limit_order_object* bo2 = create_sell_order( bob_id, asset(100, usd_id), asset(500) ); - BOOST_CHECK( db.find( ao2id ) != nullptr ); + BOOST_CHECK( db.find( ao2_id ) != nullptr ); BOOST_CHECK( bo2 == nullptr ); // data after order created - alice_bc -= 1000; - alice_bu -= usd_create_fee; - pool_b -= core_create_fee; - accum_b += accum_on_new; bob_bc -= order_create_fee; bob_bu -= 100; // data after order filled alice_bu += 100; bob_bc += 500; - accum_b += accum_on_fill; // ao2 + if( after_core_hf1604 ) + accum_b += accum_on_fill_after_update; // ao2 + else + accum_b += accum_on_fill; // ao2 BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_bc ); BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_bu ); @@ -2192,6 +2410,8 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) // before hard fork 445, no fee when order is expired; // after hard fork 445, when partially filled order expired, order cancel fee is capped at 0 alice_bc += 500; + if( after_core_hf1604 ) + alice_bc += 200; // delta * 2 BOOST_CHECK_EQUAL( get_balance( alice_id, core_id ), alice_bc ); BOOST_CHECK_EQUAL( get_balance( alice_id, usd_id ), alice_bu ); @@ -2203,11 +2423,11 @@ BOOST_AUTO_TEST_CASE( bsip26_fee_refund_test ) // Check multiple fill // Alice creating multiple orders BOOST_TEST_MESSAGE( "Creating ao31-ao35" ); - const limit_order_object* ao31 = create_sell_order( alice_id, asset(1000), asset(200, usd_id), max_exp, cer ); - const limit_order_object* ao32 = create_sell_order( alice_id, asset(1000), asset(2000, usd_id), max_exp, cer ); - const limit_order_object* ao33 = create_sell_order( alice_id, asset(1000), asset(200, usd_id), max_exp, cer ); - const limit_order_object* ao34 = create_sell_order( alice_id, asset(1000), asset(200, usd_id), max_exp, cer ); - const limit_order_object* ao35 = create_sell_order( alice_id, asset(1000), asset(200, usd_id), max_exp, cer ); + const limit_order_object* ao31 = create_sell_order( alice_id, asset(1000), asset(200, usd_id), max_exp, cer); + const limit_order_object* ao32 = create_sell_order( alice_id, asset(1000), asset(2000,usd_id), max_exp, cer); + const limit_order_object* ao33 = create_sell_order( alice_id, asset(1000), asset(200, usd_id), max_exp, cer); + const limit_order_object* ao34 = create_sell_order( alice_id, asset(1000), asset(200, usd_id), max_exp, cer); + const limit_order_object* ao35 = create_sell_order( alice_id, asset(1000), asset(200, usd_id), max_exp, cer); const limit_order_id_type ao31id = ao31->get_id(); const limit_order_id_type ao32id = ao32->get_id(); From 2a34e1bd17725eae5f25724bd368b95b2e0b7ca2 Mon Sep 17 00:00:00 2001 From: abitmore Date: Mon, 15 May 2023 15:55:00 +0000 Subject: [PATCH 101/127] Update variable names to fix variable shadowing --- libraries/chain/db_market.cpp | 12 ++++++------ libraries/chain/market_evaluator.cpp | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index 66c74cc48d..a31851ceca 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -537,7 +537,7 @@ void database::cancel_limit_order( const limit_order_object& order, bool create_ // 1. due to expiration: always deduct a fee if there is any fee deferred // 2. due to cull_small: deduct a fee after hard fork 604, but not before (will set skip_cancel_fee) const account_statistics_object* seller_acc_stats = nullptr; - const asset_dynamic_data_object* fee_asset_dyn_data = nullptr; + const asset_dynamic_data_object* deferred_fee_asset_dyn_data = nullptr; limit_order_cancel_operation vop; share_type deferred_fee = order.deferred_fee; asset deferred_paid_fee = order.deferred_paid_fee; @@ -576,8 +576,8 @@ void database::cancel_limit_order( const limit_order_object& order, bool create_ fee128 /= order.deferred_fee.value; share_type cancel_fee_amount = static_cast(fee128); // cancel_fee should be positive, pay it to asset's accumulated_fees - fee_asset_dyn_data = &deferred_paid_fee.asset_id(*this).dynamic_asset_data_id(*this); - modify( *fee_asset_dyn_data, [&cancel_fee_amount](asset_dynamic_data_object& addo) { + deferred_fee_asset_dyn_data = &deferred_paid_fee.asset_id(*this).dynamic_asset_data_id(*this); + modify( *deferred_fee_asset_dyn_data, [&cancel_fee_amount](asset_dynamic_data_object& addo) { addo.accumulated_fees += cancel_fee_amount; }); // cancel_fee should be no more than deferred_paid_fee @@ -613,9 +613,9 @@ void database::cancel_limit_order( const limit_order_object& order, bool create_ { adjust_balance(order.seller, deferred_paid_fee); // be here, must have: fee_asset != CORE - if( !fee_asset_dyn_data ) - fee_asset_dyn_data = &deferred_paid_fee.asset_id(*this).dynamic_asset_data_id(*this); - modify( *fee_asset_dyn_data, [&](asset_dynamic_data_object& addo) { + if( !deferred_fee_asset_dyn_data ) + deferred_fee_asset_dyn_data = &deferred_paid_fee.asset_id(*this).dynamic_asset_data_id(*this); + modify( *deferred_fee_asset_dyn_data, [&deferred_fee](asset_dynamic_data_object& addo) { addo.fee_pool += deferred_fee; }); } diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 3763bc8dfe..a239d89a1c 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -255,7 +255,7 @@ void limit_order_update_evaluator::process_deferred_fee() share_type deferred_fee = _order->deferred_fee; asset deferred_paid_fee = _order->deferred_paid_fee; - const asset_dynamic_data_object* fee_asset_dyn_data = nullptr; + const asset_dynamic_data_object* deferred_fee_asset_dyn_data = nullptr; const auto& current_fees = d.current_fee_schedule(); asset core_cancel_fee = current_fees.calculate_fee( limit_order_cancel_operation() ); if( core_cancel_fee.amount > 0 ) @@ -297,8 +297,8 @@ void limit_order_update_evaluator::process_deferred_fee() fee128 /= _order->deferred_fee.value; share_type cancel_fee_amount = static_cast(fee128); // cancel_fee should be positive, pay it to asset's accumulated_fees - fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); - d.modify( *fee_asset_dyn_data, [&cancel_fee_amount](asset_dynamic_data_object& addo) { + deferred_fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); + d.modify( *deferred_fee_asset_dyn_data, [&cancel_fee_amount](asset_dynamic_data_object& addo) { addo.accumulated_fees += cancel_fee_amount; }); // cancel_fee should be no more than deferred_paid_fee @@ -318,9 +318,9 @@ void limit_order_update_evaluator::process_deferred_fee() { d.adjust_balance( _order->seller, deferred_paid_fee ); // be here, must have: fee_asset != CORE - if( !fee_asset_dyn_data ) - fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); - d.modify( *fee_asset_dyn_data, [&deferred_fee](asset_dynamic_data_object& addo) { + if( !deferred_fee_asset_dyn_data ) + deferred_fee_asset_dyn_data = &deferred_paid_fee.asset_id(d).dynamic_asset_data_id(d); + d.modify( *deferred_fee_asset_dyn_data, [&deferred_fee](asset_dynamic_data_object& addo) { addo.fee_pool += deferred_fee; }); } From 126987e61c1fae3df47b6ee23d2ff5f63128a323 Mon Sep 17 00:00:00 2001 From: abitmore Date: Mon, 15 May 2023 16:20:10 +0000 Subject: [PATCH 102/127] Update a comment --- libraries/chain/market_evaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index a239d89a1c..886d5bc26c 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -310,7 +310,7 @@ void limit_order_update_evaluator::process_deferred_fee() if( 0 == _order->deferred_paid_fee.amount ) { // be here, order.create_time <= HARDFORK_CORE_604_TIME, or fee paid in CORE, or no fee to refund. - // if order was created before hard fork 604 then cancelled no matter before or after hard fork 604, + // if order was created before hard fork 604, // see it as fee paid in CORE, deferred_fee should be refunded to order owner but not fee pool d.adjust_balance( _order->seller, deferred_fee ); } From 6636959b103e3e70721d89963cecec3290a352e8 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 16 May 2023 20:15:22 +0000 Subject: [PATCH 103/127] Fix code smells --- libraries/chain/asset_evaluator.cpp | 78 +++++++++---------- .../graphene/chain/asset_evaluator.hpp | 20 +++-- .../chain/liquidity_pool_evaluator.hpp | 18 +++-- libraries/chain/liquidity_pool_evaluator.cpp | 26 +++---- .../include/graphene/protocol/market.hpp | 4 +- libraries/utilities/elasticsearch.cpp | 2 +- 6 files changed, 81 insertions(+), 67 deletions(-) diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index b56de7601a..8fbeba326b 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -182,7 +182,7 @@ namespace detail { } // graphene::chain::detail -void_result asset_create_evaluator::do_evaluate( const asset_create_operation& op ) +void_result asset_create_evaluator::do_evaluate( const asset_create_operation& op ) const { try { const database& d = db(); @@ -235,11 +235,11 @@ void_result asset_create_evaluator::do_evaluate( const asset_create_operation& o if( dotpos != std::string::npos ) { auto prefix = op.symbol.substr( 0, dotpos ); - auto asset_symbol_itr = asset_indx.find( prefix ); - FC_ASSERT( asset_symbol_itr != asset_indx.end(), + auto asset_prefix_itr = asset_indx.find( prefix ); + FC_ASSERT( asset_prefix_itr != asset_indx.end(), "Asset ${s} may only be created by issuer of asset ${p}, but asset ${p} has not been created", ("s",op.symbol)("p",prefix) ); - FC_ASSERT( asset_symbol_itr->issuer == op.issuer, "Asset ${s} may only be created by issuer of ${p}, ${i}", + FC_ASSERT( asset_prefix_itr->issuer == op.issuer, "Asset ${s} may only be created by issuer of ${p}, ${i}", ("s",op.symbol)("p",prefix)("i", op.issuer(d).name) ); } } @@ -269,7 +269,7 @@ void_result asset_create_evaluator::do_evaluate( const asset_create_operation& o } return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void asset_create_evaluator::pay_fee() { @@ -279,7 +279,7 @@ void asset_create_evaluator::pay_fee() generic_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 ) const { try { database& d = db(); @@ -294,7 +294,7 @@ object_id_type asset_create_evaluator::do_apply( const asset_create_operation& o if( fee_is_odd && !hf_429 ) { d.modify( d.get_core_dynamic_data(), []( asset_dynamic_data_object& dd ) { - dd.current_supply++; + ++dd.current_supply; }); } @@ -315,7 +315,7 @@ object_id_type asset_create_evaluator::do_apply( const asset_create_operation& o a.symbol = op.symbol; a.precision = op.precision; a.options = op.common_options; - if( a.options.core_exchange_rate.base.asset_id.instance.value == 0 ) + if( 0 == a.options.core_exchange_rate.base.asset_id.instance.value ) a.options.core_exchange_rate.quote.asset_id = next_asset_id; else a.options.core_exchange_rate.base.asset_id = next_asset_id; @@ -328,7 +328,7 @@ object_id_type asset_create_evaluator::do_apply( const asset_create_operation& o FC_ASSERT( new_asset.id == next_asset_id, "Unexpected object database error, object id mismatch" ); return new_asset.id; -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result asset_issue_evaluator::do_evaluate( const asset_issue_operation& o ) { try { @@ -349,9 +349,9 @@ void_result asset_issue_evaluator::do_evaluate( const asset_issue_operation& o ) FC_ASSERT( (asset_dyn_data->current_supply + o.asset_to_issue.amount) <= a.options.max_supply ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE -void_result asset_issue_evaluator::do_apply( const asset_issue_operation& o ) +void_result asset_issue_evaluator::do_apply( const asset_issue_operation& o ) const { try { db().adjust_balance( o.issue_to_account, o.asset_to_issue ); @@ -360,7 +360,7 @@ void_result asset_issue_evaluator::do_apply( const asset_issue_operation& o ) }); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result asset_reserve_evaluator::do_evaluate( const asset_reserve_operation& o ) { try { @@ -391,9 +391,9 @@ void_result asset_reserve_evaluator::do_evaluate( const asset_reserve_operation& } return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE -void_result asset_reserve_evaluator::do_apply( const asset_reserve_operation& o ) +void_result asset_reserve_evaluator::do_apply( const asset_reserve_operation& o ) const { try { db().adjust_balance( o.payer, -o.amount_to_reserve ); @@ -402,20 +402,20 @@ void_result asset_reserve_evaluator::do_apply( const asset_reserve_operation& o }); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result asset_fund_fee_pool_evaluator::do_evaluate(const asset_fund_fee_pool_operation& o) { try { - database& d = db(); + const database& d = db(); const asset_object& a = o.asset_id(d); asset_dyn_data = &a.dynamic_asset_data_id(d); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE -void_result asset_fund_fee_pool_evaluator::do_apply(const asset_fund_fee_pool_operation& o) +void_result asset_fund_fee_pool_evaluator::do_apply(const asset_fund_fee_pool_operation& o) const { try { db().adjust_balance(o.from_account, -o.amount); @@ -424,7 +424,7 @@ void_result asset_fund_fee_pool_evaluator::do_apply(const asset_fund_fee_pool_op }); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE static void validate_new_issuer( const database& d, const asset_object& a, account_id_type new_issuer ) { try { @@ -441,7 +441,7 @@ static void validate_new_issuer( const database& d, const asset_object& a, accou FC_ASSERT( backing.get_id() == asset_id_type(), "May not create a blockchain-controlled market asset which is not backed by CORE."); } -} FC_CAPTURE_AND_RETHROW( (a)(new_issuer) ) } +} FC_CAPTURE_AND_RETHROW( (a)(new_issuer) ) } // GCOVR_EXCL_LINE void_result asset_update_evaluator::do_evaluate(const asset_update_operation& o) { try { @@ -593,7 +593,7 @@ void_result asset_update_evaluator::do_evaluate(const asset_update_operation& o) d.get(id); return void_result(); -} FC_CAPTURE_AND_RETHROW((o)) } +} FC_CAPTURE_AND_RETHROW((o)) } // GCOVR_EXCL_LINE void_result asset_update_evaluator::do_apply(const asset_update_operation& o) { try { @@ -655,7 +655,7 @@ void_result asset_update_evaluator::do_apply(const asset_update_operation& o) }); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result asset_update_issuer_evaluator::do_evaluate(const asset_update_issuer_operation& o) { try { @@ -671,7 +671,7 @@ void_result asset_update_issuer_evaluator::do_evaluate(const asset_update_issuer ("o.issuer", o.issuer)("a.issuer", a.issuer) ); return void_result(); -} FC_CAPTURE_AND_RETHROW((o)) } +} FC_CAPTURE_AND_RETHROW((o)) } // GCOVR_EXCL_LINE void_result asset_update_issuer_evaluator::do_apply(const asset_update_issuer_operation& o) { try { @@ -681,7 +681,7 @@ void_result asset_update_issuer_evaluator::do_apply(const asset_update_issuer_op }); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE /**************** * Loop through assets, looking for ones that are backed by the asset being changed. When found, @@ -887,7 +887,7 @@ void_result asset_update_bitasset_evaluator::do_evaluate(const asset_update_bita asset_to_update = &asset_obj; return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE /******* * @brief Apply requested changes to bitasset options @@ -1042,7 +1042,7 @@ void_result asset_update_bitasset_evaluator::do_apply(const asset_update_bitasse return void_result(); - } FC_CAPTURE_AND_RETHROW( (op) ) + } FC_CAPTURE_AND_RETHROW( (op) ) // GCOVR_EXCL_LINE } void_result asset_update_feed_producers_evaluator::do_evaluate(const asset_update_feed_producers_operation& o) @@ -1067,7 +1067,7 @@ void_result asset_update_feed_producers_evaluator::do_evaluate(const asset_updat d.get(id); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result asset_update_feed_producers_evaluator::do_apply(const asset_update_feed_producers_operation& o) const { try { @@ -1105,7 +1105,7 @@ void_result asset_update_feed_producers_evaluator::do_apply(const asset_update_f d.check_call_orders( *asset_to_update, true, false, &bitasset_to_update ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result asset_global_settle_evaluator::do_evaluate(const asset_global_settle_evaluator::operation_type& op) { try { @@ -1133,14 +1133,14 @@ void_result asset_global_settle_evaluator::do_evaluate(const asset_global_settle } return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result asset_global_settle_evaluator::do_apply(const asset_global_settle_evaluator::operation_type& op) { try { database& d = db(); d.globally_settle_asset( *asset_to_settle, op.settle_price ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result asset_settle_evaluator::do_evaluate(const asset_settle_evaluator::operation_type& op) { try { @@ -1191,7 +1191,7 @@ void_result asset_settle_evaluator::do_evaluate(const asset_settle_evaluator::op bitasset_ptr = &bitasset; return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE static optional pay_collateral_fees( database& d, const asset& pays, @@ -1214,7 +1214,7 @@ static optional pay_collateral_fees( database& d, asset_to_settle.accumulate_fee( d, collateral_fees ); return collateral_fees; } - } FC_CAPTURE_AND_LOG( (pays)(settled_amount)(fill_price) ) // Catch and log the exception + } FC_CAPTURE_AND_LOG( (pays)(settled_amount)(fill_price) ) // Catch and log the exception // GCOVR_EXCL_LINE } return optional(); } @@ -1409,7 +1409,7 @@ operation_result asset_settle_evaluator::do_apply(const asset_settle_evaluator:: return result; -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result asset_publish_feeds_evaluator::do_evaluate(const asset_publish_feed_operation& o) { try { @@ -1471,7 +1471,7 @@ void_result asset_publish_feeds_evaluator::do_evaluate(const asset_publish_feed_ bitasset_ptr = &bitasset; return void_result(); -} FC_CAPTURE_AND_RETHROW((o)) } +} FC_CAPTURE_AND_RETHROW((o)) } // GCOVR_EXCL_LINE void_result asset_publish_feeds_evaluator::do_apply(const asset_publish_feed_operation& o) { try { @@ -1534,7 +1534,7 @@ void_result asset_publish_feeds_evaluator::do_apply(const asset_publish_feed_ope d.check_call_orders( base, true, false, bitasset_ptr ); return void_result(); -} FC_CAPTURE_AND_RETHROW((o)) } +} FC_CAPTURE_AND_RETHROW((o)) } // GCOVR_EXCL_LINE /*** @@ -1579,7 +1579,7 @@ void_result asset_claim_fees_evaluator::do_evaluate( const asset_claim_fees_oper } return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE /*** @@ -1602,7 +1602,7 @@ void_result asset_claim_fees_evaluator::do_apply( const asset_claim_fees_operati d.adjust_balance( o.issuer, o.amount_to_claim ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result asset_claim_pool_evaluator::do_evaluate( const asset_claim_pool_operation& o ) @@ -1610,7 +1610,7 @@ void_result asset_claim_pool_evaluator::do_evaluate( const asset_claim_pool_oper FC_ASSERT( o.asset_id(db()).issuer == o.issuer, "Asset fee pool may only be claimed by the issuer" ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result asset_claim_pool_evaluator::do_apply( const asset_claim_pool_operation& o ) { try { @@ -1627,7 +1627,7 @@ void_result asset_claim_pool_evaluator::do_apply( const asset_claim_pool_operati d.adjust_balance( o.issuer, o.amount_to_claim ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE } } // graphene::chain diff --git a/libraries/chain/include/graphene/chain/asset_evaluator.hpp b/libraries/chain/include/graphene/chain/asset_evaluator.hpp index 8b35585f02..b4a1a0d209 100644 --- a/libraries/chain/include/graphene/chain/asset_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/asset_evaluator.hpp @@ -36,13 +36,13 @@ namespace graphene { namespace chain { public: using operation_type = asset_create_operation; - void_result do_evaluate( const asset_create_operation& o ); - object_id_type do_apply( const asset_create_operation& o ); + void_result do_evaluate( const asset_create_operation& o ) const; + object_id_type do_apply( const asset_create_operation& o ) const; /** override the default behavior defined by generic_evalautor which is to * post the fee to fee_paying_account_stats.pending_fees */ - virtual void pay_fee() override; + void pay_fee() override; private: bool fee_is_odd; }; @@ -52,8 +52,9 @@ namespace graphene { namespace chain { public: using operation_type = asset_issue_operation; void_result do_evaluate( const asset_issue_operation& o ); - void_result do_apply( const asset_issue_operation& o ); + void_result do_apply( const asset_issue_operation& o ) const; + private: const asset_dynamic_data_object* asset_dyn_data = nullptr; const account_object* to_account = nullptr; }; @@ -63,8 +64,9 @@ namespace graphene { namespace chain { public: using operation_type = asset_reserve_operation; void_result do_evaluate( const asset_reserve_operation& o ); - void_result do_apply( const asset_reserve_operation& o ); + void_result do_apply( const asset_reserve_operation& o ) const; + private: const asset_dynamic_data_object* asset_dyn_data = nullptr; const account_object* from_account = nullptr; }; @@ -78,6 +80,7 @@ namespace graphene { namespace chain { void_result do_evaluate( const asset_update_operation& o ); void_result do_apply( const asset_update_operation& o ); + private: const asset_object* asset_to_update = nullptr; const asset_bitasset_data_object* bitasset_data = nullptr; }; @@ -90,6 +93,7 @@ namespace graphene { namespace chain { void_result do_evaluate( const asset_update_issuer_operation& o ); void_result do_apply( const asset_update_issuer_operation& o ); + private: const asset_object* asset_to_update = nullptr; }; @@ -116,6 +120,7 @@ namespace graphene { namespace chain { void_result do_evaluate( const operation_type& o ); void_result do_apply( const operation_type& o ) const; + private: const asset_object* asset_to_update = nullptr; }; @@ -125,8 +130,9 @@ namespace graphene { namespace chain { using operation_type = asset_fund_fee_pool_operation; void_result do_evaluate(const asset_fund_fee_pool_operation& op); - void_result do_apply(const asset_fund_fee_pool_operation& op); + void_result do_apply(const asset_fund_fee_pool_operation& op) const; + private: const asset_dynamic_data_object* asset_dyn_data = nullptr; }; @@ -138,6 +144,7 @@ namespace graphene { namespace chain { void_result do_evaluate(const operation_type& op); void_result do_apply(const operation_type& op); + private: const asset_object* asset_to_settle = nullptr; }; class asset_settle_evaluator : public evaluator @@ -174,6 +181,7 @@ namespace graphene { namespace chain { void_result do_evaluate( const asset_claim_fees_operation& o ); void_result do_apply( const asset_claim_fees_operation& o ); + private: const asset_object* container_asset = nullptr; const asset_dynamic_data_object* container_ddo = nullptr; }; diff --git a/libraries/chain/include/graphene/chain/liquidity_pool_evaluator.hpp b/libraries/chain/include/graphene/chain/liquidity_pool_evaluator.hpp index ad9a653220..b8e1b347d5 100644 --- a/libraries/chain/include/graphene/chain/liquidity_pool_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/liquidity_pool_evaluator.hpp @@ -35,22 +35,24 @@ namespace graphene { namespace chain { class liquidity_pool_create_evaluator : public evaluator { public: - typedef liquidity_pool_create_operation operation_type; + using operation_type = liquidity_pool_create_operation; void_result do_evaluate( const liquidity_pool_create_operation& op ); generic_operation_result do_apply( const liquidity_pool_create_operation& op ); + private: const asset_object* _share_asset = nullptr; }; class liquidity_pool_delete_evaluator : public evaluator { public: - typedef liquidity_pool_delete_operation operation_type; + using operation_type = liquidity_pool_delete_operation; void_result do_evaluate( const liquidity_pool_delete_operation& op ); - generic_operation_result do_apply( const liquidity_pool_delete_operation& op ); + generic_operation_result do_apply( const liquidity_pool_delete_operation& op ) const; + private: const liquidity_pool_object* _pool = nullptr; const asset_object* _share_asset = nullptr; }; @@ -63,17 +65,19 @@ namespace graphene { namespace chain { void_result do_evaluate( const liquidity_pool_update_operation& op ); void_result do_apply( const liquidity_pool_update_operation& op ) const; + private: const liquidity_pool_object* _pool = nullptr; }; class liquidity_pool_deposit_evaluator : public evaluator { public: - typedef liquidity_pool_deposit_operation operation_type; + using operation_type = liquidity_pool_deposit_operation; void_result do_evaluate( const liquidity_pool_deposit_operation& op ); generic_exchange_operation_result do_apply( const liquidity_pool_deposit_operation& op ); + private: const liquidity_pool_object* _pool = nullptr; const asset_dynamic_data_object* _share_asset_dyn_data = nullptr; asset _account_receives; @@ -84,11 +88,12 @@ namespace graphene { namespace chain { class liquidity_pool_withdraw_evaluator : public evaluator { public: - typedef liquidity_pool_withdraw_operation operation_type; + using operation_type = liquidity_pool_withdraw_operation; void_result do_evaluate( const liquidity_pool_withdraw_operation& op ); generic_exchange_operation_result do_apply( const liquidity_pool_withdraw_operation& op ); + private: const liquidity_pool_object* _pool = nullptr; const asset_dynamic_data_object* _share_asset_dyn_data = nullptr; asset _pool_pays_a; @@ -100,11 +105,12 @@ namespace graphene { namespace chain { class liquidity_pool_exchange_evaluator : public evaluator { public: - typedef liquidity_pool_exchange_operation operation_type; + using operation_type = liquidity_pool_exchange_operation; void_result do_evaluate( const liquidity_pool_exchange_operation& op ); generic_exchange_operation_result do_apply( const liquidity_pool_exchange_operation& op ); + private: const liquidity_pool_object* _pool = nullptr; const asset_object* _pool_pays_asset = nullptr; const asset_object* _pool_receives_asset = nullptr; diff --git a/libraries/chain/liquidity_pool_evaluator.cpp b/libraries/chain/liquidity_pool_evaluator.cpp index 553910b056..553ff3b897 100644 --- a/libraries/chain/liquidity_pool_evaluator.cpp +++ b/libraries/chain/liquidity_pool_evaluator.cpp @@ -59,7 +59,7 @@ void_result liquidity_pool_create_evaluator::do_evaluate(const liquidity_pool_cr "Current supply of the share asset needs to be zero" ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE generic_operation_result liquidity_pool_create_evaluator::do_apply(const liquidity_pool_create_operation& op) { try { @@ -81,7 +81,7 @@ generic_operation_result liquidity_pool_create_evaluator::do_apply(const liquidi }); return result; -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result liquidity_pool_delete_evaluator::do_evaluate(const liquidity_pool_delete_operation& op) { try { @@ -96,9 +96,9 @@ void_result liquidity_pool_delete_evaluator::do_evaluate(const liquidity_pool_de FC_ASSERT( _share_asset->issuer == op.account, "The account is not the owner of the liquidity pool" ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE -generic_operation_result liquidity_pool_delete_evaluator::do_apply(const liquidity_pool_delete_operation& op) +generic_operation_result liquidity_pool_delete_evaluator::do_apply(const liquidity_pool_delete_operation& op) const { try { database& d = db(); generic_operation_result result; @@ -112,7 +112,7 @@ generic_operation_result liquidity_pool_delete_evaluator::do_apply(const liquidi d.remove( *_pool ); return result; -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result liquidity_pool_update_evaluator::do_evaluate(const liquidity_pool_update_operation& op) { try { @@ -136,7 +136,7 @@ void_result liquidity_pool_update_evaluator::do_evaluate(const liquidity_pool_up } return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result liquidity_pool_update_evaluator::do_apply(const liquidity_pool_update_operation& op) const { try { @@ -150,7 +150,7 @@ void_result liquidity_pool_update_evaluator::do_apply(const liquidity_pool_updat }); return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result liquidity_pool_deposit_evaluator::do_evaluate(const liquidity_pool_deposit_operation& op) { try { @@ -219,7 +219,7 @@ void_result liquidity_pool_deposit_evaluator::do_evaluate(const liquidity_pool_d } return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE generic_exchange_operation_result liquidity_pool_deposit_evaluator::do_apply( const liquidity_pool_deposit_operation& op) @@ -249,7 +249,7 @@ generic_exchange_operation_result liquidity_pool_deposit_evaluator::do_apply( result.received.emplace_back( _account_receives ); return result; -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result liquidity_pool_withdraw_evaluator::do_evaluate(const liquidity_pool_withdraw_operation& op) { try { @@ -303,7 +303,7 @@ void_result liquidity_pool_withdraw_evaluator::do_evaluate(const liquidity_pool_ } return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE generic_exchange_operation_result liquidity_pool_withdraw_evaluator::do_apply( const liquidity_pool_withdraw_operation& op) @@ -338,7 +338,7 @@ generic_exchange_operation_result liquidity_pool_withdraw_evaluator::do_apply( result.fees.emplace_back( _fee_b ); return result; -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result liquidity_pool_exchange_evaluator::do_evaluate(const liquidity_pool_exchange_operation& op) { try { @@ -436,7 +436,7 @@ void_result liquidity_pool_exchange_evaluator::do_evaluate(const liquidity_pool_ _pool_taker_fee = asset( static_cast( pool_taker_fee ), op.min_to_receive.asset_id ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE generic_exchange_operation_result liquidity_pool_exchange_evaluator::do_apply( const liquidity_pool_exchange_operation& op) @@ -483,6 +483,6 @@ generic_exchange_operation_result liquidity_pool_exchange_evaluator::do_apply( result.fees.emplace_back( _pool_taker_fee ); return result; -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE } } // graphene::chain diff --git a/libraries/protocol/include/graphene/protocol/market.hpp b/libraries/protocol/include/graphene/protocol/market.hpp index bfed55ba1e..5e5d99cb94 100644 --- a/libraries/protocol/include/graphene/protocol/market.hpp +++ b/libraries/protocol/include/graphene/protocol/market.hpp @@ -190,7 +190,7 @@ namespace graphene { namespace protocol { void validate()const { FC_ASSERT( !"virtual operation" ); } /// This is a virtual operation; there is no fee - share_type calculate_fee(const fee_params_t& k)const { return 0; } + share_type calculate_fee(const fee_params_t&)const { return 0; } }; /** @@ -237,7 +237,7 @@ namespace graphene { namespace protocol { void validate()const { FC_ASSERT( !"virtual operation" ); } /// This is a virtual operation; there is no fee - share_type calculate_fee(const fee_params_t& k)const { return 0; } + share_type calculate_fee(const fee_params_t&)const { return 0; } }; } } // graphene::protocol diff --git a/libraries/utilities/elasticsearch.cpp b/libraries/utilities/elasticsearch.cpp index 8113dbc3dc..9e8faf88c1 100644 --- a/libraries/utilities/elasticsearch.cpp +++ b/libraries/utilities/elasticsearch.cpp @@ -211,7 +211,7 @@ std::string es_client::get_version() const fc::variant content = fc::json::from_string( response.content ); return content["version"]["number"].as_string(); -} FC_CAPTURE_LOG_AND_RETHROW( (base_url) ) } +} FC_CAPTURE_LOG_AND_RETHROW( (base_url) ) } // GCOVR_EXCL_LINE void es_client::check_version_7_or_above( bool& result ) const noexcept { From b26d877546a8afbb8eb075b889478e99f0442a52 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 16 May 2023 10:46:31 +0000 Subject: [PATCH 104/127] Add tests for virtual operation fees --- tests/tests/fee_tests.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/tests/fee_tests.cpp b/tests/tests/fee_tests.cpp index 4af3568568..29a7ceff97 100644 --- a/tests/tests/fee_tests.cpp +++ b/tests/tests/fee_tests.cpp @@ -3928,6 +3928,14 @@ BOOST_AUTO_TEST_CASE( defaults_test ) asset fee = schedule.calculate_fee( limit_order_create_operation() ); BOOST_CHECK_EQUAL( (int64_t)default_order_fee.fee, fee.amount.value ); + // fill_order fee is zero + fee = schedule.calculate_fee( fill_order_operation() ); + BOOST_CHECK_EQUAL( (int64_t)0, fee.amount.value ); + + // execute_bid fee is zero + fee = schedule.calculate_fee( execute_bid_operation() ); + BOOST_CHECK_EQUAL( (int64_t)0, fee.amount.value ); + limit_order_create_operation::fee_params_t new_order_fee; new_order_fee.fee = 123; // set fee + check schedule.parameters.insert( new_order_fee ); @@ -3951,6 +3959,15 @@ BOOST_AUTO_TEST_CASE( defaults_test ) schedule.parameters.insert( new_bid_fee ); fee = schedule.calculate_fee( bid_collateral_operation() ); BOOST_CHECK_EQUAL( (int64_t)new_bid_fee.fee, fee.amount.value ); + + // fill_order fee is still zero + fee = schedule.calculate_fee( fill_order_operation() ); + BOOST_CHECK_EQUAL( (int64_t)0, fee.amount.value ); + + // execute_bid fee is still zero + fee = schedule.calculate_fee( execute_bid_operation() ); + BOOST_CHECK_EQUAL( (int64_t)0, fee.amount.value ); + } catch( const fc::exception& e ) { From 2906a694e9d890016729deb6653cc5886bee4b54 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 16 May 2023 20:51:39 +0000 Subject: [PATCH 105/127] Add GCOVR_EXCL_LINE for FC_CAPTURE_AND_RETHROW --- libraries/chain/credit_offer_evaluator.cpp | 28 ++++++------- libraries/chain/db_block.cpp | 48 +++++++++++++--------- libraries/chain/db_maint.cpp | 6 +-- libraries/chain/db_market.cpp | 17 ++++---- libraries/chain/db_notify.cpp | 2 +- libraries/chain/db_update.cpp | 6 +-- libraries/chain/market_evaluator.cpp | 24 +++++------ libraries/chain/proposal_evaluator.cpp | 15 +++---- libraries/net/node.cpp | 8 ++-- libraries/protocol/market.cpp | 8 ++-- 10 files changed, 86 insertions(+), 76 deletions(-) diff --git a/libraries/chain/credit_offer_evaluator.cpp b/libraries/chain/credit_offer_evaluator.cpp index 7c1ef6edcf..b24de46ce6 100644 --- a/libraries/chain/credit_offer_evaluator.cpp +++ b/libraries/chain/credit_offer_evaluator.cpp @@ -66,7 +66,7 @@ void_result credit_offer_create_evaluator::do_evaluate(const credit_offer_create "The account is unauthorized by the asset" ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE object_id_type credit_offer_create_evaluator::do_apply(const credit_offer_create_operation& op) const { try { @@ -88,7 +88,7 @@ object_id_type credit_offer_create_evaluator::do_apply(const credit_offer_create obj.acceptable_borrowers = op.acceptable_borrowers; }); return new_credit_offer_object.id; -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result credit_offer_delete_evaluator::do_evaluate(const credit_offer_delete_operation& op) { try { @@ -104,7 +104,7 @@ void_result credit_offer_delete_evaluator::do_evaluate(const credit_offer_delete // Note: no asset authorization check here, allow funds to be moved to account balance return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE asset credit_offer_delete_evaluator::do_apply(const credit_offer_delete_operation& op) const { try { @@ -120,7 +120,7 @@ asset credit_offer_delete_evaluator::do_apply(const credit_offer_delete_operatio d.remove( *_offer ); return released; -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result credit_offer_update_evaluator::do_evaluate(const credit_offer_update_operation& op) { try { @@ -180,7 +180,7 @@ void_result credit_offer_update_evaluator::do_evaluate(const credit_offer_update } return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result credit_offer_update_evaluator::do_apply( const credit_offer_update_operation& op) const { try { @@ -224,7 +224,7 @@ void_result credit_offer_update_evaluator::do_apply( const credit_offer_update_o } return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result credit_offer_accept_evaluator::do_evaluate(const credit_offer_accept_operation& op) { try { @@ -304,7 +304,7 @@ void_result credit_offer_accept_evaluator::do_evaluate(const credit_offer_accept } return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE extendable_operation_result credit_offer_accept_evaluator::do_apply( const credit_offer_accept_operation& op) const { try { @@ -368,7 +368,7 @@ extendable_operation_result credit_offer_accept_evaluator::do_apply( const credi result.value.impacted_accounts = flat_set({ _offer->owner_account }); return result; -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result credit_deal_repay_evaluator::do_evaluate(const credit_deal_repay_operation& op) { try { @@ -400,7 +400,7 @@ void_result credit_deal_repay_evaluator::do_evaluate(const credit_deal_repay_ope "The owner of the credit offer is unauthorized by the repaying asset" ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE extendable_operation_result credit_deal_repay_evaluator::do_apply( const credit_deal_repay_operation& op) const { try { @@ -470,10 +470,10 @@ extendable_operation_result credit_deal_repay_evaluator::do_apply( const credit_ result.value.received = vector({ collateral_released }); return result; -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result credit_deal_update_evaluator::do_evaluate(const credit_deal_update_operation& op) -{ +{ try { const database& d = db(); const auto block_time = d.head_block_time(); @@ -486,10 +486,10 @@ void_result credit_deal_update_evaluator::do_evaluate(const credit_deal_update_o FC_ASSERT( _deal->auto_repay != op.auto_repay, "The automatic repayment type does not change" ); return void_result(); -} +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void_result credit_deal_update_evaluator::do_apply( const credit_deal_update_operation& op) const -{ +{ try { database& d = db(); d.modify( *_deal, [&op]( credit_deal_object& obj ){ @@ -497,6 +497,6 @@ void_result credit_deal_update_evaluator::do_apply( const credit_deal_update_ope }); return void_result(); -} +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE } } // graphene::chain diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index 2e2cbf8491..558005c1de 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -63,7 +63,7 @@ bool database::is_known_transaction( const transaction_id_type& id )const block_id_type database::get_block_id_for_num( uint32_t block_num )const { try { return _block_id_to_block.fetch_block_id( block_num ); -} FC_CAPTURE_AND_RETHROW( (block_num) ) } +} FC_CAPTURE_AND_RETHROW( (block_num) ) } // GCOVR_EXCL_LINE optional database::fetch_block_by_id( const block_id_type& id )const { @@ -92,7 +92,8 @@ const signed_transaction& database::get_recent_transaction(const transaction_id_ std::vector database::get_block_ids_on_fork(block_id_type head_of_fork) const { - pair branches = _fork_db.fetch_branch_from(head_block_id(), head_of_fork); + pair branches + = _fork_db.fetch_branch_from(head_block_id(), head_of_fork); if( !((branches.first.back()->previous_id() == branches.second.back()->previous_id())) ) { edump( (head_of_fork) @@ -180,7 +181,8 @@ bool database::_push_block(const signed_block& new_block) // remove the rest of branches.first from the fork_db, those blocks are invalid while( ritr != branches.first.rend() ) { - ilog( "removing block from fork_db #${n} ${id}", ("n",(*ritr)->data.block_num())("id",(*ritr)->id) ); + ilog( "removing block from fork_db #${n} ${id}", + ("n",(*ritr)->data.block_num())("id",(*ritr)->id) ); _fork_db.remove( (*ritr)->id ); ++ritr; } @@ -225,7 +227,7 @@ bool database::_push_block(const signed_block& new_block) } return false; -} FC_CAPTURE_AND_RETHROW( (new_block) ) } +} FC_CAPTURE_AND_RETHROW( (new_block) ) } // GCOVR_EXCL_LINE void database::verify_signing_witness( const signed_block& new_block, const fork_item& fork_entry )const { @@ -275,7 +277,7 @@ processed_transaction database::push_transaction( const precomputable_transactio result = _push_transaction( trx ); } ); return result; -} FC_CAPTURE_AND_RETHROW( (trx) ) } +} FC_CAPTURE_AND_RETHROW( (trx) ) } // GCOVR_EXCL_LINE processed_transaction database::_push_transaction( const precomputable_transaction& trx ) { @@ -313,7 +315,8 @@ class push_proposal_nesting_guard { push_proposal_nesting_guard( uint32_t& nesting_counter, const database& db ) : orig_value(nesting_counter), counter(nesting_counter) { - FC_ASSERT( counter < db.get_global_properties().active_witnesses.size() * 2, "Max proposal nesting depth exceeded!" ); + FC_ASSERT( counter < db.get_global_properties().active_witnesses.size() * 2, + "Max proposal nesting depth exceeded!" ); counter++; } ~push_proposal_nesting_guard() @@ -370,7 +373,7 @@ processed_transaction database::push_proposal(const proposal_object& proposal) ptrx.operation_results = std::move(eval_state.operation_results); return ptrx; -} FC_CAPTURE_AND_RETHROW( (proposal) ) } +} FC_CAPTURE_AND_RETHROW( (proposal) ) } // GCOVR_EXCL_LINE signed_block database::generate_block( fc::time_point_sec when, @@ -385,7 +388,7 @@ signed_block database::generate_block( result = _generate_block( when, witness_id, block_signing_private_key ); } ); return result; -} FC_CAPTURE_AND_RETHROW() } +} FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE signed_block database::_generate_block( fc::time_point_sec when, @@ -426,9 +429,10 @@ signed_block database::_generate_block( FC_ASSERT( witness_id(*this).signing_key == block_signing_private_key.get_public_key() ); } - static const size_t max_partial_block_header_size = fc::raw::pack_size( signed_block_header() ) - - fc::raw::pack_size( witness_id_type() ) // witness_id - + 3; // max space to store size of transactions (out of block header), + static const size_t max_partial_block_header_size = ( fc::raw::pack_size( signed_block_header() ) + - fc::raw::pack_size( witness_id_type() ) ) // witness_id + + 3; // max space to store size of transactions + // (out of block header), // +3 means 3*7=21 bits so it's practically safe const size_t max_block_header_size = max_partial_block_header_size + fc::raw::pack_size( witness_id ); auto maximum_block_size = get_global_properties().parameters.maximum_block_size; @@ -502,10 +506,11 @@ signed_block database::_generate_block( if( 0 == (skip & skip_witness_signature) ) pending_block.sign( block_signing_private_key ); - push_block( pending_block, skip | skip_transaction_signatures ); // skip authority check when pushing self-generated blocks + push_block( pending_block, skip | skip_transaction_signatures ); // skip authority check when pushing + // self-generated blocks return pending_block; -} FC_CAPTURE_AND_RETHROW( (witness_id) ) } +} FC_CAPTURE_AND_RETHROW( (witness_id) ) } // GCOVR_EXCL_LINE /** * Removes the most recent block from the database and @@ -524,15 +529,17 @@ void database::pop_block() FC_ASSERT( fork_db_head, "Trying to pop() block that's not in fork database!?" ); } pop_undo(); - _popped_tx.insert( _popped_tx.begin(), fork_db_head->data.transactions.begin(), fork_db_head->data.transactions.end() ); -} FC_CAPTURE_AND_RETHROW() } + _popped_tx.insert( _popped_tx.begin(), + fork_db_head->data.transactions.begin(), + fork_db_head->data.transactions.end() ); +} FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE void database::clear_pending() { try { assert( (_pending_tx.size() == 0) || _pending_tx_session.valid() ); _pending_tx.clear(); _pending_tx_session.reset(); -} FC_CAPTURE_AND_RETHROW() } +} FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE uint32_t database::push_applied_operation( const operation& op, bool is_virtual /* = true */ ) { @@ -667,7 +674,7 @@ void database::_apply_block( const signed_block& next_block ) _applied_ops.clear(); notify_changed_objects(); -} FC_CAPTURE_AND_RETHROW( (next_block.block_num()) ) } +} FC_CAPTURE_AND_RETHROW( (next_block.block_num()) ) } // GCOVR_EXCL_LINE /** * @note if a @c processed_transaction is passed in, it is cast into @c signed_transaction here. @@ -768,7 +775,7 @@ processed_transaction database::_apply_transaction(const signed_transaction& trx "Unpaid SameT Fund debt detected" ); return ptrx; -} FC_CAPTURE_AND_RETHROW( (trx) ) } +} FC_CAPTURE_AND_RETHROW( (trx) ) } // GCOVR_EXCL_LINE operation_result database::apply_operation( transaction_evaluation_state& eval_state, const operation& op, bool is_virtual /* = true */ ) @@ -783,7 +790,7 @@ operation_result database::apply_operation( transaction_evaluation_state& eval_s auto result = eval->evaluate( eval_state, op, true ); set_applied_operation_result( op_id, result ); return result; -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE operation_result database::try_push_virtual_operation( transaction_evaluation_state& eval_state, const operation& op ) { @@ -886,7 +893,8 @@ fc::future database::precompute_parallel( const signed_block& block, const for( size_t base = 0; base < block.transactions.size(); base += chunk_size ) workers.push_back( fc::do_parallel( [this,&block,base,chunk_size,skip] () { _precompute_parallel( &block.transactions[base], - base + chunk_size < block.transactions.size() ? chunk_size : block.transactions.size() - base, + ( ( base + chunk_size ) < block.transactions.size() ) ? chunk_size + : ( block.transactions.size() - base ), skip ); }) ); } diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 91d4edc88d..d019a43620 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -305,7 +305,7 @@ void database::update_active_witnesses() }); }); -} FC_CAPTURE_AND_RETHROW() } +} FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE void database::update_active_committee_members() { try { @@ -412,7 +412,7 @@ void database::update_active_committee_members() std::inserter(gp.active_committee_members, gp.active_committee_members.begin()), [](const committee_member_object& d) { return d.get_id(); }); }); -} FC_CAPTURE_AND_RETHROW() } +} FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE void database::initialize_budget_record( fc::time_point_sec now, budget_record& rec )const { @@ -564,7 +564,7 @@ void database::process_budget() // available_funds is money we could spend, but don't want to. // we simply let it evaporate back into the reserve. } - FC_CAPTURE_AND_RETHROW() + FC_CAPTURE_AND_RETHROW() // GCOVR_EXCL_LINE } template< typename Visitor > diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index a31851ceca..7809921286 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -335,7 +335,7 @@ void database::globally_settle_asset_impl( const asset_object& mia, obj.settlement_fund = collateral_gathered.amount; }); -} FC_CAPTURE_AND_RETHROW( (mia)(settlement_price) ) } +} FC_CAPTURE_AND_RETHROW( (mia)(settlement_price) ) } // GCOVR_EXCL_LINE void database::individually_settle( const asset_bitasset_data_object& bitasset, const call_order_object& order ) { @@ -448,7 +448,7 @@ void database::revive_bitasset( const asset_object& bitasset, const asset_bitass FC_ASSERT( bad.settlement_fund == 0 ); _cancel_bids_and_revive_mpa( bitasset, bad ); -} FC_CAPTURE_AND_RETHROW( (bitasset) ) } +} FC_CAPTURE_AND_RETHROW( (bitasset) ) } // GCOVR_EXCL_LINE void database::_cancel_bids_and_revive_mpa( const asset_object& bitasset, const asset_bitasset_data_object& bad ) { try { @@ -472,7 +472,7 @@ void database::_cancel_bids_and_revive_mpa( const asset_object& bitasset, const obj.settlement_price = price(); obj.settlement_fund = 0; }); -} FC_CAPTURE_AND_RETHROW( (bitasset) ) } +} FC_CAPTURE_AND_RETHROW( (bitasset) ) } // GCOVR_EXCL_LINE void database::cancel_bid(const collateral_bid_object& bid, bool create_virtual_op) { @@ -1619,7 +1619,8 @@ asset database::match_impl( const force_settlement_object& settle, cancel_settle_order( settle ); return call_receives; -} FC_CAPTURE_AND_RETHROW( (p_match_price)(max_settlement)(p_fill_price)(is_margin_call)(settle_is_taker) ) } +} FC_CAPTURE_AND_RETHROW( (p_match_price)(max_settlement)(p_fill_price) // GCOVR_EXCL_LINE + (is_margin_call)(settle_is_taker) ) } // GCOVR_EXCL_LINE bool database::fill_limit_order( const limit_order_object& order, const asset& pays, const asset& receives, bool cull_if_small, const price& fill_price, const bool is_maker) @@ -1725,7 +1726,7 @@ bool database::fill_limit_order( const limit_order_object& order, const asset& p return maybe_cull_small_order( *this, order ); return false; } -} FC_CAPTURE_AND_RETHROW( (pays)(receives) ) } +} FC_CAPTURE_AND_RETHROW( (pays)(receives) ) } // GCOVR_EXCL_LINE /*** * @brief fill a call order in the specified amounts @@ -1808,7 +1809,7 @@ bool database::fill_call_order( const call_order_object& order, const asset& pay remove( order ); return collateral_freed.valid(); -} FC_CAPTURE_AND_RETHROW( (pays)(receives) ) } +} FC_CAPTURE_AND_RETHROW( (pays)(receives) ) } // GCOVR_EXCL_LINE /*** * @brief fullfill a settle order in the specified amounts @@ -1881,7 +1882,7 @@ bool database::fill_settle_order( const force_settlement_object& settle, const a return filled; -} FC_CAPTURE_AND_RETHROW( (pays)(receives) ) } +} FC_CAPTURE_AND_RETHROW( (pays)(receives) ) } // GCOVR_EXCL_LINE /** * Starting with the least collateralized orders, fill them if their @@ -2254,7 +2255,7 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa } // while there exists a call order check_settled_debt_order( bitasset ); return margin_called; -} FC_CAPTURE_AND_RETHROW() } +} FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE bool database::match_force_settlements( const asset_bitasset_data_object& bitasset ) { diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index e1a354ad3e..c2dce4d491 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -656,6 +656,6 @@ void database::notify_changed_objects() } catch( const graphene::chain::plugin_exception& e ) { elog( "Caught plugin exception: ${e}", ("e", e.to_detail_string() ) ); throw; -} FC_CAPTURE_AND_LOG( (0) ) } +} FC_CAPTURE_AND_LOG( (0) ) } // GCOVR_EXCL_LINE } } // namespace graphene::chain diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index f3cfe14f36..59f52e27c0 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -150,7 +150,7 @@ void database::clear_expired_transactions() const auto& dedupe_index = transaction_idx.indices().get(); while( (!dedupe_index.empty()) && (head_block_time() > dedupe_index.begin()->trx.expiration) ) transaction_idx.remove(*dedupe_index.begin()); -} FC_CAPTURE_AND_RETHROW() } +} FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE void database::clear_expired_proposals() { @@ -344,7 +344,7 @@ void database::clear_expired_orders() check_call_orders( quote_asset( *this ) ); } } -} FC_CAPTURE_AND_RETHROW() } +} FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE void database::clear_expired_force_settlements() { try { @@ -526,7 +526,7 @@ void database::clear_expired_force_settlements() }); } } -} FC_CAPTURE_AND_RETHROW() } +} FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE void database::update_expired_feeds() { diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 886d5bc26c..431744a343 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -75,7 +75,7 @@ void_result limit_order_create_evaluator::do_evaluate(const limit_order_create_o ("balance",d.get_balance(*_seller,*_sell_asset))("amount_to_sell",op.amount_to_sell) ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void limit_order_create_evaluator::convert_fee() { @@ -133,7 +133,7 @@ object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_o ("op",op) ); return order_id; -} FC_CAPTURE_AND_RETHROW( (op) ) } +} FC_CAPTURE_AND_RETHROW( (op) ) } // GCOVR_EXCL_LINE void limit_order_update_evaluator::convert_fee() { @@ -153,7 +153,7 @@ void limit_order_update_evaluator::pay_fee() } void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_operation& o) -{ +{ try { const database& d = db(); FC_ASSERT( HARDFORK_CORE_1604_PASSED( d.head_block_time() ) , "Operation has not activated yet"); @@ -241,7 +241,7 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o "The account is not allowed to transact the receiving asset" ); return {}; -} +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void limit_order_update_evaluator::process_deferred_fee() { @@ -328,7 +328,7 @@ void limit_order_update_evaluator::process_deferred_fee() } void_result limit_order_update_evaluator::do_apply(const limit_order_update_operation& o) -{ +{ try { database& d = db(); // Adjust account balance @@ -363,7 +363,7 @@ void_result limit_order_update_evaluator::do_apply(const limit_order_update_oper d.apply_order(*_order); return {}; -} +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result limit_order_cancel_evaluator::do_evaluate(const limit_order_cancel_operation& o) { try { @@ -382,7 +382,7 @@ void_result limit_order_cancel_evaluator::do_evaluate(const limit_order_cancel_o ("oid", o.order) ); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE asset limit_order_cancel_evaluator::do_apply(const limit_order_cancel_operation& o) const { try { @@ -404,7 +404,7 @@ asset limit_order_cancel_evaluator::do_apply(const limit_order_cancel_operation& } return refunded; -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result call_order_update_evaluator::do_evaluate(const call_order_update_operation& o) { try { @@ -488,7 +488,7 @@ void_result call_order_update_evaluator::do_evaluate(const call_order_update_ope // which is now removed since the check is implicitly done later by `adjust_balance()` in `do_apply()`. return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE object_id_type call_order_update_evaluator::do_apply(const call_order_update_operation& o) @@ -696,7 +696,7 @@ object_id_type call_order_update_evaluator::do_apply(const call_order_update_ope } return call_order_id; -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result bid_collateral_evaluator::do_evaluate(const bid_collateral_operation& o) { try { @@ -758,7 +758,7 @@ void_result bid_collateral_evaluator::do_evaluate(const bid_collateral_operation } return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result bid_collateral_evaluator::do_apply(const bid_collateral_operation& o) const @@ -780,6 +780,6 @@ void_result bid_collateral_evaluator::do_apply(const bid_collateral_operation& o // Note: CORE asset in collateral_bid_object is not counted in account_stats.total_core_in_orders return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE } } // graphene::chain diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index 164cb12529..aad9ccb5b1 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -431,7 +431,7 @@ void_result proposal_create_evaluator::do_evaluate( const proposal_create_operat _proposed_trx.validate(); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE object_id_type proposal_create_evaluator::do_apply( const proposal_create_operation& o ) { try { @@ -466,7 +466,7 @@ object_id_type proposal_create_evaluator::do_apply( const proposal_create_operat }); return proposal.id; -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result proposal_update_evaluator::do_evaluate( const proposal_update_operation& o ) { try { @@ -490,7 +490,7 @@ void_result proposal_update_evaluator::do_evaluate( const proposal_update_operat } return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result proposal_update_evaluator::do_apply(const proposal_update_operation& o) { try { @@ -527,14 +527,15 @@ void_result proposal_update_evaluator::do_apply(const proposal_update_operation& d.modify(*_proposal, [&e](proposal_object& p) { p.fail_reason = e.to_string(fc::log_level(fc::log_level::all)); }); - wlog("Proposed transaction ${id} failed to apply once approved with exception:\n----\n${reason}\n----\nWill try again when it expires.", + wlog("Proposed transaction ${id} failed to apply once approved with exception:\n" + "----\n${reason}\n----\nWill try again when it expires.", ("id", o.proposal)("reason", e.to_detail_string())); _proposal_failed = true; } } return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result proposal_delete_evaluator::do_evaluate(const proposal_delete_operation& o) { try { @@ -549,14 +550,14 @@ void_result proposal_delete_evaluator::do_evaluate(const proposal_delete_operati ("provided", o.fee_paying_account)("required", *required_approvals)); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE void_result proposal_delete_evaluator::do_apply(const proposal_delete_operation& o) { try { db().remove(*_proposal); return void_result(); -} FC_CAPTURE_AND_RETHROW( (o) ) } +} FC_CAPTURE_AND_RETHROW( (o) ) } // GCOVR_EXCL_LINE } } // graphene::chain diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index 759d46515e..eebc21a74a 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -451,7 +451,7 @@ namespace graphene { namespace net { namespace detail { ilog( "p2p_network_connect_loop canceled" ); throw; } - FC_CAPTURE_AND_LOG( (0) ) + FC_CAPTURE_AND_LOG( (0) ) // GCOVR_EXCL_LINE }// while !canceled } @@ -482,7 +482,7 @@ namespace graphene { namespace net { namespace detail { ilog( "update_seed_nodes_task canceled" ); throw; } - FC_CAPTURE_AND_LOG( (_seed_nodes) ) + FC_CAPTURE_AND_LOG( (_seed_nodes) ) // GCOVR_EXCL_LINE schedule_next_update_seed_nodes_task(); } @@ -4047,7 +4047,7 @@ namespace graphene { namespace net { namespace detail { // limit the rate at which we accept connections to mitigate DOS attacks fc::usleep( fc::milliseconds(10) ); - } FC_CAPTURE_AND_LOG( (0) ) + } FC_CAPTURE_AND_LOG( (0) ) // GCOVR_EXCL_LINE } } // accept_loop() @@ -4476,7 +4476,7 @@ namespace graphene { namespace net { namespace detail { FC_THROW("Bad port: ${port}", ("port", port_string)); } } - FC_CAPTURE_AND_RETHROW((in)) + FC_CAPTURE_AND_RETHROW((in)) // GCOVR_EXCL_LINE } void node_impl::resolve_seed_node_and_add(const std::string& endpoint_string) diff --git a/libraries/protocol/market.cpp b/libraries/protocol/market.cpp index 7f8472cdbc..e930db0465 100644 --- a/libraries/protocol/market.cpp +++ b/libraries/protocol/market.cpp @@ -36,7 +36,7 @@ void limit_order_create_operation::validate()const } void limit_order_update_operation::validate() const -{ +{ try { FC_ASSERT(fee.amount >= 0, "Fee must not be negative"); FC_ASSERT(new_price || delta_amount_to_sell || new_expiration, "Cannot update limit order if nothing is specified to update"); @@ -44,7 +44,7 @@ void limit_order_update_operation::validate() const new_price->validate(); if (delta_amount_to_sell) FC_ASSERT(delta_amount_to_sell->amount != 0, "Cannot change limit order amount by zero"); -} +} FC_CAPTURE_AND_RETHROW((*this)) } // GCOVR_EXCL_LINE void limit_order_cancel_operation::validate()const { @@ -59,13 +59,13 @@ void call_order_update_operation::validate()const // note: no validation is needed for extensions so far: the only attribute inside is target_collateral_ratio -} FC_CAPTURE_AND_RETHROW((*this)) } +} FC_CAPTURE_AND_RETHROW((*this)) } // GCOVR_EXCL_LINE void bid_collateral_operation::validate()const { try { FC_ASSERT( fee.amount >= 0 ); FC_ASSERT( debt_covered.amount == 0 || (debt_covered.amount > 0 && additional_collateral.amount > 0) ); -} FC_CAPTURE_AND_RETHROW((*this)) } +} FC_CAPTURE_AND_RETHROW((*this)) } // GCOVR_EXCL_LINE } } // graphene::protocol From 113418ee88693c783c802abb9cfcee1b67dde646 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 20 May 2023 12:51:49 +0000 Subject: [PATCH 106/127] Add GCOVR_EXCL_LINE for FC_CAPTURE_AND_RETHROW --- libraries/app/application.cpp | 24 +++++++++---------- .../api_helper_indexes/api_helper_indexes.cpp | 18 +++++++------- .../elasticsearch/elasticsearch_plugin.cpp | 2 +- libraries/plugins/es_objects/es_objects.cpp | 6 ++--- .../include/graphene/protocol/object_id.hpp | 6 +++-- 5 files changed, 29 insertions(+), 27 deletions(-) diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index c421ad2a12..f7c340dde9 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -183,7 +183,7 @@ void application_impl::reset_p2p_node(const fc::path& data_dir) _p2p_network->sync_from(net::item_id(net::core_message_type_enum::block_message_type, _chain_db->head_block_id()), std::vector()); -} FC_CAPTURE_AND_RETHROW() } +} FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE void application_impl::new_connection( const fc::http::websocket_connection_ptr& c ) { @@ -234,7 +234,7 @@ void application_impl::reset_websocket_server() ilog("Configured websocket rpc to listen on ${ip}", ("ip",_options->at("rpc-endpoint").as())); _websocket_server->listen( fc::ip::endpoint::from_string(_options->at("rpc-endpoint").as()) ); _websocket_server->start_accept(); -} FC_CAPTURE_AND_RETHROW() } +} FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE void application_impl::reset_websocket_tls_server() { try { @@ -259,7 +259,7 @@ void application_impl::reset_websocket_tls_server() ilog("Configured websocket TLS rpc to listen on ${ip}", ("ip",_options->at("rpc-tls-endpoint").as())); _websocket_tls_server->listen( fc::ip::endpoint::from_string(_options->at("rpc-tls-endpoint").as()) ); _websocket_tls_server->start_accept(); -} FC_CAPTURE_AND_RETHROW() } +} FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE void application_impl::initialize(const fc::path& data_dir, shared_ptr options) { @@ -526,7 +526,7 @@ graphene::chain::genesis_state_type application_impl::initialize_genesis_state() genesis.initial_chain_id = fc::sha256::hash( egenesis_json ); return genesis; } - } FC_CAPTURE_AND_RETHROW() + } FC_CAPTURE_AND_RETHROW() // GCOVR_EXCL_LINE } void application_impl::open_chain_database() const @@ -646,7 +646,7 @@ bool application_impl::has_item(const net::item_id& id) else return _chain_db->is_known_transaction(id.item_hash); } - FC_CAPTURE_AND_RETHROW( (id) ) + FC_CAPTURE_AND_RETHROW( (id) ) // GCOVR_EXCL_LINE } /** @@ -728,7 +728,7 @@ bool application_impl::handle_block(const graphene::net::block_message& blk_msg, _is_finished_syncing = true; _self.syncing_finished(); } -} FC_CAPTURE_AND_RETHROW( (blk_msg)(sync_mode) ) return false; } +} FC_CAPTURE_AND_RETHROW( (blk_msg)(sync_mode) ) return false; } // GCOVR_EXCL_LINE void application_impl::handle_transaction(const graphene::net::trx_message& transaction_message) { try { @@ -744,7 +744,7 @@ void application_impl::handle_transaction(const graphene::net::trx_message& tran _chain_db->precompute_parallel( transaction_message.trx ).wait(); _chain_db->push_transaction( transaction_message.trx ); -} FC_CAPTURE_AND_RETHROW( (transaction_message) ) } +} FC_CAPTURE_AND_RETHROW( (transaction_message) ) } // GCOVR_EXCL_LINE void application_impl::handle_message(const message& message_to_process) { @@ -814,7 +814,7 @@ std::vector application_impl::get_block_ids(const std::vectorhead_block_num() - block_header::num_from_id(result.back()); return result; -} FC_CAPTURE_AND_RETHROW( (blockchain_synopsis)(remaining_item_count)(limit) ) } +} FC_CAPTURE_AND_RETHROW( (blockchain_synopsis)(remaining_item_count)(limit) ) } // GCOVR_EXCL_LINE /** * Given the hash of the requested data, fetch the body. @@ -833,7 +833,7 @@ message application_impl::get_item(const item_id& id) return block_message(std::move(*opt_block)); } return trx_message( _chain_db->get_recent_transaction( id.item_hash ) ); -} FC_CAPTURE_AND_RETHROW( (id) ) } +} FC_CAPTURE_AND_RETHROW( (id) ) } // GCOVR_EXCL_LINE chain_id_type application_impl::get_chain_id() const { @@ -1016,7 +1016,7 @@ std::vector application_impl::get_blockchain_synopsis(const item_ha //idump((synopsis)); return synopsis; -} FC_CAPTURE_AND_RETHROW() } +} FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE /** * Call this after the call to handle_message succeeds. @@ -1041,7 +1041,7 @@ void application_impl::connection_count_changed(uint32_t c) uint32_t application_impl::get_block_number(const item_hash_t& block_id) { try { return block_header::num_from_id(block_id); -} FC_CAPTURE_AND_RETHROW( (block_id) ) } +} FC_CAPTURE_AND_RETHROW( (block_id) ) } // GCOVR_EXCL_LINE /** * Returns the time a block was produced (if block_id = 0, returns genesis time). @@ -1052,7 +1052,7 @@ fc::time_point_sec application_impl::get_block_time(const item_hash_t& block_id) auto opt_block = _chain_db->fetch_block_by_id( block_id ); if( opt_block.valid() ) return opt_block->timestamp; return fc::time_point_sec::min(); -} FC_CAPTURE_AND_RETHROW( (block_id) ) } +} FC_CAPTURE_AND_RETHROW( (block_id) ) } // GCOVR_EXCL_LINE item_hash_t application_impl::get_head_block_id() const { diff --git a/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp b/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp index e6cd8100f6..32874b1fb2 100644 --- a/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp +++ b/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp @@ -50,7 +50,7 @@ void amount_in_collateral_index::object_inserted( const object& objct ) itr->second += o.collateral; } -} FC_CAPTURE_AND_RETHROW( (objct) ) } +} FC_CAPTURE_AND_RETHROW( (objct) ) } // GCOVR_EXCL_LINE void amount_in_collateral_index::object_removed( const object& objct ) { try { @@ -68,31 +68,31 @@ void amount_in_collateral_index::object_removed( const object& objct ) itr->second -= o.collateral; } -} FC_CAPTURE_AND_RETHROW( (objct) ) } +} FC_CAPTURE_AND_RETHROW( (objct) ) } // GCOVR_EXCL_LINE void amount_in_collateral_index::about_to_modify( const object& objct ) { try { object_removed( objct ); -} FC_CAPTURE_AND_RETHROW( (objct) ) } +} FC_CAPTURE_AND_RETHROW( (objct) ) } // GCOVR_EXCL_LINE void amount_in_collateral_index::object_modified( const object& objct ) { try { object_inserted( objct ); -} FC_CAPTURE_AND_RETHROW( (objct) ) } +} FC_CAPTURE_AND_RETHROW( (objct) ) } // GCOVR_EXCL_LINE share_type amount_in_collateral_index::get_amount_in_collateral( const asset_id_type& asst )const { try { auto itr = in_collateral.find( asst ); if( itr == in_collateral.end() ) return 0; return itr->second; -} FC_CAPTURE_AND_RETHROW( (asst) ) } +} FC_CAPTURE_AND_RETHROW( (asst) ) } // GCOVR_EXCL_LINE share_type amount_in_collateral_index::get_backing_collateral( const asset_id_type& asst )const { try { auto itr = backing_collateral.find( asst ); if( itr == backing_collateral.end() ) return 0; return itr->second; -} FC_CAPTURE_AND_RETHROW( (asst) ) } +} FC_CAPTURE_AND_RETHROW( (asst) ) } // GCOVR_EXCL_LINE void asset_in_liquidity_pools_index::object_inserted( const object& objct ) { try { @@ -100,7 +100,7 @@ void asset_in_liquidity_pools_index::object_inserted( const object& objct ) const liquidity_pool_id_type pool_id = o.get_id(); asset_in_pools_map[ o.asset_a ].insert( pool_id ); // Note: [] operator will create an entry if not found asset_in_pools_map[ o.asset_b ].insert( pool_id ); -} FC_CAPTURE_AND_RETHROW( (objct) ) } +} FC_CAPTURE_AND_RETHROW( (objct) ) } // GCOVR_EXCL_LINE void asset_in_liquidity_pools_index::object_removed( const object& objct ) { try { @@ -109,7 +109,7 @@ void asset_in_liquidity_pools_index::object_removed( const object& objct ) asset_in_pools_map[ o.asset_a ].erase( pool_id ); asset_in_pools_map[ o.asset_b ].erase( pool_id ); // Note: do not erase entries with an empty set from the map in order to avoid read/write race conditions -} FC_CAPTURE_AND_RETHROW( (objct) ) } +} FC_CAPTURE_AND_RETHROW( (objct) ) } // GCOVR_EXCL_LINE void asset_in_liquidity_pools_index::about_to_modify( const object& objct ) { @@ -250,6 +250,6 @@ void api_helper_indexes::refresh_next_ids() object_id_type next_object_ids_index::get_next_id( uint8_t space_id, uint8_t type_id ) const { try { return _next_ids.at( std::make_pair( space_id, type_id ) ); -} FC_CAPTURE_AND_RETHROW( (space_id)(type_id) ) } +} FC_CAPTURE_AND_RETHROW( (space_id)(type_id) ) } // GCOVR_EXCL_LINE } } diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index 14529fb3fb..ef0e46361f 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -292,7 +292,7 @@ void elasticsearch_plugin_impl::doOperationHistory( const optional send_bulk( bulk_lines ) ) { - elog( "Error sending ${n} lines of bulk data to ElasticSearch, the first lines are:", - ("n",bulk_lines.size()) ); + elog( "Error sending ${n} lines of bulk data to ElasticSearch, the first lines are:", // GCOVR_EXCL_LINE + ("n",bulk_lines.size()) ); // GCOVR_EXCL_LINE const auto log_max = std::min( bulk_lines.size(), size_t(10) ); for( size_t i = 0; i < log_max; ++i ) { - edump( (bulk_lines[i]) ); + edump( (bulk_lines[i]) ); // GCOVR_EXCL_LINE } FC_THROW_EXCEPTION( graphene::chain::plugin_exception, "Error populating ES database, we are going to keep trying." ); diff --git a/libraries/protocol/include/graphene/protocol/object_id.hpp b/libraries/protocol/include/graphene/protocol/object_id.hpp index 2fda3cf742..f64e737ec0 100644 --- a/libraries/protocol/include/graphene/protocol/object_id.hpp +++ b/libraries/protocol/include/graphene/protocol/object_id.hpp @@ -240,12 +240,14 @@ struct member_name, 0> { static constexpr const cha FC_ASSERT( type_id <= graphene::db::object_id_type::one_byte_mask, "type overflow"); auto instance = fc::to_uint64(s.substr( second_dot+1 )); vo.reset( static_cast(space_id), static_cast(type_id), instance ); - } FC_CAPTURE_AND_RETHROW( (var) ) } + } FC_CAPTURE_AND_RETHROW( (var) ) } // GCOVR_EXCL_LINE + template void to_variant( const graphene::db::object_id& var, fc::variant& vo, uint32_t max_depth = 1 ) { vo = std::string( var ); } + template void from_variant( const fc::variant& var, graphene::db::object_id& vo, uint32_t max_depth = 1 ) { try { @@ -262,7 +264,7 @@ struct member_name, 0> { static constexpr const cha ("TypeID",TypeID)("SpaceID",SpaceID)("var",var) ); graphene::db::object_id tmp { fc::to_uint64(s.substr( second_dot+1 )) }; vo = tmp; - } FC_CAPTURE_AND_RETHROW( (var) ) } + } FC_CAPTURE_AND_RETHROW( (var) ) } // GCOVR_EXCL_LINE } // namespace fc From ecc0da4d5f4e1ed27e6336b9aae9ac8f3b69827e Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 20 May 2023 14:14:09 +0000 Subject: [PATCH 107/127] Add tests for object_id and object_id_type --- tests/tests/basic_tests.cpp | 61 ++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/tests/tests/basic_tests.cpp b/tests/tests/basic_tests.cpp index 1769eb6e39..459bfa180f 100644 --- a/tests/tests/basic_tests.cpp +++ b/tests/tests/basic_tests.cpp @@ -135,6 +135,59 @@ BOOST_AUTO_TEST_CASE( valid_symbol_test ) BOOST_CHECK( is_valid_symbol( "AAA000AAA" ) ); } +BOOST_AUTO_TEST_CASE( object_id_test ) +{ + + uint64_t u56 = ((uint64_t)1)<<56; + BOOST_CHECK_THROW( object_id_type( 1, 0, u56 ), fc::exception ); + + object_id_type o102( 1, 0, 2 ); + BOOST_CHECK_THROW( (object_id<1,1>( o102 )), fc::exception ); + BOOST_CHECK_THROW( (object_id<2,1>( o102 )), fc::exception ); + BOOST_CHECK_THROW( (object_id<2,0>( o102 )), fc::exception ); + + BOOST_CHECK_THROW( (object_id<1,0>( u56 )), fc::exception ); + + object_id_type o1; + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1") ), o1 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string(".1") ), o1 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1.1") ), o1 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1..1") ), o1 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1.1.") ), o1 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("256.1.1") ), o1 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1.256.1") ), o1 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("256.256.1") ), o1 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1.1.") + std::to_string(u56) ), o1 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1.1.a") ), o1 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1.a.1") ), o1 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("a.1.1") ), o1 ), fc::exception ); + + from_variant( fc::variant( std::string("1.1.1234567") ), o1 ); + BOOST_CHECK( o1 == object_id_type( 1, 1, 1234567 ) ); + + object_id<1,1> o2; + BOOST_CHECK( o2 != o1 ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1") ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string(".1") ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1.1") ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1..1") ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1.1.") ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("2.1.1") ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1.2.1") ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("2.2.1") ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("256.1.1") ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1.256.1") ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("256.256.1") ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1.1.") + std::to_string(u56) ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1.1.a") ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("1.a.1") ), o2 ), fc::exception ); + BOOST_CHECK_THROW( from_variant( fc::variant( std::string("a.1.1") ), o2 ), fc::exception ); + + from_variant( fc::variant( std::string("1.1.1234567") ), o2 ); + BOOST_CHECK( o2 == o1 ); + +} + BOOST_AUTO_TEST_CASE( price_test ) { auto price_max = []( uint32_t a, uint32_t b ) @@ -471,7 +524,7 @@ BOOST_AUTO_TEST_CASE( merkle_root ) auto c = []( const digest_type& digest ) -> checksum_type { return checksum_type::hash( digest ); }; - + auto d = []( const digest_type& left, const digest_type& right ) -> digest_type { return digest_type::hash( std::make_pair( left, right ) ); }; @@ -486,7 +539,7 @@ BOOST_AUTO_TEST_CASE( merkle_root ) /* A=d(0,1) - / \ + / \ 0 1 */ @@ -600,7 +653,7 @@ BOOST_AUTO_TEST_CASE( merkle_root ) /* _____________O=d(M,N)______________ - / \ + / \ __M=d(I,J)__ N=K / \ / I=d(A,B) J=d(C,D) K=E @@ -621,7 +674,7 @@ BOOST_AUTO_TEST_CASE( merkle_root ) /* _____________O=d(M,N)______________ - / \ + / \ __M=d(I,J)__ N=K / \ / I=d(A,B) J=d(C,D) K=E From 4b87ba8738c3b140fda75b7feeeb99b50451829b Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 27 May 2023 13:47:54 +0000 Subject: [PATCH 108/127] Rename functions has_settlement() and has_indiv... ...idual_settlement() to is_globally_settled() and is_individually_settled_to_fund() for intuition --- libraries/chain/asset_evaluator.cpp | 28 ++-- libraries/chain/db_maint.cpp | 2 +- libraries/chain/db_market.cpp | 16 +-- libraries/chain/db_update.cpp | 2 +- .../include/graphene/chain/asset_object.hpp | 4 +- libraries/chain/market_evaluator.cpp | 4 +- tests/common/database_fixture.cpp | 2 +- tests/tests/api_limit_tests.cpp | 2 +- tests/tests/bsrm_basic_tests.cpp | 104 +++++++-------- tests/tests/bsrm_indvd_settlement_tests.cpp | 124 +++++++++--------- tests/tests/bsrm_no_settlement_tests.cpp | 52 ++++---- tests/tests/force_settle_match_tests.cpp | 4 +- tests/tests/margin_call_fee_tests.cpp | 32 ++--- tests/tests/market_tests.cpp | 26 ++-- tests/tests/operation_tests.cpp | 2 +- tests/tests/settle_tests.cpp | 26 ++-- tests/tests/swan_tests.cpp | 100 +++++++------- 17 files changed, 265 insertions(+), 265 deletions(-) diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index 8fbeba326b..6f8d428ca1 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -743,7 +743,7 @@ void_result asset_update_bitasset_evaluator::do_evaluate(const asset_update_bita const asset_bitasset_data_object& current_bitasset_data = asset_obj.bitasset_data(d); if( !HARDFORK_CORE_2282_PASSED( next_maint_time ) ) - FC_ASSERT( !current_bitasset_data.has_settlement(), + FC_ASSERT( !current_bitasset_data.is_globally_settled(), "Cannot update a bitasset after a global settlement has executed" ); if( current_bitasset_data.is_prediction_market ) @@ -784,13 +784,13 @@ void_result asset_update_bitasset_evaluator::do_evaluate(const asset_update_bita if( old_bsrm != new_bsrm ) { FC_ASSERT( asset_obj.can_owner_update_bsrm(), "No permission to update BSRM" ); - FC_ASSERT( !current_bitasset_data.has_settlement(), + FC_ASSERT( !current_bitasset_data.is_globally_settled(), "Unable to update BSRM when the asset has been globally settled" ); // Note: it is probably OK to allow BSRM update, be conservative here so far using bsrm_type = bitasset_options::black_swan_response_type; if( bsrm_type::individual_settlement_to_fund == old_bsrm ) - FC_ASSERT( !current_bitasset_data.has_individual_settlement(), + FC_ASSERT( !current_bitasset_data.is_individually_settled_to_fund(), "Unable to update BSRM when the individual settlement pool is not empty" ); else if( bsrm_type::individual_settlement_to_order == old_bsrm ) FC_ASSERT( !d.find_settled_debt_order( op.asset_to_update ), @@ -808,7 +808,7 @@ void_result asset_update_bitasset_evaluator::do_evaluate(const asset_update_bita // Are we changing the backing asset? if( op.new_options.short_backing_asset != current_bitasset_data.options.short_backing_asset ) { - FC_ASSERT( !current_bitasset_data.has_settlement(), + FC_ASSERT( !current_bitasset_data.is_globally_settled(), "Cannot change backing asset after a global settlement has executed" ); const asset_dynamic_data_object& dyn = asset_obj.dynamic_asset_data_id(d); @@ -1119,7 +1119,7 @@ void_result asset_global_settle_evaluator::do_evaluate(const asset_global_settle const asset_bitasset_data_object& _bitasset_data = asset_to_settle->bitasset_data(d); // if there is a settlement for this asset, then no further global settle may be taken - FC_ASSERT( !_bitasset_data.has_settlement(), + FC_ASSERT( !_bitasset_data.is_globally_settled(), "This asset has been globally settled, cannot globally settle again" ); // Note: after core-2467 hard fork, there can be no debt position due to individual settlements, so we check here @@ -1150,14 +1150,14 @@ void_result asset_settle_evaluator::do_evaluate(const asset_settle_evaluator::op "Can only force settle a predition market or a market issued asset" ); const auto& bitasset = asset_to_settle->bitasset_data(d); - FC_ASSERT( asset_to_settle->can_force_settle() || bitasset.has_settlement() - || bitasset.has_individual_settlement(), + FC_ASSERT( asset_to_settle->can_force_settle() || bitasset.is_globally_settled() + || bitasset.is_individually_settled_to_fund(), "Either the asset need to have the force_settle flag enabled, or it need to be globally settled, " "or the individual settlement pool is not empty" ); if( bitasset.is_prediction_market ) { - FC_ASSERT( bitasset.has_settlement(), + FC_ASSERT( bitasset.is_globally_settled(), "Global settlement must occur before force settling a prediction market" ); } else if( bitasset.current_feed.settlement_price.is_null() ) @@ -1169,7 +1169,7 @@ void_result asset_settle_evaluator::do_evaluate(const asset_settle_evaluator::op "Before the core-216 hard fork, unable to force settle when there is no sufficient " " price feeds, no matter if the asset has been globally settled" ); } - if( !bitasset.has_settlement() && !bitasset.has_individual_settlement() ) + if( !bitasset.is_globally_settled() && !bitasset.is_individually_settled_to_fund() ) { FC_THROW_EXCEPTION( insufficient_feeds, "Cannot force settle with no price feed if the asset is not globally settled and the " @@ -1363,18 +1363,18 @@ operation_result asset_settle_evaluator::do_apply(const asset_settle_evaluator:: const auto& bitasset = *bitasset_ptr; // Process global settlement fund - if( bitasset.has_settlement() ) + if( bitasset.is_globally_settled() ) return pay_settle_from_gs_fund( d, op, fee_paying_account, *asset_to_settle, bitasset ); // Process individual settlement pool extendable_operation_result result; asset to_settle = op.amount; - if( bitasset.has_individual_settlement() ) + if( bitasset.is_individually_settled_to_fund() ) { result = pay_settle_from_individual_pool( d, op, fee_paying_account, *asset_to_settle, bitasset ); // If the amount to settle is too small, or force settlement is disabled, we return - if( bitasset.has_individual_settlement() || !asset_to_settle->can_force_settle() ) + if( bitasset.is_individually_settled_to_fund() || !asset_to_settle->can_force_settle() ) return result; to_settle -= result.value.paid->front(); @@ -1426,7 +1426,7 @@ void_result asset_publish_feeds_evaluator::do_evaluate(const asset_publish_feed_ const asset_bitasset_data_object& bitasset = base.bitasset_data(d); if( bitasset.is_prediction_market || now <= HARDFORK_CORE_216_TIME ) { - FC_ASSERT( !bitasset.has_settlement(), "No further feeds may be published after a settlement event" ); + FC_ASSERT( !bitasset.is_globally_settled(), "No further feeds may be published after a settlement event" ); } // the settlement price must be quoted in terms of the backing asset @@ -1500,7 +1500,7 @@ void_result asset_publish_feeds_evaluator::do_apply(const asset_publish_feed_ope return void_result(); // Feed changed, check whether need to revive the asset and proceed if need - if( bad.has_settlement() // has globally settled, implies head_block_time > HARDFORK_CORE_216_TIME + if( bad.is_globally_settled() // has globally settled, implies head_block_time > HARDFORK_CORE_216_TIME && !bad.current_feed.settlement_price.is_null() ) // has a valid feed { bool should_revive = false; diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index d019a43620..a273d73fa4 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -984,7 +984,7 @@ void database::process_bitassets() for( const auto& d : get_index_type().indices() ) { modify( d, update_bitasset ); - if( d.has_settlement() ) + if( d.is_globally_settled() ) process_bids(d); } } diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index 7809921286..589353c555 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -53,7 +53,7 @@ bool database::check_for_blackswan( const asset_object& mia, bool enable_black_s if( !mia.is_market_issued() ) return false; 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.is_globally_settled() ) return true; // already globally settled auto settle_price = bitasset.current_feed.settlement_price; if( settle_price.is_null() ) return false; // no feed @@ -246,7 +246,7 @@ void database::globally_settle_asset_impl( const asset_object& mia, bool check_margin_calls ) { try { const asset_bitasset_data_object& bitasset = mia.bitasset_data(*this); - FC_ASSERT( !bitasset.has_settlement(), "black swan already occurred, it should not happen again" ); + FC_ASSERT( !bitasset.is_globally_settled(), "black swan already occurred, it should not happen again" ); asset collateral_gathered( 0, bitasset.options.short_backing_asset ); @@ -429,7 +429,7 @@ void database::revive_bitasset( const asset_object& bitasset, const asset_bitass { try { FC_ASSERT( bitasset.is_market_issued() ); FC_ASSERT( bitasset.id == bad.asset_id ); - FC_ASSERT( bad.has_settlement() ); + FC_ASSERT( bad.is_globally_settled() ); FC_ASSERT( !bad.is_prediction_market ); FC_ASSERT( !bad.current_feed.settlement_price.is_null() ); @@ -453,7 +453,7 @@ void database::revive_bitasset( const asset_object& bitasset, const asset_bitass void database::_cancel_bids_and_revive_mpa( const asset_object& bitasset, const asset_bitasset_data_object& bad ) { try { FC_ASSERT( bitasset.is_market_issued() ); - FC_ASSERT( bad.has_settlement() ); + FC_ASSERT( bad.is_globally_settled() ); FC_ASSERT( !bad.is_prediction_market ); // cancel remaining bids @@ -791,7 +791,7 @@ bool database::apply_order(const limit_order_object& new_order_object) sell_abd = &sell_asset.bitasset_data( *this ); if( sell_abd->options.short_backing_asset == recv_asset_id && !sell_abd->is_prediction_market - && !sell_abd->has_settlement() + && !sell_abd->is_globally_settled() && !sell_abd->current_feed.settlement_price.is_null() ) { if( before_core_hardfork_1270 ) { @@ -935,7 +935,7 @@ void database::apply_force_settlement( const force_settlement_object& new_settle FC_ASSERT( HARDFORK_CORE_2481_PASSED( maint_time ), "Internal error: hard fork core-2481 not passed" ); FC_ASSERT( new_settlement.balance.asset_id == bitasset.asset_id, "Internal error: asset type mismatch" ); FC_ASSERT( !bitasset.is_prediction_market, "Internal error: asset is a prediction market" ); - FC_ASSERT( !bitasset.has_settlement(), "Internal error: asset is globally settled already" ); + FC_ASSERT( !bitasset.is_globally_settled(), "Internal error: asset is globally settled already" ); FC_ASSERT( !bitasset.current_feed.settlement_price.is_null(), "Internal error: no sufficient price feeds" ); auto head_time = head_block_time(); @@ -2015,7 +2015,7 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa { // check for blackswan first // TODO perhaps improve performance by passing in iterators bool settled_some = check_for_blackswan( mia, enable_black_swan, &bitasset ); - if( bitasset.has_settlement() ) + if( bitasset.is_globally_settled() ) return margin_called; if( settled_some ) // which implies that BSRM is individual settlement to fund or to order @@ -2263,7 +2263,7 @@ bool database::match_force_settlements( const asset_bitasset_data_object& bitass auto maint_time = get_dynamic_global_properties().next_maintenance_time; FC_ASSERT( HARDFORK_CORE_2481_PASSED( maint_time ), "Internal error: hard fork core-2481 not passed" ); FC_ASSERT( !bitasset.is_prediction_market, "Internal error: asset is a prediction market" ); - FC_ASSERT( !bitasset.has_settlement(), "Internal error: asset is globally settled already" ); + FC_ASSERT( !bitasset.is_globally_settled(), "Internal error: asset is globally settled already" ); FC_ASSERT( !bitasset.current_feed.settlement_price.is_null(), "Internal error: no sufficient price feeds" ); auto head_time = head_block_time(); diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index 59f52e27c0..453b43249e 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -406,7 +406,7 @@ void database::clear_expired_force_settlements() const asset_object& mia_object = *mia_object_ptr; const asset_bitasset_data_object& mia = *mia_ptr; - if( mia.has_settlement() ) + if( mia.is_globally_settled() ) { ilog( "Canceling a force settlement because of black swan" ); cancel_settle_order( settle_order ); diff --git a/libraries/chain/include/graphene/chain/asset_object.hpp b/libraries/chain/include/graphene/chain/asset_object.hpp index 66938a2390..b951538df1 100644 --- a/libraries/chain/include/graphene/chain/asset_object.hpp +++ b/libraries/chain/include/graphene/chain/asset_object.hpp @@ -296,7 +296,7 @@ namespace graphene { namespace chain { share_type max_force_settlement_volume(share_type current_supply)const; /// @return true if the bitasset has been globally settled, false otherwise - bool has_settlement()const { return !settlement_price.is_null(); } + bool is_globally_settled()const { return !settlement_price.is_null(); } /** * In the event of global settlement, all margin positions @@ -321,7 +321,7 @@ namespace graphene { namespace chain { ///@} /// @return true if the individual settlement pool is not empty, false otherwise - bool has_individual_settlement()const { return ( individual_settlement_debt != 0 ); } + bool is_individually_settled_to_fund()const { return ( individual_settlement_debt != 0 ); } /// Get the price of the individual settlement pool price get_individual_settlement_price() const diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 431744a343..56d49de366 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -437,7 +437,7 @@ void_result call_order_update_evaluator::do_evaluate(const call_order_update_ope /// if there is a settlement for this asset, then no further margin positions may be taken and /// all existing margin positions should have been closed va database::globally_settle_asset - FC_ASSERT( !_bitasset_data->has_settlement(), + FC_ASSERT( !_bitasset_data->is_globally_settled(), "Cannot update debt position when the asset has been globally settled" ); FC_ASSERT( o.delta_collateral.asset_id == _bitasset_data->options.short_backing_asset, @@ -718,7 +718,7 @@ void_result bid_collateral_evaluator::do_evaluate(const bid_collateral_operation _bitasset_data = &_debt_asset->bitasset_data(d); - FC_ASSERT( _bitasset_data->has_settlement(), "Cannot bid since the asset is not globally settled" ); + FC_ASSERT( _bitasset_data->is_globally_settled(), "Cannot bid since the asset is not globally settled" ); FC_ASSERT( o.additional_collateral.asset_id == _bitasset_data->options.short_backing_asset ); diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 9b0287903c..525d3da920 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -606,7 +606,7 @@ void database_fixture_base::verify_asset_supplies( const database& db ) total_balances[bad.options.short_backing_asset] += bad.settlement_fund; total_balances[bad.options.short_backing_asset] += bad.individual_settlement_fund; total_balances[bad.options.short_backing_asset] += dasset_obj.accumulated_collateral_fees; - if( !bad.has_settlement() ) // Note: if asset has been globally settled, do not check total debt + if( !bad.is_globally_settled() ) // Note: if asset has been globally settled, do not check total debt total_debts[bad.asset_id] += bad.individual_settlement_debt; } total_balances[asset_obj.get_id()] += dasset_obj.confidential_supply.value; diff --git a/tests/tests/api_limit_tests.cpp b/tests/tests/api_limit_tests.cpp index 18167074b4..c0cfac686a 100644 --- a/tests/tests/api_limit_tests.cpp +++ b/tests/tests/api_limit_tests.cpp @@ -445,7 +445,7 @@ BOOST_AUTO_TEST_CASE(api_limit_get_collateral_bids) { // this sell order is designed to trigger a black swan create_sell_order( borrower2_id(db), swan(db).amount(1), back(db).amount(3) ); - BOOST_CHECK( swan(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan(db).bitasset_data(db).is_globally_settled() ); //making 3 collateral bids for (int i=0; i<3; i++) { diff --git a/tests/tests/bsrm_basic_tests.cpp b/tests/tests/bsrm_basic_tests.cpp index dac4a9b089..b49d71dc3d 100644 --- a/tests/tests/bsrm_basic_tests.cpp +++ b/tests/tests/bsrm_basic_tests.cpp @@ -801,8 +801,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_gs ) using bsrm_type = bitasset_options::black_swan_response_type; BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == bsrm_type::global_settlement ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // add a price feed publisher and publish a feed @@ -830,8 +830,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_gs ) // check BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == bsrm_type::global_settlement ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( !db.find( call_id ) ); @@ -852,8 +852,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_gs ) // recheck BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == bsrm_type::global_settlement ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // publish a new feed to revive the MPA @@ -862,8 +862,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_gs ) publish_feed( mpa_id, feeder_id, f, feed_icr ); // check - revived - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // Sam tries to update BSRM @@ -892,8 +892,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_gs ) // final check BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == static_cast(3) ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); } catch (fc::exception& e) { @@ -944,8 +944,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_individual_settlement_to_fund ) BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() == bsrm_type::individual_settlement_to_fund ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // add a price feed publisher and publish a feed @@ -975,8 +975,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_individual_settlement_to_fund ) publish_feed( mpa_id, feeder_id, f, feed_icr ); // check - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( db.find( call2_id ) ); @@ -1001,8 +1001,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_individual_settlement_to_fund ) // recheck BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() == bsrm_type::individual_settlement_to_fund ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // Settle debt @@ -1010,8 +1010,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_individual_settlement_to_fund ) force_settle( borrower2, asset(100000,mpa_id) ); // recheck - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // Sam tries to update BSRM @@ -1042,8 +1042,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_individual_settlement_to_fund ) // final check BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == static_cast(3) ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); } catch (fc::exception& e) { @@ -1094,8 +1094,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_individual_settlement_to_order ) BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() == bsrm_type::individual_settlement_to_order ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // add a price feed publisher and publish a feed @@ -1125,8 +1125,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_individual_settlement_to_order ) publish_feed( mpa_id, feeder_id, f, feed_icr ); // check - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( db.find( call2_id ) ); @@ -1151,8 +1151,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_individual_settlement_to_order ) // recheck BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() == bsrm_type::individual_settlement_to_order ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( db.find_settled_debt_order(mpa_id) ); // Fill the individual settlement order @@ -1161,8 +1161,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_individual_settlement_to_order ) BOOST_CHECK( !sell_ptr ); // recheck - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // Sam tries to update BSRM @@ -1193,8 +1193,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_individual_settlement_to_order ) // final check BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == static_cast(2) ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); } catch (fc::exception& e) { @@ -1252,8 +1252,8 @@ BOOST_AUTO_TEST_CASE( undercollateralized_and_update_bsrm_from_no_settlement ) BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() == bsrm_type::no_settlement ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // add a price feed publisher and publish a feed @@ -1283,8 +1283,8 @@ BOOST_AUTO_TEST_CASE( undercollateralized_and_update_bsrm_from_no_settlement ) publish_feed( mpa_id, feeder_id, f, feed_icr ); // check - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( db.find( call_id ) ); BOOST_CHECK( db.find( call2_id ) ); @@ -1307,8 +1307,8 @@ BOOST_AUTO_TEST_CASE( undercollateralized_and_update_bsrm_from_no_settlement ) case bsrm_type::global_settlement: BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == bsrm_type::global_settlement ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( !db.find( call2_id ) ); @@ -1316,8 +1316,8 @@ BOOST_AUTO_TEST_CASE( undercollateralized_and_update_bsrm_from_no_settlement ) case bsrm_type::individual_settlement_to_fund: BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == bsrm_type::individual_settlement_to_fund ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( db.find( call2_id ) ); @@ -1325,8 +1325,8 @@ BOOST_AUTO_TEST_CASE( undercollateralized_and_update_bsrm_from_no_settlement ) case bsrm_type::individual_settlement_to_order: BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == bsrm_type::individual_settlement_to_order ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( db.find( call2_id ) ); @@ -1407,8 +1407,8 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) asset_id_type mpa_id = mpa.get_id(); BOOST_CHECK( mpa.bitasset_data(db).get_black_swan_response_method() == static_cast(bsrm) ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // add a price feed publisher and publish a feed @@ -1446,8 +1446,8 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) case bsrm_type::global_settlement: BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == bsrm_type::global_settlement ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( !db.find( call2_id ) ); @@ -1459,8 +1459,8 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) case bsrm_type::no_settlement: BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == bsrm_type::no_settlement ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( db.find( call_id ) ); BOOST_CHECK( db.find( call2_id ) ); @@ -1473,8 +1473,8 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) case bsrm_type::individual_settlement_to_fund: BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == bsrm_type::individual_settlement_to_fund ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( db.find( call2_id ) ); @@ -1491,8 +1491,8 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) case bsrm_type::individual_settlement_to_order: BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == bsrm_type::individual_settlement_to_order ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( db.find( call2_id ) ); @@ -1531,8 +1531,8 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) { BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == bsrm_type::global_settlement ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( !db.find( call2_id ) ); diff --git a/tests/tests/bsrm_indvd_settlement_tests.cpp b/tests/tests/bsrm_indvd_settlement_tests.cpp index 42681117c8..6280b38ce4 100644 --- a/tests/tests/bsrm_indvd_settlement_tests.cpp +++ b/tests/tests/bsrm_indvd_settlement_tests.cpp @@ -129,8 +129,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_test ) BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == f.settlement_price ); BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa.bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // borrowers borrow some @@ -359,8 +359,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_test ) BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); const limit_order_object* settled_debt = db.find_settled_debt_order(mpa_id); BOOST_REQUIRE( settled_debt ); @@ -452,9 +452,9 @@ BOOST_AUTO_TEST_CASE( individual_settlement_test ) // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 24885 ); @@ -645,8 +645,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_disable_force_settle_tes BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // borrowers borrow some @@ -683,8 +683,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_disable_force_settle_tes // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // call: margin call fee deducted = round_down(2000*11/1250) = 17, @@ -708,8 +708,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_disable_force_settle_tes BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price.is_null() ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price.is_null() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1983 ); @@ -738,8 +738,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_disable_force_settle_tes BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1785 ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 90015 ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); if( 0 == i ) @@ -783,8 +783,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_disable_force_settle_tes BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); if( 0 == i ) @@ -898,8 +898,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_no_feed ) BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // borrowers borrow some @@ -933,8 +933,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_no_feed ) // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // call: margin call fee deducted = round_down(2000*11/1250) = 17, @@ -958,8 +958,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_no_feed ) BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price.is_null() ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price.is_null() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1983 ); @@ -998,8 +998,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_no_feed ) BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price.is_null() ); @@ -1108,8 +1108,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_test ) BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == f.settlement_price ); BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa.bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // borrowers borrow some @@ -1161,8 +1161,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_test ) // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // call: margin call fee deducted = round_down(2000*11/1250) = 17, @@ -1264,8 +1264,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_test ) // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); @@ -1430,8 +1430,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_price_test ) BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // borrowers borrow some @@ -1483,8 +1483,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_price_test ) // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // call: margin call fee deducted = round_down(2000*11/1250) = 17, @@ -1565,8 +1565,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_price_test ) // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1983 ); @@ -1611,7 +1611,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_price_test ) BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() ); BOOST_CHECK( *op_result.received->begin() == asset( 1784 ) ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 199 ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 10035 ); @@ -1641,7 +1641,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_price_test ) BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() ); BOOST_CHECK( *op_result.received->begin() == asset( 1983 ) ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); @@ -1673,7 +1673,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_price_test ) BOOST_REQUIRE( op_result.received.valid() && 1U == op_result.received->size() ); BOOST_CHECK( *op_result.received->begin() == asset( 1983 ) ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); @@ -1725,7 +1725,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_price_test ) BOOST_REQUIRE( op_result.fees.valid() && 2U == op_result.fees->size() ); BOOST_CHECK( *op_result.fees->begin() == asset( 167 ) ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 199 ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 10035 ); @@ -1763,7 +1763,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_price_test ) BOOST_REQUIRE( op_result.fees.valid() && 2U == op_result.fees->size() ); BOOST_CHECK( *op_result.fees->begin() == asset( 186 ) ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); @@ -1803,7 +1803,7 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_fund_and_taking_price_test ) BOOST_REQUIRE( op_result.fees.valid() && 2U == op_result.fees->size() ); BOOST_CHECK( *op_result.fees->begin() == asset( 186 ) ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); @@ -1935,8 +1935,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa.bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // borrowers borrow some @@ -1987,8 +1987,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test // check BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa.bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_individually_settled_to_fund() ); const limit_order_object* settled_debt = db.find_settled_debt_order(mpa_id); BOOST_REQUIRE( settled_debt ); @@ -2053,8 +2053,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa.bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( !db.find( call2_id ) ); @@ -2254,8 +2254,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test { BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); if( 0 == i ) { @@ -2456,8 +2456,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_taker_test BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa.bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // borrowers borrow some @@ -2484,8 +2484,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_taker_test // check BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa.bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_individually_settled_to_fund() ); const limit_order_object* settled_debt = db.find_settled_debt_order(mpa_id); BOOST_REQUIRE( settled_debt ); @@ -2682,8 +2682,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_taker_test { BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); // the settled-debt order was: // settled_debt_amount = 90015 @@ -2936,8 +2936,8 @@ BOOST_AUTO_TEST_CASE( settle_order_cancel_due_to_no_debt_position ) BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa.bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // borrowers borrow some @@ -2973,8 +2973,8 @@ BOOST_AUTO_TEST_CASE( settle_order_cancel_due_to_no_debt_position ) // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); const limit_order_object* settled_debt = db.find_settled_debt_order(mpa_id); BOOST_REQUIRE( settled_debt ); @@ -3011,8 +3011,8 @@ BOOST_AUTO_TEST_CASE( settle_order_cancel_due_to_no_debt_position ) // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); settled_debt = db.find_settled_debt_order(mpa_id); BOOST_REQUIRE( settled_debt ); diff --git a/tests/tests/bsrm_no_settlement_tests.cpp b/tests/tests/bsrm_no_settlement_tests.cpp index db7d304da9..46958c54ed 100644 --- a/tests/tests/bsrm_no_settlement_tests.cpp +++ b/tests/tests/bsrm_no_settlement_tests.cpp @@ -112,7 +112,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_margin_call_test ) // check BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(1250,mpa_id), asset(2000) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // borrower3 is unable to create debt position if its CR is below ICR which is calculated with median_feed // 1000 * (2000/1250) * 1.9 = 3040 @@ -131,7 +131,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_margin_call_test ) // check BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(1250,mpa_id), asset(2100) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // Sam update MSSR and MCFR // note: borrower's position is undercollateralized again due to the mssr change @@ -151,7 +151,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_margin_call_test ) BOOST_CHECK_EQUAL( mpa.bitasset_data(db).current_feed.maximum_short_squeeze_ratio, 1300u ); BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(1300,mpa_id), asset(2100) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // Transfer funds to sellers transfer( borrower, seller, asset(1000,mpa_id) ); @@ -203,7 +203,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_margin_call_test ) BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(11557,mpa_id), asset(18670) ) ); // 13:10 * (1000-111):(2100-111*210/100) // 13:10 * 889:1867 - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); BOOST_CHECK_EQUAL( call_id(db).debt.value, 1000 ); BOOST_CHECK_EQUAL( call_id(db).collateral.value, 2750 ); @@ -253,7 +253,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_margin_call_test ) BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(8957,mpa_id), asset(19600) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); BOOST_CHECK_EQUAL( call_id(db).debt.value, 689 ); BOOST_CHECK_EQUAL( call_id(db).collateral.value, 1960 ); @@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_margin_call_test ) BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find(call_id) ); BOOST_CHECK( !db.find(call2_id) ); @@ -381,7 +381,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_small_limit_taker_test ) // check BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(125000,mpa_id), asset(2000) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // borrower3 is unable to create debt position if its CR is below ICR which is calculated with median_feed // 100000 * (2000/125000) * 1.9 = 3040 @@ -400,7 +400,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_small_limit_taker_test ) // check BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(125000,mpa_id), asset(2100) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // Sam update MSSR and MCFR // note: borrower's position is undercollateralized again due to the mssr change @@ -420,7 +420,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_small_limit_taker_test ) BOOST_CHECK_EQUAL( mpa.bitasset_data(db).current_feed.maximum_short_squeeze_ratio, 1300u ); BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(130000,mpa_id), asset(2100) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // Transfer funds to sellers transfer( borrower, seller, asset(100000,mpa_id) ); @@ -478,7 +478,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_small_limit_taker_test ) BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(1156259,mpa_id), asset(18680) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); BOOST_CHECK_EQUAL( call_id(db).debt.value, 100000 ); BOOST_CHECK_EQUAL( call_id(db).collateral.value, 2750 ); @@ -545,7 +545,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_small_limit_taker_test ) BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == price( asset(896649,mpa_id), asset(19620) ) ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK_EQUAL( call_id(db).debt.value, 68973 ); BOOST_CHECK_EQUAL( call_id(db).collateral.value, 1962 ); @@ -646,7 +646,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_force_settle_test ) // check BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(1250,mpa_id), asset(2000) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // borrower3 is unable to create debt position if its CR is below ICR which is calculated with median_feed // 1000 * (2000/1250) * 1.9 = 3040 @@ -665,7 +665,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_force_settle_test ) // check BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(1250,mpa_id), asset(2100) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // Sam update MSSR and MCFR // note: borrower's position is undercollateralized again due to the mssr change @@ -685,7 +685,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_force_settle_test ) BOOST_CHECK_EQUAL( mpa.bitasset_data(db).current_feed.maximum_short_squeeze_ratio, 1300u ); BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(1300,mpa_id), asset(2100) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // Transfer funds to sellers transfer( borrower, seller, asset(1000,mpa_id) ); @@ -738,7 +738,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_force_settle_test ) BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(11557,mpa_id), asset(18670) ) ); // 13:10 * (1000-111):(2100-111*210/100) // 13:10 * 889:1867 - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); BOOST_CHECK_EQUAL( call_id(db).debt.value, 1000 ); BOOST_CHECK_EQUAL( call_id(db).collateral.value, 2750 ); @@ -796,7 +796,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_force_settle_test ) BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(8957,mpa_id), asset(19510) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); BOOST_CHECK_EQUAL( call_id(db).debt.value, 689 ); BOOST_CHECK_EQUAL( call_id(db).collateral.value, 1951 ); @@ -826,7 +826,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_force_settle_test ) BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find(call_id) ); BOOST_CHECK( !db.find(call2_id) ); @@ -924,7 +924,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_small_settle_taker_test ) // check BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(125000,mpa_id), asset(2000) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // borrower3 is unable to create debt position if its CR is below ICR which is calculated with median_feed // 100000 * (2000/125000) * 1.9 = 3040 @@ -943,7 +943,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_small_settle_taker_test ) // check BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(125000,mpa_id), asset(2100) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // Sam update MSSR and MCFR // note: borrower's position is undercollateralized again due to the mssr change @@ -963,7 +963,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_small_settle_taker_test ) BOOST_CHECK_EQUAL( mpa.bitasset_data(db).current_feed.maximum_short_squeeze_ratio, 1300u ); BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(130000,mpa_id), asset(2100) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // Transfer funds to sellers transfer( borrower, seller, asset(100000,mpa_id) ); @@ -1025,7 +1025,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_maker_small_settle_taker_test ) BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == price( asset(1156259,mpa_id), asset(18680) ) ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK_EQUAL( call_id(db).debt.value, 100000 ); BOOST_CHECK_EQUAL( call_id(db).collateral.value, 2750 ); @@ -1327,7 +1327,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_taker_test ) auto check_result = [&] { BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), expected_seller_balance_mpa ); BOOST_CHECK_EQUAL( get_balance( seller2_id, mpa_id ), expected_seller2_balance_mpa ); BOOST_CHECK_EQUAL( call3_id(db).debt.value, 1000 ); @@ -2254,7 +2254,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_update_debt_test ) // check BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(125000,mpa_id), asset(2000) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // borrower3 is unable to create debt position if its CR is below ICR which is calculated with median_feed // 100000 * (2000/125000) * 1.9 = 3040 @@ -2273,7 +2273,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_update_debt_test ) // check BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(125000,mpa_id), asset(2100) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // Sam update MSSR and MCFR // note: borrower's position is undercollateralized again due to the mssr change @@ -2293,7 +2293,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_update_debt_test ) BOOST_CHECK_EQUAL( mpa.bitasset_data(db).current_feed.maximum_short_squeeze_ratio, 1300u ); BOOST_CHECK( mpa.bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa.bitasset_data(db).current_feed.settlement_price == price( asset(130000,mpa_id), asset(2100) ) ); - BOOST_CHECK( !mpa.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa.bitasset_data(db).is_globally_settled() ); // Transfer funds to seller2 transfer( borrower3, seller2, asset(50000,mpa_id) ); @@ -2376,7 +2376,7 @@ BOOST_AUTO_TEST_CASE( no_settlement_update_debt_test ) { BOOST_TEST_MESSAGE( "Check result"); BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK_EQUAL( call3_id(db).debt.value, 100000 ); BOOST_CHECK_EQUAL( call3_id(db).collateral.value, 4181 ); diff --git a/tests/tests/force_settle_match_tests.cpp b/tests/tests/force_settle_match_tests.cpp index 6b2023e75d..8f2095202a 100644 --- a/tests/tests/force_settle_match_tests.cpp +++ b/tests/tests/force_settle_match_tests.cpp @@ -1203,7 +1203,7 @@ BOOST_AUTO_TEST_CASE(call_settle_blackswan) share_type settle4_refund = 5; // blackswan event occurs - BOOST_CHECK( usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( usd_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( db.find( call_id ) == nullptr ); BOOST_CHECK( db.find( call2_id ) == nullptr ); BOOST_CHECK( db.find( call3_id ) == nullptr ); @@ -1453,7 +1453,7 @@ BOOST_AUTO_TEST_CASE(call_settle_limit_settle) BOOST_CHECK_EQUAL( 40000, call3_id(db).collateral.value ); // blackswan event did not occur - BOOST_CHECK( !usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !usd_id(db).bitasset_data(db).is_globally_settled() ); // check balances BOOST_CHECK_EQUAL( 0, get_balance(seller_id, usd_id) ); diff --git a/tests/tests/margin_call_fee_tests.cpp b/tests/tests/margin_call_fee_tests.cpp index acb8592ea6..85ff2b0fd4 100644 --- a/tests/tests/margin_call_fee_tests.cpp +++ b/tests/tests/margin_call_fee_tests.cpp @@ -373,7 +373,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) ////// call_order_id_type bob_call_id = (*borrow(bob, bob_initial_smart, bob_initial_core)).get_id(); BOOST_REQUIRE_EQUAL(get_balance(bob, smartbit), 200 * SMARTBIT_UNIT); - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); // No global settlement + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // No global settlement const price bob_initial_cr = bob_call_id(db).collateralization(); // Units of collateral / debt BOOST_CHECK_EQUAL(bob_initial_cr.base.amount.value, 80000000); // Collateral of 80,000,000 satoshi CORE BOOST_CHECK_EQUAL(bob_initial_cr.quote.amount.value, 2000000); // Debt of 2,000,000 satoshi SMARTBIT @@ -401,7 +401,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) publish_feed(smartbit, feedproducer_id(db), current_feed); BOOST_CHECK(smartbit.bitasset_data(db).current_feed.settlement_price == current_feed.settlement_price); - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); // No global settlement + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // No global settlement // Check Bob's debt to the blockchain BOOST_CHECK_EQUAL(bob_call_id(db).debt.value, bob_initial_smart.amount.value); @@ -652,7 +652,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) ////// call_order_id_type bob_call_id = (*borrow(bob, bob_initial_smart, bob_initial_core)).get_id(); BOOST_REQUIRE_EQUAL(get_balance(bob, smartbit), 200 * SMARTBIT_UNIT); - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); // No global settlement + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // No global settlement const price bob_initial_cr = bob_call_id(db).collateralization(); // Units of collateral / debt BOOST_CHECK_EQUAL(bob_initial_cr.base.amount.value, 80000000); // Collateral of 80,000,000 satoshi CORE BOOST_CHECK_EQUAL(bob_initial_cr.quote.amount.value, 2000000); // Debt of 2,000,000 satoshi SMARTBIT @@ -680,7 +680,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) publish_feed(smartbit, feedproducer_id(db), current_feed); BOOST_CHECK(smartbit.bitasset_data(db).current_feed.settlement_price == current_feed.settlement_price); - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); // No global settlement + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // No global settlement // Check Bob's debt to the blockchain BOOST_CHECK_EQUAL(bob_call_id(db).debt.value, bob_initial_smart.amount.value); @@ -699,7 +699,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) // Charlie obtains his SMARTBIT by borrowing it from the blockchain call_order_id_type charlie_call_id = (*borrow(charlie, charlie_initial_smart, charlie_initial_core)).get_id(); BOOST_REQUIRE_EQUAL(get_balance(charlie, smartbit), 200 * SMARTBIT_UNIT); - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); // No global settlement + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // No global settlement const price charlie_initial_cr = charlie_call_id(db).collateralization(); // Units of collateral / debt BOOST_CHECK_EQUAL(charlie_initial_cr.base.amount.value, 120000000); // Collateral of 120,000,000 satoshi CORE BOOST_CHECK_EQUAL(charlie_initial_cr.quote.amount.value, 2000000); // Debt of 2,000,000 satoshi SMARTBIT @@ -974,7 +974,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) const uint16_t tcr = 2200; // Bob's target collateral ratio (TCR) 220% expressed in terms of GRAPHENE_COLLATERAL_RATIO_DENOM call_order_id_type bob_call_id = (*borrow(bob, bob_initial_smart, bob_initial_core, tcr)).get_id(); BOOST_REQUIRE_EQUAL(get_balance(bob, smartbit), 200 * SMARTBIT_UNIT); - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); // No global settlement + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // No global settlement const price bob_initial_cr = bob_call_id(db).collateralization(); // Units of collateral / debt BOOST_CHECK_EQUAL(bob_initial_cr.base.amount.value, 80000000); // Collateral of 80,000,000 satoshi CORE BOOST_CHECK_EQUAL(bob_initial_cr.quote.amount.value, 2000000); // Debt of 2,000,000 satoshi SMARTBIT @@ -1002,7 +1002,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) publish_feed(smartbit, feedproducer_id(db), current_feed); BOOST_CHECK(smartbit.bitasset_data(db).current_feed.settlement_price == current_feed.settlement_price); - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); // No global settlement + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // No global settlement // Check Bob's debt to the blockchain BOOST_CHECK_EQUAL(bob_call_id(db).debt.value, bob_initial_smart.amount.value); @@ -1343,7 +1343,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) call_order_id_type alice_call_id = (*borrow(alice, alice_initial_smart, alice_initial_core)).get_id(); BOOST_CHECK_EQUAL(get_balance(alice_id(db), smartbit_id(db)), 500 * SMARTBIT_UNIT); BOOST_CHECK_EQUAL(get_balance(alice_id, core_id), 0 * CORE_UNIT); - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); // No global settlement + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // No global settlement // Alice offer to sell the SMARTBIT // Create a "large" sell order at a "high" price of settlement_price * 1.1 = settlement_price * (11/10) @@ -1382,7 +1382,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) // Bobs's balances should reflect that CORE was used to create SMARTBIT BOOST_CHECK_EQUAL(get_balance(bob_id, smartbit_id), 200 * SMARTBIT_UNIT); BOOST_CHECK_EQUAL(get_balance(bob_id, core_id), 0); - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); // No global settlement + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // No global settlement const price bob_initial_cr = bob_call_id(db).collateralization(); // Units of collateral / debt BOOST_CHECK(bob_initial_cr == expected_bob_initial_cr); BOOST_CHECK_EQUAL(bob_initial_cr.base.amount.value, 80000000); // Collateral of 80,000,000 satoshi CORE @@ -1422,7 +1422,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) // Confirm the updated feed BOOST_CHECK(smartbit.bitasset_data(db).current_feed.settlement_price == current_feed.settlement_price); // Confirm no global settlement - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // The margin call of Bob's position should have closed the debt of bob_initial_smart @@ -1641,7 +1641,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) borrow(alice, alice_initial_smart, alice_initial_core); BOOST_CHECK_EQUAL(get_balance(alice_id(db), smartbit_id(db)), 500 * SMARTBIT_UNIT); BOOST_CHECK_EQUAL(get_balance(alice_id, core_id), 0 * CORE_UNIT); - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); // No global settlement + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // No global settlement // Alice offer to sell the SMARTBIT // Create a "large" sell order at a "high" price of settlement_price * 1.1 = settlement_price * (11/10) @@ -1679,7 +1679,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) const uint16_t tcr = 2200; // Bob's target collateral ratio (TCR) 220% expressed in terms of GRAPHENE_COLLATERAL_RATIO_DENOM call_order_id_type bob_call_id = (*borrow(bob, bob_initial_smart, bob_initial_core, tcr)).get_id(); BOOST_REQUIRE_EQUAL(get_balance(bob, smartbit), 200 * SMARTBIT_UNIT); - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); // No global settlement + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // No global settlement const price bob_initial_cr = bob_call_id(db).collateralization(); // Units of collateral / debt BOOST_CHECK_EQUAL(bob_initial_cr.base.amount.value, 80000000); // Collateral of 80,000,000 satoshi CORE BOOST_CHECK_EQUAL(bob_initial_cr.quote.amount.value, 2000000); // Debt of 2,000,000 satoshi SMARTBIT @@ -1709,7 +1709,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) // Confirm the updated feed BOOST_CHECK(smartbit.bitasset_data(db).current_feed.settlement_price == current_feed.settlement_price); // Confirm no global settlement - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // When a TCR is set for a call order, the ideal is to not sell all of the collateral // but only enough collateral so that the remaining collateral and the remaining debt in the debt position @@ -2040,7 +2040,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) call_order_id_type alice_call_id = (*borrow(alice, alice_initial_smart, alice_initial_core)).get_id(); BOOST_CHECK_EQUAL(get_balance(alice_id(db), smartbit_id(db)), 500 * SMARTBIT_UNIT); BOOST_CHECK_EQUAL(get_balance(alice_id, core_id), 0 * CORE_UNIT); - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); // No global settlement + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // No global settlement // Alice offer to sell the SMARTBIT const asset alice_debt_to_sell = smartbit.amount(500 * SMARTBIT_UNIT); @@ -2085,7 +2085,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) // Bobs's balances should reflect that CORE was used to create SMARTBIT BOOST_CHECK_EQUAL(get_balance(bob_id, smartbit_id), 200 * SMARTBIT_UNIT); BOOST_CHECK_EQUAL(get_balance(bob_id, core_id), 0); - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); // No global settlement + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // No global settlement const price bob_initial_cr = bob_call_id(db).collateralization(); // Units of collateral / debt BOOST_CHECK(bob_initial_cr == expected_bob_initial_cr); BOOST_CHECK_EQUAL(bob_initial_cr.base.amount.value, 80000000); // Collateral of 80,000,000 satoshi CORE @@ -2120,7 +2120,7 @@ BOOST_FIXTURE_TEST_SUITE(margin_call_fee_tests, bitasset_database_fixture) // Confirm the updated feed BOOST_CHECK(smartbit.bitasset_data(db).current_feed.settlement_price == current_feed.settlement_price); // Confirm no global settlement - BOOST_CHECK(!smartbit.bitasset_data(db).has_settlement()); + BOOST_CHECK(!smartbit.bitasset_data(db).is_globally_settled()); // Verify the margin call order price is as planned BOOST_CHECK(smartbit_id(db).bitasset_data(db).current_feed.margin_call_order_price(initial_mcfr) == planned_initial_mcop); diff --git a/tests/tests/market_tests.cpp b/tests/tests/market_tests.cpp index aa0be76841..d15eb54fcb 100644 --- a/tests/tests/market_tests.cpp +++ b/tests/tests/market_tests.cpp @@ -186,7 +186,7 @@ BOOST_AUTO_TEST_CASE(issue_338_etc) // settlement price = 1/20, mssp = 1/22 // black swan event doesn't occur #649 - BOOST_CHECK( !usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !usd_id(db).bitasset_data(db).is_globally_settled() ); // generate a block generate_block(); @@ -418,7 +418,7 @@ BOOST_AUTO_TEST_CASE(hardfork_core_338_test) // settlement price = 1/16, mssp = 10/176 // black swan event will occur: #649 fixed - BOOST_CHECK( usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( usd_id(db).bitasset_data(db).is_globally_settled() ); // short positions will be closed BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( !db.find( call2_id ) ); @@ -958,7 +958,7 @@ BOOST_AUTO_TEST_CASE(hard_fork_338_cross_test) // settlement price = 1/16, mssp = 10/176 // due to sell_low, black swan won't occur - BOOST_CHECK( !usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !usd_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK_EQUAL( 3000-1000-1007-7, get_balance(seller_id, usd_id) ); BOOST_CHECK_EQUAL( 0, get_balance(seller, core) ); @@ -982,7 +982,7 @@ BOOST_AUTO_TEST_CASE(hard_fork_338_cross_test) // collateralization of call3 is (16000-56-64) / (1000-7-7) = 15880/986 = 16.1, it's > 16 but < 17.6 // although there is no sell order, it should trigger a black swan event right away, // because after hard fork new limit order won't trigger black swan event - BOOST_CHECK( usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( usd_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find( call3_id ) ); BOOST_CHECK( !db.find( call4_id ) ); @@ -1084,16 +1084,16 @@ BOOST_AUTO_TEST_CASE(hard_fork_649_cross_test) // settlement price = 1/20, mssp = 1/22 // due to #649, black swan won't occur - BOOST_CHECK( !usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !usd_id(db).bitasset_data(db).is_globally_settled() ); // generate a block to include operations above generate_block(); - BOOST_CHECK( !usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !usd_id(db).bitasset_data(db).is_globally_settled() ); // go over the hard fork, make sure feed doesn't expire generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); // a black swan event should occur - BOOST_CHECK( usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( usd_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( !db.find( call2_id ) ); BOOST_CHECK( !db.find( call3_id ) ); @@ -1313,7 +1313,7 @@ BOOST_AUTO_TEST_CASE(mcfr_blackswan_test) // settlement price = 1/18, mssp = 10/198 // GS occurs even when there is a good sell order - BOOST_CHECK( usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( usd_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( !db.find( call2_id ) ); // GS price is 1/18, but the first call order has only 15000 thus capped @@ -1419,7 +1419,7 @@ BOOST_AUTO_TEST_CASE(mcfr_blackswan_test_after_hf_core_2481) // settlement price = 1/18, mssp = 10/198 // GS occurs even when there is a good sell order - BOOST_CHECK( usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( usd_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( !db.find( call2_id ) ); BOOST_CHECK( !db.find( call3_id ) ); @@ -1517,7 +1517,7 @@ BOOST_AUTO_TEST_CASE(gs_price_test) if( !hf2481 ) { // GS occurs - BOOST_CHECK( usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( usd_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( !db.find( call2_id ) ); // sell order did not change @@ -1526,7 +1526,7 @@ BOOST_AUTO_TEST_CASE(gs_price_test) else { // GS does not occur, call got filled - BOOST_CHECK( !usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !usd_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find( call_id ) ); // sell order got half-filled @@ -1648,7 +1648,7 @@ BOOST_AUTO_TEST_CASE(mcfr_rounding_test) publish_feed( bitusd, feedproducer, feed2 ); // blackswan - BOOST_CHECK( usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( usd_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( !db.find( call2_id ) ); int64_t call_pays_to_fund = (15000 * 10 + 10) / 11; @@ -1696,7 +1696,7 @@ BOOST_AUTO_TEST_CASE(mcfr_rounding_test) generate_blocks( db.head_block_time() + fc::seconds(43200) ); // The first call order should have been filled - BOOST_CHECK( !usd_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !usd_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK( !db.find( call_id ) ); BOOST_REQUIRE( db.find( call2_id ) ); diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index aad129cdb2..be81f64df4 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -1074,7 +1074,7 @@ BOOST_AUTO_TEST_CASE( bid_collateral_operation_asset_auth_test ) BOOST_TEST_MESSAGE( "Trigger a black swan event" ); current_feed.settlement_price = bitusd.amount( 10 ) / backasset.amount( 100 ); publish_feed( bitusd, sam, current_feed ); - BOOST_REQUIRE( bitusd.bitasset_data(db).has_settlement() ); + BOOST_REQUIRE( bitusd.bitasset_data(db).is_globally_settled() ); // Reproduces bitshares-core issue #973: no asset authorization check thus Dan is able to bid collateral BOOST_TEST_MESSAGE( "Dan and Sam attempting to bid collateral" ); diff --git a/tests/tests/settle_tests.cpp b/tests/tests/settle_tests.cpp index 440987c5cc..2cb8292899 100644 --- a/tests/tests/settle_tests.cpp +++ b/tests/tests/settle_tests.cpp @@ -1965,8 +1965,8 @@ BOOST_AUTO_TEST_CASE( collateral_fee_of_instant_settlement_test ) BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // borrowers borrow some @@ -1993,8 +1993,8 @@ BOOST_AUTO_TEST_CASE( collateral_fee_of_instant_settlement_test ) // check BOOST_CHECK( mpa_id(db).bitasset_data(db).median_feed.settlement_price == f.settlement_price ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_settlement() ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_globally_settled() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); // fund receives 1600 @@ -2040,8 +2040,8 @@ BOOST_AUTO_TEST_CASE( collateral_fee_of_instant_settlement_test ) BOOST_REQUIRE( op_result.fees.valid() && 2U == op_result.fees->size() ); BOOST_CHECK( *op_result.fees->begin() == asset( 204 ) ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).settlement_fund.value, 692 ); BOOST_CHECK( mpa_id(db).dynamic_data(db).accumulated_collateral_fees == 604 ); // 400 + 204 @@ -2062,8 +2062,8 @@ BOOST_AUTO_TEST_CASE( collateral_fee_of_instant_settlement_test ) BOOST_REQUIRE( op_result.fees.valid() && 1U == op_result.fees->size() ); BOOST_CHECK( *op_result.fees->begin() == asset( 0 ) ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_individual_settlement() ); - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_individually_settled_to_fund() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).settlement_fund.value, 692 ); BOOST_CHECK( mpa_id(db).dynamic_data(db).accumulated_collateral_fees == 400 ); @@ -2167,8 +2167,8 @@ BOOST_AUTO_TEST_CASE( pm_instant_settlement_price_test ) auto check_result = [&] { - BOOST_CHECK( !pm_id(db).bitasset_data(db).has_individual_settlement() ); - BOOST_CHECK( pm_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !pm_id(db).bitasset_data(db).is_individually_settled_to_fund() ); + BOOST_CHECK( pm_id(db).bitasset_data(db).is_globally_settled() ); BOOST_CHECK_EQUAL( pm_id(db).bitasset_data(db).settlement_fund.value, 700 ); BOOST_CHECK_EQUAL( pm_id(db).dynamic_data(db).accumulated_collateral_fees.value, 0 ); @@ -2384,7 +2384,7 @@ BOOST_AUTO_TEST_CASE( settle_order_cancel_due_to_gs ) BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 88900 ); // 100000 - 11100 BOOST_CHECK_EQUAL( get_balance( seller_id, asset_id_type() ), 0 ); - BOOST_CHECK( !mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_globally_settled() ); // generate a block generate_block(); @@ -2402,7 +2402,7 @@ BOOST_AUTO_TEST_CASE( settle_order_cancel_due_to_gs ) publish_feed( mpa_id, feeder_id, f ); // check - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_globally_settled() ); BOOST_REQUIRE( db.find(settle_id) ); @@ -2415,7 +2415,7 @@ BOOST_AUTO_TEST_CASE( settle_order_cancel_due_to_gs ) generate_block(); // check - BOOST_CHECK( mpa_id(db).bitasset_data(db).has_settlement() ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_globally_settled() ); // the settle order is cancelled BOOST_REQUIRE( !db.find(settle_id) ); diff --git a/tests/tests/swan_tests.cpp b/tests/tests/swan_tests.cpp index 4711f46e0d..9988dec23c 100644 --- a/tests/tests/swan_tests.cpp +++ b/tests/tests/swan_tests.cpp @@ -113,7 +113,7 @@ struct swan_fixture : database_fixture { FC_ASSERT( get_balance(borrower2(), back()) == init_balance - (2*amount2*denom+mssr-1)/mssr); } - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); return oid; } @@ -238,7 +238,7 @@ BOOST_AUTO_TEST_CASE( black_swan_issue_346 ) { const asset_object& bitusd = create_bitasset("USDBIT"+fc::to_string(trial)+"X", feeder_id); update_feed_producers( bitusd, {feeder.get_id()} ); - BOOST_CHECK( !bitusd.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !bitusd.bitasset_data(db).is_globally_settled() ); trial++; return bitusd; }; @@ -286,9 +286,9 @@ BOOST_AUTO_TEST_CASE( black_swan_issue_346 ) transfer( borrower, settler, bitusd.amount(100) ); // drop to $0.02 and settle - BOOST_CHECK( !bitusd.bitasset_data(db).has_settlement() ); + BOOST_CHECK( !bitusd.bitasset_data(db).is_globally_settled() ); set_price( bitusd, bitusd.amount(1) / core.amount(50) ); // $0.02 - BOOST_CHECK( bitusd.bitasset_data(db).has_settlement() ); + BOOST_CHECK( bitusd.bitasset_data(db).is_globally_settled() ); GRAPHENE_REQUIRE_THROW( borrow( borrower2, bitusd.amount(100), asset(10000) ), fc::exception ); force_settle( settler, bitusd.amount(100) ); @@ -314,7 +314,7 @@ BOOST_AUTO_TEST_CASE( black_swan_issue_346 ) // We attempt to match against $0.019 order and black swan, // and this is intended behavior. See discussion in ticket. // - BOOST_CHECK( bitusd.bitasset_data(db).has_settlement() ); + BOOST_CHECK( bitusd.bitasset_data(db).is_globally_settled() ); BOOST_CHECK( db.find( oid_019 ) != nullptr ); BOOST_CHECK( db.find( oid_020 ) == nullptr ); } @@ -340,9 +340,9 @@ BOOST_AUTO_TEST_CASE( revive_recovered ) // revive after price recovers set_feed( 700, 800 ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); set_feed( 701, 800 ); - BOOST_CHECK( !swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( !swan().bitasset_data(db).is_globally_settled() ); graphene::app::database_api db_api( db, &( app.get_options() )); auto swan_symbol = _swan(db).symbol; @@ -375,11 +375,11 @@ BOOST_AUTO_TEST_CASE( revive_recovered_with_bids ) // price not good enough for recovery set_feed( 700, 800 ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); bid_collateral( borrower(), back().amount(10510), swan().amount(700) ); bid_collateral( borrower2(), back().amount(21000), swan().amount(1399) ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); graphene::app::database_api db_api( db, &( app.get_options() )); auto swan_symbol = _swan(db).symbol; @@ -388,7 +388,7 @@ BOOST_AUTO_TEST_CASE( revive_recovered_with_bids ) // revive after price recovers set_feed( 701, 800 ); - BOOST_CHECK( !swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( !swan().bitasset_data(db).is_globally_settled() ); bids = db_api.get_collateral_bids(swan_symbol, 100, 0); BOOST_CHECK( bids.empty() ); @@ -420,18 +420,18 @@ BOOST_AUTO_TEST_CASE( revive_recovered_with_bids_not_by_icr_before_hf_core_2290 BOOST_CHECK( swan().dynamic_data(db).current_supply == 1400 ); BOOST_CHECK( swan().bitasset_data(db).settlement_fund == 2800 ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); BOOST_CHECK( swan().bitasset_data(db).current_feed.settlement_price.is_null() ); BOOST_REQUIRE( HARDFORK_BSIP_77_PASSED( db.head_block_time() ) ); // price not good enough for recovery set_feed( 700, 800, 1750, 1800 ); // MCR = 1750, ICR = 1800 - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); bid_collateral( borrower(), back().amount(10510), swan().amount(700) ); bid_collateral( borrower2(), back().amount(21000), swan().amount(1399) ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); graphene::app::database_api db_api( db, &( app.get_options() )); auto swan_symbol = _swan(db).symbol; @@ -440,7 +440,7 @@ BOOST_AUTO_TEST_CASE( revive_recovered_with_bids_not_by_icr_before_hf_core_2290 // good feed price set_feed( 701, 800, 1750, 1800 ); // MCR = 1750, ICR = 1800 - BOOST_CHECK( !swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( !swan().bitasset_data(db).is_globally_settled() ); bids = db_api.get_collateral_bids(swan_symbol, 100, 0); BOOST_CHECK( bids.empty() ); @@ -473,16 +473,16 @@ BOOST_AUTO_TEST_CASE( revive_recovered_with_bids_by_icr_after_hf_core_2290 ) BOOST_CHECK( swan().dynamic_data(db).current_supply == 1400 ); BOOST_CHECK( swan().bitasset_data(db).settlement_fund == 2800 ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); BOOST_CHECK( swan().bitasset_data(db).current_feed.settlement_price.is_null() ); // price not good enough for recovery set_feed( 700, 800, 1750, 1800 ); // MCR = 1750, ICR = 1800 - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); bid_collateral( borrower(), back().amount(10510), swan().amount(700) ); bid_collateral( borrower2(), back().amount(21000), swan().amount(1399) ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); graphene::app::database_api db_api( db, &( app.get_options() )); auto swan_symbol = _swan(db).symbol; @@ -491,19 +491,19 @@ BOOST_AUTO_TEST_CASE( revive_recovered_with_bids_by_icr_after_hf_core_2290 ) // price still not good enough for recovery set_feed( 701, 800, 1750, 1800 ); // MCR = 1750, ICR = 1800 - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); bids = db_api.get_collateral_bids(swan_symbol, 100, 0); BOOST_CHECK_EQUAL( 2u, bids.size() ); // price still not good enough for recovery set_feed( 720, 800, 1750, 1800 ); // MCR = 1750, ICR = 1800 - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); bids = db_api.get_collateral_bids(swan_symbol, 100, 0); BOOST_CHECK_EQUAL( 2u, bids.size() ); // good feed price set_feed( 721, 800, 1750, 1800 ); // MCR = 1750, ICR = 1800 - BOOST_CHECK( !swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( !swan().bitasset_data(db).is_globally_settled() ); bids = db_api.get_collateral_bids(swan_symbol, 100, 0); BOOST_CHECK( bids.empty() ); @@ -570,26 +570,26 @@ BOOST_AUTO_TEST_CASE( recollateralize ) BOOST_CHECK( swan().dynamic_data(db).current_supply == 1400 ); BOOST_CHECK( swan().bitasset_data(db).settlement_fund == 2800 ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); BOOST_CHECK( swan().bitasset_data(db).current_feed.settlement_price.is_null() ); // doesn't happen without price feed bid_collateral( borrower(), back().amount(1400), swan().amount(700) ); bid_collateral( borrower2(), back().amount(1400), swan().amount(700) ); wait_for_maintenance(); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); set_feed(1, 2); // doesn't happen if cover is insufficient bid_collateral( borrower2(), back().amount(1400), swan().amount(600) ); wait_for_maintenance(); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); set_feed(1, 2); // doesn't happen if some bids have a bad swan price bid_collateral( borrower2(), back().amount(1050), swan().amount(700) ); wait_for_maintenance(); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); set_feed(1, 2); // works @@ -611,10 +611,10 @@ BOOST_AUTO_TEST_CASE( recollateralize ) FC_ASSERT( _borrower == bids[0].bidder ); FC_ASSERT( _borrower2 == bids[1].bidder ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); // revive wait_for_maintenance(); - BOOST_CHECK( !swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( !swan().bitasset_data(db).is_globally_settled() ); bids = db_api.get_collateral_bids(swan_symbol, 100, 0); BOOST_CHECK( bids.empty() ); } catch( const fc::exception& e) { @@ -637,7 +637,7 @@ BOOST_AUTO_TEST_CASE( recollateralize_not_by_icr_before_hf_core_2290 ) BOOST_CHECK( swan().dynamic_data(db).current_supply == 1400 ); BOOST_CHECK( swan().bitasset_data(db).settlement_fund == 2800 ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); BOOST_CHECK( swan().bitasset_data(db).current_feed.settlement_price.is_null() ); BOOST_REQUIRE( HARDFORK_BSIP_77_PASSED( db.head_block_time() ) ); @@ -654,7 +654,7 @@ BOOST_AUTO_TEST_CASE( recollateralize_not_by_icr_before_hf_core_2290 ) // revive wait_for_maintenance(); - BOOST_CHECK( !swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( !swan().bitasset_data(db).is_globally_settled() ); bids = db_api.get_collateral_bids(swan_symbol, 100, 0); BOOST_CHECK( bids.empty() ); @@ -680,7 +680,7 @@ BOOST_AUTO_TEST_CASE( recollateralize_by_icr_after_hf_core_2290 ) BOOST_CHECK( swan().dynamic_data(db).current_supply == 1400 ); BOOST_CHECK( swan().bitasset_data(db).settlement_fund == 2800 ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); BOOST_CHECK( swan().bitasset_data(db).current_feed.settlement_price.is_null() ); set_feed(1, 2, 1750, 1800); // MCR = 1750, ICR = 1800 @@ -688,20 +688,20 @@ BOOST_AUTO_TEST_CASE( recollateralize_by_icr_after_hf_core_2290 ) bid_collateral( borrower(), back().amount(1051), swan().amount(700) ); bid_collateral( borrower2(), back().amount(2100), swan().amount(1399) ); wait_for_maintenance(); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); set_feed(1, 2, 1750, 1800); // MCR = 1750, ICR = 1800 // doesn't happen if some bids have a bad swan price bid_collateral( borrower(), back().amount(1120), swan().amount(700) ); bid_collateral( borrower2(), back().amount(1122), swan().amount(700) ); wait_for_maintenance(); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); set_feed(1, 2, 1750, 1800); // MCR = 1750, ICR = 1800 // works bid_collateral( borrower(), back().amount(1121), swan().amount(700) ); bid_collateral( borrower2(), back().amount(1122), swan().amount(700) ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); graphene::app::database_api db_api( db, &( app.get_options() )); auto swan_symbol = _swan(db).symbol; @@ -710,7 +710,7 @@ BOOST_AUTO_TEST_CASE( recollateralize_by_icr_after_hf_core_2290 ) // revive wait_for_maintenance(); - BOOST_CHECK( !swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( !swan().bitasset_data(db).is_globally_settled() ); bids = db_api.get_collateral_bids(swan_symbol, 100, 0); BOOST_CHECK( bids.empty() ); @@ -764,11 +764,11 @@ BOOST_AUTO_TEST_CASE( revive_empty_recovered ) force_settle( borrower2(), swan().amount(1000) ); BOOST_CHECK_EQUAL( 0, swan().dynamic_data(db).current_supply.value ); BOOST_CHECK_EQUAL( 0, swan().bitasset_data(db).settlement_fund.value ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); // revive after price recovers set_feed( 1, 1 ); - BOOST_CHECK( !swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( !swan().bitasset_data(db).is_globally_settled() ); auto& call_idx = db.get_index_type().indices().get(); auto itr = call_idx.find( boost::make_tuple(_feedproducer, _swan) ); @@ -797,11 +797,11 @@ BOOST_AUTO_TEST_CASE( revive_empty ) force_settle( borrower2(), swan().amount(1000) ); BOOST_CHECK_EQUAL( 0, swan().dynamic_data(db).current_supply.value ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); // revive wait_for_maintenance(); - BOOST_CHECK( !swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( !swan().bitasset_data(db).is_globally_settled() ); } catch( const fc::exception& e) { edump((e.to_detail_string())); throw; @@ -829,7 +829,7 @@ BOOST_AUTO_TEST_CASE( revive_empty_with_bid ) set_feed( 1, 2 ); // this sell order is designed to trigger a black swan limit_order_id_type oid = create_sell_order( borrower2(), swan().amount(1), back().amount(3) )->get_id(); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); cancel_limit_order( oid(db) ); force_settle( borrower(), swan().amount(500) ); @@ -841,11 +841,11 @@ BOOST_AUTO_TEST_CASE( revive_empty_with_bid ) bid_collateral( borrower(), back().amount(3000), swan().amount(700) ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); // revive wait_for_maintenance(); - BOOST_CHECK( !swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( !swan().bitasset_data(db).is_globally_settled() ); graphene::app::database_api db_api( db, &( app.get_options() )); auto swan_symbol = _swan(db).symbol; vector bids = db_api.get_collateral_bids(swan_symbol, 100, 0); @@ -985,7 +985,7 @@ BOOST_AUTO_TEST_CASE( overflow ) BOOST_REQUIRE( itr != call_idx.end() ); BOOST_CHECK_EQUAL( 1399, itr->debt.value ); - BOOST_CHECK( !swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( !swan().bitasset_data(db).is_globally_settled() ); } FC_LOG_AND_RETHROW() } /// Tests what kind of assets can have the disable_collateral_bidding flag / issuer permission @@ -1313,7 +1313,7 @@ BOOST_AUTO_TEST_CASE( disable_collateral_bidding_test ) bids = db_api.get_collateral_bids(swan_symbol, 100, 0); BOOST_CHECK_EQUAL( bids.size(), 0u ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); // Unable to bid BOOST_CHECK_THROW( bid_collateral( borrower(), back().amount(3000), swan().amount(700) ), fc::exception ); @@ -1335,7 +1335,7 @@ BOOST_AUTO_TEST_CASE( disable_collateral_bidding_test ) generate_block(); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); } FC_LOG_AND_RETHROW() } @@ -1357,7 +1357,7 @@ BOOST_AUTO_TEST_CASE( disable_collateral_bidding_cross_hardfork_test ) vector bids = db_api.get_collateral_bids(swan_symbol, 100, 0); BOOST_CHECK_EQUAL( bids.size(), 2u ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); // Advance to core-2281 hard fork auto mi = db.get_global_properties().parameters.maintenance_interval; @@ -1371,14 +1371,14 @@ BOOST_AUTO_TEST_CASE( disable_collateral_bidding_cross_hardfork_test ) bids = db_api.get_collateral_bids(swan_symbol, 100, 0); BOOST_CHECK_EQUAL( bids.size(), 0u ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); // Unable to bid BOOST_CHECK_THROW( bid_collateral( borrower(), back().amount(3000), swan().amount(700) ), fc::exception ); generate_block(); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); } FC_LOG_AND_RETHROW() } @@ -1413,18 +1413,18 @@ BOOST_AUTO_TEST_CASE( update_bitasset_after_gs ) set_expiration( db, trx ); BOOST_CHECK( swan().bitasset_data(db).options.feed_lifetime_sec == old_options.feed_lifetime_sec ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); // should succeed PUSH_TX(db, trx, ~0); BOOST_CHECK( swan().bitasset_data(db).options.feed_lifetime_sec == old_options.feed_lifetime_sec + 1 ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); generate_block(); BOOST_CHECK( swan().bitasset_data(db).options.feed_lifetime_sec == old_options.feed_lifetime_sec + 1 ); - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); // unable to update backing asset @@ -1456,7 +1456,7 @@ BOOST_AUTO_TEST_CASE( update_bitasset_after_gs ) const auto& check_result = [&]() { - BOOST_CHECK( swan().bitasset_data(db).has_settlement() ); + BOOST_CHECK( swan().bitasset_data(db).is_globally_settled() ); BOOST_CHECK( swan().bitasset_data(db).options.feed_lifetime_sec == old_options.feed_lifetime_sec + 1 ); From 92041b876bad19db5353da4e0b0ebc2c4d9fdb0a Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 27 May 2023 16:51:34 +0000 Subject: [PATCH 109/127] Refactor code about individual settlement order Store settled debt amounts and collateral amounts in bitasset objects instead of limit orders. --- libraries/chain/db_market.cpp | 118 +++++++++--------- libraries/chain/db_update.cpp | 11 +- .../include/graphene/chain/asset_object.hpp | 20 ++- .../chain/include/graphene/chain/config.hpp | 2 +- .../include/graphene/chain/market_object.hpp | 2 - libraries/chain/market_object.cpp | 2 +- tests/common/database_fixture.cpp | 7 +- tests/tests/bsrm_basic_tests.cpp | 20 ++- tests/tests/bsrm_indvd_settlement_tests.cpp | 84 +++++++------ 9 files changed, 145 insertions(+), 121 deletions(-) diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index 589353c555..4e74b99ed1 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -315,13 +315,10 @@ void database::globally_settle_asset_impl( const asset_object& mia, "Internal error: unable to close margin call ${o}", ("o", order) ); } - // Move the individual settlement order to the GS fund + // Remove the individual settlement order const limit_order_object* limit_ptr = find_settled_debt_order( bitasset.asset_id ); if( limit_ptr ) - { - collateral_gathered.amount += limit_ptr->settled_collateral_amount; remove( *limit_ptr ); - } // Move individual settlement fund to the GS fund collateral_gathered.amount += bitasset.individual_settlement_fund; @@ -355,14 +352,12 @@ void database::individually_settle( const asset_bitasset_data_object& bitasset, auto margin_call_fee = order_collateral - fund_receives; - if( bsrm_type::individual_settlement_to_fund == bsrm ) // settle to fund - { - modify( bitasset, [&order,&fund_receives]( asset_bitasset_data_object& obj ){ - obj.individual_settlement_debt += order.debt; - obj.individual_settlement_fund += fund_receives.amount; - }); - } - else // settle to order + modify( bitasset, [&order,&fund_receives]( asset_bitasset_data_object& obj ){ + obj.individual_settlement_debt += order.debt; + obj.individual_settlement_fund += fund_receives.amount; + }); + + if( bsrm_type::individual_settlement_to_order == bsrm ) // settle to order { const auto& head_time = head_block_time(); bool after_core_hardfork_2591 = HARDFORK_CORE_2591_PASSED( head_time ); // Tighter peg (fill debt order at MCOP) @@ -370,19 +365,18 @@ void database::individually_settle( const asset_bitasset_data_object& bitasset, const limit_order_object* limit_ptr = find_settled_debt_order( bitasset.asset_id ); if( limit_ptr ) { - modify( *limit_ptr, [&order,&fund_receives,after_core_hardfork_2591,&bitasset]( limit_order_object& obj ) { - obj.settled_debt_amount += order.debt; - obj.settled_collateral_amount += fund_receives.amount; + modify( *limit_ptr, [after_core_hardfork_2591,&bitasset]( limit_order_object& obj ) { // TODO fix duplicate code bool sell_all = true; if( after_core_hardfork_2591 ) { obj.sell_price = ~bitasset.get_margin_call_order_price(); - asset settled_debt( obj.settled_debt_amount, obj.receive_asset_id() ); + asset settled_debt( bitasset.individual_settlement_debt, obj.receive_asset_id() ); try { obj.for_sale = settled_debt.multiply_and_round_up( obj.sell_price ).amount; // may overflow - if( obj.for_sale <= obj.settled_collateral_amount ) // "=" for consistency of order matching logic + // Note: the "=" below is for the consistency of order matching logic + if( obj.for_sale <= bitasset.individual_settlement_fund ) sell_all = false; } catch( fc::exception& e ) // catch the overflow @@ -393,9 +387,8 @@ void database::individually_settle( const asset_bitasset_data_object& bitasset, } if( sell_all ) { - obj.for_sale = obj.settled_collateral_amount; - obj.sell_price.base.amount = obj.settled_collateral_amount; - obj.sell_price.quote.amount = obj.settled_debt_amount; + obj.for_sale = bitasset.individual_settlement_fund; + obj.sell_price = ~bitasset.get_individual_settlement_price(); } } ); } @@ -407,8 +400,6 @@ void database::individually_settle( const asset_bitasset_data_object& bitasset, obj.for_sale = fund_receives.amount; obj.sell_price = fund_receives / order_debt; obj.is_settled_debt = true; - obj.settled_debt_amount = order_debt.amount; - obj.settled_collateral_amount = fund_receives.amount; } ); } // Note: CORE asset in settled debt is not counted in account_stats.total_core_in_orders @@ -1115,14 +1106,17 @@ database::match_result_type database::match_limit_settled_debt( const limit_orde bool cull_taker = false; bool maker_filled = false; + const auto& mia = maker.receive_asset_id()(*this); + const auto& bitasset = mia.bitasset_data(*this); + auto usd_for_sale = taker.amount_for_sale(); - auto usd_to_buy = asset( maker.settled_debt_amount, maker.receive_asset_id() ); + auto usd_to_buy = asset( bitasset.individual_settlement_debt, maker.receive_asset_id() ); asset call_receives; asset order_receives; if( usd_to_buy > usd_for_sale ) { // fill taker limit order - order_receives = usd_for_sale * match_price; // round down here, in favor of call order + order_receives = usd_for_sale * match_price; // round down here, in favor of "call order" // Be here, it's possible that taker is paying something for nothing due to partially filled in last loop. // In this case, we see it as filled and cancel it later @@ -1151,13 +1145,9 @@ database::match_result_type database::match_limit_settled_debt( const limit_orde asset call_pays = order_receives; if( maker_filled ) // Regardless of hf core-2591 - call_pays.amount = maker.settled_collateral_amount; - else if( maker.for_sale != maker.settled_collateral_amount ) // implies hf core-2591 - { - price settle_price = asset( maker.settled_collateral_amount, maker.sell_asset_id() ) - / asset( maker.settled_debt_amount, maker.receive_asset_id() ); - call_pays = call_receives * settle_price; // round down here, in favor of call order - } + call_pays.amount = bitasset.individual_settlement_fund; + else if( maker.for_sale != bitasset.individual_settlement_fund ) // implies hf core-2591 + call_pays = call_receives * bitasset.get_individual_settlement_price(); // round down, in favor of "call order" if( call_pays < order_receives ) // be defensive, maybe unnecessary { wlog( "Unexpected scene: call_pays < order_receives" ); @@ -1166,7 +1156,7 @@ database::match_result_type database::match_limit_settled_debt( const limit_orde asset collateral_fee = call_pays - order_receives; // Reduce current supply, and accumulate collateral fees - const asset_dynamic_data_object& mia_ddo = call_receives.asset_id(*this).dynamic_asset_data_id(*this); + const asset_dynamic_data_object& mia_ddo = mia.dynamic_asset_data_id(*this); modify( mia_ddo, [&call_receives,&collateral_fee]( asset_dynamic_data_object& ao ){ ao.current_supply -= call_receives.amount; ao.accumulated_collateral_fees += collateral_fee.amount; @@ -1177,33 +1167,35 @@ database::match_result_type database::match_limit_settled_debt( const limit_orde push_applied_operation( fill_order_operation( maker.id, maker.seller, call_pays, call_receives, collateral_fee, match_price, true ) ); + // Update bitasset data + modify( bitasset, [&call_receives,&call_pays]( asset_bitasset_data_object& obj ){ + obj.individual_settlement_debt -= call_receives.amount; + obj.individual_settlement_fund -= call_pays.amount; + }); + // Update the maker order // Note: CORE asset in settled debt is not counted in account_stats.total_core_in_orders if( maker_filled ) remove( maker ); else { - modify( maker, [after_core_hardfork_2591,&call_pays,&call_receives]( limit_order_object& obj ) { - obj.settled_debt_amount -= call_receives.amount; - obj.settled_collateral_amount -= call_pays.amount; + modify( maker, [after_core_hardfork_2591,&bitasset]( limit_order_object& obj ) { if( after_core_hardfork_2591 ) { // Note: for simplicity, only update price when necessary - asset settled_debt( obj.settled_debt_amount, obj.receive_asset_id() ); + asset settled_debt( bitasset.individual_settlement_debt, obj.receive_asset_id() ); obj.for_sale = settled_debt.multiply_and_round_up( obj.sell_price ).amount; - if( obj.for_sale > obj.settled_collateral_amount ) // be defensive, maybe unnecessary + if( obj.for_sale > bitasset.individual_settlement_fund ) // be defensive, maybe unnecessary { - wlog( "Unexpected scene: obj.for_sale > obj.settled_collateral_amount" ); - obj.for_sale = obj.settled_collateral_amount; - obj.sell_price.base.amount = obj.settled_collateral_amount; - obj.sell_price.quote.amount = obj.settled_debt_amount; + wlog( "Unexpected scene: obj.for_sale > bitasset.individual_settlement_fund" ); + obj.for_sale = bitasset.individual_settlement_fund; + obj.sell_price = ~bitasset.get_individual_settlement_price(); } } else { - obj.for_sale = obj.settled_collateral_amount; - obj.sell_price.base.amount = obj.settled_collateral_amount; - obj.sell_price.quote.amount = obj.settled_debt_amount; + obj.for_sale = bitasset.individual_settlement_fund; + obj.sell_price = ~bitasset.get_individual_settlement_price(); } }); // Note: @@ -1225,8 +1217,11 @@ database::match_result_type database::match_settled_debt_limit( const limit_orde bool taker_filled = false; + const auto& mia = taker.receive_asset_id()(*this); + const auto& bitasset = mia.bitasset_data(*this); + auto usd_for_sale = maker.amount_for_sale(); - auto usd_to_buy = asset( taker.settled_debt_amount, taker.receive_asset_id() ); + auto usd_to_buy = asset( bitasset.individual_settlement_debt, taker.receive_asset_id() ); asset call_receives; asset order_receives; @@ -1248,13 +1243,9 @@ database::match_result_type database::match_settled_debt_limit( const limit_orde asset call_pays = order_receives; if( taker_filled ) - call_pays.amount = taker.settled_collateral_amount; - else if( taker.for_sale != taker.settled_collateral_amount ) - { - price settle_price = asset( taker.settled_collateral_amount, taker.sell_asset_id() ) - / asset( taker.settled_debt_amount, taker.receive_asset_id() ); - call_pays = call_receives * settle_price; // round down here, in favor of call order - } + call_pays.amount = bitasset.individual_settlement_fund; + else if( taker.for_sale != bitasset.individual_settlement_fund ) + call_pays = call_receives * bitasset.get_individual_settlement_price(); // round down, in favor of "call order" if( call_pays < order_receives ) // be defensive, maybe unnecessary { wlog( "Unexpected scene: call_pays < order_receives" ); @@ -1263,7 +1254,7 @@ database::match_result_type database::match_settled_debt_limit( const limit_orde asset collateral_fee = call_pays - order_receives; // Reduce current supply, and accumulate collateral fees - const asset_dynamic_data_object& mia_ddo = call_receives.asset_id(*this).dynamic_asset_data_id(*this); + const asset_dynamic_data_object& mia_ddo = mia.dynamic_asset_data_id(*this); modify( mia_ddo, [&call_receives,&collateral_fee]( asset_dynamic_data_object& ao ){ ao.current_supply -= call_receives.amount; ao.accumulated_collateral_fees += collateral_fee.amount; @@ -1274,24 +1265,27 @@ database::match_result_type database::match_settled_debt_limit( const limit_orde push_applied_operation( fill_order_operation( taker.id, taker.seller, call_pays, call_receives, collateral_fee, match_price, false ) ); + // Update bitasset data + modify( bitasset, [&call_receives,&call_pays]( asset_bitasset_data_object& obj ){ + obj.individual_settlement_debt -= call_receives.amount; + obj.individual_settlement_fund -= call_pays.amount; + }); + // Update the taker order // Note: CORE asset in settled debt is not counted in account_stats.total_core_in_orders if( taker_filled ) remove( taker ); else { - modify( taker, [&call_pays,&call_receives]( limit_order_object& obj ) { - obj.settled_debt_amount -= call_receives.amount; - obj.settled_collateral_amount -= call_pays.amount; + modify( taker, [&bitasset]( limit_order_object& obj ) { // Note: for simplicity, only update price when necessary - asset settled_debt( obj.settled_debt_amount, obj.receive_asset_id() ); + asset settled_debt( bitasset.individual_settlement_debt, obj.receive_asset_id() ); obj.for_sale = settled_debt.multiply_and_round_up( obj.sell_price ).amount; - if( obj.for_sale > obj.settled_collateral_amount ) // be defensive, maybe unnecessary + if( obj.for_sale > bitasset.individual_settlement_fund ) // be defensive, maybe unnecessary { - wlog( "Unexpected scene: obj.for_sale > obj.settled_collateral_amount" ); - obj.for_sale = obj.settled_collateral_amount; - obj.sell_price.base.amount = obj.settled_collateral_amount; - obj.sell_price.quote.amount = obj.settled_debt_amount; + wlog( "Unexpected scene: obj.for_sale > bitasset.individual_settlement_fund" ); + obj.for_sale = bitasset.individual_settlement_fund; + obj.sell_price = ~bitasset.get_individual_settlement_price(); } }); } diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index 453b43249e..9e52b933ed 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -238,11 +238,11 @@ static void update_settled_debt_order( database& db, const asset_bitasset_data_o // Note: bitasset.get_margin_call_order_price() is in debt/collateral price sell_price = ~bitasset.get_margin_call_order_price(); - asset settled_debt( limit_ptr->settled_debt_amount, limit_ptr->receive_asset_id() ); + asset settled_debt( bitasset.individual_settlement_debt, limit_ptr->receive_asset_id() ); try { for_sale = settled_debt.multiply_and_round_up( sell_price ).amount; // may overflow - if( for_sale <= limit_ptr->settled_collateral_amount ) // "=" is for the consistency of order matching logic + if( for_sale <= bitasset.individual_settlement_fund ) // "=" is for the consistency of order matching logic sell_all = false; } catch( const fc::exception& e ) // catch the overflow @@ -252,13 +252,12 @@ static void update_settled_debt_order( database& db, const asset_bitasset_data_o } // TODO Potential optimization: to avoid unnecessary database update, check before update - db.modify( *limit_ptr, [sell_all, &sell_price, &for_sale]( limit_order_object& obj ) + db.modify( *limit_ptr, [sell_all, &sell_price, &for_sale, &bitasset]( limit_order_object& obj ) { if( sell_all ) { - obj.for_sale = obj.settled_collateral_amount; - obj.sell_price.base.amount = obj.settled_collateral_amount; - obj.sell_price.quote.amount = obj.settled_debt_amount; + obj.for_sale = bitasset.individual_settlement_fund; + obj.sell_price = ~bitasset.get_individual_settlement_price(); } else { diff --git a/libraries/chain/include/graphene/chain/asset_object.hpp b/libraries/chain/include/graphene/chain/asset_object.hpp index b951538df1..c98ca5cfcd 100644 --- a/libraries/chain/include/graphene/chain/asset_object.hpp +++ b/libraries/chain/include/graphene/chain/asset_object.hpp @@ -302,6 +302,9 @@ namespace graphene { namespace chain { * In the event of global settlement, all margin positions * are settled with the siezed collateral being moved into the settlement fund. From this * point on forced settlement occurs immediately when requested, using the settlement price and fund. + * + * @note After the core-2591 hardfork, forced settlements may be paid at the margin call order price (MCOP) + * when applicable, but are not limited to the settlement price stated here. */ ///@{ /// Price at which force settlements of a globally settled asset will occur @@ -311,8 +314,10 @@ namespace graphene { namespace chain { ///@} /// The individual settlement pool. - /// In the event of individual settlements to fund, debt and collateral of the margin positions which got - /// settled are moved here. + /// In the event of individual settlements (to fund or to order), debt and collateral of the margin positions + /// which got settled are moved here. + /// * For individual settlement to fund, assets in the pool can only be retrieved through forced settlements. + /// * For individual settlement to order, assets in the pool can only be retrieved through limit orders. ///@{ /// Amount of debt due to individual settlements share_type individual_settlement_debt; @@ -320,8 +325,15 @@ namespace graphene { namespace chain { share_type individual_settlement_fund; ///@} - /// @return true if the individual settlement pool is not empty, false otherwise - bool is_individually_settled_to_fund()const { return ( individual_settlement_debt != 0 ); } + /// @return true if the individual settlement pool is not empty and the bitasset's black swan response method + /// (BSRM) is @ref bitasset_options::black_swan_response_type::individual_settlement_to_fund, + /// false otherwise + bool is_individually_settled_to_fund()const + { + using bsrm_type = bitasset_options::black_swan_response_type; + return ( ( individual_settlement_debt != 0 ) && + ( bsrm_type::individual_settlement_to_fund == get_black_swan_response_method() ) ); + } /// Get the price of the individual settlement pool price get_individual_settlement_price() const diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 5d96e58654..d9705e76df 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -32,7 +32,7 @@ #define GRAPHENE_MAX_NESTED_OBJECTS (200) -const std::string GRAPHENE_CURRENT_DB_VERSION = "20230322"; +const std::string GRAPHENE_CURRENT_DB_VERSION = "20230527"; #define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4 #define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3 diff --git a/libraries/chain/include/graphene/chain/market_object.hpp b/libraries/chain/include/graphene/chain/market_object.hpp index 81366299b8..724be9c25b 100644 --- a/libraries/chain/include/graphene/chain/market_object.hpp +++ b/libraries/chain/include/graphene/chain/market_object.hpp @@ -51,8 +51,6 @@ class limit_order_object : public abstract_object get_market()const { diff --git a/libraries/chain/market_object.cpp b/libraries/chain/market_object.cpp index 39db71cb3c..42ec31d5d0 100644 --- a/libraries/chain/market_object.cpp +++ b/libraries/chain/market_object.cpp @@ -309,7 +309,7 @@ share_type call_order_object::get_max_debt_to_cover( price match_price, FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::limit_order_object, (graphene::db::object), (expiration)(seller)(for_sale)(sell_price)(deferred_fee)(deferred_paid_fee) - (is_settled_debt)(settled_debt_amount)(settled_collateral_amount) + (is_settled_debt) ) FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::call_order_object, (graphene::db::object), diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 525d3da920..c2462ef32c 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -579,10 +579,9 @@ void database_fixture_base::verify_asset_supplies( const database& db ) total_balances[o.deferred_paid_fee.asset_id] += o.deferred_paid_fee.amount; if( o.is_settled_debt ) { - total_balances[for_sale.asset_id] += o.settled_collateral_amount; - total_debts[o.receive_asset_id()] += o.settled_debt_amount; - BOOST_CHECK_LE( o.for_sale.value, o.settled_collateral_amount.value ); - auto settled_debt = asset( o.settled_debt_amount.value, o.receive_asset_id() ); + const auto& bitasset = o.receive_asset_id()(db).bitasset_data(db); + BOOST_CHECK_LE( o.for_sale.value, bitasset.individual_settlement_fund.value ); + auto settled_debt = asset( bitasset.individual_settlement_debt, o.receive_asset_id() ); BOOST_CHECK_EQUAL( settled_debt.multiply_and_round_up( o.sell_price ).amount.value, o.for_sale.value ); } else diff --git a/tests/tests/bsrm_basic_tests.cpp b/tests/tests/bsrm_basic_tests.cpp index b49d71dc3d..c2b3781c99 100644 --- a/tests/tests/bsrm_basic_tests.cpp +++ b/tests/tests/bsrm_basic_tests.cpp @@ -883,7 +883,8 @@ BOOST_AUTO_TEST_CASE( update_bsrm_after_gs ) trx.operations.clear(); trx.operations.push_back( aubop ); PUSH_TX(db, trx, ~0); - BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() == bsrm_type::global_settlement ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).get_black_swan_response_method() + == bsrm_type::global_settlement ); } } @@ -1451,6 +1452,10 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( !db.find( call2_id ) ); + + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); // can not globally settle again @@ -1464,6 +1469,10 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) BOOST_CHECK( !db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( db.find( call_id ) ); BOOST_CHECK( db.find( call2_id ) ); + + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); + BOOST_CHECK( mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == price( asset(1250,mpa_id), asset(20) ) ); @@ -1496,6 +1505,11 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) BOOST_CHECK( db.find_settled_debt_order(mpa_id) ); BOOST_CHECK( !db.find( call_id ) ); BOOST_CHECK( db.find( call2_id ) ); + + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 100000 ); + // MSSR = 1250, MCFR = 11, fee = round_down(2000 * 11 / 1250) = 17, fund = 2000 - 17 = 1983 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1983 ); + BOOST_CHECK( !mpa_id(db).bitasset_data(db).is_current_feed_price_capped() ); BOOST_CHECK( mpa_id(db).bitasset_data(db).current_feed.settlement_price == f.settlement_price ); @@ -1546,6 +1560,8 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) break; case bsrm_type::no_settlement: BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).settlement_fund.value, 3600 ); // 1800 * 2 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); break; case bsrm_type::individual_settlement_to_fund: BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).settlement_fund.value, 4183 ); // 1983 + 2200 @@ -1554,6 +1570,8 @@ BOOST_AUTO_TEST_CASE( manual_gs_test ) break; case bsrm_type::individual_settlement_to_order: BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).settlement_fund.value, 4183 ); // 1983 + 2200 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 0 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 0 ); break; default: BOOST_FAIL( "This should not happen" ); diff --git a/tests/tests/bsrm_indvd_settlement_tests.cpp b/tests/tests/bsrm_indvd_settlement_tests.cpp index 6280b38ce4..ca005acca9 100644 --- a/tests/tests/bsrm_indvd_settlement_tests.cpp +++ b/tests/tests/bsrm_indvd_settlement_tests.cpp @@ -1997,8 +1997,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1983 ); BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 100000 ); - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 100000 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1983 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 100000 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1983 ); BOOST_CHECK( settled_debt->sell_price == asset(1983)/asset(100000,mpa_id) ); // order match price = 100000 / 1983 = 50.428643469 @@ -2036,8 +2036,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1983 ); BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 100000 ); - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 100000 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1983 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 100000 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1983 ); BOOST_CHECK( settled_debt->sell_price == asset(1983)/asset(100000,mpa_id) ); BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 390021 ); // 400000 - 9979 @@ -2071,8 +2071,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 6043 ); // 1983 + 1879 + 2181 BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290021 ); // 100000 + 90021 + 100000 - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 290021 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 6043 ); BOOST_CHECK( settled_debt->sell_price == asset(6043)/asset(290021,mpa_id) ); // order match price = 290021 / 6043 = 47.992884329 @@ -2100,8 +2100,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 6043 ); BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290021 ); - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 290021 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 6043 ); BOOST_CHECK( settled_debt->sell_price == asset(6043)/asset(290021,mpa_id) ); BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 389921 ); // 400000 - 9979 - 100 @@ -2123,8 +2123,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 6043 ); BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290021 ); - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 290021 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 6043 ); BOOST_CHECK( settled_debt->sell_price == asset(6043)/asset(290021,mpa_id) ); } else if( 1 == i ) @@ -2135,8 +2135,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 5750 ); // round_up(290021 * 19824 / 1000000) BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290052 ); //round_down(5750*1000000/19824) - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 290021 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 6043 ); BOOST_CHECK( settled_debt->sell_price == asset(19824)/asset(1000000,mpa_id) ); } @@ -2162,8 +2162,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 6043 ); BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290021 ); - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 290021 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 6043 ); BOOST_CHECK( settled_debt->sell_price == asset(6043)/asset(290021,mpa_id) ); } else if( 1 == i ) @@ -2174,8 +2174,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 5750 ); BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290052 ); - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 290021 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 6043 ); BOOST_CHECK( settled_debt->sell_price == asset(19824)/asset(1000000,mpa_id) ); } @@ -2206,8 +2206,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 5835 ); // 6043 - 208 BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 280038 ); // 290021 - 9983 - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 280038 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 5835 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 280038 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 5835 ); BOOST_CHECK( settled_debt->sell_price == asset(5835)/asset(280038,mpa_id) ); BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 379838 ); // 400000 - 9979 - 100 - 100 - 9983 @@ -2235,8 +2235,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 5750 ); BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 290052 ); - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 290021 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 6043 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 290021 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 6043 ); BOOST_CHECK( settled_debt->sell_price == asset(19824)/asset(1000000,mpa_id) ); BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 379833 ); // 400000 - 9979 - 100 - 100 - 9988 @@ -2302,8 +2302,9 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_maker_test BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1588 ); // round_up( 80073 * 19824 / 1000000 ) BOOST_CHECK_EQUAL( settled_debt->amount_to_receive().amount.value, 80104 ); //rnd_down(1588*1000000/19824) - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 80073 ); // 290021 - 209948 - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1669 ); // 6043 - 4374 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 80073 ); // 290021 + // - 209948 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1669 ); // 6043 - 4374 BOOST_CHECK( settled_debt->sell_price == asset(19824)/asset(1000000,mpa_id) ); BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 79873 ); // 400000 - 9979 - 100 - 100 - 9988 @@ -2493,8 +2494,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_taker_test // fund receives 2000 - 17 = 1983 BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1983 ); - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 100000 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1983 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 100000 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1983 ); BOOST_CHECK( settled_debt->sell_price == asset(1983)/asset(100000,mpa_id) ); // order match price = 100000 / 1983 = 50.428643469 @@ -2516,8 +2517,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_taker_test BOOST_REQUIRE( settled_debt ); BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1785 ); // 1983 - 198 - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 90015 ); // 100000 - 9985 - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1785 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 90015 ); // 100000 - 9985 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1785 ); if( 0 == i ) BOOST_CHECK( settled_debt->sell_price == asset(1785)/asset(90015,mpa_id) ); else @@ -2541,8 +2542,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_taker_test BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1785 ); else BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 558 ); // round_up( 90015 * 1239 / 200000 ) - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 90015 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1785 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 90015 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1785 ); if( 0 == i ) BOOST_CHECK( settled_debt->sell_price == asset(1785)/asset(90015,mpa_id) ); else @@ -2563,8 +2564,9 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_taker_test BOOST_REQUIRE( settled_debt ); BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1587 ); // 1983 - 198 - 198 - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 80030 ); // 100000 - 9985 - 9985 - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1587 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 80030 ); // 100000 - 9985 + // - 9985 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1587 ); BOOST_CHECK( settled_debt->sell_price == asset(1587)/asset(80030,mpa_id) ); BOOST_CHECK_EQUAL( mpa_id(db).dynamic_data(db).accumulated_collateral_fees.value, 17 ); @@ -2589,8 +2591,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_taker_test BOOST_REQUIRE( settled_debt ); BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 558 ); - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 90015 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1785 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 90015 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1785 ); BOOST_CHECK( settled_debt->sell_price == asset(1239)/asset(200000,mpa_id) ); BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 80015 ); // 100000 - 9985 - 10000 @@ -2706,8 +2708,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_taker_test BOOST_REQUIRE( settled_debt ); BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1339 ); // round_up( 80015 * 167265 / 10000000 ) - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 80015 ); // 90015 - 10000 - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1587 ); // 1785 - 198 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 80015 ); //90015 - 10000 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1587 ); // 1785 - 198 BOOST_CHECK( settled_debt->sell_price == asset(167265)/asset(10000000,mpa_id) ); BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 80015 ); // 100000 - 9985 - 10000 @@ -2738,8 +2740,10 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_taker_test BOOST_REQUIRE( settled_debt ); BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1506 ); // round_up( 90015 * 167265 / 10000000 ) - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 90015 ); // 90015 - 10000 + 10000 - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1697 ); // 1785 + 100 - 188 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 90015 ); //90015 - 10000 + // + 10000 + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1697 ); // 1785 + 100 + // - 188 BOOST_CHECK( settled_debt->sell_price == asset(167265)/asset(10000000,mpa_id) ); BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 80015 ); // 100000 - 9985 - 10000 @@ -2766,8 +2770,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_taker_test BOOST_REQUIRE( settled_debt ); BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 11697 ); - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 1090015 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 11697 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 1090015 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 11697 ); BOOST_CHECK( settled_debt->sell_price == asset(11697)/asset(1090015,mpa_id) ); BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 80015 ); // no change @@ -2797,8 +2801,8 @@ BOOST_AUTO_TEST_CASE( individual_settlement_to_order_and_matching_as_taker_test BOOST_REQUIRE( settled_debt ); BOOST_CHECK( settled_debt->is_settled_debt ); BOOST_CHECK_EQUAL( settled_debt->for_sale.value, 1506 ); // round_up( 90015 * 167265 / 10000000 ) - BOOST_CHECK_EQUAL( settled_debt->settled_debt_amount.value, 90015 ); - BOOST_CHECK_EQUAL( settled_debt->settled_collateral_amount.value, 1785 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_debt.value, 90015 ); + BOOST_CHECK_EQUAL( mpa_id(db).bitasset_data(db).individual_settlement_fund.value, 1785 ); BOOST_CHECK( settled_debt->sell_price == asset(167265)/asset(10000000,mpa_id) ); BOOST_CHECK_EQUAL( get_balance( seller_id, mpa_id ), 80015 ); // 100000 - 9985 - 10000 From 37c585335c9f0cf5c9d80bf9db9483ad9c309435 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 27 May 2023 17:04:32 +0000 Subject: [PATCH 110/127] Update some assertion messages --- libraries/chain/asset_evaluator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index 6f8d428ca1..b3ccff00e6 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -791,7 +791,7 @@ void_result asset_update_bitasset_evaluator::do_evaluate(const asset_update_bita using bsrm_type = bitasset_options::black_swan_response_type; if( bsrm_type::individual_settlement_to_fund == old_bsrm ) FC_ASSERT( !current_bitasset_data.is_individually_settled_to_fund(), - "Unable to update BSRM when the individual settlement pool is not empty" ); + "Unable to update BSRM when the individual settlement pool (for force-settlements) is not empty" ); else if( bsrm_type::individual_settlement_to_order == old_bsrm ) FC_ASSERT( !d.find_settled_debt_order( op.asset_to_update ), "Unable to update BSRM when there exists an individual settlement order" ); @@ -1153,7 +1153,7 @@ void_result asset_settle_evaluator::do_evaluate(const asset_settle_evaluator::op FC_ASSERT( asset_to_settle->can_force_settle() || bitasset.is_globally_settled() || bitasset.is_individually_settled_to_fund(), "Either the asset need to have the force_settle flag enabled, or it need to be globally settled, " - "or the individual settlement pool is not empty" ); + "or the individual settlement pool (for force-settlements) is not empty" ); if( bitasset.is_prediction_market ) { @@ -1173,7 +1173,7 @@ void_result asset_settle_evaluator::do_evaluate(const asset_settle_evaluator::op { FC_THROW_EXCEPTION( insufficient_feeds, "Cannot force settle with no price feed if the asset is not globally settled and the " - "individual settlement pool is not empty" ); + "individual settlement pool (for force-settlements) is not empty" ); } } From f8d5e8dbb90b527e4cbfeb9f10751776de9d52c9 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 27 May 2023 21:30:44 +0000 Subject: [PATCH 111/127] Add GCOVR exclusion markers around defensive code --- libraries/chain/db_market.cpp | 43 ++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index 4e74b99ed1..0e63e09f1f 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -246,7 +246,10 @@ void database::globally_settle_asset_impl( const asset_object& mia, bool check_margin_calls ) { try { const asset_bitasset_data_object& bitasset = mia.bitasset_data(*this); + // GCOVR_EXCL_START + // Defensive code, normally it should not fail FC_ASSERT( !bitasset.is_globally_settled(), "black swan already occurred, it should not happen again" ); + // GCOVR_EXCL_STOP asset collateral_gathered( 0, bitasset.options.short_backing_asset ); @@ -418,11 +421,14 @@ void database::individually_settle( const asset_bitasset_data_object& bitasset, void database::revive_bitasset( const asset_object& bitasset, const asset_bitasset_data_object& bad ) { try { + // GCOVR_EXCL_START + // Defensive code, normally none of these should fail FC_ASSERT( bitasset.is_market_issued() ); FC_ASSERT( bitasset.id == bad.asset_id ); FC_ASSERT( bad.is_globally_settled() ); FC_ASSERT( !bad.is_prediction_market ); FC_ASSERT( !bad.current_feed.settlement_price.is_null() ); + // GCOVR_EXCL_STOP const asset_dynamic_data_object& bdd = bitasset.dynamic_asset_data_id(*this); if( bdd.current_supply > 0 ) @@ -443,9 +449,12 @@ void database::revive_bitasset( const asset_object& bitasset, const asset_bitass void database::_cancel_bids_and_revive_mpa( const asset_object& bitasset, const asset_bitasset_data_object& bad ) { try { + // GCOVR_EXCL_START + // Defensive code, normally none of these should fail FC_ASSERT( bitasset.is_market_issued() ); FC_ASSERT( bad.is_globally_settled() ); FC_ASSERT( !bad.is_prediction_market ); + // GCOVR_EXCL_STOP // cancel remaining bids const auto& bid_idx = get_index_type< collateral_bid_index >().indices().get(); @@ -923,11 +932,14 @@ void database::apply_force_settlement( const force_settlement_object& new_settle { // Defensive checks auto maint_time = get_dynamic_global_properties().next_maintenance_time; + // GCOVR_EXCL_START + // Defensive code, normally none of these should fail FC_ASSERT( HARDFORK_CORE_2481_PASSED( maint_time ), "Internal error: hard fork core-2481 not passed" ); FC_ASSERT( new_settlement.balance.asset_id == bitasset.asset_id, "Internal error: asset type mismatch" ); FC_ASSERT( !bitasset.is_prediction_market, "Internal error: asset is a prediction market" ); FC_ASSERT( !bitasset.is_globally_settled(), "Internal error: asset is globally settled already" ); FC_ASSERT( !bitasset.current_feed.settlement_price.is_null(), "Internal error: no sufficient price feeds" ); + // GCOVR_EXCL_STOP auto head_time = head_block_time(); bool after_core_hardfork_2582 = HARDFORK_CORE_2582_PASSED( head_time ); // Price feed issues @@ -1013,9 +1025,12 @@ static database::match_result_type get_match_result( bool taker_filled, bool mak database::match_result_type database::match( const limit_order_object& taker, const limit_order_object& maker, const price& match_price ) { + // GCOVR_EXCL_START + // Defensive code, normally none of these should fail FC_ASSERT( taker.sell_price.quote.asset_id == maker.sell_price.base.asset_id ); FC_ASSERT( taker.sell_price.base.asset_id == maker.sell_price.quote.asset_id ); FC_ASSERT( taker.for_sale > 0 && maker.for_sale > 0 ); + // GCOVR_EXCL_STOP return maker.is_settled_debt ? match_limit_settled_debt( taker, maker, match_price ) : match_limit_normal_limit( taker, maker, match_price ); @@ -1025,8 +1040,11 @@ database::match_result_type database::match( const limit_order_object& taker, co database::match_result_type database::match_limit_normal_limit( const limit_order_object& taker, const limit_order_object& maker, const price& match_price ) { + // GCOVR_EXCL_START + // Defensive code, normally none of these should fail FC_ASSERT( !maker.is_settled_debt, "Internal error: maker is settled debt" ); FC_ASSERT( !taker.is_settled_debt, "Internal error: taker is settled debt" ); + // GCOVR_EXCL_STOP auto taker_for_sale = taker.amount_for_sale(); auto maker_for_sale = maker.amount_for_sale(); @@ -1100,8 +1118,11 @@ database::match_result_type database::match_limit_normal_limit( const limit_orde database::match_result_type database::match_limit_settled_debt( const limit_order_object& taker, const limit_order_object& maker, const price& match_price ) { + // GCOVR_EXCL_START + // Defensive code, normally none of these should fail FC_ASSERT( maker.is_settled_debt, "Internal error: maker is not settled debt" ); FC_ASSERT( !taker.is_settled_debt, "Internal error: taker is settled debt" ); + // GCOVR_EXCL_STOP bool cull_taker = false; bool maker_filled = false; @@ -1149,10 +1170,10 @@ database::match_result_type database::match_limit_settled_debt( const limit_orde else if( maker.for_sale != bitasset.individual_settlement_fund ) // implies hf core-2591 call_pays = call_receives * bitasset.get_individual_settlement_price(); // round down, in favor of "call order" if( call_pays < order_receives ) // be defensive, maybe unnecessary - { + { // GCOVR_EXCL_START wlog( "Unexpected scene: call_pays < order_receives" ); call_pays = order_receives; - } + } // GCOVR_EXCL_STOP asset collateral_fee = call_pays - order_receives; // Reduce current supply, and accumulate collateral fees @@ -1186,11 +1207,11 @@ database::match_result_type database::match_limit_settled_debt( const limit_orde asset settled_debt( bitasset.individual_settlement_debt, obj.receive_asset_id() ); obj.for_sale = settled_debt.multiply_and_round_up( obj.sell_price ).amount; if( obj.for_sale > bitasset.individual_settlement_fund ) // be defensive, maybe unnecessary - { + { // GCOVR_EXCL_START wlog( "Unexpected scene: obj.for_sale > bitasset.individual_settlement_fund" ); obj.for_sale = bitasset.individual_settlement_fund; obj.sell_price = ~bitasset.get_individual_settlement_price(); - } + } // GCOVR_EXEL_STOP } else { @@ -1212,8 +1233,11 @@ database::match_result_type database::match_limit_settled_debt( const limit_orde database::match_result_type database::match_settled_debt_limit( const limit_order_object& taker, const limit_order_object& maker, const price& match_price ) { + // GCOVR_EXCL_START + // Defensive code, normally none of these should fail FC_ASSERT( !maker.is_settled_debt, "Internal error: maker is settled debt" ); FC_ASSERT( taker.is_settled_debt, "Internal error: taker is not settled debt" ); + // GCOVR_EXCL_STOP bool taker_filled = false; @@ -1247,10 +1271,10 @@ database::match_result_type database::match_settled_debt_limit( const limit_orde else if( taker.for_sale != bitasset.individual_settlement_fund ) call_pays = call_receives * bitasset.get_individual_settlement_price(); // round down, in favor of "call order" if( call_pays < order_receives ) // be defensive, maybe unnecessary - { + { // GCOVR_EXCL_START wlog( "Unexpected scene: call_pays < order_receives" ); call_pays = order_receives; - } + } // GCOVR_EXCL_STOP asset collateral_fee = call_pays - order_receives; // Reduce current supply, and accumulate collateral fees @@ -1282,11 +1306,11 @@ database::match_result_type database::match_settled_debt_limit( const limit_orde asset settled_debt( bitasset.individual_settlement_debt, obj.receive_asset_id() ); obj.for_sale = settled_debt.multiply_and_round_up( obj.sell_price ).amount; if( obj.for_sale > bitasset.individual_settlement_fund ) // be defensive, maybe unnecessary - { + { // GCOVR_EXCL_START wlog( "Unexpected scene: obj.for_sale > bitasset.individual_settlement_fund" ); obj.for_sale = bitasset.individual_settlement_fund; obj.sell_price = ~bitasset.get_individual_settlement_price(); - } + } // GCOVR_EXCL_STOP }); } @@ -2255,10 +2279,13 @@ bool database::match_force_settlements( const asset_bitasset_data_object& bitass { // Defensive checks auto maint_time = get_dynamic_global_properties().next_maintenance_time; + // GCOVR_EXCL_START + // Defensive code, normally none of these should fail FC_ASSERT( HARDFORK_CORE_2481_PASSED( maint_time ), "Internal error: hard fork core-2481 not passed" ); FC_ASSERT( !bitasset.is_prediction_market, "Internal error: asset is a prediction market" ); FC_ASSERT( !bitasset.is_globally_settled(), "Internal error: asset is globally settled already" ); FC_ASSERT( !bitasset.current_feed.settlement_price.is_null(), "Internal error: no sufficient price feeds" ); + // GCOVR_EXCL_STOP auto head_time = head_block_time(); bool after_core_hardfork_2582 = HARDFORK_CORE_2582_PASSED( head_time ); // Price feed issues From 061594f45a45a571dcce7f7b5429458f67e43bc5 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 28 May 2023 09:49:12 +0000 Subject: [PATCH 112/127] Update comments --- libraries/chain/include/graphene/chain/asset_object.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/chain/include/graphene/chain/asset_object.hpp b/libraries/chain/include/graphene/chain/asset_object.hpp index c98ca5cfcd..60b5a0fd39 100644 --- a/libraries/chain/include/graphene/chain/asset_object.hpp +++ b/libraries/chain/include/graphene/chain/asset_object.hpp @@ -316,12 +316,14 @@ namespace graphene { namespace chain { /// The individual settlement pool. /// In the event of individual settlements (to fund or to order), debt and collateral of the margin positions /// which got settled are moved here. - /// * For individual settlement to fund, assets in the pool can only be retrieved through forced settlements. - /// * For individual settlement to order, assets in the pool can only be retrieved through limit orders. + /// * For individual settlement to fund, collateral assets in the pool can only be retrieved through + /// forced settlements. + /// * For individual settlement to order, collateral assets in the pool can only be retrieved through + /// limit orders. ///@{ /// Amount of debt due to individual settlements share_type individual_settlement_debt; - /// Amount of collateral which is available for force settlement due to individual settlements + /// Amount of collateral due to individual settlements share_type individual_settlement_fund; ///@} From 240a84aae36ad3881951997a1ce613f988b6b01e Mon Sep 17 00:00:00 2001 From: abitmore Date: Mon, 29 May 2023 14:13:03 +0000 Subject: [PATCH 113/127] Implement Order-Sends-Take-Profit-Order feature --- libraries/chain/db_block.cpp | 25 ++- libraries/chain/db_market.cpp | 174 ++++++++++++++++-- libraries/chain/hardfork.d/CORE_2535.hf | 6 + .../chain/include/graphene/chain/config.hpp | 2 +- .../chain/include/graphene/chain/database.hpp | 10 +- .../graphene/chain/market_evaluator.hpp | 2 + .../include/graphene/chain/market_object.hpp | 14 ++ .../chain/transaction_evaluation_state.hpp | 3 +- libraries/chain/market_evaluator.cpp | 100 +++++++++- libraries/chain/market_object.cpp | 2 +- libraries/chain/proposal_evaluator.cpp | 8 + .../include/graphene/protocol/market.hpp | 50 ++++- libraries/protocol/market.cpp | 42 ++++- 13 files changed, 409 insertions(+), 29 deletions(-) create mode 100644 libraries/chain/hardfork.d/CORE_2535.hf diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index 558005c1de..e5da510301 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -310,19 +310,23 @@ processed_transaction database::validate_transaction( const signed_transaction& return _apply_transaction( trx ); } -class push_proposal_nesting_guard { +class undo_session_nesting_guard { public: - push_proposal_nesting_guard( uint32_t& nesting_counter, const database& db ) + undo_session_nesting_guard( uint32_t& nesting_counter, const database& db ) : orig_value(nesting_counter), counter(nesting_counter) { FC_ASSERT( counter < db.get_global_properties().active_witnesses.size() * 2, - "Max proposal nesting depth exceeded!" ); - counter++; + "Max undo session nesting depth exceeded!" ); + ++counter; } - ~push_proposal_nesting_guard() + ~undo_session_nesting_guard() { - if( --counter != orig_value ) - elog( "Unexpected proposal nesting count value: ${n} != ${o}", ("n",counter)("o",orig_value) ); + --counter; + // GCOVR_EXCL_START + // Defensive code, should not happen + if( counter != orig_value ) + elog( "Unexpected undo session nesting count value: ${n} != ${o}", ("n",counter)("o",orig_value) ); + // GCOVR_EXCL_STOP } private: const uint32_t orig_value; @@ -341,7 +345,7 @@ processed_transaction database::push_proposal(const proposal_object& proposal) auto old_vop = _current_virtual_op; try { - push_proposal_nesting_guard guard( _push_proposal_nesting_depth, *this ); + undo_session_nesting_guard guard( _undo_session_nesting_depth, *this ); if( _undo_db.size() >= _undo_db.max_size() ) _undo_db.set_max_size( _undo_db.size() + 1 ); auto session = _undo_db.start_undo_session(true); @@ -802,7 +806,10 @@ operation_result database::try_push_virtual_operation( transaction_evaluation_st try { - auto temp_session = _undo_db.start_undo_session(); + undo_session_nesting_guard guard( _undo_session_nesting_depth, *this ); + if( _undo_db.size() >= _undo_db.max_size() ) + _undo_db.set_max_size( _undo_db.size() + 1 ); + auto temp_session = _undo_db.start_undo_session(true); auto result = apply_operation( eval_state, op ); // This is a virtual operation temp_session.merge(); return result; diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index 0e63e09f1f..1306a67c57 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -626,6 +626,20 @@ void database::cancel_limit_order( const limit_order_object& order, bool create_ set_applied_operation_result( op_id, refunded ); } + cleanup_and_remove_limit_order( order ); +} + +void database::cleanup_and_remove_limit_order( const limit_order_object& order ) +{ + // Unlink the linked take profit order if it exists + if( order.take_profit_order_id.valid() ) + { + const auto& take_profit_order = (*order.take_profit_order_id)(*this); + modify( take_profit_order, []( limit_order_object& loo ) { + loo.take_profit_order_id.reset(); + }); + } + remove(order); } @@ -1640,22 +1654,147 @@ asset database::match_impl( const force_settlement_object& settle, } FC_CAPTURE_AND_RETHROW( (p_match_price)(max_settlement)(p_fill_price) // GCOVR_EXCL_LINE (is_margin_call)(settle_is_taker) ) } // GCOVR_EXCL_LINE +optional database::process_limit_order_on_fill( const limit_order_object& order, + const asset& order_receives ) +{ + optional result; + if( order.on_fill.empty() ) + return result; + + const auto& take_profit_action = order.get_take_profit_action(); + + fc::uint128_t amount128( order_receives.amount.value ); + amount128 *= take_profit_action.size_percent; + amount128 += (GRAPHENE_100_PERCENT - 1); // Round up + amount128 /= GRAPHENE_100_PERCENT; + // GCOVR_EXCL_START + // Defensive code, should not happen + if( amount128 <= 0 ) + return result; + // GCOVR_EXCL_STOP + + asset for_sale( static_cast( amount128 ), order_receives.asset_id ); + + if( order.take_profit_order_id.valid() ) // Update existing take profit order + { + limit_order_update_operation op; + if( take_profit_action.fee_asset_id == asset_id_type() ) + op.fee = current_fee_schedule().calculate_fee( op ); + else + op.fee = current_fee_schedule().calculate_fee( op, + take_profit_action.fee_asset_id(*this).options.core_exchange_rate ); + op.seller = order.seller; + op.order = *order.take_profit_order_id; + op.delta_amount_to_sell = for_sale; + + if( *order.take_profit_order_id > order.get_id() ) // The linked take profit order was generated by this order + { + // Update order price + const auto& take_profit_order = (*order.take_profit_order_id)(*this); + for_sale.amount += take_profit_order.for_sale; + auto sell_price = (~order.sell_price) * ratio_type( GRAPHENE_100_PERCENT, + int32_t(GRAPHENE_100_PERCENT) + take_profit_action.spread_percent ); + auto new_min_to_receive = for_sale.multiply_and_round_up( sell_price ); + op.new_price = for_sale / new_min_to_receive; + } + // else do not update order price + + if( ( time_point_sec::maximum() - take_profit_action.expiration_seconds ) > head_block_time() ) + op.new_expiration = head_block_time() + take_profit_action.expiration_seconds; + else + op.new_expiration = time_point_sec::maximum(); + + transaction_evaluation_state eval_state(this); + eval_state.skip_limit_order_price_check = true; + + try + { + // GCOVR_EXCL_START + // Defensive code, should not fail + FC_ASSERT( !op.new_price || ( ~(*op.new_price) > order.sell_price ), + "Internal error: the take profit order should not match the current order" ); + // GCOVR_EXCL_STOP + + try_push_virtual_operation( eval_state, op ); + } + catch( const fc::exception& e ) + { + // We can in fact get here + // e.g. if the selling or receiving asset issuer blacklisted the account, + // or no sufficient balance to pay fees, or undo sessions nested too deeply + wlog( "Automatic action ${op} for filling limit order ${order} failed at block ${n}; " + "exception was ${e}", + ("op", operation(op))("order", order) + ("n", head_block_num())("e", e.to_detail_string()) ); + } + } + else // Create a new take profit order + { + limit_order_create_operation op; + if( take_profit_action.fee_asset_id == asset_id_type() ) + op.fee = current_fee_schedule().calculate_fee( op ); + else + op.fee = current_fee_schedule().calculate_fee( op, + take_profit_action.fee_asset_id(*this).options.core_exchange_rate ); + op.seller = order.seller; + op.amount_to_sell = for_sale; + auto sell_price = (~order.sell_price) * ratio_type( GRAPHENE_100_PERCENT, + int32_t(GRAPHENE_100_PERCENT) + take_profit_action.spread_percent ); + op.min_to_receive = for_sale.multiply_and_round_up( sell_price ); + if( ( time_point_sec::maximum() - take_profit_action.expiration_seconds ) > head_block_time() ) + op.expiration = head_block_time() + take_profit_action.expiration_seconds; + else + op.expiration = time_point_sec::maximum(); + if( take_profit_action.repeat ) + op.extensions.value.on_fill = order.on_fill; + + transaction_evaluation_state eval_state(this); + + try + { + // GCOVR_EXCL_START + // Defensive code, should not fail + FC_ASSERT( ~op.get_price() > order.sell_price, + "Internal error: the take profit order should not match the current order" ); + // GCOVR_EXCL_STOP + + auto op_result = try_push_virtual_operation( eval_state, op ); + result = limit_order_id_type( op_result.get() ); + } + catch( const fc::exception& e ) + { + // We can in fact get here + // e.g. if the selling or receiving asset issuer blacklisted the account, + // or no sufficient balance to pay fees, or undo sessions nested too deeply + wlog( "Automatic action ${op} for filling limit order ${order} failed at block ${n}; " + "exception was ${e}", + ("op", operation(op))("order", order) + ("n", head_block_num())("e", e.to_detail_string()) ); + } + } + + return result; +} + bool database::fill_limit_order( const limit_order_object& order, const asset& pays, const asset& receives, bool cull_if_small, const price& fill_price, const bool is_maker) { try { if( head_block_time() < HARDFORK_555_TIME ) cull_if_small = true; + // GCOVR_EXCL_START + // Defensive code, normally none of these should fail FC_ASSERT( order.amount_for_sale().asset_id == pays.asset_id ); FC_ASSERT( pays.asset_id != receives.asset_id ); + // GCOVR_EXCL_STOP const account_object& seller = order.seller(*this); const auto issuer_fees = pay_market_fees(&seller, receives.asset_id(*this), receives, is_maker); - pay_order( seller, receives - issuer_fees, pays ); + auto order_receives = receives - issuer_fees; + pay_order( seller, order_receives, pays ); - assert( pays.asset_id != receives.asset_id ); push_applied_operation( fill_order_operation( order.id, order.seller, pays, receives, issuer_fees, fill_price, is_maker ) ); @@ -1728,22 +1867,33 @@ bool database::fill_limit_order( const limit_order_object& order, const asset& p } } + // Process on_fill for order_receives + optional new_take_profit_order_id = process_limit_order_on_fill( order, order_receives ); + + // If this order is fully filled if( pays == order.amount_for_sale() ) { - remove( order ); + cleanup_and_remove_limit_order( order ); return true; } - else + + // This order is partially filled + if( new_take_profit_order_id.valid() ) // A new take profit order is created, link this order to it { - modify( order, [&pays]( limit_order_object& b ) { - b.for_sale -= pays.amount; - b.deferred_fee = 0; - b.deferred_paid_fee.amount = 0; - }); - if( cull_if_small ) - return maybe_cull_small_order( *this, order ); - return false; + modify( (*new_take_profit_order_id)(*this), [&order]( limit_order_object& loo ) { + loo.take_profit_order_id = order.get_id(); + }); } + modify( order, [&pays,&new_take_profit_order_id]( limit_order_object& b ) { + b.for_sale -= pays.amount; + b.deferred_fee = 0; + b.deferred_paid_fee.amount = 0; + if( new_take_profit_order_id.valid() ) // A new take profit order is created, link it to this order + b.take_profit_order_id = *new_take_profit_order_id; + }); + if( cull_if_small ) + return maybe_cull_small_order( *this, order ); + return false; } FC_CAPTURE_AND_RETHROW( (pays)(receives) ) } // GCOVR_EXCL_LINE /*** diff --git a/libraries/chain/hardfork.d/CORE_2535.hf b/libraries/chain/hardfork.d/CORE_2535.hf new file mode 100644 index 0000000000..1326d21abf --- /dev/null +++ b/libraries/chain/hardfork.d/CORE_2535.hf @@ -0,0 +1,6 @@ +// bitshares-core issue #2535 Simple Order-Sends-Order (OSO) +#ifndef HARDFORK_CORE_2535_TIME +// Jan 1 2030, midnight; this is a dummy date until a hardfork date is scheduled +#define HARDFORK_CORE_2535_TIME (fc::time_point_sec( 1893456000 )) +#define HARDFORK_CORE_2535_PASSED(head_block_time) (head_block_time >= HARDFORK_CORE_2535_TIME) +#endif diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index d9705e76df..9ac7aa7237 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -32,7 +32,7 @@ #define GRAPHENE_MAX_NESTED_OBJECTS (200) -const std::string GRAPHENE_CURRENT_DB_VERSION = "20230527"; +const std::string GRAPHENE_CURRENT_DB_VERSION = "20230529"; #define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4 #define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3 diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index cb5c800385..5a620c310a 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -326,6 +326,12 @@ namespace graphene { namespace chain { share_type collateral_from_fund, const price_feed& current_feed ); private: + /// Clean up for a limit order and then remove it from database + void cleanup_and_remove_limit_order( const limit_order_object& order ); + /// Process on_fill for a limit order + /// @return the ID of the newly created take profit order (in that case), otherwise null + optional process_limit_order_on_fill( const limit_order_object& order, + const asset& order_receives ); void _cancel_bids_and_revive_mpa( const asset_object& bitasset, const asset_bitasset_data_object& bad ); bool check_for_blackswan( const asset_object& mia, bool enable_black_swan = true, const asset_bitasset_data_object* bitasset_ptr = nullptr ); @@ -820,8 +826,8 @@ namespace graphene { namespace chain { */ bool _opened = false; - // Counts nested proposal updates - uint32_t _push_proposal_nesting_depth = 0; + /// Counts nested undo sessions due to (for example) proposal updates or order-sends-order executions + uint32_t _undo_session_nesting_depth = 0; /// Tracks assets affected by bitshares-core issue #453 before hard fork #615 in one block flat_set _issue_453_affected_assets; diff --git a/libraries/chain/include/graphene/chain/market_evaluator.hpp b/libraries/chain/include/graphene/chain/market_evaluator.hpp index 26d90c2298..f17c96d81b 100644 --- a/libraries/chain/include/graphene/chain/market_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/market_evaluator.hpp @@ -78,6 +78,8 @@ namespace graphene { namespace chain { private: void process_deferred_fee(); + /// Check if the linked take profit order is still compatible with the current order after update + bool is_linked_tp_order_compatible( const limit_order_update_operation& o ) const; share_type _deferred_fee; asset _deferred_paid_fee; diff --git a/libraries/chain/include/graphene/chain/market_object.hpp b/libraries/chain/include/graphene/chain/market_object.hpp index 724be9c25b..4faa8e5c26 100644 --- a/libraries/chain/include/graphene/chain/market_object.hpp +++ b/libraries/chain/include/graphene/chain/market_object.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -52,6 +53,19 @@ class limit_order_object : public abstract_object on_fill; + + /// ID of the take profit limit order linked to this limit order + optional take_profit_order_id; + + /// Returns the configured automatic action that will create a take profit order when this limit order is filled + const create_take_profit_order_action& get_take_profit_action() const + { + FC_ASSERT( !on_fill.empty() ); // Normally it should not fail // GCOVR_EXCL_LINE + return on_fill.front().get(); + } + pair get_market()const { auto tmp = std::make_pair( sell_price.base.asset_id, sell_price.quote.asset_id ); diff --git a/libraries/chain/include/graphene/chain/transaction_evaluation_state.hpp b/libraries/chain/include/graphene/chain/transaction_evaluation_state.hpp index 53c6f3eb87..953b05ed69 100644 --- a/libraries/chain/include/graphene/chain/transaction_evaluation_state.hpp +++ b/libraries/chain/include/graphene/chain/transaction_evaluation_state.hpp @@ -47,7 +47,8 @@ namespace chain { const signed_transaction* _trx = nullptr; database* _db = nullptr; bool _is_proposed_trx = false; - bool skip_fee = false; + bool skip_fee = false; // Note: seems unused. TODO recheck & maybe remove bool skip_fee_schedule_check = false; + bool skip_limit_order_price_check = false; // Used in limit_order_update_op }; } } // namespace graphene::chain diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 56d49de366..a09fdaf1e6 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -40,6 +40,16 @@ void_result limit_order_create_evaluator::do_evaluate(const limit_order_create_o { try { const database& d = db(); + if( op.extensions.value.on_fill.valid() ) + { + FC_ASSERT( HARDFORK_CORE_2535_PASSED( d.head_block_time() ) , + "The on_fill extension is not allowed until the core-2535 hardfork"); + FC_ASSERT( 1 == op.extensions.value.on_fill->size(), + "The on_fill action list must contain only one action until expanded in a future hardfork" ); + const auto& take_profit_action = op.extensions.value.on_fill->front().get(); + FC_ASSERT( d.find( take_profit_action.fee_asset_id ), "Fee asset does not exist" ); + } + FC_ASSERT( op.expiration >= d.head_block_time() ); _seller = this->fee_paying_account; @@ -119,6 +129,8 @@ object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_o obj.expiration = op.expiration; obj.deferred_fee = _deferred_fee; obj.deferred_paid_fee = _deferred_paid_fee; + if( op.extensions.value.on_fill.valid() ) + obj.on_fill = *op.extensions.value.on_fill; }); object_id_type order_id = new_order_object.id; // save this because we may remove the object by filling it bool filled; @@ -157,6 +169,19 @@ void_result limit_order_update_evaluator::do_evaluate(const limit_order_update_o const database& d = db(); FC_ASSERT( HARDFORK_CORE_1604_PASSED( d.head_block_time() ) , "Operation has not activated yet"); + if( o.on_fill.valid() ) + { + // Note: Assuming that HF core-1604 and HF core-2535 will take place at the same time, + // no check for HF core-2535 here. + FC_ASSERT( o.on_fill->size() <= 1, + "The on_fill action list must contain zero or one action until expanded in a future hardfork" ); + if( !o.on_fill->empty() ) + { + const auto& take_profit_action = o.on_fill->front().get(); + FC_ASSERT( d.find( take_profit_action.fee_asset_id ), "Fee asset does not exist" ); + } + } + _order = d.find( o.order ); GRAPHENE_ASSERT( _order != nullptr, @@ -327,6 +352,50 @@ void limit_order_update_evaluator::process_deferred_fee() } +bool limit_order_update_evaluator::is_linked_tp_order_compatible(const limit_order_update_operation& o) const +{ + if( !o.on_fill ) // there is no change to on_fill, so do nothing + return true; + bool is_compatible = true; + if( o.on_fill->empty() ) + { + if( !_order->on_fill.empty() ) // This order's on_fill is being removed + { + // Two scenarios: + // 1. The linked order is generated by this order, now this order's on_fill is being removed, so unlink + // 2. This order is generated by the linked order, and "repeat" was true, now this order's on_fill is + // being removed, so it becomes incompatible with the linked order, so unlink + is_compatible = false; + } + // else there is no change, nothing to do here + } + else // o.on_fill is not empty + { + if( _order->on_fill.empty() ) + { + // It means this order was generated by the linked order, and the linked order's "repeat" is false. + // We are adding on_fill to this order, so it becomes incompatible with the linked order, so unlink. + is_compatible = false; + } + else // Not empty + { + // Two scenarios: + // 1. Both order's "repeat" are true + // 2. This order's "repeat" was false, and the linked order was generated by this order + // + // Either way, if "spread_percent" or "repeat" in on_fill changed, unlink the linked take profit order. + const auto& old_take_profit_action = _order->get_take_profit_action(); + const auto& new_take_profit_action = o.on_fill->front().get(); + if( old_take_profit_action.spread_percent != new_take_profit_action.spread_percent + || old_take_profit_action.repeat != new_take_profit_action.repeat ) + { + is_compatible = false; + } + } // whether order's on_fill is empty (both handled) + } // whether o.on_fill is empty (both handled) + return is_compatible; +}; + void_result limit_order_update_evaluator::do_apply(const limit_order_update_operation& o) { try { database& d = db(); @@ -347,8 +416,33 @@ void_result limit_order_update_evaluator::do_apply(const limit_order_update_oper // Process deferred fee in the order. process_deferred_fee(); + // Process linked take profit order + bool unlink = false; + if( _order->take_profit_order_id.valid() ) + { + // If price changed, unless it is triggered by on_fill of the linked take profit order, + // unlink the linked take profit order. + if( !trx_state->skip_limit_order_price_check + && o.new_price.valid() && *o.new_price != _order->sell_price ) + { + unlink = true; + } + // If on_fill changed and the order became incompatible with the linked order, unlink + else + unlink = !is_linked_tp_order_compatible( o ); + + // Now update database + if( unlink ) + { + const auto& take_profit_order = (*_order->take_profit_order_id)(d); + d.modify( take_profit_order, []( limit_order_object& loo ) { + loo.take_profit_order_id.reset(); + }); + } + } + // Update order - d.modify(*_order, [&o,this](limit_order_object& loo) { + d.modify(*_order, [&o,this,unlink](limit_order_object& loo) { if (o.new_price) loo.sell_price = *o.new_price; if (o.delta_amount_to_sell) @@ -357,6 +451,10 @@ void_result limit_order_update_evaluator::do_apply(const limit_order_update_oper loo.expiration = *o.new_expiration; loo.deferred_fee = _deferred_fee; loo.deferred_paid_fee = _deferred_paid_fee; + if( o.on_fill ) + loo.on_fill= *o.on_fill; + if( unlink ) + loo.take_profit_order_id.reset(); }); // Perform order matching if necessary diff --git a/libraries/chain/market_object.cpp b/libraries/chain/market_object.cpp index 42ec31d5d0..bc78adb1d0 100644 --- a/libraries/chain/market_object.cpp +++ b/libraries/chain/market_object.cpp @@ -309,7 +309,7 @@ share_type call_order_object::get_max_debt_to_cover( price match_price, FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::limit_order_object, (graphene::db::object), (expiration)(seller)(for_sale)(sell_price)(deferred_fee)(deferred_paid_fee) - (is_settled_debt) + (is_settled_debt)(on_fill)(take_profit_order_id) ) FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::call_order_object, (graphene::db::object), diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index aad9ccb5b1..62efcb708e 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -75,6 +75,14 @@ struct proposal_operation_hardfork_visitor FC_ASSERT( HARDFORK_CORE_1604_PASSED(block_time), "Operation is not enabled yet" ); } + // hf_2535 + void operator()(const graphene::chain::limit_order_create_operation& op) const { + if( !HARDFORK_CORE_2535_PASSED(block_time) ) { + FC_ASSERT( !op.extensions.value.on_fill.valid(), + "The on_fill extension is not allowed until the core-2535 hardfork"); + } + } + void operator()(const graphene::chain::asset_create_operation &v) const { detail::check_asset_options_hf_1774(block_time, v.common_options); detail::check_asset_options_hf_bsip_48_75(block_time, v.common_options); diff --git a/libraries/protocol/include/graphene/protocol/market.hpp b/libraries/protocol/include/graphene/protocol/market.hpp index 5e5d99cb94..21dc2cd2ad 100644 --- a/libraries/protocol/include/graphene/protocol/market.hpp +++ b/libraries/protocol/include/graphene/protocol/market.hpp @@ -27,6 +27,30 @@ namespace graphene { namespace protocol { + /** + * Creates a take profit limit order + */ + struct create_take_profit_order_action + { + /// Asset ID that will be used to pay operation fee for placing the take profit order + asset_id_type fee_asset_id; + /// A percentage indicating how far the price of the take profit order differs from the original order + uint16_t spread_percent = 0; + /// A percentage indicating how much amount to sell in the take profit order + uint16_t size_percent = GRAPHENE_100_PERCENT; + /// How long the take profit order to be kept on the market + uint32_t expiration_seconds = 0; + /// Whether to create another take profit order for this take profit order if this take profit order is matched + bool repeat = false; + + extensions_type extensions; ///< Unused. Reserved for future use. + + void validate()const; + }; + + /// Automatic actions for limit orders + using limit_order_auto_action = static_variant< create_take_profit_order_action >; + /** * @class limit_order_create_operation * @brief instructs the blockchain to attempt to sell one asset for another @@ -47,6 +71,17 @@ namespace graphene { namespace protocol { */ struct limit_order_create_operation : public base_operation { + /** + * Options to be used in @ref limit_order_create_operation + * + * @note this struct can be expanded by adding more options in the end. + */ + struct options_type + { + /// Automatic actions when the limit order is filled or partially filled + optional< vector< limit_order_auto_action > > on_fill; + }; + struct fee_params_t { uint64_t fee = 5 * GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; @@ -60,6 +95,8 @@ namespace graphene { namespace protocol { /// If this flag is set the entire order must be filled or the operation is rejected bool fill_or_kill = false; + + using extensions_type = extension; // note: will be jsonified to {...} but not [...] extensions_type extensions; pair get_market()const @@ -89,6 +126,8 @@ namespace graphene { namespace protocol { optional new_price; optional delta_amount_to_sell; optional new_expiration; + /// Automatic actions when the limit order is filled or partially filled + optional< vector< limit_order_auto_action > > on_fill; extensions_type extensions; @@ -150,7 +189,7 @@ namespace graphene { namespace protocol { asset delta_collateral; ///< the amount of collateral to add to the margin position asset delta_debt; ///< the amount of the debt to be paid off, may be negative to issue new debt - typedef extension extensions_type; // note: this will be jsonified to {...} but no longer [...] + using extensions_type = extension; // note: this will be jsonified to {...} but no longer [...] extensions_type extensions; account_id_type fee_payer()const { return funding_account; } @@ -241,6 +280,9 @@ namespace graphene { namespace protocol { }; } } // graphene::protocol +FC_REFLECT( graphene::protocol::create_take_profit_order_action, + (fee_asset_id)(spread_percent)(size_percent)(expiration_seconds)(repeat)(extensions) ) + FC_REFLECT( graphene::protocol::limit_order_create_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::limit_order_update_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::limit_order_cancel_operation::fee_params_t, (fee) ) @@ -249,6 +291,7 @@ FC_REFLECT( graphene::protocol::bid_collateral_operation::fee_params_t, (fee) ) FC_REFLECT( graphene::protocol::fill_order_operation::fee_params_t, ) // VIRTUAL FC_REFLECT( graphene::protocol::execute_bid_operation::fee_params_t, ) // VIRTUAL +FC_REFLECT( graphene::protocol::limit_order_create_operation::options_type, (on_fill) ) FC_REFLECT( graphene::protocol::call_order_update_operation::options_type, (target_collateral_ratio) ) FC_REFLECT( graphene::protocol::limit_order_create_operation, @@ -266,12 +309,17 @@ FC_REFLECT( graphene::protocol::bid_collateral_operation, FC_REFLECT( graphene::protocol::execute_bid_operation, (fee)(bidder)(debt)(collateral) ) +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::create_take_profit_order_action) + +GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_create_operation::options_type ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::call_order_update_operation::options_type ) + GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_create_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_update_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_cancel_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::call_order_update_operation::fee_params_t ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::bid_collateral_operation::fee_params_t ) + GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_create_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_update_operation ) GRAPHENE_DECLARE_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_cancel_operation ) diff --git a/libraries/protocol/market.cpp b/libraries/protocol/market.cpp index e930db0465..63bbdfb17f 100644 --- a/libraries/protocol/market.cpp +++ b/libraries/protocol/market.cpp @@ -27,23 +27,58 @@ namespace graphene { namespace protocol { +void create_take_profit_order_action::validate() const +{ + FC_ASSERT( spread_percent > 0, "The spread percentage must be positive" ); + FC_ASSERT( size_percent > 0, "The size percentage must be positive" ); + FC_ASSERT( size_percent <= GRAPHENE_100_PERCENT, "The size percentage must not exceed 100%" ); + FC_ASSERT( expiration_seconds > 0, "The expiration seconds must be positive" ); +} + +struct lo_action_validate_visitor +{ + using result_type = void; + + template + result_type operator()( const ActionType& action )const + { + action.validate(); + } +}; + void limit_order_create_operation::validate()const { FC_ASSERT( amount_to_sell.asset_id != min_to_receive.asset_id ); FC_ASSERT( fee.amount >= 0 ); FC_ASSERT( amount_to_sell.amount > 0 ); FC_ASSERT( min_to_receive.amount > 0 ); + + if( extensions.value.on_fill.valid() ) + { + // Note: an empty on_fill action list is allowed + for( const auto& action : *extensions.value.on_fill ) + action.visit( lo_action_validate_visitor() ); + } + } void limit_order_update_operation::validate() const { try { FC_ASSERT(fee.amount >= 0, "Fee must not be negative"); - FC_ASSERT(new_price || delta_amount_to_sell || new_expiration, + FC_ASSERT(new_price || delta_amount_to_sell || new_expiration || on_fill, "Cannot update limit order if nothing is specified to update"); if (new_price) new_price->validate(); if (delta_amount_to_sell) FC_ASSERT(delta_amount_to_sell->amount != 0, "Cannot change limit order amount by zero"); + + if( on_fill.valid() ) + { + // Note: an empty on_fill action list is allowed + for( const auto& action : *on_fill ) + action.visit( lo_action_validate_visitor() ); + } + } FC_CAPTURE_AND_RETHROW((*this)) } // GCOVR_EXCL_LINE void limit_order_cancel_operation::validate()const @@ -69,12 +104,17 @@ void bid_collateral_operation::validate()const } } // graphene::protocol +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::create_take_profit_order_action ) + +GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_create_operation::options_type ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::call_order_update_operation::options_type ) + GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_create_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_update_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_cancel_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::call_order_update_operation::fee_params_t ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::bid_collateral_operation::fee_params_t ) + GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_create_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_update_operation ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::protocol::limit_order_cancel_operation ) From 78816b7ab47092d27b275b9239cef6726cfebf12 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 13 Jun 2023 22:13:37 +0000 Subject: [PATCH 114/127] Add tests for take profit order feature --- tests/common/database_fixture.cpp | 85 +- tests/common/database_fixture.hpp | 47 +- tests/tests/oso_take_profit_order_tests.cpp | 1574 +++++++++++++++++++ 3 files changed, 1651 insertions(+), 55 deletions(-) create mode 100644 tests/tests/oso_take_profit_order_tests.cpp diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index c2462ef32c..63bf0b7fc4 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -1163,27 +1163,31 @@ digest_type database_fixture_base::digest( const transaction& tx ) return tx.digest(); } -const limit_order_object* database_fixture_base::create_sell_order(account_id_type user, const asset& amount, const asset& recv, - const time_point_sec order_expiration, - const price& fee_core_exchange_rate ) +limit_order_create_operation database_fixture_base::make_limit_order_create_op( + const account_id_type& user, const asset& amount, const asset& recv, + const time_point_sec& order_expiration, + const optional< vector< limit_order_auto_action > >& on_fill ) const { - auto r = create_sell_order( user(db), amount, recv, order_expiration, fee_core_exchange_rate ); - verify_asset_supplies(db); - return r; + limit_order_create_operation buy_order; + buy_order.seller = user; + buy_order.amount_to_sell = amount; + buy_order.min_to_receive = recv; + buy_order.expiration = order_expiration; + buy_order.extensions.value.on_fill = on_fill; + return buy_order; } -const limit_order_object* database_fixture_base::create_sell_order( const account_object& user, const asset& amount, const asset& recv, - const time_point_sec order_expiration, - const price& fee_core_exchange_rate ) +const limit_order_object* database_fixture_base::create_sell_order( + const account_id_type& user, const asset& amount, const asset& recv, + const time_point_sec& order_expiration, + const price& fee_core_exchange_rate, + const optional< vector< limit_order_auto_action > >& on_fill ) { set_expiration( db, trx ); trx.operations.clear(); - limit_order_create_operation buy_order; - buy_order.seller = user.id; - buy_order.amount_to_sell = amount; - buy_order.min_to_receive = recv; - buy_order.expiration = order_expiration; + limit_order_create_operation buy_order = make_limit_order_create_op( user, amount, recv, order_expiration, + on_fill ); trx.operations = {buy_order}; for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op, fee_core_exchange_rate); trx.validate(); @@ -1193,12 +1197,22 @@ const limit_order_object* database_fixture_base::create_sell_order( const accoun return db.find( processed.operation_results[0].get() ); } +const limit_order_object* database_fixture_base::create_sell_order( + const account_object& user, const asset& amount, const asset& recv, + const time_point_sec& order_expiration, + const price& fee_core_exchange_rate, + const optional< vector< limit_order_auto_action > >& on_fill ) +{ + return create_sell_order( user.get_id(), amount, recv, order_expiration, fee_core_exchange_rate ); +} + limit_order_update_operation database_fixture_base::make_limit_order_update_op( - account_id_type seller_id, - limit_order_id_type order_id, - fc::optional new_price, - fc::optional delta_amount, - fc::optional new_expiration )const + const account_id_type& seller_id, + const limit_order_id_type& order_id, + const fc::optional& new_price, + const fc::optional& delta_amount, + const fc::optional& new_expiration, + const optional< vector< limit_order_auto_action > >& on_fill )const { limit_order_update_operation update_order; update_order.seller = seller_id; @@ -1206,21 +1220,19 @@ limit_order_update_operation database_fixture_base::make_limit_order_update_op( update_order.new_price = new_price; update_order.delta_amount_to_sell = delta_amount; update_order.new_expiration = new_expiration; + update_order.on_fill = on_fill; return update_order; } void database_fixture_base::update_limit_order(const limit_order_object& order, - fc::optional new_price, - fc::optional delta_amount, - fc::optional new_expiration, - const price& fee_core_exchange_rate ) -{ - limit_order_update_operation update_order; - update_order.seller = order.seller; - update_order.order = order.id; - update_order.new_price = new_price; - update_order.delta_amount_to_sell = delta_amount; - update_order.new_expiration = new_expiration; + const fc::optional& new_price, + const fc::optional& delta_amount, + const fc::optional& new_expiration, + const price& fee_core_exchange_rate, + const optional< vector< limit_order_auto_action > >& on_fill ) +{ + limit_order_update_operation update_order = make_limit_order_update_op( order.seller, order.get_id(), new_price, + delta_amount, new_expiration, on_fill ); trx.operations = {update_order}; for(auto& op : trx.operations) db.current_fee_schedule().set_fee(op, fee_core_exchange_rate); trx.validate(); @@ -1229,13 +1241,14 @@ void database_fixture_base::update_limit_order(const limit_order_object& order, verify_asset_supplies(db); } -void database_fixture_base::update_limit_order(limit_order_id_type order_id, - fc::optional new_price, - fc::optional delta_amount, - fc::optional new_expiration, - const price& fee_core_exchange_rate ) +void database_fixture_base::update_limit_order(const limit_order_id_type& order_id, + const fc::optional& new_price, + const fc::optional& delta_amount, + const fc::optional& new_expiration, + const price& fee_core_exchange_rate, + const optional< vector< limit_order_auto_action > >& on_fill ) { - update_limit_order(order_id(db), new_price, delta_amount, new_expiration, fee_core_exchange_rate); + update_limit_order( order_id(db), new_price, delta_amount, new_expiration, fee_core_exchange_rate, on_fill ); } asset database_fixture_base::cancel_limit_order( const limit_order_object& order ) diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index 2a876dde30..3629aa7aa4 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -411,28 +411,37 @@ struct database_fixture_base { uint64_t fund( const account_object& account, const asset& amount = asset(500000) ); digest_type digest( const transaction& tx ); void sign( signed_transaction& trx, const fc::ecc::private_key& key ); - const limit_order_object* create_sell_order( account_id_type user, const asset& amount, const asset& recv, - const time_point_sec order_expiration = time_point_sec::maximum(), - const price& fee_core_exchange_rate = price::unit_price() ); + limit_order_create_operation make_limit_order_create_op( + const account_id_type& user, const asset& amount, const asset& recv, + const time_point_sec& order_expiration = time_point_sec::maximum(), + const optional< vector< limit_order_auto_action > >& on_fill = {} ) const; + const limit_order_object* create_sell_order( const account_id_type& user, const asset& amount, const asset& recv, + const time_point_sec& order_expiration = time_point_sec::maximum(), + const price& fee_core_exchange_rate = price::unit_price(), + const optional< vector< limit_order_auto_action > >& on_fill = {} ); const limit_order_object* create_sell_order( const account_object& user, const asset& amount, const asset& recv, - const time_point_sec order_expiration = time_point_sec::maximum(), - const price& fee_core_exchange_rate = price::unit_price() ); + const time_point_sec& order_expiration = time_point_sec::maximum(), + const price& fee_core_exchange_rate = price::unit_price(), + const optional< vector< limit_order_auto_action > >& on_fill = {} ); limit_order_update_operation make_limit_order_update_op( - account_id_type seller_id, - limit_order_id_type order_id, - fc::optional new_price = {}, - fc::optional delta_amount = {}, - fc::optional new_expiration = {} )const; + const account_id_type& seller_id, + const limit_order_id_type& order_id, + const fc::optional& new_price = {}, + const fc::optional& delta_amount = {}, + const fc::optional& new_expiration = {}, + const optional< vector< limit_order_auto_action > >& on_fill = {} )const; void update_limit_order(const limit_order_object& order, - fc::optional new_price = {}, - fc::optional delta_amount = {}, - fc::optional new_expiration = {}, - const price& fee_core_exchange_rate = price::unit_price() ); - void update_limit_order(limit_order_id_type order_id, - fc::optional new_price = {}, - fc::optional delta_amount = {}, - fc::optional new_expiration = {}, - const price& fee_core_exchange_rate = price::unit_price() ); + const fc::optional& new_price = {}, + const fc::optional& delta_amount = {}, + const fc::optional& new_expiration = {}, + const price& fee_core_exchange_rate = price::unit_price(), + const optional< vector< limit_order_auto_action > >& on_fill = {} ); + void update_limit_order(const limit_order_id_type& order_id, + const fc::optional& new_price = {}, + const fc::optional& delta_amount = {}, + const fc::optional& new_expiration = {}, + const price& fee_core_exchange_rate = price::unit_price(), + const optional< vector< limit_order_auto_action > >& on_fill = {} ); asset cancel_limit_order( const limit_order_object& order ); void transfer( account_id_type from, account_id_type to, const asset& amount, const asset& fee = asset() ); void transfer( const account_object& from, const account_object& to, const asset& amount, const asset& fee = asset() ); diff --git a/tests/tests/oso_take_profit_order_tests.cpp b/tests/tests/oso_take_profit_order_tests.cpp new file mode 100644 index 0000000000..67d435c58f --- /dev/null +++ b/tests/tests/oso_take_profit_order_tests.cpp @@ -0,0 +1,1574 @@ +/* + * Copyright (c) 2023 Abit More, and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "../common/database_fixture.hpp" + +#include +#include +#include + +#include + +#include + +using namespace graphene::chain; +using namespace graphene::chain::test; + +BOOST_FIXTURE_TEST_SUITE( oso_tests, database_fixture ) + +BOOST_AUTO_TEST_CASE( oso_take_profit_order_hardfork_time_test ) +{ try { + + // Proceeds to a recent hard fork + generate_blocks( HARDFORK_CORE_2362_TIME ); + generate_block(); + set_expiration( db, trx ); + + ACTORS((sam)); + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( sam, asset(init_amount) ); + + const asset_object& usd = create_user_issued_asset( "MYUSD" ); + asset_id_type usd_id = usd.get_id(); + + // Before the hard fork, unable to create a limit order with the "on_fill" extension + // or create with proposals, + // but can create without on_fill + create_take_profit_order_action tpa1 { asset_id_type(), 5, GRAPHENE_100_PERCENT, 3600, false }; + vector on_fill { tpa1 }; + + // With on_fill + BOOST_CHECK_THROW( create_sell_order( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), price::unit_price(), on_fill ), + fc::exception ); + // Without on_fill + create_sell_order( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), price::unit_price(), {} ); + + // Proposal with on_fill + limit_order_create_operation cop1 = make_limit_order_create_op( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), on_fill ); + BOOST_CHECK_THROW( propose( cop1 ), fc::exception ); + // Proposal without on_fill + limit_order_create_operation cop2 = make_limit_order_create_op( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), {} ); + propose( cop2 ); + +} FC_LOG_AND_RETHROW() } + +/// Tests setting up oso with limit_order_create_operation +BOOST_AUTO_TEST_CASE( oso_take_profit_order_setup_test ) +{ try { + + // Proceeds to the hard fork + generate_blocks( HARDFORK_CORE_2535_TIME ); + generate_block(); + set_expiration( db, trx ); + + ACTORS((sam)); + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( sam, asset(init_amount) ); + + const asset_object& usd = create_user_issued_asset( "MYUSD" ); + asset_id_type usd_id = usd.get_id(); + + // Spread percentage should be positive + create_take_profit_order_action tpa1 { asset_id_type(), 0, GRAPHENE_100_PERCENT, 3600, false }; + vector on_fill { tpa1 }; + BOOST_CHECK_THROW( create_sell_order( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), price::unit_price(), on_fill ), + fc::exception ); + // Cannot propose either + limit_order_create_operation cop1 = make_limit_order_create_op( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), on_fill ); + BOOST_CHECK_THROW( propose( cop1 ), fc::exception ); + + // Size percentage should be positive + tpa1 = { asset_id_type(), 1, 0, 3600, false }; + on_fill = { tpa1 }; + BOOST_CHECK_THROW( create_sell_order( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), price::unit_price(), on_fill ), + fc::exception ); + // Cannot propose either + cop1 = make_limit_order_create_op( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), on_fill ); + BOOST_CHECK_THROW( propose( cop1 ), fc::exception ); + + // Size percentage should not exceed 100% + tpa1 = { asset_id_type(), 1, GRAPHENE_100_PERCENT + 1, 3600, false }; + on_fill = { tpa1 }; + BOOST_CHECK_THROW( create_sell_order( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), price::unit_price(), on_fill ), + fc::exception ); + // Cannot propose either + cop1 = make_limit_order_create_op( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), on_fill ); + BOOST_CHECK_THROW( propose( cop1 ), fc::exception ); + + // Expiration should be positive + tpa1 = { asset_id_type(), 1, GRAPHENE_100_PERCENT, 0, false }; + on_fill = { tpa1 }; + BOOST_CHECK_THROW( create_sell_order( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), price::unit_price(), on_fill ), + fc::exception ); + // Cannot propose either + cop1 = make_limit_order_create_op( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), on_fill ); + BOOST_CHECK_THROW( propose( cop1 ), fc::exception ); + + // Fee asset should exist + tpa1 = { usd_id + 1, 1, GRAPHENE_100_PERCENT, 3600, false }; + on_fill = { tpa1 }; + BOOST_CHECK_THROW( create_sell_order( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), price::unit_price(), on_fill ), + fc::exception ); + // Can propose + cop1 = make_limit_order_create_op( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), on_fill ); + propose( cop1 ); + + // on_fill must contain only 1 action + tpa1 = { asset_id_type(), 1, GRAPHENE_100_PERCENT, 3600, false }; + // size == 0 + on_fill = {}; + BOOST_CHECK_THROW( create_sell_order( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), price::unit_price(), on_fill ), + fc::exception ); + // Can propose + cop1 = make_limit_order_create_op( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), on_fill ); + propose( cop1 ); + // size > 1 + on_fill = { tpa1, tpa1 }; + BOOST_CHECK_THROW( create_sell_order( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), price::unit_price(), on_fill ), + fc::exception ); + // Can propose + cop1 = make_limit_order_create_op( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), on_fill ); + propose( cop1 ); + + // A valid operation with on_fill + tpa1 = { asset_id_type(), 1, GRAPHENE_100_PERCENT, 3600, false }; + on_fill = { tpa1 }; + const limit_order_object* order1 = create_sell_order( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), price::unit_price(), on_fill ); + // Can propose + cop1 = make_limit_order_create_op( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), on_fill ); + propose( cop1 ); + + BOOST_REQUIRE( order1 ); + limit_order_id_type order1_id = order1->get_id(); + + // Another order without on_fill + const limit_order_object* order2 = create_sell_order( sam_id, asset(1), asset(1, usd_id), + time_point_sec::maximum(), price::unit_price(), {} ); + BOOST_REQUIRE( order2 ); + limit_order_id_type order2_id = order2->get_id(); + + // Final check + const auto& check_result = [&]() + { + BOOST_CHECK( order2_id(db).on_fill.empty() ); + + BOOST_REQUIRE_EQUAL( order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( order1_id(db).on_fill.front().is_type() ); + const auto& action = order1_id(db).on_fill.front().get(); + BOOST_CHECK( action.fee_asset_id == tpa1.fee_asset_id ); + BOOST_CHECK( action.spread_percent == tpa1.spread_percent ); + BOOST_CHECK( action.size_percent == tpa1.size_percent ); + BOOST_CHECK( action.expiration_seconds == tpa1.expiration_seconds ); + BOOST_CHECK( action.repeat == tpa1.repeat ); + }; + + check_result(); + + generate_block(); + + check_result(); + +} FC_LOG_AND_RETHROW() } + +/// Tests order-sends-take-profit-order and related order cancellation +BOOST_AUTO_TEST_CASE( oso_take_profit_order_trigger_and_cancel_test ) +{ try { + + // Proceeds to the hard fork + generate_blocks( HARDFORK_CORE_2535_TIME ); + generate_block(); + set_expiration( db, trx ); + + ACTORS((sam)(ted)); + + additional_asset_options_t usd_options; + usd_options.value.taker_fee_percent = 80; // 0.8% taker fee + + const asset_object& usd = create_user_issued_asset( "MYUSD", ted, charge_market_fee | white_list, + price(asset(1, asset_id_type(1)), asset(1)), + 4, 30, usd_options ); // 0.3% maker fee + asset_id_type usd_id = usd.get_id(); + asset_id_type core_id; + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( sam, asset(init_amount) ); + fund( ted, asset(init_amount) ); + issue_uia( ted, asset(init_amount, usd_id) ); + + int64_t expected_balance_sam_core = init_amount; + int64_t expected_balance_ted_core = init_amount; + int64_t expected_balance_sam_usd = 0; + int64_t expected_balance_ted_usd = init_amount; + + const auto& check_balances = [&]() { + BOOST_CHECK_EQUAL( db.get_balance( sam_id, core_id ).amount.value, expected_balance_sam_core ); + BOOST_CHECK_EQUAL( db.get_balance( ted_id, core_id ).amount.value, expected_balance_ted_core ); + BOOST_CHECK_EQUAL( db.get_balance( sam_id, usd_id ).amount.value, expected_balance_sam_usd ); + BOOST_CHECK_EQUAL( db.get_balance( ted_id, usd_id ).amount.value, expected_balance_ted_usd ); + }; + + check_balances(); + + // Sam sells CORE for USD with on_fill + // fee_asset, spread, size, expiration, repeat + create_take_profit_order_action tpa1 { core_id, 100, 10000, 3600, false }; + vector on_fill_1 { tpa1 }; + + const limit_order_object* sell_order1 = create_sell_order( sam_id, asset(10000), asset(12345, usd_id), + time_point_sec::maximum(), price::unit_price(), on_fill_1 ); + BOOST_REQUIRE( sell_order1 ); + limit_order_id_type sell_order1_id = sell_order1->get_id(); + + limit_order_id_type last_order_id = sell_order1_id; + + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa1.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa1.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa1.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa1.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa1.repeat ); + + expected_balance_sam_core -= 10000; + check_balances(); + + // Ted buys CORE with USD without on_fill, partially fills Sam's order + const limit_order_object* buy_order1 = create_sell_order( ted_id, asset(1235, usd_id), asset(1000) ); + last_order_id = last_order_id + 1; + + // The buy order is smaller, it gets fully filled + BOOST_CHECK( !buy_order1 ); + expected_balance_ted_core += 1000; + expected_balance_ted_usd -= 1235; + + // The newly created take profit order is a buy order + last_order_id = last_order_id + 1; + limit_order_id_type buy_order2_id = last_order_id; + + auto buy_order2_expiration = db.head_block_time() + 3600; + + const auto& check_result_1 = [&]() + { + // The sell order is partially filled + BOOST_REQUIRE( db.find(sell_order1_id) ); + // The take profit order + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + // The sell order gets 1235, market fee = round_down(1235 * 30 / 10000) = 3 + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 1232 ); // 1235 - 3 + // price = (12345 / 10000) / 101% = 12345 / 10100 + // min to receive = round_up( 1232 * 10100 / 12345 ) = 1008 + // updated price = 1232 / 1008 + BOOST_CHECK( buy_order2_id(db).sell_price == asset(1232,usd_id) / asset(1008) ); + BOOST_CHECK( buy_order2_id(db).expiration == buy_order2_expiration ); + BOOST_CHECK( buy_order2_id(db).take_profit_order_id == sell_order1_id ); + BOOST_CHECK( buy_order2_id(db).on_fill.empty() ); + + // The sell order is partially filled, pays 1000 + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 9000 ); // 10000 - 1000 + BOOST_CHECK( sell_order1_id(db).take_profit_order_id == buy_order2_id ); + + check_balances(); + }; + + check_result_1(); + + generate_block(); + + check_result_1(); + + // Sam sells more CORE for USD with on_fill + // fee_asset, spread, size, expiration, repeat + create_take_profit_order_action tpa2 { usd_id, 70, 9700, uint32_t(-1), true }; + vector on_fill_2 { tpa2 }; + + const limit_order_object* sell_order2 = create_sell_order( sam_id, asset(10000), asset(13000, usd_id), + time_point_sec::maximum(), price::unit_price(), on_fill_2 ); + last_order_id = last_order_id + 1; + + BOOST_REQUIRE( sell_order2 ); + limit_order_id_type sell_order2_id = sell_order2->get_id(); + + BOOST_REQUIRE_EQUAL( sell_order2_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order2_id(db).on_fill.front().is_type() ); + const auto& action_s2 = sell_order2_id(db).on_fill.front().get(); + BOOST_CHECK( action_s2.fee_asset_id == tpa2.fee_asset_id ); + BOOST_CHECK( action_s2.spread_percent == tpa2.spread_percent ); + BOOST_CHECK( action_s2.size_percent == tpa2.size_percent ); + BOOST_CHECK( action_s2.expiration_seconds == tpa2.expiration_seconds ); + BOOST_CHECK( action_s2.repeat == tpa2.repeat ); + + expected_balance_sam_core -= 10000; + check_balances(); + + // Sam sells yet more CORE for USD with on_fill + // fee_asset, spread, size, expiration, repeat + create_take_profit_order_action tpa3 { usd_id, 70, 9970, 3600, true }; + vector on_fill_3 { tpa3 }; + + const limit_order_object* sell_order3 = create_sell_order( sam_id, asset(10000), asset(34000, usd_id), + db.head_block_time() + 7200, price::unit_price(), on_fill_3 ); + last_order_id = last_order_id + 1; + + BOOST_REQUIRE( sell_order3 ); + limit_order_id_type sell_order3_id = sell_order3->get_id(); + + // Data backup + auto sell_order3_expiration = sell_order3->expiration; + + BOOST_REQUIRE_EQUAL( sell_order3_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order3_id(db).on_fill.front().is_type() ); + const auto& action_s3 = sell_order3_id(db).on_fill.front().get(); + BOOST_CHECK( action_s3.fee_asset_id == tpa3.fee_asset_id ); + BOOST_CHECK( action_s3.spread_percent == tpa3.spread_percent ); + BOOST_CHECK( action_s3.size_percent == tpa3.size_percent ); + BOOST_CHECK( action_s3.expiration_seconds == tpa3.expiration_seconds ); + BOOST_CHECK( action_s3.repeat == tpa3.repeat ); + + expected_balance_sam_core -= 10000; + check_balances(); + + // Ted buys CORE with USD with on_fill, fills Sam's orders + // fee_asset, spread, size, expiration, repeat + create_take_profit_order_action tpa4 { core_id, 1, 9999, uint32_t(-1), true }; + vector on_fill_4 { tpa4 }; + + const limit_order_object* buy_order3 = create_sell_order( ted_id, asset(30000, usd_id), asset(7000), + time_point_sec::maximum(), price::unit_price(), on_fill_4 ); + last_order_id = last_order_id + 1; + + // buy_order3 is fully filled + BOOST_CHECK( !buy_order3 ); + + // The take profit order created by sell_order1 is updated + auto buy_order2_expiration_new = db.head_block_time() + 3600; + + // The take profit order created by buy_order3 is a sell order + last_order_id = last_order_id + 1; + limit_order_id_type sell_order4_id = last_order_id; + auto sell_order4_expiration = time_point_sec::maximum(); + + // The take profit order created by sell_order2 is a buy order + last_order_id = last_order_id + 1; + limit_order_id_type buy_order4_id = last_order_id; + auto buy_order4_expiration = time_point_sec::maximum(); + + // The take profit order created by sell_order3 is a buy order + last_order_id = last_order_id + 1; + limit_order_id_type buy_order5_id = last_order_id; + auto buy_order5_expiration = db.head_block_time() + 3600; + + expected_balance_ted_core += 1; // see calculation below + expected_balance_ted_usd -= (30000 - 1); // buy_order3 refund 1, see calculation below + expected_balance_sam_usd += (388 + 17); // sell_order2 and sell_order3, see calculation below + + + const auto& check_result_2 = [&]() + { + // sell_order1 gets fully filled + BOOST_CHECK( !db.find(sell_order1_id) ); + + // The take profit order linked to sell_order1 (buy_order2) is updated + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + // sell_order1 pays 9000, gets round_down(9000 * 12345 / 10000) = 11110, market fee = 11110 * 30 / 10000 = 33 + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 12309 ); // 1232 + 11110 - 33 + // price = (12345 / 10000) / 101% = 12345 / 10100 + // min to receive = round_up( 12309 * 10100 / 12345 ) = 10071 + // updated price = 12309 / 10071 + BOOST_CHECK( buy_order2_id(db).sell_price == asset(12309,usd_id) / asset(10071) ); + BOOST_CHECK( buy_order2_id(db).expiration == buy_order2_expiration_new ); + BOOST_CHECK( buy_order2_id(db).expiration != buy_order2_expiration ); + BOOST_CHECK( !buy_order2_id(db).take_profit_order_id ); // cleared + BOOST_CHECK( buy_order2_id(db).on_fill.empty() ); + + // buy_order3 pays 11110, gets 9000, remaining for sale = 30000 - 11110 = 18890 + + // sell_order2 gets fully filled + BOOST_CHECK( !db.find(sell_order2_id) ); + + // The take profit order created by sell_order2 + BOOST_REQUIRE( db.find(buy_order4_id) ); + BOOST_CHECK( buy_order4_id(db).seller == sam_id ); + // sell_order2 gets 13000, market fee = round_down(13000 * 30 / 10000) = 39 + // gets = 13000 - 39 = 12961 + // take profit order size = round_up(12961 * 9700 / 10000) = 12573 + // Sam USD balance change = 12961 - 12573 = 388 + BOOST_CHECK_EQUAL( buy_order4_id(db).for_sale.value, 12573 ); + // price = (13000 / 10000) / 100.7% = 13000 / 10070 + // min to receive = round_up( 12573 * 10070 / 13000 ) = 9740 + // updated price = 12573 / 9740 + BOOST_CHECK( buy_order4_id(db).sell_price == asset(12573,usd_id) / asset(9740) ); + BOOST_CHECK( buy_order4_id(db).expiration == buy_order4_expiration ); + BOOST_CHECK( !buy_order4_id(db).take_profit_order_id ); + + BOOST_REQUIRE_EQUAL( buy_order4_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( buy_order4_id(db).on_fill.front().is_type() ); + const auto& action_b4 = buy_order4_id(db).on_fill.front().get(); + BOOST_CHECK( action_b4.fee_asset_id == tpa2.fee_asset_id ); + BOOST_CHECK( action_b4.spread_percent == tpa2.spread_percent ); + BOOST_CHECK( action_b4.size_percent == tpa2.size_percent ); + BOOST_CHECK( action_b4.expiration_seconds == tpa2.expiration_seconds ); + BOOST_CHECK( action_b4.repeat == tpa2.repeat ); + + // buy_order3 pays 13000, gets 10000, remaining for sale = 18890 - 13000 = 5890 + + // sell_order3 gets partially filled + BOOST_REQUIRE( db.find(sell_order3_id) ); + // The take profit order created by sell_order3 + BOOST_REQUIRE( db.find(buy_order5_id) ); + BOOST_CHECK( buy_order5_id(db).seller == sam_id ); + // sell_order3 gets 5890, pays round_down(5890 * 10000 / 34000) = 1732 + // updated gets = round_up(1732 * 34000 / 10000) = 5889, refund = 5890 - 5889 = 1 + // market fee = round_down(5889 * 30 / 10000) = 17 + // gets = 5889 - 17 = 5872 + // take profit order size = round_up(5872 * 9970 / 10000) = 5855 + // Sam USD balance change = 5872 - 5855 = 17 + BOOST_CHECK_EQUAL( buy_order5_id(db).for_sale.value, 5855 ); + // price = (34000 / 10000) / 100.7% = 34000 / 10070 + // min to receive = round_up( 5855 * 10070 / 34000 ) = 1735 + // updated price = 5855 / 1735 = 3.374639769 + BOOST_CHECK( buy_order5_id(db).sell_price == asset(5855,usd_id) / asset(1735) ); + BOOST_CHECK( buy_order5_id(db).expiration == buy_order5_expiration ); + BOOST_CHECK( buy_order5_id(db).take_profit_order_id == sell_order3_id ); + + BOOST_REQUIRE_EQUAL( buy_order5_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( buy_order5_id(db).on_fill.front().is_type() ); + const auto& action_b5 = buy_order5_id(db).on_fill.front().get(); + BOOST_CHECK( action_b5.fee_asset_id == tpa3.fee_asset_id ); + BOOST_CHECK( action_b5.spread_percent == tpa3.spread_percent ); + BOOST_CHECK( action_b5.size_percent == tpa3.size_percent ); + BOOST_CHECK( action_b5.expiration_seconds == tpa3.expiration_seconds ); + BOOST_CHECK( action_b5.repeat == tpa3.repeat ); + + // sell_order3 gets partially filled, pays 1732 + BOOST_CHECK_EQUAL( sell_order3_id(db).for_sale.value, 8268 ); // 10000 - 1732 + BOOST_CHECK( sell_order3_id(db).take_profit_order_id == buy_order5_id ); + + // buy_order3 gets 1732, pays 5889, refund 1 + + // The take profit order created by buy_order3 + BOOST_REQUIRE( db.find(sell_order4_id) ); + BOOST_CHECK( sell_order4_id(db).seller == ted_id ); + // buy_order3 got in total 9000 + 10000 + 1732 = 20732, market fee = 0 + // take profit order size = + // round_up(9000 * 9999 / 10000) + round_up(10000 * 9999 / 10000) + round_up(1732 * 9999 / 10000) = 20731 + // Ted CORE balance change = 20732 - 20731 = 1 + BOOST_CHECK_EQUAL( sell_order4_id(db).for_sale.value, 20731 ); + // price = (7000 / 30000) / 100.01% = 7000 / 30003 + // min to receive = round_up( 20731 * 30003 / 7000 ) = 88857 + // updated price = 20731 / 88857 + BOOST_CHECK( sell_order4_id(db).sell_price == asset(20731) / asset(88857,usd_id) ); + BOOST_CHECK( sell_order4_id(db).expiration == sell_order4_expiration ); + BOOST_CHECK( !sell_order4_id(db).take_profit_order_id ); + + BOOST_REQUIRE_EQUAL( sell_order4_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order4_id(db).on_fill.front().is_type() ); + const auto& action_s4 = sell_order4_id(db).on_fill.front().get(); + BOOST_CHECK( action_s4.fee_asset_id == tpa4.fee_asset_id ); + BOOST_CHECK( action_s4.spread_percent == tpa4.spread_percent ); + BOOST_CHECK( action_s4.size_percent == tpa4.size_percent ); + BOOST_CHECK( action_s4.expiration_seconds == tpa4.expiration_seconds ); + BOOST_CHECK( action_s4.repeat == tpa4.repeat ); + + check_balances(); + }; + + check_result_2(); + + generate_block(); + + check_result_2(); + + // Ted sells CORE for USD with on_fill + // fee_asset, spread, size, expiration, repeat + create_take_profit_order_action tpa5 { usd_id, 65535, 1, 8800, true }; + vector on_fill_5 { tpa5 }; + + const limit_order_object* sell_order5 = create_sell_order( ted_id, asset(1), asset(1, usd_id), + db.head_block_time() + 9900, price::unit_price(), on_fill_5 ); + last_order_id = last_order_id + 1; + + // sell_order5 is fully filled + BOOST_CHECK( !sell_order5 ); + + // buy_order5 is partially filled + // The take profit order linked to buy_order5 (sell_order3) is updated + auto sell_order3_expiration_new = db.head_block_time() + 3600; + + // The take profit order created by sell_order5 is a buy order + last_order_id = last_order_id + 1; + limit_order_id_type buy_order6_id = last_order_id; + auto buy_order6_expiration = db.head_block_time() + 8800; + + expected_balance_ted_core -= 1; // see calculation below + expected_balance_ted_usd += 2; // see calculation below + + const auto check_result_3 = [&]() + { + // buy_order5 is partially filled + BOOST_REQUIRE( db.find(buy_order5_id) ); + BOOST_CHECK( buy_order5_id(db).seller == sam_id ); + // buy_order5 gets 1, pays round_down(1 * 5855 / 1735) = 3 + BOOST_CHECK_EQUAL( buy_order5_id(db).for_sale.value, 5852 ); // 5855 - 3 + BOOST_CHECK( buy_order5_id(db).sell_price == asset(5855,usd_id) / asset(1735) ); // unchanged + BOOST_CHECK( buy_order5_id(db).expiration == buy_order5_expiration ); // unchanged + BOOST_CHECK( buy_order5_id(db).take_profit_order_id == sell_order3_id ); // unchanged + + // All unchanged + BOOST_REQUIRE_EQUAL( buy_order5_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( buy_order5_id(db).on_fill.front().is_type() ); + const auto& action_b5 = buy_order5_id(db).on_fill.front().get(); + BOOST_CHECK( action_b5.fee_asset_id == tpa3.fee_asset_id ); + BOOST_CHECK( action_b5.spread_percent == tpa3.spread_percent ); + BOOST_CHECK( action_b5.size_percent == tpa3.size_percent ); + BOOST_CHECK( action_b5.expiration_seconds == tpa3.expiration_seconds ); + BOOST_CHECK( action_b5.repeat == tpa3.repeat ); + + // The take profit order linked to buy_order5 (sell_order3) is updated + BOOST_REQUIRE( db.find(sell_order3_id) ); + BOOST_CHECK( sell_order3_id(db).seller == sam_id ); + // new amount for sale = round_up(1 * 99.7%) = 1, account balances unchanged + BOOST_CHECK_EQUAL( sell_order3_id(db).for_sale.value, 8269 ); // 8268 + 1 + BOOST_CHECK( sell_order3_id(db).sell_price == asset(10000) / asset(34000,usd_id) ); // unchanged + BOOST_CHECK( sell_order3_id(db).expiration == sell_order3_expiration_new ); + BOOST_CHECK( sell_order3_id(db).expiration != sell_order3_expiration ); + BOOST_CHECK( sell_order3_id(db).take_profit_order_id == buy_order5_id ); // unchanged + + // All unchanged + BOOST_REQUIRE_EQUAL( sell_order3_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order3_id(db).on_fill.front().is_type() ); + const auto& action_s3 = sell_order3_id(db).on_fill.front().get(); + BOOST_CHECK( action_s3.fee_asset_id == tpa3.fee_asset_id ); + BOOST_CHECK( action_s3.spread_percent == tpa3.spread_percent ); + BOOST_CHECK( action_s3.size_percent == tpa3.size_percent ); + BOOST_CHECK( action_s3.expiration_seconds == tpa3.expiration_seconds ); + BOOST_CHECK( action_s3.repeat == tpa3.repeat ); + + // The take profit order created by sell_order5 + BOOST_REQUIRE( db.find(buy_order6_id) ); + BOOST_CHECK( buy_order6_id(db).seller == ted_id ); + // sell_order5 gets 3, market fee = round_down(3 * 30 / 10000) = 0, still gets 3 + // take profit order size = round_up(3 * 1 / 10000) = 1 + // Ted USD balance change = 3 - 1 = 2 + BOOST_CHECK_EQUAL( buy_order6_id(db).for_sale.value, 1 ); + // price = (1 / 1) / (1 + 655.35%) = 10000 / 75535 + // min to receive = round_up( 1 * 75535 / 10000 ) = 8 + // updated price = 1 / 8 + BOOST_CHECK( buy_order6_id(db).sell_price == asset(1,usd_id) / asset(8) ); + BOOST_CHECK( buy_order6_id(db).expiration == buy_order6_expiration ); + BOOST_CHECK( !buy_order6_id(db).take_profit_order_id ); + + BOOST_REQUIRE_EQUAL( buy_order6_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( buy_order6_id(db).on_fill.front().is_type() ); + const auto& action_b6 = buy_order6_id(db).on_fill.front().get(); + BOOST_CHECK( action_b6.fee_asset_id == tpa5.fee_asset_id ); + BOOST_CHECK( action_b6.spread_percent == tpa5.spread_percent ); + BOOST_CHECK( action_b6.size_percent == tpa5.size_percent ); + BOOST_CHECK( action_b6.expiration_seconds == tpa5.expiration_seconds ); + BOOST_CHECK( action_b6.repeat == tpa5.repeat ); + + check_balances(); + }; + + check_result_3(); + + generate_block(); + + check_result_3(); + + // Sam places an order to buy CORE with USD with on_fill + // fee_asset, spread, size, expiration, repeat + create_take_profit_order_action tpa6 { core_id, 10, 10000, uint32_t(-1), true }; + vector on_fill_6 { tpa6 }; + + const limit_order_object* buy_order7 = create_sell_order( sam_id, asset(338, usd_id), asset(100), + time_point_sec::maximum(), price::unit_price(), on_fill_6 ); + last_order_id = last_order_id + 1; + + BOOST_REQUIRE( buy_order7 ); + limit_order_id_type buy_order7_id = buy_order7->get_id(); + + BOOST_CHECK( buy_order7_id(db).seller == sam_id ); + BOOST_CHECK_EQUAL( buy_order7_id(db).for_sale.value, 338 ); + BOOST_CHECK( buy_order7_id(db).sell_price == asset(338,usd_id) / asset(100) ); + BOOST_CHECK( buy_order7_id(db).expiration == time_point_sec::maximum() ); + BOOST_CHECK( !buy_order7_id(db).take_profit_order_id ); + + BOOST_REQUIRE_EQUAL( buy_order7_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( buy_order7_id(db).on_fill.front().is_type() ); + const auto& action_b7 = buy_order7_id(db).on_fill.front().get(); + BOOST_CHECK( action_b7.fee_asset_id == tpa6.fee_asset_id ); + BOOST_CHECK( action_b7.spread_percent == tpa6.spread_percent ); + BOOST_CHECK( action_b7.size_percent == tpa6.size_percent ); + BOOST_CHECK( action_b7.expiration_seconds == tpa6.expiration_seconds ); + BOOST_CHECK( action_b7.repeat == tpa6.repeat ); + + expected_balance_sam_usd -= 338; + + check_balances(); + + // Make a whitelist, Sam is not in + { + BOOST_TEST_MESSAGE( "Setting up whitelisting" ); + asset_update_operation uop; + uop.asset_to_update = usd_id; + uop.issuer = usd_id(db).issuer; + uop.new_options = usd_id(db).options; + // The whitelist is managed by Ted + uop.new_options.whitelist_authorities.insert(ted_id); + trx.operations.clear(); + trx.operations.push_back(uop); + PUSH_TX( db, trx, ~0 ); + + // Upgrade Ted so that he can manage the whitelist + upgrade_to_lifetime_member( ted_id ); + + // Add Ted to the whitelist, but do not add others + account_whitelist_operation wop; + wop.authorizing_account = ted_id; + wop.account_to_list = ted_id; + wop.new_listing = account_whitelist_operation::white_listed; + trx.operations.clear(); + trx.operations.push_back(wop); + PUSH_TX( db, trx, ~0 ); + } + + // Ted sells CORE for USD, fully fills buy_order7, partially fills buy_order5 + const limit_order_object* sell_order7 = create_sell_order( ted_id, asset(200), asset(200, usd_id) ); + last_order_id = last_order_id + 1; + + // sell_order7 is fully filled + BOOST_CHECK( !sell_order7 ); + + expected_balance_sam_core += 200; // See calculation below + expected_balance_ted_core -= 200; // See calculation below + expected_balance_ted_usd += 671; // 336 + 335, See calculation below + + const auto check_result_4 = [&]() + { + // buy_order7 is fully filled + BOOST_CHECK( !db.find(buy_order7_id) ); + // buy_order7 gets 100, pays = round_down(100 * 3380 / 1000) = 338, + // updated gets = round_up( 338 * 1000 / 3380 ) = 100 + + // fails to create a take profit order due to whitelisting + BOOST_CHECK( !db.find(last_order_id+1) ); + + // Ted gets 338 USD, market fee = round_down(338 * 0.8%) = 2, + // updated gets = 338 - 2 = 336 + + // buy_order5 is partially filled + BOOST_REQUIRE( db.find(buy_order5_id) ); + BOOST_CHECK( buy_order5_id(db).seller == sam_id ); + // buy_order5 gets 100, pays round_down(100 * 5855 / 1735) = 337 + // updated gets = round_up(337 * 1735 / 5855) = 100 + BOOST_CHECK_EQUAL( buy_order5_id(db).for_sale.value, 5515 ); // 5852 - 337 + BOOST_CHECK( buy_order5_id(db).sell_price == asset(5855,usd_id) / asset(1735) ); // unchanged + BOOST_CHECK( buy_order5_id(db).expiration == buy_order5_expiration ); // unchanged + BOOST_CHECK( buy_order5_id(db).take_profit_order_id == sell_order3_id ); // unchanged + + // All unchanged + BOOST_REQUIRE_EQUAL( buy_order5_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( buy_order5_id(db).on_fill.front().is_type() ); + const auto& action_b5 = buy_order5_id(db).on_fill.front().get(); + BOOST_CHECK( action_b5.fee_asset_id == tpa3.fee_asset_id ); + BOOST_CHECK( action_b5.spread_percent == tpa3.spread_percent ); + BOOST_CHECK( action_b5.size_percent == tpa3.size_percent ); + BOOST_CHECK( action_b5.expiration_seconds == tpa3.expiration_seconds ); + BOOST_CHECK( action_b5.repeat == tpa3.repeat ); + + // Due to whitelisting, the take profit order linked to buy_order5 (sell_order3) is unchanged + BOOST_REQUIRE( db.find(sell_order3_id) ); + BOOST_CHECK( sell_order3_id(db).seller == sam_id ); + BOOST_CHECK_EQUAL( sell_order3_id(db).for_sale.value, 8269 ); // unchanged + BOOST_CHECK( sell_order3_id(db).sell_price == asset(10000) / asset(34000,usd_id) ); // unchanged + BOOST_CHECK( sell_order3_id(db).expiration == sell_order3_expiration_new ); + BOOST_CHECK( sell_order3_id(db).take_profit_order_id == buy_order5_id ); // unchanged + + // All unchanged + BOOST_REQUIRE_EQUAL( sell_order3_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order3_id(db).on_fill.front().is_type() ); + const auto& action_s3 = sell_order3_id(db).on_fill.front().get(); + BOOST_CHECK( action_s3.fee_asset_id == tpa3.fee_asset_id ); + BOOST_CHECK( action_s3.spread_percent == tpa3.spread_percent ); + BOOST_CHECK( action_s3.size_percent == tpa3.size_percent ); + BOOST_CHECK( action_s3.expiration_seconds == tpa3.expiration_seconds ); + BOOST_CHECK( action_s3.repeat == tpa3.repeat ); + + // Ted gets 337 USD, market fee = round_down(337 * 0.8%) = 2, + // updated gets = 337 - 2 = 335 + + check_balances(); + }; + + check_result_4(); + + generate_block(); + + check_result_4(); + + const asset_object& eur = create_user_issued_asset("MYEUR"); + asset_id_type eur_id = eur.get_id(); + + // Ted buys EUR with USD + const limit_order_object* buy_eur = create_sell_order( ted_id, asset(200, usd_id), asset(200, eur_id) ); + last_order_id = last_order_id + 1; + + limit_order_id_type buy_eur_id = buy_eur->get_id(); + + expected_balance_ted_usd -= 200; + + const auto check_result_5 = [&]() + { + // Check that the failed OSO operation does not increase the internal next value of limit_order_id + BOOST_CHECK( last_order_id == buy_eur_id ); + + check_balances(); + }; + + check_result_5(); + + generate_block(); + + check_result_5(); + + // Sam cancels an order + cancel_limit_order( sell_order3_id(db) ); + + expected_balance_sam_core += 8269; + + const auto check_result_6 = [&]() + { + // buy_order5 is canceled + BOOST_CHECK( !db.find(sell_order3_id) ); + + // The take profit order linked to sell_order3 (buy_order5) is updated + BOOST_REQUIRE( db.find(buy_order5_id) ); + BOOST_CHECK_EQUAL( buy_order5_id(db).for_sale.value, 5515 ); // unchanged + BOOST_CHECK( buy_order5_id(db).sell_price == asset(5855,usd_id) / asset(1735) ); // unchanged + BOOST_CHECK( buy_order5_id(db).expiration == buy_order5_expiration ); // unchanged + BOOST_CHECK( !buy_order5_id(db).take_profit_order_id ); // cleared + + // Others all unchanged + BOOST_REQUIRE_EQUAL( buy_order5_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( buy_order5_id(db).on_fill.front().is_type() ); + const auto& action_b5 = buy_order5_id(db).on_fill.front().get(); + BOOST_CHECK( action_b5.fee_asset_id == tpa3.fee_asset_id ); + BOOST_CHECK( action_b5.spread_percent == tpa3.spread_percent ); + BOOST_CHECK( action_b5.size_percent == tpa3.size_percent ); + BOOST_CHECK( action_b5.expiration_seconds == tpa3.expiration_seconds ); + BOOST_CHECK( action_b5.repeat == tpa3.repeat ); + + check_balances(); + }; + + check_result_6(); + + generate_block(); + + check_result_6(); + +} FC_LOG_AND_RETHROW() } + +/// Tests OSO-related order updates: basic operation validation and evaluation +BOOST_AUTO_TEST_CASE( oso_take_profit_order_update_basic_test ) +{ try { + + // Proceeds to the hard fork + generate_blocks( HARDFORK_CORE_2535_TIME ); + generate_block(); + set_expiration( db, trx ); + + ACTORS((sam)); + + const asset_object& usd = create_user_issued_asset( "MYUSD" ); + asset_id_type usd_id = usd.get_id(); + asset_id_type core_id; + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( sam, asset(init_amount) ); + + // Sam sells CORE for USD with on_fill + // fee_asset, spread, size, expiration, repeat + create_take_profit_order_action tpa1 { core_id, 100, 10000, 3600, false }; + vector on_fill_1 { tpa1 }; + + const limit_order_object* sell_order1 = create_sell_order( sam_id, asset(10000), asset(12345, usd_id), + time_point_sec::maximum(), price::unit_price(), on_fill_1 ); + BOOST_REQUIRE( sell_order1 ); + limit_order_id_type sell_order1_id = sell_order1->get_id(); + + // Sam tries to update a limit order + + // Spread percentage should be positive + // fee_asset, spread, size, expiration, repeat + tpa1 = { core_id, 0, 10000, 3600, false }; + on_fill_1 = { tpa1 }; + BOOST_CHECK_THROW( update_limit_order( sell_order1_id, {}, {}, {}, price::unit_price(), on_fill_1 ), + fc::exception ); + // Cannot propose either + limit_order_update_operation uop1 = make_limit_order_update_op( sam_id, sell_order1_id, {}, {}, {}, on_fill_1 ); + BOOST_CHECK_THROW( propose( uop1 ), fc::exception ); + + // Size percentage should be positive + // fee_asset, spread, size, expiration, repeat + tpa1 = { core_id, 1, 0, 3600, false }; + on_fill_1 = { tpa1 }; + BOOST_CHECK_THROW( update_limit_order( sell_order1_id, {}, {}, {}, price::unit_price(), on_fill_1 ), + fc::exception ); + // Cannot propose either + uop1 = make_limit_order_update_op( sam_id, sell_order1_id, {}, {}, {}, on_fill_1 ); + BOOST_CHECK_THROW( propose( uop1 ), fc::exception ); + + // Size percentage should not exceed 100% + // fee_asset, spread, size, expiration, repeat + tpa1 = { core_id, 1, 10001, 3600, false }; + on_fill_1 = { tpa1 }; + BOOST_CHECK_THROW( update_limit_order( sell_order1_id, {}, {}, {}, price::unit_price(), on_fill_1 ), + fc::exception ); + // Cannot propose either + uop1 = make_limit_order_update_op( sam_id, sell_order1_id, {}, {}, {}, on_fill_1 ); + BOOST_CHECK_THROW( propose( uop1 ), fc::exception ); + + // Expiration should be positive + // fee_asset, spread, size, expiration, repeat + tpa1 = { core_id, 1, 10000, 0, false }; + on_fill_1 = { tpa1 }; + BOOST_CHECK_THROW( update_limit_order( sell_order1_id, {}, {}, {}, price::unit_price(), on_fill_1 ), + fc::exception ); + // Cannot propose either + uop1 = make_limit_order_update_op( sam_id, sell_order1_id, {}, {}, {}, on_fill_1 ); + BOOST_CHECK_THROW( propose( uop1 ), fc::exception ); + + // Fee asset should exist + tpa1 = { usd_id + 1, 1, GRAPHENE_100_PERCENT, 3600, false }; + on_fill_1 = { tpa1 }; + BOOST_CHECK_THROW( update_limit_order( sell_order1_id, {}, {}, {}, price::unit_price(), on_fill_1 ), + fc::exception ); + // Can propose + uop1 = make_limit_order_update_op( sam_id, sell_order1_id, {}, {}, {}, on_fill_1 ); + propose( uop1 ); + + // on_fill must contain 0 or 1 action + tpa1 = { core_id, 1, GRAPHENE_100_PERCENT, 3600, false }; + on_fill_1 = { tpa1, tpa1 }; + BOOST_CHECK_THROW( update_limit_order( sell_order1_id, {}, {}, {}, price::unit_price(), on_fill_1 ), + fc::exception ); + // Can propose + uop1 = make_limit_order_update_op( sam_id, sell_order1_id, {}, {}, {}, on_fill_1 ); + propose( uop1 ); + + generate_block(); + +} FC_LOG_AND_RETHROW() } + +/// Tests OSO-related order updates, scenarios: +/// * update an order which is not linked to another order and has no on_fill +/// * add on_fill +/// * update an order which is not linked to another order and has on_fill +/// * update on_fill +/// * remove on_fill +BOOST_AUTO_TEST_CASE( oso_take_profit_order_update_test_1 ) +{ try { + + // Proceeds to the hard fork + generate_blocks( HARDFORK_CORE_2535_TIME ); + generate_block(); + set_expiration( db, trx ); + + ACTORS((sam)); + + const asset_object& usd = create_user_issued_asset( "MYUSD" ); + asset_id_type usd_id = usd.get_id(); + asset_id_type core_id; + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( sam, asset(init_amount) ); + + int64_t expected_balance_sam_core = init_amount; + int64_t expected_balance_sam_usd = 0; + + const auto& check_balances = [&]() { + BOOST_CHECK_EQUAL( db.get_balance( sam_id, core_id ).amount.value, expected_balance_sam_core ); + BOOST_CHECK_EQUAL( db.get_balance( sam_id, usd_id ).amount.value, expected_balance_sam_usd ); + }; + + // Sam sells CORE for USD without on_fill + const limit_order_object* sell_order1 = create_sell_order( sam_id, asset(10000), asset(12345, usd_id) ); + BOOST_REQUIRE( sell_order1 ); + limit_order_id_type sell_order1_id = sell_order1->get_id(); + + BOOST_CHECK( sell_order1_id(db).on_fill.empty() ); + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); + + expected_balance_sam_core -= 10000; + check_balances(); + + // Sam updates order with on_fill + // fee_asset, spread, size, expiration, repeat + create_take_profit_order_action tpa1 { core_id, 100, 10000, 3600, false }; + vector on_fill_1 { tpa1 }; + update_limit_order( sell_order1_id, {}, {}, {}, price::unit_price(), on_fill_1 ); + + const auto& check_result_1 = [&]() + { + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa1.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa1.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa1.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa1.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa1.repeat ); + + check_balances(); + }; + + check_result_1(); + + generate_block(); + + check_result_1(); + + // Sam updates order with new on_fill + // fee_asset, spread, size, expiration, repeat + create_take_profit_order_action tpa2 { usd_id, 10, 1000, 3800, true }; + vector on_fill_2 { tpa2 }; + update_limit_order( sell_order1_id, {}, {}, {}, price::unit_price(), on_fill_2 ); + + const auto& check_result_2 = [&]() + { + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa2.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa2.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa2.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa2.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa2.repeat ); + + check_balances(); + }; + + check_result_2(); + + generate_block(); + + check_result_2(); + + // Sam updates order without on_fill + update_limit_order( sell_order1_id, {}, asset(1) ); + expected_balance_sam_core -= 1; + + const auto& check_result_3 = [&]() + { + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa2.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa2.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa2.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa2.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa2.repeat ); + + check_balances(); + }; + + check_result_3(); + + generate_block(); + + check_result_3(); + + // Sam updates order with an empty on_fill + vector on_fill_3; + update_limit_order( sell_order1_id, {}, {}, {}, price::unit_price(), on_fill_3 ); + + const auto& check_result_4 = [&]() + { + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); + + BOOST_CHECK( sell_order1_id(db).on_fill.empty() ); + + check_balances(); + }; + + check_result_4(); + + generate_block(); + + check_result_4(); + +} FC_LOG_AND_RETHROW() } + +/// Tests OSO-related order updates, scenarios: +/// * update an order which is linked to another order but has no on_fill +/// * do not add on_fill, do not specify a new price +/// * do not add on_fill, specify a new price but no change +/// * do not add on_fill, update price +/// * add on_fill +/// * update an order which is linked to another order and has on_fill +/// * do not specify new on_fill, do not specify a new price +/// * do not specify new on_fill, specify a new price but no change +/// * do not specify new on_fill, update price +/// * remove on_fill +/// * update on_fill +/// * do not update spread_percent or repeat +/// * update spread_percent +/// * update repeat +BOOST_AUTO_TEST_CASE( oso_take_profit_order_update_test_2 ) +{ try { + + // Proceeds to the hard fork + generate_blocks( HARDFORK_CORE_2535_TIME ); + generate_block(); + set_expiration( db, trx ); + + ACTORS((sam)(ted)); + + additional_asset_options_t usd_options; + usd_options.value.taker_fee_percent = 80; // 0.8% taker fee + + const asset_object& usd = create_user_issued_asset( "MYUSD", ted, charge_market_fee | white_list, + price(asset(1, asset_id_type(1)), asset(1)), + 4, 30, usd_options ); // 0.3% maker fee + asset_id_type usd_id = usd.get_id(); + asset_id_type core_id; + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( sam, asset(init_amount) ); + fund( ted, asset(init_amount) ); + issue_uia( ted, asset(init_amount, usd_id) ); + + int64_t expected_balance_sam_core = init_amount; + int64_t expected_balance_ted_core = init_amount; + int64_t expected_balance_sam_usd = 0; + int64_t expected_balance_ted_usd = init_amount; + + const auto& check_balances = [&]() { + BOOST_CHECK_EQUAL( db.get_balance( sam_id, core_id ).amount.value, expected_balance_sam_core ); + BOOST_CHECK_EQUAL( db.get_balance( ted_id, core_id ).amount.value, expected_balance_ted_core ); + BOOST_CHECK_EQUAL( db.get_balance( sam_id, usd_id ).amount.value, expected_balance_sam_usd ); + BOOST_CHECK_EQUAL( db.get_balance( ted_id, usd_id ).amount.value, expected_balance_ted_usd ); + }; + + check_balances(); + + // Sam sells CORE for USD with on_fill + // fee_asset, spread, size, expiration, repeat + create_take_profit_order_action tpa1 { core_id, 100, 10000, 3600, false }; + vector on_fill_1 { tpa1 }; + + const limit_order_object* sell_order1 = create_sell_order( sam_id, asset(10000), asset(12345, usd_id), + time_point_sec::maximum(), price::unit_price(), on_fill_1 ); + BOOST_REQUIRE( sell_order1 ); + limit_order_id_type sell_order1_id = sell_order1->get_id(); + + limit_order_id_type last_order_id = sell_order1_id; + + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 10000 ); + BOOST_CHECK( sell_order1_id(db).sell_price == asset(10000) / asset(12345, usd_id) ); + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + { + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa1.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa1.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa1.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa1.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa1.repeat ); + } + + expected_balance_sam_core -= 10000; + check_balances(); + + // Ted buys CORE with USD without on_fill, partially fills Sam's order + const limit_order_object* buy_order1 = create_sell_order( ted_id, asset(1235, usd_id), asset(1000) ); + last_order_id = last_order_id + 1; + + // The buy order is smaller, it gets fully filled + BOOST_CHECK( !buy_order1 ); + expected_balance_ted_core += 1000; + expected_balance_ted_usd -= 1235; + + // The newly created take profit order is a buy order + last_order_id = last_order_id + 1; + limit_order_id_type buy_order2_id = last_order_id; + + auto buy_order2_expiration = db.head_block_time() + 3600; + + const auto& check_result_1 = [&]() + { + // The sell order is partially filled + BOOST_REQUIRE( db.find(sell_order1_id) ); + // The take profit order + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + // The sell order gets 1235, market fee = round_down(1235 * 30 / 10000) = 3 + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 1232 ); // 1235 - 3 + // price = (12345 / 10000) / 101% = 12345 / 10100 + // min to receive = round_up( 1232 * 10100 / 12345 ) = 1008 + // updated price = 1232 / 1008 + BOOST_CHECK( buy_order2_id(db).sell_price == asset(1232,usd_id) / asset(1008) ); + BOOST_CHECK( buy_order2_id(db).expiration == buy_order2_expiration ); + BOOST_CHECK( buy_order2_id(db).take_profit_order_id == sell_order1_id ); + BOOST_CHECK( buy_order2_id(db).on_fill.empty() ); + + // The sell order is partially filled, pays 1000 + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 9000 ); // 10000 - 1000 + BOOST_CHECK( sell_order1_id(db).sell_price == asset(10000) / asset(12345, usd_id) ); + BOOST_CHECK( sell_order1_id(db).take_profit_order_id == buy_order2_id ); + + check_balances(); + }; + + check_result_1(); + + generate_block(); + + check_result_1(); + + // Several passes to test different scenarios + auto bak_balance_sam_core = expected_balance_sam_core; + auto bak_balance_sam_usd = expected_balance_sam_usd; + for( size_t i = 0; i <= 10; ++i ) + { + // Sam updates order + create_take_profit_order_action tpa2 = tpa1; + if( 0 == i ) + { + // no on_fill, do not add on_fill, do not specify a new price + update_limit_order( buy_order2_id, {}, asset(-1, usd_id) ); + expected_balance_sam_usd += 1; + } + else if( 1 == i ) + { + // no on_fill, do not add on_fill, specify a new price but no change + update_limit_order( buy_order2_id, buy_order2_id(db).sell_price, {}, time_point_sec::maximum() ); + } + else if( 2 == i ) + { + // no on_fill, do not add on_fill, update price + auto new_price = buy_order2_id(db).sell_price; + new_price.quote.amount += 1; + update_limit_order( buy_order2_id, new_price ); + } + else if( 3 == i ) + { + // no on_fill, add on_fill + update_limit_order( buy_order2_id, {}, {}, {}, price::unit_price(), on_fill_1 ); + } + else if( 4 == i ) + { + // has on_fill, do not specify new on_fill, do not specify a new price + update_limit_order( sell_order1_id, {}, asset(1) ); + expected_balance_sam_core -= 1; + } + else if( 5 == i ) + { + // has on_fill, do not specify new on_fill, specify a new price but no change + update_limit_order( sell_order1_id, sell_order1_id(db).sell_price, asset(1) ); + expected_balance_sam_core -= 1; + } + else if( 6 == i ) + { + // has on_fill, do not specify new on_fill, update price + auto new_price = sell_order1_id(db).sell_price; + new_price.quote.amount += 1; + update_limit_order( sell_order1_id, new_price ); + } + else if( 7 == i ) + { + // has on_fill, specify an empty new on_fill (to remove it) + vector on_fill_2; + update_limit_order( sell_order1_id, {}, {}, {}, price::unit_price(), on_fill_2 ); + } + else if( 8 == i ) + { + // has on_fill, specify a new on_fill, but no update to spread_percent or repeat + // fee_asset, spread, size, expiration, repeat + tpa2 = { usd_id, 100, 9000, 7200, false }; + vector on_fill_2 { tpa2 }; + update_limit_order( sell_order1_id, {}, {}, {}, price::unit_price(), on_fill_2 ); + } + else if( 9 == i ) + { + // has on_fill, specify a new on_fill, update spread_percent + // fee_asset, spread, size, expiration, repeat + tpa2 = { core_id, 101, 10000, 3600, false }; + vector on_fill_2 { tpa2 }; + update_limit_order( sell_order1_id, {}, {}, {}, price::unit_price(), on_fill_2 ); + } + else if( 10 == i ) + { + // has on_fill, specify a new on_fill, update repeat + // fee_asset, spread, size, expiration, repeat + tpa2 = { core_id, 100, 10000, 3600, true }; + vector on_fill_2 { tpa2 }; + update_limit_order( sell_order1_id, {}, {}, {}, price::unit_price(), on_fill_2 ); + } + + const auto& check_result_2 = [&]() + { + if( 0 == i ) + { + // The sell order + BOOST_REQUIRE( db.find(sell_order1_id) ); + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 9000 ); + BOOST_CHECK( sell_order1_id(db).sell_price == asset(10000) / asset(12345, usd_id) ); + BOOST_CHECK( sell_order1_id(db).take_profit_order_id == buy_order2_id ); + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa1.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa1.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa1.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa1.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa1.repeat ); + + // The take profit order + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 1231 ); // updated: 1232 - 1 + BOOST_CHECK( buy_order2_id(db).sell_price == asset(1232,usd_id) / asset(1008) ); + BOOST_CHECK( buy_order2_id(db).expiration == buy_order2_expiration ); + BOOST_CHECK( buy_order2_id(db).take_profit_order_id == sell_order1_id ); + BOOST_CHECK( buy_order2_id(db).on_fill.empty() ); + } + else if( 1 == i ) + { + // The sell order + BOOST_REQUIRE( db.find(sell_order1_id) ); + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 9000 ); + BOOST_CHECK( sell_order1_id(db).sell_price == asset(10000) / asset(12345, usd_id) ); + BOOST_CHECK( sell_order1_id(db).take_profit_order_id == buy_order2_id ); + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa1.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa1.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa1.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa1.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa1.repeat ); + + // The take profit order + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 1232 ); + BOOST_CHECK( buy_order2_id(db).sell_price == asset(1232,usd_id) / asset(1008) ); + BOOST_CHECK( buy_order2_id(db).expiration == time_point_sec::maximum() ); // updated + BOOST_CHECK( buy_order2_id(db).take_profit_order_id == sell_order1_id ); + BOOST_CHECK( buy_order2_id(db).on_fill.empty() ); + } + else if( 2 == i ) + { + // The sell order + BOOST_REQUIRE( db.find(sell_order1_id) ); + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 9000 ); + BOOST_CHECK( sell_order1_id(db).sell_price == asset(10000) / asset(12345, usd_id) ); + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); // cleared + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa1.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa1.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa1.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa1.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa1.repeat ); + + // The take profit order + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 1232 ); + BOOST_CHECK( buy_order2_id(db).sell_price == asset(1232,usd_id) / asset(1009) ); // updated + BOOST_CHECK( buy_order2_id(db).expiration == buy_order2_expiration ); + BOOST_CHECK( !buy_order2_id(db).take_profit_order_id ); // cleared + BOOST_CHECK( buy_order2_id(db).on_fill.empty() ); + } + else if( 3 == i ) + { + // The sell order + BOOST_REQUIRE( db.find(sell_order1_id) ); + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 9000 ); + BOOST_CHECK( sell_order1_id(db).sell_price == asset(10000) / asset(12345, usd_id) ); + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); // cleared + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa1.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa1.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa1.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa1.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa1.repeat ); + + // The take profit order + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 1232 ); + BOOST_CHECK( buy_order2_id(db).sell_price == asset(1232,usd_id) / asset(1008) ); + BOOST_CHECK( buy_order2_id(db).expiration == buy_order2_expiration ); + BOOST_CHECK( !buy_order2_id(db).take_profit_order_id ); // cleared + + BOOST_REQUIRE_EQUAL( buy_order2_id(db).on_fill.size(), 1U ); // updated + BOOST_REQUIRE( buy_order2_id(db).on_fill.front().is_type() ); + const auto& action_b2 = buy_order2_id(db).on_fill.front().get(); + BOOST_CHECK( action_b2.fee_asset_id == tpa1.fee_asset_id ); + BOOST_CHECK( action_b2.spread_percent == tpa1.spread_percent ); + BOOST_CHECK( action_b2.size_percent == tpa1.size_percent ); + BOOST_CHECK( action_b2.expiration_seconds == tpa1.expiration_seconds ); + BOOST_CHECK( action_b2.repeat == tpa1.repeat ); + } + else if( 4 == i ) + { + // The sell order + BOOST_REQUIRE( db.find(sell_order1_id) ); + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 9001 ); // updated: 9000 + 1 + BOOST_CHECK( sell_order1_id(db).sell_price == asset(10000) / asset(12345, usd_id) ); + BOOST_CHECK( sell_order1_id(db).take_profit_order_id == buy_order2_id ); + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa1.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa1.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa1.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa1.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa1.repeat ); + + // The take profit order + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 1232 ); + BOOST_CHECK( buy_order2_id(db).sell_price == asset(1232,usd_id) / asset(1008) ); + BOOST_CHECK( buy_order2_id(db).expiration == buy_order2_expiration ); + BOOST_CHECK( buy_order2_id(db).take_profit_order_id == sell_order1_id ); + BOOST_CHECK( buy_order2_id(db).on_fill.empty() ); + } + else if( 5 == i ) + { + // The sell order + BOOST_REQUIRE( db.find(sell_order1_id) ); + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 9001 ); // updated: 9000 + 1 + BOOST_CHECK( sell_order1_id(db).sell_price == asset(10000) / asset(12345, usd_id) ); + BOOST_CHECK( sell_order1_id(db).take_profit_order_id == buy_order2_id ); + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa1.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa1.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa1.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa1.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa1.repeat ); + + // The take profit order + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 1232 ); + BOOST_CHECK( buy_order2_id(db).sell_price == asset(1232,usd_id) / asset(1008) ); + BOOST_CHECK( buy_order2_id(db).expiration == buy_order2_expiration ); + BOOST_CHECK( buy_order2_id(db).take_profit_order_id == sell_order1_id ); + BOOST_CHECK( buy_order2_id(db).on_fill.empty() ); + } + else if( 6 == i ) + { + // The sell order + BOOST_REQUIRE( db.find(sell_order1_id) ); + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 9000 ); + BOOST_CHECK( sell_order1_id(db).sell_price == asset(10000) / asset(12346, usd_id) ); // updated + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); // cleared + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa1.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa1.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa1.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa1.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa1.repeat ); + + // The take profit order + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 1232 ); + BOOST_CHECK( buy_order2_id(db).sell_price == asset(1232,usd_id) / asset(1008) ); + BOOST_CHECK( buy_order2_id(db).expiration == buy_order2_expiration ); + BOOST_CHECK( !buy_order2_id(db).take_profit_order_id ); // cleared + BOOST_CHECK( buy_order2_id(db).on_fill.empty() ); + } + else if( 7 == i ) + { + // The sell order + BOOST_REQUIRE( db.find(sell_order1_id) ); + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 9000 ); + BOOST_CHECK( sell_order1_id(db).sell_price == asset(10000) / asset(12345, usd_id) ); + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); // cleared + + BOOST_CHECK( sell_order1_id(db).on_fill.empty() ); // removed + + // The take profit order + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 1232 ); + BOOST_CHECK( buy_order2_id(db).sell_price == asset(1232,usd_id) / asset(1008) ); + BOOST_CHECK( buy_order2_id(db).expiration == buy_order2_expiration ); + BOOST_CHECK( !buy_order2_id(db).take_profit_order_id ); // cleared + BOOST_CHECK( buy_order2_id(db).on_fill.empty() ); + } + else if( 8 == i ) + { + // The sell order + BOOST_REQUIRE( db.find(sell_order1_id) ); + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 9000 ); + BOOST_CHECK( sell_order1_id(db).sell_price == asset(10000) / asset(12345, usd_id) ); + BOOST_CHECK( sell_order1_id(db).take_profit_order_id == buy_order2_id ); + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa2.fee_asset_id ); // updated + BOOST_CHECK( action_s1.spread_percent == tpa2.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa2.size_percent ); // updated + BOOST_CHECK( action_s1.expiration_seconds == tpa2.expiration_seconds ); // updated + BOOST_CHECK( action_s1.repeat == tpa2.repeat ); + + // The take profit order + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 1232 ); + BOOST_CHECK( buy_order2_id(db).sell_price == asset(1232,usd_id) / asset(1008) ); + BOOST_CHECK( buy_order2_id(db).expiration == buy_order2_expiration ); + BOOST_CHECK( buy_order2_id(db).take_profit_order_id == sell_order1_id ); + BOOST_CHECK( buy_order2_id(db).on_fill.empty() ); + } + else if( 9 == i ) + { + // The sell order + BOOST_REQUIRE( db.find(sell_order1_id) ); + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 9000 ); + BOOST_CHECK( sell_order1_id(db).sell_price == asset(10000) / asset(12345, usd_id) ); + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); // cleared + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa2.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa2.spread_percent ); // updated + BOOST_CHECK( action_s1.size_percent == tpa2.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa2.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa2.repeat ); + + // The take profit order + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 1232 ); + BOOST_CHECK( buy_order2_id(db).sell_price == asset(1232,usd_id) / asset(1008) ); + BOOST_CHECK( buy_order2_id(db).expiration == buy_order2_expiration ); + BOOST_CHECK( !buy_order2_id(db).take_profit_order_id ); // cleared + BOOST_CHECK( buy_order2_id(db).on_fill.empty() ); + } + else if( 10 == i ) + { + // The sell order + BOOST_REQUIRE( db.find(sell_order1_id) ); + BOOST_CHECK_EQUAL( sell_order1_id(db).for_sale.value, 9000 ); + BOOST_CHECK( sell_order1_id(db).sell_price == asset(10000) / asset(12345, usd_id) ); + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); // cleared + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa2.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa2.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa2.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa2.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa2.repeat ); // updated + + // The take profit order + BOOST_REQUIRE( db.find(buy_order2_id) ); + BOOST_CHECK( buy_order2_id(db).seller == sam_id ); + BOOST_CHECK_EQUAL( buy_order2_id(db).for_sale.value, 1232 ); + BOOST_CHECK( buy_order2_id(db).sell_price == asset(1232,usd_id) / asset(1008) ); + BOOST_CHECK( buy_order2_id(db).expiration == buy_order2_expiration ); + BOOST_CHECK( !buy_order2_id(db).take_profit_order_id ); // cleared + BOOST_CHECK( buy_order2_id(db).on_fill.empty() ); + } + + check_balances(); + + }; + + check_result_2(); + + generate_block(); + + check_result_2(); + + // reset + db.pop_block(); + expected_balance_sam_core = bak_balance_sam_core; + expected_balance_sam_usd = bak_balance_sam_usd; + } + +} FC_LOG_AND_RETHROW() } + +BOOST_AUTO_TEST_SUITE_END() From de8339d1aed6438207ebeebada91b49a67cfb6de Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 14 Jun 2023 06:34:27 +0000 Subject: [PATCH 115/127] Remove unused code --- libraries/chain/evaluator.cpp | 29 ++++++++----------- .../chain/transaction_evaluation_state.hpp | 1 - libraries/chain/market_evaluator.cpp | 4 +-- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/libraries/chain/evaluator.cpp b/libraries/chain/evaluator.cpp index 42b7f82c1d..818770e9ff 100644 --- a/libraries/chain/evaluator.cpp +++ b/libraries/chain/evaluator.cpp @@ -79,28 +79,23 @@ database& generic_evaluator::db()const { return trx_state->db(); } void generic_evaluator::convert_fee() { - if( !trx_state->skip_fee ) { - if( fee_asset->get_id() != asset_id_type() ) - { - db().modify(*fee_asset_dyn_data, [this](asset_dynamic_data_object& d) { - d.accumulated_fees += fee_from_account.amount; - d.fee_pool -= core_fee_paid; - }); - } + if( fee_asset->get_id() != asset_id_type() ) + { + db().modify(*fee_asset_dyn_data, [this](asset_dynamic_data_object& d) { + d.accumulated_fees += fee_from_account.amount; + d.fee_pool -= core_fee_paid; + }); } } void generic_evaluator::pay_fee() { try { - if( !trx_state->skip_fee ) { - database& d = db(); - /// TODO: db().pay_fee( account_id, core_fee ); - d.modify(*fee_paying_account_statistics, [&](account_statistics_object& s) - { - s.pay_fee( core_fee_paid, d.get_global_properties().parameters.cashback_vesting_threshold ); - }); - } - } FC_CAPTURE_AND_RETHROW() } + database& d = db(); + d.modify(*fee_paying_account_statistics, [this,&d](account_statistics_object& s) + { + s.pay_fee( core_fee_paid, d.get_global_properties().parameters.cashback_vesting_threshold ); + }); + } FC_CAPTURE_AND_RETHROW() } // GCOVR_EXCL_LINE void generic_evaluator::pay_fba_fee( uint64_t fba_id ) { diff --git a/libraries/chain/include/graphene/chain/transaction_evaluation_state.hpp b/libraries/chain/include/graphene/chain/transaction_evaluation_state.hpp index 953b05ed69..c00e977983 100644 --- a/libraries/chain/include/graphene/chain/transaction_evaluation_state.hpp +++ b/libraries/chain/include/graphene/chain/transaction_evaluation_state.hpp @@ -47,7 +47,6 @@ namespace chain { const signed_transaction* _trx = nullptr; database* _db = nullptr; bool _is_proposed_trx = false; - bool skip_fee = false; // Note: seems unused. TODO recheck & maybe remove bool skip_fee_schedule_check = false; bool skip_limit_order_price_check = false; // Used in limit_order_update_op }; diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index a09fdaf1e6..ec9e5130b6 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -91,7 +91,7 @@ void limit_order_create_evaluator::convert_fee() { if( db().head_block_time() <= HARDFORK_CORE_604_TIME ) generic_evaluator::convert_fee(); - else if( !trx_state->skip_fee && fee_asset->get_id() != asset_id_type() ) + else if( fee_asset->get_id() != asset_id_type() ) { db().modify(*fee_asset_dyn_data, [this](asset_dynamic_data_object& d) { d.fee_pool -= core_fee_paid; @@ -149,7 +149,7 @@ object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_o void limit_order_update_evaluator::convert_fee() { - if( !trx_state->skip_fee && fee_asset->get_id() != asset_id_type() ) + if( fee_asset->get_id() != asset_id_type() ) { db().modify(*fee_asset_dyn_data, [this](asset_dynamic_data_object& addo) { addo.fee_pool -= core_fee_paid; From 1afd436cf53b5bcad5e2f6916a7f6d53e1eafb09 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 17 Jun 2023 00:18:50 +0000 Subject: [PATCH 116/127] Adapt on_fill field (for limit orders) for ES --- libraries/utilities/elasticsearch.cpp | 43 +++++++++++++++++---------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/libraries/utilities/elasticsearch.cpp b/libraries/utilities/elasticsearch.cpp index 9e8faf88c1..87aa7c6c8f 100644 --- a/libraries/utilities/elasticsearch.cpp +++ b/libraries/utilities/elasticsearch.cpp @@ -272,28 +272,41 @@ fc::variant es_data_adaptor::adapt( const fc::variant_object& op, uint16_t max_d fc::mutable_variant_object o(op); - // Note: these fields are maps, but were stored in ES as flattened arrays - static const std::unordered_set flattened_fields = { "account_auths", "address_auths", "key_auths" }; + // Note: + // These fields are maps, they are stored redundantly in ES, + // one instance is a nested string array using the original field names (for backward compatibility, although + // ES queries return results in JSON format a little differently than node APIs), + // and a new instance is an object array with "_object" suffix added to the field name. + static const std::unordered_set to_string_array_fields = { "account_auths", "address_auths", + "key_auths" }; // Note: - // object arrays listed in this map are stored redundantly in ES, with one instance as a nested object and - // the other as a string for backward compatibility, - // object arrays not listed in this map are stored as nested objects only. + // These fields are stored redundantly in ES, + // one instance is a string using the original field names (originally for backward compatibility, + // but new fields are added here as well), + // and a new instance is a nested object or nested object array with "_object" suffix added to the field name. + // + // Why do we add new fields here? + // Because we want to keep the JSON format made by node (stored in ES as a string), and store the object format + // at the same time for more flexible query. + // + // Object arrays not listed in this map (if any) are stored as nested objects only. static const std::unordered_map to_string_fields = { { "parameters", data_type::array_type }, // in committee proposals, current_fees.parameters { "op", data_type::static_variant_type }, // proposal_create_op.proposed_ops[*].op - { "proposed_ops", data_type::array_type }, + { "proposed_ops", data_type::array_type }, // proposal_create_op.proposed_ops { "operations", data_type::array_type }, // proposal_object.operations - { "initializer", data_type::static_variant_type }, - { "policy", data_type::static_variant_type }, - { "predicates", data_type::array_type }, - { "active_special_authority", data_type::static_variant_type }, - { "owner_special_authority", data_type::static_variant_type }, - { "htlc_preimage_hash", data_type::static_variant_type }, + { "initializer", data_type::static_variant_type }, // for workers + { "policy", data_type::static_variant_type }, // for vesting balances + { "predicates", data_type::array_type }, // for assert_operation + { "active_special_authority", data_type::static_variant_type }, // for accounts + { "owner_special_authority", data_type::static_variant_type }, // for accounts + { "htlc_preimage_hash", data_type::static_variant_type }, // for HTLCs { "argument", data_type::static_variant_type }, // for custom authority, restriction.argument { "feeds", data_type::map_type }, // asset_bitasset_data_object.feeds - { "acceptable_collateral", data_type::map_type }, - { "acceptable_borrowers", data_type::map_type } + { "acceptable_collateral", data_type::map_type }, // for credit offers + { "acceptable_borrowers", data_type::map_type }, // for credit offers + { "on_fill", data_type::array_type } // for limit orders }; std::vector> original_arrays; std::vector keys_to_rename; @@ -321,7 +334,7 @@ fc::variant es_data_adaptor::adapt( const fc::variant_object& op, uint16_t max_d original_arrays.emplace_back( name, array ); element = fc::json::to_string(element); } - else if( flattened_fields.find(name) != flattened_fields.end() ) + else if( to_string_array_fields.find(name) != to_string_array_fields.end() ) { // make a backup (only if depth is sufficient) and adapt the original if( max_depth > 1 ) From ad0a5b5175fd8e0d51dbd06509fafabfbc673d4b Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 17 Jun 2023 12:01:42 +0000 Subject: [PATCH 117/127] Catch more exceptions when processing on_fill --- libraries/chain/db_market.cpp | 71 ++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index 1306a67c57..930de41a9e 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -1678,43 +1678,44 @@ optional database::process_limit_order_on_fill( const limit if( order.take_profit_order_id.valid() ) // Update existing take profit order { limit_order_update_operation op; - if( take_profit_action.fee_asset_id == asset_id_type() ) - op.fee = current_fee_schedule().calculate_fee( op ); - else - op.fee = current_fee_schedule().calculate_fee( op, - take_profit_action.fee_asset_id(*this).options.core_exchange_rate ); op.seller = order.seller; op.order = *order.take_profit_order_id; op.delta_amount_to_sell = for_sale; - if( *order.take_profit_order_id > order.get_id() ) // The linked take profit order was generated by this order - { - // Update order price - const auto& take_profit_order = (*order.take_profit_order_id)(*this); - for_sale.amount += take_profit_order.for_sale; - auto sell_price = (~order.sell_price) * ratio_type( GRAPHENE_100_PERCENT, - int32_t(GRAPHENE_100_PERCENT) + take_profit_action.spread_percent ); - auto new_min_to_receive = for_sale.multiply_and_round_up( sell_price ); - op.new_price = for_sale / new_min_to_receive; - } - // else do not update order price - if( ( time_point_sec::maximum() - take_profit_action.expiration_seconds ) > head_block_time() ) op.new_expiration = head_block_time() + take_profit_action.expiration_seconds; else op.new_expiration = time_point_sec::maximum(); - transaction_evaluation_state eval_state(this); - eval_state.skip_limit_order_price_check = true; - try { + if( take_profit_action.fee_asset_id == asset_id_type() ) + op.fee = current_fee_schedule().calculate_fee( op ); + else + op.fee = current_fee_schedule().calculate_fee( op, + take_profit_action.fee_asset_id(*this).options.core_exchange_rate ); // This may throw + + if( *order.take_profit_order_id > order.get_id() ) //The linked take profit order was generated by this order + { + // Update order price + const auto& take_profit_order = (*order.take_profit_order_id)(*this); + for_sale.amount += take_profit_order.for_sale; + auto sell_price = (~order.sell_price) * ratio_type( GRAPHENE_100_PERCENT, + int32_t(GRAPHENE_100_PERCENT) + take_profit_action.spread_percent ); + auto new_min_to_receive = for_sale.multiply_and_round_up( sell_price ); // This may throw + op.new_price = for_sale / new_min_to_receive; + } + // else do not update order price + // GCOVR_EXCL_START // Defensive code, should not fail FC_ASSERT( !op.new_price || ( ~(*op.new_price) > order.sell_price ), "Internal error: the take profit order should not match the current order" ); // GCOVR_EXCL_STOP + transaction_evaluation_state eval_state(this); + eval_state.skip_limit_order_price_check = true; + try_push_virtual_operation( eval_state, op ); } catch( const fc::exception& e ) @@ -1722,8 +1723,8 @@ optional database::process_limit_order_on_fill( const limit // We can in fact get here // e.g. if the selling or receiving asset issuer blacklisted the account, // or no sufficient balance to pay fees, or undo sessions nested too deeply - wlog( "Automatic action ${op} for filling limit order ${order} failed at block ${n}; " - "exception was ${e}", + wlog( "At block ${n}, failed to process on_fill for limit order ${order}, " + "automatic action (maybe incomplete) was ${op}, exception was ${e}", ("op", operation(op))("order", order) ("n", head_block_num())("e", e.to_detail_string()) ); } @@ -1731,16 +1732,8 @@ optional database::process_limit_order_on_fill( const limit else // Create a new take profit order { limit_order_create_operation op; - if( take_profit_action.fee_asset_id == asset_id_type() ) - op.fee = current_fee_schedule().calculate_fee( op ); - else - op.fee = current_fee_schedule().calculate_fee( op, - take_profit_action.fee_asset_id(*this).options.core_exchange_rate ); op.seller = order.seller; op.amount_to_sell = for_sale; - auto sell_price = (~order.sell_price) * ratio_type( GRAPHENE_100_PERCENT, - int32_t(GRAPHENE_100_PERCENT) + take_profit_action.spread_percent ); - op.min_to_receive = for_sale.multiply_and_round_up( sell_price ); if( ( time_point_sec::maximum() - take_profit_action.expiration_seconds ) > head_block_time() ) op.expiration = head_block_time() + take_profit_action.expiration_seconds; else @@ -1748,16 +1741,26 @@ optional database::process_limit_order_on_fill( const limit if( take_profit_action.repeat ) op.extensions.value.on_fill = order.on_fill; - transaction_evaluation_state eval_state(this); - try { + if( take_profit_action.fee_asset_id == asset_id_type() ) + op.fee = current_fee_schedule().calculate_fee( op ); + else + op.fee = current_fee_schedule().calculate_fee( op, + take_profit_action.fee_asset_id(*this).options.core_exchange_rate ); // This may throw + + auto sell_price = (~order.sell_price) * ratio_type( GRAPHENE_100_PERCENT, + int32_t(GRAPHENE_100_PERCENT) + take_profit_action.spread_percent ); + op.min_to_receive = for_sale.multiply_and_round_up( sell_price ); // This may throw + // GCOVR_EXCL_START // Defensive code, should not fail FC_ASSERT( ~op.get_price() > order.sell_price, "Internal error: the take profit order should not match the current order" ); // GCOVR_EXCL_STOP + transaction_evaluation_state eval_state(this); + auto op_result = try_push_virtual_operation( eval_state, op ); result = limit_order_id_type( op_result.get() ); } @@ -1766,8 +1769,8 @@ optional database::process_limit_order_on_fill( const limit // We can in fact get here // e.g. if the selling or receiving asset issuer blacklisted the account, // or no sufficient balance to pay fees, or undo sessions nested too deeply - wlog( "Automatic action ${op} for filling limit order ${order} failed at block ${n}; " - "exception was ${e}", + wlog( "At block ${n}, failed to process on_fill for limit order ${order}, " + "automatic action (maybe incomplete) was ${op}, exception was ${e}", ("op", operation(op))("order", order) ("n", head_block_num())("e", e.to_detail_string()) ); } From ec47739f2560422510c5475595cda11c3fa1fa42 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 17 Jun 2023 12:02:10 +0000 Subject: [PATCH 118/127] Add tests for failure to send take profit order --- tests/tests/oso_take_profit_order_tests.cpp | 117 ++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/tests/tests/oso_take_profit_order_tests.cpp b/tests/tests/oso_take_profit_order_tests.cpp index 67d435c58f..b8e4877413 100644 --- a/tests/tests/oso_take_profit_order_tests.cpp +++ b/tests/tests/oso_take_profit_order_tests.cpp @@ -817,6 +817,123 @@ BOOST_AUTO_TEST_CASE( oso_take_profit_order_trigger_and_cancel_test ) } FC_LOG_AND_RETHROW() } +/// Tests a scenario where a take profit order fails to be sent due to extreme order price +BOOST_AUTO_TEST_CASE( oso_take_profit_order_fail_test_1 ) +{ try { + + // Proceeds to the hard fork + generate_blocks( HARDFORK_CORE_2535_TIME ); + generate_block(); + set_expiration( db, trx ); + + ACTORS((sam)(ted)); + + const asset_object& usd = create_user_issued_asset( "MYUSD" ); + asset_id_type usd_id = usd.get_id(); + asset_id_type core_id; + + auto init_amount = 10000000 * GRAPHENE_BLOCKCHAIN_PRECISION; + fund( sam, asset(init_amount) ); + fund( ted, asset(init_amount) ); + + issue_uia( ted, asset(GRAPHENE_MAX_SHARE_SUPPLY, usd_id) ); + + int64_t expected_balance_sam_core = init_amount; + int64_t expected_balance_ted_core = init_amount; + int64_t expected_balance_sam_usd = 0; + int64_t expected_balance_ted_usd = GRAPHENE_MAX_SHARE_SUPPLY; + + const auto& check_balances = [&]() { + BOOST_CHECK_EQUAL( db.get_balance( sam_id, core_id ).amount.value, expected_balance_sam_core ); + BOOST_CHECK_EQUAL( db.get_balance( ted_id, core_id ).amount.value, expected_balance_ted_core ); + BOOST_CHECK_EQUAL( db.get_balance( sam_id, usd_id ).amount.value, expected_balance_sam_usd ); + BOOST_CHECK_EQUAL( db.get_balance( ted_id, usd_id ).amount.value, expected_balance_ted_usd ); + }; + + check_balances(); + + // Ted buys CORE with USD with on_fill + // fee_asset, spread, size, expiration, repeat + create_take_profit_order_action tpa1 { core_id, 500, 10000, 3600, false }; + vector on_fill_1 { tpa1 }; + + const limit_order_object* sell_order1 = create_sell_order( ted_id, asset(GRAPHENE_MAX_SHARE_SUPPLY, usd_id), + asset(100), time_point_sec::maximum(), + price::unit_price(), on_fill_1 ); + BOOST_REQUIRE( sell_order1 ); + limit_order_id_type sell_order1_id = sell_order1->get_id(); + + limit_order_id_type last_order_id = sell_order1_id; + + BOOST_CHECK( !sell_order1_id(db).take_profit_order_id ); + + BOOST_REQUIRE_EQUAL( sell_order1_id(db).on_fill.size(), 1U ); + BOOST_REQUIRE( sell_order1_id(db).on_fill.front().is_type() ); + const auto& action_s1 = sell_order1_id(db).on_fill.front().get(); + BOOST_CHECK( action_s1.fee_asset_id == tpa1.fee_asset_id ); + BOOST_CHECK( action_s1.spread_percent == tpa1.spread_percent ); + BOOST_CHECK( action_s1.size_percent == tpa1.size_percent ); + BOOST_CHECK( action_s1.expiration_seconds == tpa1.expiration_seconds ); + BOOST_CHECK( action_s1.repeat == tpa1.repeat ); + + expected_balance_ted_usd -= GRAPHENE_MAX_SHARE_SUPPLY; + check_balances(); + + // Sam sells CORE for USD without on_fill, fully fills Ted's order + const limit_order_object* buy_order1 = create_sell_order( sam_id, asset(100), + asset(GRAPHENE_MAX_SHARE_SUPPLY, usd_id) ); + last_order_id = last_order_id + 1; + + // The buy order gets fully filled + BOOST_CHECK( !buy_order1 ); + + expected_balance_sam_core -= 100; + expected_balance_sam_usd += GRAPHENE_MAX_SHARE_SUPPLY; + + expected_balance_ted_core += 100; + + const auto& check_result_1 = [&]() + { + // The sell order is fully filled + BOOST_CHECK( !db.find(sell_order1_id) ); + + // The take profit order is not created due to an exception + BOOST_CHECK( !db.find(last_order_id+1) ); + + check_balances(); + }; + + check_result_1(); + + generate_block(); + + check_result_1(); + + // Sam sells more CORE for USD without on_fill + const limit_order_object* sell_order2 = create_sell_order( sam_id, asset(10000), asset(13000, usd_id) ); + last_order_id = last_order_id + 1; + + BOOST_REQUIRE( sell_order2 ); + limit_order_id_type sell_order2_id = sell_order2->get_id(); + + expected_balance_sam_core -= 10000; + + const auto check_result_2 = [&]() + { + // Check that the failed OSO operation does not increase the internal next value of limit_order_id + BOOST_CHECK( last_order_id == sell_order2_id ); + + check_balances(); + }; + + check_result_2(); + + generate_block(); + + check_result_2(); + +} FC_LOG_AND_RETHROW() } + /// Tests OSO-related order updates: basic operation validation and evaluation BOOST_AUTO_TEST_CASE( oso_take_profit_order_update_basic_test ) { try { From ed08a9b7d270d47d9c1582de565f43a78486c51f Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 16 Sep 2022 18:58:49 +0000 Subject: [PATCH 119/127] Improve performance of account history wallet APIs By using the block_time field in operation_history_object. --- libraries/wallet/wallet_results.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libraries/wallet/wallet_results.cpp b/libraries/wallet/wallet_results.cpp index a47e28476f..02329f03b8 100644 --- a/libraries/wallet/wallet_results.cpp +++ b/libraries/wallet/wallet_results.cpp @@ -50,10 +50,8 @@ namespace graphene { namespace wallet { namespace detail { for( operation_detail& d : r ) { operation_history_object& i = d.op; - auto b = _remote_db->get_block_header(i.block_num); - FC_ASSERT(b); ss << i.block_num << " "; - ss << b->timestamp.to_iso_string() << " "; + ss << i.block_time.to_iso_string() << " "; ss << string(i.id) << " "; i.op.visit(operation_printer(ss, *this, i)); ss << " \n"; @@ -72,10 +70,8 @@ namespace graphene { namespace wallet { namespace detail { ss << "result_count : " << r.result_count << " \n"; for (operation_detail_ex& d : r.details) { operation_history_object& i = d.op; - auto b = _remote_db->get_block_header(i.block_num); - FC_ASSERT(b); ss << i.block_num << " "; - ss << b->timestamp.to_iso_string() << " "; + ss << i.block_time.to_iso_string() << " "; ss << string(i.id) << " "; i.op.visit(operation_printer(ss, *this, i)); ss << " transaction_id : "; From 481b67e0289153858ea85a01a6279c0d9bda1bfa Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 21 Jun 2023 17:45:53 +0000 Subject: [PATCH 120/127] Use ES version 8.8.1 and 7.17.10 in Github Actions --- .github/workflows/build-and-test.ubuntu-debug.yml | 4 ++-- .github/workflows/build-and-test.ubuntu-release.yml | 4 ++-- .github/workflows/sonar-scan.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-and-test.ubuntu-debug.yml b/.github/workflows/build-and-test.ubuntu-debug.yml index 35a506108c..5e44e8ee8c 100644 --- a/.github/workflows/build-and-test.ubuntu-debug.yml +++ b/.github/workflows/build-and-test.ubuntu-debug.yml @@ -12,7 +12,7 @@ jobs: runs-on: ${{ matrix.os }} services: elasticsearch8: - image: elastic/elasticsearch:8.6.1 + image: elastic/elasticsearch:8.8.1 options: >- --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node @@ -22,7 +22,7 @@ jobs: --env cluster.routing.allocation.disk.threshold_enabled=false --publish 9200:9200 elasticsearch7: - image: elastic/elasticsearch:7.17.9 + image: elastic/elasticsearch:7.17.10 options: >- --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node diff --git a/.github/workflows/build-and-test.ubuntu-release.yml b/.github/workflows/build-and-test.ubuntu-release.yml index d85aed7b6b..5fff3893d9 100644 --- a/.github/workflows/build-and-test.ubuntu-release.yml +++ b/.github/workflows/build-and-test.ubuntu-release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ${{ matrix.os }} services: elasticsearch8: - image: elastic/elasticsearch:8.6.1 + image: elastic/elasticsearch:8.8.1 options: >- --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node @@ -22,7 +22,7 @@ jobs: --env cluster.routing.allocation.disk.threshold_enabled=false --publish 9200:9200 elasticsearch7: - image: elastic/elasticsearch:7.17.9 + image: elastic/elasticsearch:7.17.10 options: >- --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node diff --git a/.github/workflows/sonar-scan.yml b/.github/workflows/sonar-scan.yml index bb591b1df4..820de552d1 100644 --- a/.github/workflows/sonar-scan.yml +++ b/.github/workflows/sonar-scan.yml @@ -12,7 +12,7 @@ jobs: runs-on: ${{ matrix.os }} services: elasticsearch8: - image: elastic/elasticsearch:8.6.1 + image: elastic/elasticsearch:8.8.1 options: >- --env ES_JAVA_OPTS="-Xms512m -Xmx512m" --env discovery.type=single-node From a0e1b28d7b038e2dc11a14825921a3de72e219e0 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 21 Jun 2023 18:00:57 +0000 Subject: [PATCH 121/127] Update CURL version used in CI to 8.1.2 --- .github/workflows/build-and-test.win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-and-test.win.yml b/.github/workflows/build-and-test.win.yml index 2419ff10c3..bc17ecff43 100644 --- a/.github/workflows/build-and-test.win.yml +++ b/.github/workflows/build-and-test.win.yml @@ -6,7 +6,7 @@ env: # The following are for windows cross-build only: BOOST_VERSION: 1_69_0 BOOST_DOTTED_VERSION: 1.69.0 - CURL_VERSION: 7.86.0 + CURL_VERSION: 8.1.2 OPENSSL_VERSION: 1.1.1s ZLIB_VERSION: 1.2.13 jobs: From e4ef0a4508f0fc44ef303ddcc1278f36e99c47d5 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 21 Jun 2023 18:01:44 +0000 Subject: [PATCH 122/127] Update OpenSSL version used in CI to 1.1.1u --- .github/workflows/build-and-test.win.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-and-test.win.yml b/.github/workflows/build-and-test.win.yml index bc17ecff43..417c8f9556 100644 --- a/.github/workflows/build-and-test.win.yml +++ b/.github/workflows/build-and-test.win.yml @@ -7,7 +7,7 @@ env: BOOST_VERSION: 1_69_0 BOOST_DOTTED_VERSION: 1.69.0 CURL_VERSION: 8.1.2 - OPENSSL_VERSION: 1.1.1s + OPENSSL_VERSION: 1.1.1u ZLIB_VERSION: 1.2.13 jobs: prepare-mingw64-libs: From b99d62f8af3b4eeb2abd35966bbbe622e2fdf3cc Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 24 Jun 2023 17:07:36 +0000 Subject: [PATCH 123/127] Fix a comment in a test case --- tests/tests/liquidity_pool_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests/liquidity_pool_tests.cpp b/tests/tests/liquidity_pool_tests.cpp index 2f40bf744c..7f437d7970 100644 --- a/tests/tests/liquidity_pool_tests.cpp +++ b/tests/tests/liquidity_pool_tests.cpp @@ -232,7 +232,7 @@ BOOST_AUTO_TEST_CASE( liquidity_pool_update_test ) BOOST_CHECK( lpo1.withdrawal_fee_percent == 0 ); BOOST_CHECK( lpo1.virtual_value == 200 ); - // Sam is able to update lpo2 if to update its withdrawal fee to 0 + // Ted is able to update lpo2 if to update its withdrawal fee to 0 update_liquidity_pool( ted_id, lpo2.get_id(), 2, 0 ); BOOST_CHECK( lpo2.asset_a == core.id ); From 16c77988b91b54962a59b2ca6b3d4c231e994d0c Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 24 Jun 2023 17:22:26 +0000 Subject: [PATCH 124/127] Fix a test case --- tests/tests/credit_offer_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/tests/credit_offer_tests.cpp b/tests/tests/credit_offer_tests.cpp index 474b3e3139..8c485961ed 100644 --- a/tests/tests/credit_offer_tests.cpp +++ b/tests/tests/credit_offer_tests.cpp @@ -179,9 +179,9 @@ BOOST_AUTO_TEST_CASE( credit_deal_auto_repay_hardfork_time_test ) // Before the hard fork, unable to update a credit deal // or update with proposals - BOOST_CHECK_THROW( update_credit_deal( sam_id, cd11_id, 1 ), fc::exception ); + BOOST_CHECK_THROW( update_credit_deal( ray_id, cd11_id, 1 ), fc::exception ); - credit_deal_update_operation updop = make_credit_deal_update_op( sam_id, cd11_id, 1 ); + credit_deal_update_operation updop = make_credit_deal_update_op( ray_id, cd11_id, 1 ); BOOST_CHECK_THROW( propose( updop ), fc::exception ); } FC_LOG_AND_RETHROW() } From 21051651262e68aca7415950cb2062b96cda0067 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 1 Jul 2023 10:10:32 +0000 Subject: [PATCH 125/127] Fix a comment in a test case --- tests/tests/fee_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests/fee_tests.cpp b/tests/tests/fee_tests.cpp index 29a7ceff97..2d28d8aa7d 100644 --- a/tests/tests/fee_tests.cpp +++ b/tests/tests/fee_tests.cpp @@ -4259,7 +4259,7 @@ BOOST_AUTO_TEST_CASE( fee_change_test ) cop.proposed_ops.emplace_back( cmuop ); trx.operations.push_back( cop ); - // It should fail + // It should succeed processed_transaction ptx = PUSH_TX(db, trx, ~0); trx.clear(); proposal_id_type prop_id { ptx.operation_results[0].get() }; From 29553e3202d60f34b06ee94dfb70de3acae2b2c8 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 1 Jul 2023 10:55:12 +0000 Subject: [PATCH 126/127] Fix a test case about updating limit orders --- tests/tests/operation_tests.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index be81f64df4..7b27fe0aa6 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -419,21 +419,30 @@ BOOST_AUTO_TEST_CASE(limit_order_update_dust_test) generate_blocks(HARDFORK_CORE_1604_TIME + 10); set_expiration( db, trx ); - ACTORS((nathan)); + ACTORS((nathan)(dan)); const auto& munee = create_user_issued_asset("MUNEE"); transfer(committee_account, nathan_id, asset(10000)); - issue_uia(nathan, munee.amount(1000)); + issue_uia(dan, munee.amount(1000)); auto expiration = db.head_block_time() + 1000; limit_order_id_type order_id = create_sell_order(nathan, asset(1000), munee.amount(100), expiration)->get_id(); - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, {}, asset(-995)), fc::exception); - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(1000000), munee.amount(100))), - fc::exception); - GRAPHENE_REQUIRE_THROW(update_limit_order(order_id, price(asset(2000), munee.amount(100)), asset(-985)), - fc::exception); + REQUIRE_EXCEPTION_WITH_TEXT( update_limit_order(order_id, {}, asset(-995)), "order becomes too small" ); + + // Partially fill the first order so that we can test price changes + const limit_order_object* order2 = create_sell_order( dan, munee.amount(99), asset(990) ); + BOOST_CHECK( !order2 ); + + auto sell_price = asset(1000) / munee.amount(100); + BOOST_CHECK_EQUAL( fc::json::to_string(order_id(db).sell_price), fc::json::to_string(sell_price) ); + BOOST_CHECK_EQUAL( order_id(db).for_sale.value, 10 ); + + REQUIRE_EXCEPTION_WITH_TEXT( update_limit_order(order_id, price(asset(1000), munee.amount(99))), + "order becomes too small" ); + REQUIRE_EXCEPTION_WITH_TEXT( update_limit_order(order_id, price(asset(990), munee.amount(150)), asset(-5)), + "order becomes too small" ); generate_block(); From c7c5ac5bda529cc9c3d6383735f9d1f06c4a9199 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 21 Jun 2023 17:22:47 +0000 Subject: [PATCH 127/127] Update sonar.branch.target for release branch --- sonar-project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonar-project.properties b/sonar-project.properties index 1c160ab32a..77e8a510b6 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -29,4 +29,4 @@ sonar.coverageReportPaths=coverage.xml # Decide which tree the current build belongs to in SonarCloud. # Managed by the `set_sonar_branch*` script(s) when building with CI. -sonar.branch.target=hardfork +sonar.branch.target=master