diff --git a/libraries/chain/chain_controller.cpp b/libraries/chain/chain_controller.cpp index aa4757123f61af583534e3edde3c9d811e7516de..6c4fe5b823483d55dd2dc7fd8079e40b77651103 100644 --- a/libraries/chain/chain_controller.cpp +++ b/libraries/chain/chain_controller.cpp @@ -956,7 +956,13 @@ void chain_controller::apply_message(apply_context& context) const auto& recipient = _db.get(context.code); if (recipient.code.size()) { //idump((context.code)(context.msg.type)); - wasm_interface::get().apply(context); + const uint32_t execution_time = + _skip_flags | received_block + ? _rcvd_block_trans_execution_time + : _skip_flags | created_block + ? _create_block_trans_execution_time + : _trans_execution_time; + wasm_interface::get().apply(context, execution_time); } } FC_CAPTURE_AND_RETHROW((context.msg)) } @@ -1158,7 +1164,7 @@ void chain_controller::initialize_chain(chain_initializer_interface& starter) MessageOutput output; ProcessedTransaction trx; /// dummy tranaction required for scope validation std::sort(trx.scope.begin(), trx.scope.end() ); - with_skip_flags(skip_scope_check | skip_transaction_signatures | skip_authority_check, [&](){ + with_skip_flags(skip_scope_check | skip_transaction_signatures | skip_authority_check | received_block, [&](){ process_message(trx,m.code,m,output); }); }); @@ -1167,8 +1173,11 @@ void chain_controller::initialize_chain(chain_initializer_interface& starter) } FC_CAPTURE_AND_RETHROW() } chain_controller::chain_controller(database& database, fork_database& fork_db, block_log& blocklog, - chain_initializer_interface& starter, unique_ptr admin) - : _db(database), _fork_db(fork_db), _block_log(blocklog), _admin(std::move(admin)) { + chain_initializer_interface& starter, unique_ptr admin, + uint32_t trans_execution_time, uint32_t rcvd_block_trans_execution_time, + uint32_t create_block_trans_execution_time) + : _db(database), _fork_db(fork_db), _block_log(blocklog), _admin(std::move(admin)), _trans_execution_time(trans_execution_time), + _rcvd_block_trans_execution_time(rcvd_block_trans_execution_time), _create_block_trans_execution_time(create_block_trans_execution_time) { initialize_indexes(); starter.register_types(*this, _db); @@ -1213,7 +1222,8 @@ void chain_controller::replay() { skip_transaction_dupe_check | skip_tapos_check | skip_producer_schedule_check | - skip_authority_check); + skip_authority_check | + received_block); } auto end = fc::time_point::now(); ilog("Done replaying ${n} blocks, elapsed time: ${t} sec", diff --git a/libraries/chain/include/eos/chain/chain_controller.hpp b/libraries/chain/include/eos/chain/chain_controller.hpp index 6b1274e438297a3fb8f61f4cb6a8c1b5a1e6f069..b9a335dce3d1209efcf5f1c1691db48b4d8be205 100644 --- a/libraries/chain/include/eos/chain/chain_controller.hpp +++ b/libraries/chain/include/eos/chain/chain_controller.hpp @@ -56,7 +56,9 @@ namespace eos { namespace chain { class chain_controller { public: chain_controller(database& database, fork_database& fork_db, block_log& blocklog, - chain_initializer_interface& starter, unique_ptr admin); + chain_initializer_interface& starter, unique_ptr admin, + uint32_t trans_execution_time, uint32_t rcvd_block_trans_execution_time, + uint32_t create_block_trans_execution_time); chain_controller(chain_controller&&) = default; ~chain_controller(); @@ -105,7 +107,10 @@ namespace eos { namespace chain { skip_producer_schedule_check= 1 << 10, ///< used while reindexing skip_validate = 1 << 11, ///< used prior to checkpoint, skips validate() call on transaction skip_scope_check = 1 << 12, ///< used to skip checks for proper scope - skip_output_check = 1 << 13 ///< used to skip checks for outputs in block exactly matching those created from apply + skip_output_check = 1 << 13, ///< used to skip checks for outputs in block exactly matching those created from apply + pushed_transaction = 1 << 14, ///< used to indicate that the origination of the call was from a push_transaction, to determine time allotment + created_block = 1 << 15, ///< used to indicate that the origination of the call was for creating a block, to determine time allotment + received_block = 1 << 16 ///< used to indicate that the origination of the call was for a received block, to determine time allotment }; /** @@ -379,6 +384,10 @@ namespace eos { namespace chain { bool _currently_applying_block = false; uint64_t _skip_flags = 0; + const uint32_t _trans_execution_time; + const uint32_t _rcvd_block_trans_execution_time; + const uint32_t _create_block_trans_execution_time; + flat_map _checkpoints; typedef pair handler_key; diff --git a/libraries/chain/include/eos/chain/wasm_interface.hpp b/libraries/chain/include/eos/chain/wasm_interface.hpp index 7122bf734cab9052852dbb4f8aa451f7c008f754..3284f4e6cc3355b81acdeb679d3c3d8b49fa3a01 100644 --- a/libraries/chain/include/eos/chain/wasm_interface.hpp +++ b/libraries/chain/include/eos/chain/wasm_interface.hpp @@ -32,7 +32,7 @@ class wasm_interface { static wasm_interface& get(); void init( apply_context& c ); - void apply( apply_context& c ); + void apply( apply_context& c, uint32_t execution_time ); void validate( apply_context& c ); void precondition( apply_context& c ); @@ -47,6 +47,7 @@ class wasm_interface { ModuleState* current_state = nullptr; wasm_memory* current_memory_management = nullptr; + uint32_t checktime_limit = 0; private: void load( const AccountName& name, const chainbase::database& db ); diff --git a/libraries/chain/wasm_interface.cpp b/libraries/chain/wasm_interface.cpp index 5c5bd62c3a349e37e4ca95d53de19e05e0c96d1a..3a52c3aae66a2529d8b157554e91fb3c8df73a9a 100644 --- a/libraries/chain/wasm_interface.cpp +++ b/libraries/chain/wasm_interface.cpp @@ -46,16 +46,16 @@ namespace eos { namespace chain { const int CHECKTIME_LIMIT = 18000; #endif - void checktime(int64_t duration) + void checktime(int64_t duration, uint32_t checktime_limit) { - if (duration > CHECKTIME_LIMIT) { + if (duration > checktime_limit) { wlog("checktime called ${d}", ("d", duration)); throw checktime_exceeded(); } } DEFINE_INTRINSIC_FUNCTION0(env,checktime,checktime,none) { - checktime(wasm_interface::get().current_execution_time()); + checktime(wasm_interface::get().current_execution_time(), wasm_interface::get().checktime_limit); } template @@ -350,7 +350,7 @@ DEFINE_INTRINSIC_FUNCTION1(env,sbrk,sbrk,i32,i32,num_bytes) { FC_ASSERT( num_bytes >= 0, "sbrk can only allocate memory, not reduce" ); FC_ASSERT( wasm.current_memory_management != nullptr, "sbrk can only be called during the scope of wasm_interface::vm_call" ); U32 previous_bytes_allocated = wasm.current_memory_management->sbrk(num_bytes); - checktime(wasm.current_execution_time()); + checktime(wasm.current_execution_time(), wasm_interface::get().checktime_limit); return previous_bytes_allocated; } @@ -615,7 +615,7 @@ DEFINE_INTRINSIC_FUNCTION1(env,free,free,none,i32,ptr) { Runtime::invokeFunction(call,args); wasm_memory_mgmt.reset(); - checktime(current_execution_time()); + checktime(current_execution_time(), checktime_limit); } catch( const Runtime::Exception& e ) { edump((std::string(describeExceptionCause(e.cause)))); edump((e.callStack)); @@ -673,11 +673,12 @@ DEFINE_INTRINSIC_FUNCTION1(env,free,free,none,i32,ptr) { } FC_CAPTURE_AND_RETHROW() } - void wasm_interface::apply( apply_context& c ) { + void wasm_interface::apply( apply_context& c, uint32_t execution_time ) { try { current_validate_context = &c; current_precondition_context = &c; current_apply_context = &c; + checktime_limit = execution_time; load( c.code, c.db ); vm_apply(); @@ -689,6 +690,7 @@ DEFINE_INTRINSIC_FUNCTION1(env,free,free,none,i32,ptr) { current_validate_context = &c; current_precondition_context = &c; current_apply_context = &c; + checktime_limit = CHECKTIME_LIMIT; load( c.code, c.db ); vm_onInit();