Skip to content

Commit

Permalink
Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
pwojcikdev committed Sep 30, 2024
1 parent 8bec4ee commit ed4c175
Show file tree
Hide file tree
Showing 3 changed files with 303 additions and 0 deletions.
289 changes: 289 additions & 0 deletions nano/core_test/bootstrap_ascending.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <nano/node/make_store.hpp>
#include <nano/secure/ledger.hpp>
#include <nano/secure/ledger_set_any.hpp>
#include <nano/test_common/chains.hpp>
#include <nano/test_common/system.hpp>
#include <nano/test_common/testutil.hpp>

Expand Down Expand Up @@ -266,3 +267,291 @@ TEST (bootstrap_ascending, trace_base)
// std::cerr << "node1: " << node1.network.endpoint () << std::endl;
ASSERT_TIMELY (10s, node1.block (receive1->hash ()) != nullptr);
}

/*
* Tests that bootstrap will prioritize existing accounts with outdated frontiers
*/
TEST (bootstrap_ascending, frontier_scan)
{
nano::test::system system;

nano::node_flags flags;
flags.disable_legacy_bootstrap = true;
nano::node_config config;
// Disable other bootstrap strategies
config.bootstrap_ascending.enable_scan = false;
config.bootstrap_ascending.enable_dependency_walker = false;
// Disable election activation
config.backlog_population.enable = false;
config.priority_scheduler.enable = false;
config.optimistic_scheduler.enable = false;
config.hinted_scheduler.enable = false;

// Prepare blocks for frontier scan (genesis 10 sends -> 10 opens -> 10 updates)
std::vector<std::shared_ptr<nano::block>> sends;
std::vector<std::shared_ptr<nano::block>> opens;
std::vector<std::shared_ptr<nano::block>> updates;
{
auto source = nano::dev::genesis_key;
auto latest = nano::dev::genesis->hash ();
auto balance = nano::dev::genesis->balance ().number ();

size_t const count = 10;

for (int n = 0; n < count; ++n)
{
nano::keypair key;
nano::block_builder builder;

balance -= 1;
auto send = builder
.state ()
.account (source.pub)
.previous (latest)
.representative (source.pub)
.balance (balance)
.link (key.pub)
.sign (source.prv, source.pub)
.work (*system.work.generate (latest))
.build ();

latest = send->hash ();

auto open = builder
.state ()
.account (key.pub)
.previous (0)
.representative (key.pub)
.balance (1)
.link (send->hash ())
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.build ();

auto update = builder
.state ()
.account (key.pub)
.previous (open->hash ())
.representative (0)
.balance (1)
.link (0)
.sign (key.prv, key.pub)
.work (*system.work.generate (open->hash ()))
.build ();

sends.push_back (send);
opens.push_back (open);
updates.push_back (update);
}
}

// Initialize nodes with blocks without the `updates` frontiers
std::vector<std::shared_ptr<nano::block>> blocks;
blocks.insert (blocks.end (), sends.begin (), sends.end ());
blocks.insert (blocks.end (), opens.begin (), opens.end ());
system.set_initialization_blocks ({ blocks.begin (), blocks.end () });

auto & node0 = *system.add_node (config, flags);
ASSERT_TRUE (nano::test::process (node0, updates));

// No blocks should be broadcast to the other node
auto & node1 = *system.add_node (config, flags);
ASSERT_ALWAYS_EQ (100ms, node1.ledger.block_count (), blocks.size () + 1);

// Frontier scan should detect all the accounts with missing blocks
ASSERT_TIMELY (10s, std::all_of (updates.begin (), updates.end (), [&node1] (auto const & block) {
return node1.ascendboot.prioritized (block->account ());
}));
}

/*
* Tests that bootstrap will prioritize not yet existing accounts with pending blocks
*/
TEST (bootstrap_ascending, frontier_scan_pending)
{
nano::test::system system;

nano::node_flags flags;
flags.disable_legacy_bootstrap = true;
nano::node_config config;
// Disable other bootstrap strategies
config.bootstrap_ascending.enable_scan = false;
config.bootstrap_ascending.enable_dependency_walker = false;
// Disable election activation
config.backlog_population.enable = false;
config.priority_scheduler.enable = false;
config.optimistic_scheduler.enable = false;
config.hinted_scheduler.enable = false;

// Prepare blocks for frontier scan (genesis 10 sends -> 10 opens)
std::vector<std::shared_ptr<nano::block>> sends;
std::vector<std::shared_ptr<nano::block>> opens;
{
auto source = nano::dev::genesis_key;
auto latest = nano::dev::genesis->hash ();
auto balance = nano::dev::genesis->balance ().number ();

size_t const count = 10;

for (int n = 0; n < count; ++n)
{
nano::keypair key;
nano::block_builder builder;

balance -= 1;
auto send = builder
.state ()
.account (source.pub)
.previous (latest)
.representative (source.pub)
.balance (balance)
.link (key.pub)
.sign (source.prv, source.pub)
.work (*system.work.generate (latest))
.build ();

latest = send->hash ();

auto open = builder
.state ()
.account (key.pub)
.previous (0)
.representative (key.pub)
.balance (1)
.link (send->hash ())
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.build ();

sends.push_back (send);
opens.push_back (open);
}
}

// Initialize nodes with blocks without the `updates` frontiers
std::vector<std::shared_ptr<nano::block>> blocks;
blocks.insert (blocks.end (), sends.begin (), sends.end ());
system.set_initialization_blocks ({ blocks.begin (), blocks.end () });

auto & node0 = *system.add_node (config, flags);
ASSERT_TRUE (nano::test::process (node0, opens));

// No blocks should be broadcast to the other node
auto & node1 = *system.add_node (config, flags);
ASSERT_ALWAYS_EQ (100ms, node1.ledger.block_count (), blocks.size () + 1);

// Frontier scan should detect all the accounts with missing blocks
ASSERT_TIMELY (10s, std::all_of (opens.begin (), opens.end (), [&node1] (auto const & block) {
return node1.ascendboot.prioritized (block->account ());
}));
}

