Progress #66: Audit calculate_fee implementations

I've audited all the calculate_fee impls and they all should be
reasonable at this point.

TODO: Set default fee values.
This commit is contained in:
Nathan Hourt 2015-06-23 14:19:34 -04:00
parent a0d2b18959
commit 08cba191c7
8 changed files with 331 additions and 239 deletions

View file

@ -249,8 +249,6 @@ void database::init_genesis(const genesis_state_type& genesis_state)
for( const auto& handout : genesis_state.allocation_targets ) for( const auto& handout : genesis_state.allocation_targets )
total_allocation += handout.weight; total_allocation += handout.weight;
fc::time_point start_time = fc::time_point::now();
for( const auto& handout : genesis_state.allocation_targets ) for( const auto& handout : genesis_state.allocation_targets )
{ {
asset amount(handout.weight); asset amount(handout.weight);
@ -298,10 +296,6 @@ void database::init_genesis(const genesis_state_type& genesis_state)
}); });
} }
} }
// fc::microseconds duration = fc::time_point::now() - start_time;
// ilog("Finished allocating to ${n} accounts in ${t} milliseconds.",
// ("n", genesis_state.allocation_targets.size())("t", duration.count() / 1000));
} }
flat_set<delegate_id_type> init_delegates; flat_set<delegate_id_type> init_delegates;

View file

