Graphene Updates and DApp Support #643

Closed
nathanielhourt wants to merge 84 commits from dapp-support into develop
42 changed files with 501 additions and 284 deletions
Showing only changes of commit e8b432c19f - Show all commits

View file

@ -130,7 +130,7 @@ void asset_create_evaluator::pay_fee()
{
fee_is_odd = core_fee_paid.value & 1;
core_fee_paid -= core_fee_paid.value/2;
generic_evaluator::pay_fee();
consensus_evaluator::pay_fee();
}
object_id_type asset_create_evaluator::do_apply( const asset_create_operation& op )
@ -283,7 +283,7 @@ void lottery_asset_create_evaluator::pay_fee()
{
fee_is_odd = core_fee_paid.value & 1;
core_fee_paid -= core_fee_paid.value/2;
generic_evaluator::pay_fee();
consensus_evaluator::pay_fee();
}
object_id_type lottery_asset_create_evaluator::do_apply( const lottery_asset_create_operation& op )

View file

@ -74,7 +74,7 @@ void transfer_to_blind_evaluator::pay_fee()
if( db().head_block_time() >= HARDFORK_563_TIME )
pay_fba_fee( fba_accumulator_id_transfer_to_blind );
else
generic_evaluator::pay_fee();
consensus_evaluator::pay_fee();
}
void_result transfer_from_blind_evaluator::do_evaluate( const transfer_from_blind_operation& o )
@ -118,7 +118,7 @@ void transfer_from_blind_evaluator::pay_fee()
if( db().head_block_time() >= HARDFORK_563_TIME )
pay_fba_fee( fba_accumulator_id_transfer_from_blind );
else
generic_evaluator::pay_fee();
consensus_evaluator::pay_fee();
}
void_result blind_transfer_evaluator::do_evaluate( const blind_transfer_operation& o )
@ -175,7 +175,7 @@ void blind_transfer_evaluator::pay_fee()
if( db().head_block_time() >= HARDFORK_563_TIME )
pay_fba_fee( fba_accumulator_id_blind_transfer );
else
generic_evaluator::pay_fee();
consensus_evaluator::pay_fee();
}
} } // graphene::chain

View file

@ -42,6 +42,7 @@
#include <graphene/protocol/betting_market.hpp>
#include <fc/crypto/digest.hpp>
#include <fc/thread/non_preemptable_scope_check.hpp>
namespace {
@ -866,12 +867,18 @@ operation_result database::apply_operation(transaction_evaluation_state& eval_st
int i_which = op.which();
uint64_t u_which = uint64_t( i_which );
FC_ASSERT( i_which >= 0, "Negative operation tag in operation ${op}", ("op",op) );
FC_ASSERT( u_which < _operation_evaluators.size(), "No registered evaluator for operation ${op}", ("op",op) );
unique_ptr<op_evaluator>& eval = _operation_evaluators[ u_which ];
FC_ASSERT( u_which < _consensus_operation_evaluators.size(), "No registered evaluator for operation ${op}", ("op",op) );
unique_ptr<op_evaluator>& eval = _consensus_operation_evaluators[ u_which ];
FC_ASSERT( eval, "No registered evaluator for operation ${op}", ("op",op) );
auto op_id = push_applied_operation( op );
auto result = eval->evaluate( eval_state, op, true );
set_applied_operation_result( op_id, result );
// Run third party evaluator chain
if (_third_party_operation_evaluators.size() > u_which && _third_party_operation_evaluators[u_which]) {
ASSERT_TASK_NOT_PREEMPTED();
_third_party_operation_evaluators[u_which]->evaluate( eval_state, op, true );
}
return result;
} FC_CAPTURE_AND_RETHROW( (op) ) }

View file

