diff --git a/libraries/chain/apply_context.cpp b/libraries/chain/apply_context.cpp index 9b92b8d2a1f..de1450013d8 100644 --- a/libraries/chain/apply_context.cpp +++ b/libraries/chain/apply_context.cpp @@ -29,81 +29,95 @@ static inline void print_debug(account_name receiver, const action_trace& ar) { } } -action_trace apply_context::exec_one() +void apply_context::exec_one( action_trace& trace ) { auto start = fc::time_point::now(); + action_receipt r; + r.receiver = receiver; + r.act_digest = digest_type::hash(act); + + trace.trx_id = trx_context.id; + trace.block_num = control.pending_block_state()->block_num; + trace.block_time = control.pending_block_time(); + trace.producer_block_id = control.pending_producer_block_id(); + trace.act = act; + trace.context_free = context_free; + const auto& cfg = control.get_global_properties().configuration; try { - const auto& a = control.get_account( receiver ); - privileged = a.privileged; - auto native = control.find_apply_handler( receiver, act.account, act.name ); - if( native ) { - if( trx_context.can_subjectively_fail && control.is_producing_block()) { - control.check_contract_list( receiver ); - control.check_action_list( act.account, act.name ); + try { + const auto& a = control.get_account( receiver ); + privileged = a.privileged; + auto native = control.find_apply_handler( receiver, act.account, act.name ); + if( native ) { + if( trx_context.can_subjectively_fail && control.is_producing_block() ) { + control.check_contract_list( receiver ); + control.check_action_list( act.account, act.name ); + } + (*native)( *this ); } - (*native)( *this ); - } - if( a.code.size() > 0 - && !(act.account == config::system_account_name && act.name == N( setcode ) && - receiver == config::system_account_name)) { - if( trx_context.can_subjectively_fail && control.is_producing_block()) { - control.check_contract_list( receiver ); - control.check_action_list( act.account, act.name ); + if( a.code.size() > 0 + && !(act.account == config::system_account_name && act.name == N( setcode ) && + receiver == config::system_account_name) ) { + if( trx_context.can_subjectively_fail && control.is_producing_block() ) { + control.check_contract_list( receiver ); + control.check_action_list( act.account, act.name ); + } + try { + control.get_wasm_interface().apply( a.code_version, a.code, *this ); + } catch( const wasm_exit& ) {} } - try { - control.get_wasm_interface().apply( a.code_version, a.code, *this ); - } catch( const wasm_exit& ) {} - } - - } FC_RETHROW_EXCEPTIONS(warn, "pending console output: ${console}", ("console", _pending_console_output.str())) + } FC_RETHROW_EXCEPTIONS( warn, "pending console output: ${console}", ("console", _pending_console_output.str()) ) + } catch( fc::exception& e ) { + trace.receipt = r; // fill with known data + trace.except = e; + finalize_trace( trace, start ); + throw; + } - action_receipt r; - r.receiver = receiver; - r.act_digest = digest_type::hash(act); r.global_sequence = next_global_sequence(); r.recv_sequence = next_recv_sequence( receiver ); const auto& account_sequence = db.get(act.account); - r.code_sequence = account_sequence.code_sequence; - r.abi_sequence = account_sequence.abi_sequence; + r.code_sequence = account_sequence.code_sequence; // could be modified by action execution above + r.abi_sequence = account_sequence.abi_sequence; // could be modified by action execution above for( const auto& auth : act.authorization ) { r.auth_sequence[auth.actor] = next_auth_sequence( auth.actor ); } - action_trace t(r); - t.trx_id = trx_context.id; - t.block_num = control.pending_block_state()->block_num; - t.block_time = control.pending_block_time(); - t.producer_block_id = control.pending_producer_block_id(); - t.account_ram_deltas = std::move( _account_ram_deltas ); - _account_ram_deltas.clear(); - t.act = act; - t.context_free = context_free; - t.console = _pending_console_output.str(); + trace.receipt = r; trx_context.executed.emplace_back( move(r) ); + finalize_trace( trace, start ); + if ( control.contracts_console() ) { - print_debug(receiver, t); + print_debug(receiver, trace); } +} + +void apply_context::finalize_trace( action_trace& trace, const fc::time_point& start ) +{ + trace.account_ram_deltas = std::move( _account_ram_deltas ); + _account_ram_deltas.clear(); + trace.console = _pending_console_output.str(); reset_console(); - t.elapsed = fc::time_point::now() - start; - return t; + trace.elapsed = fc::time_point::now() - start; } -void apply_context::exec() +void apply_context::exec( action_trace& trace ) { _notified.push_back(receiver); - trace = exec_one(); + exec_one( trace ); for( uint32_t i = 1; i < _notified.size(); ++i ) { receiver = _notified[i]; - trace.inline_traces.emplace_back( exec_one() ); + trace.inline_traces.emplace_back( ); + exec_one( trace.inline_traces.back() ); } if( _cfa_inline_actions.size() > 0 || _inline_actions.size() > 0 ) { diff --git a/libraries/chain/include/eosio/chain/apply_context.hpp b/libraries/chain/include/eosio/chain/apply_context.hpp index 70fb198b1e7..a253d950358 100644 --- a/libraries/chain/include/eosio/chain/apply_context.hpp +++ b/libraries/chain/include/eosio/chain/apply_context.hpp @@ -472,8 +472,8 @@ class apply_context { /// Execution methods: public: - action_trace exec_one(); - void exec(); + void exec_one( action_trace& trace ); + void exec( action_trace& trace ); void execute_inline( action&& a ); void execute_context_free_inline( action&& a ); void schedule_deferred_transaction( const uint128_t& sender_id, account_name payer, transaction&& trx, bool replace_existing ); @@ -573,6 +573,7 @@ class apply_context { uint64_t next_auth_sequence( account_name actor ); void add_ram_usage( account_name account, int64_t ram_delta ); + void finalize_trace( action_trace& trace, const fc::time_point& start ); private: @@ -600,8 +601,6 @@ class apply_context { generic_index idx_double; generic_index idx_long_double; - action_trace trace; - private: iterator_cache keyval_cache; diff --git a/libraries/chain/include/eosio/chain/trace.hpp b/libraries/chain/include/eosio/chain/trace.hpp index ad02baf5bac..03750bd512e 100644 --- a/libraries/chain/include/eosio/chain/trace.hpp +++ b/libraries/chain/include/eosio/chain/trace.hpp @@ -28,15 +28,14 @@ namespace eosio { namespace chain { action act; bool context_free = false; fc::microseconds elapsed; - uint64_t cpu_usage = 0; string console; - uint64_t total_cpu_usage = 0; /// total of inline_traces[x].cpu_usage + cpu_usage transaction_id_type trx_id; ///< the transaction that generated this action uint32_t block_num = 0; block_timestamp_type block_time; fc::optional producer_block_id; flat_set account_ram_deltas; + fc::optional except; }; struct action_trace : public base_action_trace { @@ -70,8 +69,8 @@ FC_REFLECT( eosio::chain::account_delta, (account)(delta) ) FC_REFLECT( eosio::chain::base_action_trace, - (receipt)(act)(context_free)(elapsed)(cpu_usage)(console)(total_cpu_usage)(trx_id) - (block_num)(block_time)(producer_block_id)(account_ram_deltas) ) + (receipt)(act)(context_free)(elapsed)(console)(trx_id) + (block_num)(block_time)(producer_block_id)(account_ram_deltas)(except) ) FC_REFLECT_DERIVED( eosio::chain::action_trace, (eosio::chain::base_action_trace), (inline_traces) ) diff --git a/libraries/chain/transaction_context.cpp b/libraries/chain/transaction_context.cpp index 806ce5d3f8e..fd79a91703c 100644 --- a/libraries/chain/transaction_context.cpp +++ b/libraries/chain/transaction_context.cpp @@ -429,14 +429,7 @@ namespace eosio { namespace chain { acontext.context_free = context_free; acontext.receiver = receiver; - try { - acontext.exec(); - } catch( ... ) { - trace = move(acontext.trace); - throw; - } - - trace = move(acontext.trace); + acontext.exec( trace ); } void transaction_context::schedule_transaction() {