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>
|
#include <cctype>
|
||||||
|
|
||||||
|
#define GET_REQUIRED_FEES_MAX_RECURSION 4
|
||||||
|
|
||||||
namespace graphene { namespace app {
|
namespace graphene { namespace app {
|
||||||
|
|
||||||
class database_api_impl;
|
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_authority( const signed_transaction& trx )const;
|
||||||
bool verify_account_authority( const string& name_or_id, const flat_set<public_key_type>& signers )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;
|
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
|
// Proposed transactions
|
||||||
vector<proposal_object> get_proposed_transactions( account_id_type id )const;
|
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);
|
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 );
|
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());
|
result.reserve(ops.size());
|
||||||
const asset_object& a = id(_db);
|
const asset_object& a = id(_db);
|
||||||
for( const auto& op : ops )
|
get_required_fees_helper helper(
|
||||||
result.push_back( _db.current_fee_schedule().calculate_fee( op, a.options.core_exchange_rate ) );
|
_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;
|
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
|
* For each operation calculate the required fee in the specified asset type. If the asset type does
|
||||||
* not have a valid core_exchange_rate
|
* 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 //
|
// Proposed transactions //
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue