database_api.cpp: Recursively evaluate proposal fees #434
This commit is contained in:
parent
a96fd62d03
commit
b03ac00b6c
2 changed files with 78 additions and 8 deletions
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#include <cctype>
|
||||
|
||||
#define GET_REQUIRED_FEES_MAX_RECURSION 4
|
||||
|
||||
namespace graphene { namespace app {
|
||||
|
||||
class database_api_impl;
|
||||
|
|
@ -116,7 +118,7 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
|||
bool verify_authority( const signed_transaction& trx )const;
|
||||
bool verify_account_authority( const string& name_or_id, const flat_set<public_key_type>& signers )const;
|
||||
processed_transaction validate_transaction( const signed_transaction& trx )const;
|
||||
vector<asset> get_required_fees( const vector<operation>& ops, asset_id_type id )const;
|
||||
vector< fc::variant > get_required_fees( const vector<operation>& ops, asset_id_type id )const;
|
||||
|
||||
// Proposed transactions
|
||||
vector<proposal_object> get_proposed_transactions( account_id_type id )const;
|
||||
|
|
@ -1355,18 +1357,86 @@ processed_transaction database_api_impl::validate_transaction( const signed_tran
|
|||
return _db.validate_transaction(trx);
|
||||
}
|
||||
|
||||
vector<asset> database_api::get_required_fees( const vector<operation>& ops, asset_id_type id )const
|
||||
vector< fc::variant > database_api::get_required_fees( const vector<operation>& ops, asset_id_type id )const
|
||||
{
|
||||
return my->get_required_fees( ops, id );
|
||||
}
|
||||
|
||||
vector<asset> database_api_impl::get_required_fees( const vector<operation>& ops, asset_id_type id )const
|
||||
/**
|
||||
* Container method for mutually recursive functions used to
|
||||
* implement get_required_fees() with potentially nested proposals.
|
||||
*/
|
||||
struct get_required_fees_helper
|
||||
{
|
||||
vector<asset> result;
|
||||
get_required_fees_helper(
|
||||
const fee_schedule& _current_fee_schedule,
|
||||
const price& _core_exchange_rate,
|
||||
uint32_t _max_recursion
|
||||
)
|
||||
: current_fee_schedule(_current_fee_schedule),
|
||||
core_exchange_rate(_core_exchange_rate),
|
||||
max_recursion(_max_recursion)
|
||||
{}
|
||||
|
||||
fc::variant set_op_fees( operation& op )
|
||||
{
|
||||
if( op.which() == operation::tag<proposal_create_operation>::value )
|
||||
{
|
||||
return set_proposal_create_op_fees( op );
|
||||
}
|
||||
else
|
||||
{
|
||||
asset fee = current_fee_schedule.set_fee( op, core_exchange_rate );
|
||||
fc::variant result;
|
||||
fc::to_variant( fee, result );
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
fc::variant set_proposal_create_op_fees( operation& proposal_create_op )
|
||||
{
|
||||
proposal_create_operation& op = proposal_create_op.get<proposal_create_operation>();
|
||||
std::pair< asset, fc::variants > result;
|
||||
for( op_wrapper& prop_op : op.proposed_ops )
|
||||
{
|
||||
FC_ASSERT( current_recursion < max_recursion );
|
||||
++current_recursion;
|
||||
result.second.push_back( set_op_fees( prop_op.op ) );
|
||||
--current_recursion;
|
||||
}
|
||||
// we need to do this on the boxed version, which is why we use
|
||||
// two mutually recursive functions instead of a visitor
|
||||
result.first = current_fee_schedule.set_fee( proposal_create_op, core_exchange_rate );
|
||||
fc::variant vresult;
|
||||
fc::to_variant( result, vresult );
|
||||
return vresult;
|
||||
}
|
||||
|
||||
const fee_schedule& current_fee_schedule;
|
||||
const price& core_exchange_rate;
|
||||
uint32_t max_recursion;
|
||||
uint32_t current_recursion = 0;
|
||||
};
|
||||
|
||||
vector< fc::variant > database_api_impl::get_required_fees( const vector<operation>& ops, asset_id_type id )const
|
||||
{
|
||||
vector< operation > _ops = ops;
|
||||
//
|
||||
// we copy the ops because we need to mutate an operation to reliably
|
||||
// determine its fee, see #435
|
||||
//
|
||||
|
||||
vector< fc::variant > result;
|
||||
result.reserve(ops.size());
|
||||
const asset_object& a = id(_db);
|
||||
for( const auto& op : ops )
|
||||
result.push_back( _db.current_fee_schedule().calculate_fee( op, a.options.core_exchange_rate ) );
|
||||
const asset_object& a = id(_db);
|
||||
get_required_fees_helper helper(
|
||||
_db.current_fee_schedule(),
|
||||
a.options.core_exchange_rate,
|
||||
GET_REQUIRED_FEES_MAX_RECURSION );
|
||||
for( operation& op : _ops )
|
||||
{
|
||||
result.push_back( helper.set_op_fees( op ) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -447,7 +447,7 @@ class database_api
|
|||
* For each operation calculate the required fee in the specified asset type. If the asset type does
|
||||
* not have a valid core_exchange_rate
|
||||
*/
|
||||
vector<asset> get_required_fees( const vector<operation>& ops, asset_id_type id )const;
|
||||
vector< fc::variant > get_required_fees( const vector<operation>& ops, asset_id_type id )const;
|
||||
|
||||
///////////////////////////
|
||||
// Proposed transactions //
|
||||
|
|
|
|||
Loading…
Reference in a new issue