Defer something-for-nothing culling for taker orders until the order is unmatched #555

This commit is contained in:
theoreticalbts 2016-02-05 17:29:13 -05:00
parent b67d223d17
commit ad339d2729
3 changed files with 43 additions and 17 deletions

View file

@ -132,6 +132,27 @@ void database::cancel_order( const limit_order_object& order, bool create_virtua
remove(order);
}
bool maybe_cull_small_order( database& db, const limit_order_object& order )
{
/**
* There are times when the AMOUNT_FOR_SALE * SALE_PRICE == 0 which means that we
* have hit the limit where the seller is asking for nothing in return. When this
* happens we must refund any balance back to the seller, it is too small to be
* sold at the sale price.
*
* If the order is a taker order (as opposed to a maker order), so the price is
* set by the counterparty, this check is deferred until the order becomes unmatched
* (see #555) -- however, detecting this condition is the responsibility of the caller.
*/
if( order.amount_to_receive().amount == 0 )
{
ilog( "applied epsilon logic" );
db.cancel_order(order);
return true;
}
return false;
}
bool database::apply_order(const limit_order_object& new_order_object, bool allow_black_swan)
{
auto order_id = new_order_object.id;
@ -171,7 +192,15 @@ bool database::apply_order(const limit_order_object& new_order_object, bool allo
check_call_orders(sell_asset, allow_black_swan);
check_call_orders(receive_asset, allow_black_swan);
return find_object(order_id) == nullptr;
const limit_order_object* updated_order_object = find< limit_order_object >( order_id );
if( updated_order_object == nullptr )
return true;
if( head_block_time() <= HARDFORK_555_TIME )
return false;
// before #555 we would have done maybe_cull_small_order() logic as a result of fill_order() being called by match() above
// however after #555 we need to get rid of small orders -- #555 hardfork defers logic that was done too eagerly before, and
// this is the point it's deferred to.
return maybe_cull_small_order( *this, *updated_order_object );
}
/**
@ -218,8 +247,8 @@ int database::match( const limit_order_object& usd, const OrderType& core, const
core_pays == core.amount_for_sale() );
int result = 0;
result |= fill_order( usd, usd_pays, usd_receives );
result |= fill_order( core, core_pays, core_receives ) << 1;
result |= fill_order( usd, usd_pays, usd_receives, false );
result |= fill_order( core, core_pays, core_receives, true ) << 1;
assert( result != 0 );
return result;
}
@ -263,8 +292,10 @@ asset database::match( const call_order_object& call,
return call_receives;
} FC_CAPTURE_AND_RETHROW( (call)(settle)(match_price)(max_settlement) ) }
bool database::fill_order( const limit_order_object& order, const asset& pays, const asset& receives )
bool database::fill_order( const limit_order_object& order, const asset& pays, const asset& receives, bool cull_if_small )
{ try {
cull_if_small |= (head_block_time() < HARDFORK_555_TIME);
FC_ASSERT( order.amount_for_sale().asset_id == pays.asset_id );
FC_ASSERT( pays.asset_id != receives.asset_id );
@ -297,17 +328,8 @@ bool database::fill_order( const limit_order_object& order, const asset& pays, c
b.for_sale -= pays.amount;
b.deferred_fee = 0;
});
/**
* There are times when the AMOUNT_FOR_SALE * SALE_PRICE == 0 which means that we
* have hit the limit where the seller is asking for nothing in return. When this
* happens we must refund any balance back to the seller, it is too small to be
* sold at the sale price.
*/
if( order.amount_to_receive().amount == 0 )
{
cancel_order(order);
return true;
}
if( cull_if_small )
return maybe_cull_small_order( *this, order );
return false;
}
} FC_CAPTURE_AND_RETHROW( (order)(pays)(receives) ) }
@ -517,7 +539,7 @@ bool database::check_call_orders(const asset_object& mia, bool enable_black_swan
fill_order(*old_call_itr, call_pays, call_receives);
auto old_limit_itr = filled_limit ? limit_itr++ : limit_itr;
fill_order(*old_limit_itr, order_pays, order_receives);
fill_order(*old_limit_itr, order_pays, order_receives, true);
} // whlie call_itr != call_end

View file

@ -0,0 +1,4 @@
// #555 Buyback accounts
#ifndef HARDFORK_555_TIME
#define HARDFORK_555_TIME (fc::time_point_sec( 1455127200 ))
#endif

View file

@ -370,7 +370,7 @@ namespace graphene { namespace chain {
/**
* @return true if the order was completely filled and thus freed.
*/
bool fill_order( const limit_order_object& order, const asset& pays, const asset& receives );
bool fill_order( const limit_order_object& order, const asset& pays, const asset& receives, bool cull_if_small );
bool fill_order( const call_order_object& order, const asset& pays, const asset& receives );
bool fill_order( const force_settlement_object& settle, const asset& pays, const asset& receives );