This commit is contained in:
Piotr Wójcik 2025-01-07 16:15:27 +01:00
commit f9d7c76a68
4 changed files with 168 additions and 10 deletions

View file

@ -270,18 +270,12 @@ TEST (bootstrap, trace_base)
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.build ();
// std::cerr << "Genesis key: " << nano::dev::genesis_key.pub.to_account () << std::endl;
// std::cerr << "Key: " << key.pub.to_account () << std::endl;
// std::cerr << "Genesis: " << nano::dev::genesis->hash ().to_string () << std::endl;
// std::cerr << "send1: " << send1->hash ().to_string () << std::endl;
// std::cerr << "receive1: " << receive1->hash ().to_string () << std::endl;
auto & node1 = *system.add_node ();
// std::cerr << "--------------- Start ---------------\n";
ASSERT_EQ (nano::block_status::progress, node0.process (send1));
ASSERT_EQ (nano::block_status::progress, node0.process (receive1));
ASSERT_EQ (node1.ledger.any.receivable_end (), node1.ledger.any.receivable_upper_bound (node1.ledger.tx_begin_read (), key.pub, 0));
// std::cerr << "node0: " << node0.network.endpoint () << std::endl;
// std::cerr << "node1: " << node1.network.endpoint () << std::endl;
ASSERT_TIMELY (10s, node1.block (receive1->hash ()) != nullptr);
}
@ -573,4 +567,48 @@ TEST (bootstrap, frontier_scan_cannot_prioritize)
}));
}
// TODO: Test bootstrap.reset ()
/*
* Tests that bootstrap.reset() properly recovers when called during an ongoing bootstrap
* This mimics node restart behaviour so this also ensures that the bootstrap is able to recover from a node restart
*/
TEST (bootstrap, reset)
{
nano::test::system system;
// Test configuration
int const chain_count = 10;
int const blocks_per_chain = 5;
nano::node_config config;
// Disable election activation
config.backlog_scan.enable = false;
config.priority_scheduler.enable = false;
config.optimistic_scheduler.enable = false;
config.hinted_scheduler.enable = false;
// Add request limits to slow down bootstrap
config.bootstrap.rate_limit = 30;
// Start server node
auto & node_server = *system.add_node (config);
// Create multiple chains of blocks
auto chains = nano::test::setup_chains (system, node_server, chain_count, blocks_per_chain);
int const total_blocks = node_server.block_count ();
int const halfway_blocks = total_blocks / 2;
// Start client node and begin bootstrap
auto & node_client = *system.add_node (config);
ASSERT_LE (node_client.block_count (), halfway_blocks); // Should not be synced yet
// Wait until bootstrap has started and processed some blocks but not all
// Target approximately halfway through
ASSERT_TIMELY (15s, node_client.block_count () >= halfway_blocks);
ASSERT_LT (node_client.block_count (), total_blocks);
// Reset bootstrap halfway through the process
node_client.bootstrap.reset ();
// Bootstrap should automatically restart and eventually sync all blocks
ASSERT_TIMELY_EQ (30s, node_client.block_count (), total_blocks);
}

View file

