Skip to content

Commit

Permalink
Constrained successor and destination block activation (#2895)
Browse files Browse the repository at this point in the history
Adapted for V21.2 patch
  • Loading branch information
guilhermelawless committed Sep 2, 2020
1 parent 951c6fe commit 86fb2e0
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 15 deletions.
62 changes: 62 additions & 0 deletions nano/core_test/active_transactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1170,3 +1170,65 @@ TEST (active_transactions, activate_account_chain)
ASSERT_TIMELY (3s, node.block_confirmed (send3->hash ()));
ASSERT_TIMELY (3s, node.active.active (receive->qualified_root ()));
}

TEST (active_transactions, activate_inactive)
{
nano::system system;
nano::node_flags flags;
nano::node_config config (nano::get_available_port (), system.logging);
config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
auto & node = *system.add_node (config, flags);

nano::keypair key;
nano::state_block_builder builder;
std::shared_ptr<nano::block> send = builder.make_block ()
.account (nano::test_genesis_key.pub)
.previous (nano::genesis_hash)
.representative (nano::test_genesis_key.pub)
.link (key.pub)
.balance (nano::genesis_amount - 1)
.sign (nano::test_genesis_key.prv, nano::test_genesis_key.pub)
.work (*system.work.generate (nano::genesis_hash))
.build ();
std::shared_ptr<nano::block> send2 = builder.make_block ()
.account (nano::test_genesis_key.pub)
.previous (send->hash ())
.representative (nano::test_genesis_key.pub)
.link (nano::keypair ().pub)
.balance (nano::genesis_amount - 2)
.sign (nano::test_genesis_key.prv, nano::test_genesis_key.pub)
.work (*system.work.generate (send->hash ()))
.build ();
std::shared_ptr<nano::block> open = builder.make_block ()
.account (key.pub)
.previous (0)
.representative (key.pub)
.link (send->hash ())
.balance (1)
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.build ();

ASSERT_EQ (nano::process_result::progress, node.process (*send).code);
ASSERT_EQ (nano::process_result::progress, node.process (*send2).code);
ASSERT_EQ (nano::process_result::progress, node.process (*open).code);

node.block_confirm (send2);
{
auto election = node.active.election (send2->qualified_root ());
ASSERT_NE (nullptr, election);
nano::lock_guard<std::mutex> guard (node.active.mutex);
election->confirm_once ();
}

ASSERT_TIMELY (3s, !node.confirmation_height_processor.is_processing_block (send2->hash ()));
ASSERT_TRUE (node.block_confirmed (send2->hash ()));
ASSERT_TRUE (node.block_confirmed (send->hash ()));

ASSERT_EQ (1, node.stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::inactive_conf_height, nano::stat::dir::out));
ASSERT_EQ (1, node.stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::active_quorum, nano::stat::dir::out));
ASSERT_EQ (0, node.stats.count (nano::stat::type::confirmation_observer, nano::stat::detail::active_conf_height, nano::stat::dir::out));

// The first block was not active so no activation takes place
ASSERT_FALSE (node.active.active (open->qualified_root ()) || node.block_confirmed_or_being_confirmed (node.store.tx_begin_read (), open->hash ()));
}
11 changes: 4 additions & 7 deletions nano/core_test/confirmation_height.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,16 +356,13 @@ TEST (confirmation_height, gap_live)
ASSERT_EQ (nano::genesis_hash, confirmation_height_info.frontier);
}

// Vote and confirm all existing blocks
node->block_confirm (send1);
ASSERT_TIMELY (10s, node->stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out) == 3);

// Now complete the chain where the block comes in on the live network
node->process_active (open1);
node->block_processor.flush ();
node->block_confirm (open1);
{
auto election = node->active.election (open1->qualified_root ());
ASSERT_NE (nullptr, election);
nano::lock_guard<std::mutex> guard (node->active.mutex);
election->confirm_once ();
}

system.deadline_set (10s);
while (node->stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out) != 6)
Expand Down
29 changes: 22 additions & 7 deletions nano/node/active_transactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

