未验证 提交 50b5eb1a 编写于 作者: K Kevin Heifner 提交者: GitHub

Merge pull request #5486 from taokayan/get_scope

5380 support iteration over scopes & tables in cleos
......@@ -89,6 +89,7 @@ void chain_api_plugin::plugin_startup() {
CHAIN_RO_CALL(get_abi, 200),
CHAIN_RO_CALL(get_raw_code_and_abi, 200),
CHAIN_RO_CALL(get_table_rows, 200),
CHAIN_RO_CALL(get_table_by_scope, 200),
CHAIN_RO_CALL(get_currency_balance, 200),
CHAIN_RO_CALL(get_currency_stats, 200),
CHAIN_RO_CALL(get_producers, 200),
......
......@@ -1104,6 +1104,48 @@ read_only::get_table_rows_result read_only::get_table_rows( const read_only::get
}
}
read_only::get_table_by_scope_result read_only::get_table_by_scope( const read_only::get_table_by_scope_params& p )const {
const auto& d = db.db();
const auto& idx = d.get_index<chain::table_id_multi_index, chain::by_code_scope_table>();
decltype(idx.lower_bound(boost::make_tuple(0, 0, 0))) lower;
decltype(idx.upper_bound(boost::make_tuple(0, 0, 0))) upper;
if (p.lower_bound.size()) {
uint64_t scope = convert_to_type<uint64_t>(p.lower_bound, "lower_bound scope");
lower = idx.lower_bound( boost::make_tuple(p.code, scope, p.table));
} else {
lower = idx.lower_bound(boost::make_tuple(p.code, 0, p.table));
}
if (p.upper_bound.size()) {
uint64_t scope = convert_to_type<uint64_t>(p.upper_bound, "upper_bound scope");
upper = idx.lower_bound( boost::make_tuple(p.code, scope, 0));
} else {
upper = idx.lower_bound(boost::make_tuple((uint64_t)p.code + 1, 0, 0));
}
auto end = fc::time_point::now() + fc::microseconds(1000 * 10); /// 10ms max time
unsigned int count = 0;
auto itr = lower;
read_only::get_table_by_scope_result result;
for (; itr != upper; ++itr) {
if (p.table && itr->table != p.table) {
if (fc::time_point::now() > end) {
break;
}
continue;
}
result.rows.push_back({itr->code, itr->scope, itr->table, itr->payer, itr->count});
if (++count == p.limit || fc::time_point::now() > end) {
++itr;
break;
}
}
if (itr != upper) {
result.more = (string)itr->scope;
}
return result;
}
vector<asset> read_only::get_currency_balance( const read_only::get_currency_balance_params& p )const {
const abi_def abi = eosio::chain_apis::get_abi( db, p.code );
......
......@@ -260,6 +260,27 @@ public:
get_table_rows_result get_table_rows( const get_table_rows_params& params )const;
struct get_table_by_scope_params {
name code; // mandatory
name table = 0; // optional, act as filter
string lower_bound; // lower bound of scope, optional
string upper_bound; // upper bound of scope, optional
uint32_t limit = 10;
};
struct get_table_by_scope_result_row {
name code;
name scope;
name table;
name payer;
uint32_t count;
};
struct get_table_by_scope_result {
vector<get_table_by_scope_result_row> rows;
string more; ///< fill lower_bound with this value to fetch more rows
};
get_table_by_scope_result get_table_by_scope( const get_table_by_scope_params& params )const;
struct get_currency_balance_params {
name code;
name account;
......@@ -634,6 +655,10 @@ FC_REFLECT( eosio::chain_apis::read_write::push_transaction_results, (transactio
FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_params, (json)(code)(scope)(table)(table_key)(lower_bound)(upper_bound)(limit)(key_type)(index_position)(encode_type) )
FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_result, (rows)(more) );
FC_REFLECT( eosio::chain_apis::read_only::get_table_by_scope_params, (code)(table)(lower_bound)(upper_bound)(limit) )
FC_REFLECT( eosio::chain_apis::read_only::get_table_by_scope_result_row, (code)(scope)(table)(payer)(count));
FC_REFLECT( eosio::chain_apis::read_only::get_table_by_scope_result, (rows)(more) );
FC_REFLECT( eosio::chain_apis::read_only::get_currency_balance_params, (code)(account)(symbol));
FC_REFLECT( eosio::chain_apis::read_only::get_currency_stats_params, (code)(symbol));
FC_REFLECT( eosio::chain_apis::read_only::get_currency_stats_result, (supply)(max_supply)(issuer));
......
......@@ -89,6 +89,7 @@ namespace eosio { namespace client { namespace http {
const string get_block_header_state_func = chain_func_base + "/get_block_header_state";
const string get_account_func = chain_func_base + "/get_account";
const string get_table_func = chain_func_base + "/get_table_rows";
const string get_table_by_scope_func = chain_func_base + "/get_table_by_scope";
const string get_code_func = chain_func_base + "/get_code";
const string get_abi_func = chain_func_base + "/get_abi";
const string get_raw_code_and_abi_func = chain_func_base + "/get_raw_code_and_abi";
......
......@@ -2032,6 +2032,23 @@ int main( int argc, char** argv ) {
<< std::endl;
});
auto getScope = get->add_subcommand( "scope", localized("Retrieve a list of scopes and tables owned by a contract"), false);
getScope->add_option( "contract", code, localized("The contract who owns the table") )->required();
getScope->add_option( "-t,--table", table, localized("The name of the table as filter") );
getScope->add_option( "-l,--limit", limit, localized("The maximum number of rows to return") );
getScope->add_option( "-L,--lower", lower, localized("lower bound of scope") );
getScope->add_option( "-U,--upper", upper, localized("upper bound of scope") );
getScope->set_callback([&] {
auto result = call(get_table_by_scope_func, fc::mutable_variant_object("code",code)
("table",table)
("lower_bound",lower)
("upper_bound",upper)
("limit",limit)
);
std::cout << fc::json::to_pretty_string(result)
<< std::endl;
});
// currency accessors
// get currency balance
string symbol;
......
......@@ -13,7 +13,7 @@ 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)
target_link_libraries( plugin_test eosio_testing eosio_chain chainbase eos_utilities chain_plugin wallet_plugin abi_generator fc ${PLATFORM_SPECIFIC_LIBS} )
......
#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 <eosio.system/eosio.system.wast.hpp>
#include <eosio.system/eosio.system.abi.hpp>
#include <eosio.token/eosio.token.wast.hpp>
#include <eosio.token/eosio.token.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(get_table_tests)
BOOST_FIXTURE_TEST_CASE( get_scope_test, TESTER ) try {
produce_blocks(2);
create_accounts({ N(eosio.token), N(eosio.ram), N(eosio.ramfee), N(eosio.stake),
N(eosio.bpay), N(eosio.vpay), N(eosio.saving), N(eosio.names) });
std::vector<account_name> accs{N(inita), N(initb), N(initc), N(initd)};
create_accounts(accs);
produce_block();
set_code( N(eosio.token), eosio_token_wast );
set_abi( N(eosio.token), eosio_token_abi );
produce_blocks(1);
// create currency
auto act = mutable_variant_object()
("issuer", "eosio")
("maximum_supply", eosio::chain::asset::from_string("1000000000.0000 SYS"));
push_action(N(eosio.token), N(create), N(eosio.token), act );
// issue
for (account_name a: accs) {
push_action( N(eosio.token), N(issue), "eosio", mutable_variant_object()
("to", name(a) )
("quantity", eosio::chain::asset::from_string("999.0000 SYS") )
("memo", "")
);
}
produce_blocks(1);
// iterate over scope
eosio::chain_apis::read_only plugin(*(this->control), fc::microseconds(INT_MAX));
eosio::chain_apis::read_only::get_table_by_scope_params param{N(eosio.token), N(accounts), "inita", "", 10};
eosio::chain_apis::read_only::get_table_by_scope_result result = plugin.read_only::get_table_by_scope(param);
BOOST_REQUIRE_EQUAL(4, result.rows.size());
BOOST_REQUIRE_EQUAL("", result.more);
if (result.rows.size() >= 4) {
BOOST_REQUIRE_EQUAL(name(N(eosio.token)), result.rows[0].code);
BOOST_REQUIRE_EQUAL(name(N(inita)), result.rows[0].scope);
BOOST_REQUIRE_EQUAL(name(N(accounts)), result.rows[0].table);
BOOST_REQUIRE_EQUAL(name(N(eosio)), result.rows[0].payer);
BOOST_REQUIRE_EQUAL(1, result.rows[0].count);
BOOST_REQUIRE_EQUAL(name(N(initb)), result.rows[1].scope);
BOOST_REQUIRE_EQUAL(name(N(initc)), result.rows[2].scope);
BOOST_REQUIRE_EQUAL(name(N(initd)), result.rows[3].scope);
}
param.lower_bound = "initb";
param.upper_bound = "initd";
result = plugin.read_only::get_table_by_scope(param);
BOOST_REQUIRE_EQUAL(2, result.rows.size());
BOOST_REQUIRE_EQUAL("", result.more);
if (result.rows.size() >= 2) {
BOOST_REQUIRE_EQUAL(name(N(initb)), result.rows[0].scope);
BOOST_REQUIRE_EQUAL(name(N(initc)), result.rows[1].scope);
}
param.limit = 1;
result = plugin.read_only::get_table_by_scope(param);
BOOST_REQUIRE_EQUAL(1, result.rows.size());
BOOST_REQUIRE_EQUAL("initc", result.more);
param.table = name(0);
result = plugin.read_only::get_table_by_scope(param);
BOOST_REQUIRE_EQUAL(1, result.rows.size());
BOOST_REQUIRE_EQUAL("initc", result.more);
param.table = N(invalid);
result = plugin.read_only::get_table_by_scope(param);
BOOST_REQUIRE_EQUAL(0, result.rows.size());
BOOST_REQUIRE_EQUAL("", result.more);
} FC_LOG_AND_RETHROW() /// get_scope_test
BOOST_AUTO_TEST_SUITE_END()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册