未验证 提交 360e3329 编写于 作者: K Kevin Heifner 提交者: GitHub

Merge pull request #1856 from EOSIO/1616

#1616 - Asset symbol without .
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <boost/rational.hpp> #include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp> #include <boost/multiprecision/cpp_int.hpp>
#include <fc/reflect/variant.hpp> #include <fc/reflect/variant.hpp>
#include <eosio/chain/exceptions.hpp>
namespace eosio { namespace chain { namespace eosio { namespace chain {
typedef boost::multiprecision::int128_t int128_t; typedef boost::multiprecision::int128_t int128_t;
...@@ -34,37 +35,46 @@ string asset::to_string()const { ...@@ -34,37 +35,46 @@ string asset::to_string()const {
asset asset::from_string(const string& from) asset asset::from_string(const string& from)
{ {
try { try {
asset result;
string s = fc::trim(from); string s = fc::trim(from);
auto dot_pos = s.find(".");
FC_ASSERT(dot_pos != string::npos, "dot missing in asset from string");
auto space_pos = s.find(" ", dot_pos);
FC_ASSERT(space_pos != string::npos, "space missing in asset from string");
asset result; // Find space in order to split amount and symbol
auto space_pos = s.find(' ');
auto intpart = s.substr(0, dot_pos); EOS_ASSERT((space_pos != string::npos), asset_type_exception, "Asset's amount and symbol should be separated with space");
result.amount = fc::to_int64(intpart); auto symbol_str = fc::trim(s.substr(space_pos + 1));
string symbol_part; auto amount_str = s.substr(0, space_pos);
if (dot_pos != string::npos && space_pos != string::npos) {
symbol_part = eosio::chain::to_string(space_pos - dot_pos - 1); // Ensure that if decimal point is used (.), decimal fraction is specified
symbol_part += ','; auto dot_pos = amount_str.find('.');
symbol_part += s.substr(space_pos + 1); if (dot_pos != string::npos) {
EOS_ASSERT((dot_pos != amount_str.size() - 1), asset_type_exception, "Missing decimal fraction after decimal point");
} }
// Parse symbol
string precision_digit_str;
if (dot_pos != string::npos) {
precision_digit_str = eosio::chain::to_string(amount_str.size() - dot_pos - 1);
} else {
precision_digit_str = "0";
}
string symbol_part = precision_digit_str + ',' + symbol_str;
result.sym = symbol::from_string(symbol_part); result.sym = symbol::from_string(symbol_part);
// Parse amount
int64_t int_part, fract_part = 0;
if (dot_pos != string::npos) { if (dot_pos != string::npos) {
auto fractpart = "1" + s.substr(dot_pos + 1, space_pos - dot_pos - 1); int_part = fc::to_int64(amount_str.substr(0, dot_pos));
fract_part = fc::to_int64(amount_str.substr(dot_pos + 1));
result.amount *= int64_t(result.precision()); if (amount_str[0] == '-') fract_part *= -1;
if ( intpart[0] == '-' ) { } else {
result.amount -= int64_t(fc::to_int64(fractpart)); int_part = fc::to_int64(amount_str);
result.amount += int64_t(result.precision());
} else {
result.amount += int64_t(fc::to_int64(fractpart));
result.amount -= int64_t(result.precision());
}
} }
result.amount = int_part;
result.amount *= int64_t(result.precision());
result.amount += fract_part;
return result; return result;
} }
FC_CAPTURE_LOG_AND_RETHROW( (from) ) FC_CAPTURE_LOG_AND_RETHROW( (from) )
......
...@@ -62,6 +62,7 @@ namespace eosio { namespace chain { ...@@ -62,6 +62,7 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( action_type_exception, eosio::chain::chain_type_exception, 3120004, "Invalid action" ) FC_DECLARE_DERIVED_EXCEPTION( action_type_exception, eosio::chain::chain_type_exception, 3120004, "Invalid action" )
FC_DECLARE_DERIVED_EXCEPTION( transaction_type_exception, eosio::chain::chain_type_exception, 3120005, "Invalid transaction" ) FC_DECLARE_DERIVED_EXCEPTION( transaction_type_exception, eosio::chain::chain_type_exception, 3120005, "Invalid transaction" )
FC_DECLARE_DERIVED_EXCEPTION( abi_type_exception, eosio::chain::chain_type_exception, 3120006, "Invalid ABI" ) FC_DECLARE_DERIVED_EXCEPTION( abi_type_exception, eosio::chain::chain_type_exception, 3120006, "Invalid ABI" )
FC_DECLARE_DERIVED_EXCEPTION( asset_type_exception, eosio::chain::chain_type_exception, 3120007, "Invalid asset" )
FC_DECLARE_DERIVED_EXCEPTION( missing_chain_api_plugin_exception, eosio::chain::missing_plugin_exception, 3130001, "Missing Chain API Plugin" ) FC_DECLARE_DERIVED_EXCEPTION( missing_chain_api_plugin_exception, eosio::chain::missing_plugin_exception, 3130001, "Missing Chain API Plugin" )
FC_DECLARE_DERIVED_EXCEPTION( missing_wallet_api_plugin_exception, eosio::chain::missing_plugin_exception, 3130002, "Missing Wallet API Plugin" ) FC_DECLARE_DERIVED_EXCEPTION( missing_wallet_api_plugin_exception, eosio::chain::missing_plugin_exception, 3130002, "Missing Wallet API Plugin" )
......
...@@ -42,7 +42,7 @@ namespace eosio { ...@@ -42,7 +42,7 @@ namespace eosio {
while(str[len]) ++len; while(str[len]) ++len;
uint64_t result = 0; uint64_t result = 0;
for (uint32_t i = 0; i < len; ++i) { for (uint32_t i = 0; i < len; ++i) {
// All characters must be upper case alaphabets // All characters must be upper case alphabets
FC_ASSERT (str[i] >= 'A' && str[i] <= 'Z', "invalid character in symbol name"); FC_ASSERT (str[i] >= 'A' && str[i] <= 'Z', "invalid character in symbol name");
result |= (uint64_t(str[i]) << (8*(i+1))); result |= (uint64_t(str[i]) << (8*(i+1)));
} }
...@@ -68,7 +68,6 @@ namespace eosio { ...@@ -68,7 +68,6 @@ namespace eosio {
FC_ASSERT(comma_pos != string::npos, "missing comma in symbol"); FC_ASSERT(comma_pos != string::npos, "missing comma in symbol");
auto prec_part = s.substr(0, comma_pos); auto prec_part = s.substr(0, comma_pos);
uint8_t p = fc::to_int64(prec_part); uint8_t p = fc::to_int64(prec_part);
FC_ASSERT(p > 0, "zero decimals in symbol");
string name_part = s.substr(comma_pos + 1); string name_part = s.substr(comma_pos + 1);
return symbol(string_to_symbol(p, name_part.c_str())); return symbol(string_to_symbol(p, name_part.c_str()));
} FC_CAPTURE_LOG_AND_RETHROW((from)) } FC_CAPTURE_LOG_AND_RETHROW((from))
...@@ -76,7 +75,6 @@ namespace eosio { ...@@ -76,7 +75,6 @@ namespace eosio {
uint64_t value() const { return m_value; } uint64_t value() const { return m_value; }
bool valid() const bool valid() const
{ {
if (decimals() == 0) return false;
const auto& s = name(); const auto& s = name();
return valid_name(s); return valid_name(s);
} }
......
...@@ -245,18 +245,17 @@ BOOST_FIXTURE_TEST_CASE(test_symbol, tester) try { ...@@ -245,18 +245,17 @@ BOOST_FIXTURE_TEST_CASE(test_symbol, tester) try {
fc::assert_exception, assert_message_is("creating symbol from empty string")); fc::assert_exception, assert_message_is("creating symbol from empty string"));
} }
// precision part missing // precision part missing
{ {
BOOST_CHECK_EXCEPTION(symbol::from_string("RND"), BOOST_CHECK_EXCEPTION(symbol::from_string("RND"),
fc::assert_exception, assert_message_is("missing comma in symbol")); fc::assert_exception, assert_message_is("missing comma in symbol"));
} }
// 0 decimals part
// precision part missing
{ {
BOOST_CHECK_EXCEPTION(symbol::from_string("0,EURO"), symbol sym = symbol::from_string("0,EURO");
fc::assert_exception, assert_message_is("zero decimals in symbol")); BOOST_REQUIRE_EQUAL(0, sym.decimals());
BOOST_REQUIRE_EQUAL("EURO", sym.name());
} }
// invalid - contains lower case characters, no validation // invalid - contains lower case characters, no validation
...@@ -273,10 +272,63 @@ BOOST_FIXTURE_TEST_CASE(test_symbol, tester) try { ...@@ -273,10 +272,63 @@ BOOST_FIXTURE_TEST_CASE(test_symbol, tester) try {
fc::assert_exception, assert_message_is("invalid character in symbol name")); fc::assert_exception, assert_message_is("invalid character in symbol name"));
} }
// invalid - missing decimal point // 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.precision(), 1);
BOOST_REQUIRE_EQUAL(a.decimals(), 0);
BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
}
// Missing space
{
BOOST_CHECK_EXCEPTION(asset::from_string("10CUR"),
asset_type_exception, assert_message_is("Asset's amount and symbol should be separated with space"));
}
// Precision is not specified when decimal separator is introduced
{
BOOST_CHECK_EXCEPTION(asset::from_string("10. CUR"),
asset_type_exception, assert_message_is("Missing decimal fraction after decimal point"));
}
// Missing symbol
{
BOOST_CHECK_EXCEPTION(asset::from_string("10"),
asset_type_exception, assert_message_is("Asset's amount and symbol should be separated with space"));
}
// Multiple spaces
{
asset a = asset::from_string("1000000000.00000 CUR");
BOOST_REQUIRE_EQUAL(a.amount, 100000000000000);
BOOST_REQUIRE_EQUAL(a.decimals(), 5);
BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
}
// Valid asset
{
asset a = asset::from_string("1000000000.00000 CUR");
BOOST_REQUIRE_EQUAL(a.amount, 100000000000000);
BOOST_REQUIRE_EQUAL(a.decimals(), 5);
BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
}
// Negative asset
{
asset a = asset::from_string("-001000000.00010 CUR");
BOOST_REQUIRE_EQUAL(a.amount, -100000000010);
BOOST_REQUIRE_EQUAL(a.decimals(), 5);
BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
}
// Negative asset below 1
{ {
BOOST_CHECK_EXCEPTION(asset::from_string("10 CUR"), asset a = asset::from_string("-000000000.00100 CUR");
fc::assert_exception, assert_message_is("dot missing in asset from string")); BOOST_REQUIRE_EQUAL(a.amount, -100);
BOOST_REQUIRE_EQUAL(a.decimals(), 5);
BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
} }
} FC_LOG_AND_RETHROW() /// test_symbol } FC_LOG_AND_RETHROW() /// test_symbol
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册