Refactor fee schedule for extensibility

This commit is contained in:
Daniel Larimer 2015-07-06 14:56:35 -04:00
parent 423eccf4a4
commit 8ccafe0f03
8 changed files with 87 additions and 40 deletions

View file

@ -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());

View file

@ -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);

View file

@ -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); }
}; };
///@} ///@}

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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;
} ); } );

View file

@ -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;
} }