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

[3.2] Fix eosio::name conversion in get_table_rows_by_seckey #520

Merged
merged 11 commits into from
Jun 26, 2022
1 change: 1 addition & 0 deletions libraries/testing/contracts.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ namespace eosio {
MAKE_READ_WASM_ABI(deferred_test, deferred_test, test-contracts)
MAKE_READ_WASM_ABI(get_sender_test, get_sender_test, test-contracts)
MAKE_READ_WASM_ABI(get_table_test, get_table_test, test-contracts)
MAKE_READ_WASM_ABI(get_table_seckey_test, get_table_seckey_test, test-contracts)
MAKE_READ_WASM_ABI(noop, noop, test-contracts)
MAKE_READ_WASM_ABI(payloadless, payloadless, test-contracts)
MAKE_READ_WASM_ABI(proxy, proxy, test-contracts)
Expand Down
4 changes: 4 additions & 0 deletions plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1583,6 +1583,10 @@ uint64_t read_only::get_table_index_name(const read_only::get_table_rows_params&
return index;
}

uint64_t convert_to_type(const eosio::name &n, const string &desc) {
return n.to_uint64_t();
}

template<>
uint64_t convert_to_type(const string& str, const string& desc) {

Expand Down
20 changes: 14 additions & 6 deletions plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ Type convert_to_type(const string& str, const string& desc) {
} FC_RETHROW_EXCEPTIONS(warn, "Could not convert ${desc} string '${str}' to key type.", ("desc", desc)("str",str) )
}

uint64_t convert_to_type(const eosio::name &n, const string &desc);

template<>
uint64_t convert_to_type(const string& str, const string& desc);

Expand Down Expand Up @@ -518,9 +520,12 @@ class read_only {

if( p.lower_bound.size() ) {
if( p.key_type == "name" ) {
name s(p.lower_bound);
SecKeyType lv = convert_to_type<SecKeyType>( s.to_string(), "lower_bound name" ); // avoids compiler error
std::get<1>(lower_bound_lookup_tuple) = conv( lv );
if constexpr (std::is_same_v<uint64_t, SecKeyType>) {
SecKeyType lv = convert_to_type(name{p.lower_bound}, "lower_bound name");
std::get<1>(lower_bound_lookup_tuple) = conv(lv);
} else {
EOS_ASSERT(false, chain::contract_table_query_exception, "Invalid key type of eosio::name ${nm} for lower bound", ("nm", p.lower_bound));
}
} else {
SecKeyType lv = convert_to_type<SecKeyType>( p.lower_bound, "lower_bound" );
std::get<1>(lower_bound_lookup_tuple) = conv( lv );
Expand All @@ -529,9 +534,12 @@ class read_only {

if( p.upper_bound.size() ) {
if( p.key_type == "name" ) {
name s(p.upper_bound);
SecKeyType uv = convert_to_type<SecKeyType>( s.to_string(), "upper_bound name" );
std::get<1>(upper_bound_lookup_tuple) = conv( uv );
if constexpr (std::is_same_v<uint64_t, SecKeyType>) {
SecKeyType uv = convert_to_type(name{p.upper_bound}, "upper_bound name");
std::get<1>(upper_bound_lookup_tuple) = conv(uv);
} else {
EOS_ASSERT(false, chain::contract_table_query_exception, "Invalid key type of eosio::name ${nm} for upper bound", ("nm", p.upper_bound));
}
} else {
SecKeyType uv = convert_to_type<SecKeyType>( p.upper_bound, "upper_bound" );
std::get<1>(upper_bound_lookup_tuple) = conv( uv );
Expand Down
98 changes: 98 additions & 0 deletions tests/get_table_seckey_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#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 <contracts.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(get_table_seckey_tests)

BOOST_FIXTURE_TEST_CASE( get_table_next_key_test, TESTER ) try {
create_account("test"_n);

// setup contract and abi
set_code( "test"_n, contracts::get_table_seckey_test_wasm() );
set_abi( "test"_n, contracts::get_table_seckey_test_abi().data() );
produce_block();

chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum(), {}, {});
chain_apis::read_only::get_table_rows_params params = []{
chain_apis::read_only::get_table_rows_params params{};
params.json=true;
params.code="test"_n;
params.scope="test";
params.limit=1;
return params;
}();

params.table = "numobjs"_n;


// name secondary key type
push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 2)("nm", "a"));
push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 5)("nm", "b"));
push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 7)("nm", "c"));

params.table = "numobjs"_n;
params.key_type = "name";
params.limit = 10;
params.index_position = "6";
params.lower_bound = "a";
params.upper_bound = "a";
auto res_nm = plugin.get_table_rows(params);
BOOST_REQUIRE(res_nm.rows.size() == 1);

params.lower_bound = "a";
params.upper_bound = "b";
res_nm = plugin.get_table_rows(params);
BOOST_REQUIRE(res_nm.rows.size() == 2);

params.lower_bound = "a";
params.upper_bound = "c";
res_nm = plugin.get_table_rows(params);
BOOST_REQUIRE(res_nm.rows.size() == 3);

push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 8)("nm", "1111"));
push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 9)("nm", "2222"));
push_action("test"_n, "addnumobj"_n, "test"_n, mutable_variant_object()("input", 10)("nm", "3333"));

