Skip to content

Commit 5fe30e1

Browse files
committed
fix get_kv_table_rows secondary index search
1 parent e653931 commit 5fe30e1

10 files changed

Lines changed: 1057 additions & 19 deletions

File tree

plugins/chain_plugin/chain_plugin.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2238,6 +2238,7 @@ read_only::get_table_rows_result read_only::get_kv_table_rows_context( const rea
22382238
if( !point_query ) {
22392239
lb_key.resize(lb_key_size);
22402240
status_lb = lb_itr->kv_it_key(0, lb_key.data(), lb_key_size, lb_key_actual_size);
2241+
EOS_ASSERT(lb_key_size == lb_key_actual_size, chain::contract_table_query_exception, "Invalid lower bound iterator in ${t} ${i}", ("t", p.table)("i", p.index_name));
22412242
}
22422243
}
22432244

@@ -2253,6 +2254,7 @@ read_only::get_table_rows_result read_only::get_kv_table_rows_context( const rea
22532254
EOS_ASSERT(status_ub != chain::kv_it_stat::iterator_erased, chain::contract_table_query_exception, "Invalid upper bound iterator in ${t} ${i}", ("t", p.table)("i", p.index_name));
22542255
ub_key.resize(ub_key_size);
22552256
status_ub = ub_itr->kv_it_key(0, ub_key.data(), ub_key_size, ub_key_actual_size);
2257+
EOS_ASSERT(ub_key_size == ub_key_actual_size, chain::contract_table_query_exception, "Invalid upper bound iterator in ${t} ${i}", ("t", p.table)("i", p.index_name));
22562258
}
22572259

