提交 38c05b84 编写于 作者: A arhag

bill discounted cpu usage rates for context free actions

上级 5f92f93e
...@@ -95,12 +95,12 @@ ...@@ -95,12 +95,12 @@
"name": "blockchain_parameters", "name": "blockchain_parameters",
"base": "", "base": "",
"fields": [ "fields": [
{"name":"max_block_net_usage", "type": "uint64"}, {"name":"max_block_net_usage", "type": "uint32"},
{"name":"target_block_net_usage_pct", "type": "uint32"}, {"name":"target_block_net_usage_pct", "type": "uint32"},
{"name":"max_transaction_net_usage", "type":"uint32"}, {"name":"max_transaction_net_usage", "type":"uint32"},
{"name":"base_per_transaction_net_usage", "type":"uint32"}, {"name":"base_per_transaction_net_usage", "type":"uint32"},
{"name":"context_free_discount_net_usage_num", "type":"uint64"}, {"name":"context_free_discount_net_usage_num", "type":"uint32"},
{"name":"context_free_discount_net_usage_den", "type":"uint64"}, {"name":"context_free_discount_net_usage_den", "type":"uint32"},
{"name":"max_block_cpu_usage", "type": "uint64"}, {"name":"max_block_cpu_usage", "type": "uint64"},
{"name":"target_block_cpu_usage_pct", "type": "uint32"}, {"name":"target_block_cpu_usage_pct", "type": "uint32"},
{"name":"max_transaction_cpu_usage", "type":"uint32"}, {"name":"max_transaction_cpu_usage", "type":"uint32"},
...@@ -108,8 +108,8 @@ ...@@ -108,8 +108,8 @@
{"name":"base_per_action_cpu_usage", "type":"uint32"}, {"name":"base_per_action_cpu_usage", "type":"uint32"},
{"name":"base_setcode_cpu_usage", "type":"uint32"}, {"name":"base_setcode_cpu_usage", "type":"uint32"},
{"name":"per_signature_cpu_usage", "type":"uint32"}, {"name":"per_signature_cpu_usage", "type":"uint32"},
{"name":"context_free_discount_cpu_usage_num", "type":"uint64"}, {"name":"context_free_discount_cpu_usage_num", "type":"uint32"},
{"name":"context_free_discount_cpu_usage_den", "type":"uint64"}, {"name":"context_free_discount_cpu_usage_den", "type":"uint32"},
{"name":"max_transaction_lifetime", "type":"uint32"}, {"name":"max_transaction_lifetime", "type":"uint32"},
{"name":"deferred_trx_expiration_window", "type":"uint32"}, {"name":"deferred_trx_expiration_window", "type":"uint32"},
{"name":"max_transaction_delay", "type":"uint32"}, {"name":"max_transaction_delay", "type":"uint32"},
......
...@@ -191,22 +191,22 @@ namespace eosiosystem { ...@@ -191,22 +191,22 @@ namespace eosiosystem {
producers_table producers_tbl( SystemAccount, SystemAccount ); producers_table producers_tbl( SystemAccount, SystemAccount );
auto idx = producers_tbl.template get_index<N(prototalvote)>(); auto idx = producers_tbl.template get_index<N(prototalvote)>();
std::array<uint64_t, 21> max_block_net_usage; std::array<uint32_t, 21> max_block_net_usage;
std::array<uint32_t, 21> target_block_net_usage_pct; std::array<uint32_t, 21> target_block_net_usage_pct;
std::array<uint32_t, 21> base_per_transaction_net_usage; std::array<uint32_t, 21> base_per_transaction_net_usage;
std::array<uint32_t, 21> max_transaction_net_usage; std::array<uint32_t, 21> max_transaction_net_usage;
std::array<uint64_t, 21> context_free_discount_net_usage_num; std::array<uint32_t, 21> context_free_discount_net_usage_num;
std::array<uint64_t, 21> context_free_discount_net_usage_den; std::array<uint32_t, 21> context_free_discount_net_usage_den;
std::array<uint64_t, 21> max_block_cpu_usage; std::array<uint32_t, 21> max_block_cpu_usage;
std::array<uint32_t, 21> target_block_cpu_usage_pct; std::array<uint32_t, 21> target_block_cpu_usage_pct;
std::array<uint32_t, 21> max_transaction_cpu_usage; std::array<uint32_t, 21> max_transaction_cpu_usage;
std::array<uint32_t, 21> base_per_transaction_cpu_usage; std::array<uint32_t, 21> base_per_transaction_cpu_usage;
std::array<uint32_t, 21> base_per_action_cpu_usage; std::array<uint32_t, 21> base_per_action_cpu_usage;
std::array<uint32_t, 21> base_setcode_cpu_usage; std::array<uint32_t, 21> base_setcode_cpu_usage;
std::array<uint32_t, 21> per_signature_cpu_usage; std::array<uint32_t, 21> per_signature_cpu_usage;
std::array<uint64_t, 21> context_free_discount_cpu_usage_num; std::array<uint32_t, 21> context_free_discount_cpu_usage_num;
std::array<uint64_t, 21> context_free_discount_cpu_usage_den; std::array<uint32_t, 21> context_free_discount_cpu_usage_den;
std::array<uint32_t, 21> max_transaction_lifetime; std::array<uint32_t, 21> max_transaction_lifetime;
std::array<uint32_t, 21> deferred_trx_expiration_window; std::array<uint32_t, 21> deferred_trx_expiration_window;
......
...@@ -36,6 +36,7 @@ action_trace apply_context::exec_one() ...@@ -36,6 +36,7 @@ action_trace apply_context::exec_one()
{ {
auto start = fc::time_point::now(); auto start = fc::time_point::now();
cpu_usage = 0; cpu_usage = 0;
cpu_usage_limit = trx_context.get_action_cpu_usage_limit( context_free );
checktime( control.get_global_properties().configuration.base_per_action_cpu_usage ); checktime( control.get_global_properties().configuration.base_per_action_cpu_usage );
try { try {
const auto &a = control.get_account(receiver); const auto &a = control.get_account(receiver);
...@@ -63,6 +64,8 @@ action_trace apply_context::exec_one() ...@@ -63,6 +64,8 @@ action_trace apply_context::exec_one()
r.auth_sequence[auth.actor] = next_auth_sequence( auth.actor ); r.auth_sequence[auth.actor] = next_auth_sequence( auth.actor );
} }
cpu_usage = trx_context.add_action_cpu_usage( cpu_usage, context_free );
action_trace t(r); action_trace t(r);
t.trx_id = trx_context.id; t.trx_id = trx_context.id;
t.act = act; t.act = act;
...@@ -101,7 +104,7 @@ void apply_context::exec() ...@@ -101,7 +104,7 @@ void apply_context::exec()
ncontext.context_free = true; ncontext.context_free = true;
ncontext.exec(); ncontext.exec();
fc::move_append( executed, move(ncontext.executed) ); fc::move_append( executed, move(ncontext.executed) );
total_cpu_usage += ncontext.total_cpu_usage; total_cpu_usage += ncontext.trace.total_cpu_usage;
trace.total_cpu_usage += ncontext.trace.total_cpu_usage; trace.total_cpu_usage += ncontext.trace.total_cpu_usage;
trace.inline_traces.emplace_back(ncontext.trace); trace.inline_traces.emplace_back(ncontext.trace);
} }
...@@ -352,7 +355,8 @@ void apply_context::reset_console() { ...@@ -352,7 +355,8 @@ void apply_context::reset_console() {
void apply_context::checktime(uint32_t instruction_count) { void apply_context::checktime(uint32_t instruction_count) {
cpu_usage += instruction_count; cpu_usage += instruction_count;
trx_context.add_cpu_usage_and_check_time( instruction_count ); EOS_ASSERT( BOOST_LIKELY(cpu_usage <= cpu_usage_limit), tx_cpu_usage_exceeded, "action cpu usage exceeded" );
trx_context.check_time();
} }
bytes apply_context::get_packed_transaction() { bytes apply_context::get_packed_transaction() {
......
...@@ -611,6 +611,7 @@ class apply_context { ...@@ -611,6 +611,7 @@ class apply_context {
uint64_t cpu_usage = 0; uint64_t cpu_usage = 0;
uint64_t total_cpu_usage = 0; uint64_t total_cpu_usage = 0;
uint64_t cpu_usage_limit = 0;
private: private:
......
...@@ -21,18 +21,18 @@ struct chain_config { ...@@ -21,18 +21,18 @@ struct chain_config {
uint32_t target_block_net_usage_pct; ///< the target percent (1% == 100, 100%= 10,000) of maximum net usage; exceeding this triggers congestion handling uint32_t target_block_net_usage_pct; ///< the target percent (1% == 100, 100%= 10,000) of maximum net usage; exceeding this triggers congestion handling
uint32_t max_transaction_net_usage; ///< the maximum objectively measured net usage that the chain will allow regardless of account limits uint32_t max_transaction_net_usage; ///< the maximum objectively measured net usage that the chain will allow regardless of account limits
uint32_t base_per_transaction_net_usage; ///< the base amount of net usage billed for a transaction to cover incidentals uint32_t base_per_transaction_net_usage; ///< the base amount of net usage billed for a transaction to cover incidentals
uint64_t context_free_discount_net_usage_num; ///< the numerator for the discount on net usage of context-free data uint32_t context_free_discount_net_usage_num; ///< the numerator for the discount on net usage of context-free data
uint64_t context_free_discount_net_usage_den; ///< the denominator for the discount on net usage of context-free data uint32_t context_free_discount_net_usage_den; ///< the denominator for the discount on net usage of context-free data
uint64_t max_block_cpu_usage; ///< the maxiumum cpu usage in instructions for a block uint32_t max_block_cpu_usage; ///< the maxiumum cpu usage in instructions for a block
uint32_t target_block_cpu_usage_pct; ///< the target percent (1% == 100, 100%= 10,000) of maximum cpu usage; exceeding this triggers congestion handling uint32_t target_block_cpu_usage_pct; ///< the target percent (1% == 100, 100%= 10,000) of maximum cpu usage; exceeding this triggers congestion handling
uint32_t max_transaction_cpu_usage; ///< the maximum objectively measured cpu usage that the chain will allow regardless of account limits uint32_t max_transaction_cpu_usage; ///< the maximum objectively measured cpu usage that the chain will allow regardless of account limits
uint32_t base_per_transaction_cpu_usage; ///< the base amount of cpu usage billed for a transaction to cover incidentals uint32_t base_per_transaction_cpu_usage; ///< the base amount of cpu usage billed for a transaction to cover incidentals
uint32_t base_per_action_cpu_usage; ///< the base amount of cpu usage billed for an action to cover incidentals uint32_t base_per_action_cpu_usage; ///< the base amount of cpu usage billed for an action to cover incidentals
uint32_t base_setcode_cpu_usage; ///< the base amount of cpu usage billed for a setcode action to cover compilation/etc uint32_t base_setcode_cpu_usage; ///< the base amount of cpu usage billed for a setcode action to cover compilation/etc
uint32_t per_signature_cpu_usage; ///< the cpu usage billed for every signature on a transaction uint32_t per_signature_cpu_usage; ///< the cpu usage billed for every signature on a transaction
uint64_t context_free_discount_cpu_usage_num; ///< the numerator for the discount on cpu usage of context-free actions uint32_t context_free_discount_cpu_usage_num; ///< the numerator for the discount on cpu usage of context-free actions
uint64_t context_free_discount_cpu_usage_den; ///< the denominator for the discount on cpu usage of context-free actions uint32_t context_free_discount_cpu_usage_den; ///< the denominator for the discount on cpu usage of context-free actions
uint32_t max_transaction_lifetime; ///< the maximum number of seconds that an input transaction's expiration can be ahead of the time of the block in which it is first included uint32_t max_transaction_lifetime; ///< the maximum number of seconds that an input transaction's expiration can be ahead of the time of the block in which it is first included
uint32_t deferred_trx_expiration_window; ///< the number of seconds after the time a deferred transaction can first execute until it expires uint32_t deferred_trx_expiration_window; ///< the number of seconds after the time a deferred transaction can first execute until it expires
......
...@@ -58,8 +58,8 @@ const static uint32_t default_max_block_net_usage = 1024 * 102 ...@@ -58,8 +58,8 @@ const static uint32_t default_max_block_net_usage = 1024 * 102
const static uint32_t default_target_block_net_usage_pct = 10 * percent_1; /// we target 1000 TPS const static uint32_t default_target_block_net_usage_pct = 10 * percent_1; /// we target 1000 TPS
const static uint32_t default_max_transaction_net_usage = default_max_block_net_usage / 10; const static uint32_t default_max_transaction_net_usage = default_max_block_net_usage / 10;
const static uint32_t default_base_per_transaction_net_usage = 12; // 12 bytes (11 bytes for worst case of transaction_receipt_header + 1 byte for static_variant tag) const static uint32_t default_base_per_transaction_net_usage = 12; // 12 bytes (11 bytes for worst case of transaction_receipt_header + 1 byte for static_variant tag)
const static uint64_t default_context_free_discount_net_usage_num = 20; // TODO: is this reasonable? const static uint32_t default_context_free_discount_net_usage_num = 20; // TODO: is this reasonable?
const static uint64_t default_context_free_discount_net_usage_den = 100; const static uint32_t default_context_free_discount_net_usage_den = 100;
const static uint32_t transaction_id_net_usage = 32; // 32 bytes for the size of a transaction id const static uint32_t transaction_id_net_usage = 32; // 32 bytes for the size of a transaction id
const static uint32_t default_max_block_cpu_usage = 100 * 1024 * 1024; /// at 500ms blocks and 20000instr trx, this enables ~10,000 TPS burst const static uint32_t default_max_block_cpu_usage = 100 * 1024 * 1024; /// at 500ms blocks and 20000instr trx, this enables ~10,000 TPS burst
...@@ -69,8 +69,8 @@ const static uint32_t default_base_per_transaction_cpu_usage = 512; ...@@ -69,8 +69,8 @@ const static uint32_t default_base_per_transaction_cpu_usage = 512;
const static uint32_t default_base_per_action_cpu_usage = 1024; const static uint32_t default_base_per_action_cpu_usage = 1024;
const static uint32_t default_base_setcode_cpu_usage = 2 * 1024 * 1024; /// overbilling cpu usage for setcode to cover incidental const static uint32_t default_base_setcode_cpu_usage = 2 * 1024 * 1024; /// overbilling cpu usage for setcode to cover incidental
const static uint32_t default_per_signature_cpu_usage = 100 * 1024; // TODO: is this reasonable? const static uint32_t default_per_signature_cpu_usage = 100 * 1024; // TODO: is this reasonable?
const static uint64_t default_context_free_discount_cpu_usage_num = 20; const static uint32_t default_context_free_discount_cpu_usage_num = 20;
const static uint64_t default_context_free_discount_cpu_usage_den = 100; const static uint32_t default_context_free_discount_cpu_usage_den = 100;
const static uint32_t default_max_trx_lifetime = 60*60; // 1 hour const static uint32_t default_max_trx_lifetime = 60*60; // 1 hour
const static uint32_t default_deferred_trx_expiration_window = 10*60; // 10 minutes const static uint32_t default_deferred_trx_expiration_window = 10*60; // 10 minutes
......
...@@ -31,7 +31,10 @@ namespace eosio { namespace chain { ...@@ -31,7 +31,10 @@ namespace eosio { namespace chain {
inline void add_net_usage( uint64_t u ) { net_usage += u; check_net_usage(); } inline void add_net_usage( uint64_t u ) { net_usage += u; check_net_usage(); }
inline void add_cpu_usage( uint64_t u ) { cpu_usage += u; check_cpu_usage(); } inline void add_cpu_usage( uint64_t u ) { cpu_usage += u; check_cpu_usage(); }
inline void add_cpu_usage_and_check_time( uint64_t u ) { check_time(); cpu_usage += u; check_cpu_usage(); }
/// returns cpu usage amount that was actually added
uint64_t add_action_cpu_usage( uint64_t u, bool context_free );
uint64_t get_action_cpu_usage_limit( bool context_free )const;
void check_net_usage()const; void check_net_usage()const;
void check_cpu_usage()const; void check_cpu_usage()const;
......
...@@ -116,7 +116,8 @@ namespace eosio { namespace chain { ...@@ -116,7 +116,8 @@ namespace eosio { namespace chain {
&& cfg.context_free_discount_net_usage_num < cfg.context_free_discount_net_usage_den ) && cfg.context_free_discount_net_usage_num < cfg.context_free_discount_net_usage_den )
{ {
discounted_size_for_pruned_data *= cfg.context_free_discount_net_usage_num; discounted_size_for_pruned_data *= cfg.context_free_discount_net_usage_num;
discounted_size_for_pruned_data /= cfg.context_free_discount_net_usage_den; discounted_size_for_pruned_data = ( discounted_size_for_pruned_data + cfg.context_free_discount_net_usage_den - 1)
/ cfg.context_free_discount_net_usage_den; // rounds up
} }
uint64_t initial_net_usage = static_cast<uint64_t>(cfg.base_per_transaction_net_usage) uint64_t initial_net_usage = static_cast<uint64_t>(cfg.base_per_transaction_net_usage)
...@@ -189,6 +190,38 @@ namespace eosio { namespace chain { ...@@ -189,6 +190,38 @@ namespace eosio { namespace chain {
undo_session.squash(); undo_session.squash();
} }
uint64_t transaction_context::add_action_cpu_usage( uint64_t u, bool context_free ) {
const auto& cfg = control.get_global_properties().configuration;
uint64_t discounted_cpu_usage = u;
if( context_free && cfg.context_free_discount_cpu_usage_den > 0
&& cfg.context_free_discount_cpu_usage_num < cfg.context_free_discount_cpu_usage_den )
{
discounted_cpu_usage *= cfg.context_free_discount_cpu_usage_num;
discounted_cpu_usage = ( discounted_cpu_usage + cfg.context_free_discount_cpu_usage_den - 1)
/ cfg.context_free_discount_cpu_usage_den; // rounds up
}
add_cpu_usage( discounted_cpu_usage );
return discounted_cpu_usage;
}
uint64_t transaction_context::get_action_cpu_usage_limit( bool context_free )const {
check_cpu_usage();
uint64_t diff = max_cpu - cpu_usage;
if( !context_free ) return diff;
const auto& cfg = control.get_global_properties().configuration;
uint64_t n = cfg.context_free_discount_cpu_usage_num;
uint64_t d = cfg.context_free_discount_cpu_usage_den;
if( d == 0 || n >= d ) return diff;
if( n == 0 ) return std::numeric_limits<uint64_t>::max();
return (diff * d)/n;
}
void transaction_context::check_net_usage()const { void transaction_context::check_net_usage()const {
if( BOOST_UNLIKELY(net_usage > max_net) ) { if( BOOST_UNLIKELY(net_usage > max_net) ) {
if( BOOST_UNLIKELY( net_limit_due_to_block ) ) { if( BOOST_UNLIKELY( net_limit_due_to_block ) ) {
...@@ -233,7 +266,15 @@ namespace eosio { namespace chain { ...@@ -233,7 +266,15 @@ namespace eosio { namespace chain {
apply_context acontext( control, *this, a ); apply_context acontext( control, *this, a );
acontext.context_free = context_free; acontext.context_free = context_free;
acontext.receiver = receiver; acontext.receiver = receiver;
acontext.exec();
try {
acontext.exec();
} catch( const tx_cpu_usage_exceeded& e ) {
add_action_cpu_usage( acontext.cpu_usage, context_free ); // Will update cpu_usage to latest value and throw appropriate exception
FC_ASSERT(false, "should not have reached here" );
} catch( ... ) {
throw;
}
fc::move_append(executed, move(acontext.executed) ); fc::move_append(executed, move(acontext.executed) );
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册