Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion plugins/chain_api_plugin/chain.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,11 @@ paths:
description: List of authorizing keys
items:
$ref: "https://docs.eosnetwork.com/openapi/v2.0/PublicKey.yaml"
limit:
type: integer
default: 1000
maximum: 1000
description: Maximum number of account permission authorities to return. The server enforces an upper bound of 1000.
responses:
"200":
description: OK
Expand All @@ -685,6 +690,7 @@ paths:
description: Result containing a list of accounts which are authorized, in whole or part, by the provided accounts and keys
required:
- accounts
- more
properties:
accounts:
type: array
Expand Down Expand Up @@ -713,6 +719,9 @@ paths:
threshold:
type: "integer"
description: the sum of weights that must be met or exceeded to satisfy the permission
more:
type: boolean
description: True when additional matching account permission authorities were omitted because the result limit was reached.
/get_transaction_status:
post:
description: Attempts to get current blockchain state and, if available, transaction information given the transaction id. For query to work, the transaction finality status feature must be enabled by configuring the chain plugin with the config option '--transaction-finality-status-max-storage-size-gb' in nodeos.
Expand Down Expand Up @@ -927,4 +936,4 @@ paths:
content:
application/json:
schema:
description: Returns Nothing
description: Returns Nothing
21 changes: 16 additions & 5 deletions plugins/chain_plugin/account_query_db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <boost/bimap/multiset_of.hpp>
#include <boost/bimap/set_of.hpp>

#include <algorithm>
#include <shared_mutex>

using namespace eosio;
Expand Down Expand Up @@ -423,6 +424,7 @@ namespace eosio::chain_apis {

using result_t = account_query_db::get_accounts_by_authorizers_result;
result_t result;
const auto limit = std::min(args.limit, account_query_db::max_results);

// deduplicate inputs
auto account_set = std::set<chain::permission_level>(args.accounts.begin(), args.accounts.end());
Expand All @@ -431,8 +433,9 @@ namespace eosio::chain_apis {
/**
* Add a range of results
*/
auto push_results = [&result](const auto& begin, const auto& end) {
for (auto itr = begin; itr != end; ++itr) {
auto push_results = [&result, limit](const auto& begin, const auto& end) {
auto itr = begin;
for (; itr != end && result.accounts.size() < limit; ++itr) {
const auto& pi = itr->second.get();
const auto& authorizer = itr->first.value;
auto weight = itr->first.weight;
Expand All @@ -446,6 +449,11 @@ namespace eosio::chain_apis {
pi.threshold
});
}
if (itr != end) {
result.more = true;
return false;
}
return true;
};


Expand All @@ -457,21 +465,24 @@ namespace eosio::chain_apis {
const auto begin = name_bimap.left.lower_bound(weighted<chain::permission_level>::lower_bound_for({a.actor, a.permission}));
const auto next_account_name = chain::name(a.actor.to_uint64_t() + 1);
const auto end = name_bimap.left.lower_bound(weighted<chain::permission_level>::lower_bound_for({next_account_name, a.permission}));
push_results(begin, end);
if (!push_results(begin, end))
return result;
} else {
// construct a range of all possible weights for an account/permission pair
const auto p = chain::permission_level{a.actor, a.permission};
const auto begin = name_bimap.left.lower_bound(weighted<chain::permission_level>::lower_bound_for(p));
const auto end = name_bimap.left.upper_bound(weighted<chain::permission_level>::upper_bound_for(p));
push_results(begin, end);
if (!push_results(begin, end))
return result;
}
}

for (const auto& k: key_set) {
// construct a range of all possible weights for a key
const auto begin = key_bimap.left.lower_bound(weighted<chain::public_key_type>::lower_bound_for(k));
const auto end = key_bimap.left.upper_bound(weighted<chain::public_key_type>::upper_bound_for(k));
push_results(begin, end);
if (!push_results(begin, end))
return result;
}

return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ namespace eosio::chain_apis {
*/
class account_query_db {
public:
static constexpr uint32_t max_results = 1000;


/**
* Instantiate a new account query DB from the given chain controller
Expand Down Expand Up @@ -54,6 +56,7 @@ namespace eosio::chain_apis {

std::vector<permission_level> accounts;
std::vector<chain::public_key_type> keys;
uint32_t limit = max_results;
};

/**
Expand All @@ -70,6 +73,7 @@ namespace eosio::chain_apis {
};

std::vector<account_result> accounts;
bool more = false;
};
/**
* Given a set of account names and public keys, find all account permission authorities that are, in part or whole,
Expand Down Expand Up @@ -130,6 +134,6 @@ namespace fc {
}
}

FC_REFLECT( eosio::chain_apis::account_query_db::get_accounts_by_authorizers_params, (accounts)(keys))
FC_REFLECT( eosio::chain_apis::account_query_db::get_accounts_by_authorizers_params, (accounts)(keys)(limit))
FC_REFLECT( eosio::chain_apis::account_query_db::get_accounts_by_authorizers_result::account_result, (account_name)(permission_name)(authorizing_account)(authorizing_key)(weight)(threshold))
FC_REFLECT( eosio::chain_apis::account_query_db::get_accounts_by_authorizers_result, (accounts))
FC_REFLECT( eosio::chain_apis::account_query_db::get_accounts_by_authorizers_result, (accounts)(more))
42 changes: 41 additions & 1 deletion plugins/chain_plugin/test/test_account_query_db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,47 @@ BOOST_FIXTURE_TEST_CASE(updateauth_test, validating_tester) { try {

} FC_LOG_AND_RETHROW() }

BOOST_FIXTURE_TEST_CASE(get_accounts_by_authorizers_limit_test, validating_tester) { try {

auto aq_db = account_query_db(*control);

auto c = control->accepted_block.connect([&](const block_signal_params& t) {
const auto& [ block, id ] = t;
aq_db.commit_block( block );
});

produce_blocks(10);

const auto tester_account = "tester"_n;
const auto shared_key = get_public_key(tester_account, "shared");
create_account(tester_account);

for (const auto permission : {"first"_n, "second"_n, "third"_n}) {
const auto trace_ptr = push_action(config::system_account_name, updateauth::get_name(), tester_account,
fc::mutable_variant_object()
("account", tester_account)
("permission", permission)
("parent", "active")
("auth", authority(shared_key, 1)));
aq_db.cache_transaction_trace(trace_ptr);
produce_block();
}

params pars;
pars.keys.emplace_back(shared_key);
pars.limit = 2;

const auto limited_results = aq_db.get_accounts_by_authorizers(pars);
BOOST_TEST_REQUIRE(limited_results.accounts.size() == 2u);
BOOST_TEST_REQUIRE(limited_results.more == true);

pars.limit = 3;
const auto complete_results = aq_db.get_accounts_by_authorizers(pars);
BOOST_TEST_REQUIRE(complete_results.accounts.size() == 3u);
BOOST_TEST_REQUIRE(complete_results.more == false);

} FC_LOG_AND_RETHROW() }

BOOST_FIXTURE_TEST_CASE(updateauth_test_multi_threaded, validating_tester) { try {

// instantiate an account_query_db
Expand Down Expand Up @@ -286,4 +327,3 @@ BOOST_AUTO_TEST_CASE(fork_test) { try {
} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_SUITE_END()