提交 2df8fc72 编写于 作者: A arhag

allow for block producer configurable leeway for cpu and net usage during...

allow for block producer configurable leeway for cpu and net usage during execution (still checks against new limits without the leeway at the end of the transaction)
上级 db0dbb10
......@@ -73,6 +73,7 @@
{"name":"target_block_net_usage_pct", "type": "uint32"},
{"name":"max_transaction_net_usage", "type":"uint32"},
{"name":"base_per_transaction_net_usage", "type":"uint32"},
{"name":"net_usage_leeway", "type":"uint32"},
{"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"},
......@@ -82,6 +83,7 @@
{"name":"base_per_action_cpu_usage", "type":"uint32"},
{"name":"base_setcode_cpu_usage", "type":"uint32"},
{"name":"per_signature_cpu_usage", "type":"uint32"},
{"name":"cpu_usage_leeway", "type":"uint32"},
{"name":"context_free_discount_cpu_usage_num", "type":"uint32"},
{"name":"context_free_discount_cpu_usage_den", "type":"uint32"},
{"name":"max_transaction_lifetime", "type":"uint32"},
......
......@@ -10,6 +10,7 @@ namespace eosio {
uint32_t target_block_net_usage_pct;
uint32_t max_transaction_net_usage;
uint32_t base_per_transaction_net_usage;
uint32_t net_usage_leeway;
uint64_t context_free_discount_net_usage_num;
uint64_t context_free_discount_net_usage_den;
......@@ -20,6 +21,7 @@ namespace eosio {
uint32_t base_per_action_cpu_usage;
uint32_t base_setcode_cpu_usage;
uint32_t per_signature_cpu_usage;
uint32_t cpu_usage_leeway;
uint64_t context_free_discount_cpu_usage_num;
uint64_t context_free_discount_cpu_usage_den;
......@@ -33,12 +35,12 @@ namespace eosio {
EOSLIB_SERIALIZE( blockchain_parameters,
(max_block_net_usage)(target_block_net_usage_pct)
(max_transaction_net_usage)(base_per_transaction_net_usage)
(max_transaction_net_usage)(base_per_transaction_net_usage)(net_usage_leeway)
(context_free_discount_net_usage_num)(context_free_discount_net_usage_den)
(max_block_cpu_usage)(target_block_cpu_usage_pct)
(max_transaction_cpu_usage)(base_per_transaction_cpu_usage)
(base_per_action_cpu_usage)(base_setcode_cpu_usage)(per_signature_cpu_usage)
(base_per_action_cpu_usage)(base_setcode_cpu_usage)(per_signature_cpu_usage)(cpu_usage_leeway)
(context_free_discount_cpu_usage_num)(context_free_discount_cpu_usage_den)
(max_transaction_lifetime)(deferred_trx_expiration_window)(max_transaction_delay)
......
......@@ -438,13 +438,13 @@ struct controller_impl {
transaction_context trx_context( self, dtrx, gto.trx_id );
transaction_trace_ptr trace = trx_context.trace;
flat_set<account_name> bill_to_accounts;
uint64_t max_cpu;
uint64_t max_cpu = 0;
bool abort_on_error = false;
try {
trx_context.init_for_deferred_trx( deadline, gto.published );
bill_to_accounts = trx_context.bill_to_accounts;
max_cpu = trx_context.max_cpu;
max_cpu = trx_context.initial_max_billable_cpu;
trx_context.exec(); // Automatically rounds up network and CPU usage in trace and bills payers if successful
trace->elapsed = fc::time_point::now() - start;
......
......@@ -21,6 +21,7 @@ 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
uint32_t net_usage_leeway;
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
......@@ -31,6 +32,7 @@ struct chain_config {
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
uint32_t cpu_usage_leeway;
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
......@@ -48,6 +50,7 @@ struct chain_config {
<< "Target Block Net Usage Percent: " << ((double)c.target_block_net_usage_pct / (double)config::percent_1) << "%, "
<< "Max Transaction Net Usage: " << c.max_transaction_net_usage << ", "
<< "Base Per-Transaction Net Usage: " << c.base_per_transaction_net_usage << ", "
<< "Net Usage Leeway: " << c.net_usage_leeway << ", "
<< "Context-Free Data Net Usage Discount: " << (double)c.context_free_discount_net_usage_num * 100.0 / (double)c.context_free_discount_net_usage_den << "% , "
<< "Max Block CPU Usage: " << c.max_block_cpu_usage << ", "
......@@ -57,6 +60,7 @@ struct chain_config {
<< "Base Per-Action CPU Usage: " << c.base_per_action_cpu_usage << ", "
<< "Base Setcode CPU Usage: " << c.base_setcode_cpu_usage << ", "
<< "Per-Signature CPU Usage: " << c.per_signature_cpu_usage << ", "
<< "CPU Usage Leeway: " << c.cpu_usage_leeway << ", "
<< "Context-Free Action CPU Usage Discount: " << (double)c.context_free_discount_cpu_usage_num * 100.0 / (double)c.context_free_discount_cpu_usage_den << "% , "
<< "Max Transaction Lifetime: " << c.max_transaction_lifetime << ", "
......@@ -76,12 +80,12 @@ inline bool operator!=(const chain_config& a, const chain_config& b) { return !(
FC_REFLECT(eosio::chain::chain_config,
(max_block_net_usage)(target_block_net_usage_pct)
(max_transaction_net_usage)(base_per_transaction_net_usage)
(max_transaction_net_usage)(base_per_transaction_net_usage)(net_usage_leeway)
(context_free_discount_net_usage_num)(context_free_discount_net_usage_den)
(max_block_cpu_usage)(target_block_cpu_usage_pct)
(max_transaction_cpu_usage)(base_per_transaction_cpu_usage)
(base_per_action_cpu_usage)(base_setcode_cpu_usage)(per_signature_cpu_usage)
(base_per_action_cpu_usage)(base_setcode_cpu_usage)(per_signature_cpu_usage)(cpu_usage_leeway)
(context_free_discount_cpu_usage_num)(context_free_discount_cpu_usage_den)
(max_transaction_lifetime)(deferred_trx_expiration_window)(max_transaction_delay)
......
......@@ -58,6 +58,7 @@ 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 uint32_t default_net_usage_leeway = 500; // TODO: is this reasonable?
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
......@@ -69,6 +70,7 @@ 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 uint32_t default_cpu_usage_leeway = 2048; // TODO: is this reasonable?
const static uint32_t default_context_free_discount_cpu_usage_num = 20;
const static uint32_t default_context_free_discount_cpu_usage_den = 100;
......
......@@ -21,6 +21,7 @@ struct genesis_state {
.target_block_net_usage_pct = config::default_target_block_net_usage_pct,
.max_transaction_net_usage = config::default_max_transaction_net_usage,
.base_per_transaction_net_usage = config::default_base_per_transaction_net_usage,
.net_usage_leeway = config::default_net_usage_leeway,
.context_free_discount_net_usage_num = config::default_context_free_discount_net_usage_num,
.context_free_discount_net_usage_den = config::default_context_free_discount_net_usage_den,
......@@ -31,6 +32,7 @@ struct genesis_state {
.base_per_action_cpu_usage = config::default_base_per_action_cpu_usage,
.base_setcode_cpu_usage = config::default_base_setcode_cpu_usage,
.per_signature_cpu_usage = config::default_per_signature_cpu_usage,
.cpu_usage_leeway = config::default_cpu_usage_leeway,
.context_free_discount_cpu_usage_num = config::default_context_free_discount_cpu_usage_num,
.context_free_discount_cpu_usage_den = config::default_context_free_discount_cpu_usage_den,
......
......@@ -67,8 +67,17 @@ namespace eosio { namespace chain {
vector<action_receipt> executed;
flat_set<account_name> bill_to_accounts;
flat_set<account_name> validate_ram_usage;
uint64_t max_net = 0; /// the maximum number of network usage bytes the transaction can consume
uint64_t max_cpu = 0; /// the maximum number of CPU instructions the transaction may consume
/// the maximum number of network usage bytes the transaction can consume (ignoring what billable accounts can pay and ignoring the remaining usage available in the block)
uint64_t max_net = 0;
uint64_t eager_net_limit = 0; ///< net usage limit (in bytes) to check against eagerly
/// the maximum number of virtual CPU instructions the transaction may consume (ignoring what billable accounts can pay and ignoring the remaining usage available in the block)
uint64_t max_cpu = 0;
uint64_t eager_cpu_limit = 0; ///< cpu usage limit (in virtual CPU instructions) to check against eagerly
/// the maximum number of virtual CPU instructions of the transaction that can be safely billed to the billable accounts
uint64_t initial_max_billable_cpu = 0;
fc::microseconds delay;
bool is_input = false;
bool apply_context_free = true;
......
......@@ -52,6 +52,25 @@ namespace eosio { namespace chain {
if( trx_specified_cpu_usage_limit > 0 )
max_cpu = std::min( max_cpu, trx_specified_cpu_usage_limit );
eager_net_limit = max_net;
eager_cpu_limit = max_cpu;
// Update usage values of accounts to reflect new time
auto& rl = control.get_mutable_resource_limits_manager();
rl.add_transaction_usage( bill_to_accounts, 0, 0, block_timestamp_type(control.pending_block_time()).slot );
uint64_t block_net_limit = rl.get_block_net_limit();
uint64_t block_cpu_limit = rl.get_block_cpu_limit();
if( block_net_limit < eager_net_limit ) {
eager_net_limit = block_net_limit;
net_limit_due_to_block = true;
}
if( block_cpu_limit < eager_cpu_limit ) {
eager_cpu_limit = block_cpu_limit;
cpu_limit_due_to_block = true;
}
// Initial billing for network usage
if( initial_net_usage > 0 )
add_net_usage( initial_net_usage );
......@@ -63,32 +82,43 @@ namespace eosio { namespace chain {
+ bill_to_accounts.size() * config::resource_processing_cpu_overhead_per_billed_account );
// Fails early if current CPU usage is already greater than the current limit (which may still go lower).
// Update usage values of accounts to reflect new time
auto& rl = control.get_mutable_resource_limits_manager();
rl.add_transaction_usage( bill_to_accounts, 0, 0, block_timestamp_type(control.pending_block_time()).slot );
eager_net_limit = max_net;
eager_cpu_limit = max_cpu;
net_limit_due_to_block = false;
cpu_limit_due_to_block = false;
// Lower limits to what the billed accounts can afford to pay
for( const auto& a : bill_to_accounts ) {
auto net_limit = rl.get_account_net_limit(a);
if( net_limit >= 0 )
max_net = std::min( max_net, static_cast<uint64_t>(net_limit) ); // reduce max_net to the amount the account is able to pay
eager_net_limit = std::min( eager_net_limit, static_cast<uint64_t>(net_limit) ); // reduce max_net to the amount the account is able to pay
auto cpu_limit = rl.get_account_cpu_limit(a);
if( cpu_limit >= 0 )
max_cpu = std::min( max_cpu, static_cast<uint64_t>(cpu_limit) ); // reduce max_cpu to the amount the account is able to pay
eager_cpu_limit = std::min( eager_cpu_limit, static_cast<uint64_t>(cpu_limit) ); // reduce max_cpu to the amount the account is able to pay
}
if( rl.get_block_net_limit() < max_net ) {
max_net = rl.get_block_net_limit();
initial_max_billable_cpu = eager_cpu_limit; // Possibly used for hard failure purposes
eager_net_limit += cfg.net_usage_leeway;
eager_net_limit = std::min(eager_net_limit, max_net);
eager_cpu_limit += cfg.cpu_usage_leeway;
eager_cpu_limit = std::min(eager_cpu_limit, max_cpu);
if( block_net_limit < eager_net_limit ) {
eager_net_limit = block_net_limit;
net_limit_due_to_block = true;
}
if( rl.get_block_cpu_limit() < max_cpu ) {
max_cpu = rl.get_block_cpu_limit();
if( block_cpu_limit < eager_cpu_limit ) {
eager_cpu_limit = block_cpu_limit;
cpu_limit_due_to_block = true;
}
// Round down network and CPU usage limits so that comparison to actual usage is more efficient
max_net = (max_net/8)*8; // Round down to nearest multiple of word size (8 bytes)
max_cpu = (max_cpu/1024)*1024; // Round down to nearest multiple of 1024
eager_net_limit = (eager_net_limit/8)*8; // Round down to nearest multiple of word size (8 bytes)
eager_cpu_limit = (eager_cpu_limit/1024)*1024; // Round down to nearest multiple of 1024
if( initial_net_usage > 0 )
check_net_usage(); // Fail early if current net usage is already greater than the calculated limit
check_cpu_usage(); // Fail early if current CPU usage is already greater than the calculated limit
......@@ -182,11 +212,30 @@ namespace eosio { namespace chain {
rl.verify_account_ram_usage( a );
}
eager_net_limit = max_net;
eager_cpu_limit = max_cpu;
net_limit_due_to_block = false;
cpu_limit_due_to_block = false;
// Lower limits to what the billed accounts can afford to pay
for( const auto& a : bill_to_accounts ) {
auto net_limit = rl.get_account_net_limit(a);
if( net_limit >= 0 )
eager_net_limit = std::min( eager_net_limit, static_cast<uint64_t>(net_limit) ); // reduce max_net to the amount the account is able to pay
auto cpu_limit = rl.get_account_cpu_limit(a);
if( cpu_limit >= 0 )
eager_cpu_limit = std::min( eager_cpu_limit, static_cast<uint64_t>(cpu_limit) ); // reduce max_cpu to the amount the account is able to pay
}
net_usage = ((net_usage + 7)/8)*8; // Round up to nearest multiple of word size (8 bytes)
cpu_usage = ((cpu_usage + 1023)/1024)*1024; // Round up to nearest multiple of 1024
control.get_mutable_resource_limits_manager()
.add_transaction_usage( bill_to_accounts, cpu_usage, net_usage,
block_timestamp_type(control.pending_block_time()).slot );
check_net_usage();
check_cpu_usage();
rl.add_transaction_usage( bill_to_accounts, cpu_usage, net_usage,
block_timestamp_type(control.pending_block_time()).slot ); // Should never fail
}
void transaction_context::squash() {
......@@ -226,7 +275,7 @@ namespace eosio { namespace chain {
}
void transaction_context::check_net_usage()const {
if( BOOST_UNLIKELY(net_usage > max_net) ) {
if( BOOST_UNLIKELY(net_usage > eager_net_limit) ) {
if( BOOST_UNLIKELY( net_limit_due_to_block ) ) {
EOS_THROW( tx_soft_net_usage_exceeded,
"not enough space left in block: ${actual_net_usage} > ${net_usage_limit}",
......@@ -240,7 +289,7 @@ namespace eosio { namespace chain {
}
void transaction_context::check_cpu_usage()const {
if( BOOST_UNLIKELY(cpu_usage > max_cpu) ) {
if( BOOST_UNLIKELY(cpu_usage > eager_cpu_limit) ) {
if( BOOST_UNLIKELY( cpu_limit_due_to_block ) ) {
EOS_THROW( tx_soft_cpu_usage_exceeded,
"not enough CPU usage allotment left in block: ${actual_cpu_usage} > ${cpu_usage_limit}",
......
......@@ -410,6 +410,7 @@ fc::variant regproducer_variant(const account_name& producer,
("target_block_net_usage_pct", config::default_target_block_net_usage_pct)
("max_transaction_net_usage", config::default_max_transaction_net_usage)
("base_per_transaction_net_usage", config::default_base_per_transaction_net_usage)
("net_usage_leeway", config::default_net_usage_leeway)
("context_free_discount_net_usage_num", config::default_context_free_discount_net_usage_num)
("context_free_discount_net_usage_den", config::default_context_free_discount_net_usage_den)
("max_block_cpu_usage", config::default_max_block_cpu_usage)
......@@ -419,6 +420,7 @@ fc::variant regproducer_variant(const account_name& producer,
("base_per_action_cpu_usage", config::default_base_per_action_cpu_usage)
("base_setcode_cpu_usage", config::default_base_setcode_cpu_usage)
("per_signature_cpu_usage", config::default_per_signature_cpu_usage)
("cpu_usage_leeway", config::default_cpu_usage_leeway)
("context_free_discount_cpu_usage_num", config::default_context_free_discount_cpu_usage_num)
("context_free_discount_cpu_usage_den", config::default_context_free_discount_cpu_usage_den)
("max_transaction_lifetime", config::default_max_trx_lifetime)
......
......@@ -145,6 +145,7 @@ public:
("target_block_net_usage_pct", 10 + n )
("max_transaction_net_usage", 1000000 + n )
("base_per_transaction_net_usage", 100 + n)
("net_usage_leeway", 500 + n )
("context_free_discount_net_usage_num", 1 + n )
("context_free_discount_net_usage_den", 100 + n )
("max_block_cpu_usage", 10000000 + n )
......@@ -154,6 +155,7 @@ public:
("base_per_action_cpu_usage", 100 + n)
("base_setcode_cpu_usage", 100 + n)
("per_signature_cpu_usage", 100 + n)
("cpu_usage_leeway", 2048 + n )
("context_free_discount_cpu_usage_num", 1 + n )
("context_free_discount_cpu_usage_den", 100 + n )
("max_transaction_lifetime", 3600 + n)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册