diff --git a/nano/core_test/block_store.cpp b/nano/core_test/block_store.cpp index 525969f43..0bdb5a880 100644 --- a/nano/core_test/block_store.cpp +++ b/nano/core_test/block_store.cpp @@ -758,6 +758,20 @@ TEST (block_store, account_count) ASSERT_EQ (1, store.account_count (transaction)); } +TEST (block_store, cemented_count) +{ + nano::logger_mt logger; + bool init (false); + nano::mdb_store store (init, logger, nano::unique_path ()); + ASSERT_TRUE (!init); + auto transaction (store.tx_begin_write ()); + ASSERT_EQ (0, store.cemented_count (transaction)); + nano::genesis genesis; + auto hash (genesis.hash ()); + store.initialize (transaction, genesis); + ASSERT_EQ (1, store.cemented_count (transaction)); +} + TEST (block_store, sequence_increment) { nano::logger_mt logger; diff --git a/nano/nano_node/entry.cpp b/nano/nano_node/entry.cpp index 832713512..841d15707 100644 --- a/nano/nano_node/entry.cpp +++ b/nano/nano_node/entry.cpp @@ -1033,14 +1033,7 @@ int main (int argc, char * const * argv) { nano::inactive_node node (data_path); auto transaction (node.node->store.tx_begin_read ()); - - uint64_t sum = 0; - for (auto i (node.node->store.latest_begin (transaction)), n (node.node->store.latest_end ()); i != n; ++i) - { - nano::account_info const & info (i->second); - sum += info.confirmation_height; - } - std::cout << "Total cemented block count: " << sum << std::endl; + std::cout << "Total cemented block count: " << node.node->store.cemented_count (transaction) << std::endl; } else if (vm.count ("debug_sys_logging")) { diff --git a/nano/node/json_handler.cpp b/nano/node/json_handler.cpp index 80bf8200d..8a758770d 100644 --- a/nano/node/json_handler.cpp +++ b/nano/node/json_handler.cpp @@ -1161,6 +1161,13 @@ void nano::json_handler::block_count () auto transaction (node.store.tx_begin_read ()); response_l.put ("count", std::to_string (node.store.block_count (transaction).sum ())); response_l.put ("unchecked", std::to_string (node.store.unchecked_count (transaction))); + + const auto include_cemented = request.get ("include_cemented", false); + if (include_cemented) + { + response_l.put ("cemented", std::to_string (node.store.cemented_count (transaction))); + } + response_errors (); } diff --git a/nano/node/lmdb.cpp b/nano/node/lmdb.cpp index f547f22f5..b8a719a9b 100644 --- a/nano/node/lmdb.cpp +++ b/nano/node/lmdb.cpp @@ -2028,6 +2028,17 @@ void nano::mdb_store::confirmation_height_clear (nano::transaction const & trans } } +uint64_t nano::mdb_store::cemented_count (nano::transaction const & transaction_a) +{ + uint64_t sum = 0; + for (auto i (latest_begin (transaction_a)), n (latest_end ()); i != n; ++i) + { + nano::account_info const & info (i->second); + sum += info.confirmation_height; + } + return sum; +} + void nano::mdb_store::pending_put (nano::transaction const & transaction_a, nano::pending_key const & key_a, nano::pending_info const & pending_a) { auto status (mdb_put (env.tx (transaction_a), get_pending_db (pending_a.epoch), nano::mdb_val (key_a), nano::mdb_val (pending_a), 0)); diff --git a/nano/node/lmdb.hpp b/nano/node/lmdb.hpp index 5fd5db5b5..962e7a0da 100644 --- a/nano/node/lmdb.hpp +++ b/nano/node/lmdb.hpp @@ -211,6 +211,7 @@ public: size_t account_count (nano::transaction const &) override; void confirmation_height_clear (nano::transaction const &, nano::account const & account, nano::account_info const & account_info) override; void confirmation_height_clear (nano::transaction const &) override; + uint64_t cemented_count (nano::transaction const &) override; nano::store_iterator latest_v0_begin (nano::transaction const &, nano::account const &) override; nano::store_iterator latest_v0_begin (nano::transaction const &) override; nano::store_iterator latest_v0_end () override; diff --git a/nano/node/testing.cpp b/nano/node/testing.cpp index c7126fcd6..41e18224e 100644 --- a/nano/node/testing.cpp +++ b/nano/node/testing.cpp @@ -115,7 +115,7 @@ system () for (uint16_t i (0); i < count_a; ++i) { nano::node_config config (port_a + i, logging); - nano::system::add_node (config, nano::node_flags (), type_a); + add_node (config, nano::node_flags (), type_a); } } diff --git a/nano/rpc/rpc_handler.cpp b/nano/rpc/rpc_handler.cpp index 7a71795b8..75fc44fd9 100644 --- a/nano/rpc/rpc_handler.cpp +++ b/nano/rpc/rpc_handler.cpp @@ -83,7 +83,17 @@ void nano::rpc_handler::process_request () else if (action == "process") { auto force = request.get_optional ("force"); - if (force && !rpc_config.enable_control) + if (force.is_initialized () && *force && !rpc_config.enable_control) + { + json_error_response (response, rpc_control_disabled_ec.message ()); + error = true; + } + } + else if (action == "block_count") + { + // Cemented blocks can take a while to generate so require control + auto include_cemented = request.get_optional ("include_cemented"); + if (include_cemented.is_initialized () && *include_cemented && !rpc_config.enable_control) { json_error_response (response, rpc_control_disabled_ec.message ()); error = true; diff --git a/nano/rpc/rpc_handler.hpp b/nano/rpc/rpc_handler.hpp index 6d8276d8a..226f4fce5 100644 --- a/nano/rpc/rpc_handler.hpp +++ b/nano/rpc/rpc_handler.hpp @@ -4,6 +4,7 @@ #include #include +#include namespace nano { diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index f5ccf2a76..2eaf38366 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -2687,26 +2687,71 @@ TEST (rpc, work_peer_many) TEST (rpc, block_count) { - nano::system system (24000, 1); - auto & node1 (*system.nodes[0]); - enable_ipc_transport_tcp (node1.config.ipc_config.transport_tcp); - nano::node_rpc_config node_rpc_config; - nano::ipc::ipc_server ipc_server (node1, node_rpc_config); - nano::rpc_config rpc_config (true); - 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 (); - boost::property_tree::ptree request1; - request1.put ("action", "block_count"); - test_response response1 (request1, rpc.config.port, system.io_ctx); - system.deadline_set (5s); - while (response1.status == 0) { - ASSERT_NO_ERROR (system.poll ()); + nano::system system (24000, 1); + auto & node1 (*system.nodes[0]); + enable_ipc_transport_tcp (node1.config.ipc_config.transport_tcp); + nano::node_rpc_config node_rpc_config; + nano::ipc::ipc_server ipc_server (node1, node_rpc_config); + nano::rpc_config rpc_config (true); + 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 (); + boost::property_tree::ptree request1; + request1.put ("action", "block_count"); + { + test_response response1 (request1, rpc.config.port, system.io_ctx); + system.deadline_set (5s); + while (response1.status == 0) + { + ASSERT_NO_ERROR (system.poll ()); + } + ASSERT_EQ (200, response1.status); + ASSERT_EQ ("1", response1.json.get ("count")); + ASSERT_EQ ("0", response1.json.get ("unchecked")); + { + ASSERT_FALSE (response1.json.get_optional ("cemented").is_initialized ()); + } + } + request1.put ("include_cemented", "true"); + test_response response1 (request1, rpc.config.port, system.io_ctx); + system.deadline_set (5s); + while (response1.status == 0) + { + ASSERT_NO_ERROR (system.poll ()); + } + ASSERT_EQ (200, response1.status); + ASSERT_EQ ("1", response1.json.get ("count")); + ASSERT_EQ ("0", response1.json.get ("unchecked")); + ASSERT_EQ ("1", response1.json.get ("cemented")); + } + + // Should not be able to get the cemented count when enable_control is false. + { + nano::system system (24000, 1); + auto & node1 (*system.nodes[0]); + enable_ipc_transport_tcp (node1.config.ipc_config.transport_tcp); + nano::node_rpc_config node_rpc_config; + nano::ipc::ipc_server ipc_server (node1, node_rpc_config); + nano::rpc_config rpc_config (false); + 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 (); + boost::property_tree::ptree request1; + request1.put ("action", "block_count"); + request1.put ("include_cemented", "true"); + { + test_response response1 (request1, rpc.config.port, system.io_ctx); + system.deadline_set (5s); + while (response1.status == 0) + { + ASSERT_NO_ERROR (system.poll ()); + } + ASSERT_EQ (200, response1.status); + std::error_code ec (nano::error_rpc::rpc_control_disabled); + ASSERT_EQ (response1.json.get ("error"), ec.message ()); + } } - ASSERT_EQ (200, response1.status); - ASSERT_EQ ("1", response1.json.get ("count")); - ASSERT_EQ ("0", response1.json.get ("unchecked")); } TEST (rpc, frontier_count) diff --git a/nano/secure/blockstore.hpp b/nano/secure/blockstore.hpp index 51c41846b..6eda74282 100644 --- a/nano/secure/blockstore.hpp +++ b/nano/secure/blockstore.hpp @@ -281,6 +281,7 @@ public: virtual size_t account_count (nano::transaction const &) = 0; virtual void confirmation_height_clear (nano::transaction const &, nano::account const & account, nano::account_info const & account_info) = 0; virtual void confirmation_height_clear (nano::transaction const &) = 0; + virtual uint64_t cemented_count (nano::transaction const &) = 0; virtual nano::store_iterator latest_v0_begin (nano::transaction const &, nano::account const &) = 0; virtual nano::store_iterator latest_v0_begin (nano::transaction const &) = 0; virtual nano::store_iterator latest_v0_end () = 0;