@ -1105,6 +1105,16 @@ void nano::node::bootstrap_block (const nano::block_hash & hash)
}
}
uint64_t nano::node::block_count () const
{
return ledger.block_count ();
}
uint64_t nano::node::cemented_count () const
{
return ledger.cemented_count ();
}
nano::account nano::node::get_node_id () const
{
return node_id.pub;

View file

@ -77,11 +77,13 @@ public:
void add_initial_peers ();
void start_election (std::shared_ptr<nano::block> const & block);
bool block_confirmed (nano::block_hash const &);
// This function may spuriously return false after returning true until the database transaction is refreshed
bool block_confirmed_or_being_confirmed (nano::secure::transaction const &, nano::block_hash const &);
bool block_confirmed_or_being_confirmed (nano::block_hash const &);
uint64_t block_count () const;
uint64_t cemented_count () const;
void do_rpc_callback (boost::asio::ip::tcp::resolver::iterator i_a, std::string const &, uint16_t, std::shared_ptr<std::string> const &, std::shared_ptr<std::string> const &, std::shared_ptr<boost::asio::ip::tcp::resolver> const &);
bool online () const;
bool init_error () const;

View file

@ -6876,3 +6876,111 @@ TEST (rpc, election_statistics)
ASSERT_LT (response.get<int> ("max_election_age"), 5000);
ASSERT_LT (response.get<int> ("average_election_age"), 5000);
}
TEST (rpc, bootstrap_priorities)
{
nano::test::system system;
// Test configuration
int const chain_count = 5;
int const blocks_per_chain = 2;
nano::node_config config;
config.bootstrap.rate_limit = 10; // Add request limits to slow down bootstrap
// Start server node
auto & node_server = *system.add_node (config);
// Create multiple chains of blocks
auto chains = nano::test::setup_chains (system, node_server, chain_count, blocks_per_chain);
int const total_blocks = node_server.block_count ();
int const halfway_blocks = total_blocks / 2;
// Start client node to observe bootstrap
auto node = add_ipc_enabled_node (system);
auto const rpc_ctx = add_rpc (system, node);
// Wait until bootstrap has started and processed some blocks but not all
// Target approximately halfway through
ASSERT_TIMELY (15s, node->block_count () >= halfway_blocks);
boost::property_tree::ptree request;
request.put ("action", "bootstrap_priorities");
auto response = wait_response (system, rpc_ctx, request);
ASSERT_TRUE (response.get_child_optional ("priorities"));
ASSERT_TRUE (response.get_child_optional ("blocking"));
ASSERT_FALSE (response.get_child_optional ("priorities").value ().empty ());
}
TEST (rpc, bootstrap_reset)
{
nano::test::system system;
// Test configuration
int const chain_count = 5;
int const blocks_per_chain = 2;
nano::node_config config;
config.bootstrap.rate_limit = 10; // Add request limits to slow down bootstrap
// Start server node
auto & node_server = *system.add_node (config);
// Create multiple chains of blocks
auto chains = nano::test::setup_chains (system, node_server, chain_count, blocks_per_chain);
int const total_blocks = node_server.block_count ();
int const halfway_blocks = total_blocks / 2;
// Start client node to observe bootstrap
auto node = add_ipc_enabled_node (system);
auto const rpc_ctx = add_rpc (system, node);
// Wait until bootstrap has started and processed some blocks but not all
// Target approximately halfway through
ASSERT_TIMELY (15s, node->block_count () >= halfway_blocks);
boost::property_tree::ptree request;
request.put ("action", "bootstrap_reset");
auto response = wait_response (system, rpc_ctx, request);
ASSERT_TRUE (response.get<std::string> ("success").empty ());
}
TEST (rpc, bootstrap_status)
{
nano::test::system system;
// Test configuration
int const chain_count = 5;
int const blocks_per_chain = 2;
nano::node_config config;
config.bootstrap.rate_limit = 10; // Add request limits to slow down bootstrap
// Start server node
auto & node_server = *system.add_node (config);
// Create multiple chains of blocks
auto chains = nano::test::setup_chains (system, node_server, chain_count, blocks_per_chain);
int const total_blocks = node_server.block_count ();
int const halfway_blocks = total_blocks / 2;
// Start client node to observe bootstrap
auto node = add_ipc_enabled_node (system);
auto const rpc_ctx = add_rpc (system, node);
// Wait until bootstrap has started and processed some blocks but not all
// Target approximately halfway through
ASSERT_TIMELY (15s, node->block_count () >= halfway_blocks);
boost::property_tree::ptree request;
request.put ("action", "bootstrap_status");
auto response = wait_response (system, rpc_ctx, request);
ASSERT_GT (response.get<int> ("priorities"), 0);
ASSERT_EQ (response.get<int> ("blocking"), 0);
}