-
Notifications
You must be signed in to change notification settings - Fork 646
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bsip 0018 #340
Bsip 0018 #340
Conversation
…val after price recovery
Use writable fee parameters for account_create only Fixed fee calculation
Added missing reflections
Resolves #216 |
{ try { | ||
FC_ASSERT( limit <= 100 ); | ||
const asset_object& swan = asset_id(_db); | ||
FC_ASSERT( swan.is_market_issued() ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we not also assert that swan has a settlement fund > 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just an accessor method. I think it will simplify things if we're lenient here. The call will return an empty list if the requested asset is not in global settlement. (This is technically correct.)
if( !bad.current_feed.settlement_price.is_null() | ||
&& ~price::call_price(asset(mia_dyn.current_supply, o.asset_id), | ||
asset(bad.settlement_fund, bad.options.short_backing_asset), | ||
bad.current_feed.maintenance_collateral_ratio ) < bad.current_feed.settlement_price ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are we 100% sure about the <
at this place? is this correct for any comvination of assetid and short backing asset?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The feed price is defined to be debt/collateral, see asset.hpp. The call price is computed as the inverse of debt/collateral*ratio. So if the inverted call price is lower than the feed, it means that we have less debt per collateral than required.
libraries/chain/db_market.cpp
Outdated
auto to_short = bdd.current_supply; | ||
auto collateral = bad.settlement_fund; | ||
if( collateral > 0 ) | ||
adjust_balance( bitasset.issuer, asset( collateral, bad.options.short_backing_asset ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why does it say bitasset.issuer here?
libraries/chain/db_market.cpp
Outdated
auto to_short = bdd.current_supply; | ||
auto collateral = bad.settlement_fund; | ||
if( collateral > 0 ) | ||
adjust_balance( bitasset.issuer, asset( collateral, bad.options.short_backing_asset ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, I assume after settlement all supply is 'shorted' by the issuer .. correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, this is the part where auto-revival happens after the feed has recovered. A call_order is created from debt and collateral, and this call_order belongs to the issuer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means the issuer will get the 75% extra collateral for free, which didn't worth that much when the black swan occurred.
Usually this won't happen, because usually bidders will cover the debt before the collateral ratio raised so high, asset holders may also have settled, unless the debt amount is too huge to cover, and the holders forgot to settle or lost the key, etc.
I suggest that we fulfill the bids first rather than sending the whole collateral to the issuer.
remove(bid); | ||
} | ||
|
||
void database::execute_bid( const collateral_bid_object& bid, share_type debt_covered, share_type collateral_from_fund, const price_feed& current_feed ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assuming this is a virtual operation, why does it not have the if condition for 'create_virtual_ops'?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I left it out because I always want to create the virtual op.
|
||
if( o.additional_collateral.amount > 0 ) | ||
{ | ||
FC_ASSERT( d.get_balance(*_paying_account, _bitasset_data->options.short_backing_asset(d)) >= o.additional_collateral, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldnt fee be in here as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fees are handled globally, in evaluator.cpp, not separately in each evaluator.
const collateral_bid_index& bids = d.get_index_type<collateral_bid_index>(); | ||
const auto& index = bids.indices().get<by_account>(); | ||
const auto& bid = index.find( boost::make_tuple( o.debt_covered.asset_id, o.bidder ) ); | ||
if( bid != index.end() ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i am not sure i understand this.
How can i bid if this evaluator asserts that i can update an existing bid? am i reading this wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
o.debt_covered.amount == 0 means that we only want to cancel an existing bid (which means a bid must already exist).
o.debt_covered.amount > 0 means create-or-update.
If you invert the logic you arrive at "if bid exists then fine else assert o.debt_covered.amount > 0".
if( o.debt_covered.amount == 0 ) return void_result(); | ||
|
||
d.adjust_balance( o.bidder, -o.additional_collateral ); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do i not need to credit for the previous bid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That already happened in d.cancel_bid (called on line 321).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me
libraries/app/database_api.cpp
Outdated
const auto& idx = _db.get_index_type<collateral_bid_index>(); | ||
const auto& aidx = idx.indices().get<by_price>(); | ||
auto start = aidx.lower_bound( boost::make_tuple( asset_id, price::max(back.id, asset_id), collateral_bid_id_type(GRAPHENE_DB_MAX_INSTANCE_ID) ) ); | ||
auto end = aidx.lower_bound( boost::make_tuple( asset_id, price::min(back.id, asset_id), collateral_bid_id_type(GRAPHENE_DB_MAX_INSTANCE_ID) ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's strange that both start
and end
use GRAPHENE_DB_MAX_INSTANCE_ID
, although technically it's not a big deal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix.
libraries/chain/db_market.cpp
Outdated
auto to_short = bdd.current_supply; | ||
auto collateral = bad.settlement_fund; | ||
if( collateral > 0 ) | ||
adjust_balance( bitasset.issuer, asset( collateral, bad.options.short_backing_asset ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means the issuer will get the 75% extra collateral for free, which didn't worth that much when the black swan occurred.
Usually this won't happen, because usually bidders will cover the debt before the collateral ratio raised so high, asset holders may also have settled, unless the debt amount is too huge to cover, and the holders forgot to settle or lost the key, etc.
I suggest that we fulfill the bids first rather than sending the whole collateral to the issuer.
libraries/chain/db_market.cpp
Outdated
const asset_bitasset_data_object& bad = bitasset.bitasset_data(*this); | ||
FC_ASSERT( bad.has_settlement() ); | ||
const asset_dynamic_data_object& bdd = bitasset.dynamic_asset_data_id(*this); | ||
FC_ASSERT( shorter != account_id_type() ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
account_id_type()
is committee-account
which should be allowed here. When this function is called from asset_publish_feeds_evaluator::do_apply()
, for example if the asset is bitUSD, the issuer is committee-account
.
By the way, why we need this shorter
parameter when revive_bitasset()
will only be called in asset_publish_feeds_evaluator
which always use the issuer as the parameter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will remove the shorter parameter and the assertion. It's a leftover from an earlier version. revive_bitasset is only used for auto-revival after the feed has recovered, and it always creates a call_order that belongs to the issuer.
libraries/chain/market_evaluator.cpp
Outdated
{ try { | ||
database& d = db(); | ||
|
||
FC_ASSERT( d.head_block_time() >= HARDFORK_CORE_216_TIME, "Not yet!" ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think >
is better here. Be consistent.
By the way, do we need to check for asset white-listing/black-listing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix >.
I don't think white/blacklisting are relevant here, because you can only bid BACK that you already have, and you'll only ever get BACK out again (possibly more than you put in). You can't transfer or trade BACK or SWAN here, and you cannot get SWAN out.
Thanks @abitmore ! Note that in revive_bitasset the issuer receives the collateral, but only to use it up in the call_order_update a few lines further down. The idea here is that the issuer will probably have the interests of the asset holders in mind, and will hopefully leave the collateral alone. Bidders usually have their own interests in mind and are likely to take their profits and leave. Now that I'm writing this I think revive_bitasset should be modified to call execute_bid instead of using adjust_balance and call_order_update_operation. Will think about this some more. |
@@ -268,150 +268,6 @@ namespace graphene { namespace app { | |||
return *_debug_api; | |||
} | |||
|
|||
vector<account_id_type> get_relevant_accounts( const object* obj ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good job removing this from api.cpp, no needed at all.
* Black swan occurs when price feed falls, triggered by settlement | ||
* order. | ||
*/ | ||
BOOST_AUTO_TEST_CASE( black_swan_issue_346 ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unsure about the reference to issue 346 here, it seems to not be related in bitshares-core or cryptonomex repos.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was moved here from the original https://github.com/bitshares/bitshares-core/blob/master/tests/tests/operation_tests.cpp#L287 , I didn't check what the 346 refers to. It seems that it indeed references the cryptonomes repo - cryptonomex/graphene@9d5a5dd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are right it actually came from here cryptonomex/graphene#346, at first saw i thought it was unrelated but going lower into the issue bytemaster explains. thanks.
the pull adds 14 test cases for black swan scenarios. they are at tests/swan_tests.cpp can run them all by:
or individually:
|
@@ -34,6 +34,49 @@ namespace graphene { namespace chain { | |||
}; | |||
typedef transform_to_fee_parameters<operation>::type fee_parameters; | |||
|
|||
template<typename Operation> | |||
class fee_helper { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unsure about why the fee_helper was needed to be implemented, sure it haves a reason but can you explain a bit further this and about why the account_create_operation
and the new created bid_collateral_operation
are special ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The challenge here was to create a fee that defaults to the value of another fee, as opposed to a static default. For this I needed to specialize the function template, and trying to do that I ran into the trap that partial specialization of certain templates is not allowed. The solution was to introduce a new class fee_helper that can be specialized as needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
account_create is special because it is the only operation that uses the non-const get().
bid_collateral is special because the fee defaults to the current value of call_order_update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got it, thanks!
error cant push more blocks in a new chain with this pull code, part of the output:
this is after block 170000, seems to be some problem with the fees. do i need to change some hardfork date ? this was just started with everything default. |
WTF? Will check. |
hold on, i messed up with the code of another node ... edit: not really, i am in the correct place. it seems to be failing there. |
Found and fixed this one, but ran into another special case. Still working on it. |
Replayed successfully with hf date in the future and in the past as well |
the new fee tests look good, the chain now replays fine too. i was checking a bit the api calls and wallet, we have 1 node new api call against cny:
against ALTCAP.X:
against non MPA assert:
Then in the cli_wallet we have 2 calls. First we have
We need to make sure the fees are charged only after the operation checks pass, in the list of the BSIP it says it will be the first thing to do. It is important to note that anyone will be able to do a revive, i am ok with this. Next step is to send the code to a testnet and revive MPAs in blackswan there to check the process. |
Great, thanks for your work! |
merged everything, now checking if |
new |
This is my initial implementation of BSIP-0018.