Merge branch '434-api-fillin-proposed-op-fees' into develop
This commit is contained in:
commit
979d52c4c9
3 changed files with 97 additions and 10 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 //
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ namespace fc
|
|||
//template const graphene::chain::fee_schedule& smart_ref<graphene::chain::fee_schedule>::operator*() const;
|
||||
}
|
||||
|
||||
#define MAX_FEE_STABILIZATION_ITERATION 4
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
typedef fc::smart_ref<fee_schedule> smart_fee_schedule;
|
||||
|
|
@ -138,8 +140,23 @@ namespace graphene { namespace chain {
|
|||
asset fee_schedule::set_fee( operation& op, const price& core_exchange_rate )const
|
||||
{
|
||||
auto f = calculate_fee( op, core_exchange_rate );
|
||||
op.visit( set_fee_visitor( f ) );
|
||||
return f;
|
||||
auto f_max = f;
|
||||
for( int i=0; i<MAX_FEE_STABILIZATION_ITERATION; i++ )
|
||||
{
|
||||
op.visit( set_fee_visitor( f_max ) );
|
||||
auto f2 = calculate_fee( op, core_exchange_rate );
|
||||
if( f == f2 )
|
||||
break;
|
||||
f_max = std::max( f_max, f2 );
|
||||
f = f2;
|
||||
if( i == 0 )
|
||||
{
|
||||
// no need for warnings on later iterations
|
||||
wlog( "set_fee requires multiple iterations to stabilize with core_exchange_rate ${p} on operation ${op}",
|
||||
("p", core_exchange_rate) ("op", op) );
|
||||
}
|
||||
}
|
||||
return f_max;
|
||||
}
|
||||
|
||||
void chain_parameters::validate()const
|
||||
|
|
|
|||
Loading…
Reference in a new issue