Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #5548 from EOSIO/taokayan-blk_abi
Browse files Browse the repository at this point in the history
fix abi serialization exception in get block
  • Loading branch information
heifner authored Sep 5, 2018
2 parents d7ac9aa + b727733 commit 9c81c86
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 13 deletions.
24 changes: 14 additions & 10 deletions libraries/chain/include/eosio/chain/abi_serializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,21 +286,25 @@ namespace impl {
mvo("name", act.name);
mvo("authorization", act.authorization);

auto abi = resolver(act.account);
if (abi.valid()) {
auto type = abi->get_action_type(act.name);
if (!type.empty()) {
try {
mvo( "data", abi->_binary_to_variant( type, act.data, recursion_depth, deadline, max_serialization_time ));
mvo("hex_data", act.data);
} catch(...) {
// any failure to serialize data, then leave as not serailzed
try {
auto abi = resolver(act.account);
if (abi.valid()) {
auto type = abi->get_action_type(act.name);
if (!type.empty()) {
try {
mvo( "data", abi->_binary_to_variant( type, act.data, recursion_depth, deadline, max_serialization_time ));
mvo("hex_data", act.data);
} catch(...) {
// any failure to serialize data, then leave as not serailzed
mvo("data", act.data);
}
} else {
mvo("data", act.data);
}
} else {
mvo("data", act.data);
}
} else {
} catch(...) {
mvo("data", act.data);
}
out(name, std::move(mvo));
Expand Down
8 changes: 5 additions & 3 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ set( CMAKE_CXX_STANDARD 14 )

include_directories("${CMAKE_SOURCE_DIR}/plugins/wallet_plugin/include")

file(GLOB UNIT_TESTS "wallet_tests.cpp")
file(GLOB UNIT_TESTS "*.cpp")

add_executable( plugin_test ${UNIT_TESTS} ${WASM_UNIT_TESTS} main.cpp)
add_executable( plugin_test ${UNIT_TESTS} ${WASM_UNIT_TESTS} )
target_link_libraries( plugin_test eosio_testing eosio_chain chainbase eos_utilities chain_plugin wallet_plugin abi_generator fc ${PLATFORM_SPECIFIC_LIBS} )

target_include_directories( plugin_test PUBLIC ${CMAKE_SOURCE_DIR}/plugins/net_plugin/include )
target_include_directories( plugin_test PUBLIC
${CMAKE_SOURCE_DIR}/plugins/net_plugin/include
${CMAKE_SOURCE_DIR}/plugins/chain_plugin/include )
add_dependencies(plugin_test asserter test_api test_api_mem test_api_db test_api_multi_index exchange proxy identity identity_test stltest infinite eosio.system eosio.token eosio.bios test.inline multi_index_test noop dice eosio.msig)

#
Expand Down
132 changes: 132 additions & 0 deletions tests/chain_plugin_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#include <boost/test/unit_test.hpp>
#include <boost/algorithm/string/predicate.hpp>

#include <eosio/testing/tester.hpp>
#include <eosio/chain/abi_serializer.hpp>
#include <eosio/chain/wasm_eosio_constraints.hpp>
#include <eosio/chain/resource_limits.hpp>
#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/wast_to_wasm.hpp>
#include <eosio/chain_plugin/chain_plugin.hpp>

#include <asserter/asserter.wast.hpp>
#include <asserter/asserter.abi.hpp>

#include <stltest/stltest.wast.hpp>
#include <stltest/stltest.abi.hpp>

#include <noop/noop.wast.hpp>
#include <noop/noop.abi.hpp>

#include <eosio.system/eosio.system.wast.hpp>
#include <eosio.system/eosio.system.abi.hpp>

#include <fc/io/fstream.hpp>

#include <Runtime/Runtime.h>

#include <fc/variant_object.hpp>
#include <fc/io/json.hpp>

#include <array>
#include <utility>

#ifdef NON_VALIDATING_TEST
#define TESTER tester
#else
#define TESTER validating_tester
#endif

using namespace eosio;
using namespace eosio::chain;
using namespace eosio::testing;
using namespace fc;

BOOST_AUTO_TEST_SUITE(chain_plugin_tests)

BOOST_FIXTURE_TEST_CASE( get_block_with_invalid_abi, TESTER ) try {
produce_blocks(2);

create_accounts( {N(asserter)} );
produce_block();

// setup contract and abi
set_code(N(asserter), asserter_wast);
set_abi(N(asserter), asserter_abi);
produce_blocks(1);

auto resolver = [&,this]( const account_name& name ) -> optional<abi_serializer> {
try {
const auto& accnt = this->control->db().get<account_object,by_name>( name );
abi_def abi;
if (abi_serializer::to_abi(accnt.abi, abi)) {
return abi_serializer(abi, abi_serializer_max_time);
}
return optional<abi_serializer>();
} FC_RETHROW_EXCEPTIONS(error, "resolver failed at chain_plugin_tests::abi_invalid_type");
};

// abi should be resolved
BOOST_REQUIRE_EQUAL(true, resolver(N(asserter)).valid());

// make an action using the valid contract & abi
variant pretty_trx = mutable_variant_object()
("actions", variants({
mutable_variant_object()
("account", "asserter")
("name", "procassert")
("authorization", variants({
mutable_variant_object()
("actor", "asserter")
("permission", name(config::active_name).to_string())
}))
("data", mutable_variant_object()
("condition", 1)
("message", "Should Not Assert!")
)
})
);
signed_transaction trx;
abi_serializer::from_variant(pretty_trx, trx, resolver, abi_serializer_max_time);
set_transaction_headers(trx);
trx.sign( get_private_key( N(asserter), "active" ), control->get_chain_id() );
push_transaction( trx );
produce_blocks(1);

// retrieve block num
uint32_t headnum = this->control->head_block_num();

char headnumstr[20];
sprintf(headnumstr, "%d", headnum);
chain_apis::read_only::get_block_params param{headnumstr};
chain_apis::read_only plugin(*(this->control), fc::microseconds(INT_MAX));

// block should be decoded successfully
std::string block_str = json::to_pretty_string(plugin.get_block(param));
BOOST_TEST(block_str.find("procassert") != std::string::npos);
BOOST_TEST(block_str.find("condition") != std::string::npos);
BOOST_TEST(block_str.find("Should Not Assert!") != std::string::npos);
BOOST_TEST(block_str.find("011253686f756c64204e6f742041737365727421") != std::string::npos); //action data

// set an invalid abi (int8->xxxx)
std::string abi2 = asserter_abi;
auto pos = abi2.find("int8");
BOOST_TEST(pos != std::string::npos);
abi2.replace(pos, 4, "xxxx");
set_abi(N(asserter), abi2.c_str());
produce_blocks(1);

// resolving the invalid abi result in exception
BOOST_CHECK_THROW(resolver(N(asserter)), invalid_type_inside_abi);

// get the same block as string, results in decode failed(invalid abi) but not exception
std::string block_str2 = json::to_pretty_string(plugin.get_block(param));
BOOST_TEST(block_str2.find("procassert") != std::string::npos);
BOOST_TEST(block_str2.find("condition") == std::string::npos); // decode failed
BOOST_TEST(block_str2.find("Should Not Assert!") == std::string::npos); // decode failed
BOOST_TEST(block_str2.find("011253686f756c64204e6f742041737365727421") != std::string::npos); //action data

} FC_LOG_AND_RETHROW() /// get_block_with_invalid_abi

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 9c81c86

Please sign in to comment.