/*
* Bootstrap should not attempt to prioritize accounts that can't be immediately connected to the ledger (no pending blocks, no existing frontier)
*/
TEST (bootstrap_ascending, frontier_scan_cannot_prioritize)
{
nano::test::system system;

nano::node_flags flags;
flags.disable_legacy_bootstrap = true;
nano::node_config config;
// Disable other bootstrap strategies
config.bootstrap_ascending.enable_scan = false;
config.bootstrap_ascending.enable_dependency_walker = false;
// Disable election activation
config.backlog_population.enable = false;
config.priority_scheduler.enable = false;
config.optimistic_scheduler.enable = false;
config.hinted_scheduler.enable = false;

// Prepare blocks for frontier scan (genesis 10 sends -> 10 opens -> 10 sends -> 10 opens)
std::vector<std::shared_ptr<nano::block>> sends;
std::vector<std::shared_ptr<nano::block>> opens;
std::vector<std::shared_ptr<nano::block>> sends2;
std::vector<std::shared_ptr<nano::block>> opens2;
{
auto source = nano::dev::genesis_key;
auto latest = nano::dev::genesis->hash ();
auto balance = nano::dev::genesis->balance ().number ();

size_t const count = 10;

for (int n = 0; n < count; ++n)
{
nano::keypair key, key2;
nano::block_builder builder;

balance -= 1;
auto send = builder
.state ()
.account (source.pub)
.previous (latest)
.representative (source.pub)
.balance (balance)
.link (key.pub)
.sign (source.prv, source.pub)
.work (*system.work.generate (latest))
.build ();

latest = send->hash ();

auto open = builder
.state ()
.account (key.pub)
.previous (0)
.representative (key.pub)
.balance (1)
.link (send->hash ())
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.build ();

auto send2 = builder
.state ()
.account (key.pub)
.previous (open->hash ())
.representative (key.pub)
.balance (0)
.link (key2.pub)
.sign (key.prv, key.pub)
.work (*system.work.generate (open->hash ()))
.build ();

auto open2 = builder
.state ()
.account (key2.pub)
.previous (0)
.representative (key2.pub)
.balance (1)
.link (send2->hash ())
.sign (key2.prv, key2.pub)
.work (*system.work.generate (key2.pub))
.build ();

sends.push_back (send);
opens.push_back (open);
sends2.push_back (send2);
opens2.push_back (open2);
}
}

// Initialize nodes with blocks without the `updates` frontiers
std::vector<std::shared_ptr<nano::block>> blocks;
blocks.insert (blocks.end (), sends.begin (), sends.end ());
blocks.insert (blocks.end (), opens.begin (), opens.end ());
system.set_initialization_blocks ({ blocks.begin (), blocks.end () });

auto & node0 = *system.add_node (config, flags);
ASSERT_TRUE (nano::test::process (node0, sends2));
ASSERT_TRUE (nano::test::process (node0, opens2));

// No blocks should be broadcast to the other node
auto & node1 = *system.add_node (config, flags);
ASSERT_ALWAYS_EQ (100ms, node1.ledger.block_count (), blocks.size () + 1);

// Frontier scan should not detect the accounts
ASSERT_ALWAYS (1s, std::none_of (opens2.begin (), opens2.end (), [&node1] (auto const & block) {
return node1.ascendboot.prioritized (block->account ());
}));
}
12 changes: 12 additions & 0 deletions nano/node/bootstrap_ascending/service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,18 @@ std::size_t nano::bootstrap_ascending::service::score_size () const
return scoring.size ();
}

bool nano::bootstrap_ascending::service::prioritized (nano::account const & account) const
{
nano::lock_guard<nano::mutex> lock{ mutex };
return accounts.prioritized (account);
}

bool nano::bootstrap_ascending::service::blocked (nano::account const & account) const
{
nano::lock_guard<nano::mutex> lock{ mutex };
return accounts.blocked (account);
}

/** Inspects a block that has been processed by the block processor
- Marks an account as blocked if the result code is gap source as there is no reason request additional blocks for this account until the dependency is resolved
- Marks an account as forwarded if it has been recently referenced by a block that has been inserted.
Expand Down
2 changes: 2 additions & 0 deletions nano/node/bootstrap_ascending/service.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ namespace bootstrap_ascending
std::size_t blocked_size () const;
std::size_t priority_size () const;
std::size_t score_size () const;
bool prioritized (nano::account const &) const;
bool blocked (nano::account const &) const;
nano::bootstrap_ascending::account_sets::info_t info () const;

private: // Dependencies
Expand Down

0 comments on commit ed4c175

Please sign in to comment.