@ -214,119 +214,120 @@ const uint8_t random_number_object::type_id;
void database::initialize_evaluators()
{
_operation_evaluators.resize(255);
register_evaluator<account_create_evaluator>();
register_evaluator<account_update_evaluator>();
register_evaluator<account_upgrade_evaluator>();
register_evaluator<account_whitelist_evaluator>();
register_evaluator<committee_member_create_evaluator>();
register_evaluator<committee_member_update_evaluator>();
register_evaluator<committee_member_update_global_parameters_evaluator>();
register_evaluator<custom_evaluator>();
register_evaluator<asset_create_evaluator>();
register_evaluator<asset_issue_evaluator>();
register_evaluator<asset_reserve_evaluator>();
register_evaluator<asset_update_evaluator>();
register_evaluator<asset_update_bitasset_evaluator>();
register_evaluator<asset_update_dividend_evaluator>();
register_evaluator<asset_update_feed_producers_evaluator>();
register_evaluator<asset_settle_evaluator>();
register_evaluator<asset_global_settle_evaluator>();
register_evaluator<assert_evaluator>();
register_evaluator<limit_order_create_evaluator>();
register_evaluator<limit_order_cancel_evaluator>();
register_evaluator<call_order_update_evaluator>();
register_evaluator<transfer_evaluator>();
register_evaluator<override_transfer_evaluator>();
register_evaluator<asset_fund_fee_pool_evaluator>();
register_evaluator<asset_publish_feeds_evaluator>();
register_evaluator<proposal_create_evaluator>();
register_evaluator<proposal_update_evaluator>();
register_evaluator<proposal_delete_evaluator>();
register_evaluator<vesting_balance_create_evaluator>();
register_evaluator<vesting_balance_withdraw_evaluator>();
register_evaluator<witness_create_evaluator>();
register_evaluator<witness_update_evaluator>();
register_evaluator<withdraw_permission_create_evaluator>();
register_evaluator<withdraw_permission_claim_evaluator>();
register_evaluator<withdraw_permission_update_evaluator>();
register_evaluator<withdraw_permission_delete_evaluator>();
register_evaluator<worker_create_evaluator>();
register_evaluator<balance_claim_evaluator>();
register_evaluator<transfer_to_blind_evaluator>();
register_evaluator<transfer_from_blind_evaluator>();
register_evaluator<blind_transfer_evaluator>();
register_evaluator<asset_claim_fees_evaluator>();
register_evaluator<sport_create_evaluator>();
register_evaluator<sport_update_evaluator>();
register_evaluator<sport_delete_evaluator>();
register_evaluator<event_group_create_evaluator>();
register_evaluator<event_group_update_evaluator>();
register_evaluator<event_group_delete_evaluator>();
register_evaluator<event_create_evaluator>();
register_evaluator<event_update_evaluator>();
register_evaluator<event_update_status_evaluator>();
register_evaluator<betting_market_rules_create_evaluator>();
register_evaluator<betting_market_rules_update_evaluator>();
register_evaluator<betting_market_group_create_evaluator>();
register_evaluator<betting_market_group_update_evaluator>();
register_evaluator<betting_market_create_evaluator>();
register_evaluator<betting_market_update_evaluator>();
register_evaluator<bet_place_evaluator>();
register_evaluator<bet_cancel_evaluator>();
register_evaluator<betting_market_group_resolve_evaluator>();
register_evaluator<betting_market_group_cancel_unmatched_bets_evaluator>();
register_evaluator<tournament_create_evaluator>();
register_evaluator<tournament_join_evaluator>();
register_evaluator<game_move_evaluator>();
register_evaluator<tournament_leave_evaluator>();
register_evaluator<lottery_asset_create_evaluator>();
register_evaluator<ticket_purchase_evaluator>();
register_evaluator<lottery_reward_evaluator>();
register_evaluator<lottery_end_evaluator>();
register_evaluator<sweeps_vesting_claim_evaluator>();
register_evaluator<create_custom_permission_evaluator>();
register_evaluator<update_custom_permission_evaluator>();
register_evaluator<delete_custom_permission_evaluator>();
register_evaluator<create_custom_account_authority_evaluator>();
register_evaluator<update_custom_account_authority_evaluator>();
register_evaluator<delete_custom_account_authority_evaluator>();
register_evaluator<offer_evaluator>();
register_evaluator<bid_evaluator>();
register_evaluator<cancel_offer_evaluator>();
register_evaluator<finalize_offer_evaluator>();
register_evaluator<nft_metadata_create_evaluator>();
register_evaluator<nft_metadata_update_evaluator>();
register_evaluator<nft_mint_evaluator>();
register_evaluator<nft_safe_transfer_from_evaluator>();
register_evaluator<nft_approve_evaluator>();
register_evaluator<nft_set_approval_for_all_evaluator>();
register_evaluator<account_role_create_evaluator>();
register_evaluator<account_role_update_evaluator>();
register_evaluator<account_role_delete_evaluator>();
register_evaluator<nft_lottery_token_purchase_evaluator>();
register_evaluator<nft_lottery_reward_evaluator>();
register_evaluator<nft_lottery_end_evaluator>();
register_evaluator<create_son_evaluator>();
register_evaluator<update_son_evaluator>();
register_evaluator<deregister_son_evaluator>();
register_evaluator<son_heartbeat_evaluator>();
register_evaluator<son_report_down_evaluator>();
register_evaluator<son_maintenance_evaluator>();
register_evaluator<recreate_son_wallet_evaluator>();
register_evaluator<update_son_wallet_evaluator>();
register_evaluator<create_son_wallet_deposit_evaluator>();
register_evaluator<process_son_wallet_deposit_evaluator>();
register_evaluator<create_son_wallet_withdraw_evaluator>();
register_evaluator<process_son_wallet_withdraw_evaluator>();
register_evaluator<add_sidechain_address_evaluator>();
register_evaluator<update_sidechain_address_evaluator>();
register_evaluator<delete_sidechain_address_evaluator>();
register_evaluator<sidechain_transaction_create_evaluator>();
register_evaluator<sidechain_transaction_sign_evaluator>();
register_evaluator<sidechain_transaction_send_evaluator>();
register_evaluator<sidechain_transaction_settle_evaluator>();
register_evaluator<random_number_store_evaluator>();
_consensus_operation_evaluators.resize(255);
_third_party_operation_evaluators.resize(255);
register_consensus_evaluator<account_create_evaluator>();
register_consensus_evaluator<account_update_evaluator>();
register_consensus_evaluator<account_upgrade_evaluator>();
register_consensus_evaluator<account_whitelist_evaluator>();
register_consensus_evaluator<committee_member_create_evaluator>();
register_consensus_evaluator<committee_member_update_evaluator>();
register_consensus_evaluator<committee_member_update_global_parameters_evaluator>();
register_consensus_evaluator<custom_evaluator>();
register_consensus_evaluator<asset_create_evaluator>();
register_consensus_evaluator<asset_issue_evaluator>();
register_consensus_evaluator<asset_reserve_evaluator>();
register_consensus_evaluator<asset_update_evaluator>();
register_consensus_evaluator<asset_update_bitasset_evaluator>();
register_consensus_evaluator<asset_update_dividend_evaluator>();
register_consensus_evaluator<asset_update_feed_producers_evaluator>();
register_consensus_evaluator<asset_settle_evaluator>();
register_consensus_evaluator<asset_global_settle_evaluator>();
register_consensus_evaluator<assert_evaluator>();
register_consensus_evaluator<limit_order_create_evaluator>();
register_consensus_evaluator<limit_order_cancel_evaluator>();
register_consensus_evaluator<call_order_update_evaluator>();
register_consensus_evaluator<transfer_evaluator>();
register_consensus_evaluator<override_transfer_evaluator>();
register_consensus_evaluator<asset_fund_fee_pool_evaluator>();
register_consensus_evaluator<asset_publish_feeds_evaluator>();
register_consensus_evaluator<proposal_create_evaluator>();
register_consensus_evaluator<proposal_update_evaluator>();
register_consensus_evaluator<proposal_delete_evaluator>();
register_consensus_evaluator<vesting_balance_create_evaluator>();
register_consensus_evaluator<vesting_balance_withdraw_evaluator>();
register_consensus_evaluator<witness_create_evaluator>();
register_consensus_evaluator<witness_update_evaluator>();
register_consensus_evaluator<withdraw_permission_create_evaluator>();
register_consensus_evaluator<withdraw_permission_claim_evaluator>();
register_consensus_evaluator<withdraw_permission_update_evaluator>();
register_consensus_evaluator<withdraw_permission_delete_evaluator>();
register_consensus_evaluator<worker_create_evaluator>();
register_consensus_evaluator<balance_claim_evaluator>();
register_consensus_evaluator<transfer_to_blind_evaluator>();
register_consensus_evaluator<transfer_from_blind_evaluator>();
register_consensus_evaluator<blind_transfer_evaluator>();
register_consensus_evaluator<asset_claim_fees_evaluator>();
register_consensus_evaluator<sport_create_evaluator>();
register_consensus_evaluator<sport_update_evaluator>();
register_consensus_evaluator<sport_delete_evaluator>();
register_consensus_evaluator<event_group_create_evaluator>();
register_consensus_evaluator<event_group_update_evaluator>();
register_consensus_evaluator<event_group_delete_evaluator>();
register_consensus_evaluator<event_create_evaluator>();
register_consensus_evaluator<event_update_evaluator>();
register_consensus_evaluator<event_update_status_evaluator>();
register_consensus_evaluator<betting_market_rules_create_evaluator>();
register_consensus_evaluator<betting_market_rules_update_evaluator>();
register_consensus_evaluator<betting_market_group_create_evaluator>();
register_consensus_evaluator<betting_market_group_update_evaluator>();
register_consensus_evaluator<betting_market_create_evaluator>();
register_consensus_evaluator<betting_market_update_evaluator>();
register_consensus_evaluator<bet_place_evaluator>();
register_consensus_evaluator<bet_cancel_evaluator>();
register_consensus_evaluator<betting_market_group_resolve_evaluator>();
register_consensus_evaluator<betting_market_group_cancel_unmatched_bets_evaluator>();
register_consensus_evaluator<tournament_create_evaluator>();
register_consensus_evaluator<tournament_join_evaluator>();
register_consensus_evaluator<game_move_evaluator>();
register_consensus_evaluator<tournament_leave_evaluator>();
register_consensus_evaluator<lottery_asset_create_evaluator>();
register_consensus_evaluator<ticket_purchase_evaluator>();
register_consensus_evaluator<lottery_reward_evaluator>();
register_consensus_evaluator<lottery_end_evaluator>();
register_consensus_evaluator<sweeps_vesting_claim_evaluator>();
register_consensus_evaluator<create_custom_permission_evaluator>();
register_consensus_evaluator<update_custom_permission_evaluator>();
register_consensus_evaluator<delete_custom_permission_evaluator>();
register_consensus_evaluator<create_custom_account_authority_evaluator>();
register_consensus_evaluator<update_custom_account_authority_evaluator>();
register_consensus_evaluator<delete_custom_account_authority_evaluator>();
register_consensus_evaluator<offer_evaluator>();
register_consensus_evaluator<bid_evaluator>();
register_consensus_evaluator<cancel_offer_evaluator>();
register_consensus_evaluator<finalize_offer_evaluator>();
register_consensus_evaluator<nft_metadata_create_evaluator>();
register_consensus_evaluator<nft_metadata_update_evaluator>();
register_consensus_evaluator<nft_mint_evaluator>();
register_consensus_evaluator<nft_safe_transfer_from_evaluator>();
register_consensus_evaluator<nft_approve_evaluator>();
register_consensus_evaluator<nft_set_approval_for_all_evaluator>();
register_consensus_evaluator<account_role_create_evaluator>();
register_consensus_evaluator<account_role_update_evaluator>();
register_consensus_evaluator<account_role_delete_evaluator>();
register_consensus_evaluator<nft_lottery_token_purchase_evaluator>();
register_consensus_evaluator<nft_lottery_reward_evaluator>();
register_consensus_evaluator<nft_lottery_end_evaluator>();
register_consensus_evaluator<create_son_evaluator>();
register_consensus_evaluator<update_son_evaluator>();
register_consensus_evaluator<deregister_son_evaluator>();
register_consensus_evaluator<son_heartbeat_evaluator>();
register_consensus_evaluator<son_report_down_evaluator>();
register_consensus_evaluator<son_maintenance_evaluator>();
register_consensus_evaluator<recreate_son_wallet_evaluator>();
register_consensus_evaluator<update_son_wallet_evaluator>();
register_consensus_evaluator<create_son_wallet_deposit_evaluator>();
register_consensus_evaluator<process_son_wallet_deposit_evaluator>();
register_consensus_evaluator<create_son_wallet_withdraw_evaluator>();
register_consensus_evaluator<process_son_wallet_withdraw_evaluator>();
register_consensus_evaluator<add_sidechain_address_evaluator>();
register_consensus_evaluator<update_sidechain_address_evaluator>();
register_consensus_evaluator<delete_sidechain_address_evaluator>();
register_consensus_evaluator<sidechain_transaction_create_evaluator>();
register_consensus_evaluator<sidechain_transaction_sign_evaluator>();
register_consensus_evaluator<sidechain_transaction_send_evaluator>();
register_consensus_evaluator<sidechain_transaction_settle_evaluator>();
register_consensus_evaluator<random_number_store_evaluator>();
}
void database::initialize_indexes()

View file

