Refactor fee schedule for extensibility
This commit is contained in:
parent
423eccf4a4
commit
8ccafe0f03
8 changed files with 87 additions and 40 deletions
|
|
@ -157,8 +157,7 @@ namespace detail {
|
||||||
|
|
||||||
auto nathan_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan")));
|
auto nathan_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan")));
|
||||||
genesis_state_type initial_state;
|
genesis_state_type initial_state;
|
||||||
fc::reflector<fee_schedule_type>::visit(
|
initial_state.initial_parameters.current_fees.set_all_fees(0);
|
||||||
fee_schedule_type::fee_set_visitor{initial_state.initial_parameters.current_fees, 0});
|
|
||||||
secret_hash_type::encoder enc;
|
secret_hash_type::encoder enc;
|
||||||
fc::raw::pack(enc, nathan_key);
|
fc::raw::pack(enc, nathan_key);
|
||||||
fc::raw::pack(enc, secret_hash_type());
|
fc::raw::pack(enc, secret_hash_type());
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,8 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
||||||
p.parameters = genesis_state.initial_parameters;
|
p.parameters = genesis_state.initial_parameters;
|
||||||
// Set fees to zero initially, so that genesis initialization needs not pay them
|
// Set fees to zero initially, so that genesis initialization needs not pay them
|
||||||
// We'll fix it at the end of the function
|
// We'll fix it at the end of the function
|
||||||
fc::reflector<fee_schedule_type>::visit(fee_schedule_type::fee_set_visitor{p.parameters.current_fees, 0});
|
p.parameters.current_fees.set_all_fees(0);
|
||||||
|
|
||||||
});
|
});
|
||||||
create<dynamic_global_property_object>( [&](dynamic_global_property_object& p) {
|
create<dynamic_global_property_object>( [&](dynamic_global_property_object& p) {
|
||||||
p.time = fc::time_point_sec(GRAPHENE_GENESIS_TIMESTAMP);
|
p.time = fc::time_point_sec(GRAPHENE_GENESIS_TIMESTAMP);
|
||||||
|
|
|
||||||
|
|
@ -1050,8 +1050,7 @@ namespace graphene { namespace chain {
|
||||||
account_id_type fee_payer()const { return fee_paying_account; }
|
account_id_type fee_payer()const { return fee_paying_account; }
|
||||||
void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>& owner_auth_set)const;
|
void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>& owner_auth_set)const;
|
||||||
void validate()const;
|
void validate()const;
|
||||||
share_type calculate_fee(const fee_schedule_type& k)const
|
share_type calculate_fee(const fee_schedule_type& k)const;
|
||||||
{ return k.proposal_delete_fee; }
|
|
||||||
void get_balance_delta(balance_accumulator& acc, const operation_result& result = asset())const { acc.adjust(fee_payer(), -fee); }
|
void get_balance_delta(balance_accumulator& acc, const operation_result& result = asset())const { acc.adjust(fee_payer(), -fee); }
|
||||||
};
|
};
|
||||||
///@}
|
///@}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
#include <fc/container/flat.hpp>
|
#include <fc/container/flat.hpp>
|
||||||
#include <fc/string.hpp>
|
#include <fc/string.hpp>
|
||||||
#include <fc/io/raw.hpp>
|
#include <fc/io/raw.hpp>
|
||||||
|
#include <fc/uint128.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
@ -312,35 +313,24 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
struct fee_schedule_type
|
struct fee_schedule_type
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @brief The fee_set_visitor struct sets all fees to a particular value in one fell swoop
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* @code
|
|
||||||
* fee_schedule_type sch;
|
|
||||||
* // Set all fees to 50
|
|
||||||
* fc::reflector<fee_schedule_type>::visit(fee_schedule_type::fee_set_visitor{sch, 50});
|
|
||||||
* @endcode
|
|
||||||
*/
|
|
||||||
struct fee_set_visitor {
|
|
||||||
fee_schedule_type& f;
|
|
||||||
uint32_t fee;
|
|
||||||
|
|
||||||
template<typename Member, typename Class, Member (Class::*member)>
|
|
||||||
void operator()(const char*)const
|
|
||||||
{
|
|
||||||
f.*member = fee;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The number of bytes to charge a data fee for
|
/// The number of bytes to charge a data fee for
|
||||||
const static int BYTES_PER_DATA_FEE = 1024;
|
const static int BYTES_PER_DATA_FEE = 1024;
|
||||||
|
|
||||||
template <class... Ts>
|
template <class... Ts>
|
||||||
uint32_t total_data_fee(Ts... ts)const {
|
uint32_t total_data_fee(Ts... ts)const {
|
||||||
return data_size(ts...) / BYTES_PER_DATA_FEE * data_fee;
|
return data_size(ts...) / BYTES_PER_DATA_FEE * data_fee;
|
||||||
|
// return ((fc::uint128(data_size(ts...)) * data_fee) / BYTES_PER_DATA_FEE).to_uint64();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard fees
|
||||||
|
*
|
||||||
|
* These fees are listed because they will be updated frequently and it is lower
|
||||||
|
* overhead than having a key/value map.
|
||||||
|
*/
|
||||||
|
///@{
|
||||||
uint64_t key_create_fee = 270300; ///< the cost to register a public key with the blockchain
|
uint64_t key_create_fee = 270300; ///< the cost to register a public key with the blockchain
|
||||||
uint64_t account_create_fee = 666666; ///< the cost to register the cheapest non-free account
|
uint64_t account_create_fee = 666666; ///< the cost to register the cheapest non-free account
|
||||||
uint64_t account_update_fee = 150000; ///< the cost to update an existing account
|
uint64_t account_update_fee = 150000; ///< the cost to update an existing account
|
||||||
|
|
@ -370,7 +360,6 @@ namespace graphene { namespace chain {
|
||||||
uint64_t witness_withdraw_pay_fee = 1500000; ///< fee for withdrawing witness pay
|
uint64_t witness_withdraw_pay_fee = 1500000; ///< fee for withdrawing witness pay
|
||||||
uint64_t transfer_fee = 2700000; ///< fee for transferring some asset
|
uint64_t transfer_fee = 2700000; ///< fee for transferring some asset
|
||||||
uint64_t limit_order_create_fee = 666666; ///< fee for placing a limit order in the markets
|
uint64_t limit_order_create_fee = 666666; ///< fee for placing a limit order in the markets
|
||||||
uint64_t limit_order_cancel_fee = 0; ///< fee for canceling a limit order
|
|
||||||
uint64_t call_order_fee = 800000; ///< fee for placing a call order in the markets
|
uint64_t call_order_fee = 800000; ///< fee for placing a call order in the markets
|
||||||
uint64_t publish_feed_fee = 10000; ///< fee for publishing a price feed
|
uint64_t publish_feed_fee = 10000; ///< fee for publishing a price feed
|
||||||
uint64_t data_fee = 13500000; ///< a price per BYTES_PER_DATA_FEE bytes of user data
|
uint64_t data_fee = 13500000; ///< a price per BYTES_PER_DATA_FEE bytes of user data
|
||||||
|
|
@ -380,22 +369,49 @@ namespace graphene { namespace chain {
|
||||||
uint64_t withdraw_permission_create_fee = 2700000; ///< the cost to create a withdraw permission
|
uint64_t withdraw_permission_create_fee = 2700000; ///< the cost to create a withdraw permission
|
||||||
uint64_t withdraw_permission_update_fee = 150000; ///< the cost to update a withdraw permission
|
uint64_t withdraw_permission_update_fee = 150000; ///< the cost to update a withdraw permission
|
||||||
uint64_t withdraw_permission_claim_fee = 700000; ///< the cost to withdraw from a withdraw permission
|
uint64_t withdraw_permission_claim_fee = 700000; ///< the cost to withdraw from a withdraw permission
|
||||||
uint64_t withdraw_permission_delete_fee = 0; ///< the cost to delete a withdraw permission
|
|
||||||
uint64_t vesting_balance_create_fee = 7000000;
|
uint64_t vesting_balance_create_fee = 7000000;
|
||||||
uint64_t vesting_balance_withdraw_fee = 2700000;
|
uint64_t vesting_balance_withdraw_fee = 2700000;
|
||||||
uint64_t worker_create_fee = 680000000; ///< the cost to create a new worker
|
uint64_t worker_create_fee = 680000000; ///< the cost to create a new worker
|
||||||
uint64_t assert_op_fee = 150000; ///< fee per assert operation
|
uint64_t assert_op_fee = 150000; ///< fee per assert operation
|
||||||
uint64_t proposal_create_fee = 7000000; ///< fee for creating a proposed transaction
|
uint64_t proposal_create_fee = 7000000; ///< fee for creating a proposed transaction
|
||||||
uint64_t proposal_update_fee = 1500000; ///< fee for adding or removing approval of a proposed transaction
|
uint64_t proposal_update_fee = 1500000; ///< fee for adding or removing approval of a proposed transaction
|
||||||
uint64_t proposal_delete_fee = 0; ///< fee for deleting a proposed transaction
|
|
||||||
uint64_t custom_operation_fee = 300000; ///< fee for a custom operation
|
uint64_t custom_operation_fee = 300000; ///< fee for a custom operation
|
||||||
|
///@{
|
||||||
|
|
||||||
|
void set_all_fees( uint64_t v );
|
||||||
|
|
||||||
|
/** Advanced Fees
|
||||||
|
*
|
||||||
|
* THese fields are reserved for future expansion of the fee schedule without breaking the
|
||||||
|
* protocol serialization.
|
||||||
|
*/
|
||||||
|
///@{
|
||||||
|
enum advanced_fee_id
|
||||||
|
{
|
||||||
|
withdraw_permission_delete_fee_id = 1, ///< the cost to delete a withdraw permission
|
||||||
|
proposal_delete_fee_id = 2, ///< fee for deleting a proposed transaction
|
||||||
|
limit_order_cancel_fee_id = 3 ///< fee for canceling a limit order
|
||||||
|
};
|
||||||
|
|
||||||
|
uint64_t get_advanced_fee( advanced_fee_id id )const
|
||||||
|
{
|
||||||
|
auto itr = advanced.find(id);
|
||||||
|
if( itr == advanced.end() ) return 0;
|
||||||
|
return itr->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t withdraw_permission_delete_fee()const { return get_advanced_fee( withdraw_permission_delete_fee_id ); }
|
||||||
|
|
||||||
|
|
||||||
|
flat_map<unsigned_int,uint64_t> advanced;
|
||||||
|
///@}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t data_size()const {
|
uint64_t data_size()const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
template <class T, class... Ts>
|
template <class T, class... Ts>
|
||||||
size_t data_size(T t, Ts... ts)const {
|
uint64_t data_size(T t, Ts... ts)const {
|
||||||
return fc::raw::pack_size(t) + data_size(ts...);
|
return fc::raw::pack_size(t) + data_size(ts...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -562,7 +578,6 @@ FC_REFLECT( graphene::chain::fee_schedule_type,
|
||||||
(witness_withdraw_pay_fee)
|
(witness_withdraw_pay_fee)
|
||||||
(transfer_fee)
|
(transfer_fee)
|
||||||
(limit_order_create_fee)
|
(limit_order_create_fee)
|
||||||
(limit_order_cancel_fee)
|
|
||||||
(call_order_fee)
|
(call_order_fee)
|
||||||
(publish_feed_fee)
|
(publish_feed_fee)
|
||||||
(asset_create_fee)
|
(asset_create_fee)
|
||||||
|
|
@ -578,7 +593,6 @@ FC_REFLECT( graphene::chain::fee_schedule_type,
|
||||||
(withdraw_permission_create_fee)
|
(withdraw_permission_create_fee)
|
||||||
(withdraw_permission_update_fee)
|
(withdraw_permission_update_fee)
|
||||||
(withdraw_permission_claim_fee)
|
(withdraw_permission_claim_fee)
|
||||||
(withdraw_permission_delete_fee)
|
|
||||||
(vesting_balance_create_fee)
|
(vesting_balance_create_fee)
|
||||||
(vesting_balance_withdraw_fee)
|
(vesting_balance_withdraw_fee)
|
||||||
(asset_global_settle_fee)
|
(asset_global_settle_fee)
|
||||||
|
|
@ -586,8 +600,12 @@ FC_REFLECT( graphene::chain::fee_schedule_type,
|
||||||
(assert_op_fee)
|
(assert_op_fee)
|
||||||
(proposal_create_fee)
|
(proposal_create_fee)
|
||||||
(proposal_update_fee)
|
(proposal_update_fee)
|
||||||
(proposal_delete_fee)
|
(advanced)
|
||||||
)
|
)
|
||||||
|
FC_REFLECT_ENUM( graphene::chain::fee_schedule_type::advanced_fee_id,
|
||||||
|
(withdraw_permission_delete_fee_id)
|
||||||
|
(proposal_delete_fee_id)
|
||||||
|
(limit_order_cancel_fee_id) )
|
||||||
|
|
||||||
FC_REFLECT( graphene::chain::chain_parameters,
|
FC_REFLECT( graphene::chain::chain_parameters,
|
||||||
(current_fees)
|
(current_fees)
|
||||||
|
|
|
||||||
|
|
@ -454,7 +454,7 @@ void limit_order_cancel_operation::validate()const
|
||||||
|
|
||||||
share_type limit_order_cancel_operation::calculate_fee(const fee_schedule_type& k) const
|
share_type limit_order_cancel_operation::calculate_fee(const fee_schedule_type& k) const
|
||||||
{
|
{
|
||||||
return k.limit_order_create_fee;
|
return k.get_advanced_fee(fee_schedule_type::limit_order_cancel_fee_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void call_order_update_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const
|
void call_order_update_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const
|
||||||
|
|
@ -555,6 +555,8 @@ void proposal_delete_operation::get_required_auth(flat_set<account_id_type>& act
|
||||||
else
|
else
|
||||||
active_auth_set.insert(fee_paying_account);
|
active_auth_set.insert(fee_paying_account);
|
||||||
}
|
}
|
||||||
|
share_type proposal_delete_operation::calculate_fee(const fee_schedule_type& k)const
|
||||||
|
{ return k.get_advanced_fee( fee_schedule_type::proposal_delete_fee_id ); }
|
||||||
|
|
||||||
void account_transfer_operation::validate()const
|
void account_transfer_operation::validate()const
|
||||||
{
|
{
|
||||||
|
|
@ -677,7 +679,7 @@ void withdraw_permission_delete_operation::validate() const
|
||||||
|
|
||||||
share_type withdraw_permission_delete_operation::calculate_fee(const fee_schedule_type& k) const
|
share_type withdraw_permission_delete_operation::calculate_fee(const fee_schedule_type& k) const
|
||||||
{
|
{
|
||||||
return k.withdraw_permission_delete_fee;
|
return k.get_advanced_fee( fee_schedule_type::withdraw_permission_delete_fee_id );
|
||||||
}
|
}
|
||||||
|
|
||||||
void withdraw_permission_create_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const
|
void withdraw_permission_create_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,35 @@ namespace graphene { namespace chain {
|
||||||
{
|
{
|
||||||
return p1.key_data != p2.key_data;
|
return p1.key_data != p2.key_data;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @brief The fee_set_visitor struct sets all fees to a particular value in one fell swoop
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* @code
|
||||||
|
* fee_schedule_type sch;
|
||||||
|
* // Set all fees to 50
|
||||||
|
* fc::reflector<fee_schedule_type>::visit(fee_schedule_type::fee_set_visitor{sch, 50});
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
struct fee_set_visitor {
|
||||||
|
fee_schedule_type& f;
|
||||||
|
uint64_t fee;
|
||||||
|
|
||||||
|
template<typename Member, typename Class, uint64_t (Class::*member)>
|
||||||
|
void operator()(const char*)const
|
||||||
|
{
|
||||||
|
f.*member = fee;
|
||||||
|
}
|
||||||
|
template<typename Member, typename Class, flat_map<unsigned_int,uint64_t> (Class::*member)>
|
||||||
|
void operator()(const char*)const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void fee_schedule_type::set_all_fees( uint64_t v )
|
||||||
|
{
|
||||||
|
fc::reflector<fee_schedule_type>::visit(fee_set_visitor{*this, v});
|
||||||
|
}
|
||||||
|
|
||||||
} } // graphene::chain
|
} } // graphene::chain
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ database_fixture::database_fixture()
|
||||||
genesis_state.initial_committee_candidates.push_back({name});
|
genesis_state.initial_committee_candidates.push_back({name});
|
||||||
genesis_state.initial_witness_candidates.push_back({name, delegate_priv_key.get_public_key(), secret});
|
genesis_state.initial_witness_candidates.push_back({name, delegate_priv_key.get_public_key(), secret});
|
||||||
}
|
}
|
||||||
fc::reflector<fee_schedule_type>::visit(fee_schedule_type::fee_set_visitor{genesis_state.initial_parameters.current_fees, 0});
|
genesis_state.initial_parameters.current_fees.set_all_fees(0);
|
||||||
db.init_genesis(genesis_state);
|
db.init_genesis(genesis_state);
|
||||||
ahplugin->plugin_startup();
|
ahplugin->plugin_startup();
|
||||||
mhplugin->plugin_startup();
|
mhplugin->plugin_startup();
|
||||||
|
|
@ -782,8 +782,7 @@ void database_fixture::enable_fees(
|
||||||
{
|
{
|
||||||
db.modify(global_property_id_type()(db), [fee](global_property_object& gpo)
|
db.modify(global_property_id_type()(db), [fee](global_property_object& gpo)
|
||||||
{
|
{
|
||||||
fc::reflector<fee_schedule_type>::visit(fee_schedule_type::fee_set_visitor{gpo.parameters.current_fees,
|
gpo.parameters.current_fees.set_all_fees(fee.value);
|
||||||
uint32_t(fee.value)});
|
|
||||||
gpo.parameters.current_fees.membership_annual_fee = 3*fee.value;
|
gpo.parameters.current_fees.membership_annual_fee = 3*fee.value;
|
||||||
gpo.parameters.current_fees.membership_lifetime_fee = 10*fee.value;
|
gpo.parameters.current_fees.membership_lifetime_fee = 10*fee.value;
|
||||||
} );
|
} );
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ genesis_state_type make_genesis() {
|
||||||
genesis_state.initial_committee_candidates.push_back({name});
|
genesis_state.initial_committee_candidates.push_back({name});
|
||||||
genesis_state.initial_witness_candidates.push_back({name, delegate_priv_key.get_public_key(), secret});
|
genesis_state.initial_witness_candidates.push_back({name, delegate_priv_key.get_public_key(), secret});
|
||||||
}
|
}
|
||||||
fc::reflector<fee_schedule_type>::visit(fee_schedule_type::fee_set_visitor{genesis_state.initial_parameters.current_fees, 0});
|
genesis_state.initial_parameters.current_fees.set_all_fees(0);
|
||||||
return genesis_state;
|
return genesis_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue