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 all 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
3 changes: 2 additions & 1 deletion libraries/chain/apply_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@ 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 fc::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;
Expand Down
11 changes: 11 additions & 0 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,7 @@ struct controller_impl {
throw;
} catch( const fc::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();
}
Expand Down Expand Up @@ -1135,6 +1136,7 @@ struct controller_impl {
throw;
} catch( const fc::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();
trace->elapsed = fc::time_point::now() - trx_context.start;
Expand Down Expand Up @@ -1329,6 +1331,7 @@ struct controller_impl {
} catch( const protocol_feature_bad_block_exception& ) {
throw;
} catch (const fc::exception& e) {
trace->error_code = controller::convert_exception_to_error_code( e );
trace->except = e;
trace->except_ptr = std::current_exception();
}
Expand Down Expand Up @@ -3003,6 +3006,14 @@ 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 fc::exception& e ) {
const eosio_assert_code_exception* e_ptr = dynamic_cast<const eosio_assert_code_exception*>( &e );

if( e_ptr == nullptr ) return {};

return e_ptr->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 fc::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
38 changes: 37 additions & 1 deletion libraries/chain/include/eosio/chain/exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,42 @@
{ throw( effect_type( e.what(), e.get_log() ) ); }


#define FC_DECLARE_DERIVED_EXCEPTION_WITH_ERROR_CODE( TYPE, BASE, CODE, WHAT ) \
class TYPE : public BASE \
{ \
public: \
enum code_enum { \
code_value = CODE, \
}; \
explicit TYPE( int64_t code, const std::string& name_value, const std::string& what_value ) \
:BASE( code, name_value, what_value ){} \
explicit TYPE( fc::log_message&& m, int64_t code, const std::string& name_value, const std::string& what_value ) \
:BASE( std::move(m), code, name_value, what_value ){} \
explicit TYPE( fc::log_messages&& m, int64_t code, const std::string& name_value, const std::string& what_value )\
:BASE( std::move(m), code, name_value, what_value ){}\
explicit TYPE( const fc::log_messages& m, int64_t code, const std::string& name_value, const std::string& what_value )\
:BASE( m, code, name_value, what_value ){}\
TYPE( const std::string& what_value, const fc::log_messages& m ) \
:BASE( m, CODE, BOOST_PP_STRINGIZE(TYPE), what_value ){} \
TYPE( fc::log_message&& m ) \
:BASE( fc::move(m), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ){}\
TYPE( fc::log_messages msgs ) \
:BASE( fc::move( msgs ), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ) {} \
TYPE( const TYPE& c ) \
:BASE(c),error_code(c.error_code) {} \
TYPE( const BASE& c ) \
:BASE(c){} \
TYPE():BASE(CODE, BOOST_PP_STRINGIZE(TYPE), WHAT){}\
\
virtual std::shared_ptr<fc::exception> dynamic_copy_exception()const\
{ return std::make_shared<TYPE>( *this ); } \
virtual NO_RETURN void dynamic_rethrow_exception()const \
{ if( code() == CODE ) throw *this;\
else fc::exception::dynamic_rethrow_exception(); \
} \
fc::optional<uint64_t> error_code; \
};

namespace eosio { namespace chain {

FC_DECLARE_EXCEPTION( chain_exception,
Expand Down Expand Up @@ -213,7 +249,7 @@ namespace eosio { namespace chain {
3050002, "Invalid Action Arguments" )
FC_DECLARE_DERIVED_EXCEPTION( eosio_assert_message_exception, action_validate_exception,
3050003, "eosio_assert_message assertion failure" )
FC_DECLARE_DERIVED_EXCEPTION( eosio_assert_code_exception, action_validate_exception,
FC_DECLARE_DERIVED_EXCEPTION_WITH_ERROR_CODE( eosio_assert_code_exception, action_validate_exception,
3050004, "eosio_assert_code assertion failure" )
FC_DECLARE_DERIVED_EXCEPTION( action_not_found_exception, action_validate_exception,
3050005, "Action can not be found" )
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 @@ -618,29 +618,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 @@ -651,7 +656,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
8 changes: 6 additions & 2 deletions libraries/chain/wasm_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -960,8 +960,12 @@ class context_free_system_api : public context_aware_api {

void eosio_assert_code( bool condition, uint64_t error_code ) {
if( BOOST_UNLIKELY( !condition ) ) {
EOS_THROW( eosio_assert_code_exception,
"assertion failure with error code: ${error_code}", ("error_code", error_code) );
eosio_assert_code_exception e( FC_LOG_MESSAGE( error,
"assertion failure with error code: ${error_code}",
("error_code", error_code)
) );
e.error_code = error_code;
throw e;
}
}

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
Loading