未验证 提交 2d1844c6 编写于 作者: K Kevin Heifner 提交者: GitHub

Merge pull request #3277 from EOSIO/gh#3219-nodeos-crash

Gh#3219 nodeos crash
......@@ -461,12 +461,12 @@ namespace impl {
* @tparam Reslover - callable with the signature (const name& code_account) -> optional<abi_def>
*/
template<typename T, typename Resolver>
class abi_from_variant_visitor
class abi_from_variant_visitor : reflector_verifier_visitor<T>
{
public:
abi_from_variant_visitor( const variant_object& _vo, T& v, Resolver _resolver )
:_vo(_vo)
,_val(v)
: reflector_verifier_visitor<T>(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;
};
......
......@@ -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<asset>;
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 {
......
......@@ -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<symbol>;
......
......@@ -350,17 +350,17 @@ namespace fc {
};
template<typename Stream, typename Class>
struct unpack_object_visitor {
struct unpack_object_visitor : fc::reflector_verifier_visitor<Class> {
unpack_object_visitor(Class& _c, Stream& _s)
:c(_c),s(_s){}
: fc::reflector_verifier_visitor<Class>(_c), s(_s){}
template<typename T, typename C, T(C::*p)>
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;
};
......
......@@ -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<typename Class>
* struct functor : reflector_verifier_visitor<Class> {
* functor(Class& _c)
* : fc::reflector_verifier_visitor<Class>(_c) {}
*
* template<typename Member, class Class, Member (Class::*member)>
* 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 <typename Class>
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<class T>
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<class T>
auto verify_imp(const T& t, long) -> decltype(t, void()) {}
template<typename T>
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<typename Visitor>\
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<TYPE> {\
typedef TYPE type; \
typedef fc::true_type is_defined; \
typedef fc::false_type is_enum; \
template<typename Visitor> \
static auto verify_imp(const Visitor& v, int) -> decltype(v.reflector_verify(), void()) { \
v.reflector_verify(); \
} \
template<typename Visitor> \
static auto verify_imp(const Visitor& v, long) -> decltype(v, void()) {} \
template<typename Visitor> \
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<BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct reflector<TYPE> {\
typedef TYPE type; \
typedef fc::true_type is_defined; \
typedef fc::false_type is_enum; \
template<typename Visitor> \
static auto verify_imp(const Visitor& v, int) -> decltype(v.reflector_verify(), void()) { \
v.reflector_verify(); \
} \
template<typename Visitor> \
static auto verify_imp(const Visitor& v, long) -> decltype(v, void()) {} \
template<typename Visitor> \
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 )\
......
......@@ -39,22 +39,22 @@ namespace fc
};
template<typename T>
class from_variant_visitor
class from_variant_visitor : reflector_verifier_visitor<T>
{
public:
from_variant_visitor( const variant_object& _vo, T& v )
:vo(_vo),val(v){}
:reflector_verifier_visitor<T>(v)
,vo(_vo){}
template<typename Member, class Class, Member (Class::*member)>
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<typename IsReflected=fc::false_type>
......
......@@ -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 << ": " <<my->_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();
}
/**
......
......@@ -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<api_namespace::call_name ## _params>()); \
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); \
} \
}}
......
......@@ -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<api_namespace::call_name ## _params>()); \
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); \
} \
}}
......
......@@ -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); \
} \
}}
......
......@@ -62,14 +62,8 @@ using results_pair = std::pair<uint32_t,fc::variant>;
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); \
} \
}}
......
......@@ -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<api_namespace::call_name ## _params>()); \
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); \
} \
}}
......
......@@ -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" )
......@@ -3,6 +3,7 @@
* @copyright defined in eos/LICENSE.txt
*/
#include <eosio/http_plugin/http_plugin.hpp>
#include <eosio/chain/exceptions.hpp>
#include <fc/network/ip.hpp>
#include <fc/log/logger_config.hpp>
......@@ -129,51 +130,67 @@ namespace eosio {
return ctx;
}
template<class T>
static void handle_exception(typename websocketpp::server<detail::asio_with_stub_log<T>>::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<class T>
void handle_http_request(typename websocketpp::server<detail::asio_with_stub_log<T>>::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<T>( 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;
}
}
}
......@@ -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<class http_plugin_impl> my;
};
......
......@@ -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); \
} \
}}
......
......@@ -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); \
} \
}}
......
......@@ -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); \
} \
}}
......
......@@ -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<eosio::chain::symbol_code, eosio::chain::symbol> 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<eosio::chain_apis::read_only::get_currency_stats_result>();
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
......
......@@ -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
......
......@@ -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());
}
......
......@@ -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<asset>());
total = get_total_stake( "alice1111111" );
BOOST_REQUIRE_EQUAL( core_from_string("210.0000").amount, total["net_weight"].as<asset>().amount );
BOOST_REQUIRE_EQUAL( core_from_string("110.0000").amount, total["cpu_weight"].as<asset>().amount );
BOOST_REQUIRE_EQUAL( core_from_string("210.0000").get_amount(), total["net_weight"].as<asset>().get_amount() );
BOOST_REQUIRE_EQUAL( core_from_string("110.0000").get_amount(), total["cpu_weight"].as<asset>().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<uint64_t>());
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<int64_t>();
// 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<int32_t>(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<uint32_t>());
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()
......
......@@ -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<asset>::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<asset>::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");
......
......@@ -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();
}
}
......@@ -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");
});
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册