@@ -730,7 +730,8 @@ void_result asset_update_bitasset_evaluator::do_apply(const asset_update_bitasse
730
730
});
731
731
732
732
if ( to_check_call_orders )
733
- db_conn.check_call_orders ( asset_being_updated );
733
+ // Process margin calls, allow black swan, not for a new limit order
734
+ db_conn.check_call_orders ( asset_being_updated, true , false , bitasset_to_update );
734
735
735
736
return void_result ();
736
737
@@ -741,28 +742,42 @@ void_result asset_update_feed_producers_evaluator::do_evaluate(const asset_updat
741
742
{ try {
742
743
database& d = db ();
743
744
744
- FC_ASSERT ( o.new_feed_producers .size () <= d.get_global_properties ().parameters .maximum_asset_feed_publishers );
745
- for ( auto id : o.new_feed_producers )
746
- d.get_object (id);
745
+ FC_ASSERT ( o.new_feed_producers .size () <= d.get_global_properties ().parameters .maximum_asset_feed_publishers ,
746
+ " Cannot specify more feed producers than maximum allowed" );
747
747
748
748
const asset_object& a = o.asset_to_update (d);
749
749
750
750
FC_ASSERT (a.is_market_issued (), " Cannot update feed producers on a non-BitAsset." );
751
751
FC_ASSERT (!(a.options .flags & committee_fed_asset), " Cannot set feed producers on a committee-fed asset." );
752
752
FC_ASSERT (!(a.options .flags & witness_fed_asset), " Cannot set feed producers on a witness-fed asset." );
753
753
754
- const asset_bitasset_data_object& b = a.bitasset_data (d);
755
- bitasset_to_update = &b;
756
- FC_ASSERT ( a.issuer == o.issuer );
754
+ FC_ASSERT ( a.issuer == o.issuer , " Only asset issuer can update feed producers of an asset" );
755
+
756
+ asset_to_update = &a;
757
+
758
+ // Make sure all producers exist. Check these after asset because account lookup is more expensive
759
+ for ( auto id : o.new_feed_producers )
760
+ d.get_object (id);
761
+
757
762
return void_result ();
758
763
} FC_CAPTURE_AND_RETHROW ( (o) ) }
759
764
760
765
void_result asset_update_feed_producers_evaluator::do_apply (const asset_update_feed_producers_evaluator::operation_type& o)
761
766
{ try {
762
- db ().modify (*bitasset_to_update, [&](asset_bitasset_data_object& a) {
767
+ database& d = db ();
768
+ const auto head_time = d.head_block_time ();
769
+ const asset_bitasset_data_object& bitasset_to_update = asset_to_update->bitasset_data (d);
770
+ d.modify ( bitasset_to_update, [&o,head_time](asset_bitasset_data_object& a) {
763
771
// This is tricky because I have a set of publishers coming in, but a map of publisher to feed is stored.
764
772
// I need to update the map such that the keys match the new publishers, but not munge the old price feeds from
765
773
// publishers who are being kept.
774
+
775
+ // TODO possible performance optimization:
776
+ // Since both the map and the set are ordered by account already, we can iterate through them only once
777
+ // and avoid lookups while iterating by maintaining two iterators at same time.
778
+ // However, this operation is not used much, and both the set and the map are small,
779
+ // so likely we won't gain much with the optimization.
780
+
766
781
// First, remove any old publishers who are no longer publishers
767
782
for ( auto itr = a.feeds .begin (); itr != a.feeds .end (); )
768
783
{
@@ -772,12 +787,14 @@ void_result asset_update_feed_producers_evaluator::do_apply(const asset_update_f
772
787
++itr;
773
788
}
774
789
// Now, add any new publishers
775
- for ( auto itr = o.new_feed_producers .begin (); itr != o.new_feed_producers .end (); ++itr )
776
- if ( !a.feeds .count (*itr) )
777
- a.feeds [*itr];
778
- a.update_median_feeds (db ().head_block_time ());
790
+ for ( const account_id_type acc : o.new_feed_producers )
791
+ {
792
+ a.feeds [acc];
793
+ }
794
+ a.update_median_feeds ( head_time );
779
795
});
780
- db ().check_call_orders ( o.asset_to_update (db ()) );
796
+ // Process margin calls, allow black swan, not for a new limit order
797
+ d.check_call_orders ( *asset_to_update, true , false , &bitasset_to_update );
781
798
782
799
return void_result ();
783
800
} FC_CAPTURE_AND_RETHROW ( (o) ) }
@@ -786,20 +803,19 @@ void_result asset_global_settle_evaluator::do_evaluate(const asset_global_settle
786
803
{ try {
787
804
const database& d = db ();
788
805
asset_to_settle = &op.asset_to_settle (d);
789
- FC_ASSERT (asset_to_settle->is_market_issued ());
790
- FC_ASSERT (asset_to_settle->can_global_settle ());
791
- FC_ASSERT (asset_to_settle->issuer == op.issuer );
792
- FC_ASSERT (asset_to_settle->dynamic_data (d).current_supply > 0 );
806
+ FC_ASSERT ( asset_to_settle->is_market_issued (), " Can only globally settle market-issued assets " );
807
+ FC_ASSERT ( asset_to_settle->can_global_settle (), " The global_settle permission of this asset is disabled " );
808
+ FC_ASSERT ( asset_to_settle->issuer == op.issuer , " Only asset issuer can globally settle an asset " );
809
+ FC_ASSERT ( asset_to_settle->dynamic_data (d).current_supply > 0 , " Can not globally settle an asset with zero supply " );
793
810
794
811
const asset_bitasset_data_object& _bitasset_data = asset_to_settle->bitasset_data (d);
795
812
// if there is a settlement for this asset, then no further global settle may be taken
796
813
FC_ASSERT ( !_bitasset_data.has_settlement (), " This asset has settlement, cannot global settle again" );
797
814
798
815
const auto & idx = d.get_index_type <call_order_index>().indices ().get <by_collateral>();
799
- assert ( !idx.empty () );
800
- auto itr = idx.lower_bound (boost::make_tuple (price::min (asset_to_settle->bitasset_data (d).options .short_backing_asset ,
801
- op.asset_to_settle )));
802
- assert ( itr != idx.end () && itr->debt_type () == op.asset_to_settle );
816
+ FC_ASSERT ( !idx.empty (), " Internal error: no debt position found" );
817
+ auto itr = idx.lower_bound ( price::min ( _bitasset_data.options .short_backing_asset , op.asset_to_settle ) );
818
+ FC_ASSERT ( itr != idx.end () && itr->debt_type () == op.asset_to_settle , " Internal error: no debt position found" );
803
819
const call_order_object& least_collateralized_short = *itr;
804
820
FC_ASSERT (least_collateralized_short.get_debt () * op.settle_price <= least_collateralized_short.get_collateral (),
805
821
" Cannot force settle at supplied price: least collateralized short lacks sufficient collateral to settle." );
@@ -810,7 +826,7 @@ void_result asset_global_settle_evaluator::do_evaluate(const asset_global_settle
810
826
void_result asset_global_settle_evaluator::do_apply (const asset_global_settle_evaluator::operation_type& op)
811
827
{ try {
812
828
database& d = db ();
813
- d.globally_settle_asset ( op. asset_to_settle ( db ()) , op.settle_price );
829
+ d.globally_settle_asset ( * asset_to_settle, op.settle_price );
814
830
return void_result ();
815
831
} FC_CAPTURE_AND_RETHROW ( (op) ) }
816
832
@@ -897,7 +913,7 @@ void_result asset_publish_feeds_evaluator::do_evaluate(const asset_publish_feed_
897
913
898
914
const asset_object& base = o.asset_id (d);
899
915
// Verify that this feed is for a market-issued asset and that asset is backed by the base
900
- FC_ASSERT (base.is_market_issued ());
916
+ FC_ASSERT ( base.is_market_issued (), " Can only publish price feeds for market-issued assets " );
901
917
902
918
const asset_bitasset_data_object& bitasset = base.bitasset_data (d);
903
919
if ( bitasset.is_prediction_market || d.head_block_time () <= HARDFORK_CORE_216_TIME )
@@ -906,37 +922,46 @@ void_result asset_publish_feeds_evaluator::do_evaluate(const asset_publish_feed_
906
922
}
907
923
908
924
// the settlement price must be quoted in terms of the backing asset
909
- FC_ASSERT ( o.feed .settlement_price .quote .asset_id == bitasset.options .short_backing_asset );
925
+ FC_ASSERT ( o.feed .settlement_price .quote .asset_id == bitasset.options .short_backing_asset ,
926
+ " Quote asset type in settlement price should be same as backing asset of this asset" );
910
927
911
928
if ( d.head_block_time () > HARDFORK_480_TIME )
912
929
{
913
930
if ( !o.feed .core_exchange_rate .is_null () )
914
931
{
915
- FC_ASSERT ( o.feed .core_exchange_rate .quote .asset_id == asset_id_type () );
932
+ FC_ASSERT ( o.feed .core_exchange_rate .quote .asset_id == asset_id_type (),
933
+ " Quote asset in core exchange rate should be CORE asset" );
916
934
}
917
935
}
918
936
else
919
937
{
920
938
if ( (!o.feed .settlement_price .is_null ()) && (!o.feed .core_exchange_rate .is_null ()) )
921
939
{
922
- FC_ASSERT ( o.feed .settlement_price .quote .asset_id == o.feed .core_exchange_rate .quote .asset_id );
940
+ // Old buggy code, but we have to live with it
941
+ FC_ASSERT ( o.feed .settlement_price .quote .asset_id == o.feed .core_exchange_rate .quote .asset_id , " Bad feed" );
923
942
}
924
943
}
925
944
926
945
// Verify that the publisher is authoritative to publish a feed
927
946
if ( base.options .flags & witness_fed_asset )
928
947
{
929
- FC_ASSERT ( d.get (GRAPHENE_WITNESS_ACCOUNT).active .account_auths .count (o.publisher ) );
948
+ FC_ASSERT ( d.get (GRAPHENE_WITNESS_ACCOUNT).active .account_auths .count (o.publisher ),
949
+ " Only active witnesses are allowed to publish price feeds for this asset" );
930
950
}
931
951
else if ( base.options .flags & committee_fed_asset )
932
952
{
933
- FC_ASSERT ( d.get (GRAPHENE_COMMITTEE_ACCOUNT).active .account_auths .count (o.publisher ) );
953
+ FC_ASSERT ( d.get (GRAPHENE_COMMITTEE_ACCOUNT).active .account_auths .count (o.publisher ),
954
+ " Only active committee members are allowed to publish price feeds for this asset" );
934
955
}
935
956
else
936
957
{
937
- FC_ASSERT (bitasset.feeds .count (o.publisher ));
958
+ FC_ASSERT ( bitasset.feeds .count (o.publisher ),
959
+ " The account is not in the set of allowed price feed producers of this asset" );
938
960
}
939
961
962
+ asset_ptr = &base;
963
+ bitasset_ptr = &bitasset;
964
+
940
965
return void_result ();
941
966
} FC_CAPTURE_AND_RETHROW ((o)) }
942
967
@@ -945,8 +970,8 @@ void_result asset_publish_feeds_evaluator::do_apply(const asset_publish_feed_ope
945
970
946
971
database& d = db ();
947
972
948
- const asset_object& base = o. asset_id (d) ;
949
- const asset_bitasset_data_object& bad = base. bitasset_data (d) ;
973
+ const asset_object& base = *asset_ptr ;
974
+ const asset_bitasset_data_object& bad = *bitasset_ptr ;
950
975
951
976
auto old_feed = bad.current_feed ;
952
977
// Store medians for this asset
@@ -967,7 +992,8 @@ void_result asset_publish_feeds_evaluator::do_apply(const asset_publish_feed_ope
967
992
bad.current_feed .maintenance_collateral_ratio ) < bad.current_feed .settlement_price ) )
968
993
d.revive_bitasset (base);
969
994
}
970
- db ().check_call_orders (base);
995
+ // Process margin calls, allow black swan, not for a new limit order
996
+ d.check_call_orders ( base, true , false , bitasset_ptr );
971
997
}
972
998
973
999
return void_result ();
0 commit comments