Skip to content

Commit

Permalink
Merge branch 'main' of github.com:AntelopeIO/leap into boost_submodule
Browse files Browse the repository at this point in the history
  • Loading branch information
greg7mdp committed Jul 5, 2023
2 parents a990d74 + d4ed800 commit d87819a
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 20 deletions.
5 changes: 3 additions & 2 deletions libraries/chain/abi_serializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -548,14 +548,15 @@ namespace eosio { namespace chain {
bool disallow_additional_fields = false;
for( uint32_t i = 0; i < st.fields.size(); ++i ) {
const auto& field = st.fields[i];
if( vo.contains( string(field.name).c_str() ) ) {
bool present = vo.contains(string(field.name).c_str());
if( present || is_optional(field.type) ) {
if( disallow_additional_fields )
EOS_THROW( pack_exception, "Unexpected field '${f}' found in input object while processing struct '${p}'",
("f", ctx.maybe_shorten(field.name))("p", ctx.get_path_string()) );
{
auto h1 = ctx.push_to_path( impl::field_path_item{ .parent_struct_itr = s_itr, .field_ordinal = i } );
auto h2 = ctx.disallow_extensions_unless( &field == &st.fields.back() );
_variant_to_binary(_remove_bin_extension(field.type), vo[field.name], ds, ctx);
_variant_to_binary(_remove_bin_extension(field.type), present ? vo[field.name] : fc::variant(nullptr), ds, ctx);
}
} else if( ends_with(field.type, "$") && ctx.extensions_allowed() ) {
disallow_additional_fields = true;
Expand Down
13 changes: 7 additions & 6 deletions libraries/libfc/include/fc/time.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ namespace fc {
class microseconds {
public:
constexpr explicit microseconds( int64_t c = 0) :_count(c){}
static constexpr microseconds maximum() { return microseconds(0x7fffffffffffffffll); }
static constexpr microseconds maximum() { return microseconds(std::numeric_limits<int64_t>::max()); }
static constexpr microseconds minimum() { return microseconds(std::numeric_limits<int64_t>::min()); }
friend constexpr microseconds operator + (const microseconds& l, const microseconds& r ) { return microseconds(l._count+r._count); }
friend constexpr microseconds operator - (const microseconds& l, const microseconds& r ) { return microseconds(l._count-r._count); }

Expand Down Expand Up @@ -52,12 +53,12 @@ namespace fc {

// protect against overflow/underflow
constexpr time_point& safe_add( const microseconds& m ) {
if (m.count() > 0 && elapsed > fc::microseconds::maximum() - m) {
if (m.count() > 0 && elapsed > microseconds::maximum() - m) {
elapsed = microseconds::maximum();
} else if (m.count() < 0 && elapsed.count() < std::numeric_limits<int64_t >::min() - m.count()) {
elapsed = microseconds(std::numeric_limits<int64_t >::min());
} else if (m.count() < 0 && elapsed < microseconds::minimum() - m) {
elapsed = microseconds::minimum();
} else {
elapsed += m;
elapsed += m;
}
return *this;
}
Expand Down Expand Up @@ -94,7 +95,7 @@ namespace fc {
constexpr explicit time_point_sec( const time_point& t )
:utc_seconds( t.time_since_epoch().count() / 1000000ll ){}

static constexpr time_point_sec maximum() { return time_point_sec(0xffffffff); }
static constexpr time_point_sec maximum() { return time_point_sec(std::numeric_limits<uint32_t>::max()); }
static constexpr time_point_sec min() { return time_point_sec(0); }

constexpr time_point to_time_point()const { return time_point( fc::seconds( utc_seconds) ); }
Expand Down
139 changes: 127 additions & 12 deletions unittests/abi_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,15 @@ FC_REFLECT(act_sig, (sig) )

BOOST_AUTO_TEST_SUITE(abi_tests)

#ifdef NDEBUG
fc::microseconds max_serialization_time = fc::seconds(1); // some test machines are very slow
#else
fc::microseconds max_serialization_time = fc::microseconds::maximum(); // don't check in debug builds
#endif

static fc::time_point get_deadline() {
return fc::time_point::now().safe_add(max_serialization_time);
}

// verify that round trip conversion, via bytes, reproduces the exact same data
fc::variant verify_byte_round_trip_conversion( const abi_serializer& abis, const type_name& type, const fc::variant& var )
Expand All @@ -53,8 +61,8 @@ fc::variant verify_byte_round_trip_conversion( const abi_serializer& abis, const
auto var2 = abis.binary_to_variant(type, bytes, abi_serializer::create_yield_function( max_serialization_time ));
auto var3 = abis.binary_to_variant(type, b, max_serialization_time);

std::string r2 = fc::json::to_string(var2, fc::time_point::now() + max_serialization_time);
std::string r3 = fc::json::to_string(var3, fc::time_point::now() + max_serialization_time);
std::string r2 = fc::json::to_string(var2, get_deadline());
std::string r3 = fc::json::to_string(var3, get_deadline());
BOOST_TEST( r2 == r3 );

auto bytes2 = abis.variant_to_binary(type, var2, abi_serializer::create_yield_function( max_serialization_time ));
Expand All @@ -74,9 +82,9 @@ void verify_round_trip_conversion( const abi_serializer& abis, const type_name&
auto b = abis.variant_to_binary(type, var, max_serialization_time);
BOOST_REQUIRE_EQUAL(fc::to_hex(b), hex);
auto var2 = abis.binary_to_variant(type, bytes, abi_serializer::create_yield_function( max_serialization_time ));
BOOST_REQUIRE_EQUAL(fc::json::to_string(var2, fc::time_point::now() + max_serialization_time), expected_json);
BOOST_REQUIRE_EQUAL(fc::json::to_string(var2, get_deadline()), expected_json);
auto var3 = abis.binary_to_variant(type, b, max_serialization_time );
BOOST_REQUIRE_EQUAL(fc::json::to_string(var3, fc::time_point::now() + max_serialization_time), expected_json);
BOOST_REQUIRE_EQUAL(fc::json::to_string(var3, get_deadline()), expected_json);
auto bytes2 = abis.variant_to_binary(type, var2, abi_serializer::create_yield_function( max_serialization_time ));
BOOST_REQUIRE_EQUAL(fc::to_hex(bytes2), hex);
auto b2 = abis.variant_to_binary(type, var3, max_serialization_time);
Expand Down Expand Up @@ -115,8 +123,8 @@ fc::variant verify_type_round_trip_conversion( const abi_serializer& abis, const
fc::variant var3;
abi_serializer::to_variant(obj2, var3, get_resolver(), max_serialization_time);

std::string r2 = fc::json::to_string(var2, fc::time_point::now() + max_serialization_time);
std::string r3 = fc::json::to_string(var3, fc::time_point::now() + max_serialization_time);
std::string r2 = fc::json::to_string(var2, get_deadline());
std::string r3 = fc::json::to_string(var3, get_deadline());
BOOST_TEST( r2 == r3 );

auto bytes2 = abis.variant_to_binary(type, var2, abi_serializer::create_yield_function( max_serialization_time ));
Expand Down Expand Up @@ -1972,6 +1980,113 @@ BOOST_AUTO_TEST_CASE(abi_type_loop)

} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_CASE(abi_std_optional)
{ try {
const char* repeat_abi = R"=====(
{
"version": "eosio::abi/1.2",
"types": [],
"structs": [
{
"name": "fees",
"base": "",
"fields": [
{
"name": "gas_price",
"type": "uint64?"
},
{
"name": "miner_cut",
"type": "uint32?"
},
{
"name": "bridge_fee",
"type": "uint32?"
}
]
}
],
"actions": [
{
"name": "fees",
"type": "fees",
"ricardian_contract": ""
}
],
"tables": [],
"ricardian_clauses": [],
"variants": [],
"action_results": []
}
)=====";

abi_serializer abis(fc::json::from_string(repeat_abi).as<abi_def>(), abi_serializer::create_yield_function( max_serialization_time ));
{
// check conversion when all optional members are provided
std::string test_data = R"=====(
{
"gas_price" : "42",
"miner_cut" : "2",
"bridge_fee" : "2"
}
)=====";

auto var = fc::json::from_string(test_data);
verify_byte_round_trip_conversion(abis, "fees", var);
}

{
// check conversion when the first optional member is missing
std::string test_data = R"=====(
{
"miner_cut" : "2",
"bridge_fee" : "2"
}
)=====";

auto var = fc::json::from_string(test_data);
verify_byte_round_trip_conversion(abis, "fees", var);
}

{
// check conversion when the second optional member is missing
std::string test_data = R"=====(
{
"gas_price" : "42",
"bridge_fee" : "2"
}
)=====";

auto var = fc::json::from_string(test_data);
verify_byte_round_trip_conversion(abis, "fees", var);
}

{
// check conversion when the last optional member is missing
std::string test_data = R"=====(
{
"gas_price" : "42",
"miner_cut" : "2",
}
)=====";

auto var = fc::json::from_string(test_data);
verify_byte_round_trip_conversion(abis, "fees", var);
}

{
// check conversion when all optional members are missing
std::string test_data = R"=====(
{
}
)=====";

auto var = fc::json::from_string(test_data);
verify_byte_round_trip_conversion(abis, "fees", var);
}

} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_CASE(abi_type_redefine)
{ try {
// inifinite loop in types
Expand Down Expand Up @@ -3127,15 +3242,15 @@ BOOST_AUTO_TEST_CASE(abi_to_variant__add_action__good_return_value)
mutable_variant_object mvo;
eosio::chain::impl::abi_traverse_context ctx(abi_serializer::create_yield_function(max_serialization_time), fc::microseconds{});
eosio::chain::impl::abi_to_variant::add(mvo, "action_traces", at, get_resolver(abidef), ctx);
std::string res = fc::json::to_string(mvo, fc::time_point::now() + max_serialization_time);
std::string res = fc::json::to_string(mvo, get_deadline());

BOOST_CHECK_EQUAL(res, expected_json);
}
{
mutable_variant_object mvo;
eosio::chain::impl::abi_traverse_context ctx(abi_serializer::create_depth_yield_function(), max_serialization_time);
eosio::chain::impl::abi_to_variant::add(mvo, "action_traces", at, get_resolver(abidef), ctx);
std::string res = fc::json::to_string(mvo, fc::time_point::now() + max_serialization_time);
std::string res = fc::json::to_string(mvo, get_deadline());

BOOST_CHECK_EQUAL(res, expected_json);
}
Expand All @@ -3162,15 +3277,15 @@ BOOST_AUTO_TEST_CASE(abi_to_variant__add_action__bad_return_value)
mutable_variant_object mvo;
eosio::chain::impl::abi_traverse_context ctx(abi_serializer::create_yield_function(max_serialization_time), fc::microseconds{});
eosio::chain::impl::abi_to_variant::add(mvo, "action_traces", at, get_resolver(abidef), ctx);
std::string res = fc::json::to_string(mvo, fc::time_point::now() + max_serialization_time);
std::string res = fc::json::to_string(mvo, get_deadline());

BOOST_CHECK_EQUAL(res, expected_json);
}
{
mutable_variant_object mvo;
eosio::chain::impl::abi_traverse_context ctx(abi_serializer::create_depth_yield_function(), max_serialization_time);
eosio::chain::impl::abi_to_variant::add(mvo, "action_traces", at, get_resolver(abidef), ctx);
std::string res = fc::json::to_string(mvo, fc::time_point::now() + max_serialization_time);
std::string res = fc::json::to_string(mvo, get_deadline());

BOOST_CHECK_EQUAL(res, expected_json);
}
Expand Down Expand Up @@ -3207,15 +3322,15 @@ BOOST_AUTO_TEST_CASE(abi_to_variant__add_action__no_return_value)
mutable_variant_object mvo;
eosio::chain::impl::abi_traverse_context ctx(abi_serializer::create_yield_function(max_serialization_time), fc::microseconds{});
eosio::chain::impl::abi_to_variant::add(mvo, "action_traces", at, get_resolver(abidef), ctx);
std::string res = fc::json::to_string(mvo, fc::time_point::now() + max_serialization_time);
std::string res = fc::json::to_string(mvo, get_deadline());

BOOST_CHECK_EQUAL(res, expected_json);
}
{
mutable_variant_object mvo;
eosio::chain::impl::abi_traverse_context ctx(abi_serializer::create_depth_yield_function(), max_serialization_time);
eosio::chain::impl::abi_to_variant::add(mvo, "action_traces", at, get_resolver(abidef), ctx);
std::string res = fc::json::to_string(mvo, fc::time_point::now() + max_serialization_time);
std::string res = fc::json::to_string(mvo, get_deadline());

BOOST_CHECK_EQUAL(res, expected_json);
}
Expand Down

0 comments on commit d87819a

Please sign in to comment.