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

Add threshold optional to RPC unopened and ledger #2014

Merged
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
82 changes: 49 additions & 33 deletions nano/node/json_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2249,6 +2249,7 @@ void nano::json_handler::key_expand ()
void nano::json_handler::ledger ()
{
auto count (count_optional_impl ());
auto threshold (threshold_optional_impl ());
if (!ec)
{
nano::account start (0);
Expand Down Expand Up @@ -2280,10 +2281,19 @@ void nano::json_handler::ledger ()
for (auto i (node.store.latest_begin (transaction, start)), n (node.store.latest_end ()); i != n && accounts.size () < count; ++i)
{
nano::account_info const & info (i->second);
if (info.modified >= modified_since)
if (info.modified >= modified_since && (pending || info.balance.number () >= threshold.number ()))
{
nano::account const & account (i->first);
boost::property_tree::ptree response_a;
if (pending)
{
auto account_pending (node.ledger.account_pending (transaction, account));
if (info.balance.number () + account_pending < threshold.number ())
{
continue;
}
response_a.put ("pending", account_pending.convert_to<std::string> ());
}
response_a.put ("frontier", info.head.to_string ());
response_a.put ("open_block", info.open_block.to_string ());
response_a.put ("representative_block", info.rep_block.to_string ());
Expand All @@ -2303,11 +2313,6 @@ void nano::json_handler::ledger ()
auto account_weight (node.ledger.weight (transaction, account));
response_a.put ("weight", account_weight.convert_to<std::string> ());
}
if (pending)
{
auto account_pending (node.ledger.account_pending (transaction, account));
response_a.put ("pending", account_pending.convert_to<std::string> ());
}
accounts.push_back (std::make_pair (account.to_account (), response_a));
}
}
Expand All @@ -2330,33 +2335,40 @@ void nano::json_handler::ledger ()
for (auto i (ledger_l.begin ()), n (ledger_l.end ()); i != n && accounts.size () < count; ++i)
{
node.store.account_get (transaction, i->second, info);
nano::account const & account (i->second);
boost::property_tree::ptree response_a;
response_a.put ("frontier", info.head.to_string ());
response_a.put ("open_block", info.open_block.to_string ());
response_a.put ("representative_block", info.rep_block.to_string ());
std::string balance;
(i->first).encode_dec (balance);
response_a.put ("balance", balance);
response_a.put ("modified_timestamp", std::to_string (info.modified));
response_a.put ("block_count", std::to_string (info.block_count));
if (representative)
{
auto block (node.store.block_get (transaction, info.rep_block));
assert (block != nullptr);
response_a.put ("representative", block->representative ().to_account ());
}
if (weight)
{
auto account_weight (node.ledger.weight (transaction, account));
response_a.put ("weight", account_weight.convert_to<std::string> ());
}
if (pending)
if (pending || info.balance.number () >= threshold.number ())
{
auto account_pending (node.ledger.account_pending (transaction, account));
response_a.put ("pending", account_pending.convert_to<std::string> ());
nano::account const & account (i->second);
boost::property_tree::ptree response_a;
if (pending)
{
auto account_pending (node.ledger.account_pending (transaction, account));
if (info.balance.number () + account_pending < threshold.number ())
{
continue;
}
response_a.put ("pending", account_pending.convert_to<std::string> ());
}
response_a.put ("frontier", info.head.to_string ());
response_a.put ("open_block", info.open_block.to_string ());
response_a.put ("representative_block", info.rep_block.to_string ());
std::string balance;
(i->first).encode_dec (balance);
response_a.put ("balance", balance);
response_a.put ("modified_timestamp", std::to_string (info.modified));
response_a.put ("block_count", std::to_string (info.block_count));
if (representative)
{
auto block (node.store.block_get (transaction, info.rep_block));
assert (block != nullptr);
response_a.put ("representative", block->representative ().to_account ());
}
if (weight)
{
auto account_weight (node.ledger.weight (transaction, account));
response_a.put ("weight", account_weight.convert_to<std::string> ());
}
accounts.push_back (std::make_pair (account.to_account (), response_a));
}
accounts.push_back (std::make_pair (account.to_account (), response_a));
}
}
response_l.add_child ("accounts", accounts);
Expand Down Expand Up @@ -3628,6 +3640,7 @@ void nano::json_handler::unchecked_keys ()
void nano::json_handler::unopened ()
{
auto count (count_optional_impl ());
auto threshold (threshold_optional_impl ());
nano::account start (1); // exclude burn account by default
boost::optional<std::string> account_text (request.get_optional<std::string> ("account"));
if (account_text.is_initialized ())
Expand Down Expand Up @@ -3665,7 +3678,10 @@ void nano::json_handler::unopened ()
{
if (current_account_sum > 0)
{
accounts.put (current_account.to_account (), current_account_sum.convert_to<std::string> ());
if (current_account_sum >= threshold.number ())
{
accounts.put (current_account.to_account (), current_account_sum.convert_to<std::string> ());
}
current_account_sum = 0;
}
current_account = account;
Expand All @@ -3675,7 +3691,7 @@ void nano::json_handler::unopened ()
}
}
// last one after iterator reaches end
if (current_account_sum > 0 && accounts.size () < count)
if (accounts.size () < count && current_account_sum > 0 && current_account_sum >= threshold.number ())
{
accounts.put (current_account.to_account (), current_account_sum.convert_to<std::string> ());
}
Expand Down
162 changes: 113 additions & 49 deletions nano/rpc_test/rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4675,7 +4675,10 @@ TEST (rpc, ledger)
system.wallet (0)->insert_adhoc (key.prv);
auto & node1 (*system.nodes[0]);
auto latest (node1.latest (nano::test_genesis_key.pub));
nano::send_block send (latest, key.pub, 100, nano::test_genesis_key.prv, nano::test_genesis_key.pub, node1.work_generate_blocking (latest));
auto genesis_balance (nano::genesis_amount);
auto send_amount (genesis_balance - 100);
genesis_balance -= send_amount;
nano::send_block send (latest, key.pub, genesis_balance, nano::test_genesis_key.prv, nano::test_genesis_key.pub, node1.work_generate_blocking (latest));
node1.process (send);
nano::open_block open (send.hash (), nano::test_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);
Expand All @@ -4689,58 +4692,103 @@ TEST (rpc, ledger)
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "ledger");
request.put ("sorting", "1");
request.put ("sorting", true);
request.put ("count", "1");
test_response response (request, rpc.config.port, system.io_ctx);
system.deadline_set (5s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
for (auto & accounts : response.json.get_child ("accounts"))
{
std::string account_text (accounts.first);
ASSERT_EQ (key.pub.to_account (), account_text);
std::string frontier (accounts.second.get<std::string> ("frontier"));
ASSERT_EQ (open.hash ().to_string (), frontier);
std::string open_block (accounts.second.get<std::string> ("open_block"));
ASSERT_EQ (open.hash ().to_string (), open_block);
std::string representative_block (accounts.second.get<std::string> ("representative_block"));
ASSERT_EQ (open.hash ().to_string (), representative_block);
std::string balance_text (accounts.second.get<std::string> ("balance"));
ASSERT_EQ ("340282366920938463463374607431768211355", balance_text);
std::string modified_timestamp (accounts.second.get<std::string> ("modified_timestamp"));
ASSERT_LT (std::abs ((long)time - stol (modified_timestamp)), 5);
std::string block_count (accounts.second.get<std::string> ("block_count"));
ASSERT_EQ ("1", block_count);
boost::optional<std::string> weight (accounts.second.get_optional<std::string> ("weight"));
ASSERT_FALSE (weight.is_initialized ());
boost::optional<std::string> pending (accounts.second.get_optional<std::string> ("pending"));
ASSERT_FALSE (pending.is_initialized ());
boost::optional<std::string> representative (accounts.second.get_optional<std::string> ("representative"));
ASSERT_FALSE (representative.is_initialized ());
test_response response (request, rpc.config.port, system.io_ctx);
system.deadline_set (5s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
for (auto & account : response.json.get_child ("accounts"))
{
std::string account_text (account.first);
ASSERT_EQ (key.pub.to_account (), account_text);
std::string frontier (account.second.get<std::string> ("frontier"));
ASSERT_EQ (open.hash ().to_string (), frontier);
std::string open_block (account.second.get<std::string> ("open_block"));
ASSERT_EQ (open.hash ().to_string (), open_block);
std::string representative_block (account.second.get<std::string> ("representative_block"));
ASSERT_EQ (open.hash ().to_string (), representative_block);
std::string balance_text (account.second.get<std::string> ("balance"));
ASSERT_EQ (send_amount.convert_to<std::string> (), balance_text);
std::string modified_timestamp (account.second.get<std::string> ("modified_timestamp"));
ASSERT_LT (std::abs ((long)time - stol (modified_timestamp)), 5);
std::string block_count (account.second.get<std::string> ("block_count"));
ASSERT_EQ ("1", block_count);
boost::optional<std::string> weight (account.second.get_optional<std::string> ("weight"));
ASSERT_FALSE (weight.is_initialized ());
boost::optional<std::string> pending (account.second.get_optional<std::string> ("pending"));
ASSERT_FALSE (pending.is_initialized ());
boost::optional<std::string> representative (account.second.get_optional<std::string> ("representative"));
ASSERT_FALSE (representative.is_initialized ());
}
}
// Test for optional values
request.put ("weight", "1");
request.put ("pending", "1");
request.put ("representative", "true");
test_response response2 (request, rpc.config.port, system.io_ctx);
system.deadline_set (5s);
while (response2.status == 0)
request.put ("weight", true);
request.put ("pending", true);
request.put ("representative", true);
{
ASSERT_NO_ERROR (system.poll ());
test_response response (request, rpc.config.port, system.io_ctx);
system.deadline_set (5s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
for (auto & account : response.json.get_child ("accounts"))
{
boost::optional<std::string> weight (account.second.get_optional<std::string> ("weight"));
ASSERT_TRUE (weight.is_initialized ());
ASSERT_EQ ("0", weight.get ());
boost::optional<std::string> pending (account.second.get_optional<std::string> ("pending"));
ASSERT_TRUE (pending.is_initialized ());
ASSERT_EQ ("0", pending.get ());
boost::optional<std::string> representative (account.second.get_optional<std::string> ("representative"));
ASSERT_TRUE (representative.is_initialized ());
ASSERT_EQ (nano::test_genesis_key.pub.to_account (), representative.get ());
}
}
for (auto & accounts : response2.json.get_child ("accounts"))
// Test threshold
request.put ("count", 2);
request.put ("threshold", genesis_balance + 1);
{
boost::optional<std::string> weight (accounts.second.get_optional<std::string> ("weight"));
ASSERT_TRUE (weight.is_initialized ());
ASSERT_EQ ("0", weight.get ());
boost::optional<std::string> pending (accounts.second.get_optional<std::string> ("pending"));
ASSERT_TRUE (pending.is_initialized ());
ASSERT_EQ ("0", pending.get ());
boost::optional<std::string> representative (accounts.second.get_optional<std::string> ("representative"));
ASSERT_TRUE (representative.is_initialized ());
ASSERT_EQ (nano::test_genesis_key.pub.to_account (), representative.get ());
test_response response (request, rpc.config.port, system.io_ctx);
system.deadline_set (5s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
auto & accounts (response.json.get_child ("accounts"));
ASSERT_EQ (1, accounts.size ());
auto account (accounts.begin ());
ASSERT_EQ (key.pub.to_account (), account->first);
std::string balance_text (account->second.get<std::string> ("balance"));
ASSERT_EQ (send_amount.convert_to<std::string> (), balance_text);
}
auto send2_amount (50);
genesis_balance -= send2_amount;
nano::send_block send2 (send.hash (), key.pub, genesis_balance, nano::test_genesis_key.prv, nano::test_genesis_key.pub, node1.work_generate_blocking (send.hash ()));
node1.process (send2);
// When asking for pending, pending amount is taken into account for threshold so the account must show up
request.put ("count", 2);
request.put ("threshold", (send_amount + send2_amount).convert_to<std::string> ());
request.put ("pending", true);
{
test_response response (request, rpc.config.port, system.io_ctx);
system.deadline_set (5s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
auto & accounts (response.json.get_child ("accounts"));
ASSERT_EQ (1, accounts.size ());
auto account (accounts.begin ());
ASSERT_EQ (key.pub.to_account (), account->first);
std::string balance_text (account->second.get<std::string> ("balance"));
ASSERT_EQ (send_amount.convert_to<std::string> (), balance_text);
std::string pending_text (account->second.get<std::string> ("pending"));
ASSERT_EQ (std::to_string (send2_amount), pending_text);
}
}

Expand Down Expand Up @@ -5725,7 +5773,7 @@ TEST (rpc, unopened)
ASSERT_FALSE (genesis.is_zero ());
auto send (system.wallet (0)->send_action (nano::test_genesis_key.pub, account1, 1));
ASSERT_NE (nullptr, send);
auto send2 (system.wallet (0)->send_action (nano::test_genesis_key.pub, account2, 2));
auto send2 (system.wallet (0)->send_action (nano::test_genesis_key.pub, account2, 10));
ASSERT_NE (nullptr, send2);
auto node = system.nodes.front ();
enable_ipc_transport_tcp (node->config.ipc_config.transport_tcp);
Expand All @@ -5748,7 +5796,7 @@ TEST (rpc, unopened)
auto & accounts (response.json.get_child ("accounts"));
ASSERT_EQ (2, accounts.size ());
ASSERT_EQ ("1", accounts.get<std::string> (account1.to_account ()));
ASSERT_EQ ("2", accounts.get<std::string> (account2.to_account ()));
ASSERT_EQ ("10", accounts.get<std::string> (account2.to_account ()));
}
{
// starting at second account should get a single result
Expand All @@ -5764,7 +5812,7 @@ TEST (rpc, unopened)
ASSERT_EQ (200, response.status);
auto & accounts (response.json.get_child ("accounts"));
ASSERT_EQ (1, accounts.size ());
ASSERT_EQ ("2", accounts.get<std::string> (account2.to_account ()));
ASSERT_EQ ("10", accounts.get<std::string> (account2.to_account ()));
}
{
// starting at third account should get no results
Expand Down Expand Up @@ -5797,6 +5845,22 @@ TEST (rpc, unopened)
ASSERT_EQ (1, accounts.size ());
ASSERT_EQ ("1", accounts.get<std::string> (account1.to_account ()));
}
{
// using threshold at 5 should get a single result
boost::property_tree::ptree request;
request.put ("action", "unopened");
request.put ("threshold", 5);
test_response response (request, rpc.config.port, system.io_ctx);
system.deadline_set (5s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_EQ (200, response.status);
auto & accounts (response.json.get_child ("accounts"));
ASSERT_EQ (1, accounts.size ());
ASSERT_EQ ("10", accounts.get<std::string> (account2.to_account ()));
}
}

TEST (rpc, unopened_burn)
Expand Down