Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
2d1844c6
Y
YTBP
项目概览
YottaChain
/
YTBP
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Y
YTBP
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
2d1844c6
编写于
5月 22, 2018
作者:
K
Kevin Heifner
提交者:
GitHub
5月 22, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #3277 from EOSIO/gh#3219-nodeos-crash
Gh#3219 nodeos crash
上级
dd0cb785
27f6873a
变更
25
隐藏空白更改
内联
并排
Showing
25 changed file
with
329 addition
and
202 deletion
+329
-202
libraries/chain/include/eosio/chain/abi_serializer.hpp
libraries/chain/include/eosio/chain/abi_serializer.hpp
+4
-5
libraries/chain/include/eosio/chain/asset.hpp
libraries/chain/include/eosio/chain/asset.hpp
+12
-3
libraries/chain/include/eosio/chain/symbol.hpp
libraries/chain/include/eosio/chain/symbol.hpp
+7
-1
libraries/fc/include/fc/io/raw.hpp
libraries/fc/include/fc/io/raw.hpp
+4
-4
libraries/fc/include/fc/reflect/reflect.hpp
libraries/fc/include/fc/reflect/reflect.hpp
+67
-0
libraries/fc/include/fc/reflect/variant.hpp
libraries/fc/include/fc/reflect/variant.hpp
+4
-4
libraries/fc/src/exception.cpp
libraries/fc/src/exception.cpp
+50
-14
plugins/account_history_api_plugin/account_history_api_plugin.cpp
...account_history_api_plugin/account_history_api_plugin.cpp
+2
-8
plugins/chain_api_plugin/chain_api_plugin.cpp
plugins/chain_api_plugin/chain_api_plugin.cpp
+2
-17
plugins/db_size_api_plugin/db_size_api_plugin.cpp
plugins/db_size_api_plugin/db_size_api_plugin.cpp
+2
-8
plugins/faucet_testnet_plugin/faucet_testnet_plugin.cpp
plugins/faucet_testnet_plugin/faucet_testnet_plugin.cpp
+2
-8
plugins/history_api_plugin/history_api_plugin.cpp
plugins/history_api_plugin/history_api_plugin.cpp
+2
-8
plugins/http_plugin/CMakeLists.txt
plugins/http_plugin/CMakeLists.txt
+1
-1
plugins/http_plugin/http_plugin.cpp
plugins/http_plugin/http_plugin.cpp
+90
-33
plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp
...ins/http_plugin/include/eosio/http_plugin/http_plugin.hpp
+3
-0
plugins/net_api_plugin/net_api_plugin.cpp
plugins/net_api_plugin/net_api_plugin.cpp
+2
-8
plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp
plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp
+2
-8
plugins/wallet_api_plugin/wallet_api_plugin.cpp
plugins/wallet_api_plugin/wallet_api_plugin.cpp
+2
-8
programs/cleos/main.cpp
programs/cleos/main.cpp
+3
-3
unittests/bootseq_tests.cpp
unittests/bootseq_tests.cpp
+1
-1
unittests/currency_tests.cpp
unittests/currency_tests.cpp
+7
-7
unittests/eosio.system_tests.cpp
unittests/eosio.system_tests.cpp
+37
-36
unittests/eosio.token_tests.cpp
unittests/eosio.token_tests.cpp
+8
-2
unittests/eosio_system_tester.hpp
unittests/eosio_system_tester.hpp
+3
-3
unittests/misc_tests.cpp
unittests/misc_tests.cpp
+12
-12
未找到文件。
libraries/chain/include/eosio/chain/abi_serializer.hpp
浏览文件 @
2d1844c6
...
...
@@ -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
)
,
_v
al
(
v
)
:
reflector_verifier_visitor
<
T
>
(
v
)
,
_v
o
(
_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
;
};
...
...
libraries/chain/include/eosio/chain/asset.hpp
浏览文件 @
2d1844c6
...
...
@@ -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
{
...
...
libraries/chain/include/eosio/chain/symbol.hpp
浏览文件 @
2d1844c6
...
...
@@ -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
>
;
...
...
libraries/fc/include/fc/io/raw.hpp
浏览文件 @
2d1844c6
...
...
@@ -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
;
};
...
...
libraries/fc/include/fc/reflect/reflect.hpp
浏览文件 @
2d1844c6
...
...
@@ -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 )\
...
...
libraries/fc/include/fc/reflect/variant.hpp
浏览文件 @
2d1844c6
...
...
@@ -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
>
...
...
libraries/fc/src/exception.cpp
浏览文件 @
2d1844c6
...
...
@@ -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
();
}
/**
...
...
plugins/account_history_api_plugin/account_history_api_plugin.cpp
浏览文件 @
2d1844c6
...
...
@@ -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); \
} \
}}
...
...
plugins/chain_api_plugin/chain_api_plugin.cpp
浏览文件 @
2d1844c6
...
...
@@ -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); \
} \
}}
...
...
plugins/db_size_api_plugin/db_size_api_plugin.cpp
浏览文件 @
2d1844c6
...
...
@@ -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); \
} \
}}
...
...
plugins/faucet_testnet_plugin/faucet_testnet_plugin.cpp
浏览文件 @
2d1844c6
...
...
@@ -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); \
} \
}}
...
...
plugins/history_api_plugin/history_api_plugin.cpp
浏览文件 @
2d1844c6
...
...
@@ -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); \
} \
}}
...
...
plugins/http_plugin/CMakeLists.txt
浏览文件 @
2d1844c6
...
...
@@ -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"
)
plugins/http_plugin/http_plugin.cpp
浏览文件 @
2d1844c6
...
...
@@ -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
;
}
}
}
plugins/http_plugin/include/eosio/http_plugin/http_plugin.hpp
浏览文件 @
2d1844c6
...
...
@@ -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
;
};
...
...
plugins/net_api_plugin/net_api_plugin.cpp
浏览文件 @
2d1844c6
...
...
@@ -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); \
} \
}}
...
...
plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp
浏览文件 @
2d1844c6
...
...
@@ -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); \
} \
}}
...
...
plugins/wallet_api_plugin/wallet_api_plugin.cpp
浏览文件 @
2d1844c6
...
...
@@ -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); \
} \
}}
...
...
programs/cleos/main.cpp
浏览文件 @
2d1844c6
...
...
@@ -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
...
...
unittests/bootseq_tests.cpp
浏览文件 @
2d1844c6
...
...
@@ -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
...
...
unittests/currency_tests.cpp
浏览文件 @
2d1844c6
...
...
@@ -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
()
);
}
...
...
unittests/eosio.system_tests.cpp
浏览文件 @
2d1844c6
...
...
@@ -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
()
...
...
unittests/eosio.token_tests.cpp
浏览文件 @
2d1844c6
...
...
@@ -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"
);
...
...
unittests/eosio_system_tester.hpp
浏览文件 @
2d1844c6
...
...
@@ -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
()
;
}
}
unittests/misc_tests.cpp
浏览文件 @
2d1844c6
...
...
@@ -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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录