22582260
kv_it_stat status;
@@ -2283,7 +2285,8 @@ read_only::get_table_rows_result read_only::get_kv_table_rows_context( const rea
22832285
unsigned int count = 0;
22842286
for( count = 0; cur_time <= end_time && count < p.limit && cmp < 0; cur_time = fc::time_point::now() ) {
22852287
row_key.resize(key_size);
2286-
status = itr->kv_it_key(0, row_key.data(), key_size, value_size);
2288+
status = itr->kv_it_key(0, row_key.data(), key_size, actual_size);
2289+
EOS_ASSERT(key_size == actual_size, chain::contract_table_query_exception, "Invalid iterator in ${t} ${i}", ("t", p.table)("i", p.index_name));
22872290
if( point_query ) {
22882291
if( row_key.size() != lb_key_size || row_key != lb_key) {
22892292
cmp = 1;
@@ -2293,17 +2296,19 @@ read_only::get_table_rows_result read_only::get_kv_table_rows_context( const rea
22932296

22942297
row_value.clear();
22952298
row_value.resize(value_size);
2296-
status = itr->kv_it_value(offset, row_value.data(), key_size, value_size);
2297-
EOS_ASSERT(status == chain::kv_it_stat::iterator_ok, chain::contract_table_query_exception, "Invalid key in ${t} ${i}", ("t", p.table)("i", p.index_name));
2299+
status = itr->kv_it_value(offset, row_value.data(), value_size, actual_size);
2300+
EOS_ASSERT(status == chain::kv_it_stat::iterator_ok, chain::contract_table_query_exception, "Invalid iterator value in ${t} ${i}", ("t", p.table)("i", p.index_name));
2301+
EOS_ASSERT(value_size == actual_size, chain::contract_table_query_exception, "Invalid iterator value in ${t} ${i}", ("t", p.table)("i", p.index_name));
22982302

22992303
if (!is_primary_idx) {
2304+
value_size = row_value.size();
23002305
auto success = kv_context.kv_get(p.code.to_uint64_t(), row_value.data(), row_value.size(), value_size);
23012306
if (success) {
23022307
row_value.resize(value_size);
23032308
actual_size = kv_context.kv_get_data(offset, row_value.data(), value_size);
2304-
EOS_ASSERT(value_size == actual_size, chain::contract_table_query_exception, "range query value size mismatch: ${s1} ${s2}", ("s1", value_size)("s2", actual_size));
2309+
EOS_ASSERT(value_size == actual_size, chain::contract_table_query_exception, "query value size mismatch: ${s1} ${s2}", ("s1", value_size)("s2", actual_size));
23052310
} else {
2306-
EOS_ASSERT(value_size == actual_size, chain::contract_table_query_exception, "range query value size mismatch: ${s1} ${s2}", ("s1", value_size)("s2", actual_size));
2311+
EOS_ASSERT(false, chain::contract_table_query_exception, "invalid secondary index in ${t} ${i}", ("t", p.table)("i", p.index_name));
23072312
}
23082313
}
23092314

tests/get_kv_table_addr_tests.cpp

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
#include <boost/test/unit_test.hpp>
2+
#include <boost/algorithm/string/predicate.hpp>
3+
4+
#include <eosio/testing/tester.hpp>
5+
#include <eosio/chain/abi_serializer.hpp>
6+
#include <eosio/chain/wasm_eosio_constraints.hpp>
7+
#include <eosio/chain/resource_limits.hpp>
8+
#include <eosio/chain/exceptions.hpp>
9+
#include <eosio/chain/wast_to_wasm.hpp>
10+
#include <eosio/chain_plugin/chain_plugin.hpp>
11+
#include <eosio/chain/backing_store/kv_context.hpp>
12+
13+
#include <contracts.hpp>
14+
15+
#include <fc/io/fstream.hpp>
16+
17+
#include <Runtime/Runtime.h>
18+
19+
#include <fc/variant_object.hpp>
20+
#include <fc/io/json.hpp>
21+
22+
#include <array>
23+
#include <utility>
24+
25+
#ifdef NON_VALIDATING_TEST
26+
#define TESTER tester
27+
#else
28+
#define TESTER validating_tester
29+
#endif
30+
31+
using namespace eosio;
32+
using namespace eosio::chain;
33+
using namespace eosio::testing;
34+
using namespace fc;
35+
36+
BOOST_AUTO_TEST_SUITE(get_kv_table_addr_tests)
37+
38+
39+
BOOST_FIXTURE_TEST_CASE( get_kv_table_addr_test, TESTER ) try {
40+
eosio::chain_apis::read_only::get_table_rows_result result;
41+
auto chk_result = [&](int row, int data) {
42+
if( data == 1 )
43+
{
44+
BOOST_REQUIRE_EQUAL("jane", result.rows[row]["account_name"].as_string());
45+
BOOST_REQUIRE_EQUAL("jane", result.rows[row]["first_name"]["field_0"].as_string());
46+
BOOST_REQUIRE_EQUAL("Jane", result.rows[row]["first_name"]["field_1"].as_string());
47+
BOOST_REQUIRE_EQUAL("jane", result.rows[row]["last_name"]["field_0"].as_string());
48+
BOOST_REQUIRE_EQUAL("Doe", result.rows[row]["last_name"]["field_1"].as_string());
49+
BOOST_REQUIRE_EQUAL("1234 MyStreet", result.rows[row]["street_city_state_cntry"]["field_1"].as_string());
50+
BOOST_REQUIRE_EQUAL("jane", result.rows[row]["personal_id"]["field_0"].as_string());
51+
BOOST_REQUIRE_EQUAL("jdoe", result.rows[row]["personal_id"]["field_1"].as_string());
52+
}
53+
else if (data == 2)
54+
{
55+
BOOST_REQUIRE_EQUAL("john", result.rows[row]["account_name"].as_string());
56+
BOOST_REQUIRE_EQUAL("john", result.rows[row]["first_name"]["field_0"].as_string());
57+
BOOST_REQUIRE_EQUAL("John", result.rows[row]["first_name"]["field_1"].as_string());
58+
BOOST_REQUIRE_EQUAL("john", result.rows[row]["last_name"]["field_0"].as_string());
59+
BOOST_REQUIRE_EQUAL("Smith", result.rows[row]["last_name"]["field_1"].as_string());
60+
BOOST_REQUIRE_EQUAL("123 MyStreet", result.rows[row]["street_city_state_cntry"]["field_1"].as_string());
61+
BOOST_REQUIRE_EQUAL("john", result.rows[row]["personal_id"]["field_0"].as_string());
62+
BOOST_REQUIRE_EQUAL("jsmith", result.rows[row]["personal_id"]["field_1"].as_string());
63+
}
64+
else if (data == 3)
65+
{
66+
BOOST_REQUIRE_EQUAL("lois", result.rows[row]["account_name"].as_string());
67+
BOOST_REQUIRE_EQUAL("lois", result.rows[row]["first_name"]["field_0"].as_string());
68+
BOOST_REQUIRE_EQUAL("Lois", result.rows[row]["first_name"]["field_1"].as_string());
69+
BOOST_REQUIRE_EQUAL("lois", result.rows[row]["last_name"]["field_0"].as_string());
70+
BOOST_REQUIRE_EQUAL("Lane", result.rows[row]["last_name"]["field_1"].as_string());
71+
BOOST_REQUIRE_EQUAL("5432 MyStreet", result.rows[row]["street_city_state_cntry"]["field_1"].as_string());
72+
BOOST_REQUIRE_EQUAL("lois", result.rows[row]["personal_id"]["field_0"].as_string());
73+
BOOST_REQUIRE_EQUAL("llane", result.rows[row]["personal_id"]["field_1"].as_string());
74+
}
75+
else
76+
{
77+
BOOST_REQUIRE_EQUAL("steve", result.rows[row]["account_name"].as_string());
78+
BOOST_REQUIRE_EQUAL("steve", result.rows[row]["first_name"]["field_0"].as_string());
79+
BOOST_REQUIRE_EQUAL("Steve", result.rows[row]["first_name"]["field_1"].as_string());
80+
BOOST_REQUIRE_EQUAL("steve", result.rows[row]["last_name"]["field_0"].as_string());
81+
BOOST_REQUIRE_EQUAL("Jones", result.rows[row]["last_name"]["field_1"].as_string());
82+
BOOST_REQUIRE_EQUAL("321 MyStreet", result.rows[row]["street_city_state_cntry"]["field_1"].as_string());
83+
BOOST_REQUIRE_EQUAL("steve", result.rows[row]["personal_id"]["field_0"].as_string());
84+
BOOST_REQUIRE_EQUAL("sjones", result.rows[row]["personal_id"]["field_1"].as_string());
85+
}
86+
};
87+
88+
produce_blocks(2);
89+
90+
create_accounts({ "kvaddrbook"_n });
91+
92+
produce_block();
93+
94+
set_code(config::system_account_name, contracts::kv_bios_wasm());
95+
set_abi(config::system_account_name, contracts::kv_bios_abi().data());
96+
push_action("eosio"_n, "ramkvlimits"_n, "eosio"_n, mutable_variant_object()("k", 1024)("v", 1024)("i", 1024));
97+
produce_blocks(1);
98+
99+
set_code( "kvaddrbook"_n, contracts::kv_addr_book_wasm() );
100+
set_abi( "kvaddrbook"_n, contracts::kv_addr_book_abi().data() );
101+
produce_blocks(1);
102+
103+
auto arg = mutable_variant_object();
104+
push_action("kvaddrbook"_n, "test"_n, "kvaddrbook"_n, arg );
105+
106+
107+
eosio::chain_apis::read_only plugin(*(this->control), {}, fc::microseconds::maximum());
108+
eosio::chain_apis::read_only::get_kv_table_rows_params p;
109+
p.code = "kvaddrbook"_n;
110+
p.table = "kvaddrbook"_n;
111+
p.index_name = "accname"_n;
112+
p.index_value = "john";
113+
p.encode_type = "name";
114+
p.lower_bound = "";
115+
p.upper_bound = "";
116+
p.json = true;
117+
p.reverse = false;
118+
result = plugin.read_only::get_kv_table_rows(p);
119+
BOOST_REQUIRE_EQUAL(1u, result.rows.size());
120+
chk_result(0, 2);
121+
122+
p.index_name = "accname"_n;
123+
p.index_value = "";
124+
p.encode_type = "name";
125+
p.lower_bound = "aaa";
126+
p.upper_bound = "";
127+
p.reverse = false;
128+
result = plugin.read_only::get_kv_table_rows(p);
129+
BOOST_REQUIRE_EQUAL(4u, result.rows.size());
130+
chk_result(0, 1);
131+
chk_result(1, 2);
132+
chk_result(2, 3);
133+
chk_result(3, 4);
134+
135+
p.index_name = "accname"_n;
136+
p.index_value = "";
137+
p.encode_type = "name";
138+
p.lower_bound = "john";
139+
p.upper_bound = "";
140+
p.reverse = false;
141+
result = plugin.read_only::get_kv_table_rows(p);
142+
BOOST_REQUIRE_EQUAL(3u, result.rows.size());
143+
chk_result(0, 2);
144+
chk_result(1, 3);
145+
chk_result(2, 4);
146+
147+
p.index_name = "accname"_n;
148+
p.index_value = "";
149+
p.encode_type = "name";
150+
p.lower_bound = "john";
151+
p.upper_bound = "lois";
152+
p.reverse = false;
153+
result = plugin.read_only::get_kv_table_rows(p);
154+
BOOST_REQUIRE_EQUAL(1u, result.rows.size());
155+
chk_result(0, 2);
156+
157+
p.index_name = "accname"_n;
158+
p.index_value = "";
159+
p.encode_type = "name";
160+
p.lower_bound = "";
161+
p.upper_bound = "steve";
162+
p.reverse = true;
163+
result = plugin.read_only::get_kv_table_rows(p);
164+
BOOST_REQUIRE_EQUAL(4u, result.rows.size());
165+
chk_result(0, 4);
166+
chk_result(1, 3);
167+
chk_result(2, 2);
168+
chk_result(3, 1);
169+
170+
p.index_name = "accname"_n;
171+
p.index_value = "";
172+
p.encode_type = "name";
173+
p.lower_bound = "john";
174+
p.upper_bound = "steve";
175+
p.reverse = true;
176+
result = plugin.read_only::get_kv_table_rows(p);
177+
BOOST_REQUIRE_EQUAL(2u, result.rows.size());
178+
chk_result(0, 4);
179+
chk_result(1, 3);
180+
181+
p.index_name = "accname"_n;
182+
p.index_value = "";
183+
p.encode_type = "name";
184+
p.lower_bound = "";
185+
p.upper_bound = "aaaa";
186+
p.reverse = true;
187+
result = plugin.read_only::get_kv_table_rows(p);
188+
BOOST_REQUIRE_EQUAL(0u, result.rows.size());
189+
190+
p.index_name = "accname"_n;
191+
p.index_value = "";
192+
p.encode_type = "name";
193+
p.lower_bound = "steve";
194+
p.upper_bound = "john";
195+
p.reverse = true;
196+
result = plugin.read_only::get_kv_table_rows(p);
197+
BOOST_REQUIRE_EQUAL(0u, result.rows.size());
198+
199+
p.index_name = "accname"_n;
200+
p.index_value = "";
201+
p.encode_type = "name";
202+
p.lower_bound = "";
203+
p.upper_bound = "john";
204+
p.reverse = true;
205+
result = plugin.read_only::get_kv_table_rows(p);
206+
BOOST_REQUIRE_EQUAL(2u, result.rows.size());
207+
chk_result(0, 2);
208+
chk_result(1, 1);
209+
}
210+
FC_LOG_AND_RETHROW()
211+
212+
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)