Skip to content

Commit

Permalink
Improve handling of rep weights snapshots
Browse files Browse the repository at this point in the history
  • Loading branch information
pwojcikdev committed Feb 19, 2025
1 parent 20e5f56 commit f45210c
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 44 deletions.
70 changes: 53 additions & 17 deletions nano/core_test/ledger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2251,51 +2251,87 @@ TEST (ledger, send_open_receive_rollback)
ASSERT_EQ (nano::dev::constants.genesis_amount - 0, ledger.weight (nano::dev::genesis_key.pub));
}

TEST (ledger, bootstrap_rep_weight)
TEST (ledger, bootstrap_weights)
{
auto ctx = nano::test::ledger_empty ();
auto & ledger = ctx.ledger ();
auto & store = ctx.store ();
nano::keypair key2;
auto & pool = ctx.pool ();

nano::keypair rep_key1, rep_key2, throwaway;

// Genesis key has all the voting weight
ASSERT_EQ (std::numeric_limits<nano::uint128_t>::max (), ledger.weight (nano::dev::genesis_key.pub));

// Throwaway transaction to reduce genesis weight
{
auto transaction = ledger.tx_begin_write ();
auto info1 = ledger.any.account_get (transaction, nano::dev::genesis_key.pub);
ASSERT_TRUE (info1);
auto genesis_info = ledger.any.account_get (transaction, nano::dev::genesis_key.pub);
ASSERT_TRUE (genesis_info);
nano::block_builder builder;
auto send = builder
.send ()
.previous (info1->head)
.destination (key2.pub)
.previous (genesis_info->head)
.destination (throwaway.pub)
.balance (std::numeric_limits<nano::uint128_t>::max () - 50)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*pool.generate (info1->head))
.work (*pool.generate (genesis_info->head))
.build ();
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send));
}

// Override bootstrap weights
ledger.bootstrap_weight_max_blocks = 4;
ledger.bootstrap_weights[rep_key1.pub] = 1000;

// Should use bootstrap weights
ASSERT_EQ (2, ledger.block_count ());
ASSERT_FALSE (ledger.bootstrap_height_reached ());
ASSERT_EQ (0, ledger.weight (nano::dev::genesis_key.pub));
ASSERT_EQ (1000, ledger.weight (rep_key1.pub));
{
ledger.bootstrap_weight_max_blocks = 3;
ledger.bootstrap_weights[key2.pub] = 1000;
ASSERT_EQ (1000, ledger.weight (key2.pub));
auto snapshot = ledger.rep_weights_snapshot ();
ASSERT_EQ (1, snapshot.size ());
ASSERT_EQ (1000, snapshot[rep_key1.pub]);
}

// Open normal representative account, should not use bootstrap weights anymore
{
auto transaction = ledger.tx_begin_write ();
auto info1 = ledger.any.account_get (transaction, nano::dev::genesis_key.pub);
ASSERT_TRUE (info1);
auto genesis_info = ledger.any.account_get (transaction, nano::dev::genesis_key.pub);
ASSERT_TRUE (genesis_info);
nano::block_builder builder;
auto send = builder
.send ()
.previous (info1->head)
.destination (key2.pub)
.previous (genesis_info->head)
.destination (rep_key2.pub)
.balance (std::numeric_limits<nano::uint128_t>::max () - 100)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*pool.generate (info1->head))
.work (*pool.generate (genesis_info->head))
.build ();
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, send));

auto open = builder
.open ()
.source (send->hash ())
.representative (rep_key2.pub)
.account (rep_key2.pub)
.sign (rep_key2.prv, rep_key2.pub)
.work (*pool.generate (rep_key2.pub))
.build ();
ASSERT_EQ (nano::block_status::progress, ledger.process (transaction, open));
}
ASSERT_EQ (4, ledger.block_count ());
ASSERT_TRUE (ledger.bootstrap_height_reached ());
ASSERT_EQ (std::numeric_limits<nano::uint128_t>::max () - 100, ledger.weight (nano::dev::genesis_key.pub));
ASSERT_EQ (0, ledger.weight (rep_key1.pub));
ASSERT_EQ (50, ledger.weight (rep_key2.pub));
{
auto snapshot = ledger.rep_weights_snapshot ();
ASSERT_EQ (2, snapshot.size ());
ASSERT_EQ (std::numeric_limits<nano::uint128_t>::max () - 100, snapshot[nano::dev::genesis_key.pub]);
ASSERT_EQ (50, snapshot[rep_key2.pub]);
}
ASSERT_EQ (3, ledger.block_count ());
ASSERT_EQ (0, ledger.weight (key2.pub));
}