params.lower_bound = "1111";
params.upper_bound = "3333";
res_nm = plugin.get_table_rows(params);
BOOST_REQUIRE(res_nm.rows.size() == 3);

params.lower_bound = "2222";
params.upper_bound = "3333";
res_nm = plugin.get_table_rows(params);
BOOST_REQUIRE(res_nm.rows.size() == 2);

} FC_LOG_AND_RETHROW() /// get_table_next_key_test

BOOST_AUTO_TEST_SUITE_END()
1 change: 1 addition & 0 deletions unittests/test-contracts/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ add_subdirectory( asserter )
add_subdirectory( deferred_test )
add_subdirectory( get_sender_test )
add_subdirectory( get_table_test )
add_subdirectory( get_table_seckey_test )
add_subdirectory( integration_test )
add_subdirectory( noop )
add_subdirectory( payloadless )
Expand Down
6 changes: 6 additions & 0 deletions unittests/test-contracts/get_table_seckey_test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
if( EOSIO_COMPILE_TEST_CONTRACTS )
add_contract( get_table_seckey_test get_table_seckey_test get_table_seckey_test.cpp )
else()
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/get_table_seckey_test.wasm ${CMAKE_CURRENT_BINARY_DIR}/get_table_seckey_test.wasm COPYONLY )
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/get_table_seckey_test.abi ${CMAKE_CURRENT_BINARY_DIR}/get_table_seckey_test.abi COPYONLY )
endif()
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"____comment": "This file was generated with eosio-abigen. DO NOT EDIT ",
"version": "eosio::abi/1.2",
"types": [],
"structs": [
{
"name": "addnumobj",
"base": "",
"fields": [
{
"name": "input",
"type": "uint64"
},
{
"name": "nm",
"type": "string"
}
]
},
{
"name": "numobj",
"base": "",
"fields": [
{
"name": "key",
"type": "uint64"
},
{
"name": "sec64",
"type": "uint64"
},
{
"name": "sec128",
"type": "uint128"
},
{
"name": "secdouble",
"type": "float64"
},
{
"name": "secldouble",
"type": "float128"
},
{
"name": "nm",
"type": "name"
}
]
}
],
"actions": [
{
"name": "addnumobj",
"type": "addnumobj",
"ricardian_contract": ""
}
],
"tables": [
{
"name": "numobjs",
"type": "numobj",
"index_type": "i64",
"key_names": [],
"key_types": []
}
],
"kv_tables": {},
"ricardian_clauses": [],
"variants": [],
"action_results": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* @file
* @copyright defined in eos/LICENSE
*/
#include "get_table_seckey_test.hpp"


void get_table_seckey_test::addnumobj(uint64_t input, std::string nm) {
numobjs numobjs_table( _self, _self.value );
numobjs_table.emplace(_self, [&](auto &obj) {
obj.key = numobjs_table.available_primary_key();
obj.sec64 = input;
obj.sec128 = input;
obj.secdouble = input;
obj.secldouble = input;
obj.nm = name(nm);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* @file
* @copyright defined in eos/LICENSE
*/
#pragma once

#include <eosio/eosio.hpp>
#include <eosio/crypto.hpp>

using namespace eosio;

class [[eosio::contract]] get_table_seckey_test : public eosio::contract {
public:
using eosio::contract::contract;

// Number object
struct [[eosio::table]] numobj {
uint64_t key;
uint64_t sec64;
uint128_t sec128;
double secdouble;
long double secldouble;
name nm;

uint64_t primary_key() const { return key; }
uint64_t sec64_key() const { return sec64; }
uint128_t sec128_key() const { return sec128; }
double secdouble_key() const { return secdouble; }
long double secldouble_key() const { return secldouble; }
uint64_t name_key() const { return nm.value; }
};

typedef eosio::multi_index< "numobjs"_n, numobj,
indexed_by<"bysec1"_n, const_mem_fun<numobj, uint64_t, &numobj::sec64_key>>,
indexed_by<"bysec2"_n, const_mem_fun<numobj, uint128_t, &numobj::sec128_key>>,
indexed_by<"bysec3"_n, const_mem_fun<numobj, double, &numobj::secdouble_key>>,
indexed_by<"bysec4"_n, const_mem_fun<numobj, long double, &numobj::secldouble_key>>,
indexed_by<"byname"_n, const_mem_fun<numobj, uint64_t, &numobj::name_key>>
> numobjs;

[[eosio::action]]
void addnumobj(uint64_t input, std::string nm);
};
Binary file not shown.