Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.0 -> main] TraceAPI: Correctly convert return value via ABI #2249

Merged
merged 9 commits into from
Feb 20, 2024
5 changes: 4 additions & 1 deletion plugins/trace_api_plugin/abi_data_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ namespace eosio::trace_api {
auto params = serializer_p->binary_to_variant(type_name, action.data, abi_yield);
if constexpr (std::is_same_v<T, action_trace_v1>) {
if(action.return_value.size() > 0) {
ret_data = serializer_p->binary_to_variant(type_name, action.return_value, abi_yield);
auto return_type_name = serializer_p->get_action_result_type(action_name);
if (!return_type_name.empty()) {
ret_data = serializer_p->binary_to_variant(return_type_name, action.return_value, abi_yield);
}
}
}
return {params, ret_data};
Expand Down
7 changes: 2 additions & 5 deletions plugins/trace_api_plugin/request_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,22 @@ namespace {
});
for ( int index : indices) {
const auto& a = actions.at(index);
auto common_mvo = fc::mutable_variant_object();
auto action_variant = fc::mutable_variant_object();

common_mvo("global_sequence", a.global_sequence)
action_variant("global_sequence", a.global_sequence)
("receiver", a.receiver.to_string())
("account", a.account.to_string())
("action", a.action.to_string())
("authorization", process_authorizations(a.authorization))
("data", fc::to_hex(a.data.data(), a.data.size()));

auto action_variant = fc::mutable_variant_object();
if constexpr(std::is_same_v<ActionTrace, action_trace_v0>){
action_variant(std::move(common_mvo));
auto [params, return_data] = data_handler(a);
if (!params.is_null()) {
action_variant("params", params);
}
}
else if constexpr(std::is_same_v<ActionTrace, action_trace_v1>){
action_variant(std::move(common_mvo));
action_variant("return_value", fc::to_hex(a.return_value.data(),a.return_value.size())) ;
auto [params, return_data] = data_handler(a);
if (!params.is_null()) {
Expand Down
57 changes: 55 additions & 2 deletions plugins/trace_api_plugin/test/test_data_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ BOOST_AUTO_TEST_SUITE(abi_data_handler_tests)
auto actual = handler.serialize_to_variant(action_trace_t);

BOOST_TEST(to_kv(expected) == to_kv(std::get<0>(actual)), boost::test_tools::per_element());
BOOST_REQUIRE(!std::get<1>(actual));
}

BOOST_AUTO_TEST_CASE(empty_data_v1)
Expand All @@ -36,6 +37,7 @@ BOOST_AUTO_TEST_SUITE(abi_data_handler_tests)
auto actual = handler.serialize_to_variant(action_trace_t);

BOOST_TEST(to_kv(expected) == to_kv(std::get<0>(actual)), boost::test_tools::per_element());
BOOST_REQUIRE(!std::get<1>(actual));
}

BOOST_AUTO_TEST_CASE(no_abi)
Expand All @@ -50,6 +52,7 @@ BOOST_AUTO_TEST_SUITE(abi_data_handler_tests)
auto actual = handler.serialize_to_variant(action_trace_t);

BOOST_TEST(to_kv(expected) == to_kv(std::get<0>(actual)), boost::test_tools::per_element());
BOOST_REQUIRE(!std::get<1>(actual));
}

BOOST_AUTO_TEST_CASE(no_abi_v1)
Expand All @@ -65,6 +68,7 @@ BOOST_AUTO_TEST_SUITE(abi_data_handler_tests)
auto actual = handler.serialize_to_variant(action_trace_t);

BOOST_TEST(to_kv(expected) == to_kv(std::get<0>(actual)), boost::test_tools::per_element());
BOOST_REQUIRE(!std::get<1>(actual));
}

BOOST_AUTO_TEST_CASE(basic_abi)
Expand Down Expand Up @@ -98,27 +102,30 @@ BOOST_AUTO_TEST_SUITE(abi_data_handler_tests)
auto actual = handler.serialize_to_variant(action_trace_t);

BOOST_TEST(to_kv(expected) == to_kv(std::get<0>(actual)), boost::test_tools::per_element());
BOOST_REQUIRE(!std::get<1>(actual));
}

