From db332d57208df4510bf2787e035498236c8a4f36 Mon Sep 17 00:00:00 2001 From: Cathal Tummon Date: Sun, 21 Oct 2018 23:46:37 +0100 Subject: [PATCH 1/7] Add accounts filter to accounts_history rpc call. #1110 Add test for account_history account filter option. Remove unnecessary return Add seperate account_history test. --- nano/core_test/rpc.cpp | 85 ++++++++++++++++++++++++++++++++++++++++++ nano/node/rpc.cpp | 67 ++++++++++++++++++++++++++++++--- nano/node/rpc.hpp | 1 - 3 files changed, 146 insertions(+), 7 deletions(-) diff --git a/nano/core_test/rpc.cpp b/nano/core_test/rpc.cpp index 8c28e500d3..09ff9cfaaa 100644 --- a/nano/core_test/rpc.cpp +++ b/nano/core_test/rpc.cpp @@ -1126,6 +1126,91 @@ TEST (rpc, history) ASSERT_EQ (genesis.hash ().to_string (), std::get<3> (history_l[4])); } +TEST (rpc, account_history) +{ + nano::system system (24000, 1); + system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv); + auto change (system.wallet (0)->change_action (nano::test_genesis_key.pub, nano::test_genesis_key.pub)); + ASSERT_NE (nullptr, change); + auto send (system.wallet (0)->send_action (nano::test_genesis_key.pub, nano::test_genesis_key.pub, system.nodes[0]->config.receive_minimum.number ())); + ASSERT_NE (nullptr, send); + auto receive (system.wallet (0)->receive_action (*send, nano::test_genesis_key.pub, system.nodes[0]->config.receive_minimum.number ())); + ASSERT_NE (nullptr, receive); + auto node0 (system.nodes[0]); + nano::genesis genesis; + nano::state_block usend (nano::genesis_account, node0->latest (nano::genesis_account), nano::genesis_account, nano::genesis_amount - nano::Gxrb_ratio, nano::genesis_account, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0); + nano::state_block ureceive (nano::genesis_account, usend.hash (), nano::genesis_account, nano::genesis_amount, usend.hash (), nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0); + nano::state_block uchange (nano::genesis_account, ureceive.hash (), nano::keypair ().pub, nano::genesis_amount, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0); + { + auto transaction (node0->wallets.tx_begin (true)); + ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, usend).code); + ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, ureceive).code); + ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, uchange).code); + } + nano::rpc rpc (system.service, *node0, nano::rpc_config (true)); + rpc.start (); + boost::property_tree::ptree request; + request.put ("action", "account_history"); + request.put ("account", nano::genesis_account.to_account ()); + request.put ("count", 100); + test_response response (request, rpc, system.service); + while (response.status == 0) + { + system.poll (); + } + ASSERT_EQ (200, response.status); + std::vector> history_l; + auto & history_node (response.json.get_child ("history")); + for (auto i (history_node.begin ()), n (history_node.end ()); i != n; ++i) + { + history_l.push_back (std::make_tuple (i->second.get ("type"), i->second.get ("account"), i->second.get ("amount"), i->second.get ("hash"))); + } + ASSERT_EQ (5, history_l.size ()); + ASSERT_EQ ("receive", std::get<0> (history_l[0])); + ASSERT_EQ (ureceive.hash ().to_string (), std::get<3> (history_l[0])); + ASSERT_EQ (nano::test_genesis_key.pub.to_account (), std::get<1> (history_l[0])); + ASSERT_EQ (nano::Gxrb_ratio.convert_to (), std::get<2> (history_l[0])); + ASSERT_EQ (5, history_l.size ()); + ASSERT_EQ ("send", std::get<0> (history_l[1])); + ASSERT_EQ (usend.hash ().to_string (), std::get<3> (history_l[1])); + ASSERT_EQ (nano::test_genesis_key.pub.to_account (), std::get<1> (history_l[1])); + ASSERT_EQ (nano::Gxrb_ratio.convert_to (), std::get<2> (history_l[1])); + ASSERT_EQ ("receive", std::get<0> (history_l[2])); + ASSERT_EQ (nano::test_genesis_key.pub.to_account (), std::get<1> (history_l[2])); + ASSERT_EQ (system.nodes[0]->config.receive_minimum.to_string_dec (), std::get<2> (history_l[2])); + ASSERT_EQ (receive->hash ().to_string (), std::get<3> (history_l[2])); + ASSERT_EQ ("send", std::get<0> (history_l[3])); + ASSERT_EQ (nano::test_genesis_key.pub.to_account (), std::get<1> (history_l[3])); + ASSERT_EQ (system.nodes[0]->config.receive_minimum.to_string_dec (), std::get<2> (history_l[3])); + ASSERT_EQ (send->hash ().to_string (), std::get<3> (history_l[3])); + ASSERT_EQ ("receive", std::get<0> (history_l[4])); + ASSERT_EQ (nano::test_genesis_key.pub.to_account (), std::get<1> (history_l[4])); + ASSERT_EQ (nano::genesis_amount.convert_to (), std::get<2> (history_l[4])); + ASSERT_EQ (genesis.hash ().to_string (), std::get<3> (history_l[4])); + //Tests filtering + auto account2 (system.wallet (0)->deterministic_insert ()); + auto send2 (system.wallet (0)->send_action (nano::test_genesis_key.pub, account2, system.nodes[0]->config.receive_minimum.number ())); + ASSERT_NE (nullptr, send2); + auto receive2 (system.wallet (0)->receive_action (static_cast (*send2), account2, system.nodes[0]->config.receive_minimum.number ())); + ASSERT_NE (nullptr, receive2); + boost::property_tree::ptree request2; + request2.put ("action", "account_history"); + request2.put ("account", nano::test_genesis_key.pub.to_account ()); + boost::property_tree::ptree other_account; + other_account.put ("", account2.to_account ()); + boost::property_tree::ptree filtered_accounts; + filtered_accounts.push_back (std::make_pair ("", other_account)); + request2.add_child ("account_filter", filtered_accounts); + request2.put ("count", 100); + test_response response2 (request2, rpc, system.service); + while (response2.status == 0) + { + system.poll (); + } + auto history_node2 (response2.json.get_child ("history")); + ASSERT_EQ (history_node2.size (), 1); +} + TEST (rpc, history_count) { nano::system system (24000, 1); diff --git a/nano/node/rpc.cpp b/nano/node/rpc.cpp index 32d9dc2b27..7db6ae7c87 100644 --- a/nano/node/rpc.cpp +++ b/nano/node/rpc.cpp @@ -1739,17 +1739,22 @@ namespace class history_visitor : public nano::block_visitor { public: - history_visitor (nano::rpc_handler & handler_a, bool raw_a, nano::transaction & transaction_a, boost::property_tree::ptree & tree_a, nano::block_hash const & hash_a) : + history_visitor (nano::rpc_handler & handler_a, bool raw_a, nano::transaction & transaction_a, boost::property_tree::ptree & tree_a, nano::block_hash const & hash_a, std::vector & accounts_filter_a) : handler (handler_a), raw (raw_a), transaction (transaction_a), tree (tree_a), - hash (hash_a) + hash (hash_a), + accounts_filter (accounts_filter_a) { } virtual ~history_visitor () = default; void send_block (nano::send_block const & block_a) { + if (should_ignore_account (block_a.hashables.destination)) + { + return; + } tree.put ("type", "send"); auto account (block_a.hashables.destination.to_account ()); tree.put ("account", account); @@ -1764,6 +1769,10 @@ class history_visitor : public nano::block_visitor } void receive_block (nano::receive_block const & block_a) { + if (should_ignore_account (block_a.hashables.source)) + { + return; + } tree.put ("type", "receive"); auto account (handler.node.ledger.account (transaction, block_a.hashables.source).to_account ()); tree.put ("account", account); @@ -1777,6 +1786,10 @@ class history_visitor : public nano::block_visitor } void open_block (nano::open_block const & block_a) { + if (should_ignore_account (block_a.hashables.source)) + { + return; + } if (raw) { tree.put ("type", "open"); @@ -1802,7 +1815,7 @@ class history_visitor : public nano::block_visitor } void change_block (nano::change_block const & block_a) { - if (raw) + if (raw && accounts_filter.empty ()) { tree.put ("type", "change"); tree.put ("representative", block_a.hashables.representative.to_account ()); @@ -1823,6 +1836,11 @@ class history_visitor : public nano::block_visitor auto previous_balance (handler.node.ledger.balance (transaction, block_a.hashables.previous)); if (balance < previous_balance) { + if (should_ignore_account (block_a.hashables.link)) + { + tree.clear (); + return; + } if (raw) { tree.put ("subtype", "send"); @@ -1838,14 +1856,14 @@ class history_visitor : public nano::block_visitor { if (block_a.hashables.link.is_zero ()) { - if (raw) + if (raw && accounts_filter.empty ()) { tree.put ("subtype", "change"); } } else if (balance == previous_balance && !handler.node.ledger.epoch_link.is_zero () && handler.node.ledger.is_epoch_link (block_a.hashables.link)) { - if (raw) + if (raw && accounts_filter.empty ()) { tree.put ("subtype", "epoch"); tree.put ("account", handler.node.ledger.epoch_signer.to_account ()); @@ -1853,6 +1871,11 @@ class history_visitor : public nano::block_visitor } else { + if (should_ignore_account (block_a.hashables.link)) + { + tree.clear (); + return; + } if (raw) { tree.put ("subtype", "receive"); @@ -1866,16 +1889,48 @@ class history_visitor : public nano::block_visitor } } } + bool should_ignore_account (nano::public_key const & account) + { + bool ignore (false); + if (!accounts_filter.empty ()) + { + if (std::find (accounts_filter.begin (), accounts_filter.end (), account) == accounts_filter.end ()) + { + ignore = true; + } + } + return ignore; + } nano::rpc_handler & handler; bool raw; nano::transaction & transaction; boost::property_tree::ptree & tree; nano::block_hash const & hash; + std::vector & accounts_filter; }; } void nano::rpc_handler::account_history () { + std::vector accounts_to_filter; + const auto accounts_filter_node = request.get_child_optional ("account_filter"); + if (accounts_filter_node.is_initialized ()) + { + for (auto & a : (*accounts_filter_node)) + { + nano::public_key account; + auto error (account.decode_account (a.second.get (""))); + if (!error) + { + accounts_to_filter.push_back (account); + } + else + { + ec = nano::error_common::bad_account_number; + break; + } + } + } nano::account account; bool output_raw (request.get_optional ("raw") == true); nano::block_hash hash; @@ -1924,7 +1979,7 @@ void nano::rpc_handler::account_history () else { boost::property_tree::ptree entry; - history_visitor visitor (*this, output_raw, transaction, entry, hash); + history_visitor visitor (*this, output_raw, transaction, entry, hash, accounts_to_filter); block->visit (visitor); if (!entry.empty ()) { diff --git a/nano/node/rpc.hpp b/nano/node/rpc.hpp index e61f61cb66..7f6b533a1e 100644 --- a/nano/node/rpc.hpp +++ b/nano/node/rpc.hpp @@ -169,7 +169,6 @@ class rpc_handler : public std::enable_shared_from_this void delegators_count (); void deterministic_key (); void frontiers (); - void history (); void keepalive (); void key_create (); void key_expand (); From 044ccb5a2de7f317074f2cdb31ec2b21e67d9f14 Mon Sep 17 00:00:00 2001 From: Cathal Tummon Date: Wed, 6 Feb 2019 20:24:22 +0000 Subject: [PATCH 2/7] Add default param for history visitor --- nano/node/rpc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nano/node/rpc.cpp b/nano/node/rpc.cpp index 7db6ae7c87..fe7fa2bd4c 100644 --- a/nano/node/rpc.cpp +++ b/nano/node/rpc.cpp @@ -1739,7 +1739,7 @@ namespace class history_visitor : public nano::block_visitor { public: - history_visitor (nano::rpc_handler & handler_a, bool raw_a, nano::transaction & transaction_a, boost::property_tree::ptree & tree_a, nano::block_hash const & hash_a, std::vector & accounts_filter_a) : + history_visitor(nano::rpc_handler & handler_a, bool raw_a, nano::transaction & transaction_a, boost::property_tree::ptree & tree_a, nano::block_hash const & hash_a, std::vector & accounts_filter_a = {}) : handler (handler_a), raw (raw_a), transaction (transaction_a), From f7a74130040965ef1cf1d40a56e4ee5096460793 Mon Sep 17 00:00:00 2001 From: Cathal Tummon Date: Thu, 7 Feb 2019 09:34:20 +0000 Subject: [PATCH 3/7] Add const --- nano/node/rpc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nano/node/rpc.cpp b/nano/node/rpc.cpp index fe7fa2bd4c..f07b86fd2d 100644 --- a/nano/node/rpc.cpp +++ b/nano/node/rpc.cpp @@ -1739,7 +1739,7 @@ namespace class history_visitor : public nano::block_visitor { public: - history_visitor(nano::rpc_handler & handler_a, bool raw_a, nano::transaction & transaction_a, boost::property_tree::ptree & tree_a, nano::block_hash const & hash_a, std::vector & accounts_filter_a = {}) : + history_visitor(nano::rpc_handler & handler_a, bool raw_a, nano::transaction & transaction_a, boost::property_tree::ptree & tree_a, nano::block_hash const & hash_a, std::vector const & accounts_filter_a = {}) : handler (handler_a), raw (raw_a), transaction (transaction_a), @@ -1906,7 +1906,7 @@ class history_visitor : public nano::block_visitor nano::transaction & transaction; boost::property_tree::ptree & tree; nano::block_hash const & hash; - std::vector & accounts_filter; + std::vector const & accounts_filter; }; } From de927012383b9c6210a29d03737ccb854fc58191 Mon Sep 17 00:00:00 2001 From: Cathal Tummon Date: Wed, 13 Feb 2019 22:19:27 +0000 Subject: [PATCH 4/7] Fix build --- nano/core_test/rpc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nano/core_test/rpc.cpp b/nano/core_test/rpc.cpp index 09ff9cfaaa..8358b6dee1 100644 --- a/nano/core_test/rpc.cpp +++ b/nano/core_test/rpc.cpp @@ -1147,13 +1147,13 @@ TEST (rpc, account_history) ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, ureceive).code); ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, uchange).code); } - nano::rpc rpc (system.service, *node0, nano::rpc_config (true)); + nano::rpc rpc(system.io_ctx, *node0, nano::rpc_config(true)); rpc.start (); boost::property_tree::ptree request; request.put ("action", "account_history"); request.put ("account", nano::genesis_account.to_account ()); request.put ("count", 100); - test_response response (request, rpc, system.service); + test_response response (request, rpc, system.io_ctx); while (response.status == 0) { system.poll (); @@ -1202,7 +1202,7 @@ TEST (rpc, account_history) filtered_accounts.push_back (std::make_pair ("", other_account)); request2.add_child ("account_filter", filtered_accounts); request2.put ("count", 100); - test_response response2 (request2, rpc, system.service); + test_response response2 (request2, rpc, system.io_ctx); while (response2.status == 0) { system.poll (); From 6e388e57ac41b84cee2a771ed79dca567896f18d Mon Sep 17 00:00:00 2001 From: Cathal Tummon Date: Sat, 16 Feb 2019 20:38:03 +0000 Subject: [PATCH 5/7] Update test. --- nano/core_test/rpc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nano/core_test/rpc.cpp b/nano/core_test/rpc.cpp index 8358b6dee1..a614375cce 100644 --- a/nano/core_test/rpc.cpp +++ b/nano/core_test/rpc.cpp @@ -1142,7 +1142,7 @@ TEST (rpc, account_history) nano::state_block ureceive (nano::genesis_account, usend.hash (), nano::genesis_account, nano::genesis_amount, usend.hash (), nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0); nano::state_block uchange (nano::genesis_account, ureceive.hash (), nano::keypair ().pub, nano::genesis_amount, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0); { - auto transaction (node0->wallets.tx_begin (true)); + auto transaction (node0->store.tx_begin (true)); ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, usend).code); ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, ureceive).code); ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, uchange).code); @@ -1156,7 +1156,7 @@ TEST (rpc, account_history) test_response response (request, rpc, system.io_ctx); while (response.status == 0) { - system.poll (); + ASSERT_NO_ERROR(system.poll()); } ASSERT_EQ (200, response.status); std::vector> history_l; From dd447d717f93b552353f8b6674f0d2b4c6bdeb37 Mon Sep 17 00:00:00 2001 From: Cathal Tummon Date: Sun, 17 Feb 2019 11:24:18 +0000 Subject: [PATCH 6/7] Formatting --- nano/core_test/rpc.cpp | 4 ++-- nano/node/rpc.cpp | 2 +- nano/node/rpc_secure.cpp | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/nano/core_test/rpc.cpp b/nano/core_test/rpc.cpp index a614375cce..d3647479f2 100644 --- a/nano/core_test/rpc.cpp +++ b/nano/core_test/rpc.cpp @@ -1147,7 +1147,7 @@ TEST (rpc, account_history) ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, ureceive).code); ASSERT_EQ (nano::process_result::progress, node0->ledger.process (transaction, uchange).code); } - nano::rpc rpc(system.io_ctx, *node0, nano::rpc_config(true)); + nano::rpc rpc (system.io_ctx, *node0, nano::rpc_config (true)); rpc.start (); boost::property_tree::ptree request; request.put ("action", "account_history"); @@ -1156,7 +1156,7 @@ TEST (rpc, account_history) test_response response (request, rpc, system.io_ctx); while (response.status == 0) { - ASSERT_NO_ERROR(system.poll()); + ASSERT_NO_ERROR (system.poll ()); } ASSERT_EQ (200, response.status); std::vector> history_l; diff --git a/nano/node/rpc.cpp b/nano/node/rpc.cpp index f07b86fd2d..73dc1ec92a 100644 --- a/nano/node/rpc.cpp +++ b/nano/node/rpc.cpp @@ -1739,7 +1739,7 @@ namespace class history_visitor : public nano::block_visitor { public: - history_visitor(nano::rpc_handler & handler_a, bool raw_a, nano::transaction & transaction_a, boost::property_tree::ptree & tree_a, nano::block_hash const & hash_a, std::vector const & accounts_filter_a = {}) : + history_visitor (nano::rpc_handler & handler_a, bool raw_a, nano::transaction & transaction_a, boost::property_tree::ptree & tree_a, nano::block_hash const & hash_a, std::vector const & accounts_filter_a = {}) : handler (handler_a), raw (raw_a), transaction (transaction_a), diff --git a/nano/node/rpc_secure.cpp b/nano/node/rpc_secure.cpp index 8999a38b30..22880526e9 100644 --- a/nano/node/rpc_secure.cpp +++ b/nano/node/rpc_secure.cpp @@ -191,14 +191,12 @@ void nano::rpc_connection_secure::read () this_l->res.set (boost::beast::http::field::allow, "POST, OPTIONS"); this_l->res.prepare_payload (); boost::beast::http::async_write (this_l->stream, this_l->res, [this_l](boost::system::error_code const & ec, size_t bytes_transferred) { - // Perform the SSL shutdown this_l->stream.async_shutdown ( std::bind ( &rai::rpc_connection_secure::on_shutdown, this_l, std::placeholders::_1)); - }); break; } From 6155543a53b3467fe4ba7cc5567a368db772b5c2 Mon Sep 17 00:00:00 2001 From: Cathal Tummon Date: Wed, 13 Mar 2019 19:38:04 +0000 Subject: [PATCH 7/7] Formatting --- nano/node/rpc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nano/node/rpc.cpp b/nano/node/rpc.cpp index 3497a1cf52..dff51eeedd 100644 --- a/nano/node/rpc.cpp +++ b/nano/node/rpc.cpp @@ -1964,7 +1964,7 @@ class history_visitor : public nano::block_visitor boost::property_tree::ptree & tree; nano::block_hash const & hash; nano::network_params network_params; - std::vector const & accounts_filter; + std::vector const & accounts_filter; }; }