TEST (ledger, block_destination_source)
Expand Down
6 changes: 2 additions & 4 deletions nano/node/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,18 +355,16 @@ nano::node::node (std::shared_ptr<boost::asio::io_context> io_ctx_a, std::filesy
{
auto const bootstrap_weights = get_bootstrap_weights ();
ledger.bootstrap_weight_max_blocks = bootstrap_weights.first;
ledger.bootstrap_weights = bootstrap_weights.second;

logger.info (nano::log::type::node, "Initial bootstrap height: {}", ledger.bootstrap_weight_max_blocks);
logger.info (nano::log::type::node, "Current ledger height: {}", ledger.block_count ());

// Use bootstrap weights if initial bootstrap is not completed
const bool use_bootstrap_weight = ledger.block_count () < bootstrap_weights.first;
const bool use_bootstrap_weight = !ledger.bootstrap_height_reached ();
if (use_bootstrap_weight)
{
logger.info (nano::log::type::node, "Using predefined representative weights, since block count is less than bootstrap threshold");

ledger.bootstrap_weights = bootstrap_weights.second;

logger.info (nano::log::type::node, "******************************************** Bootstrap weights ********************************************");

// Sort the weights
Expand Down
2 changes: 1 addition & 1 deletion nano/node/rep_tiers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ void nano::rep_tiers::run ()
void nano::rep_tiers::calculate_tiers ()
{
auto stake = online_reps.trended ();
auto rep_amounts = ledger.cache.rep_weights.get_rep_amounts ();
auto rep_amounts = ledger.rep_weights_snapshot ();

decltype (representatives_1) representatives_1_l;
decltype (representatives_2) representatives_2_l;
Expand Down
51 changes: 31 additions & 20 deletions nano/secure/ledger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -711,14 +711,17 @@ void representative_visitor::state_block (nano::state_block const & block_a)
{
result = block_a.hash ();
}
} // namespace
}

/*
* ledger
*/

nano::ledger::ledger (nano::store::component & store_a, nano::stats & stat_a, nano::ledger_constants & constants, nano::generate_cache_flags const & generate_cache_flags_a, nano::uint128_t min_rep_weight_a) :
constants{ constants },
store{ store_a },
cache{ store_a.rep_weight, min_rep_weight_a },
stats{ stat_a },
check_bootstrap_weights{ true },
any_impl{ std::make_unique<ledger_set_any> (*this) },
confirmed_impl{ std::make_unique<ledger_set_confirmed> (*this) },
any{ *any_impl },
Expand Down Expand Up @@ -962,25 +965,38 @@ std::deque<std::shared_ptr<nano::block>> nano::ledger::random_blocks (secure::tr
return result;
}

// Vote weight of an account
bool nano::ledger::bootstrap_height_reached () const
{
return cache.block_count >= bootstrap_weight_max_blocks;
}

std::unordered_map<nano::account, nano::uint128_t> nano::ledger::rep_weights_snapshot () const
{
if (!bootstrap_height_reached ())
{
return bootstrap_weights;
}
else
{
return cache.rep_weights.get_rep_amounts ();
}
}

nano::uint128_t nano::ledger::weight (nano::account const & account_a) const
{
if (check_bootstrap_weights.load ())
if (!bootstrap_height_reached ())
{
if (cache.block_count < bootstrap_weight_max_blocks)
auto weight = bootstrap_weights.find (account_a);
if (weight != bootstrap_weights.end ())
{
auto weight = bootstrap_weights.find (account_a);
if (weight != bootstrap_weights.end ())
{
return weight->second;
}
}
else
{
check_bootstrap_weights = false;
return weight->second;
}
return 0;
}
else
{
return cache.rep_weights.representation_get (account_a);
}
return cache.rep_weights.representation_get (account_a);
}

nano::uint128_t nano::ledger::weight_exact (secure::transaction const & txn_a, nano::account const & representative_a) const
Expand Down Expand Up @@ -1511,11 +1527,6 @@ bool nano::ledger::migrate_lmdb_to_rocksdb (std::filesystem::path const & data_p
return error;
}

bool nano::ledger::bootstrap_weight_reached () const
{
return cache.block_count >= bootstrap_weight_max_blocks;
}

nano::epoch nano::ledger::version (nano::block const & block)
{
if (block.type () == nano::block_type::state)
Expand Down
4 changes: 2 additions & 2 deletions nano/secure/ledger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ class ledger final
nano::account const & epoch_signer (nano::link const &) const;
nano::link const & epoch_link (nano::epoch) const;
bool migrate_lmdb_to_rocksdb (std::filesystem::path const &) const;
bool bootstrap_weight_reached () const;
bool bootstrap_height_reached () const;
std::unordered_map<nano::account, nano::uint128_t> rep_weights_snapshot () const;

static nano::epoch version (nano::block const & block);
nano::epoch version (secure::transaction const &, nano::block_hash const & hash) const;
Expand Down Expand Up @@ -104,7 +105,6 @@ class ledger final

std::unordered_map<nano::account, nano::uint128_t> bootstrap_weights;
uint64_t bootstrap_weight_max_blocks{ 1 };
mutable std::atomic<bool> check_bootstrap_weights;

bool pruning{ false };

Expand Down

0 comments on commit f45210c

Please sign in to comment.