BOOST_AUTO_TEST_CASE(basic_abi_v1)
{
auto action = action_trace_v1 {
{ 0, "alice"_n, "alice"_n, "foo"_n, {}, {0x00, 0x01, 0x02, 0x03}},
{0x04, 0x05, 0x06, 0x07}
{0x04, 0x05, 0x06}
};

std::variant<action_trace_v0, action_trace_v1> action_trace_t = action;

auto abi = chain::abi_def ( {},
{
{ "foo", "", { {"a", "varuint32"}, {"b", "varuint32"}, {"c", "varuint32"}, {"d", "varuint32"} } }
{ "foo", "", { {"a", "varuint32"}, {"b", "varuint32"}, {"c", "varuint32"}, {"d", "varuint32"} } },
{ "foor", "", { {"e", "varuint32"}, {"f", "varuint32"}, {"g", "varuint32"} } }
},
{
{ "foo"_n, "foo", ""}
},
{}, {}, {}
);
abi.version = "eosio::abi/1.";
abi.action_results = { std::vector<chain::action_result_def>{ chain::action_result_def{ "foo"_n, "foor"} } };

abi_data_handler handler(exception_handler{});
handler.add_abi("alice"_n, std::move(abi));
Expand All @@ -128,10 +135,16 @@ BOOST_AUTO_TEST_SUITE(abi_data_handler_tests)
("b", 1)
("c", 2)
("d", 3);
fc::variant expected_return = fc::mutable_variant_object()
("e", 4)
("f", 5)
("g", 6);

auto actual = handler.serialize_to_variant(action_trace_t);

BOOST_TEST(to_kv(expected) == to_kv(std::get<0>(actual)), boost::test_tools::per_element());
BOOST_REQUIRE(std::get<1>(actual));
BOOST_TEST(to_kv(expected_return) == to_kv(*std::get<1>(actual)), boost::test_tools::per_element());
}

BOOST_AUTO_TEST_CASE(basic_abi_wrong_type)
Expand Down Expand Up @@ -161,6 +174,7 @@ BOOST_AUTO_TEST_SUITE(abi_data_handler_tests)
auto actual = handler.serialize_to_variant(action_trace_t);

BOOST_TEST(to_kv(expected) == to_kv(std::get<0>(actual)), boost::test_tools::per_element());
BOOST_REQUIRE(!std::get<1>(actual));
}

BOOST_AUTO_TEST_CASE(basic_abi_wrong_type_v1)
Expand Down Expand Up @@ -190,6 +204,7 @@ BOOST_AUTO_TEST_SUITE(abi_data_handler_tests)
auto actual = handler.serialize_to_variant(action_trace_t);

BOOST_TEST(to_kv(expected) == to_kv(std::get<0>(actual)), boost::test_tools::per_element());
BOOST_REQUIRE(!std::get<1>(actual));
}

BOOST_AUTO_TEST_CASE(basic_abi_insufficient_data)
Expand Down Expand Up @@ -221,6 +236,44 @@ BOOST_AUTO_TEST_SUITE(abi_data_handler_tests)

BOOST_TEST(to_kv(expected) == to_kv(std::get<0>(actual)), boost::test_tools::per_element());
BOOST_TEST(log_called);
BOOST_REQUIRE(!std::get<1>(actual));
}

// If no ABI provided for return type then do not attempt to decode it
BOOST_AUTO_TEST_CASE(basic_abi_no_return_abi_when_return_value_provided)
{
auto action = action_trace_v1 {
{ 0, "alice"_n, "alice"_n, "foo"_n, {}, {0x00, 0x01, 0x02, 0x03}},
{0x04, 0x05, 0x06}
};

std::variant<action_trace_v0, action_trace_v1> action_trace_t = action;

auto abi = chain::abi_def ( {},
{
{ "foo", "", { {"a", "varuint32"}, {"b", "varuint32"}, {"c", "varuint32"}, {"d", "varuint32"} } },
},
{
{ "foo"_n, "foo", ""}
},
{}, {}, {}
);
abi.version = "eosio::abi/1.";

abi_data_handler handler(exception_handler{});
handler.add_abi("alice"_n, std::move(abi));

fc::variant expected = fc::mutable_variant_object()
("a", 0)
("b", 1)
("c", 2)
("d", 3);

auto actual = handler.serialize_to_variant(action_trace_t);

BOOST_TEST(to_kv(expected) == to_kv(std::get<0>(actual)), boost::test_tools::per_element());
BOOST_REQUIRE(!std::get<1>(actual));
}


BOOST_AUTO_TEST_SUITE_END()
Loading