using namespace std::chrono;

size_t constexpr nano::active_transactions::max_active_elections_frontier_insertion;

nano::active_transactions::active_transactions (nano::node & node_a, nano::confirmation_height_processor & confirmation_height_processor_a) :
recently_dropped (node_a.stats),
confirmation_height_processor (confirmation_height_processor_a),
Expand Down Expand Up @@ -59,7 +61,7 @@ void nano::active_transactions::confirm_prioritized_frontiers (nano::transaction
auto is_test_network = node.network_params.network.is_test_network ();
auto roots_size = size ();
auto check_time_exceeded = std::chrono::steady_clock::now () >= next_frontier_check;
auto max_elections = 1000ull;
auto max_elections = max_active_elections_frontier_insertion;
auto low_active_elections = roots_size < max_elections;
bool wallets_check_required = (!skip_wallets || !priority_wallet_cementable_frontiers.empty ()) && !agressive_mode;
// Minimise dropping real-time transactions, set the number of frontiers added to a factor of the maximum number of possible active elections
Expand Down Expand Up @@ -189,16 +191,29 @@ void nano::active_transactions::block_cemented_callback (std::shared_ptr<nano::b
}
}

// Start or vote for the next unconfirmed block in this account
auto const & account (!block_a->account ().is_zero () ? block_a->account () : block_a->sideband ().account);
debug_assert (!account.is_zero ());
activate (account);

// Start or vote for the next unconfirmed block in the destination account
auto const & destination (node.ledger.block_destination (transaction, *block_a));
if (!destination.is_zero () && destination != account)
// Next-block activations are done after cementing hardcoded bootstrap count to allow confirming very large chains without interference
bool const cemented_bootstrap_count_reached{ node.ledger.cache.cemented_count >= node.ledger.bootstrap_weight_max_blocks };

// Next-block activations are only done for blocks with previously active elections
bool const was_active{ *election_status_type == nano::election_status_type::active_confirmed_quorum || *election_status_type == nano::election_status_type::active_confirmation_height };

// Activations are only done if there is not a large amount of active elections, ensuring frontier confirmation takes place
auto const low_active_elections = [this] { return this->size () < nano::active_transactions::max_active_elections_frontier_insertion / 2; };

if (cemented_bootstrap_count_reached && was_active && low_active_elections ())
{
activate (destination);
// Start or vote for the next unconfirmed block
activate (account);

// Start or vote for the next unconfirmed block in the destination account
auto const & destination (node.ledger.block_destination (transaction, *block_a));
if (!destination.is_zero () && destination != account)
{
activate (destination);
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions nano/node/active_transactions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ class active_transactions final
void frontiers_confirmation (nano::unique_lock<std::mutex> &);
nano::account next_frontier_account{ 0 };
std::chrono::steady_clock::time_point next_frontier_check{ std::chrono::steady_clock::now () };
constexpr static size_t max_active_elections_frontier_insertion{ 1000 };
nano::condition_variable condition;
bool started{ false };
std::atomic<bool> stopped{ false };
Expand Down
2 changes: 1 addition & 1 deletion nano/node/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,13 +412,13 @@ node_seq (seq)
bool use_bootstrap_weight = ledger.cache.block_count < bootstrap_weights.first;
if (use_bootstrap_weight)
{
ledger.bootstrap_weight_max_blocks = bootstrap_weights.first;
ledger.bootstrap_weights = bootstrap_weights.second;
for (auto const & rep : ledger.bootstrap_weights)
{
logger.always_log ("Using bootstrap rep weight: ", rep.first.to_account (), " -> ", nano::uint128_union (rep.second).format_balance (Mxrb_ratio, 0, true), " XRB");
}
}
ledger.bootstrap_weight_max_blocks = bootstrap_weights.first;

// Drop unchecked blocks if initial bootstrap is completed
if (!flags.disable_unchecked_drop && !use_bootstrap_weight && !flags.read_only)
Expand Down

0 comments on commit 86fb2e0

Please sign in to comment.