diff --git a/Docker/README.md b/Docker/README.md index ebcc9ba233c..fb9da669bdf 100644 --- a/Docker/README.md +++ b/Docker/README.md @@ -142,7 +142,7 @@ docker volume rm enuwallet-data-volume ### Docker Hub Docker Hub image available from [docker hub](https://hub.docker.com/r/eosio/eos/). -Replace the `docker-compose.yaml` file with the content below +Create a new `docker-compose.yaml` file with the content below ```bash version: "3" diff --git a/contracts/enumivo.system/enumivo.system.abi b/contracts/enumivo.system/enumivo.system.abi index 18032d09565..6957d6f3881 100644 --- a/contracts/enumivo.system/enumivo.system.abi +++ b/contracts/enumivo.system/enumivo.system.abi @@ -97,13 +97,7 @@ {"name":"max_block_cpu_usage", "type": "uint64"}, {"name":"target_block_cpu_usage_pct", "type": "uint32"}, {"name":"max_transaction_cpu_usage", "type":"uint32"}, - {"name":"base_per_transaction_cpu_usage", "type":"uint32"}, - {"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":"min_transaction_cpu_usage", "type":"uint32"}, {"name":"max_transaction_lifetime", "type":"uint32"}, {"name":"deferred_trx_expiration_window", "type":"uint32"}, {"name":"max_transaction_delay", "type":"uint32"}, diff --git a/contracts/enumivolib/privileged.hpp b/contracts/enumivolib/privileged.hpp index 0393ef95858..328ad4200d9 100644 --- a/contracts/enumivolib/privileged.hpp +++ b/contracts/enumivolib/privileged.hpp @@ -17,13 +17,7 @@ namespace eosio { uint32_t max_block_cpu_usage; uint32_t target_block_cpu_usage_pct; uint32_t max_transaction_cpu_usage; - uint32_t base_per_transaction_cpu_usage; - uint32_t base_per_action_cpu_usage; - uint32_t base_setcode_cpu_usage; - uint32_t per_signature_cpu_usage; - uint32_t cpu_usage_leeway; - uint32_t context_free_discount_cpu_usage_num; - uint32_t context_free_discount_cpu_usage_den; + uint32_t min_transaction_cpu_usage; uint32_t max_transaction_lifetime; uint32_t deferred_trx_expiration_window; @@ -39,9 +33,7 @@ namespace eosio { (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)(cpu_usage_leeway) - (context_free_discount_cpu_usage_num)(context_free_discount_cpu_usage_den) + (max_transaction_cpu_usage)(min_transaction_cpu_usage) (max_transaction_lifetime)(deferred_trx_expiration_window)(max_transaction_delay) (max_inline_action_size)(max_inline_action_depth) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 4cf30cfc811..f6215169550 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -686,7 +686,7 @@ struct controller_impl { try { auto onbtrx = std::make_shared( get_on_block_transaction() ); - push_transaction( onbtrx, fc::time_point::maximum(), true, config::default_min_transaction_cpu_usage_us); + push_transaction( onbtrx, fc::time_point::maximum(), true, self.get_global_properties().configuration.min_transaction_cpu_usage ); } catch ( ... ) { ilog( "on block transaction failed, but shouldn't impact block generation, system contract needs update" ); } diff --git a/libraries/chain/include/enumivo/chain/chain_config.hpp b/libraries/chain/include/enumivo/chain/chain_config.hpp index a3c70bb4117..1ba2039afc7 100644 --- a/libraries/chain/include/enumivo/chain/chain_config.hpp +++ b/libraries/chain/include/enumivo/chain/chain_config.hpp @@ -25,16 +25,10 @@ struct chain_config { 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 - uint32_t max_block_cpu_usage; ///< the maxiumum cpu usage in instructions for a block + uint32_t max_block_cpu_usage; ///< the maxiumum billable cpu usage (in microseconds) 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 - 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 + uint32_t max_transaction_cpu_usage; ///< the maximum billable cpu usage (in microseconds) that the chain will allow regardless of account limits + uint32_t min_transaction_cpu_usage; ///< the minimum billable cpu usage (in microseconds) that the chain requires 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 @@ -56,12 +50,7 @@ struct chain_config { << "Max Block CPU Usage: " << c.max_block_cpu_usage << ", " << "Target Block CPU Usage Percent: " << ((double)c.target_block_cpu_usage_pct / (double)config::percent_1) << "%, " << "Max Transaction CPU Usage: " << c.max_transaction_cpu_usage << ", " - << "Base Per-Transaction CPU Usage: " << c.base_per_transaction_cpu_usage << ", " - << "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 << "% , " + << "Min Transaction CPU Usage: " << c.min_transaction_cpu_usage << ", " << "Max Transaction Lifetime: " << c.max_transaction_lifetime << ", " << "Deferred Transaction Expiration Window: " << c.deferred_trx_expiration_window << ", " @@ -84,9 +73,7 @@ FC_REFLECT(eosio::chain::chain_config, (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)(cpu_usage_leeway) - (context_free_discount_cpu_usage_num)(context_free_discount_cpu_usage_den) + (max_transaction_cpu_usage)(min_transaction_cpu_usage) (max_transaction_lifetime)(deferred_trx_expiration_window)(max_transaction_delay) (max_inline_action_size)(max_inline_action_depth) diff --git a/libraries/chain/include/enumivo/chain/config.hpp b/libraries/chain/include/enumivo/chain/config.hpp index b603b6f1b04..f7e696c6ef7 100644 --- a/libraries/chain/include/enumivo/chain/config.hpp +++ b/libraries/chain/include/enumivo/chain/config.hpp @@ -65,31 +65,17 @@ const static uint32_t transaction_id_net_usage = 32; // 32 const static uint32_t default_max_block_cpu_usage = 100'000; /// max block cpu usage in microseconds const static uint32_t default_target_block_cpu_usage_pct = 5 * percent_1; /// target 1000 TPS -const static uint32_t default_max_transaction_cpu_usage = default_max_block_cpu_usage; -const static uint32_t default_min_transaction_cpu_usage_us = 100; /// 10000 TPS equiv -const static uint32_t default_base_per_transaction_cpu_usage = 512; // TODO: is this reasonable? -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; +const static uint32_t default_max_transaction_cpu_usage = default_max_block_cpu_usage / 2; /// max trx cpu usage in microseconds +const static uint32_t default_min_transaction_cpu_usage = 100; /// min trx cpu usage in microseconds (10000 TPS equiv) 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 -//static const uint32_t deferred_trx_expiration_window_ms = 10*60*1000l; // TODO: make 10 minutes configurable by system const static uint32_t default_max_trx_delay = 45*24*3600; // 45 days const static uint32_t default_max_inline_action_size = 4 * 1024; // 4 KB const static uint16_t default_max_inline_action_depth = 4; const static uint16_t default_max_auth_depth = 6; const static uint32_t default_max_gen_trx_count = 16; -const static uint32_t base_check_authorization_cpu_per_authorization = 64; // TODO: is this reasonable? -const static uint32_t base_authority_checker_cpu_per_permission = 128; // TODO: is this reasonable? -const static uint32_t resource_processing_cpu_overhead_per_billed_account = 256; // TODO: is this reasonable? -const static uint32_t determine_payers_cpu_overhead_per_authorization = 64; // TODO: is this reasonable? -const static uint32_t ram_usage_validation_overhead_per_account = 64; // TODO: is this reasonable? - const static uint32_t fixed_net_overhead_of_packed_trx = 16; // TODO: is this reasonable? const static uint32_t fixed_overhead_shared_vector_ram_bytes = 16; ///< overhead accounts for fixed portion of size of shared_vector field diff --git a/libraries/chain/include/enumivo/chain/genesis_state.hpp b/libraries/chain/include/enumivo/chain/genesis_state.hpp index 3a9f2deb752..911d3e07de5 100644 --- a/libraries/chain/include/enumivo/chain/genesis_state.hpp +++ b/libraries/chain/include/enumivo/chain/genesis_state.hpp @@ -28,13 +28,7 @@ struct genesis_state { .max_block_cpu_usage = config::default_max_block_cpu_usage, .target_block_cpu_usage_pct = config::default_target_block_cpu_usage_pct, .max_transaction_cpu_usage = config::default_max_transaction_cpu_usage, - .base_per_transaction_cpu_usage = config::default_base_per_transaction_cpu_usage, - .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, + .min_transaction_cpu_usage = config::default_min_transaction_cpu_usage, .max_transaction_lifetime = config::default_max_trx_lifetime, .deferred_trx_expiration_window = config::default_deferred_trx_expiration_window, diff --git a/libraries/chain/include/enumivo/chain/transaction_context.hpp b/libraries/chain/include/enumivo/chain/transaction_context.hpp index 9c278ccec7c..7b579774ce7 100644 --- a/libraries/chain/include/enumivo/chain/transaction_context.hpp +++ b/libraries/chain/include/enumivo/chain/transaction_context.hpp @@ -30,8 +30,12 @@ namespace eosio { namespace chain { inline void add_net_usage( uint64_t u ) { net_usage += u; check_net_usage(); } void check_net_usage()const; + void checktime()const; + void pause_billing_timer(); + void resume_billing_timer(); + void add_ram_usage( account_name account, int64_t ram_delta ); private: @@ -86,8 +90,12 @@ namespace eosio { namespace chain { uint64_t& net_usage; /// reference to trace->net_usage fc::microseconds objective_duration_limit; - bool objective_duration_limit_due_to_block = true; + fc::time_point _deadline = fc::time_point::maximum(); int64_t deadline_exception_code = block_cpu_usage_exceeded::code_value; + int64_t billing_timer_exception_code = block_cpu_usage_exceeded::code_value; + fc::time_point pseudo_start; + fc::microseconds billed_time; + fc::microseconds billing_timer_duration_limit; }; } } diff --git a/libraries/chain/include/enumivo/chain/wasm_interface_private.hpp b/libraries/chain/include/enumivo/chain/wasm_interface_private.hpp index abdd37b5e61..625d49af4ed 100644 --- a/libraries/chain/include/enumivo/chain/wasm_interface_private.hpp +++ b/libraries/chain/include/enumivo/chain/wasm_interface_private.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "IR/Module.h" #include "Runtime/Intrinsics.h" @@ -28,7 +29,7 @@ namespace eosio { namespace chain { else FC_THROW("wasm_interface_impl fall through"); } - + std::vector parse_initial_memory(const Module& module) { std::vector mem_image; @@ -47,9 +48,13 @@ namespace eosio { namespace chain { return mem_image; } - std::unique_ptr& get_instantiated_module(const digest_type& code_id, const shared_string& code) { + std::unique_ptr& get_instantiated_module( const digest_type& code_id, + const shared_string& code, + transaction_context& trx_context ) + { auto it = instantiation_cache.find(code_id); if(it == instantiation_cache.end()) { + trx_context.pause_billing_timer(); IR::Module module; try { Serialization::MemoryInputStream stream((const U8*)code.data(), code.size()); @@ -70,6 +75,7 @@ namespace eosio { namespace chain { ENU_ASSERT(false, wasm_serialization_error, e.message.c_str()); } it = instantiation_cache.emplace(code_id, runtime_interface->instantiate_module((const char*)bytes.data(), bytes.size(), parse_initial_memory(module))).first; + trx_context.resume_billing_timer(); } return it->second; } diff --git a/libraries/chain/transaction_context.cpp b/libraries/chain/transaction_context.cpp index 397251d9274..40d9368baf3 100644 --- a/libraries/chain/transaction_context.cpp +++ b/libraries/chain/transaction_context.cpp @@ -20,6 +20,7 @@ namespace eosio { namespace chain { ,trace(std::make_shared()) ,start(s) ,net_usage(trace->net_usage) + ,pseudo_start(s) { trace->id = id; executed.reserve( trx.total_actions() ); @@ -31,21 +32,13 @@ namespace eosio { namespace chain { FC_ASSERT( !is_initialized, "cannot initialize twice" ); const static int64_t large_number_no_overflow = std::numeric_limits::max()/2; - auto original_deadline = deadline; - const auto& cfg = control.get_global_properties().configuration; auto& rl = control.get_mutable_resource_limits_manager(); net_limit = rl.get_block_net_limit(); objective_duration_limit = fc::microseconds( rl.get_block_cpu_limit() ); - deadline = start + objective_duration_limit; - - // Check if deadline is limited by block deadline or caller-set deadline - if( original_deadline <= deadline ) { - deadline = original_deadline; - deadline_exception_code = deadline_exception::code_value; - } + _deadline = start + objective_duration_limit; // Possibly lower net_limit to the maximum net usage a transaction is allowed to be billed if( cfg.max_transaction_net_usage <= net_limit ) { @@ -53,6 +46,13 @@ namespace eosio { namespace chain { net_limit_due_to_block = false; } + // Possibly lower objective_duration_limit to the maximum cpu usage a transaction is allowed to be billed + if( cfg.max_transaction_cpu_usage <= objective_duration_limit.count() ) { + objective_duration_limit = fc::microseconds(cfg.max_transaction_cpu_usage); + billing_timer_exception_code = tx_cpu_usage_exceeded::code_value; + _deadline = start + objective_duration_limit; + } + // Possibly lower net_limit to optional limit set in the transaction header uint64_t trx_specified_net_usage_limit = static_cast(trx.max_net_usage_words.value) * 8; if( trx_specified_net_usage_limit > 0 && trx_specified_net_usage_limit <= net_limit ) { @@ -65,16 +65,11 @@ namespace eosio { namespace chain { auto trx_specified_cpu_usage_limit = fc::milliseconds(trx.max_cpu_usage_ms); if( trx_specified_cpu_usage_limit <= objective_duration_limit ) { objective_duration_limit = trx_specified_cpu_usage_limit; - objective_duration_limit_due_to_block = false; + billing_timer_exception_code = tx_cpu_usage_exceeded::code_value; + _deadline = start + objective_duration_limit; } } - // Possibly limit deadline if objective_duration_limit is not due to the block and does not exceed current delta - if( !objective_duration_limit_due_to_block && objective_duration_limit <= (deadline - start) ) { - deadline = start + objective_duration_limit; - deadline_exception_code = tx_cpu_usage_exceeded::code_value; - } - if( billed_cpu_time_us > 0 ) validate_cpu_usage_to_bill( billed_cpu_time_us, false ); // Fail early if the amount to be billed is too high @@ -111,9 +106,19 @@ namespace eosio { namespace chain { } // Possibly limit deadline if the duration accounts can be billed for (+ a subjective leeway) does not exceed current delta - if( ( fc::microseconds(account_cpu_limit) + leeway ) <= (deadline - start) ) { - deadline = start + fc::microseconds(account_cpu_limit) + leeway; - deadline_exception_code = leeway_deadline_exception::code_value; + if( (fc::microseconds(account_cpu_limit) + leeway) <= (_deadline - start) ) { + _deadline = start + fc::microseconds(account_cpu_limit) + leeway; + billing_timer_exception_code = leeway_deadline_exception::code_value; + } + + billing_timer_duration_limit = _deadline - start; + + // Check if deadline is limited by caller-set deadline (only change deadline if billed_cpu_time_us is not set) + if( billed_cpu_time_us > 0 || deadline < _deadline ) { + _deadline = deadline; + deadline_exception_code = deadline_exception::code_value; + } else { + deadline_exception_code = billing_timer_exception_code; } eager_net_limit = (eager_net_limit/8)*8; // Round down to nearest multiple of word size (8 bytes) so check_net_usage can be efficient @@ -121,9 +126,6 @@ namespace eosio { namespace chain { if( initial_net_usage > 0 ) add_net_usage( initial_net_usage ); // Fail early if current net usage is already greater than the calculated limit - if( billed_cpu_time_us > 0 ) - deadline = original_deadline; // Only change deadline if billed_cpu_time_us is not set - checktime(); // Fail early if deadline has already been exceeded is_initialized = true; @@ -237,7 +239,7 @@ namespace eosio { namespace chain { // Possibly lower objective_duration_limit to what the billed accounts can pay if( account_cpu_limit <= objective_duration_limit.count() ) { objective_duration_limit = fc::microseconds(account_cpu_limit); - objective_duration_limit_due_to_block = false; + billing_timer_exception_code = tx_cpu_usage_exceeded::code_value; } net_usage = ((net_usage + 7)/8)*8; // Round up to nearest multiple of word size (8 bytes) @@ -245,10 +247,13 @@ namespace eosio { namespace chain { eager_net_limit = net_limit; check_net_usage(); - trace->elapsed = fc::time_point::now() - start; + auto now = fc::time_point::now(); + trace->elapsed = now - start; - if( billed_cpu_time_us == 0 ) - billed_cpu_time_us = std::max( trace->elapsed.count(), static_cast(config::default_min_transaction_cpu_usage_us) ); + if( billed_cpu_time_us == 0 ) { + const auto& cfg = control.get_global_properties().configuration; + billed_cpu_time_us = std::max( (now - pseudo_start).count(), static_cast(cfg.min_transaction_cpu_usage) ); + } validate_cpu_usage_to_bill( billed_cpu_time_us ); @@ -277,34 +282,60 @@ namespace eosio { namespace chain { void transaction_context::checktime()const { auto now = fc::time_point::now(); - if( BOOST_UNLIKELY( now > deadline ) ) { + if( BOOST_UNLIKELY( now > _deadline ) ) { if( billed_cpu_time_us > 0 || deadline_exception_code == deadline_exception::code_value ) { - ENU_THROW( deadline_exception, "deadline exceeded", ("now", now)("deadline", deadline)("start", start) ); + ENU_THROW( deadline_exception, "deadline exceeded", ("now", now)("deadline", _deadline)("start", start) ); } else if( deadline_exception_code == block_cpu_usage_exceeded::code_value ) { ENU_THROW( block_cpu_usage_exceeded, "not enough time left in block to complete executing transaction", - ("now", now)("deadline", deadline)("start", start) ); + ("now", now)("deadline", _deadline)("start", start) ); } else if( deadline_exception_code == tx_cpu_usage_exceeded::code_value ) { ENU_THROW( tx_cpu_usage_exceeded, "transaction was executing for too long", - ("now", now)("deadline", deadline)("start", start) ); + ("now", now)("deadline", _deadline)("start", start) ); } else if( deadline_exception_code == leeway_deadline_exception::code_value ) { ENU_THROW( leeway_deadline_exception, "the transaction was unable to complete by deadline, " "but it is possible it could have succeeded if it were allow to run to completion", - ("now", now)("deadline", deadline)("start", start) ); + ("now", now)("deadline", _deadline)("start", start) ); } FC_ASSERT( false, "unexpected deadline exception code" ); } } + + void transaction_context::pause_billing_timer() { + if( billed_cpu_time_us > 0 || pseudo_start == fc::time_point() ) return; // either irrelevant or already paused + + auto now = fc::time_point::now(); + billed_time = now - pseudo_start; + deadline_exception_code = deadline_exception::code_value; // Other timeout exceptions cannot be thrown while billable timer is paused. + pseudo_start = fc::time_point(); + } + + void transaction_context::resume_billing_timer() { + if( billed_cpu_time_us > 0 || pseudo_start != fc::time_point() ) return; // either irrelevant or already running + + auto now = fc::time_point::now(); + pseudo_start = now - billed_time; + if( (pseudo_start + billing_timer_duration_limit) <= deadline ) { + _deadline = pseudo_start + billing_timer_duration_limit; + deadline_exception_code = billing_timer_exception_code; + } else { + _deadline = deadline; + deadline_exception_code = deadline_exception::code_value; + } + } + void transaction_context::validate_cpu_usage_to_bill( int64_t billed_us, bool check_minimum )const { -#warning make min_transaction_cpu_us into a configuration parameter - ENU_ASSERT( !check_minimum || billed_us >= config::default_min_transaction_cpu_usage_us, transaction_exception, - "cannot bill CPU time less than the minimum of ${min_billable} us", - ("min_billable", config::default_min_transaction_cpu_usage_us)("billed_cpu_time_us", billed_us) - ); + if( check_minimum ) { + const auto& cfg = control.get_global_properties().configuration; + ENU_ASSERT( billed_us >= cfg.min_transaction_cpu_usage, transaction_exception, + "cannot bill CPU time less than the minimum of ${min_billable} us", + ("min_billable", cfg.min_transaction_cpu_usage)("billed_cpu_time_us", billed_us) + ); + } - if( objective_duration_limit_due_to_block ) { + if( billing_timer_exception_code == block_cpu_usage_exceeded::code_value ) { ENU_ASSERT( billed_us <= objective_duration_limit.count(), block_cpu_usage_exceeded, "billed CPU time (${billed} us) is greater than the billable CPU time left in the block (${billable} us)", diff --git a/libraries/chain/wasm_interface.cpp b/libraries/chain/wasm_interface.cpp index 3b5db87bb51..fa5aac3293d 100644 --- a/libraries/chain/wasm_interface.cpp +++ b/libraries/chain/wasm_interface.cpp @@ -53,7 +53,7 @@ namespace eosio { namespace chain { } void wasm_interface::apply( const digest_type& code_id, const shared_string& code, apply_context& context ) { - my->get_instantiated_module(code_id, code)->apply(context); + my->get_instantiated_module(code_id, code, context.trx_context)->apply(context); } wasm_instantiated_module_interface::~wasm_instantiated_module_interface() {} @@ -681,7 +681,7 @@ class producer_api : public context_aware_api { auto copy_size = std::min( buffer_size, s ); memcpy( producers, active_producers.data(), copy_size ); - + return copy_size; } }; diff --git a/libraries/testing/include/enumivo/testing/tester.hpp b/libraries/testing/include/enumivo/testing/tester.hpp index a18ae356dce..7b0fba9b21d 100644 --- a/libraries/testing/include/enumivo/testing/tester.hpp +++ b/libraries/testing/include/enumivo/testing/tester.hpp @@ -151,7 +151,7 @@ namespace eosio { namespace testing { transaction_trace_ptr push_reqauth( account_name from, const vector& auths, const vector& keys ); transaction_trace_ptr push_reqauth(account_name from, string role, bool multi_sig = false); // use when just want any old non-context free action - transaction_trace_ptr push_dummy(account_name from, const string& v = "blah"); + transaction_trace_ptr push_dummy(account_name from, const string& v = "blah", uint32_t billed_cpu_time_us = DEFAULT_BILLED_CPU_TIME_US ); transaction_trace_ptr transfer( account_name from, account_name to, asset amount, string memo, account_name currency ); transaction_trace_ptr transfer( account_name from, account_name to, string amount, string memo, account_name currency ); transaction_trace_ptr issue( account_name to, string amount, account_name currency ); diff --git a/libraries/testing/tester.cpp b/libraries/testing/tester.cpp index c805005d220..939b0b67509 100644 --- a/libraries/testing/tester.cpp +++ b/libraries/testing/tester.cpp @@ -399,7 +399,7 @@ namespace eosio { namespace testing { } - transaction_trace_ptr base_tester::push_dummy(account_name from, const string& v) { + transaction_trace_ptr base_tester::push_dummy(account_name from, const string& v, uint32_t billed_cpu_time_us) { // use reqauth for a normal action, this could be anything variant pretty_trx = fc::mutable_variant_object() ("actions", fc::variants({ @@ -430,7 +430,7 @@ namespace eosio { namespace testing { set_transaction_headers(trx); trx.sign( get_private_key( from, "active" ), chain_id_type() ); - return push_transaction( trx ); + return push_transaction( trx, fc::time_point::maximum(), billed_cpu_time_us ); } diff --git a/programs/enucli/main.cpp b/programs/enucli/main.cpp index afacadc5b23..07350ac012a 100644 --- a/programs/enucli/main.cpp +++ b/programs/enucli/main.cpp @@ -463,13 +463,6 @@ fc::variant regproducer_variant(const account_name& producer, ("max_block_cpu_usage", config::default_max_block_cpu_usage) ("target_block_cpu_usage_pct", config::default_target_block_cpu_usage_pct) ("max_transaction_cpu_usage", config::default_max_transaction_cpu_usage) - ("base_per_transaction_cpu_usage", config::default_base_per_transaction_cpu_usage) - ("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) ("deferred_trx_expiration_window", config::default_deferred_trx_expiration_window) ("max_transaction_delay", config::default_max_trx_delay) @@ -720,7 +713,7 @@ bool port_used(uint16_t port) { void try_port( uint16_t port, uint32_t duration ) { using namespace std::chrono; auto start_time = duration_cast( system_clock::now().time_since_epoch() ).count(); - while ( !port_used(port)) { + while ( !port_used(port)) { if (duration_cast( system_clock::now().time_since_epoch()).count() - start_time > duration ) { std::cerr << "Unable to connect to enuwallet, if enuwallet is running please kill the process and try again.\n"; throw connection_exception(fc::log_messages{FC_LOG_MESSAGE(error, "Unable to connect to enuwallet")}); @@ -843,7 +836,7 @@ struct create_account_subcommand { add_standard_transaction_options(createAccount); createAccount->set_callback([this] { - if( !active_key_str.size() ) + if( !active_key_str.size() ) active_key_str = owner_key_str; public_key_type owner_key, active_key; try { diff --git a/unittests/api_tests.cpp b/unittests/api_tests.cpp index 7a0c525b9ca..556cf3c201b 100644 --- a/unittests/api_tests.cpp +++ b/unittests/api_tests.cpp @@ -651,10 +651,6 @@ BOOST_FIXTURE_TEST_CASE(checktime_pass_tests, TESTER) { try { } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE(checktime_fail_tests) { try { - // TODO: This is an extremely fragile test. It needs improvements: - // 1) compilation of the smart contract should probably not count towards the CPU time of a transaction that first uses it; - // 2) checktime should eventually switch to a deterministic metric which should hopefully fix the inconsistencies - // of this test succeeding/failing on different machines (for example, succeeding on our local dev machines but failing on Jenkins). TESTER t; t.produce_blocks(2); @@ -669,7 +665,7 @@ BOOST_AUTO_TEST_CASE(checktime_fail_tests) { try { t.control->get_resource_limits_manager().get_account_limits( N(testapi), x, net, cpu ); wdump((net)(cpu)); - auto call_test = [](TESTER& test, auto ac, uint32_t billed_cpu_time_us, uint8_t max_cpu_usage_ms ) { + auto call_test = [](TESTER& test, auto ac, uint32_t billed_cpu_time_us /*, uint8_t max_cpu_usage_ms */ ) { signed_transaction trx; auto pl = vector{{N(testapi), config::active_name}}; @@ -679,7 +675,7 @@ BOOST_AUTO_TEST_CASE(checktime_fail_tests) { try { trx.actions.push_back(act); test.set_transaction_headers(trx); - trx.max_cpu_usage_ms = max_cpu_usage_ms; + //trx.max_cpu_usage_ms = max_cpu_usage_ms; auto sigs = trx.sign(test.get_private_key(N(testapi), "active"), chain_id_type()); trx.get_signature_keys(chain_id_type() ); auto res = test.push_transaction( trx, fc::time_point::now() + fc::milliseconds(200), billed_cpu_time_us ); @@ -689,16 +685,23 @@ BOOST_AUTO_TEST_CASE(checktime_fail_tests) { try { BOOST_CHECK_EXCEPTION( call_test( t, test_api_action{}, - 5000, 0 ), + 5000 ), deadline_exception, is_deadline_exception ); BOOST_CHECK_EXCEPTION( call_test( t, test_api_action{}, - 0, 50 ), + 0 ), tx_cpu_usage_exceeded, is_tx_cpu_usage_exceeded ); + uint32_t time_left_in_block_us = config::default_max_block_cpu_usage - config::default_min_transaction_cpu_usage; + std::string dummy_string = "nonce"; + uint32_t increment = config::default_max_transaction_cpu_usage / 3; + for( auto i = 0; time_left_in_block_us > 2*increment; ++i ) { + t.push_dummy( N(testapi), dummy_string + std::to_string(i), increment ); + time_left_in_block_us -= increment; + } BOOST_CHECK_EXCEPTION( call_test( t, test_api_action{}, - 0, 0 ), - block_cpu_usage_exceeded, is_block_cpu_usage_exceeded ); // Because the onblock uses up some of the CPU + 0 ), + block_cpu_usage_exceeded, is_block_cpu_usage_exceeded ); BOOST_REQUIRE_EQUAL( t.validate(), true ); } FC_LOG_AND_RETHROW() } diff --git a/unittests/eosio.system_tests.cpp b/unittests/eosio.system_tests.cpp index 9c30863ec64..5d7e68ec791 100644 --- a/unittests/eosio.system_tests.cpp +++ b/unittests/eosio.system_tests.cpp @@ -167,7 +167,7 @@ class enumivo_system_tester : public TESTER { set_transaction_headers(trx); asset cpu = asset::from_string("80.0000 EOS"); asset net = asset::from_string("80.0000 EOS"); - asset ram = asset::from_string("1.0000 EOS"); + asset ram = asset::from_string("1.0000 EOS"); for (const auto& a: accounts) { authority owner_auth( get_public_key( a, "owner" ) ); @@ -185,7 +185,7 @@ class enumivo_system_tester : public TESTER { ("receiver", a) ("quant", ram) ) ); - + trx.actions.emplace_back( get_action( N(eosio), N(delegatebw), vector{ {creator, config::active_name} }, mvo() ("from", creator) @@ -196,7 +196,7 @@ class enumivo_system_tester : public TESTER { ) ); } - + set_transaction_headers(trx); trx.sign( get_private_key( creator, "active" ), chain_id_type() ); return push_transaction( trx ); @@ -277,13 +277,7 @@ class enumivo_system_tester : public TESTER { ("max_block_cpu_usage", 10000000 + n ) ("target_block_cpu_usage_pct", 10 + n ) ("max_transaction_cpu_usage", 1000000 + n ) - ("base_per_transaction_cpu_usage", 100 + n) - ("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 ) + ("min_transaction_cpu_usage", 100 + n ) ("max_transaction_lifetime", 3600 + n) ("deferred_trx_expiration_window", 600 + n) ("max_transaction_delay", 10*86400+n) @@ -528,7 +522,7 @@ BOOST_FIXTURE_TEST_CASE( buysell, enumivo_system_tester ) try { BOOST_REQUIRE_EQUAL( asset::from_string("100000999.9943 EOS"), get_balance( "alice1111111" ) ); -} FC_LOG_AND_RETHROW() +} FC_LOG_AND_RETHROW() BOOST_FIXTURE_TEST_CASE( stake_unstake, enumivo_system_tester ) try { //issue( "eosio", "1000.0000 EOS", config::system_account_name ); @@ -926,7 +920,7 @@ BOOST_FIXTURE_TEST_CASE( vote_for_producer, enumivo_system_tester, * boost::unit ("producer", "alice1111111") ("producer_key", get_public_key( N(alice1111111), "active") ) ("url", "http://block.one") - ("location", 0 ) + ("location", 0 ) ) ); auto prod = get_producer_info( "alice1111111" ); @@ -1452,9 +1446,9 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, enumivo_system_tester, * boost::unit_test: BOOST_REQUIRE_EQUAL(0, prod["last_claim_time"].as()); const asset initial_supply = get_token_supply(); const asset initial_balance = get_balance(N(defproducera)); - + BOOST_REQUIRE_EQUAL(success(), push_action(N(defproducera), N(claimrewards), mvo()("owner", "defproducera"))); - + const auto global_state = get_global_state(); const uint64_t claim_time = global_state["last_pervote_bucket_fill"].as_uint64(); const asset pervote_bucket = global_state["pervote_bucket"].as(); @@ -1466,12 +1460,12 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, enumivo_system_tester, * boost::unit_test: BOOST_REQUIRE_EQUAL(claim_time, prod["last_claim_time"].as()); const int32_t secs_between_fills = static_cast((claim_time - initial_claim_time) / 1000000); - + BOOST_REQUIRE_EQUAL(0, initial_pervote_bucket.amount); BOOST_REQUIRE_EQUAL(int64_t( (initial_supply.amount * secs_between_fills * ((4.879-1.0)/100.0)) / (52*7*24*3600) ), savings.amount - initial_savings.amount); - + int64_t block_payments = int64_t( initial_supply.amount * produced_blocks * (0.25/100.0) / (52*7*24*3600*2) ); int64_t from_pervote_bucket = int64_t( initial_supply.amount * secs_between_fills * (0.75/100.0) / (52*7*24*3600) ); @@ -1486,7 +1480,7 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, enumivo_system_tester, * boost::unit_test: const int64_t max_supply_growth = int64_t( (initial_supply.amount * secs_between_fills * (4.879/100.0)) / (52*7*24*3600) ); BOOST_REQUIRE(max_supply_growth >= supply.amount - initial_supply.amount); } - + { BOOST_REQUIRE_EQUAL(error("condition: assertion failed: already claimed rewards within a day"), push_action(N(defproducera), N(claimrewards), mvo()("owner", "defproducera"))); @@ -1516,7 +1510,7 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, enumivo_system_tester, * boost::unit_test: BOOST_REQUIRE_EQUAL(success(), push_action(N(defproducera), N(claimrewards), mvo()("owner", "defproducera"))); - + const auto global_state = get_global_state(); const uint64_t claim_time = global_state["last_pervote_bucket_fill"].as_uint64(); const asset pervote_bucket = global_state["pervote_bucket"].as(); @@ -1547,7 +1541,7 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, enumivo_system_tester, * boost::unit_test: const int64_t max_supply_growth = int64_t( (initial_supply.amount * secs_between_fills * (4.879/100.0)) / (52*7*24*3600) ); BOOST_REQUIRE(max_supply_growth >= supply.amount - initial_supply.amount); } - + // defproducerb tries to claim rewards but he's not on the list { BOOST_REQUIRE_EQUAL(error("condition: assertion failed: account name is not in producer list"), @@ -1594,8 +1588,8 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, enumivo_system_tester, * boost::u auto defproducera_info = get_producer_info( N(defproducera) ); wdump((defproducera_info)); BOOST_REQUIRE_EQUAL(0, defproducera_info["total_votes"].as()); - - + + ilog( "------ get defproducerz ----------" ); auto defproducerz_info = get_producer_info( N(defproducerz) ); wdump((defproducerz_info)); @@ -1685,12 +1679,12 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, enumivo_system_tester, * boost::u total_votes += vote_shares[i]; } std::for_each(vote_shares.begin(), vote_shares.end(), [total_votes](double& x) { x /= total_votes; }); - + BOOST_TEST(double(1) == std::accumulate(vote_shares.begin(), vote_shares.end(), double(0))); BOOST_TEST(double(3./57.) == vote_shares.front()); BOOST_TEST(double(1./57.) == vote_shares.back()); } - + { const uint32_t prod_index = 2; const auto prod_name = producer_names[prod_index]; @@ -1702,9 +1696,9 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, enumivo_system_tester, * boost::u const asset initial_savings = initial_global_state["savings"].as(); const asset initial_supply = get_token_supply(); const asset initial_balance = get_balance(prod_name); - + BOOST_REQUIRE_EQUAL(success(), push_action(prod_name, N(claimrewards), mvo()("owner", prod_name))); - + const auto global_state = get_global_state(); const uint64_t claim_time = global_state["last_pervote_bucket_fill"].as_uint64(); const asset pervote_bucket = global_state["pervote_bucket"].as(); @@ -1716,11 +1710,11 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, enumivo_system_tester, * boost::u BOOST_REQUIRE_EQUAL(int64_t( (initial_supply.amount * secs_between_fills * (cont_rate - standby_rate - block_rate)) / secs_per_year ), savings.amount - initial_savings.amount); - + int64_t block_payments = int64_t( initial_supply.amount * produced_blocks * block_rate / blocks_per_year ); - int64_t expected_pervote_bucket = int64_t( initial_pervote_bucket.amount + initial_supply.amount * secs_between_fills * standby_rate / secs_per_year ); + int64_t expected_pervote_bucket = int64_t( initial_pervote_bucket.amount + initial_supply.amount * secs_between_fills * standby_rate / secs_per_year ); int64_t from_pervote_bucket = int64_t( vote_shares[prod_index] * expected_pervote_bucket ); - + if (from_pervote_bucket >= 100 * 10000) { BOOST_REQUIRE_EQUAL(block_payments + from_pervote_bucket, balance.amount - initial_balance.amount); BOOST_REQUIRE_EQUAL(expected_pervote_bucket - from_pervote_bucket, pervote_bucket.amount); @@ -1750,7 +1744,7 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, enumivo_system_tester, * boost::u } // wait to 23 hours which is not enough for producers to get deactivated - // payment calculations don't change. By now, pervote_bucket has grown enough + // payment calculations don't change. By now, pervote_bucket has grown enough // that a producer's share is more than 100 tokens produce_block(fc::seconds(23 * 3600)); @@ -1803,12 +1797,12 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, enumivo_system_tester, * boost::u push_action(prod_name, N(claimrewards), mvo()("owner", prod_name))); } - // wait two more hours, now most producers haven't produced in a day and will + // wait two more hours, now most producers haven't produced in a day and will // be deactivated produce_block(fc::seconds(2 * 3600)); produce_blocks(8 * 21 * 12); - + { bool all_newly_elected_produced = true; for (uint32_t i = 21; i < producer_names.size(); ++i) { @@ -1856,7 +1850,7 @@ BOOST_FIXTURE_TEST_CASE(producer_onblock_check, enumivo_system_tester) try { N(defproduceru),N(defproducerv),N(defproducerw),N(defproducerx),N(defproducery),N(defproducerz)}; setup_producer_accounts(producer_names); - for (auto a:producer_names) + for (auto a:producer_names) regproducer(a); BOOST_REQUIRE_EQUAL(0, get_producer_info( N(defproducera) )["total_votes"].as()); @@ -1901,7 +1895,7 @@ BOOST_FIXTURE_TEST_CASE(producer_onblock_check, enumivo_system_tester) try { ("producers", vector(producer_names.begin(), producer_names.begin()+21)) ) ); - + BOOST_REQUIRE_EQUAL(success(), push_action(N(producvoterc), N(voteproducer), mvo() ("voter", "producvoterc") ("proxy", name(0).to_string()) @@ -2202,12 +2196,7 @@ fc::mutable_variant_object config_to_variant( const eosio::chain::chain_config& ( "max_block_cpu_usage", config.max_block_cpu_usage ) ( "target_block_cpu_usage_pct", config.target_block_cpu_usage_pct ) ( "max_transaction_cpu_usage", config.max_transaction_cpu_usage ) - ( "base_per_transaction_cpu_usage", config.base_per_transaction_cpu_usage ) - ( "base_per_action_cpu_usage", config.base_per_action_cpu_usage ) - ( "base_setcode_cpu_usage", config.base_setcode_cpu_usage ) - ( "per_signature_cpu_usage", config.per_signature_cpu_usage ) - ( "context_free_discount_cpu_usage_num", config.context_free_discount_cpu_usage_num ) - ( "context_free_discount_cpu_usage_den", config.context_free_discount_cpu_usage_den ) + ( "min_transaction_cpu_usage", config.min_transaction_cpu_usage ) ( "max_transaction_lifetime", config.max_transaction_lifetime ) ( "deferred_trx_expiration_window", config.deferred_trx_expiration_window ) ( "max_transaction_delay", config.max_transaction_delay )