From 674b652649880d9192e4dafcd2a1ca9ff8eee1bf Mon Sep 17 00:00:00 2001 From: Bart Wyatt Date: Fri, 17 May 2019 10:53:44 -0400 Subject: [PATCH 1/2] Allow aliases of variants in ABI This resolves 7254 We had a redundant validation that attempted to prevent aliasing to an unknown type however, this was done before variants were loaded so, it would reject an alias of a variant. `::validate` will perform this validation after all types are known so, this assert was not needed --- libraries/chain/abi_serializer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/chain/abi_serializer.cpp b/libraries/chain/abi_serializer.cpp index 2f453e0cf93..8b91b332392 100644 --- a/libraries/chain/abi_serializer.cpp +++ b/libraries/chain/abi_serializer.cpp @@ -119,7 +119,6 @@ namespace eosio { namespace chain { structs[st.name] = st; for( const auto& td : abi.types ) { - EOS_ASSERT(_is_type(td.type, ctx), invalid_type_inside_abi, "invalid type ${type}", ("type",td.type)); EOS_ASSERT(!_is_type(td.new_type_name, ctx), duplicate_abi_type_def_exception, "type already exists", ("new_type_name",td.new_type_name)); typedefs[td.new_type_name] = td.type; } From e5a8940a703cd839283af7302438444137edb699 Mon Sep 17 00:00:00 2001 From: Bart Wyatt Date: Mon, 20 May 2019 12:07:22 -0400 Subject: [PATCH 2/2] added unit tests for aliased variant and variant of aliases. fixed exception expectation on other unit test --- unittests/abi_tests.cpp | 55 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/unittests/abi_tests.cpp b/unittests/abi_tests.cpp index 7e6c84fb6f2..e632cb20c75 100644 --- a/unittests/abi_tests.cpp +++ b/unittests/abi_tests.cpp @@ -1955,8 +1955,8 @@ BOOST_AUTO_TEST_CASE(abi_type_redefine) } )====="; - auto is_type_exception = [](fc::exception const & e) -> bool { return e.to_detail_string().find("invalid type") != std::string::npos; }; - BOOST_CHECK_EXCEPTION( abi_serializer abis(fc::json::from_string(repeat_abi).as(), max_serialization_time), invalid_type_inside_abi, is_type_exception ); + auto is_type_exception = [](fc::exception const & e) -> bool { return e.to_detail_string().find("Circular reference in type account_name") != std::string::npos; }; + BOOST_CHECK_EXCEPTION( abi_serializer abis(fc::json::from_string(repeat_abi).as(), max_serialization_time), abi_circular_def_exception, is_type_exception ); } FC_LOG_AND_RETHROW() } @@ -2304,6 +2304,57 @@ BOOST_AUTO_TEST_CASE(variants) } FC_LOG_AND_RETHROW() } +BOOST_AUTO_TEST_CASE(aliased_variants) +{ + using eosio::testing::fc_exception_message_starts_with; + + auto aliased_variant = R"({ + "version": "eosio::abi/1.1", + "types": [ + { "new_type_name": "foo", "type": "foo_variant" } + ], + "variants": [ + {"name": "foo_variant", "types": ["int8", "string"]} + ], + })"; + + try { + // round-trip abi through multiple formats + // json -> variant -> abi_def -> bin + auto bin = fc::raw::pack(fc::json::from_string(aliased_variant).as()); + // bin -> abi_def -> variant -> abi_def + abi_serializer abis(variant(fc::raw::unpack(bin)).as(), max_serialization_time ); + + verify_round_trip_conversion(abis, "foo", R"(["int8",21])", "0015"); + } FC_LOG_AND_RETHROW() +} + +BOOST_AUTO_TEST_CASE(variant_of_aliases) +{ + using eosio::testing::fc_exception_message_starts_with; + + auto aliased_variant = R"({ + "version": "eosio::abi/1.1", + "types": [ + { "new_type_name": "foo_0", "type": "int8" }, + { "new_type_name": "foo_1", "type": "string" } + ], + "variants": [ + {"name": "foo", "types": ["foo_0", "foo_1"]} + ], + })"; + + try { + // round-trip abi through multiple formats + // json -> variant -> abi_def -> bin + auto bin = fc::raw::pack(fc::json::from_string(aliased_variant).as()); + // bin -> abi_def -> variant -> abi_def + abi_serializer abis(variant(fc::raw::unpack(bin)).as(), max_serialization_time ); + + verify_round_trip_conversion(abis, "foo", R"(["foo_0",21])", "0015"); + } FC_LOG_AND_RETHROW() +} + BOOST_AUTO_TEST_CASE(extend) { using eosio::testing::fc_exception_message_starts_with;