diff --git a/libraries/chain/include/eosio/chain/abi_serializer.hpp b/libraries/chain/include/eosio/chain/abi_serializer.hpp index eca88c5e05e5ebd978c3651490f971cfcc011f17..b5f7030366e464f2187328a97b7db6361d21f933 100644 --- a/libraries/chain/include/eosio/chain/abi_serializer.hpp +++ b/libraries/chain/include/eosio/chain/abi_serializer.hpp @@ -461,12 +461,12 @@ namespace impl { * @tparam Reslover - callable with the signature (const name& code_account) -> optional */ template - class abi_from_variant_visitor + class abi_from_variant_visitor : reflector_verifier_visitor { public: abi_from_variant_visitor( const variant_object& _vo, T& v, Resolver _resolver ) - :_vo(_vo) - ,_val(v) + : reflector_verifier_visitor(v) + ,_vo(_vo) ,_resolver(_resolver) {} @@ -482,12 +482,11 @@ namespace impl { { auto itr = _vo.find(name); if( itr != _vo.end() ) - abi_from_variant::extract( itr->value(), _val.*member, _resolver ); + abi_from_variant::extract( itr->value(), this->obj.*member, _resolver ); } private: const variant_object& _vo; - T& _val; Resolver _resolver; }; diff --git a/libraries/chain/include/eosio/chain/asset.hpp b/libraries/chain/include/eosio/chain/asset.hpp index db4530488480c7ec34d2739f58fdb9c689d15172..d4bce45df7ea689fde32fa3e992757d991d2fb97 100644 --- a/libraries/chain/include/eosio/chain/asset.hpp +++ b/libraries/chain/include/eosio/chain/asset.hpp @@ -27,9 +27,6 @@ struct asset EOS_ASSERT( sym.valid(), asset_type_exception, "invalid symbol" ); } - share_type amount; - symbol sym; - bool is_amount_within_range()const { return -max_amount <= amount && amount <= max_amount; } bool is_valid()const { return is_amount_within_range() && sym.valid(); } @@ -39,6 +36,7 @@ struct asset string symbol_name()const; int64_t precision()const; const symbol& get_symbol() const { return sym; } + share_type get_amount()const { return amount; } static asset from_string(const string& from); string to_string()const; @@ -84,6 +82,17 @@ struct asset friend std::ostream& operator << (std::ostream& out, const asset& a) { return out << a.to_string(); } + friend struct fc::reflector; + + void reflector_verify()const { + EOS_ASSERT( is_amount_within_range(), asset_type_exception, "magnitude of asset amount must be less than 2^62" ); + EOS_ASSERT( sym.valid(), asset_type_exception, "invalid symbol" ); + } + +private: + share_type amount; + symbol sym; + }; struct extended_asset { diff --git a/libraries/chain/include/eosio/chain/symbol.hpp b/libraries/chain/include/eosio/chain/symbol.hpp index b7ca01900dee00d968cca364536b36dd2098797c..389d4103671afb970dcc93a84521ea98d0e9efde 100644 --- a/libraries/chain/include/eosio/chain/symbol.hpp +++ b/libraries/chain/include/eosio/chain/symbol.hpp @@ -79,7 +79,7 @@ namespace eosio { auto prec_part = s.substr(0, comma_pos); uint8_t p = fc::to_int64(prec_part); string name_part = s.substr(comma_pos + 1); - FC_ASSERT( p <= max_precision, "precision should be <= 18"); + FC_ASSERT( p <= max_precision, "precision ${p} should be <= 18", ("p", p)); return symbol(string_to_symbol(p, name_part.c_str())); } FC_CAPTURE_LOG_AND_RETHROW((from)) } @@ -97,6 +97,7 @@ namespace eosio { uint8_t decimals() const { return m_value & 0xFF; } uint64_t precision() const { + FC_ASSERT( decimals() <= max_precision, "precision ${p} should be <= 18", ("p", decimals()) ); uint64_t p10 = 1; uint64_t p = decimals(); while( p > 0 ) { @@ -136,6 +137,11 @@ namespace eosio { return ds << s.to_string(); } + void reflector_verify()const { + FC_ASSERT( decimals() <= max_precision, "precision ${p} should be <= 18", ("p", decimals()) ); + FC_ASSERT( valid_name(name()), "invalid symbol: ${name}", ("name",name())); + } + private: uint64_t m_value; friend struct fc::reflector; diff --git a/libraries/fc/include/fc/io/raw.hpp b/libraries/fc/include/fc/io/raw.hpp index 40a4a447c289e58cd28e1ea740b367b90c93de45..bec9ae709f7e6b2bf1a58c81be8cd70041d1f0b6 100644 --- a/libraries/fc/include/fc/io/raw.hpp +++ b/libraries/fc/include/fc/io/raw.hpp @@ -350,17 +350,17 @@ namespace fc { }; template - struct unpack_object_visitor { + struct unpack_object_visitor : fc::reflector_verifier_visitor { unpack_object_visitor(Class& _c, Stream& _s) - :c(_c),s(_s){} + : fc::reflector_verifier_visitor(_c), s(_s){} template inline void operator()( const char* name )const { try { - fc::raw::unpack( s, c.*p ); + fc::raw::unpack( s, this->obj.*p ); } FC_RETHROW_EXCEPTIONS( warn, "Error unpacking field ${field}", ("field",name) ) } + private: - Class& c; Stream& s; }; diff --git a/libraries/fc/include/fc/reflect/reflect.hpp b/libraries/fc/include/fc/reflect/reflect.hpp index 1093db2e8a745f35a59952adba27aca4b415341f..9ee0f729c04a2c2dd76caf56c63ad435891036c4 100644 --- a/libraries/fc/include/fc/reflect/reflect.hpp +++ b/libraries/fc/include/fc/reflect/reflect.hpp @@ -45,6 +45,21 @@ struct reflector{ * }; * @endcode * + * If reflection requires a verification (what a constructor might normally assert) then + * derive your Visitor from reflector_verifier_visitor and implement a reflector_verify() + * on your reflected type. + * + * @code + * template + * struct functor : reflector_verifier_visitor { + * functor(Class& _c) + * : fc::reflector_verifier_visitor(_c) {} + * + * template + * void operator()( const char* name )const; + * }; + * @endcode + * * If T is an enum then the functor has the following form: * @code * struct functor { @@ -65,6 +80,37 @@ struct reflector{ void throw_bad_enum_cast( int64_t i, const char* e ); void throw_bad_enum_cast( const char* k, const char* e ); + +template +struct reflector_verifier_visitor { + explicit reflector_verifier_visitor( Class& c ) + : obj(c) {} + + void reflector_verify() { + reflect_verify( obj ); + } + + private: + + // int matches 0 if reflector_verify exists SFINAE + template + auto verify_imp(const T& t, int) -> decltype(t.reflector_verify(), void()) { + t.reflector_verify(); + } + + // if no reflector_verify method exists (SFINAE), 0 matches long + template + auto verify_imp(const T& t, long) -> decltype(t, void()) {} + + template + auto reflect_verify(const T& t) -> decltype(verify_imp(t, 0), void()) { + verify_imp(t, 0); + } + + protected: + Class& obj; +}; + } // namespace fc @@ -99,6 +145,7 @@ template\ static inline void visit( const Visitor& v ) { \ BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_BASE, v, INHERITS ) \ BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_MEMBER, v, MEMBERS ) \ + verify( v ); \ } #define FC_REFLECT_DERIVED_IMPL_EXT( TYPE, INHERITS, MEMBERS ) \ @@ -206,6 +253,16 @@ template<> struct reflector {\ typedef TYPE type; \ typedef fc::true_type is_defined; \ typedef fc::false_type is_enum; \ + template \ + static auto verify_imp(const Visitor& v, int) -> decltype(v.reflector_verify(), void()) { \ + v.reflector_verify(); \ + } \ + template \ + static auto verify_imp(const Visitor& v, long) -> decltype(v, void()) {} \ + template \ + static auto verify(const Visitor& v) -> decltype(verify_imp(v, 0), void()) { \ + verify_imp(v, 0); \ + } \ enum member_count_enum { \ local_member_count = 0 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ),\ total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\ @@ -219,6 +276,16 @@ template struct reflector {\ typedef TYPE type; \ typedef fc::true_type is_defined; \ typedef fc::false_type is_enum; \ + template \ + static auto verify_imp(const Visitor& v, int) -> decltype(v.reflector_verify(), void()) { \ + v.reflector_verify(); \ + } \ + template \ + static auto verify_imp(const Visitor& v, long) -> decltype(v, void()) {} \ + template \ + static auto verify(const Visitor& v) -> decltype(verify_imp(v, 0), void()) { \ + verify_imp(v, 0); \ + } \ enum member_count_enum { \ local_member_count = 0 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ),\ total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\ diff --git a/libraries/fc/include/fc/reflect/variant.hpp b/libraries/fc/include/fc/reflect/variant.hpp index 31bbbdf18a29d83aa00cb05e78573954b89df761..95863d18448fbdb5c3de2b7e808db627dc45b90a 100644 --- a/libraries/fc/include/fc/reflect/variant.hpp +++ b/libraries/fc/include/fc/reflect/variant.hpp @@ -39,22 +39,22 @@ namespace fc }; template - class from_variant_visitor + class from_variant_visitor : reflector_verifier_visitor { public: from_variant_visitor( const variant_object& _vo, T& v ) - :vo(_vo),val(v){} + :reflector_verifier_visitor(v) + ,vo(_vo){} template void operator()( const char* name )const { auto itr = vo.find(name); if( itr != vo.end() ) - from_variant( itr->value(), val.*member ); + from_variant( itr->value(), this->obj.*member ); } const variant_object& vo; - T& val; }; template diff --git a/libraries/fc/src/exception.cpp b/libraries/fc/src/exception.cpp index 17cb19da65c784179465fce491f1684731591592..14b4a3be80080aa99949ac55d523e944b2a3c362 100644 --- a/libraries/fc/src/exception.cpp +++ b/libraries/fc/src/exception.cpp @@ -158,14 +158,32 @@ namespace fc string exception::to_detail_string( log_level ll )const { std::stringstream ss; - ss << variant(my->_code).as_string() <<" " << my->_name << ": " <_what<<"\n"; - for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ) - { - ss << itr->get_message() <<"\n"; //fc::format_string( itr->get_format(), itr->get_data() ) <<"\n"; - ss << " " << json::to_string( itr->get_data() ) <<"\n"; - ss << " " << itr->get_context().to_string(); - ++itr; - if( itr != my->_elog.end() ) ss<<"\n"; + try { + try { + ss << variant( my->_code ).as_string(); + } catch( std::bad_alloc& ) { + throw; + } catch( ... ) { + ss << "<- exception in to_detail_string."; + } + ss << " " << my->_name << ": " << my->_what << "\n"; + for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ) { + try { + ss << itr->get_message() << "\n"; //fc::format_string( itr->get_format(), itr->get_data() ) <<"\n"; + ss << " " << json::to_string( itr->get_data()) << "\n"; + ss << " " << itr->get_context().to_string(); + ++itr; + } catch( std::bad_alloc& ) { + throw; + } catch( ... ) { + ss << "<- exception in to_detail_string."; + } + if( itr != my->_elog.end()) ss << "\n"; + } + } catch( std::bad_alloc& ) { + throw; + } catch( ... ) { + ss << "<- exception in to_detail_string.\n"; } return ss.str(); } @@ -176,13 +194,31 @@ namespace fc string exception::to_string( log_level ll )const { std::stringstream ss; - ss << what() << " (" << variant(my->_code).as_string() <<")\n"; - for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr ) - { - ss << fc::format_string( itr->get_format(), itr->get_data() ) <<"\n"; - // ss << " " << itr->get_context().to_string() <<"\n"; + try { + ss << my->_what; + try { + ss << " (" << variant( my->_code ).as_string() << ")\n"; + } catch( std::bad_alloc& ) { + throw; + } catch( ... ) { + ss << "<- exception in to_string.\n"; + } + for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr ) { + try { + ss << fc::format_string( itr->get_format(), itr->get_data()) << "\n"; + // ss << " " << itr->get_context().to_string() <<"\n"; + } catch( std::bad_alloc& ) { + throw; + } catch( ... ) { + ss << "<- exception in to_string.\n"; + } + } + return ss.str(); + } catch( std::bad_alloc& ) { + throw; + } catch( ... ) { + ss << "<- exception in to_string.\n"; } - return ss.str(); } /** diff --git a/plugins/account_history_api_plugin/account_history_api_plugin.cpp b/plugins/account_history_api_plugin/account_history_api_plugin.cpp index 2202adda3f260d5484b54b5889913da747ab0d1a..d73298e7bb2a12228e5c0aeb9ba6123888e4418c 100644 --- a/plugins/account_history_api_plugin/account_history_api_plugin.cpp +++ b/plugins/account_history_api_plugin/account_history_api_plugin.cpp @@ -27,14 +27,8 @@ void account_history_api_plugin::plugin_initialize(const variables_map&) {} if (body.empty()) body = "{}"; \ auto result = api_handle.call_name(fc::json::from_string(body).as()); \ cb(200, fc::json::to_string(result)); \ - } catch (fc::eof_exception& e) { \ - error_results results{400, "Bad Request", e}; \ - cb(400, fc::json::to_string(results)); \ - elog("Unable to parse arguments: ${args}", ("args", body)); \ - } catch (fc::exception& e) { \ - error_results results{500, "Internal Service Error", e}; \ - cb(500, fc::json::to_string(results)); \ - elog("Exception encountered while processing ${call}: ${e}", ("call", #api_name "." #call_name)("e", e)); \ + } catch (...) { \ + http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ }} diff --git a/plugins/chain_api_plugin/chain_api_plugin.cpp b/plugins/chain_api_plugin/chain_api_plugin.cpp index 92263ab9abf2588f5ce6054c6da815d320e312fc..004dc32c089465dfdc730b73eb4c64b12da164c4 100644 --- a/plugins/chain_api_plugin/chain_api_plugin.cpp +++ b/plugins/chain_api_plugin/chain_api_plugin.cpp @@ -35,23 +35,8 @@ void chain_api_plugin::plugin_initialize(const variables_map&) {} if (body.empty()) body = "{}"; \ auto result = api_handle.call_name(fc::json::from_string(body).as()); \ cb(http_response_code, fc::json::to_string(result)); \ - } catch (chain::unsatisfied_authorization& e) { \ - error_results results{401, "UnAuthorized", e}; \ - cb(401, fc::json::to_string(results)); \ - } catch (chain::tx_duplicate& e) { \ - error_results results{409, "Conflict", e}; \ - cb(409, fc::json::to_string(results)); \ - } catch (chain::transaction_exception& e) { \ - error_results results{400, "Bad Request", e}; \ - cb(400, fc::json::to_string(results)); \ - } catch (fc::eof_exception& e) { \ - error_results results{400, "Bad Request", e}; \ - cb(400, fc::json::to_string(results)); \ - elog("Unable to parse arguments: ${args}", ("args", body)); \ - } catch (fc::exception& e) { \ - error_results results{500, "Internal Service Error", e}; \ - cb(500, fc::json::to_string(results)); \ - elog("Exception encountered while processing ${call}: ${e}", ("call", #api_name "." #call_name)("e", e.to_detail_string())); \ + } catch (...) { \ + http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ }} diff --git a/plugins/db_size_api_plugin/db_size_api_plugin.cpp b/plugins/db_size_api_plugin/db_size_api_plugin.cpp index 5ee0b1093a8f514881b28994aaed9dc81f59a0fe..8dd5b50f48e60acd0ca6960d2cf2e6eb4245543a 100644 --- a/plugins/db_size_api_plugin/db_size_api_plugin.cpp +++ b/plugins/db_size_api_plugin/db_size_api_plugin.cpp @@ -19,14 +19,8 @@ using namespace eosio; if (body.empty()) body = "{}"; \ INVOKE \ cb(http_response_code, fc::json::to_string(result)); \ - } catch (fc::eof_exception& e) { \ - error_results results{400, "Bad Request", e}; \ - cb(400, fc::json::to_string(results)); \ - elog("Unable to parse arguments: ${args}", ("args", body)); \ - } catch (fc::exception& e) { \ - error_results results{500, "Internal Service Error", e}; \ - cb(500, fc::json::to_string(results)); \ - elog("Exception encountered while processing ${call}: ${e}", ("call", #api_name "." #call_name)("e", e)); \ + } catch (...) { \ + http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ }} diff --git a/plugins/faucet_testnet_plugin/faucet_testnet_plugin.cpp b/plugins/faucet_testnet_plugin/faucet_testnet_plugin.cpp index 76e6f9d824110381d037ea90415d767cd7281673..d53c2335415452bc60ed0d5b1c68ddf6f65e8769 100644 --- a/plugins/faucet_testnet_plugin/faucet_testnet_plugin.cpp +++ b/plugins/faucet_testnet_plugin/faucet_testnet_plugin.cpp @@ -62,14 +62,8 @@ using results_pair = std::pair; if (body.empty()) body = "{}"; \ const auto result = api_handle->invoke_cb(body); \ response_cb(result.first, fc::json::to_string(result.second)); \ - } catch (fc::eof_exception& e) { \ - error_results results{400, "Bad Request", e}; \ - response_cb(400, fc::json::to_string(results)); \ - elog("Unable to parse arguments: ${args}", ("args", body)); \ - } catch (fc::exception& e) { \ - error_results results{500, "Internal Service Error", e}; \ - response_cb(500, fc::json::to_string(results)); \ - elog("Exception encountered while processing ${call}: ${e}", ("call", #api_name "." #call_name)("e", e)); \ + } catch (...) { \ + http_plugin::handle_exception(#api_name, #call_name, body, response_cb); \ } \ }} diff --git a/plugins/history_api_plugin/history_api_plugin.cpp b/plugins/history_api_plugin/history_api_plugin.cpp index 2e99e37a5fc4be96bc29933226485c152d015137..71f4370172833d4b4cb5cf879f59ded2508c4f63 100644 --- a/plugins/history_api_plugin/history_api_plugin.cpp +++ b/plugins/history_api_plugin/history_api_plugin.cpp @@ -26,14 +26,8 @@ void history_api_plugin::plugin_initialize(const variables_map&) {} if (body.empty()) body = "{}"; \ auto result = api_handle.call_name(fc::json::from_string(body).as()); \ cb(200, fc::json::to_string(result)); \ - } catch (fc::eof_exception& e) { \ - error_results results{400, "Bad Request", e}; \ - cb(400, fc::json::to_string(results)); \ - elog("Unable to parse arguments: ${args}", ("args", body)); \ - } catch (fc::exception& e) { \ - error_results results{500, "Internal Service Error", e}; \ - cb(500, fc::json::to_string(results)); \ - elog("Exception encountered while processing ${call}: ${e}", ("call", #api_name "." #call_name)("e", e)); \ + } catch (...) { \ + http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ }} diff --git a/plugins/http_plugin/CMakeLists.txt b/plugins/http_plugin/CMakeLists.txt index 86cb41e8129a5a3862ddd51ca12596f7ac64c74f..b12eb696067da0e9f33dec3557d588ef68436655 100644 --- a/plugins/http_plugin/CMakeLists.txt +++ b/plugins/http_plugin/CMakeLists.txt @@ -3,5 +3,5 @@ add_library( http_plugin http_plugin.cpp ${HEADERS} ) -target_link_libraries( http_plugin appbase fc ) +target_link_libraries( http_plugin eosio_chain appbase fc ) target_include_directories( http_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) diff --git a/plugins/http_plugin/http_plugin.cpp b/plugins/http_plugin/http_plugin.cpp index a768fbd6cb10400e7f46f9199f7b73fc951b9646..6eb378a9eb05c03b481a08fd5ebb886e668c71e5 100644 --- a/plugins/http_plugin/http_plugin.cpp +++ b/plugins/http_plugin/http_plugin.cpp @@ -3,6 +3,7 @@ * @copyright defined in eos/LICENSE.txt */ #include +#include #include #include @@ -129,51 +130,67 @@ namespace eosio { return ctx; } + template + static void handle_exception(typename websocketpp::server>::connection_ptr con) { + string err = "Internal Service error, http: "; + try { + con->set_status( websocketpp::http::status_code::internal_server_error ); + try { + throw; + } catch (const fc::exception& e) { + err += e.to_detail_string(); + elog( "${e}", ("e", err)); + error_results results{websocketpp::http::status_code::internal_server_error, + "Internal Service Error", e}; + con->set_body( fc::json::to_string( results )); + } catch (const std::exception& e) { + err += e.what(); + elog( "${e}", ("e", err)); + error_results results{websocketpp::http::status_code::internal_server_error, + "Internal Service Error", fc::exception( FC_LOG_MESSAGE( error, e.what()))}; + } catch (...) { + err += "Unknown Exception"; + error_results results{websocketpp::http::status_code::internal_server_error, + "Internal Service Error", + fc::exception( FC_LOG_MESSAGE( error, "Unknown Exception" ))}; + con->set_body( fc::json::to_string( results )); + } + } catch (...) { + con->set_body( R"xxx({"message": "Internal Server Error"})xxx" ); + std::cerr << "Exception attempting to handle exception: " << err << std::endl; + } + } + template void handle_http_request(typename websocketpp::server>::connection_ptr con) { try { - if (!access_control_allow_origin.empty()) { - con->append_header("Access-Control-Allow-Origin", access_control_allow_origin); + if( !access_control_allow_origin.empty()) { + con->append_header( "Access-Control-Allow-Origin", access_control_allow_origin ); } - if (!access_control_allow_headers.empty()) { - con->append_header("Access-Control-Allow-Headers", access_control_allow_headers); + if( !access_control_allow_headers.empty()) { + con->append_header( "Access-Control-Allow-Headers", access_control_allow_headers ); } - if (access_control_allow_credentials) { - con->append_header("Access-Control-Allow-Credentials", "true"); + if( access_control_allow_credentials ) { + con->append_header( "Access-Control-Allow-Credentials", "true" ); } - con->append_header("Content-type", "application/json"); + con->append_header( "Content-type", "application/json" ); auto body = con->get_request_body(); auto resource = con->get_uri()->get_resource(); - auto handler_itr = url_handlers.find(resource); - if(handler_itr != url_handlers.end()) { - handler_itr->second(resource, body, [con](auto code, auto&& body) { - con->set_body(std::move(body)); - con->set_status(websocketpp::http::status_code::value(code)); - }); + auto handler_itr = url_handlers.find( resource ); + if( handler_itr != url_handlers.end()) { + handler_itr->second( resource, body, [con]( auto code, auto&& body ) { + con->set_body( std::move( body )); + con->set_status( websocketpp::http::status_code::value( code )); + } ); } else { - wlog("404 - not found: ${ep}", ("ep",resource)); + wlog( "404 - not found: ${ep}", ("ep", resource)); error_results results{websocketpp::http::status_code::not_found, - "Not Found", fc::exception(FC_LOG_MESSAGE(error, "Unknown Endpoint"))}; - con->set_body(fc::json::to_string(results)); - con->set_status(websocketpp::http::status_code::not_found); + "Not Found", fc::exception( FC_LOG_MESSAGE( error, "Unknown Endpoint" ))}; + con->set_body( fc::json::to_string( results )); + con->set_status( websocketpp::http::status_code::not_found ); } - } catch( const fc::exception& e ) { - elog( "http: ${e}", ("e",e.to_detail_string())); - error_results results{websocketpp::http::status_code::internal_server_error, - "Internal Service Error", e}; - con->set_body(fc::json::to_string(results)); - con->set_status(websocketpp::http::status_code::internal_server_error); - } catch( const std::exception& e ) { - elog( "http: ${e}", ("e",e.what())); - error_results results{websocketpp::http::status_code::internal_server_error, - "Internal Service Error", fc::exception(FC_LOG_MESSAGE(error, e.what()))}; - con->set_body(fc::json::to_string(results)); - con->set_status(websocketpp::http::status_code::internal_server_error); } catch( ... ) { - error_results results{websocketpp::http::status_code::internal_server_error, - "Internal Service Error", fc::exception(FC_LOG_MESSAGE(error, "Unknown Exception"))}; - con->set_body(fc::json::to_string(results)); - con->set_status(websocketpp::http::status_code::internal_server_error); + handle_exception( con ); } } @@ -327,4 +344,44 @@ namespace eosio { my->url_handlers.insert(std::make_pair(url,handler)); }); } + + void http_plugin::handle_exception( const char *api_name, const char *call_name, const string& body, url_response_callback cb ) { + try { + try { + throw; + } catch (chain::unsatisfied_authorization& e) { + error_results results{401, "UnAuthorized", e}; + cb( 401, fc::json::to_string( results )); + } catch (chain::tx_duplicate& e) { + error_results results{409, "Conflict", e}; + cb( 409, fc::json::to_string( results )); + } catch (chain::transaction_exception& e) { + error_results results{400, "Bad Request", e}; + cb( 400, fc::json::to_string( results )); + } catch (fc::eof_exception& e) { + error_results results{400, "Bad Request", e}; + cb( 400, fc::json::to_string( results )); + elog( "Unable to parse arguments: ${args}", ("args", body)); + } catch (fc::exception& e) { + error_results results{500, "Internal Service Error", e}; + cb( 500, fc::json::to_string( results )); + elog( "FC Exception encountered while processing ${api}.${call}: ${e}", + ("api", api_name)( "call", call_name )( "e", e.to_detail_string())); + } catch (std::exception& e) { + error_results results{500, "Internal Service Error", fc::exception( FC_LOG_MESSAGE( error, e.what()))}; + cb( 500, fc::json::to_string( results )); + elog( "STD Exception encountered while processing ${api}.${call}: ${e}", + ("api", api_name)( "call", call_name )( "e", e.what())); + } catch (...) { + error_results results{500, "Internal Service Error", + fc::exception( FC_LOG_MESSAGE( error, "Unknown Exception" ))}; + cb( 500, fc::json::to_string( results )); + elog( "Unknown Exception encountered while processing ${api}.${call}", + ("api", api_name)( "call", call_name )); + } + } catch (...) { + std::cerr << "Exception attempting to handle exception for " << api_name << "." << call_name << std::endl; + } + } + } diff --git a/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp b/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp index da2d50124742ed85da01021968bd89d00fd4a32e..0fa7e4c386d5d0e696811f731ce1bc4051405864 100644 --- a/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp +++ b/plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp @@ -73,6 +73,9 @@ namespace eosio { add_handler(call.first, call.second); } + // standard exception handling for api handlers + static void handle_exception( const char *api_name, const char *call_name, const string& body, url_response_callback cb ); + private: std::unique_ptr my; }; diff --git a/plugins/net_api_plugin/net_api_plugin.cpp b/plugins/net_api_plugin/net_api_plugin.cpp index 54d3d25c104facbcf1c78d54ce3b22a5ac1f6981..ad4852a71ccce1609e564d5346484077000d4147 100644 --- a/plugins/net_api_plugin/net_api_plugin.cpp +++ b/plugins/net_api_plugin/net_api_plugin.cpp @@ -30,14 +30,8 @@ using namespace eosio; if (body.empty()) body = "{}"; \ INVOKE \ cb(http_response_code, fc::json::to_string(result)); \ - } catch (fc::eof_exception& e) { \ - error_results results{400, "Bad Request", e}; \ - cb(400, fc::json::to_string(results)); \ - elog("Unable to parse arguments: ${args}", ("args", body)); \ - } catch (fc::exception& e) { \ - error_results results{500, "Internal Service Error", e}; \ - cb(500, fc::json::to_string(results)); \ - elog("Exception encountered while processing ${call}: ${e}", ("call", #api_name "." #call_name)("e", e)); \ + } catch (...) { \ + http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ }} diff --git a/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp b/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp index 0d0f393483bb98fc49a5b79990ffb2fc79ce3a13..97c421dc9a0741ee574d3e888b675a1f25e7230e 100644 --- a/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp +++ b/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp @@ -45,14 +45,8 @@ using namespace eosio::chain; if (body.empty()) body = "{}"; \ INVOKE \ cb(http_response_code, fc::json::to_string(result)); \ - } catch (fc::eof_exception& e) { \ - error_results results{400, "Bad Request", e}; \ - cb(400, fc::json::to_string(results)); \ - elog("Unable to parse arguments: ${args}", ("args", body)); \ - } catch (fc::exception& e) { \ - error_results results{500, "Internal Service Error", e}; \ - cb(500, fc::json::to_string(results)); \ - elog("Exception encountered while processing ${call}: ${e}", ("call", #api_name "." #call_name)("e", e)); \ + } catch (...) { \ + http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ }} diff --git a/plugins/wallet_api_plugin/wallet_api_plugin.cpp b/plugins/wallet_api_plugin/wallet_api_plugin.cpp index d08bcf5098ca2b7fea9f1f03968235237e2a42f5..d11faccb330e093ba61aa9eca8e4ccc0483e4b67 100644 --- a/plugins/wallet_api_plugin/wallet_api_plugin.cpp +++ b/plugins/wallet_api_plugin/wallet_api_plugin.cpp @@ -31,14 +31,8 @@ using namespace eosio; if (body.empty()) body = "{}"; \ INVOKE \ cb(http_response_code, fc::json::to_string(result)); \ - } catch (fc::eof_exception& e) { \ - error_results results{400, "Bad Request", e}; \ - cb(400, fc::json::to_string(results)); \ - elog("Unable to parse arguments: ${args}", ("args", body)); \ - } catch (fc::exception& e) { \ - error_results results{500, "Internal Service Error", e}; \ - cb(500, fc::json::to_string(results)); \ - elog("Exception encountered while processing ${call}: ${e}", ("call", #api_name "." #call_name)("e", e)); \ + } catch (...) { \ + http_plugin::handle_exception(#api_name, #call_name, body, cb); \ } \ }} diff --git a/programs/cleos/main.cpp b/programs/cleos/main.cpp index fda8327ad26ce0c6e6760afdd50d4359e948ac5f..23f5e4388c4534940a1170729d1a73fb202e6986 100644 --- a/programs/cleos/main.cpp +++ b/programs/cleos/main.cpp @@ -576,7 +576,7 @@ authority parse_json_authority_or_key(const std::string& authorityJsonOrFile) { asset to_asset( const string& code, const string& s ) { static map cache; auto a = asset::from_string( s ); - eosio::chain::symbol_code sym = a.sym.to_symbol_code(); + eosio::chain::symbol_code sym = a.get_symbol().to_symbol_code(); auto it = cache.find( sym ); auto sym_str = a.symbol_name(); if ( it == cache.end() ) { @@ -588,7 +588,7 @@ asset to_asset( const string& code, const string& s ) { auto obj_it = obj.find( sym_str ); if (obj_it != obj.end()) { auto result = obj_it->value().as(); - auto p = cache.insert(make_pair( sym, result.max_supply.sym )); + auto p = cache.insert(make_pair( sym, result.max_supply.get_symbol() )); it = p.first; } else { FC_THROW("Symbol ${s} is not supported by token contract ${c}", ("s", sym_str)("c", code)); @@ -598,7 +598,7 @@ asset to_asset( const string& code, const string& s ) { if ( a.decimals() < expected_symbol.decimals() ) { auto factor = expected_symbol.precision() / a.precision(); auto a_old = a; - a = asset( a.amount * factor, expected_symbol ); + a = asset( a.get_amount() * factor, expected_symbol ); } else if ( a.decimals() > expected_symbol.decimals() ) { FC_THROW("Too many decimal digits in ${a}, only ${d} supported", ("a", a)("d", expected_symbol.decimals())); } // else precision matches diff --git a/unittests/bootseq_tests.cpp b/unittests/bootseq_tests.cpp index 786c641468bbe1a0be53e06faa4aa56c5579b542..7c140d21fc433119e273aedf3d7130be61ca4c65 100644 --- a/unittests/bootseq_tests.cpp +++ b/unittests/bootseq_tests.cpp @@ -309,7 +309,7 @@ BOOST_FIXTURE_TEST_CASE( bootseq_test, bootseq_tester ) { produce_min_num_of_blocks_to_spend_time_wo_inactive_prod(fc::seconds(30 * 24 * 3600)); // 30 days // Since the total activated stake is larger than 150,000,000, pool should be filled reward should be bigger than zero claim_rewards(N(runnerup1)); - BOOST_TEST(get_balance(N(runnerup1)).amount > 0); + BOOST_TEST(get_balance(N(runnerup1)).get_amount() > 0); const auto first_june_2018 = fc::seconds(1527811200); // 2018-06-01 const auto first_june_2028 = fc::seconds(1843430400); // 2028-06-01 diff --git a/unittests/currency_tests.cpp b/unittests/currency_tests.cpp index 6e46d8af238f279758f0b18acd7cb248014e41f1..eb5ba9613765b69431899183fc590441370b8846 100644 --- a/unittests/currency_tests.cpp +++ b/unittests/currency_tests.cpp @@ -329,7 +329,7 @@ BOOST_FIXTURE_TEST_CASE(test_symbol, TESTER) try { // Missing decimal point, should create asset with 0 decimals { asset a = asset::from_string("10 CUR"); - BOOST_REQUIRE_EQUAL(a.amount, 10); + BOOST_REQUIRE_EQUAL(a.get_amount(), 10); BOOST_REQUIRE_EQUAL(a.precision(), 1); BOOST_REQUIRE_EQUAL(a.decimals(), 0); BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR"); @@ -356,7 +356,7 @@ BOOST_FIXTURE_TEST_CASE(test_symbol, TESTER) try { // Multiple spaces { asset a = asset::from_string("1000000000.00000 CUR"); - BOOST_REQUIRE_EQUAL(a.amount, 100000000000000); + BOOST_REQUIRE_EQUAL(a.get_amount(), 100000000000000); BOOST_REQUIRE_EQUAL(a.decimals(), 5); BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR"); BOOST_REQUIRE_EQUAL(a.to_string(), "1000000000.00000 CUR"); @@ -365,7 +365,7 @@ BOOST_FIXTURE_TEST_CASE(test_symbol, TESTER) try { // Valid asset { asset a = asset::from_string("1000000000.00000 CUR"); - BOOST_REQUIRE_EQUAL(a.amount, 100000000000000); + BOOST_REQUIRE_EQUAL(a.get_amount(), 100000000000000); BOOST_REQUIRE_EQUAL(a.decimals(), 5); BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR"); BOOST_REQUIRE_EQUAL(a.to_string(), "1000000000.00000 CUR"); @@ -374,7 +374,7 @@ BOOST_FIXTURE_TEST_CASE(test_symbol, TESTER) try { // Negative asset { asset a = asset::from_string("-001000000.00010 CUR"); - BOOST_REQUIRE_EQUAL(a.amount, -100000000010); + BOOST_REQUIRE_EQUAL(a.get_amount(), -100000000010); BOOST_REQUIRE_EQUAL(a.decimals(), 5); BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR"); BOOST_REQUIRE_EQUAL(a.to_string(), "-1000000.00010 CUR"); @@ -383,7 +383,7 @@ BOOST_FIXTURE_TEST_CASE(test_symbol, TESTER) try { // Negative asset below 1 { asset a = asset::from_string("-000000000.00100 CUR"); - BOOST_REQUIRE_EQUAL(a.amount, -100); + BOOST_REQUIRE_EQUAL(a.get_amount(), -100); BOOST_REQUIRE_EQUAL(a.decimals(), 5); BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR"); BOOST_REQUIRE_EQUAL(a.to_string(), "-0.00100 CUR"); @@ -392,7 +392,7 @@ BOOST_FIXTURE_TEST_CASE(test_symbol, TESTER) try { // Negative asset below 1 { asset a = asset::from_string("-0.0001 PPP"); - BOOST_REQUIRE_EQUAL(a.amount, -1); + BOOST_REQUIRE_EQUAL(a.get_amount(), -1); BOOST_REQUIRE_EQUAL(a.decimals(), 4); BOOST_REQUIRE_EQUAL(a.symbol_name(), "PPP"); BOOST_REQUIRE_EQUAL(a.to_string(), "-0.0001 PPP"); @@ -575,7 +575,7 @@ BOOST_FIXTURE_TEST_CASE( test_input_quantity, currency_tester ) try { BOOST_CHECK_EQUAL(true, chain_has_transaction(trace->id)); BOOST_CHECK_EQUAL(asset::from_string( "100.0000 CUR"), get_balance(N(alice))); - BOOST_CHECK_EQUAL(1000000, get_balance(N(alice)).amount); + BOOST_CHECK_EQUAL(1000000, get_balance(N(alice)).get_amount()); } diff --git a/unittests/eosio.system_tests.cpp b/unittests/eosio.system_tests.cpp index fa595f796d373063674041280a224a6fa1b5bb89..8de1945c17c4cda93475def3f86c1b99aff59a71 100644 --- a/unittests/eosio.system_tests.cpp +++ b/unittests/eosio.system_tests.cpp @@ -139,8 +139,8 @@ BOOST_FIXTURE_TEST_CASE( stake_unstake, eosio_system_tester ) try { BOOST_REQUIRE_EQUAL( core_from_string("110.0000"), total["cpu_weight"].as()); total = get_total_stake( "alice1111111" ); - BOOST_REQUIRE_EQUAL( core_from_string("210.0000").amount, total["net_weight"].as().amount ); - BOOST_REQUIRE_EQUAL( core_from_string("110.0000").amount, total["cpu_weight"].as().amount ); + BOOST_REQUIRE_EQUAL( core_from_string("210.0000").get_amount(), total["net_weight"].as().get_amount() ); + BOOST_REQUIRE_EQUAL( core_from_string("110.0000").get_amount(), total["cpu_weight"].as().get_amount() ); REQUIRE_MATCHING_OBJECT( voter( "alice1111111", core_from_string("300.0000")), get_voter_info( "alice1111111" ) ); @@ -1147,22 +1147,22 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, eosio_system_tester, * boost::unit_test::t BOOST_REQUIRE_EQUAL(0, initial_perblock_bucket); BOOST_REQUIRE_EQUAL(0, initial_pervote_bucket); - BOOST_REQUIRE_EQUAL(int64_t( ( initial_supply.amount * double(secs_between_fills) * continuous_rate ) / secs_per_year ), - supply.amount - initial_supply.amount); - BOOST_REQUIRE_EQUAL(int64_t( ( initial_supply.amount * double(secs_between_fills) * (4. * continuous_rate/ 5.) / secs_per_year ) ), + BOOST_REQUIRE_EQUAL(int64_t( ( initial_supply.get_amount() * double(secs_between_fills) * continuous_rate ) / secs_per_year ), + supply.get_amount() - initial_supply.get_amount()); + BOOST_REQUIRE_EQUAL(int64_t( ( initial_supply.get_amount() * double(secs_between_fills) * (4. * continuous_rate/ 5.) / secs_per_year ) ), savings - initial_savings); - BOOST_REQUIRE_EQUAL(int64_t( ( initial_supply.amount * double(secs_between_fills) * (0.25 * continuous_rate/ 5.) / secs_per_year ) ), - balance.amount - initial_balance.amount); + BOOST_REQUIRE_EQUAL(int64_t( ( initial_supply.get_amount() * double(secs_between_fills) * (0.25 * continuous_rate/ 5.) / secs_per_year ) ), + balance.get_amount() - initial_balance.get_amount()); - int64_t from_perblock_bucket = int64_t( initial_supply.amount * double(secs_between_fills) * (0.25 * continuous_rate/ 5.) / secs_per_year ) ; - int64_t from_pervote_bucket = int64_t( initial_supply.amount * double(secs_between_fills) * (0.75 * continuous_rate/ 5.) / secs_per_year ) ; + int64_t from_perblock_bucket = int64_t( initial_supply.get_amount() * double(secs_between_fills) * (0.25 * continuous_rate/ 5.) / secs_per_year ) ; + int64_t from_pervote_bucket = int64_t( initial_supply.get_amount() * double(secs_between_fills) * (0.75 * continuous_rate/ 5.) / secs_per_year ) ; if (from_pervote_bucket >= 100 * 10000) { - BOOST_REQUIRE_EQUAL(from_perblock_bucket + from_pervote_bucket, balance.amount - initial_balance.amount); + BOOST_REQUIRE_EQUAL(from_perblock_bucket + from_pervote_bucket, balance.get_amount() - initial_balance.get_amount()); BOOST_REQUIRE_EQUAL(0, pervote_bucket); } else { - BOOST_REQUIRE_EQUAL(from_perblock_bucket, balance.amount - initial_balance.amount); + BOOST_REQUIRE_EQUAL(from_perblock_bucket, balance.get_amount() - initial_balance.get_amount()); BOOST_REQUIRE_EQUAL(from_pervote_bucket, pervote_bucket); } } @@ -1224,20 +1224,20 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, eosio_system_tester, * boost::unit_test::t BOOST_REQUIRE_EQUAL(claim_time, prod["last_claim_time"].as()); auto usecs_between_fills = claim_time - initial_claim_time; - BOOST_REQUIRE_EQUAL(int64_t( ( double(initial_supply.amount) * double(usecs_between_fills) * continuous_rate / usecs_per_year ) ), - supply.amount - initial_supply.amount); - BOOST_REQUIRE_EQUAL( (supply.amount - initial_supply.amount) - (supply.amount - initial_supply.amount) / 5, + BOOST_REQUIRE_EQUAL(int64_t( ( double(initial_supply.get_amount()) * double(usecs_between_fills) * continuous_rate / usecs_per_year ) ), + supply.get_amount() - initial_supply.get_amount()); + BOOST_REQUIRE_EQUAL( (supply.get_amount() - initial_supply.get_amount()) - (supply.get_amount() - initial_supply.get_amount()) / 5, savings - initial_savings); - int64_t to_producer = int64_t( (double(initial_supply.amount) * double(usecs_between_fills) * continuous_rate) / usecs_per_year ) / 5; + int64_t to_producer = int64_t( (double(initial_supply.get_amount()) * double(usecs_between_fills) * continuous_rate) / usecs_per_year ) / 5; int64_t to_perblock_bucket = to_producer / 4; int64_t to_pervote_bucket = to_producer - to_perblock_bucket; if (to_pervote_bucket + initial_pervote_bucket >= 100 * 10000) { - BOOST_REQUIRE_EQUAL(to_perblock_bucket + to_pervote_bucket + initial_pervote_bucket, balance.amount - initial_balance.amount); + BOOST_REQUIRE_EQUAL(to_perblock_bucket + to_pervote_bucket + initial_pervote_bucket, balance.get_amount() - initial_balance.get_amount()); BOOST_REQUIRE_EQUAL(0, pervote_bucket); } else { - BOOST_REQUIRE_EQUAL(to_perblock_bucket, balance.amount - initial_balance.amount); + BOOST_REQUIRE_EQUAL(to_perblock_bucket, balance.get_amount() - initial_balance.get_amount()); BOOST_REQUIRE_EQUAL(to_pervote_bucket + initial_pervote_bucket, pervote_bucket); } } @@ -1266,8 +1266,8 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, eosio_system_tester, * boost::unit_test::t const int64_t savings = get_global_state()["savings"].as(); // Amount issued per year is very close to the 5% inflation target. Small difference (500 tokens out of 50'000'000 issued) // is due to compounding every 8 hours in this test as opposed to theoretical continuous compounding - BOOST_REQUIRE(500 * 10000 > int64_t(double(initial_supply.amount) * double(0.05)) - (supply.amount - initial_supply.amount)); - BOOST_REQUIRE(500 * 10000 > int64_t(double(initial_supply.amount) * double(0.04)) - (savings - initial_savings)); + BOOST_REQUIRE(500 * 10000 > int64_t(double(initial_supply.get_amount()) * double(0.05)) - (supply.get_amount() - initial_supply.get_amount())); + BOOST_REQUIRE(500 * 10000 > int64_t(double(initial_supply.get_amount()) * double(0.04)) - (savings - initial_savings)); } } FC_LOG_AND_RETHROW() @@ -1422,12 +1422,13 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni const uint64_t usecs_between_fills = claim_time - initial_claim_time; const int32_t secs_between_fills = static_cast(usecs_between_fills / 1000000); - const double expected_supply_growth = initial_supply.amount * double(usecs_between_fills) * cont_rate / usecs_per_year; - BOOST_REQUIRE_EQUAL( int64_t(expected_supply_growth), supply.amount - initial_supply.amount ); + const double expected_supply_growth = initial_supply.get_amount() * double(usecs_between_fills) * cont_rate / usecs_per_year; + BOOST_REQUIRE_EQUAL( int64_t(expected_supply_growth), supply.get_amount() - initial_supply.get_amount() ); + BOOST_REQUIRE_EQUAL( int64_t(expected_supply_growth) - int64_t(expected_supply_growth)/5, savings - initial_savings ); - const int64_t expected_perblock_bucket = int64_t( initial_supply.amount * secs_between_fills * (0.25 * cont_rate/ 5.) / secs_per_year ) ; - const int64_t expected_pervote_bucket = int64_t( initial_supply.amount * secs_between_fills * (0.75 * cont_rate/ 5.) / secs_per_year ) ; + const int64_t expected_perblock_bucket = int64_t( initial_supply.get_amount() * secs_between_fills * (0.25 * cont_rate/ 5.) / secs_per_year ) ; + const int64_t expected_pervote_bucket = int64_t( initial_supply.get_amount() * secs_between_fills * (0.75 * cont_rate/ 5.) / secs_per_year ) ; const int64_t from_perblock_bucket = initial_unpaid_blocks * expected_perblock_bucket / initial_tot_unpaid_blocks ; const int64_t from_pervote_bucket = int64_t( vote_shares[prod_index] * expected_pervote_bucket); @@ -1435,10 +1436,10 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni BOOST_REQUIRE( 1 >= abs(int32_t(initial_tot_unpaid_blocks - tot_unpaid_blocks) - int32_t(initial_unpaid_blocks - unpaid_blocks)) ); if (from_pervote_bucket >= 100 * 10000) { - BOOST_REQUIRE_EQUAL(from_perblock_bucket + from_pervote_bucket, balance.amount - initial_balance.amount); + BOOST_REQUIRE_EQUAL(from_perblock_bucket + from_pervote_bucket, balance.get_amount() - initial_balance.get_amount()); BOOST_REQUIRE_EQUAL(expected_pervote_bucket - from_pervote_bucket, pervote_bucket); } else { - BOOST_REQUIRE_EQUAL(from_perblock_bucket, balance.amount - initial_balance.amount); + BOOST_REQUIRE_EQUAL(from_perblock_bucket, balance.get_amount() - initial_balance.get_amount()); BOOST_REQUIRE_EQUAL(expected_pervote_bucket, pervote_bucket); } @@ -1453,7 +1454,7 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni const auto prod_name = producer_names[prod_index]; BOOST_REQUIRE_EQUAL(success(), push_action(prod_name, N(claimrewards), mvo()("owner", prod_name))); - BOOST_REQUIRE_EQUAL(0, get_balance(prod_name).amount); + BOOST_REQUIRE_EQUAL(0, get_balance(prod_name).get_amount()); BOOST_REQUIRE_EQUAL(wasm_assert_msg("already claimed rewards within past day"), push_action(prod_name, N(claimrewards), mvo()("owner", prod_name))); } @@ -1491,23 +1492,23 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni const uint64_t usecs_between_fills = claim_time - initial_claim_time; - const double expected_supply_growth = initial_supply.amount * double(usecs_between_fills) * cont_rate / usecs_per_year; - BOOST_REQUIRE_EQUAL( int64_t(expected_supply_growth), supply.amount - initial_supply.amount ); + const double expected_supply_growth = initial_supply.get_amount() * double(usecs_between_fills) * cont_rate / usecs_per_year; + BOOST_REQUIRE_EQUAL( int64_t(expected_supply_growth), supply.get_amount() - initial_supply.get_amount() ); BOOST_REQUIRE_EQUAL( int64_t(expected_supply_growth) - int64_t(expected_supply_growth)/5, savings - initial_savings ); - const int64_t expected_perblock_bucket = int64_t( initial_supply.amount * double(usecs_between_fills) * (0.25 * cont_rate/ 5.) / usecs_per_year ) + const int64_t expected_perblock_bucket = int64_t( initial_supply.get_amount() * double(usecs_between_fills) * (0.25 * cont_rate/ 5.) / usecs_per_year ) + initial_perblock_bucket; - const int64_t expected_pervote_bucket = int64_t( initial_supply.amount * double(usecs_between_fills) * (0.75 * cont_rate/ 5.) / usecs_per_year ) + const int64_t expected_pervote_bucket = int64_t( initial_supply.get_amount() * double(usecs_between_fills) * (0.75 * cont_rate/ 5.) / usecs_per_year ) + initial_pervote_bucket; const int64_t from_perblock_bucket = initial_unpaid_blocks * expected_perblock_bucket / initial_tot_unpaid_blocks ; const int64_t from_pervote_bucket = int64_t( vote_shares[prod_index] * expected_pervote_bucket); BOOST_REQUIRE( 1 >= abs(int32_t(initial_tot_unpaid_blocks - tot_unpaid_blocks) - int32_t(initial_unpaid_blocks - unpaid_blocks)) ); if (from_pervote_bucket >= 100 * 10000) { - BOOST_REQUIRE_EQUAL(from_perblock_bucket + from_pervote_bucket, balance.amount - initial_balance.amount); + BOOST_REQUIRE_EQUAL(from_perblock_bucket + from_pervote_bucket, balance.get_amount() - initial_balance.get_amount()); BOOST_REQUIRE_EQUAL(expected_pervote_bucket - from_pervote_bucket, pervote_bucket); } else { - BOOST_REQUIRE_EQUAL(from_perblock_bucket, balance.amount - initial_balance.amount); + BOOST_REQUIRE_EQUAL(from_perblock_bucket, balance.get_amount() - initial_balance.get_amount()); BOOST_REQUIRE_EQUAL(expected_pervote_bucket, pervote_bucket); } @@ -1522,7 +1523,7 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni const auto prod_name = producer_names[prod_index]; BOOST_REQUIRE_EQUAL(success(), push_action(prod_name, N(claimrewards), mvo()("owner", prod_name))); - BOOST_REQUIRE(100 * 10000 <= get_balance(prod_name).amount); + BOOST_REQUIRE(100 * 10000 <= get_balance(prod_name).get_amount()); BOOST_REQUIRE_EQUAL(wasm_assert_msg("already claimed rewards within past day"), push_action(prod_name, N(claimrewards), mvo()("owner", prod_name))); } @@ -1807,10 +1808,10 @@ BOOST_FIXTURE_TEST_CASE(producer_onblock_check, eosio_system_tester) try { BOOST_CHECK_EQUAL(0, get_global_state()["total_unpaid_blocks"].as()); BOOST_REQUIRE_EQUAL(wasm_assert_msg("not enough has been staked for producers to claim rewards"), push_action(producer_names.front(), N(claimrewards), mvo()("owner", producer_names.front()))); - BOOST_REQUIRE_EQUAL(0, get_balance(producer_names.front()).amount); + BOOST_REQUIRE_EQUAL(0, get_balance(producer_names.front()).get_amount()); BOOST_REQUIRE_EQUAL(wasm_assert_msg("not enough has been staked for producers to claim rewards"), push_action(producer_names.back(), N(claimrewards), mvo()("owner", producer_names.back()))); - BOOST_REQUIRE_EQUAL(0, get_balance(producer_names.back()).amount); + BOOST_REQUIRE_EQUAL(0, get_balance(producer_names.back()).get_amount()); } // stake across 15% boundary @@ -1852,7 +1853,7 @@ BOOST_FIXTURE_TEST_CASE(producer_onblock_check, eosio_system_tester) try { BOOST_REQUIRE_EQUAL(true, rest_didnt_produce); BOOST_REQUIRE_EQUAL(success(), push_action(producer_names.front(), N(claimrewards), mvo()("owner", producer_names.front()))); - BOOST_REQUIRE(0 < get_balance(producer_names.front()).amount); + BOOST_REQUIRE(0 < get_balance(producer_names.front()).get_amount()); } } FC_LOG_AND_RETHROW() diff --git a/unittests/eosio.token_tests.cpp b/unittests/eosio.token_tests.cpp index ea084bd0d07f2c4af6488f3f46b840526c60494d..b181ff85b4fe90d67bcd6a77b4a2b95d4e76112a 100644 --- a/unittests/eosio.token_tests.cpp +++ b/unittests/eosio.token_tests.cpp @@ -149,7 +149,10 @@ BOOST_FIXTURE_TEST_CASE( create_max_supply, eosio_token_tester ) try { produce_blocks(1); asset max(10, symbol(SY(0, NKT))); - max.amount = 4611686018427387904; + share_type amount = 4611686018427387904; + static_assert(sizeof(share_type) <= sizeof(asset), "asset changed so test is no longer valid"); + static_assert(std::is_trivially_copyable::value, "asset is not trivially copyable"); + memcpy(&max, &amount, sizeof(share_type)); // hack in an invalid amount BOOST_CHECK_EXCEPTION( create( N(alice), max) , asset_type_exception, [](const asset_type_exception& e) { return expect_assert_message(e, "magnitude of asset amount must be less than 2^62"); @@ -171,7 +174,10 @@ BOOST_FIXTURE_TEST_CASE( create_max_decimals, eosio_token_tester ) try { asset max(10, symbol(SY(0, NKT))); //1.0000000000000000000 => 0x8ac7230489e80000L - max.amount = 0x8ac7230489e80000L; + share_type amount = 0x8ac7230489e80000L; + static_assert(sizeof(share_type) <= sizeof(asset), "asset changed so test is no longer valid"); + static_assert(std::is_trivially_copyable::value, "asset is not trivially copyable"); + memcpy(&max, &amount, sizeof(share_type)); // hack in an invalid amount BOOST_CHECK_EXCEPTION( create( N(alice), max) , asset_type_exception, [](const asset_type_exception& e) { return expect_assert_message(e, "magnitude of asset amount must be less than 2^62"); diff --git a/unittests/eosio_system_tester.hpp b/unittests/eosio_system_tester.hpp index 673af4a6f111f3b52eafa9dfc4b73d80683284d1..a145a54b2851a4400184a3c44c3c56e626de7962 100644 --- a/unittests/eosio_system_tester.hpp +++ b/unittests/eosio_system_tester.hpp @@ -368,7 +368,7 @@ public: double stake2votes( asset stake ) { auto now = control->pending_block_time().time_since_epoch().count() / 1000000; - return stake.amount * pow(2, int64_t((now - (config::block_timestamp_epoch / 1000)) / (86400 * 7))/ double(52) ); // 52 week periods (i.e. ~years) + return stake.get_amount() * pow(2, int64_t((now - (config::block_timestamp_epoch / 1000)) / (86400 * 7))/ double(52) ); // 52 week periods (i.e. ~years) } double stake2votes( const string& s ) { @@ -418,7 +418,7 @@ inline fc::mutable_variant_object voter( account_name acct ) { } inline fc::mutable_variant_object voter( account_name acct, const asset& vote_stake ) { - return voter( acct )( "staked", vote_stake.amount ); + return voter( acct )( "staked", vote_stake.get_amount() ); } inline fc::mutable_variant_object voter( account_name acct, int64_t vote_stake ) { @@ -430,7 +430,7 @@ inline fc::mutable_variant_object proxy( account_name acct ) { } inline uint64_t M( const string& eos_str ) { - return core_from_string( eos_str ).amount; + return core_from_string( eos_str ).get_amount(); } } diff --git a/unittests/misc_tests.cpp b/unittests/misc_tests.cpp index 1c304e2a11f8b8377ce13aef088e751e9cc02f33..c13a143bdad0d0d1b5e9e4832845a62da06aa542 100644 --- a/unittests/misc_tests.cpp +++ b/unittests/misc_tests.cpp @@ -59,23 +59,23 @@ BOOST_AUTO_TEST_CASE(asset_from_string_overflow) // precision = 19, magnitude < 2^61 BOOST_CHECK_EXCEPTION( asset::from_string("0.1000000000000000000 CUR") , assert_exception, [](const assert_exception& e) { - return expect_assert_message(e, "precision should be <= 18"); + return expect_assert_message(e, "precision 19 should be <= 18"); }); BOOST_CHECK_EXCEPTION( asset::from_string("-0.1000000000000000000 CUR") , assert_exception, [](const assert_exception& e) { - return expect_assert_message(e, "precision should be <= 18"); + return expect_assert_message(e, "precision 19 should be <= 18"); }); BOOST_CHECK_EXCEPTION( asset::from_string("1.0000000000000000000 CUR") , assert_exception, [](const assert_exception& e) { - return expect_assert_message(e, "precision should be <= 18"); + return expect_assert_message(e, "precision 19 should be <= 18"); }); BOOST_CHECK_EXCEPTION( asset::from_string("-1.0000000000000000000 CUR") , assert_exception, [](const assert_exception& e) { - return expect_assert_message(e, "precision should be <= 18"); + return expect_assert_message(e, "precision 19 should be <= 18"); }); // precision = 18, magnitude < 2^58 a = asset::from_string("0.100000000000000000 CUR"); - BOOST_CHECK_EQUAL(a.amount, 100000000000000000L); + BOOST_CHECK_EQUAL(a.get_amount(), 100000000000000000L); a = asset::from_string("-0.100000000000000000 CUR"); - BOOST_CHECK_EQUAL(a.amount, -100000000000000000L); + BOOST_CHECK_EQUAL(a.get_amount(), -100000000000000000L); // precision = 18, magnitude = 2^62 BOOST_CHECK_EXCEPTION( asset::from_string("4.611686018427387904 CUR") , asset_type_exception, [](const asset_type_exception& e) { @@ -93,9 +93,9 @@ BOOST_AUTO_TEST_CASE(asset_from_string_overflow) // precision = 18, magnitude = 2^62-1 a = asset::from_string("4.611686018427387903 CUR"); - BOOST_CHECK_EQUAL(a.amount, 4611686018427387903L); + BOOST_CHECK_EQUAL(a.get_amount(), 4611686018427387903L); a = asset::from_string("-4.611686018427387903 CUR"); - BOOST_CHECK_EQUAL(a.amount, -4611686018427387903L); + BOOST_CHECK_EQUAL(a.get_amount(), -4611686018427387903L); // precision = 0, magnitude = 2^62 BOOST_CHECK_EXCEPTION( asset::from_string("4611686018427387904 CUR") , asset_type_exception, [](const asset_type_exception& e) { @@ -107,9 +107,9 @@ BOOST_AUTO_TEST_CASE(asset_from_string_overflow) // precision = 0, magnitude = 2^62-1 a = asset::from_string("4611686018427387903 CUR"); - BOOST_CHECK_EQUAL(a.amount, 4611686018427387903L); + BOOST_CHECK_EQUAL(a.get_amount(), 4611686018427387903L); a = asset::from_string("-4611686018427387903 CUR"); - BOOST_CHECK_EQUAL(a.amount, -4611686018427387903L); + BOOST_CHECK_EQUAL(a.get_amount(), -4611686018427387903L); // precision = 18, magnitude = 2^65 BOOST_CHECK_EXCEPTION( asset::from_string("36.893488147419103232 CUR") , overflow_exception, [](const overflow_exception& e) { @@ -137,10 +137,10 @@ BOOST_AUTO_TEST_CASE(asset_from_string_overflow) // precision = 20, magnitude > 2^142 BOOST_CHECK_EXCEPTION( asset::from_string("100000000000000000000000.00000000000000000000 CUR") , assert_exception, [](const assert_exception& e) { - return expect_assert_message(e, "precision should be <= 18"); + return expect_assert_message(e, "precision 20 should be <= 18"); }); BOOST_CHECK_EXCEPTION( asset::from_string("-100000000000000000000000.00000000000000000000 CUR") , assert_exception, [](const assert_exception& e) { - return expect_assert_message(e, "precision should be <= 18"); + return expect_assert_message(e, "precision 20 should be <= 18"); }); }