@ -36,9 +36,9 @@
#include <graphene/protocol/fee_schedule.hpp>
namespace graphene { namespace chain {
database& generic_evaluator::db()const { return trx_state->db(); }
database& consensus_evaluator::db()const { return trx_state->db(); }
operation_result generic_evaluator::start_evaluate( transaction_evaluation_state& eval_state, const operation& op, bool apply )
operation_result consensus_evaluator::start_evaluate( transaction_evaluation_state& eval_state, const operation& op, bool apply )
{ try {
trx_state = &eval_state;
//check_required_authorities(op);
@ -48,7 +48,7 @@ database& generic_evaluator::db()const { return trx_state->db(); }
return result;
} FC_CAPTURE_AND_RETHROW() }
void generic_evaluator::prepare_fee(account_id_type account_id, asset fee)
void consensus_evaluator::prepare_fee(account_id_type account_id, asset fee)
{
const database& d = db();
fee_from_account = fee;
@ -77,7 +77,7 @@ database& generic_evaluator::db()const { return trx_state->db(); }
}
}
void generic_evaluator::convert_fee()
void consensus_evaluator::convert_fee()
{
if( !trx_state->skip_fee ) {
if( fee_asset->get_id() != asset_id_type() )
@ -90,7 +90,7 @@ database& generic_evaluator::db()const { return trx_state->db(); }
}
}
void generic_evaluator::pay_fee()
void consensus_evaluator::pay_fee()
{ try {
if( !trx_state->skip_fee ) {
database& d = db();
@ -102,13 +102,13 @@ database& generic_evaluator::db()const { return trx_state->db(); }
}
} FC_CAPTURE_AND_RETHROW() }
void generic_evaluator::pay_fba_fee( uint64_t fba_id )
void consensus_evaluator::pay_fba_fee( uint64_t fba_id )
{
database& d = db();
const fba_accumulator_object& fba = d.get< fba_accumulator_object >( fba_accumulator_id_type( fba_id ) );
if( !fba.is_configured(d) )
{
generic_evaluator::pay_fee();
consensus_evaluator::pay_fee();
return;
}
d.modify( fba, [&]( fba_accumulator_object& _fba )
@ -117,16 +117,16 @@ database& generic_evaluator::db()const { return trx_state->db(); }
} );
}
share_type generic_evaluator::calculate_fee_for_operation(const operation& op) const
share_type consensus_evaluator::calculate_fee_for_operation(const operation& op) const
{
return db().current_fee_schedule().calculate_fee( op ).amount;
}
void generic_evaluator::db_adjust_balance(const account_id_type& fee_payer, asset fee_from_account)
void consensus_evaluator::db_adjust_balance(const account_id_type& fee_payer, asset fee_from_account)
{
db().adjust_balance(fee_payer, fee_from_account);
}
object_id_type generic_evaluator::get_relative_id( object_id_type rel_id )const
object_id_type consensus_evaluator::get_relative_id( object_id_type rel_id )const
{
if (!is_relative(rel_id))
FC_THROW("get_relative_id() called for non-relative id ${id}", ("id", rel_id));

View file

@ -27,7 +27,7 @@
namespace graphene { namespace chain {
class account_create_evaluator : public evaluator<account_create_evaluator>
class account_create_evaluator : public fee_handling_evaluator<account_create_evaluator>
{
public:
typedef account_create_operation operation_type;
@ -36,7 +36,7 @@ public:
object_id_type do_apply( const account_create_operation& o ) ;
};
class account_update_evaluator : public evaluator<account_update_evaluator>
class account_update_evaluator : public fee_handling_evaluator<account_update_evaluator>
{
public:
typedef account_update_operation operation_type;
@ -47,7 +47,7 @@ public:
const account_object* acnt;
};
class account_upgrade_evaluator : public evaluator<account_upgrade_evaluator>
class account_upgrade_evaluator : public fee_handling_evaluator<account_upgrade_evaluator>
{
public:
typedef account_upgrade_operation operation_type;
@ -58,7 +58,7 @@ public:
const account_object* account;
};
class account_whitelist_evaluator : public evaluator<account_whitelist_evaluator>
class account_whitelist_evaluator : public fee_handling_evaluator<account_whitelist_evaluator>
{
public:
typedef account_whitelist_operation operation_type;

View file

@ -7,7 +7,7 @@
namespace graphene { namespace chain {
class account_role_create_evaluator : public evaluator<account_role_create_evaluator>
class account_role_create_evaluator : public fee_handling_evaluator<account_role_create_evaluator>
{
public:
typedef account_role_create_operation operation_type;
@ -15,7 +15,7 @@ namespace graphene { namespace chain {
object_id_type do_apply( const account_role_create_operation& o );
};
class account_role_update_evaluator : public evaluator<account_role_update_evaluator>
class account_role_update_evaluator : public fee_handling_evaluator<account_role_update_evaluator>
{
public:
typedef account_role_update_operation operation_type;
@ -23,7 +23,7 @@ namespace graphene { namespace chain {
void_result do_apply( const account_role_update_operation& o );
};
class account_role_delete_evaluator : public evaluator<account_role_delete_evaluator>
class account_role_delete_evaluator : public fee_handling_evaluator<account_role_delete_evaluator>
{
public:
typedef account_role_delete_operation operation_type;

View file

@ -28,7 +28,7 @@
namespace graphene { namespace chain {
class assert_evaluator : public evaluator<assert_evaluator>
class assert_evaluator : public fee_handling_evaluator<assert_evaluator>
{
public:
typedef assert_operation operation_type;

View file

@ -28,7 +28,7 @@
namespace graphene { namespace chain {
class asset_create_evaluator : public evaluator<asset_create_evaluator>
class asset_create_evaluator : public fee_handling_evaluator<asset_create_evaluator>
{
public:
typedef asset_create_operation operation_type;
@ -44,7 +44,7 @@ namespace graphene { namespace chain {
bool fee_is_odd;
};
class lottery_asset_create_evaluator : public evaluator<lottery_asset_create_evaluator>
class lottery_asset_create_evaluator : public fee_handling_evaluator<lottery_asset_create_evaluator>
{
public:
typedef lottery_asset_create_operation operation_type;
@ -60,7 +60,7 @@ namespace graphene { namespace chain {
bool fee_is_odd;
};
class asset_issue_evaluator : public evaluator<asset_issue_evaluator>
class asset_issue_evaluator : public fee_handling_evaluator<asset_issue_evaluator>
{
public:
typedef asset_issue_operation operation_type;
@ -71,7 +71,7 @@ namespace graphene { namespace chain {
const account_object* to_account = nullptr;
};
class asset_reserve_evaluator : public evaluator<asset_reserve_evaluator>
class asset_reserve_evaluator : public fee_handling_evaluator<asset_reserve_evaluator>
{
public:
typedef asset_reserve_operation operation_type;
@ -83,7 +83,7 @@ namespace graphene { namespace chain {
};
class asset_update_evaluator : public evaluator<asset_update_evaluator>
class asset_update_evaluator : public fee_handling_evaluator<asset_update_evaluator>
{
public:
typedef asset_update_operation operation_type;
@ -94,7 +94,7 @@ namespace graphene { namespace chain {
const asset_object* asset_to_update = nullptr;
};
class asset_update_bitasset_evaluator : public evaluator<asset_update_bitasset_evaluator>
class asset_update_bitasset_evaluator : public fee_handling_evaluator<asset_update_bitasset_evaluator>
{
public:
typedef asset_update_bitasset_operation operation_type;
@ -105,7 +105,7 @@ namespace graphene { namespace chain {
const asset_bitasset_data_object* bitasset_to_update = nullptr;
};
class asset_update_dividend_evaluator : public evaluator<asset_update_dividend_evaluator>
class asset_update_dividend_evaluator : public fee_handling_evaluator<asset_update_dividend_evaluator>
{
public:
typedef asset_update_dividend_operation operation_type;
@ -117,7 +117,7 @@ namespace graphene { namespace chain {
const asset_dividend_data_object* asset_dividend_data_to_update = nullptr;
};
class asset_update_feed_producers_evaluator : public evaluator<asset_update_feed_producers_evaluator>
class asset_update_feed_producers_evaluator : public fee_handling_evaluator<asset_update_feed_producers_evaluator>
{
public:
typedef asset_update_feed_producers_operation operation_type;
@ -128,7 +128,7 @@ namespace graphene { namespace chain {
const asset_bitasset_data_object* bitasset_to_update = nullptr;
};
class asset_fund_fee_pool_evaluator : public evaluator<asset_fund_fee_pool_evaluator>
class asset_fund_fee_pool_evaluator : public fee_handling_evaluator<asset_fund_fee_pool_evaluator>
{
public:
typedef asset_fund_fee_pool_operation operation_type;
@ -139,7 +139,7 @@ namespace graphene { namespace chain {
const asset_dynamic_data_object* asset_dyn_data = nullptr;
};
class asset_global_settle_evaluator : public evaluator<asset_global_settle_evaluator>
class asset_global_settle_evaluator : public fee_handling_evaluator<asset_global_settle_evaluator>
{
public:
typedef asset_global_settle_operation operation_type;
@ -149,7 +149,7 @@ namespace graphene { namespace chain {
const asset_object* asset_to_settle = nullptr;
};
class asset_settle_evaluator : public evaluator<asset_settle_evaluator>
class asset_settle_evaluator : public fee_handling_evaluator<asset_settle_evaluator>
{
public:
typedef asset_settle_operation operation_type;
@ -160,7 +160,7 @@ namespace graphene { namespace chain {
const asset_object* asset_to_settle = nullptr;
};
class asset_publish_feeds_evaluator : public evaluator<asset_publish_feeds_evaluator>
class asset_publish_feeds_evaluator : public fee_handling_evaluator<asset_publish_feeds_evaluator>
{
public:
typedef asset_publish_feed_operation operation_type;
@ -171,7 +171,7 @@ namespace graphene { namespace chain {
std::map<std::pair<asset_id_type,asset_id_type>,price_feed> median_feed_values;
};
class asset_claim_fees_evaluator : public evaluator<asset_claim_fees_evaluator>
class asset_claim_fees_evaluator : public fee_handling_evaluator<asset_claim_fees_evaluator>
{
public:
typedef asset_claim_fees_operation operation_type;

View file

@ -31,7 +31,7 @@
namespace graphene { namespace chain {
class balance_claim_evaluator : public evaluator<balance_claim_evaluator>
class balance_claim_evaluator : public fee_handling_evaluator<balance_claim_evaluator>
{
public:
typedef balance_claim_operation operation_type;

View file

@ -29,7 +29,7 @@
namespace graphene { namespace chain {
class betting_market_rules_create_evaluator : public evaluator<betting_market_rules_create_evaluator>
class betting_market_rules_create_evaluator : public fee_handling_evaluator<betting_market_rules_create_evaluator>
{
public:
typedef betting_market_rules_create_operation operation_type;
@ -38,7 +38,7 @@ namespace graphene { namespace chain {
object_id_type do_apply( const betting_market_rules_create_operation& o );
};
class betting_market_rules_update_evaluator : public evaluator<betting_market_rules_update_evaluator>
class betting_market_rules_update_evaluator : public fee_handling_evaluator<betting_market_rules_update_evaluator>
{
public:
typedef betting_market_rules_update_operation operation_type;
@ -49,7 +49,7 @@ namespace graphene { namespace chain {
const betting_market_rules_object* _rules;
};
class betting_market_group_create_evaluator : public evaluator<betting_market_group_create_evaluator>
class betting_market_group_create_evaluator : public fee_handling_evaluator<betting_market_group_create_evaluator>
{
public:
typedef betting_market_group_create_operation operation_type;
@ -61,7 +61,7 @@ namespace graphene { namespace chain {
betting_market_rules_id_type _rules_id;
};
class betting_market_group_update_evaluator : public evaluator<betting_market_group_update_evaluator>
class betting_market_group_update_evaluator : public fee_handling_evaluator<betting_market_group_update_evaluator>
{
public:
typedef betting_market_group_update_operation operation_type;
@ -73,7 +73,7 @@ namespace graphene { namespace chain {
const betting_market_group_object* _betting_market_group;
};
class betting_market_create_evaluator : public evaluator<betting_market_create_evaluator>
class betting_market_create_evaluator : public fee_handling_evaluator<betting_market_create_evaluator>
{
public:
typedef betting_market_create_operation operation_type;
@ -84,7 +84,7 @@ namespace graphene { namespace chain {
betting_market_group_id_type _group_id;
};
class betting_market_update_evaluator : public evaluator<betting_market_update_evaluator>
class betting_market_update_evaluator : public fee_handling_evaluator<betting_market_update_evaluator>
{
public:
typedef betting_market_update_operation operation_type;
@ -96,7 +96,7 @@ namespace graphene { namespace chain {
betting_market_group_id_type _group_id;
};
class bet_place_evaluator : public evaluator<bet_place_evaluator>
class bet_place_evaluator : public fee_handling_evaluator<bet_place_evaluator>
{
public:
typedef bet_place_operation operation_type;
@ -111,7 +111,7 @@ namespace graphene { namespace chain {
share_type _stake_plus_fees;
};
class bet_cancel_evaluator : public evaluator<bet_cancel_evaluator>
class bet_cancel_evaluator : public fee_handling_evaluator<bet_cancel_evaluator>
{
public:
typedef bet_cancel_operation operation_type;
@ -122,7 +122,7 @@ namespace graphene { namespace chain {
const bet_object* _bet_to_cancel;
};
class betting_market_group_resolve_evaluator : public evaluator<betting_market_group_resolve_evaluator>
class betting_market_group_resolve_evaluator : public fee_handling_evaluator<betting_market_group_resolve_evaluator>
{
public:
typedef betting_market_group_resolve_operation operation_type;
@ -133,7 +133,7 @@ namespace graphene { namespace chain {
const betting_market_group_object* _betting_market_group;
};
class betting_market_group_cancel_unmatched_bets_evaluator : public evaluator<betting_market_group_cancel_unmatched_bets_evaluator>
class betting_market_group_cancel_unmatched_bets_evaluator : public fee_handling_evaluator<betting_market_group_cancel_unmatched_bets_evaluator>
{
public:
typedef betting_market_group_cancel_unmatched_bets_operation operation_type;

View file

@ -28,7 +28,7 @@
namespace graphene { namespace chain {
class committee_member_create_evaluator : public evaluator<committee_member_create_evaluator>
class committee_member_create_evaluator : public fee_handling_evaluator<committee_member_create_evaluator>
{
public:
typedef committee_member_create_operation operation_type;
@ -37,7 +37,7 @@ namespace graphene { namespace chain {
object_id_type do_apply( const committee_member_create_operation& o );
};
class committee_member_update_evaluator : public evaluator<committee_member_update_evaluator>
class committee_member_update_evaluator : public fee_handling_evaluator<committee_member_update_evaluator>
{
public:
typedef committee_member_update_operation operation_type;
@ -46,7 +46,7 @@ namespace graphene { namespace chain {
void_result do_apply( const committee_member_update_operation& o );
};
class committee_member_update_global_parameters_evaluator : public evaluator<committee_member_update_global_parameters_evaluator>
class committee_member_update_global_parameters_evaluator : public fee_handling_evaluator<committee_member_update_global_parameters_evaluator>
{
public:
typedef committee_member_update_global_parameters_operation operation_type;

View file

@ -27,7 +27,7 @@
namespace graphene { namespace chain {
class transfer_to_blind_evaluator : public evaluator<transfer_to_blind_evaluator>
class transfer_to_blind_evaluator : public fee_handling_evaluator<transfer_to_blind_evaluator>
{
public:
typedef transfer_to_blind_operation operation_type;
@ -38,7 +38,7 @@ class transfer_to_blind_evaluator : public evaluator<transfer_to_blind_evaluator
virtual void pay_fee() override;
};
class transfer_from_blind_evaluator : public evaluator<transfer_from_blind_evaluator>
class transfer_from_blind_evaluator : public fee_handling_evaluator<transfer_from_blind_evaluator>
{
public:
typedef transfer_from_blind_operation operation_type;
@ -49,7 +49,7 @@ class transfer_from_blind_evaluator : public evaluator<transfer_from_blind_evalu
virtual void pay_fee() override;
};
class blind_transfer_evaluator : public evaluator<blind_transfer_evaluator>
class blind_transfer_evaluator : public fee_handling_evaluator<blind_transfer_evaluator>
{
public:
typedef blind_transfer_operation operation_type;

View file

@ -8,7 +8,7 @@ namespace graphene
namespace chain
{
class create_custom_account_authority_evaluator : public evaluator<create_custom_account_authority_evaluator>
class create_custom_account_authority_evaluator : public fee_handling_evaluator<create_custom_account_authority_evaluator>
{
public:
typedef custom_account_authority_create_operation operation_type;
@ -17,7 +17,7 @@ public:
object_id_type do_apply(const custom_account_authority_create_operation &o);
};
class update_custom_account_authority_evaluator : public evaluator<update_custom_account_authority_evaluator>
class update_custom_account_authority_evaluator : public fee_handling_evaluator<update_custom_account_authority_evaluator>
{
public:
typedef custom_account_authority_update_operation operation_type;
@ -26,7 +26,7 @@ public:
object_id_type do_apply(const custom_account_authority_update_operation &o);
};
class delete_custom_account_authority_evaluator : public evaluator<delete_custom_account_authority_evaluator>
class delete_custom_account_authority_evaluator : public fee_handling_evaluator<delete_custom_account_authority_evaluator>
{
public:
typedef custom_account_authority_delete_operation operation_type;

View file

@ -28,7 +28,7 @@
namespace graphene { namespace chain {
class custom_evaluator : public evaluator<custom_evaluator>
class custom_evaluator : public fee_handling_evaluator<custom_evaluator>
{
public:
typedef custom_operation operation_type;

View file

@ -9,7 +9,7 @@ namespace graphene
namespace chain
{
class create_custom_permission_evaluator : public evaluator<create_custom_permission_evaluator>
class create_custom_permission_evaluator : public fee_handling_evaluator<create_custom_permission_evaluator>
{
public:
typedef custom_permission_create_operation operation_type;
@ -18,7 +18,7 @@ public:
object_id_type do_apply(const custom_permission_create_operation &o);
};
class update_custom_permission_evaluator : public evaluator<update_custom_permission_evaluator>
class update_custom_permission_evaluator : public fee_handling_evaluator<update_custom_permission_evaluator>
{
public:
typedef custom_permission_update_operation operation_type;
@ -27,7 +27,7 @@ public:
object_id_type do_apply(const custom_permission_update_operation &o);
};
class delete_custom_permission_evaluator : public evaluator<delete_custom_permission_evaluator>
class delete_custom_permission_evaluator : public fee_handling_evaluator<delete_custom_permission_evaluator>
{
public:
typedef custom_permission_delete_operation operation_type;

View file

@ -347,52 +347,49 @@ namespace graphene { namespace chain {
void init_genesis(const genesis_state_type& genesis_state = genesis_state_type());
/**
* @brief Register a new evaluator to the evaluator chain for its operation type
* @brief Register a new third party evaluator to the evaluator chain for its operation type
* @tparam EvaluatorType An evaluator type which will be used to evaluate its declared operation type
* @return If registering an evaluator for an operation that already has an evaluator, returns a handle for
* the newly added evaluator which can be used to delete it later.
* @return Returns a handle for the newly added evaluator which can be used to delete it later.
*
* This method registers a new evaluator type with tthe database. The evaluator specifies an operation type
* which it should be used to evaluate. The evaluator will be instantiated each time an operaton of the
* appropriate type is processed and used to evaluate the operation.
* This method registers a new third party evaluator type with the database. The evaluator specifies an
* operation type which it should be used to evaluate. A third party evaluator is an evaluator which belongs
* to code which is not part of official blockchain consensus. Consensus evaluators can only be added by the
* blockchain database itself. The evaluator will be instantiated each time an operaton of the appropriate
* type is processed and used to evaluate the operation.
*
* This method may be called more than once with multiple evaluator types for a given operation type. When
* multiple evaluator types are registered for a given operation type, they will all execute in the order of
* registration; however, only the return value of the first registered evaluator will be returned; return
* values of subsequently registered evaluators will be silently dropped.
* registration. Values returned by third party evaluators will be ignored.
*
* The first evaluator registered for a given operation type is permanent, and is the only evaluator which
* can return a value. Subsequent (auxiliary) evaluators for that operation type can be deleted at runtime
* by calling @ref delete_evaluator() with the evaluator_handle obtained when registering the evaluator.
* IMPORTANT: Third party evaluators must observe certain rules of etiquette:
* - No exceptions. Exceptions indicate the operation is invalid, and only consensus code can declare an
* operation invalid. Third party evaluators should not throw exceptions.
* - No yielding. Evaluators run as part of the core consensus pathway, and must not yield, to preserve the
* guarantees of consistency of the database.
* - Fast execution. Evaluators must be quick. If heavy processing is necessary, defer it until after the
* core consensus pathway has finished execution.
*/
template<typename EvaluatorType>
optional<op_evaluator::evaluator_handle> register_evaluator()
op_evaluator::evaluator_handle register_third_party_evaluator()
{
auto& eval_ptr = _operation_evaluators[operation::tag<typename EvaluatorType::operation_type>::value];
if (eval_ptr == nullptr)
eval_ptr = std::make_unique<op_evaluator_impl<EvaluatorType>>();
else
return eval_ptr->append_evaluator(std::make_unique<op_evaluator_impl<EvaluatorType>>());
return {};
return register_evaluator<EvaluatorType, true>(_third_party_operation_evaluators);
}
/**
* @brief Delete an auxiliary evaluator
* @brief Delete a third party evaluator
* @param handle The evaluator handle for the evaluator to delete, as returned by @ref register_evaluator
*
* Auxiliary evaluators, or the second and subsequent evaluators registered for a given operation type,
* can be deleted so that they no longer execute when operations of the relevant type are processed.
* Third party evaluators, or evaluators registered by non-consensus code for a given operation type, can be
* deleted so that they no longer execute when operations of the relevant type are processed.
*
* If it may be desired to delete an auxiliary evaluator, retain the evaluator handle obtained when the
* evaluator was initially registered and when it is necessary to delete the evaluator, pass the handle
* to this function.
* If it may be desired to delete an evaluator, retain the evaluator handle obtained when the evaluator was
* initially registered and when it is necessary to delete the evaluator, pass the handle to this function.
*
* The evaluator will have been deleted by the time this function returns.
*/
void delete_evaluator(op_evaluator::evaluator_handle&& handle)
void delete_third_party_evaluator(op_evaluator::evaluator_handle&& handle)
{
if ((uint64_t)handle.get_operation_type() < _operation_evaluators.size())
_operation_evaluators[handle.get_operation_type()]->delete_evaluator(std::move(handle));
delete_evaluator(_third_party_operation_evaluators, std::move(handle));
}
//////////////////// db_balance.cpp ////////////////////
@ -553,7 +550,7 @@ namespace graphene { namespace chain {
*/
/// Enable or disable tracking of votes of standby witnesses and committee members
inline void enable_standby_votes_tracking(bool enable) { _track_standby_votes = enable; }
protected:
protected:
//Mark pop_undo() as protected -- we do not want outside calling pop_undo(); it should call pop_block() instead
void pop_undo() { object_database::pop_undo(); }
void notify_applied_block( const signed_block& block );
@ -562,14 +559,49 @@ namespace graphene { namespace chain {
private:
optional<undo_database::session> _pending_tx_session;
vector< unique_ptr<op_evaluator> > _operation_evaluators;
vector< unique_ptr<op_evaluator> > _third_party_operation_evaluators;
vector< unique_ptr<op_evaluator> > _consensus_operation_evaluators;
template<typename EvaluatorType, bool DiscardExceptions>
op_evaluator::evaluator_handle register_evaluator(vector<unique_ptr<op_evaluator>>& registry) {
auto op_tag = operation::tag<typename EvaluatorType::operation_type>::value;
FC_ASSERT(registry.size() > (size_t)op_tag,
"Cannot register evaluator for operation type ${T}: operation type is too large.",
("T", op_tag));
auto& eval_ptr = registry[op_tag];
if (eval_ptr == nullptr) {
eval_ptr = std::make_unique<op_evaluator_impl<EvaluatorType, DiscardExceptions>>();
return {eval_ptr.get(), op_tag};
} else {
auto new_evaluator = std::make_unique<op_evaluator_impl<EvaluatorType, DiscardExceptions>>();
return eval_ptr->append_evaluator(std::move(new_evaluator));
}
}
template<typename EvaluatorType>
op_evaluator::evaluator_handle register_consensus_evaluator() {
return register_evaluator<EvaluatorType, false>(_consensus_operation_evaluators);
}
void delete_evaluator(vector<unique_ptr<op_evaluator>>& registry, op_evaluator::evaluator_handle&& handle)
{
if ((uint64_t)handle.get_operation_type() < registry.size()) {
auto& eval_ptr = registry[handle.get_operation_type()];
if (eval_ptr.get() == handle.pointer)
eval_ptr = eval_ptr->take_next();
else
eval_ptr->delete_evaluator(std::move(handle));
}
}
void delete_consensus_evaluator(op_evaluator::evaluator_handle&& handle)
{
delete_evaluator(_consensus_operation_evaluators, std::move(handle));
}
template<class Index>
vector<std::reference_wrapper<const typename Index::object_type>> sort_votable_objects(size_t count)const;
//////////////////// db_block.cpp ////////////////////
public:
public:
// these were formerly private, but they have a fairly well-defined API, so let's make them public
void apply_block( const signed_block& next_block, uint32_t skip = skip_nothing );
processed_transaction apply_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );

View file

@ -29,17 +29,17 @@
namespace graphene { namespace chain {
class database;
class generic_evaluator;
class consensus_evaluator;
class transaction_evaluation_state;
class account_object;
class account_statistics_object;
class asset_object;
class asset_dynamic_data_object;
class generic_evaluator
class consensus_evaluator
{
public:
virtual ~generic_evaluator(){}
virtual ~consensus_evaluator(){}
virtual int get_type()const = 0;
virtual operation_result start_evaluate(transaction_evaluation_state& eval_state, const operation& op, bool apply);
@ -132,8 +132,9 @@ namespace graphene { namespace chain {
evaluator_handle(const evaluator_handle&) = delete;
evaluator_handle& operator=(const evaluator_handle&) = delete;
friend class database;
friend class op_evaluator;
template<typename>
template<typename, bool>
friend class op_evaluator_impl;
// Pointer to the handled evaluator
@ -150,17 +151,22 @@ namespace graphene { namespace chain {
virtual ~op_evaluator(){}
virtual evaluator_handle append_evaluator(unique_ptr<op_evaluator> next_evaluator) = 0;
std::unique_ptr<op_evaluator> take_next() { return std::move(next_evaluator); }
virtual void delete_evaluator(evaluator_handle&& handle) {
FC_ASSERT(handle.pointer != this, "Cannot delete first element of evaluator chain!");
if (next_evaluator.get() == handle.pointer)
// Next evaluator in chain is the one to delete. Move its next pointer into ours, and unique_ptr will delete the one that's going away.
next_evaluator = std::move(next_evaluator->next_evaluator);
else
next_evaluator = next_evaluator->take_next();
else if (next_evaluator != nullptr)
next_evaluator->delete_evaluator(std::move(handle));
else
elog("ERROR: Attempted to delete evaluator, but did not find referenced evaluator in the chain");
}
virtual operation_result evaluate(transaction_evaluation_state& eval_state, const operation& op, bool apply) = 0;
};
template<typename T>
template<typename T, bool DiscardExceptions>
class op_evaluator_impl : public op_evaluator
{
public:
@ -174,16 +180,30 @@ namespace graphene { namespace chain {
}
virtual operation_result evaluate(transaction_evaluation_state& eval_state, const operation& op, bool apply = true) override
{
T eval;
auto result = eval.start_evaluate(eval_state, op, apply);
operation_result result;
try {
T eval;
result = eval.start_evaluate(eval_state, op, apply);
} catch (fc::exception_ptr e) {
if (DiscardExceptions)
elog("ERROR: Third party evaluator threw an exception. Discarding.", ("exception", e));
else
throw;
} catch (...) {
if (DiscardExceptions)
elog("ERROR: Third party evaluator threw an unknown exception type. Discarding.");
else
throw;
}
if (this->next_evaluator != nullptr)
this->next_evaluator->evaluate(eval_state, op, apply);
this->next_evaluator->evaluate(eval_state, op, apply);
return result;
}
};
template<typename DerivedEvaluator>
class evaluator : public generic_evaluator
class fee_handling_evaluator : public consensus_evaluator
{
public:
virtual int get_type()const override { return operation::tag<typename DerivedEvaluator::operation_type>::value; }
@ -221,4 +241,32 @@ namespace graphene { namespace chain {
return result;
}
};
template<typename DerivedEvaluator>
class third_party_evaluator {
protected:
transaction_evaluation_state* trx_state = nullptr;
database& db() {
FC_ASSERT(trx_state != nullptr, "Cannot get database: evaluator not initialized");
return trx_state->db();
}
public:
operation_result start_evaluate(transaction_evaluation_state& eval_state, const operation& op, bool apply) {
trx_state = &eval_state;
using Operation = typename DerivedEvaluator::operation_type;
Operation specific_operation = op.get<Operation>();
DerivedEvaluator& specific_evaluator = static_cast<DerivedEvaluator&>(*this);
operation_result result;
result = specific_evaluator.do_evaluate(specific_operation);
if (apply)
result = specific_evaluator.do_apply(specific_operation);
return result;
}
};
} }

View file

@ -31,7 +31,7 @@
namespace graphene { namespace chain {
class event_create_evaluator : public evaluator<event_create_evaluator>
class event_create_evaluator : public fee_handling_evaluator<event_create_evaluator>
{
public:
typedef event_create_operation operation_type;
@ -42,7 +42,7 @@ namespace graphene { namespace chain {
event_group_id_type event_group_id;
};
class event_update_evaluator : public evaluator<event_update_evaluator>
class event_update_evaluator : public fee_handling_evaluator<event_update_evaluator>
{
public:
typedef event_update_operation operation_type;
@ -53,7 +53,7 @@ namespace graphene { namespace chain {
event_group_id_type event_group_id;
};
class event_update_status_evaluator : public evaluator<event_update_status_evaluator>
class event_update_status_evaluator : public fee_handling_evaluator<event_update_status_evaluator>
{
public:
typedef event_update_status_operation operation_type;

View file

@ -31,7 +31,7 @@ namespace graphene { namespace chain {
class event_group_object;
class event_group_create_evaluator : public evaluator<event_group_create_evaluator>
class event_group_create_evaluator : public fee_handling_evaluator<event_group_create_evaluator>
{
public:
typedef event_group_create_operation operation_type;
@ -43,7 +43,7 @@ namespace graphene { namespace chain {
sport_id_type sport_id;
};
class event_group_update_evaluator : public evaluator<event_group_update_evaluator>
class event_group_update_evaluator : public fee_handling_evaluator<event_group_update_evaluator>
{
public:
typedef event_group_update_operation operation_type;
@ -55,7 +55,7 @@ namespace graphene { namespace chain {
sport_id_type sport_id;
};
class event_group_delete_evaluator : public evaluator<event_group_delete_evaluator>
class event_group_delete_evaluator : public fee_handling_evaluator<event_group_delete_evaluator>
{
public:
typedef event_group_delete_operation operation_type;

View file

@ -28,7 +28,7 @@
namespace graphene { namespace chain {
class ticket_purchase_evaluator : public evaluator<ticket_purchase_evaluator>
class ticket_purchase_evaluator : public fee_handling_evaluator<ticket_purchase_evaluator>
{
public:
typedef ticket_purchase_operation operation_type;
@ -40,7 +40,7 @@ namespace graphene { namespace chain {
const asset_dynamic_data_object* asset_dynamic_data;
};
class lottery_reward_evaluator : public evaluator<lottery_reward_evaluator>
class lottery_reward_evaluator : public fee_handling_evaluator<lottery_reward_evaluator>
{
public:
typedef lottery_reward_operation operation_type;
@ -52,7 +52,7 @@ namespace graphene { namespace chain {
const asset_dynamic_data_object* asset_dynamic_data;
};
class lottery_end_evaluator : public evaluator<lottery_end_evaluator>
class lottery_end_evaluator : public fee_handling_evaluator<lottery_end_evaluator>
{
public:
typedef lottery_end_operation operation_type;
@ -64,7 +64,7 @@ namespace graphene { namespace chain {
const asset_dynamic_data_object* asset_dynamic_data;
};
class sweeps_vesting_claim_evaluator : public evaluator<sweeps_vesting_claim_evaluator>
class sweeps_vesting_claim_evaluator : public fee_handling_evaluator<sweeps_vesting_claim_evaluator>
{
public:
typedef sweeps_vesting_claim_operation operation_type;

View file

@ -33,7 +33,7 @@ namespace graphene { namespace chain {
class call_order_object;
class limit_order_object;
class limit_order_create_evaluator : public evaluator<limit_order_create_evaluator>
class limit_order_create_evaluator : public fee_handling_evaluator<limit_order_create_evaluator>
{
public:
typedef limit_order_create_operation operation_type;
@ -55,7 +55,7 @@ namespace graphene { namespace chain {
const asset_object* _receive_asset = nullptr;
};
class limit_order_cancel_evaluator : public evaluator<limit_order_cancel_evaluator>
class limit_order_cancel_evaluator : public fee_handling_evaluator<limit_order_cancel_evaluator>
{
public:
typedef limit_order_cancel_operation operation_type;
@ -66,7 +66,7 @@ namespace graphene { namespace chain {
const limit_order_object* _order;
};
class call_order_update_evaluator : public evaluator<call_order_update_evaluator>
class call_order_update_evaluator : public fee_handling_evaluator<call_order_update_evaluator>
{
public:
typedef call_order_update_operation operation_type;

View file

@ -8,7 +8,7 @@
namespace graphene { namespace chain {
class nft_metadata_create_evaluator : public evaluator<nft_metadata_create_evaluator>
class nft_metadata_create_evaluator : public fee_handling_evaluator<nft_metadata_create_evaluator>
{
public:
typedef nft_metadata_create_operation operation_type;
@ -16,7 +16,7 @@ namespace graphene { namespace chain {
object_id_type do_apply( const nft_metadata_create_operation& o );
};
class nft_metadata_update_evaluator : public evaluator<nft_metadata_update_evaluator>
class nft_metadata_update_evaluator : public fee_handling_evaluator<nft_metadata_update_evaluator>
{
public:
typedef nft_metadata_update_operation operation_type;
@ -24,7 +24,7 @@ namespace graphene { namespace chain {
void_result do_apply( const nft_metadata_update_operation& o );
};
class nft_mint_evaluator : public evaluator<nft_mint_evaluator>
class nft_mint_evaluator : public fee_handling_evaluator<nft_mint_evaluator>
{
public:
typedef nft_mint_operation operation_type;
@ -32,7 +32,7 @@ namespace graphene { namespace chain {
object_id_type do_apply( const nft_mint_operation& o );
};
class nft_safe_transfer_from_evaluator : public evaluator<nft_safe_transfer_from_evaluator>
class nft_safe_transfer_from_evaluator : public fee_handling_evaluator<nft_safe_transfer_from_evaluator>
{
public:
typedef nft_safe_transfer_from_operation operation_type;
@ -40,7 +40,7 @@ namespace graphene { namespace chain {
object_id_type do_apply( const nft_safe_transfer_from_operation& o );
};
class nft_approve_evaluator : public evaluator<nft_approve_evaluator>
class nft_approve_evaluator : public fee_handling_evaluator<nft_approve_evaluator>
{
public:
typedef nft_approve_operation operation_type;
@ -48,7 +48,7 @@ namespace graphene { namespace chain {
object_id_type do_apply( const nft_approve_operation& o );
};
class nft_set_approval_for_all_evaluator : public evaluator<nft_set_approval_for_all_evaluator>
class nft_set_approval_for_all_evaluator : public fee_handling_evaluator<nft_set_approval_for_all_evaluator>
{
public:
typedef nft_set_approval_for_all_operation operation_type;

View file

@ -10,7 +10,7 @@ namespace graphene
namespace chain
{
class nft_lottery_token_purchase_evaluator : public evaluator<nft_lottery_token_purchase_evaluator>
class nft_lottery_token_purchase_evaluator : public fee_handling_evaluator<nft_lottery_token_purchase_evaluator>
{
public:
typedef nft_lottery_token_purchase_operation operation_type;
@ -19,7 +19,7 @@ namespace graphene
object_id_type do_apply(const nft_lottery_token_purchase_operation &o);
};
class nft_lottery_reward_evaluator : public evaluator<nft_lottery_reward_evaluator>
class nft_lottery_reward_evaluator : public fee_handling_evaluator<nft_lottery_reward_evaluator>
{
public:
typedef nft_lottery_reward_operation operation_type;
@ -28,7 +28,7 @@ namespace graphene
void_result do_apply(const nft_lottery_reward_operation &o);
};
class nft_lottery_end_evaluator : public evaluator<nft_lottery_end_evaluator>
class nft_lottery_end_evaluator : public fee_handling_evaluator<nft_lottery_end_evaluator>
{
public:
typedef nft_lottery_end_operation operation_type;

View file

@ -8,7 +8,7 @@ namespace graphene
namespace chain
{
class offer_evaluator : public evaluator<offer_evaluator>
class offer_evaluator : public fee_handling_evaluator<offer_evaluator>
{
public:
typedef offer_operation operation_type;
@ -17,7 +17,7 @@ namespace graphene
object_id_type do_apply(const offer_operation &o);
};
class bid_evaluator : public evaluator<bid_evaluator>
class bid_evaluator : public fee_handling_evaluator<bid_evaluator>
{
public:
typedef bid_operation operation_type;
@ -26,7 +26,7 @@ namespace graphene
void_result do_apply(const bid_operation &o);
};
class cancel_offer_evaluator : public evaluator<cancel_offer_evaluator>
class cancel_offer_evaluator : public fee_handling_evaluator<cancel_offer_evaluator>
{
public:
typedef cancel_offer_operation operation_type;
@ -35,7 +35,7 @@ namespace graphene
void_result do_apply(const cancel_offer_operation &o);
};
class finalize_offer_evaluator : public evaluator<finalize_offer_evaluator>
class finalize_offer_evaluator : public fee_handling_evaluator<finalize_offer_evaluator>
{
public:
typedef finalize_offer_operation operation_type;

View file

@ -46,7 +46,7 @@ namespace graphene { namespace chain {
void operator()( const son_report_down_operation &v );
};
class proposal_create_evaluator : public evaluator<proposal_create_evaluator>
class proposal_create_evaluator : public fee_handling_evaluator<proposal_create_evaluator>
{
public:
typedef proposal_create_operation operation_type;
@ -57,7 +57,7 @@ namespace graphene { namespace chain {
transaction _proposed_trx;
};
class proposal_update_evaluator : public evaluator<proposal_update_evaluator>
class proposal_update_evaluator : public fee_handling_evaluator<proposal_update_evaluator>
{
public:
typedef proposal_update_operation operation_type;
@ -71,7 +71,7 @@ namespace graphene { namespace chain {
bool _proposal_failed = false;
};
class proposal_delete_evaluator : public evaluator<proposal_delete_evaluator>
class proposal_delete_evaluator : public fee_handling_evaluator<proposal_delete_evaluator>
{
public:
typedef proposal_delete_operation operation_type;

View file

@ -7,7 +7,7 @@
namespace graphene { namespace chain {
class random_number_store_evaluator : public evaluator<random_number_store_evaluator>
class random_number_store_evaluator : public fee_handling_evaluator<random_number_store_evaluator>
{
public:
typedef random_number_store_operation operation_type;

View file

@ -5,7 +5,7 @@
namespace graphene { namespace chain {
class add_sidechain_address_evaluator : public evaluator<add_sidechain_address_evaluator>
class add_sidechain_address_evaluator : public fee_handling_evaluator<add_sidechain_address_evaluator>
{
public:
typedef sidechain_address_add_operation operation_type;
@ -14,7 +14,7 @@ public:
object_id_type do_apply(const sidechain_address_add_operation& o);
};
class update_sidechain_address_evaluator : public evaluator<update_sidechain_address_evaluator>
class update_sidechain_address_evaluator : public fee_handling_evaluator<update_sidechain_address_evaluator>
{
public:
typedef sidechain_address_update_operation operation_type;
@ -23,7 +23,7 @@ public:
object_id_type do_apply(const sidechain_address_update_operation& o);
};
class delete_sidechain_address_evaluator : public evaluator<delete_sidechain_address_evaluator>
class delete_sidechain_address_evaluator : public fee_handling_evaluator<delete_sidechain_address_evaluator>
{
public:
typedef sidechain_address_delete_operation operation_type;

View file

@ -5,7 +5,7 @@
namespace graphene { namespace chain {
class sidechain_transaction_create_evaluator : public evaluator<sidechain_transaction_create_evaluator>
class sidechain_transaction_create_evaluator : public fee_handling_evaluator<sidechain_transaction_create_evaluator>
{
public:
typedef sidechain_transaction_create_operation operation_type;
@ -14,7 +14,7 @@ public:
object_id_type do_apply(const sidechain_transaction_create_operation& o);
};
class sidechain_transaction_sign_evaluator : public evaluator<sidechain_transaction_sign_evaluator>
class sidechain_transaction_sign_evaluator : public fee_handling_evaluator<sidechain_transaction_sign_evaluator>
{
public:
typedef sidechain_transaction_sign_operation operation_type;
@ -23,7 +23,7 @@ public:
object_id_type do_apply(const sidechain_transaction_sign_operation& o);
};
class sidechain_transaction_send_evaluator : public evaluator<sidechain_transaction_send_evaluator>
class sidechain_transaction_send_evaluator : public fee_handling_evaluator<sidechain_transaction_send_evaluator>
{
public:
typedef sidechain_transaction_send_operation operation_type;
@ -32,7 +32,7 @@ public:
object_id_type do_apply(const sidechain_transaction_send_operation& o);
};
class sidechain_transaction_settle_evaluator : public evaluator<sidechain_transaction_settle_evaluator>
class sidechain_transaction_settle_evaluator : public fee_handling_evaluator<sidechain_transaction_settle_evaluator>
{
public:
typedef sidechain_transaction_settle_operation operation_type;

View file

@ -5,7 +5,7 @@
namespace graphene { namespace chain {
class create_son_evaluator : public evaluator<create_son_evaluator>
class create_son_evaluator : public fee_handling_evaluator<create_son_evaluator>
{
public:
typedef son_create_operation operation_type;
@ -14,7 +14,7 @@ public:
object_id_type do_apply(const son_create_operation& o);
};
class update_son_evaluator : public evaluator<update_son_evaluator>
class update_son_evaluator : public fee_handling_evaluator<update_son_evaluator>
{
public:
typedef son_update_operation operation_type;
@ -23,7 +23,7 @@ public:
object_id_type do_apply(const son_update_operation& o);
};
class deregister_son_evaluator : public evaluator<deregister_son_evaluator>
class deregister_son_evaluator : public fee_handling_evaluator<deregister_son_evaluator>
{
public:
typedef son_deregister_operation operation_type;
@ -32,7 +32,7 @@ public:
void_result do_apply(const son_deregister_operation& o);
};
class son_heartbeat_evaluator : public evaluator<son_heartbeat_evaluator>
class son_heartbeat_evaluator : public fee_handling_evaluator<son_heartbeat_evaluator>
{
public:
typedef son_heartbeat_operation operation_type;
@ -41,7 +41,7 @@ public:
object_id_type do_apply(const son_heartbeat_operation& o);
};
class son_report_down_evaluator : public evaluator<son_report_down_evaluator>
class son_report_down_evaluator : public fee_handling_evaluator<son_report_down_evaluator>
{
public:
typedef son_report_down_operation operation_type;
@ -50,7 +50,7 @@ public:
object_id_type do_apply(const son_report_down_operation& o);
};
class son_maintenance_evaluator : public evaluator<son_maintenance_evaluator>
class son_maintenance_evaluator : public fee_handling_evaluator<son_maintenance_evaluator>
{
public:
typedef son_maintenance_operation operation_type;

View file

@ -3,7 +3,7 @@
namespace graphene { namespace chain {
class create_son_wallet_deposit_evaluator : public evaluator<create_son_wallet_deposit_evaluator>
class create_son_wallet_deposit_evaluator : public fee_handling_evaluator<create_son_wallet_deposit_evaluator>
{
public:
typedef son_wallet_deposit_create_operation operation_type;
@ -12,7 +12,7 @@ public:
object_id_type do_apply(const son_wallet_deposit_create_operation& o);
};
class process_son_wallet_deposit_evaluator : public evaluator<process_son_wallet_deposit_evaluator>
class process_son_wallet_deposit_evaluator : public fee_handling_evaluator<process_son_wallet_deposit_evaluator>
{
public:
typedef son_wallet_deposit_process_operation operation_type;

View file

@ -4,7 +4,7 @@
namespace graphene { namespace chain {
class recreate_son_wallet_evaluator : public evaluator<recreate_son_wallet_evaluator>
class recreate_son_wallet_evaluator : public fee_handling_evaluator<recreate_son_wallet_evaluator>
{
public:
typedef son_wallet_recreate_operation operation_type;
@ -13,7 +13,7 @@ public:
object_id_type do_apply(const son_wallet_recreate_operation& o);
};
class update_son_wallet_evaluator : public evaluator<update_son_wallet_evaluator>
class update_son_wallet_evaluator : public fee_handling_evaluator<update_son_wallet_evaluator>
{
public:
typedef son_wallet_update_operation operation_type;

View file

@ -3,7 +3,7 @@
namespace graphene { namespace chain {
class create_son_wallet_withdraw_evaluator : public evaluator<create_son_wallet_withdraw_evaluator>
class create_son_wallet_withdraw_evaluator : public fee_handling_evaluator<create_son_wallet_withdraw_evaluator>
{
public:
typedef son_wallet_withdraw_create_operation operation_type;
@ -12,7 +12,7 @@ public:
object_id_type do_apply(const son_wallet_withdraw_create_operation& o);
};
class process_son_wallet_withdraw_evaluator : public evaluator<process_son_wallet_withdraw_evaluator>
class process_son_wallet_withdraw_evaluator : public fee_handling_evaluator<process_son_wallet_withdraw_evaluator>
{
public:
typedef son_wallet_withdraw_process_operation operation_type;

View file

@ -31,7 +31,7 @@ namespace graphene { namespace chain {
class sport_object;
class sport_create_evaluator : public evaluator<sport_create_evaluator>
class sport_create_evaluator : public fee_handling_evaluator<sport_create_evaluator>
{
public:
typedef sport_create_operation operation_type;
@ -40,7 +40,7 @@ namespace graphene { namespace chain {
object_id_type do_apply( const sport_create_operation& o );
};
class sport_update_evaluator : public evaluator<sport_update_evaluator>
class sport_update_evaluator : public fee_handling_evaluator<sport_update_evaluator>
{
public:
typedef sport_update_operation operation_type;
@ -49,7 +49,7 @@ namespace graphene { namespace chain {
void_result do_apply( const sport_update_operation& o );
};
class sport_delete_evaluator : public evaluator<sport_delete_evaluator>
class sport_delete_evaluator : public fee_handling_evaluator<sport_delete_evaluator>
{
public:
typedef sport_delete_operation operation_type;

View file

@ -5,7 +5,7 @@
namespace graphene { namespace chain {
class tournament_create_evaluator : public evaluator<tournament_create_evaluator>
class tournament_create_evaluator : public fee_handling_evaluator<tournament_create_evaluator>
{
public:
typedef tournament_create_operation operation_type;
@ -14,7 +14,7 @@ namespace graphene { namespace chain {
object_id_type do_apply( const tournament_create_operation& o );
};
class tournament_join_evaluator : public evaluator<tournament_join_evaluator>
class tournament_join_evaluator : public fee_handling_evaluator<tournament_join_evaluator>
{
private:
const tournament_object* _tournament_obj = nullptr;
@ -28,7 +28,7 @@ namespace graphene { namespace chain {
void_result do_apply( const tournament_join_operation& o );
};
class tournament_leave_evaluator : public evaluator<tournament_leave_evaluator>
class tournament_leave_evaluator : public fee_handling_evaluator<tournament_leave_evaluator>
{
private:
const tournament_object* _tournament_obj = nullptr;
@ -40,7 +40,7 @@ namespace graphene { namespace chain {
void_result do_apply( const tournament_leave_operation& o );
};
class game_move_evaluator : public evaluator<game_move_evaluator>
class game_move_evaluator : public fee_handling_evaluator<game_move_evaluator>
{
private:
const game_object* _game_obj = nullptr;

View file

@ -28,7 +28,7 @@
namespace graphene { namespace chain {
class transfer_evaluator : public evaluator<transfer_evaluator>
class transfer_evaluator : public fee_handling_evaluator<transfer_evaluator>
{
public:
typedef transfer_operation operation_type;
@ -37,7 +37,7 @@ namespace graphene { namespace chain {
void_result do_apply( const transfer_operation& o );
};
class override_transfer_evaluator : public evaluator<override_transfer_evaluator>
class override_transfer_evaluator : public fee_handling_evaluator<override_transfer_evaluator>
{
public:
typedef override_transfer_operation operation_type;

View file

@ -30,7 +30,7 @@ namespace graphene { namespace chain {
class vesting_balance_create_evaluator;
class vesting_balance_withdraw_evaluator;
class vesting_balance_create_evaluator : public evaluator<vesting_balance_create_evaluator>
class vesting_balance_create_evaluator : public fee_handling_evaluator<vesting_balance_create_evaluator>
{
public:
typedef vesting_balance_create_operation operation_type;
@ -39,7 +39,7 @@ class vesting_balance_create_evaluator : public evaluator<vesting_balance_create
object_id_type do_apply( const vesting_balance_create_operation& op );
};
class vesting_balance_withdraw_evaluator : public evaluator<vesting_balance_withdraw_evaluator>
class vesting_balance_withdraw_evaluator : public fee_handling_evaluator<vesting_balance_withdraw_evaluator>
{
public:
typedef vesting_balance_withdraw_operation operation_type;

View file

@ -27,7 +27,7 @@
namespace graphene { namespace chain {
class withdraw_permission_create_evaluator : public evaluator<withdraw_permission_create_evaluator>
class withdraw_permission_create_evaluator : public fee_handling_evaluator<withdraw_permission_create_evaluator>
{
public:
typedef withdraw_permission_create_operation operation_type;
@ -36,7 +36,7 @@ public:
object_id_type do_apply( const operation_type& op );
};
class withdraw_permission_claim_evaluator : public evaluator<withdraw_permission_claim_evaluator>
class withdraw_permission_claim_evaluator : public fee_handling_evaluator<withdraw_permission_claim_evaluator>
{
public:
typedef withdraw_permission_claim_operation operation_type;
@ -45,7 +45,7 @@ public:
void_result do_apply( const operation_type& op );
};
class withdraw_permission_update_evaluator : public evaluator<withdraw_permission_update_evaluator>
class withdraw_permission_update_evaluator : public fee_handling_evaluator<withdraw_permission_update_evaluator>
{
public:
typedef withdraw_permission_update_operation operation_type;
@ -54,7 +54,7 @@ public:
void_result do_apply( const operation_type& op );
};
class withdraw_permission_delete_evaluator : public evaluator<withdraw_permission_delete_evaluator>
class withdraw_permission_delete_evaluator : public fee_handling_evaluator<withdraw_permission_delete_evaluator>
{
public:
typedef withdraw_permission_delete_operation operation_type;

View file

@ -27,7 +27,7 @@
namespace graphene { namespace chain {
class witness_create_evaluator : public evaluator<witness_create_evaluator>
class witness_create_evaluator : public fee_handling_evaluator<witness_create_evaluator>
{
public:
typedef witness_create_operation operation_type;
@ -36,7 +36,7 @@ namespace graphene { namespace chain {
object_id_type do_apply( const witness_create_operation& o );
};
class witness_update_evaluator : public evaluator<witness_update_evaluator>
class witness_update_evaluator : public fee_handling_evaluator<witness_update_evaluator>
{
public:
typedef witness_update_operation operation_type;

View file

@ -26,7 +26,7 @@
namespace graphene { namespace chain {
class worker_create_evaluator : public evaluator<worker_create_evaluator>
class worker_create_evaluator : public fee_handling_evaluator<worker_create_evaluator>
{
public:
typedef worker_create_operation operation_type;

View file

@ -69,7 +69,7 @@ void_result limit_order_create_evaluator::do_evaluate(const limit_order_create_o
void limit_order_create_evaluator::pay_fee()
{
if( db().head_block_time() <= HARDFORK_445_TIME )
generic_evaluator::pay_fee();
consensus_evaluator::pay_fee();
else
_deferred_fee = core_fee_paid;
}

View file

@ -0,0 +1,129 @@
/*
* Copyright (c) 2015 Cryptonomex, Inc., 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 <boost/test/unit_test.hpp>
#include <graphene/chain/database.hpp>
#include "../common/database_fixture.hpp"
using namespace graphene::chain;
using namespace graphene::chain::test;
static std::string evaluators_ran;
template<int discriminant>
class test_evaluator : public third_party_evaluator<test_evaluator<discriminant>>
{
public:
using operation_type = custom_operation;
operation_result do_evaluate(const custom_operation&) {
evaluators_ran += std::to_string(discriminant);
return {};
}
operation_result do_apply(const custom_operation&) { return {}; }
};
BOOST_AUTO_TEST_SUITE(evaluator_tests)
BOOST_FIXTURE_TEST_CASE(evaluator_chain, database_fixture)
{ try {
// Required because custom_operation uses old fee > 0 check rather than fee >= 0 check... Fees required.
enable_fees();
// Create an account and give him tokens
ACTORS((nathaniel));
transfer(account_id_type(), nathaniel_id, asset(1000000));
generate_block();
// Create 4 different third party evaluators on custom operation
auto handle_0 = db.register_third_party_evaluator<test_evaluator<0>>();
auto handle_1 = db.register_third_party_evaluator<test_evaluator<1>>();
auto handle_2 = db.register_third_party_evaluator<test_evaluator<2>>();
auto handle_3 = db.register_third_party_evaluator<test_evaluator<3>>();
// Run a custom operation
custom_operation op;
op.payer = nathaniel_id;
op.fee.amount.value =
op.calculate_fee(db.get_global_properties().parameters.current_fees->get<custom_operation>()).value;
signed_transaction trx;
trx.operations = {op};
test::set_expiration(db, trx);
sign(trx, nathaniel_private_key);
db.push_transaction(trx);
// Check that all 4 evaluators ran, and reset record
BOOST_CHECK_EQUAL(evaluators_ran, "0123");
evaluators_ran.clear();
// Delete second evaluator in chain
db.delete_third_party_evaluator(std::move(handle_1));
// Run again and verify proper evaluator sequence
trx.expiration += 1;
trx.clear_signatures();
sign(trx, nathaniel_private_key);
db.push_transaction(trx);
BOOST_CHECK_EQUAL(evaluators_ran, "023");
evaluators_ran.clear();
// Delete first evaluator in chain
db.delete_third_party_evaluator(std::move(handle_0));
// Run again and verify proper evaluator sequence
trx.expiration += 1;
trx.clear_signatures();
sign(trx, nathaniel_private_key);
db.push_transaction(trx);
BOOST_CHECK_EQUAL(evaluators_ran, "23");
evaluators_ran.clear();
// Delete last evaluator in chain
db.delete_third_party_evaluator(std::move(handle_3));
// Run again and verify proper evaluator sequence
trx.expiration += 1;
trx.clear_signatures();
sign(trx, nathaniel_private_key);
db.push_transaction(trx);
BOOST_CHECK_EQUAL(evaluators_ran, "2");
evaluators_ran.clear();
// Delete only evaluator in chain
db.delete_third_party_evaluator(std::move(handle_2));
// Run again and verify none of our evaluators ran
trx.expiration += 1;
trx.clear_signatures();
sign(trx, nathaniel_private_key);
db.push_transaction(trx);
BOOST_TEST_CHECK(evaluators_ran.empty());
BOOST_CHECK_EQUAL(db.get_balance(nathaniel_id, asset_id_type()).amount.value, (1000000 - op.fee.amount*5).value);
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_SUITE_END()