@ -155,7 +155,8 @@ namespace graphene { namespace chain {
/** defines the assets that this asset may not be traded against in the market, must not overlap whitelist */ /** defines the assets that this asset may not be traded against in the market, must not overlap whitelist */
flat_set<asset_id_type> blacklist_markets; flat_set<asset_id_type> blacklist_markets;
/** data that describes the meaning/purpose of this asset, fee will be charged proportional to /**
* data that describes the meaning/purpose of this asset, fee will be charged proportional to
* size of description. * size of description.
*/ */
string description; string description;

View file

@ -224,6 +224,10 @@ namespace graphene { namespace chain {
/** /**
* @ingroup operations * @ingroup operations
* @brief Update an existing account
*
* This operation is used to update an existing account. It can be used to update the authorities, or adjust the options on the account.
* See @ref account_object::options_type for the options which may be updated.
*/ */
struct account_update_operation struct account_update_operation
{ {
@ -469,17 +473,15 @@ namespace graphene { namespace chain {
*/ */
struct transfer_operation struct transfer_operation
{ {
/** paid by the from account, may be of any asset for which there is a funded fee pool
**/
asset fee; asset fee;
/// Account to transfer asset from
account_id_type from; account_id_type from;
/// Account to transfer asset to
account_id_type to; account_id_type to;
/** the amount and asset type that will be withdrawn from account "from" and added to account "to" /// The amount of asset to transfer from @ref from to @ref to
*
**/
asset amount; asset amount;
/** user provided data encrypted to the memo key of the "to" account */ /// User provided data encrypted to the memo key of the "to" account
optional<memo_data> memo; optional<memo_data> memo;
account_id_type fee_payer()const { return from; } account_id_type fee_payer()const { return from; }
@ -695,8 +697,7 @@ namespace graphene { namespace chain {
void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const
{ active_auth_set.insert(fee_payer()); } { active_auth_set.insert(fee_payer()); }
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.asset_update_fee; }
void get_balance_delta(balance_accumulator& acc, const operation_result& result = asset())const void get_balance_delta(balance_accumulator& acc, const operation_result& result = asset())const
{ acc.adjust(fee_payer(), -fee); } { acc.adjust(fee_payer(), -fee); }
}; };
@ -800,14 +801,12 @@ namespace graphene { namespace chain {
account_id_type seller; account_id_type seller;
asset amount_to_sell; asset amount_to_sell;
asset min_to_receive; asset min_to_receive;
/**
* This order should expire if not filled by expiration /// The order will be removed from the books if not filled by expiration
*/ /// Upon expiration, all unsold asset will be returned to seller
time_point_sec expiration = time_point_sec::maximum(); time_point_sec expiration = time_point_sec::maximum();
/** if this flag is set the entire order must be filled or /// If this flag is set the entire order must be filled or the operation is rejected
* the operation is rejected.
*/
bool fill_or_kill = false; bool fill_or_kill = false;
pair<asset_id_type,asset_id_type> get_market()const pair<asset_id_type,asset_id_type> get_market()const
@ -847,7 +846,6 @@ namespace graphene { namespace chain {
void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const; void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)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;
void get_balance_delta(balance_accumulator& acc, const operation_result& result = asset())const void get_balance_delta(balance_accumulator& acc, const operation_result& result = asset())const
{ {
acc.adjust(fee_payer(), -fee); acc.adjust(fee_payer(), -fee);
@ -943,9 +941,9 @@ 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>& )const; void get_required_auth( flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>& )const;
void validate()const; void validate()const;
share_type calculate_fee( const fee_schedule_type& k )const { return 0; } share_type calculate_fee(const fee_schedule_type& k)const;
void get_balance_delta(balance_accumulator& acc, const operation_result& result = asset())const
void get_balance_delta( balance_accumulator& acc, const operation_result& result = asset())const { acc.adjust( fee_payer(), -fee ); } { acc.adjust(fee_payer(), -fee); }
}; };
/** /**
@ -981,7 +979,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 { return 0; } share_type calculate_fee(const fee_schedule_type& k)const;
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); }
}; };
@ -1006,7 +1004,8 @@ 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 { return 0; } 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); }
}; };
///@} ///@}
@ -1037,9 +1036,11 @@ namespace graphene { namespace chain {
void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const
{ active_auth_set.insert(fee_payer()); } { active_auth_set.insert(fee_payer()); }
void validate()const { FC_ASSERT( !"virtual operation" ); } void validate()const { FC_ASSERT( !"virtual operation" ); }
share_type calculate_fee( const fee_schedule_type& k )const { return share_type(); } share_type calculate_fee(const fee_schedule_type& k)const
// This is a virtual operation; there is no fee
{ return 0; }
void get_balance_delta(balance_accumulator& acc, const operation_result& result = asset())const { void get_balance_delta(balance_accumulator& acc, const operation_result& result = asset())const {
// acc.adjust( fee_payer(), -fee ); fee never actually entered the account, this is a virtual operation
acc.adjust(account_id, receives); acc.adjust(account_id, receives);
} }
}; };
@ -1198,16 +1199,15 @@ namespace graphene { namespace chain {
uint32_t vesting_seconds = 0; uint32_t vesting_seconds = 0;
}; };
struct ccd_vesting_policy_initializer struct cdd_vesting_policy_initializer
{ {
/** while coindays may accrue over time, none may be claimed before the start_claim time */ /** while coindays may accrue over time, none may be claimed before the start_claim time */
fc::time_point_sec start_claim; fc::time_point_sec start_claim;
uint32_t vesting_seconds = 0; uint32_t vesting_seconds = 0;
ccd_vesting_policy_initializer( uint32_t vest_sec = 0, fc::time_point_sec sc = fc::time_point_sec() ):start_claim(sc),vesting_seconds(vest_sec){} cdd_vesting_policy_initializer( uint32_t vest_sec = 0, fc::time_point_sec sc = fc::time_point_sec() ):start_claim(sc),vesting_seconds(vest_sec){}
}; };
typedef fc::static_variant< linear_vesting_policy_initializer, ccd_vesting_policy_initializer > vesting_policy_initializer; typedef fc::static_variant<linear_vesting_policy_initializer, cdd_vesting_policy_initializer> vesting_policy_initializer;
/** /**
* @brief Create a vesting balance. * @brief Create a vesting balance.
@ -1628,5 +1628,5 @@ FC_REFLECT_TYPENAME( graphene::chain::operation )
FC_REFLECT_TYPENAME( graphene::chain::operation_result ) FC_REFLECT_TYPENAME( graphene::chain::operation_result )
FC_REFLECT_TYPENAME( fc::flat_set<graphene::chain::vote_id_type> ) FC_REFLECT_TYPENAME( fc::flat_set<graphene::chain::vote_id_type> )
FC_REFLECT(graphene::chain::linear_vesting_policy_initializer, (start_claim)(begin_date)(vesting_seconds) ) FC_REFLECT(graphene::chain::linear_vesting_policy_initializer, (start_claim)(begin_date)(vesting_seconds) )
FC_REFLECT(graphene::chain::ccd_vesting_policy_initializer, (start_claim)(vesting_seconds) ) FC_REFLECT(graphene::chain::cdd_vesting_policy_initializer, (start_claim)(vesting_seconds) )
FC_REFLECT_TYPENAME( graphene::chain::vesting_policy_initializer ) FC_REFLECT_TYPENAME( graphene::chain::vesting_policy_initializer )

View file

@ -18,7 +18,6 @@
#pragma once #pragma once
#include <fc/container/flat_fwd.hpp> #include <fc/container/flat_fwd.hpp>
#include <fc/io/varint.hpp> #include <fc/io/varint.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/io/enum_type.hpp> #include <fc/io/enum_type.hpp>
#include <fc/crypto/sha224.hpp> #include <fc/crypto/sha224.hpp>
#include <fc/crypto/elliptic.hpp> #include <fc/crypto/elliptic.hpp>
@ -28,6 +27,7 @@
#include <fc/safe.hpp> #include <fc/safe.hpp>
#include <fc/container/flat.hpp> #include <fc/container/flat.hpp>
#include <fc/string.hpp> #include <fc/string.hpp>
#include <fc/io/raw.hpp>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <deque> #include <deque>
@ -340,42 +340,74 @@ namespace graphene { namespace chain {
memset((char*)this, 0, sizeof(*this)); memset((char*)this, 0, sizeof(*this));
} }
/// The number of bytes to charge a data fee for
const static int BYTES_PER_DATA_FEE = 1024;
template <class... Ts>
uint32_t total_data_fee(Ts... ts)const {
return data_size(ts...) / BYTES_PER_DATA_FEE * data_fee;
}
uint32_t key_create_fee; ///< the cost to register a public key with the blockchain uint32_t key_create_fee; ///< the cost to register a public key with the blockchain
uint32_t account_create_fee; ///< the cost to register the cheapest non-free account uint32_t account_create_fee; ///< the cost to register the cheapest non-free account
uint32_t account_len8_fee; uint32_t account_update_fee; ///< the cost to update an existing account
uint32_t account_transfer_fee; ///< the cost to transfer an account to a new owner
uint32_t account_len8up_fee;
uint32_t account_len7_fee; uint32_t account_len7_fee;
uint32_t account_len6_fee; uint32_t account_len6_fee;
uint32_t account_len5_fee; uint32_t account_len5_fee;
uint32_t account_len4_fee; uint32_t account_len4_fee;
uint32_t account_len3_fee; uint32_t account_len3_fee;
uint32_t account_len2_fee; uint32_t account_len2_fee;
uint32_t account_premium_fee; ///< accounts with premium names; i.e. @ref is_cheap_name returns false uint32_t asset_len3_fee;
uint32_t asset_len4_fee;
uint32_t asset_len5_fee;
uint32_t asset_len6_fee;
uint32_t asset_len7up_fee;
uint32_t account_whitelist_fee; ///< the fee to whitelist an account uint32_t account_whitelist_fee; ///< the fee to whitelist an account
uint32_t delegate_create_fee; ///< fixed fee for registering as a delegate; used to discourage frivioulous delegates uint32_t delegate_create_fee; ///< fixed fee for registering as a delegate; used to discourage frivolous delegates
uint32_t witness_withdraw_pay_fee; ///< fee for withdrawing witness pay uint32_t witness_withdraw_pay_fee; ///< fee for withdrawing witness pay
uint32_t transfer_fee; ///< fee for transferring some asset uint32_t transfer_fee; ///< fee for transferring some asset
uint32_t limit_order_fee; ///< fee for placing a limit order in the markets uint32_t limit_order_create_fee; ///< fee for placing a limit order in the markets
uint32_t limit_order_cancel_fee; ///< fee for canceling a limit order
uint32_t call_order_fee; ///< fee for placing a call order in the markets uint32_t call_order_fee; ///< fee for placing a call order in the markets
uint32_t publish_feed_fee; ///< fee for publishing a price feed uint32_t publish_feed_fee; ///< fee for publishing a price feed
uint32_t asset_create_fee; ///< the cost to register the cheapest asset uint32_t asset_create_fee; ///< the cost to register the cheapest asset
uint32_t asset_update_fee; ///< the cost to modify a registered asset uint32_t asset_update_fee; ///< the cost to modify a registered asset
uint32_t asset_issue_fee; ///< the cost to modify a registered asset uint32_t asset_issue_fee; ///< the cost to modify a registered asset
uint32_t asset_burn_fee; ///< the cost to burn an asset
uint32_t asset_fund_fee_pool_fee; ///< the cost to add funds to an asset's fee pool uint32_t asset_fund_fee_pool_fee; ///< the cost to add funds to an asset's fee pool
uint32_t asset_settle_fee; ///< the cost to trigger a forced settlement of a market-issued asset uint32_t asset_settle_fee; ///< the cost to trigger a forced settlement of a market-issued asset
uint32_t market_fee; ///< a percentage charged on market orders uint32_t market_fee; ///< a percentage charged on market orders
uint32_t transaction_fee; ///< a base price for every transaction uint32_t transaction_fee; ///< a base price for every transaction
uint32_t data_fee; ///< a price per 1024 bytes of user data uint32_t data_fee; ///< a price per BYTES_PER_DATA_FEE bytes of user data
uint32_t signature_fee; ///< a surcharge on transactions with more than 2 signatures. uint32_t signature_fee; ///< a surcharge on transactions with more than 2 signatures.
uint32_t global_parameters_update_fee; ///< the cost to update the global parameters uint32_t global_parameters_update_fee; ///< the cost to update the global parameters
uint32_t membership_annual_fee; ///< the annual cost of a membership subscription uint32_t membership_annual_fee; ///< the annual cost of a membership subscription
uint32_t membership_lifetime_fee; ///< the cost to upgrade to a lifetime member uint32_t membership_lifetime_fee; ///< the cost to upgrade to a lifetime member
uint32_t withdraw_permission_update_fee; ///< the cost to create/update a withdraw permission uint32_t withdraw_permission_create_fee; ///< the cost to create a withdraw permission
uint32_t withdraw_permission_update_fee; ///< the cost to update a withdraw permission
uint32_t withdraw_permission_claim_fee; ///< the cost to withdraw from a withdraw permission
uint32_t withdraw_permission_delete_fee; ///< the cost to delete a withdraw permission
uint32_t vesting_balance_create_fee; uint32_t vesting_balance_create_fee;
uint32_t vesting_balance_withdraw_fee; uint32_t vesting_balance_withdraw_fee;
uint32_t global_settle_fee; uint32_t global_settle_fee;
uint32_t worker_create_fee; ///< the cost to create a new worker uint32_t worker_create_fee; ///< the cost to create a new worker
uint32_t worker_delete_fee; ///< the cost to delete a worker uint32_t worker_delete_fee; ///< the cost to delete a worker
uint32_t assert_op_fee; ///< fee per assert operation uint32_t assert_op_fee; ///< fee per assert operation
uint32_t proposal_create_fee; ///< fee for creating a proposed transaction
uint32_t proposal_update_fee; ///< fee for adding or removing approval of a proposed transaction
uint32_t proposal_delete_fee; ///< fee for deleting a proposed transaction
uint32_t custom_operation_fee; ///< fee for a custom operation
protected:
size_t data_size()const {
return 0;
}
template <class T, class... Ts>
size_t data_size(T t, Ts... ts)const {
return fc::raw::pack_size(t) + data_size(ts...);
}
}; };
@ -517,24 +549,32 @@ FC_REFLECT_ENUM( graphene::chain::meta_info_object_type, (meta_account_object_ty
FC_REFLECT( graphene::chain::fee_schedule_type, FC_REFLECT( graphene::chain::fee_schedule_type,
(key_create_fee) (key_create_fee)
(account_create_fee) (account_create_fee)
(account_len8_fee) (account_update_fee)
(account_transfer_fee)
(account_len8up_fee)
(account_len7_fee) (account_len7_fee)
(account_len6_fee) (account_len6_fee)
(account_len5_fee) (account_len5_fee)
(account_len4_fee) (account_len4_fee)
(account_len3_fee) (account_len3_fee)
(account_len2_fee) (account_len2_fee)
(account_premium_fee) (asset_len3_fee)
(asset_len4_fee)
(asset_len5_fee)
(asset_len6_fee)
(asset_len7up_fee)
(account_whitelist_fee) (account_whitelist_fee)
(delegate_create_fee) (delegate_create_fee)
(witness_withdraw_pay_fee) (witness_withdraw_pay_fee)
(transfer_fee) (transfer_fee)
(limit_order_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)
(asset_update_fee) (asset_update_fee)
(asset_issue_fee) (asset_issue_fee)
(asset_burn_fee)
(asset_fund_fee_pool_fee) (asset_fund_fee_pool_fee)
(asset_settle_fee) (asset_settle_fee)
(market_fee) (market_fee)
@ -544,13 +584,19 @@ FC_REFLECT( graphene::chain::fee_schedule_type,
(global_parameters_update_fee) (global_parameters_update_fee)
(membership_annual_fee) (membership_annual_fee)
(membership_lifetime_fee) (membership_lifetime_fee)
(withdraw_permission_create_fee)
(withdraw_permission_update_fee) (withdraw_permission_update_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)
(global_settle_fee) (global_settle_fee)
(worker_create_fee) (worker_create_fee)
(worker_delete_fee) (worker_delete_fee)
(assert_op_fee) (assert_op_fee)
(proposal_create_fee)
(proposal_update_fee)
(proposal_delete_fee)
) )
FC_REFLECT( graphene::chain::chain_parameters, FC_REFLECT( graphene::chain::chain_parameters,

View file

@ -112,12 +112,13 @@ share_type account_create_operation::calculate_fee( const fee_schedule_type& sch
auto core_fee_required = schedule.account_create_fee; auto core_fee_required = schedule.account_create_fee;
uint32_t s = name.size(); uint32_t s = name.size();
if( is_cheap_name( name ) ) s = 63; if( is_cheap_name(name) )
s = 63;
FC_ASSERT( s >= 2 ); FC_ASSERT( s >= 2 );
if( s >= 8 && s < 63 ) if( s >= 8 && s < 63 )
core_fee_required = schedule.account_len8_fee; core_fee_required = schedule.account_len8up_fee;
else if( s == 7 ) else if( s == 7 )
core_fee_required = schedule.account_len7_fee; core_fee_required = schedule.account_len7_fee;
else if( s == 6 ) else if( s == 6 )
@ -131,11 +132,17 @@ share_type account_create_operation::calculate_fee( const fee_schedule_type& sch
else if( s == 2 ) else if( s == 2 )
core_fee_required = schedule.account_len2_fee; core_fee_required = schedule.account_len2_fee;
// Authorities and vote lists can be arbitrarily large, so charge a data fee for big ones
core_fee_required += schedule.total_data_fee(active, owner, options.votes);
return core_fee_required; return core_fee_required;
} }
share_type account_update_operation::calculate_fee( const fee_schedule_type& schedule )const share_type account_update_operation::calculate_fee( const fee_schedule_type& schedule )const
{ {
return schedule.account_create_fee; auto core_fee_required = schedule.account_update_fee + schedule.total_data_fee(owner, active);
if( new_options )
core_fee_required += schedule.total_data_fee(new_options->votes);
return core_fee_required;
} }
void account_update_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, void account_update_operation::get_required_auth(flat_set<account_id_type>& active_auth_set,
flat_set<account_id_type>& owner_auth_set) const flat_set<account_id_type>& owner_auth_set) const
@ -160,10 +167,21 @@ share_type asset_create_operation::calculate_fee( const fee_schedule_type& sched
{ {
auto core_fee_required = schedule.asset_create_fee; auto core_fee_required = schedule.asset_create_fee;
uint32_t s = symbol.size(); switch(symbol.size()) {
while( s <= 6 ) { core_fee_required *= 30; ++s; } case 3: core_fee_required += schedule.asset_len3_fee;
break;
case 4: core_fee_required += schedule.asset_len4_fee;
break;
case 5: core_fee_required += schedule.asset_len5_fee;
break;
case 6: core_fee_required += schedule.asset_len6_fee;
break;
default: core_fee_required += schedule.asset_len7up_fee;
}
// common_options contains several lists and a string. Charge fees for its size
core_fee_required += schedule.total_data_fee(common_options);
core_fee_required += ((fc::raw::pack_size(*this)*schedule.data_fee)/1024);
return core_fee_required; return core_fee_required;
} }
@ -171,9 +189,7 @@ share_type transfer_operation::calculate_fee( const fee_schedule_type& schedule
{ {
share_type core_fee_required = schedule.transfer_fee; share_type core_fee_required = schedule.transfer_fee;
if( memo ) if( memo )
{ core_fee_required += schedule.total_data_fee(memo->message);
core_fee_required += share_type((memo->message.size() * schedule.data_fee)/1024);
}
return core_fee_required; return core_fee_required;
} }
@ -290,7 +306,7 @@ void asset_update_operation::validate()const
share_type asset_update_operation::calculate_fee(const fee_schedule_type& k)const share_type asset_update_operation::calculate_fee(const fee_schedule_type& k)const
{ {
return k.asset_update_fee + ((fc::raw::pack_size(*this)*k.data_fee)/1024); return k.asset_update_fee + k.total_data_fee(new_options);
} }
void asset_burn_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const void asset_burn_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const
@ -307,7 +323,7 @@ void asset_burn_operation::validate()const
share_type asset_burn_operation::calculate_fee(const fee_schedule_type& k)const share_type asset_burn_operation::calculate_fee(const fee_schedule_type& k)const
{ {
return k.asset_issue_fee; return k.asset_burn_fee;
} }
void asset_issue_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const void asset_issue_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const
@ -330,7 +346,7 @@ share_type asset_issue_operation::calculate_fee( const fee_schedule_type& k )con
share_type delegate_create_operation::calculate_fee( const fee_schedule_type& k )const share_type delegate_create_operation::calculate_fee( const fee_schedule_type& k )const
{ {
return k.delegate_create_fee ; return k.delegate_create_fee + k.total_data_fee(url);
} }
void delegate_create_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const void delegate_create_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const
@ -376,7 +392,7 @@ void limit_order_create_operation::validate()const
share_type limit_order_create_operation::calculate_fee(const fee_schedule_type& k) const share_type limit_order_create_operation::calculate_fee(const fee_schedule_type& k) const
{ {
return k.limit_order_fee; return k.limit_order_create_fee;
} }
void limit_order_cancel_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const void limit_order_cancel_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const
@ -391,10 +407,9 @@ 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_fee; return k.limit_order_create_fee;
} }
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
{ {
active_auth_set.insert(funding_account); active_auth_set.insert(funding_account);
@ -433,6 +448,11 @@ void proposal_create_operation::validate() const
for( const auto& op : proposed_ops ) op.validate(); for( const auto& op : proposed_ops ) op.validate();
} }
share_type proposal_create_operation::calculate_fee(const fee_schedule_type& k) const
{
return k.proposal_create_fee + k.total_data_fee(proposed_ops);
}
void proposal_update_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, void proposal_update_operation::get_required_auth(flat_set<account_id_type>& active_auth_set,
flat_set<account_id_type>& owner_auth_set) const flat_set<account_id_type>& owner_auth_set) const
{ {
@ -470,6 +490,16 @@ void proposal_update_operation::validate() const
} }
} }
share_type proposal_update_operation::calculate_fee(const fee_schedule_type& k) const
{
return k.proposal_create_fee + k.total_data_fee(active_approvals_to_add,
active_approvals_to_remove,
owner_approvals_to_add,
owner_approvals_to_remove,
key_approvals_to_add,
key_approvals_to_remove);
}
void proposal_delete_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, void proposal_delete_operation::get_required_auth(flat_set<account_id_type>& active_auth_set,
flat_set<account_id_type>& owner_auth_set) const flat_set<account_id_type>& owner_auth_set) const
{ {
@ -491,7 +521,7 @@ void account_transfer_operation::get_required_auth(flat_set<account_id_type>& ac
share_type account_transfer_operation::calculate_fee( const fee_schedule_type& k )const share_type account_transfer_operation::calculate_fee( const fee_schedule_type& k )const
{ {
return k.transfer_fee; return k.account_transfer_fee;
} }
@ -545,7 +575,7 @@ void witness_create_operation::validate() const
share_type witness_create_operation::calculate_fee(const fee_schedule_type& k) const share_type witness_create_operation::calculate_fee(const fee_schedule_type& k) const
{ {
return k.delegate_create_fee; return k.delegate_create_fee + k.total_data_fee(url);
} }
void withdraw_permission_update_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const void withdraw_permission_update_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const
@ -579,11 +609,11 @@ void withdraw_permission_claim_operation::validate()const
FC_ASSERT( fee.amount >= 0 ); FC_ASSERT( fee.amount >= 0 );
} }
share_type withdraw_permission_claim_operation::calculate_fee( const fee_schedule_type& schedule )const share_type withdraw_permission_claim_operation::calculate_fee(const fee_schedule_type& k)const
{ {
share_type core_fee_required = schedule.transfer_fee; share_type core_fee_required = k.withdraw_permission_claim_fee;
if( memo ) if( memo )
core_fee_required += share_type((memo->message.size() * schedule.data_fee)/1024); core_fee_required += k.total_data_fee(memo->message);
return core_fee_required; return core_fee_required;
} }
@ -600,7 +630,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_update_fee; return k.withdraw_permission_delete_fee;
} }
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
@ -620,7 +650,7 @@ void withdraw_permission_create_operation::validate() const
share_type withdraw_permission_create_operation::calculate_fee(const fee_schedule_type& k) const share_type withdraw_permission_create_operation::calculate_fee(const fee_schedule_type& k) const
{ {
return k.withdraw_permission_update_fee; return k.withdraw_permission_create_fee;
} }
@ -684,6 +714,11 @@ void asset_update_feed_producers_operation::validate() const
FC_ASSERT( fee.amount >= 0 ); FC_ASSERT( fee.amount >= 0 );
} }
share_type asset_update_feed_producers_operation::calculate_fee(const fee_schedule_type &k) const
{
return k.asset_update_fee + k.total_data_fee(new_feed_producers);
}
void vesting_balance_create_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const void vesting_balance_create_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const
{ {
// owner's authorization isn't needed since this is effectively a transfer of value TO the owner // owner's authorization isn't needed since this is effectively a transfer of value TO the owner
@ -692,7 +727,8 @@ void vesting_balance_create_operation::get_required_auth(flat_set<account_id_typ
share_type vesting_balance_create_operation::calculate_fee(const fee_schedule_type& k)const share_type vesting_balance_create_operation::calculate_fee(const fee_schedule_type& k)const
{ {
return k.vesting_balance_create_fee; // We don't want to have custom inspection for each policy type; instead, charge a data fee for big ones
return k.vesting_balance_create_fee + k.total_data_fee(policy);
} }
void vesting_balance_create_operation::validate()const void vesting_balance_create_operation::validate()const
@ -766,7 +802,7 @@ void custom_operation::validate()const
} }
share_type custom_operation::calculate_fee(const fee_schedule_type& k)const share_type custom_operation::calculate_fee(const fee_schedule_type& k)const
{ {
return (data.size() * k.data_fee)/1024; return k.custom_operation_fee + k.total_data_fee(required_auths, data);
} }
void worker_create_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const void worker_create_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const
@ -786,7 +822,8 @@ void worker_create_operation::validate() const
share_type worker_create_operation::calculate_fee(const fee_schedule_type& k) const share_type worker_create_operation::calculate_fee(const fee_schedule_type& k) const
{ {
return k.worker_create_fee; // Charge data fees for excessively long name, URL, or large initializers
return k.worker_create_fee + k.total_data_fee(name, url, initializer);
} }
string memo_message::serialize() const string memo_message::serialize() const
@ -853,11 +890,12 @@ void assert_operation::get_required_auth(flat_set<account_id_type>& active_auth_
} }
/** /**
* The fee for assert operations is proportional to their size * The fee for assert operations is proportional to their size,
* but cheaper than a data fee because they require no storage
*/ */
share_type assert_operation::calculate_fee(const fee_schedule_type& k)const share_type assert_operation::calculate_fee(const fee_schedule_type& k)const
{ {
return (k.assert_op_fee * fc::raw::pack_size(*this)) / 1024; return std::max(size_t(1), fc::raw::pack_size(*this) / 1024) * k.assert_op_fee;
} }
} } // namespace graphene::chain } } // namespace graphene::chain

View file

@ -61,7 +61,7 @@ struct init_policy_visitor
p = policy; p = policy;
} }
void operator()( const ccd_vesting_policy_initializer& i )const void operator()( const cdd_vesting_policy_initializer& i )const
{ {
cdd_vesting_policy policy; cdd_vesting_policy policy;
policy.vesting_seconds = i.vesting_seconds; policy.vesting_seconds = i.vesting_seconds;

View file

@ -238,4 +238,17 @@ BOOST_AUTO_TEST_CASE( witness_rng_test_bits )
} FC_LOG_AND_RETHROW() } FC_LOG_AND_RETHROW()
} }
BOOST_AUTO_TEST_CASE( data_fees )
{
fee_schedule_type fs;
fs.data_fee = 10;
int x = 1489520937;
BOOST_CHECK_EQUAL(fs.total_data_fee(), 0);
BOOST_CHECK_EQUAL(fs.total_data_fee(fs), 0);
BOOST_CHECK_EQUAL(fs.total_data_fee(fs.key_create_fee), 0);
BOOST_CHECK_EQUAL(fs.total_data_fee(x, fs, authority()), 0);
auto keys = vector<private_key_type>(100, private_key_type::generate());
BOOST_CHECK_EQUAL(fs.total_data_fee(keys, x), (fc::raw::pack_size(keys) + fc::raw::pack_size(x)) / 1024 * 10);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View file

@ -1396,7 +1396,7 @@ BOOST_AUTO_TEST_CASE( vesting_balance_create_test )
op.owner = account_id_type(); op.owner = account_id_type();
op.amount = test_asset.amount( 100 ); op.amount = test_asset.amount( 100 );
//op.vesting_seconds = 60*60*24; //op.vesting_seconds = 60*60*24;
op.policy = ccd_vesting_policy_initializer{ 60*60*24 }; op.policy = cdd_vesting_policy_initializer{ 60*60*24 };
// Fee must be non-negative // Fee must be non-negative
REQUIRE_OP_VALIDATION_SUCCESS( op, fee, core.amount(1) ); REQUIRE_OP_VALIDATION_SUCCESS( op, fee, core.amount(1) );
@ -1485,7 +1485,7 @@ BOOST_AUTO_TEST_CASE( vesting_balance_withdraw_test )
create_op.creator = creator; create_op.creator = creator;
create_op.owner = owner; create_op.owner = owner;
create_op.amount = amount; create_op.amount = amount;
create_op.policy = ccd_vesting_policy_initializer( vesting_seconds ); create_op.policy = cdd_vesting_policy_initializer(vesting_seconds);
tx.operations.push_back( create_op ); tx.operations.push_back( create_op );
processed_transaction ptx = PUSH_TX( db, tx, ~0 ); processed_transaction ptx = PUSH_TX( db, tx, ~0 );