Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Add optional error_code to transaction and action traces #7108

Merged
merged 5 commits into from
Apr 11, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion libraries/chain/apply_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,13 @@ void apply_context::exec_one()
} catch( const wasm_exit& ) {}
}
} FC_RETHROW_EXCEPTIONS( warn, "pending console output: ${console}", ("console", _pending_console_output) )
} catch( fc::exception& e ) {
} catch( const eosio_assert_code_exception& e ) {
action_trace& trace = trx_context.get_action_trace( action_ordinal );
trace.error_code = controller::convert_exception_to_error_code( e );
trace.except = e;
finalize_trace( trace, start );
throw;
} catch( const fc::exception& e ) {
action_trace& trace = trx_context.get_action_trace( action_ordinal );
trace.except = e;
finalize_trace( trace, start );
Expand Down
40 changes: 39 additions & 1 deletion libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,11 @@ struct controller_impl {
return trace;
} catch( const protocol_feature_bad_block_exception& ) {
throw;
} catch( const eosio_assert_code_exception& e ) {
cpu_time_to_bill_us = trx_context.update_billed_cpu_time( fc::time_point::now() );
trace->error_code = controller::convert_exception_to_error_code( e );
trace->except = e;
trace->except_ptr = std::current_exception();
} catch( const fc::exception& e ) {
cpu_time_to_bill_us = trx_context.update_billed_cpu_time( fc::time_point::now() );
trace->except = e;
Expand Down Expand Up @@ -1123,6 +1128,11 @@ struct controller_impl {
return trace;
} catch( const protocol_feature_bad_block_exception& ) {
throw;
} catch( const eosio_assert_code_exception& e ) {
trace->error_code = controller::convert_exception_to_error_code( e );
trace->except = e;
trace->except_ptr = std::current_exception();
trace->elapsed = fc::time_point::now() - trx_context.start;
} catch( const fc::exception& e ) {
cpu_time_to_bill_us = trx_context.update_billed_cpu_time( fc::time_point::now() );
trace->except = e;
Expand Down Expand Up @@ -1314,7 +1324,11 @@ struct controller_impl {
unapplied_transactions.erase( trx->signed_id );
}
return trace;
} catch (const fc::exception& e) {
} catch( const eosio_assert_code_exception& e ) {
trace->error_code = controller::convert_exception_to_error_code( e );
trace->except = e;
trace->except_ptr = std::current_exception();
} catch( const fc::exception& e ) {
trace->except = e;
trace->except_ptr = std::current_exception();
}
Expand Down Expand Up @@ -2983,6 +2997,30 @@ bool controller::all_subjective_mitigations_disabled()const {
return my->conf.disable_all_subjective_mitigations;
}

fc::optional<uint64_t> controller::convert_exception_to_error_code( const eosio_assert_code_exception& e ) {
const auto& logs = e.get_log();

if( logs.size() == 0 ) return {};

const auto msg = logs[0].get_message();

auto pos = msg.find( ": " );

if( pos == std::string::npos || (pos + 2) >= msg.size() ) return {};

pos += 2;

uint64_t error_code = 0;

try {
error_code = std::strtoull( msg.c_str() + pos, nullptr, 10 );
} catch( ... ) {
return {};
}

return error_code;
}

heifner marked this conversation as resolved.
Show resolved Hide resolved
/// Protocol feature activation handlers:

template<>
Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ namespace eosio { namespace chain {
void add_to_ram_correction( account_name account, uint64_t ram_bytes );
bool all_subjective_mitigations_disabled()const;

static fc::optional<uint64_t> convert_exception_to_error_code( const eosio_assert_code_exception& e );

signal<void(const signed_block_ptr&)> pre_accepted_block;
signal<void(const block_state_ptr&)> accepted_block_header;
signal<void(const block_state_ptr&)> accepted_block;
Expand Down
16 changes: 10 additions & 6 deletions libraries/chain/include/eosio/chain/trace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@ namespace eosio { namespace chain {

struct action_trace {
action_trace( const transaction_trace& trace, const action& act, account_name receiver, bool context_free,
uint32_t action_ordinal, uint32_t creator_action_ordinal, uint32_t parent_action_ordinal );
uint32_t action_ordinal, uint32_t creator_action_ordinal,
uint32_t closest_unnotified_ancestor_action_ordinal );
action_trace( const transaction_trace& trace, action&& act, account_name receiver, bool context_free,
uint32_t action_ordinal, uint32_t creator_action_ordinal, uint32_t parent_action_ordinal );
uint32_t action_ordinal, uint32_t creator_action_ordinal,
uint32_t closest_unnotified_ancestor_action_ordinal );
action_trace(){}

fc::unsigned_int action_ordinal;
fc::unsigned_int creator_action_ordinal;
fc::unsigned_int parent_action_ordinal;
fc::unsigned_int closest_unnotified_ancestor_action_ordinal;
fc::optional<action_receipt> receipt;
action_name receiver;
action act;
Expand All @@ -45,6 +47,7 @@ namespace eosio { namespace chain {
fc::optional<block_id_type> producer_block_id;
flat_set<account_delta> account_ram_deltas;
fc::optional<fc::exception> except;
fc::optional<uint64_t> error_code;
};

struct transaction_trace {
Expand All @@ -61,6 +64,7 @@ namespace eosio { namespace chain {

transaction_trace_ptr failed_dtrx_trace;
fc::optional<fc::exception> except;
fc::optional<uint64_t> error_code;
std::exception_ptr except_ptr;
};

Expand All @@ -70,10 +74,10 @@ FC_REFLECT( eosio::chain::account_delta,
(account)(delta) )

FC_REFLECT( eosio::chain::action_trace,
(action_ordinal)(creator_action_ordinal)(parent_action_ordinal)(receipt)
(action_ordinal)(creator_action_ordinal)(closest_unnotified_ancestor_action_ordinal)(receipt)
(receiver)(act)(context_free)(elapsed)(console)(trx_id)(block_num)(block_time)
(producer_block_id)(account_ram_deltas)(except) )
(producer_block_id)(account_ram_deltas)(except)(error_code) )

FC_REFLECT( eosio::chain::transaction_trace, (id)(block_num)(block_time)(producer_block_id)
(receipt)(elapsed)(net_usage)(scheduled)
(action_traces)(account_ram_delta)(failed_dtrx_trace)(except) )
(action_traces)(account_ram_delta)(failed_dtrx_trace)(except)(error_code) )
6 changes: 3 additions & 3 deletions libraries/chain/include/eosio/chain/transaction_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ namespace eosio { namespace chain {

/** invalidates any action_trace references returned by get_action_trace */
uint32_t schedule_action( const action& act, account_name receiver, bool context_free,
uint32_t creator_action_ordinal, uint32_t parent_action_ordinal );
uint32_t creator_action_ordinal, uint32_t closest_unnotified_ancestor_action_ordinal );

/** invalidates any action_trace references returned by get_action_trace */
uint32_t schedule_action( action&& act, account_name receiver, bool context_free,
uint32_t creator_action_ordinal, uint32_t parent_action_ordinal );
uint32_t creator_action_ordinal, uint32_t closest_unnotified_ancestor_action_ordinal );

/** invalidates any action_trace references returned by get_action_trace */
uint32_t schedule_action( uint32_t action_ordinal, account_name receiver, bool context_free,
uint32_t creator_action_ordinal, uint32_t parent_action_ordinal );
uint32_t creator_action_ordinal, uint32_t closest_unnotified_ancestor_action_ordinal );

void execute_action( uint32_t action_ordinal, uint32_t recurse_depth );

Expand Down
8 changes: 4 additions & 4 deletions libraries/chain/trace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ namespace eosio { namespace chain {

action_trace::action_trace(
const transaction_trace& trace, const action& act, account_name receiver, bool context_free,
uint32_t action_ordinal, uint32_t creator_action_ordinal, uint32_t parent_action_ordinal
uint32_t action_ordinal, uint32_t creator_action_ordinal, uint32_t closest_unnotified_ancestor_action_ordinal
)
:action_ordinal( action_ordinal )
,creator_action_ordinal( creator_action_ordinal )
,parent_action_ordinal( parent_action_ordinal )
,closest_unnotified_ancestor_action_ordinal( closest_unnotified_ancestor_action_ordinal )
,receiver( receiver )
,act( act )
,context_free( context_free )
Expand All @@ -24,11 +24,11 @@ action_trace::action_trace(

action_trace::action_trace(
const transaction_trace& trace, action&& act, account_name receiver, bool context_free,
uint32_t action_ordinal, uint32_t creator_action_ordinal, uint32_t parent_action_ordinal
uint32_t action_ordinal, uint32_t creator_action_ordinal, uint32_t closest_unnotified_ancestor_action_ordinal
)
:action_ordinal( action_ordinal )
,creator_action_ordinal( creator_action_ordinal )
,parent_action_ordinal( parent_action_ordinal )
,closest_unnotified_ancestor_action_ordinal( closest_unnotified_ancestor_action_ordinal )
,receiver( receiver )
,act( std::move(act) )
,context_free( context_free )
Expand Down
18 changes: 12 additions & 6 deletions libraries/chain/transaction_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -595,29 +595,34 @@ namespace bacc = boost::accumulators;
}

uint32_t transaction_context::schedule_action( const action& act, account_name receiver, bool context_free,
uint32_t creator_action_ordinal, uint32_t parent_action_ordinal )
uint32_t creator_action_ordinal,
uint32_t closest_unnotified_ancestor_action_ordinal )
{
uint32_t new_action_ordinal = trace->action_traces.size() + 1;

trace->action_traces.emplace_back( *trace, act, receiver, context_free,
new_action_ordinal, creator_action_ordinal, parent_action_ordinal );
new_action_ordinal, creator_action_ordinal,
closest_unnotified_ancestor_action_ordinal );

return new_action_ordinal;
}

uint32_t transaction_context::schedule_action( action&& act, account_name receiver, bool context_free,
uint32_t creator_action_ordinal, uint32_t parent_action_ordinal )
uint32_t creator_action_ordinal,
uint32_t closest_unnotified_ancestor_action_ordinal )
{
uint32_t new_action_ordinal = trace->action_traces.size() + 1;

trace->action_traces.emplace_back( *trace, std::move(act), receiver, context_free,
new_action_ordinal, creator_action_ordinal, parent_action_ordinal );
new_action_ordinal, creator_action_ordinal,
closest_unnotified_ancestor_action_ordinal );

return new_action_ordinal;
}

uint32_t transaction_context::schedule_action( uint32_t action_ordinal, account_name receiver, bool context_free,
uint32_t creator_action_ordinal, uint32_t parent_action_ordinal )
uint32_t creator_action_ordinal,
uint32_t closest_unnotified_ancestor_action_ordinal )
{
uint32_t new_action_ordinal = trace->action_traces.size() + 1;

Expand All @@ -628,7 +633,8 @@ namespace bacc = boost::accumulators;
// The reserve above is required so that the emplace_back below does not invalidate the provided_action reference.

trace->action_traces.emplace_back( *trace, provided_action, receiver, context_free,
new_action_ordinal, creator_action_ordinal, parent_action_ordinal );
new_action_ordinal, creator_action_ordinal,
closest_unnotified_ancestor_action_ordinal );

return new_action_ordinal;
}
Expand Down
34 changes: 21 additions & 13 deletions plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1899,34 +1899,42 @@ void read_write::push_transaction(const read_write::push_transaction_params& par
try {
output = db.to_variant_with_abi( *trx_trace_ptr, abi_serializer_max_time );

// Create map of (parent_action_ordinal, global_sequence) with action trace
// Create map of (closest_unnotified_ancestor_action_ordinal, global_sequence) with action trace
std::map< std::pair<uint32_t, uint64_t>, fc::mutable_variant_object > act_traces_map;
for( const auto& act_trace : output["action_traces"].get_array() ) {
if (act_trace["receipt"].is_null() && act_trace["except"].is_null()) continue;
auto parent_action_ordinal = act_trace["parent_action_ordinal"].as<fc::unsigned_int>().value;
auto closest_unnotified_ancestor_action_ordinal =
act_trace["closest_unnotified_ancestor_action_ordinal"].as<fc::unsigned_int>().value;
auto global_sequence = act_trace["receipt"].is_null() ?
std::numeric_limits<uint64_t>::max() :
act_trace["receipt"]["global_sequence"].as<uint64_t>();
act_traces_map.emplace( std::make_pair( parent_action_ordinal, global_sequence ),
act_traces_map.emplace( std::make_pair( closest_unnotified_ancestor_action_ordinal,
global_sequence ),
act_trace.get_object() );
}

std::function<vector<fc::variant>(uint32_t)> convert_act_trace_to_tree_struct = [&](uint32_t parent_action_ordinal) {
std::function<vector<fc::variant>(uint32_t)> convert_act_trace_to_tree_struct =
[&](uint32_t closest_unnotified_ancestor_action_ordinal) {
vector<fc::variant> restructured_act_traces;
auto it = act_traces_map.lower_bound( std::make_pair(parent_action_ordinal, 0) );
for( ; it != act_traces_map.end() && it->first.first == parent_action_ordinal; ++it ) {
auto it = act_traces_map.lower_bound(
std::make_pair( closest_unnotified_ancestor_action_ordinal, 0)
);
for( ;
it != act_traces_map.end() && it->first.first == closest_unnotified_ancestor_action_ordinal; ++it )
{
auto& act_trace_mvo = it->second;

auto action_ordinal = act_trace_mvo["action_ordinal"].as<fc::unsigned_int>().value;
act_trace_mvo["inline_traces"] = convert_act_trace_to_tree_struct(action_ordinal);
if (act_trace_mvo["receipt"].is_null()) {
act_trace_mvo["receipt"] = fc::mutable_variant_object()("abi_sequence", 0)
("act_digest", digest_type::hash(trx_trace_ptr->action_traces[action_ordinal-1].act))
("auth_sequence", flat_map<account_name,uint64_t>())
("code_sequence", 0)
("global_sequence", 0)
("receiver", act_trace_mvo["receiver"])
("recv_sequence", 0);
act_trace_mvo["receipt"] = fc::mutable_variant_object()
("abi_sequence", 0)
("act_digest", digest_type::hash(trx_trace_ptr->action_traces[action_ordinal-1].act))
("auth_sequence", flat_map<account_name,uint64_t>())
("code_sequence", 0)
("global_sequence", 0)
("receiver", act_trace_mvo["receiver"])
("recv_sequence", 0);
}
restructured_act_traces.push_back( std::move(act_trace_mvo) );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,6 @@ datastream<ST>& operator<<(datastream<ST>& ds, const history_serial_wrapper<eosi
fc::raw::pack(ds, fc::unsigned_int(0));
fc::raw::pack(ds, as_type<fc::unsigned_int>(obj.obj.action_ordinal));
fc::raw::pack(ds, as_type<fc::unsigned_int>(obj.obj.creator_action_ordinal));
fc::raw::pack(ds, as_type<fc::unsigned_int>(obj.obj.parent_action_ordinal));
fc::raw::pack(ds, bool(obj.obj.receipt));
if (obj.obj.receipt) {
fc::raw::pack(ds, make_history_serial_wrapper(obj.db, as_type<eosio::chain::action_receipt>(*obj.obj.receipt)));
Expand All @@ -498,6 +497,7 @@ datastream<ST>& operator<<(datastream<ST>& ds, const history_serial_wrapper<eosi
if (obj.obj.except)
e = obj.obj.except->to_string();
fc::raw::pack(ds, as_type<fc::optional<std::string>>(e));
fc::raw::pack(ds, as_type<fc::optional<uint64_t>>(obj.obj.error_code));

return ds;
}
Expand Down Expand Up @@ -534,6 +534,7 @@ datastream<ST>& operator<<(datastream<ST>&
if (obj.obj.except)
e = obj.obj.except->to_string();
fc::raw::pack(ds, as_type<fc::optional<std::string>>(e));
fc::raw::pack(ds, as_type<fc::optional<uint64_t>>(obj.obj.error_code));

fc::raw::pack(ds, bool(obj.obj.failed_dtrx_trace));
if (obj.obj.failed_dtrx_trace) {
Expand Down
5 changes: 3 additions & 2 deletions plugins/state_history_plugin/state_history_plugin_abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,15 @@ extern const char* const state_history_plugin_abi = R"({
"name": "action_trace_v0", "fields": [
{ "name": "action_ordinal", "type": "varuint32" },
{ "name": "creator_action_ordinal", "type": "varuint32" },
{ "name": "parent_action_ordinal", "type": "varuint32" },
{ "name": "receipt", "type": "action_receipt?" },
heifner marked this conversation as resolved.
Show resolved Hide resolved
{ "name": "receiver", "type": "name" },
{ "name": "act", "type": "action" },
{ "name": "context_free", "type": "bool" },
{ "name": "elapsed", "type": "int64" },
{ "name": "console", "type": "string" },
{ "name": "account_ram_deltas", "type": "account_delta[]" },
{ "name": "except", "type": "string?" }
{ "name": "except", "type": "string?" },
{ "name": "error_code", "type": "uint64?" }
]
},
{
Expand All @@ -118,6 +118,7 @@ extern const char* const state_history_plugin_abi = R"({
{ "name": "action_traces", "type": "action_trace[]" },
{ "name": "account_ram_delta", "type": "account_delta?" },
{ "name": "except", "type": "string?" },
{ "name": "error_code", "type": "uint64?" },
{ "name": "failed_dtrx_trace", "type": "transaction_trace?" }
]
},
Expand Down
Loading