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

Improve delegators rpc by adding "count", "start", and "threshold" parameters (#3330) #3333

Merged
merged 16 commits into from
Jun 15, 2021
Merged
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
29 changes: 21 additions & 8 deletions nano/node/json_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2068,20 +2068,33 @@ void nano::json_handler::database_txn_tracker ()

void nano::json_handler::delegators ()
{
auto account (account_impl ());
auto representative (account_impl ());
auto count (count_optional_impl (1024));
auto threshold (threshold_optional_impl ());
auto start_account_text (request.get_optional<std::string> ("start"));

nano::account start_account (0);
if (!ec && start_account_text.is_initialized ())
{
start_account = account_impl (start_account_text.get ());
}

if (!ec)
{
boost::property_tree::ptree delegators;
auto transaction (node.store.tx_begin_read ());
for (auto i (node.store.account.begin (transaction)), n (node.store.account.end ()); i != n; ++i)
boost::property_tree::ptree delegators;
for (auto i (node.store.account.begin (transaction, start_account.number () + 1)), n (node.store.account.end ()); i != n && delegators.size () < count; ++i)
{
nano::account_info const & info (i->second);
if (info.representative == account)
if (info.representative == representative)
{
std::string balance;
nano::uint128_union (info.balance).encode_dec (balance);
nano::account const & account (i->first);
delegators.put (account.to_account (), balance);
if (info.balance.number () >= threshold.number ())
{
std::string balance;
nano::uint128_union (info.balance).encode_dec (balance);
nano::account const & delegator (i->first);
delegators.put (delegator.to_account (), balance);
}
}
}
response_l.add_child ("delegators", delegators);
Expand Down
111 changes: 111 additions & 0 deletions nano/rpc_test/rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4633,6 +4633,117 @@ TEST (rpc, delegators)
ASSERT_EQ ("340282366920938463463374607431768211355", delegators.get<std::string> (key.pub.to_account ()));
}

TEST (rpc, delegators_parameters)
{
nano::system system;
auto & node1 = *add_ipc_enabled_node (system);
nano::keypair key;
auto latest (node1.latest (nano::dev_genesis_key.pub));
nano::send_block send (latest, key.pub, 100, nano::dev_genesis_key.prv, nano::dev_genesis_key.pub, *node1.work_generate_blocking (latest));
node1.process (send);
nano::open_block open (send.hash (), nano::dev_genesis_key.pub, key.pub, key.prv, key.pub, *node1.work_generate_blocking (key.pub));
ASSERT_EQ (nano::process_result::progress, node1.process (open).code);

scoped_io_thread_name_change scoped_thread_name_io;
nano::node_rpc_config node_rpc_config;
nano::ipc::ipc_server ipc_server (node1, node_rpc_config);
nano::rpc_config rpc_config (nano::get_available_port (), true);
rpc_config.rpc_process.ipc_port = node1.config.ipc_config.transport_tcp.port;
nano::ipc_rpc_processor ipc_rpc_processor (system.io_ctx, rpc_config);
nano::rpc rpc (system.io_ctx, rpc_config, ipc_rpc_processor);
rpc.start ();

// Test with "count" = 2
boost::property_tree::ptree request;
request.put ("action", "delegators");
request.put ("account", nano::dev_genesis_key.pub.to_account ());
request.put ("count", 2);
test_response response (request, rpc.config.port, system.io_ctx);
ASSERT_TIMELY (5s, response.status != 0);
ASSERT_EQ (200, response.status);
auto & delegators_node (response.json.get_child ("delegators"));
boost::property_tree::ptree delegators;
for (auto i (delegators_node.begin ()), n (delegators_node.end ()); i != n; ++i)
{
delegators.put ((i->first), (i->second.get<std::string> ("")));
}
ASSERT_EQ (2, delegators.size ());
ASSERT_EQ ("100", delegators.get<std::string> (nano::dev_genesis_key.pub.to_account ()));
ASSERT_EQ ("340282366920938463463374607431768211355", delegators.get<std::string> (key.pub.to_account ()));

// Test with "count" = 1
request.put ("count", 1);
test_response response2 (request, rpc.config.port, system.io_ctx);
ASSERT_TIMELY (5s, response2.status != 0);
ASSERT_EQ (200, response2.status);
auto & delegators_node2 (response2.json.get_child ("delegators"));
boost::property_tree::ptree delegators2;
for (auto i (delegators_node2.begin ()), n (delegators_node2.end ()); i != n; ++i)
{
delegators2.put ((i->first), (i->second.get<std::string> ("")));
}
ASSERT_EQ (1, delegators2.size ());
// What is first in ledger by public key?
if (nano::dev_genesis_key.pub.number () < key.pub.number ())
{
ASSERT_EQ ("100", delegators2.get<std::string> (nano::dev_genesis_key.pub.to_account ()));
}
else
{
ASSERT_EQ ("340282366920938463463374607431768211355", delegators2.get<std::string> (key.pub.to_account ()));
}

// Test with "threshold"
request.put ("count", 1024);
request.put ("threshold", 101); // higher than remaining genesis balance
test_response response3 (request, rpc.config.port, system.io_ctx);
ASSERT_TIMELY (5s, response3.status != 0);
ASSERT_EQ (200, response3.status);
auto & delegators_node3 (response3.json.get_child ("delegators"));
boost::property_tree::ptree delegators3;
for (auto i (delegators_node3.begin ()), n (delegators_node3.end ()); i != n; ++i)
{
delegators3.put ((i->first), (i->second.get<std::string> ("")));
}
ASSERT_EQ (1, delegators3.size ());
ASSERT_EQ ("340282366920938463463374607431768211355", delegators3.get<std::string> (key.pub.to_account ()));

// Test with "start" before last account
request.put ("threshold", 0);
auto last_account (key.pub);
if (nano::dev_genesis_key.pub.number () > key.pub.number ())
{
last_account = nano::dev_genesis_key.pub;
}
request.put ("start", nano::account (last_account.number () - 1).to_account ());

test_response response4 (request, rpc.config.port, system.io_ctx);
ASSERT_TIMELY (5s, response4.status != 0);
ASSERT_EQ (200, response4.status);
auto & delegators_node4 (response4.json.get_child ("delegators"));
boost::property_tree::ptree delegators4;
for (auto i (delegators_node4.begin ()), n (delegators_node4.end ()); i != n; ++i)
{
delegators4.put ((i->first), (i->second.get<std::string> ("")));
}
ASSERT_EQ (1, delegators4.size ());
boost::optional<std::string> balance (delegators4.get_optional<std::string> (last_account.to_account ()));
ASSERT_TRUE (balance.is_initialized ());

// Test with "start" equal to last account
request.put ("start", last_account.to_account ());
test_response response5 (request, rpc.config.port, system.io_ctx);
ASSERT_TIMELY (5s, response5.status != 0);
ASSERT_EQ (200, response5.status);
auto & delegators_node5 (response5.json.get_child ("delegators"));
boost::property_tree::ptree delegators5;
for (auto i (delegators_node5.begin ()), n (delegators_node5.end ()); i != n; ++i)
{
delegators5.put ((i->first), (i->second.get<std::string> ("")));
}
ASSERT_EQ (0, delegators5.size ());
}

TEST (rpc, delegators_count)
{
nano::system system;
Expand Down