From 7eebf69574bca5a093563751174a52ba24d68c7f Mon Sep 17 00:00:00 2001 From: arhag Date: Thu, 11 Apr 2019 13:35:05 -0400 Subject: [PATCH] store uint64_t error_code in eosio_assert_code_exception rather than extracting it from the string message #6898 --- libraries/chain/apply_context.cpp | 7 +-- libraries/chain/controller.cpp | 43 ++++--------------- .../chain/include/eosio/chain/controller.hpp | 2 +- .../chain/include/eosio/chain/exceptions.hpp | 38 +++++++++++++++- libraries/chain/wasm_interface.cpp | 8 +++- 5 files changed, 53 insertions(+), 45 deletions(-) diff --git a/libraries/chain/apply_context.cpp b/libraries/chain/apply_context.cpp index 616c8e31dac..5badd7185d0 100644 --- a/libraries/chain/apply_context.cpp +++ b/libraries/chain/apply_context.cpp @@ -82,14 +82,9 @@ void apply_context::exec_one() } catch( const wasm_exit& ) {} } } FC_RETHROW_EXCEPTIONS( warn, "pending console output: ${console}", ("console", _pending_console_output) ) - } 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.error_code = controller::convert_exception_to_error_code( e ); trace.except = e; finalize_trace( trace, start ); throw; diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index bccad2c784b..e3721ef4726 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -981,13 +981,9 @@ 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->error_code = controller::convert_exception_to_error_code( e ); trace->except = e; trace->except_ptr = std::current_exception(); } @@ -1128,13 +1124,9 @@ 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->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; @@ -1324,11 +1316,8 @@ struct controller_impl { unapplied_transactions.erase( trx->signed_id ); } return trace; - } 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->error_code = controller::convert_exception_to_error_code( e ); trace->except = e; trace->except_ptr = std::current_exception(); } @@ -2997,28 +2986,12 @@ bool controller::all_subjective_mitigations_disabled()const { return my->conf.disable_all_subjective_mitigations; } -fc::optional 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 {}; - } +fc::optional controller::convert_exception_to_error_code( const fc::exception& e ) { + const eosio_assert_code_exception* e_ptr = dynamic_cast( &e ); + + if( e_ptr == nullptr ) return {}; - return error_code; + return e_ptr->error_code; } /// Protocol feature activation handlers: diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index 31b6ae4b830..43d1f1637c9 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -275,7 +275,7 @@ 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 convert_exception_to_error_code( const eosio_assert_code_exception& e ); + static fc::optional convert_exception_to_error_code( const fc::exception& e ); signal pre_accepted_block; signal accepted_block_header; diff --git a/libraries/chain/include/eosio/chain/exceptions.hpp b/libraries/chain/include/eosio/chain/exceptions.hpp index a80213e0425..51ab7e9f6c6 100644 --- a/libraries/chain/include/eosio/chain/exceptions.hpp +++ b/libraries/chain/include/eosio/chain/exceptions.hpp @@ -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 dynamic_copy_exception()const\ + { return std::make_shared( *this ); } \ + virtual NO_RETURN void dynamic_rethrow_exception()const \ + { if( code() == CODE ) throw *this;\ + else fc::exception::dynamic_rethrow_exception(); \ + } \ + fc::optional error_code; \ + }; + namespace eosio { namespace chain { FC_DECLARE_EXCEPTION( chain_exception, @@ -207,7 +243,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" ) diff --git a/libraries/chain/wasm_interface.cpp b/libraries/chain/wasm_interface.cpp index 004a7326e83..54feb1b6a87 100644 --- a/libraries/chain/wasm_interface.cpp +++ b/libraries/chain/wasm_interface.cpp @@ -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; } }