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

bill discounted cpu usage rates for context free actions

上级 5f92f93e
......@@ -95,12 +95,12 @@
"name": "blockchain_parameters",
"base": "",
"fields": [
{"name":"max_block_net_usage", "type": "uint64"},
{"name":"max_block_net_usage", "type": "uint32"},
{"name":"target_block_net_usage_pct", "type": "uint32"},
{"name":"max_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_den", "type":"uint64"},
{"name":"context_free_discount_net_usage_num", "type":"uint32"},
{"name":"context_free_discount_net_usage_den", "type":"uint32"},
{"name":"max_block_cpu_usage", "type": "uint64"},
{"name":"target_block_cpu_usage_pct", "type": "uint32"},
{"name":"max_transaction_cpu_usage", "type":"uint32"},
......@@ -108,8 +108,8 @@
{"name":"base_per_action_cpu_usage", "type":"uint32"},
{"name":"base_setcode_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_den", "type":"uint64"},
{"name":"context_free_discount_cpu_usage_num", "type":"uint32"},
{"name":"context_free_discount_cpu_usage_den", "type":"uint32"},
{"name":"max_transaction_lifetime", "type":"uint32"},
{"name":"deferred_trx_expiration_window", "type":"uint32"},
{"name":"max_transaction_delay", "type":"uint32"},
......
......@@ -191,22 +191,22 @@ namespace eosiosystem {
producers_table producers_tbl( SystemAccount, SystemAccount );
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> base_per_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<uint64_t, 21> context_free_discount_net_usage_den;
std::array<uint32_t, 21> context_free_discount_net_usage_num;
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> max_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_setcode_cpu_usage;
std::array<uint32_t, 21> per_signature_cpu_usage;
std::array<uint64_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_num;
std::array<uint32_t, 21> context_free_discount_cpu_usage_den;
std::array<uint32_t, 21> max_transaction_lifetime;
std::array<uint32_t, 21> deferred_trx_expiration_window;
......
......@@ -36,6 +36,7 @@ action_trace apply_context::exec_one()
{
auto start = fc::time_point::now();
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 );
try {
const auto &a = control.get_account(receiver);
......@@ -63,6 +64,8 @@ action_trace apply_context::exec_one()
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);
t.trx_id = trx_context.id;
t.act = act;
......@@ -101,7 +104,7 @@ void apply_context::exec()
ncontext.context_free = true;
ncontext.exec();
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.inline_traces.emplace_back(ncontext.trace);
}
......@@ -352,7 +355,8 @@ void apply_context::reset_console() {
void apply_context::checktime(uint32_t 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() {
......
......@@ -611,6 +611,7 @@ class apply_context {
uint64_t cpu_usage = 0;
uint64_t total_cpu_usage = 0;
uint64_t cpu_usage_limit = 0;
private:
......
......@@ -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 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
uint64_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_num; ///< the numerator 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 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_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 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
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_num; ///< the numerator 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 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
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_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 uint64_t default_context_free_discount_net_usage_den = 100;
const static uint32_t default_context_free_discount_net_usage_num = 20; // TODO: is this reasonable?
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 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;
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_per_signature_cpu_usage = 100 * 1024; // TODO: is this reasonable?
const static uint64_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_num = 20;
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_deferred_trx_expiration_window = 10*60; // 10 minutes
......
......@@ -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_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_cpu_usage()const;
......
......@@ -116,7 +116,8 @@ namespace eosio { namespace chain {
&& 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_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)
......@@ -189,6 +190,38 @@ namespace eosio { namespace chain {
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 {
if( BOOST_UNLIKELY(net_usage > max_net) ) {
if( BOOST_UNLIKELY( net_limit_due_to_block ) ) {
......@@ -233,7 +266,15 @@ namespace eosio { namespace chain {
apply_context acontext( control, *this, a );
acontext.context_free = context_free;
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) );
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册