From 5980be65cb58d7d9747c62c3523b18c329f2b145 Mon Sep 17 00:00:00 2001 From: Gustav Schauwecker Date: Mon, 11 Mar 2024 15:31:33 +0100 Subject: [PATCH 01/10] Fill rep_weights table --- nano/core_test/block_store.cpp | 43 ++++++++++++++++++++++++++++++++++ nano/secure/account_info.cpp | 33 ++++++++++++++++++++++++++ nano/secure/account_info.hpp | 20 ++++++++++++++++ nano/store/component.hpp | 2 +- nano/store/db_val.hpp | 4 ++++ nano/store/db_val_impl.hpp | 16 +++++++++++++ nano/store/lmdb/lmdb.cpp | 40 ++++++++++++++++++++++++++++++- nano/store/lmdb/lmdb.hpp | 1 + nano/store/rocksdb/rocksdb.cpp | 36 ++++++++++++++++++++++++++++ nano/store/rocksdb/rocksdb.hpp | 1 + 10 files changed, 194 insertions(+), 2 deletions(-) diff --git a/nano/core_test/block_store.cpp b/nano/core_test/block_store.cpp index ecd575ea41..2f611b01fd 100644 --- a/nano/core_test/block_store.cpp +++ b/nano/core_test/block_store.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -1445,6 +1446,48 @@ TEST (rocksdb_block_store, upgrade_v21_v22) } } +// Tests that the new rep_weight table gets filled with all +// existing representatives +TEST (mdb_block_store, upgrade_v22_to_v23) +{ + nano::logger logger; + auto const path = nano::unique_path (); + nano::account rep_a{ 123 }; + nano::account rep_b{ 456 }; + // Setting the database to its 22nd version state + { + auto store{ nano::make_store (logger, path, nano::dev::constants) }; + auto txn{ store->tx_begin_write () }; + + // Add three accounts referencing two representatives + nano::account_info info1{}; + info1.representative = rep_a; + info1.balance = 1000; + store->account.put (txn, 1, info1); + + nano::account_info info2{}; + info2.representative = rep_a; + info2.balance = 500; + store->account.put (txn, 2, info2); + + nano::account_info info3{}; + info3.representative = rep_b; + info3.balance = 42; + store->account.put (txn, 3, info3); + + store->version.put (txn, 22); + } + + // Testing the upgrade code worked + auto store{ nano::make_store (logger, path, nano::dev::constants) }; + auto txn (store->tx_begin_read ()); + ASSERT_EQ (store->version.get (txn), store->version_current); + + // The rep_weight table should contain all reps now + ASSERT_EQ (1500, store->rep_weight.get (txn, rep_a)); + ASSERT_EQ (42, store->rep_weight.get (txn, rep_b)); +} + TEST (mdb_block_store, upgrade_backup) { if (nano::rocksdb_config::using_rocksdb_in_tests ()) diff --git a/nano/secure/account_info.cpp b/nano/secure/account_info.cpp index b478f95e71..1b18ca6024 100644 --- a/nano/secure/account_info.cpp +++ b/nano/secure/account_info.cpp @@ -58,3 +58,36 @@ nano::epoch nano::account_info::epoch () const { return epoch_m; } + +size_t nano::account_info_v22::db_size () const +{ + debug_assert (reinterpret_cast (this) == reinterpret_cast (&head)); + debug_assert (reinterpret_cast (&head) + sizeof (head) == reinterpret_cast (&representative)); + debug_assert (reinterpret_cast (&representative) + sizeof (representative) == reinterpret_cast (&open_block)); + debug_assert (reinterpret_cast (&open_block) + sizeof (open_block) == reinterpret_cast (&balance)); + debug_assert (reinterpret_cast (&balance) + sizeof (balance) == reinterpret_cast (&modified)); + debug_assert (reinterpret_cast (&modified) + sizeof (modified) == reinterpret_cast (&block_count)); + debug_assert (reinterpret_cast (&block_count) + sizeof (block_count) == reinterpret_cast (&epoch_m)); + return sizeof (head) + sizeof (representative) + sizeof (open_block) + sizeof (balance) + sizeof (modified) + sizeof (block_count) + sizeof (epoch_m); +} + +bool nano::account_info_v22::deserialize (nano::stream & stream_a) +{ + auto error (false); + try + { + nano::read (stream_a, head.bytes); + nano::read (stream_a, representative.bytes); + nano::read (stream_a, open_block.bytes); + nano::read (stream_a, balance.bytes); + nano::read (stream_a, modified); + nano::read (stream_a, block_count); + nano::read (stream_a, epoch_m); + } + catch (std::runtime_error const &) + { + error = true; + } + + return error; +} \ No newline at end of file diff --git a/nano/secure/account_info.hpp b/nano/secure/account_info.hpp index 422515fa87..bd7a7b0ccd 100644 --- a/nano/secure/account_info.hpp +++ b/nano/secure/account_info.hpp @@ -29,4 +29,24 @@ class account_info final uint64_t block_count{ 0 }; nano::epoch epoch_m{ nano::epoch::epoch_0 }; }; + +/** + * Account info as of DB version 22. + * This class protects the DB upgrades from future changes of the account_info class. + */ +class account_info_v22 final +{ +public: + account_info_v22 () = default; + size_t db_size () const; + bool deserialize (nano::stream &); + nano::block_hash head{ 0 }; + nano::account representative{}; + nano::block_hash open_block{ 0 }; + nano::amount balance{ 0 }; + /** Seconds since posix epoch */ + nano::seconds_t modified{ 0 }; + uint64_t block_count{ 0 }; + nano::epoch epoch_m{ nano::epoch::epoch_0 }; +}; } // namespace nano diff --git a/nano/store/component.hpp b/nano/store/component.hpp index eaa8faf958..ac5103e92c 100644 --- a/nano/store/component.hpp +++ b/nano/store/component.hpp @@ -72,7 +72,7 @@ namespace store store::pending & pending; store::rep_weight & rep_weight; static int constexpr version_minimum{ 21 }; - static int constexpr version_current{ 22 }; + static int constexpr version_current{ 23 }; public: store::online_weight & online_weight; diff --git a/nano/store/db_val.hpp b/nano/store/db_val.hpp index fee58d9e0d..7cc415a5fd 100644 --- a/nano/store/db_val.hpp +++ b/nano/store/db_val.hpp @@ -12,6 +12,7 @@ namespace nano { class account_info; +class account_info_v22; class block; class pending_info; class pending_key; @@ -63,6 +64,8 @@ class db_val db_val (nano::account_info const & val_a); + db_val (nano::account_info_v22 const & val_a); + db_val (nano::pending_info const & val_a); db_val (nano::pending_key const & val_a); @@ -103,6 +106,7 @@ class db_val } explicit operator nano::account_info () const; + explicit operator nano::account_info_v22 () const; explicit operator block_info () const { diff --git a/nano/store/db_val_impl.hpp b/nano/store/db_val_impl.hpp index c8ee18624f..f2eaf48840 100644 --- a/nano/store/db_val_impl.hpp +++ b/nano/store/db_val_impl.hpp @@ -10,6 +10,13 @@ nano::store::db_val::db_val (nano::account_info const & val_a) : db_val (val_a.db_size (), const_cast (&val_a)) { } + +template +nano::store::db_val::db_val (nano::account_info_v22 const & val_a) : + db_val (val_a.db_size (), const_cast (&val_a)) +{ +} + template nano::store::db_val::db_val (std::shared_ptr const & val_a) : buffer (std::make_shared> ()) @@ -44,6 +51,15 @@ nano::store::db_val::operator nano::account_info () const return result; } +template +nano::store::db_val::operator nano::account_info_v22 () const +{ + nano::account_info_v22 result; + debug_assert (size () == result.db_size ()); + std::copy (reinterpret_cast (data ()), reinterpret_cast (data ()) + result.db_size (), reinterpret_cast (&result)); + return result; +} + template nano::store::db_val::operator std::shared_ptr () const { diff --git a/nano/store/lmdb/lmdb.cpp b/nano/store/lmdb/lmdb.cpp index b5397b50fc..179c14b407 100644 --- a/nano/store/lmdb/lmdb.cpp +++ b/nano/store/lmdb/lmdb.cpp @@ -1,6 +1,8 @@ +#include #include #include #include +#include #include #include #include @@ -206,7 +208,7 @@ void nano::store::lmdb::component::open_databases (bool & error_a, store::transa pending_store.pending_handle = pending_store.pending_v0_handle; error_a |= mdb_dbi_open (env.tx (transaction_a), "final_votes", flags, &final_vote_store.final_votes_handle) != 0; error_a |= mdb_dbi_open (env.tx (transaction_a), "blocks", MDB_CREATE, &block_store.blocks_handle) != 0; - mdb_dbi_open (env.tx (transaction_a), "rep_weights", flags, &rep_weight_store.rep_weights_handle); + error_a |= mdb_dbi_open (env.tx (transaction_a), "rep_weights", flags, &rep_weight_store.rep_weights_handle) != 0; } bool nano::store::lmdb::component::do_upgrades (store::write_transaction & transaction_a, nano::ledger_constants & constants, bool & needs_vacuuming) @@ -224,6 +226,9 @@ bool nano::store::lmdb::component::do_upgrades (store::write_transaction & trans upgrade_v21_to_v22 (transaction_a); [[fallthrough]]; case 22: + upgrade_v22_to_v23 (transaction_a); + [[fallthrough]]; + case 23: break; default: logger.critical (nano::log::type::lmdb, "The version of the ledger ({}) is too high for this node", version_l); @@ -245,6 +250,39 @@ void nano::store::lmdb::component::upgrade_v21_to_v22 (store::write_transaction logger.info (nano::log::type::lmdb, "Upgrading database from v21 to v22 completed"); } +// Fill rep_weights table with all existing representatives and their vote weight +void nano::store::lmdb::component::upgrade_v22_to_v23 (store::write_transaction const & transaction_a) +{ + logger.info (nano::log::type::lmdb, "Upgrading database from v22 to v23..."); + auto i{ make_iterator (transaction_a, tables::accounts) }; + auto end{ store::iterator (nullptr) }; + uint64_t processed_accounts = 0; + for (; i != end; ++i) + { + if (!i->second.balance.is_zero ()) + { + nano::uint128_t total{ 0 }; + nano::store::lmdb::db_val value; + auto status = get (transaction_a, tables::rep_weights, i->second.representative, value); + if (success (status)) + { + total = nano::amount{ value }.number (); + } + total += i->second.balance.number (); + status = put (transaction_a, tables::rep_weights, i->second.representative, nano::amount{ total }); + release_assert_success (status); + } + processed_accounts++; + if (processed_accounts % 250000 == 0) + { + logger.info (nano::log::type::lmdb, "processed {} accounts", processed_accounts); + } + } + logger.info (nano::log::type::lmdb, "processed {} accounts", processed_accounts); + version.put (transaction_a, 23); + logger.info (nano::log::type::lmdb, "Upgrading database from v22 to v23 completed"); +} + /** Takes a filepath, appends '_backup_' to the end (but before any extension) and saves that file in the same directory */ void nano::store::lmdb::component::create_backup_file (nano::store::lmdb::env & env_a, std::filesystem::path const & filepath_a, nano::logger & logger) { diff --git a/nano/store/lmdb/lmdb.hpp b/nano/store/lmdb/lmdb.hpp index 90bbc8ca6c..c763818863 100644 --- a/nano/store/lmdb/lmdb.hpp +++ b/nano/store/lmdb/lmdb.hpp @@ -116,6 +116,7 @@ class component : public nano::store::component private: bool do_upgrades (store::write_transaction &, nano::ledger_constants & constants, bool &); void upgrade_v21_to_v22 (store::write_transaction const &); + void upgrade_v22_to_v23 (store::write_transaction const &); void open_databases (bool &, store::transaction const &, unsigned); diff --git a/nano/store/rocksdb/rocksdb.cpp b/nano/store/rocksdb/rocksdb.cpp index 515a03772d..f13cdb76ba 100644 --- a/nano/store/rocksdb/rocksdb.cpp +++ b/nano/store/rocksdb/rocksdb.cpp @@ -245,6 +245,9 @@ bool nano::store::rocksdb::component::do_upgrades (store::write_transaction cons upgrade_v21_to_v22 (transaction_a); [[fallthrough]]; case 22: + upgrade_v22_to_v23 (transaction_a); + [[fallthrough]]; + case 23: break; default: logger.critical (nano::log::type::rocksdb, "The version of the ledger ({}) is too high for this node", version_l); @@ -280,6 +283,39 @@ void nano::store::rocksdb::component::upgrade_v21_to_v22 (store::write_transacti logger.info (nano::log::type::rocksdb, "Upgrading database from v21 to v22 completed"); } +// Fill rep_weights table with all existing representatives and their vote weight +void nano::store::rocksdb::component::upgrade_v22_to_v23 (store::write_transaction const & transaction_a) +{ + logger.info (nano::log::type::rocksdb, "Upgrading database from v22 to v23..."); + auto i{ make_iterator (transaction_a, tables::accounts) }; + auto end{ store::iterator (nullptr) }; + uint64_t processed_accounts = 0; + for (; i != end; ++i) + { + if (!i->second.balance.is_zero ()) + { + nano::uint128_t total{ 0 }; + nano::store::rocksdb::db_val value; + auto status = get (transaction_a, tables::rep_weights, i->second.representative, value); + if (success (status)) + { + total = nano::amount{ value }.number (); + } + total += i->second.balance.number (); + status = put (transaction_a, tables::rep_weights, i->second.representative, nano::amount{ total }); + release_assert_success (status); + } + processed_accounts++; + if (processed_accounts % 250000 == 0) + { + logger.info (nano::log::type::lmdb, "processed {} accounts", processed_accounts); + } + } + logger.info (nano::log::type::lmdb, "processed {} accounts", processed_accounts); + version.put (transaction_a, 23); + logger.info (nano::log::type::rocksdb, "Upgrading database from v22 to v23 completed"); +} + void nano::store::rocksdb::component::generate_tombstone_map () { tombstone_map.emplace (std::piecewise_construct, std::forward_as_tuple (nano::tables::blocks), std::forward_as_tuple (0, 25000)); diff --git a/nano/store/rocksdb/rocksdb.hpp b/nano/store/rocksdb/rocksdb.hpp index f23145b021..f6c2d683b8 100644 --- a/nano/store/rocksdb/rocksdb.hpp +++ b/nano/store/rocksdb/rocksdb.hpp @@ -154,6 +154,7 @@ class component : public nano::store::component bool do_upgrades (store::write_transaction const &); void upgrade_v21_to_v22 (store::write_transaction const &); + void upgrade_v22_to_v23 (store::write_transaction const &); void construct_column_family_mutexes (); ::rocksdb::Options get_db_options (); From 23947a3a68b859be1e9573278bf55c07b1366725 Mon Sep 17 00:00:00 2001 From: Gustav Schauwecker Date: Tue, 12 Mar 2024 09:00:00 +0100 Subject: [PATCH 02/10] Move reps_cache to nano/secure This is needed, because reps_cache will get access to the new rep_cache data store. --- nano/lib/CMakeLists.txt | 2 -- nano/secure/CMakeLists.txt | 2 ++ nano/secure/common.hpp | 2 +- nano/secure/ledger.cpp | 2 +- nano/secure/ledger_cache.hpp | 2 +- nano/{lib => secure}/rep_weights.cpp | 2 +- nano/{lib => secure}/rep_weights.hpp | 0 7 files changed, 6 insertions(+), 6 deletions(-) rename nano/{lib => secure}/rep_weights.cpp (98%) rename nano/{lib => secure}/rep_weights.hpp (100%) diff --git a/nano/lib/CMakeLists.txt b/nano/lib/CMakeLists.txt index c7029af764..fa9c81f610 100644 --- a/nano/lib/CMakeLists.txt +++ b/nano/lib/CMakeLists.txt @@ -72,8 +72,6 @@ add_library( rate_limiting.hpp rate_limiting.cpp relaxed_atomic.hpp - rep_weights.hpp - rep_weights.cpp rocksdbconfig.hpp rocksdbconfig.cpp rpc_handler_interface.hpp diff --git a/nano/secure/CMakeLists.txt b/nano/secure/CMakeLists.txt index f9ca76129a..cdb5adae02 100644 --- a/nano/secure/CMakeLists.txt +++ b/nano/secure/CMakeLists.txt @@ -53,6 +53,8 @@ add_library( network_filter.cpp pending_info.hpp pending_info.cpp + rep_weights.hpp + rep_weights.cpp utility.hpp utility.cpp vote.hpp diff --git a/nano/secure/common.hpp b/nano/secure/common.hpp index e1d43fec89..119e05142d 100644 --- a/nano/secure/common.hpp +++ b/nano/secure/common.hpp @@ -6,10 +6,10 @@ #include #include #include -#include #include #include #include +#include #include #include diff --git a/nano/secure/ledger.cpp b/nano/secure/ledger.cpp index 55570fcf81..e9d0291836 100644 --- a/nano/secure/ledger.cpp +++ b/nano/secure/ledger.cpp @@ -1,12 +1,12 @@ #include #include -#include #include #include #include #include #include #include +#include #include #include #include diff --git a/nano/secure/ledger_cache.hpp b/nano/secure/ledger_cache.hpp index 726a1e1119..28cac3dcd4 100644 --- a/nano/secure/ledger_cache.hpp +++ b/nano/secure/ledger_cache.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include diff --git a/nano/lib/rep_weights.cpp b/nano/secure/rep_weights.cpp similarity index 98% rename from nano/lib/rep_weights.cpp rename to nano/secure/rep_weights.cpp index 65a0604b4d..dd69bbd65b 100644 --- a/nano/lib/rep_weights.cpp +++ b/nano/secure/rep_weights.cpp @@ -1,4 +1,4 @@ -#include +#include #include void nano::rep_weights::representation_add (nano::account const & source_rep_a, nano::uint128_t const & amount_a) diff --git a/nano/lib/rep_weights.hpp b/nano/secure/rep_weights.hpp similarity index 100% rename from nano/lib/rep_weights.hpp rename to nano/secure/rep_weights.hpp From 3e5055e3c6b5496eebcc0115f8b5b1df87b0e7f1 Mon Sep 17 00:00:00 2001 From: Gustav Schauwecker Date: Mon, 11 Mar 2024 16:38:34 +0100 Subject: [PATCH 03/10] Update rep_weight table when rep_weights cache is changed --- nano/core_test/block_store.cpp | 10 ++++----- nano/core_test/ledger.cpp | 4 +++- nano/core_test/node.cpp | 2 +- nano/secure/ledger.cpp | 38 +++++++++++++++++++++------------- nano/secure/ledger_cache.cpp | 6 ++++++ nano/secure/ledger_cache.hpp | 2 ++ nano/secure/rep_weights.cpp | 32 +++++++++++++++++++--------- nano/secure/rep_weights.hpp | 11 +++++++--- nano/store/component.cpp | 1 + 9 files changed, 72 insertions(+), 34 deletions(-) diff --git a/nano/core_test/block_store.cpp b/nano/core_test/block_store.cpp index 2f611b01fd..385829766c 100644 --- a/nano/core_test/block_store.cpp +++ b/nano/core_test/block_store.cpp @@ -380,7 +380,7 @@ TEST (block_store, genesis) nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); - nano::ledger_cache ledger_cache; + nano::ledger_cache ledger_cache{ store->rep_weight }; auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger_cache, nano::dev::constants); nano::account_info info; @@ -902,7 +902,7 @@ TEST (block_store, cemented_count_cache) auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); ASSERT_TRUE (!store->init_error ()); auto transaction (store->tx_begin_write ()); - nano::ledger_cache ledger_cache; + nano::ledger_cache ledger_cache{ store->rep_weight }; store->initialize (transaction, ledger_cache, nano::dev::constants); ASSERT_EQ (1, ledger_cache.cemented_count); } @@ -912,7 +912,7 @@ TEST (block_store, block_random) nano::logger logger; auto store = nano::make_store (logger, nano::unique_path (), nano::dev::constants); { - nano::ledger_cache ledger_cache; + nano::ledger_cache ledger_cache{ store->rep_weight }; auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger_cache, nano::dev::constants); } @@ -939,7 +939,7 @@ TEST (block_store, pruned_random) block->sideband_set ({}); auto hash1 (block->hash ()); { - nano::ledger_cache ledger_cache; + nano::ledger_cache ledger_cache{ store->rep_weight }; auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger_cache, nano::dev::constants); store->pruned.put (transaction, hash1); @@ -969,7 +969,7 @@ TEST (block_store, state_block) block1->sideband_set ({}); { - nano::ledger_cache ledger_cache; + nano::ledger_cache ledger_cache{ store->rep_weight }; auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger_cache, nano::dev::constants); ASSERT_EQ (nano::block_type::state, block1->type ()); diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index 773057e894..e688ccff6f 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -657,8 +658,9 @@ TEST (ledger, open_fork) TEST (ledger, representation_changes) { + auto store{ nano::test::make_store () }; nano::keypair key1; - nano::rep_weights rep_weights; + nano::rep_weights rep_weights{ store->rep_weight }; ASSERT_EQ (0, rep_weights.representation_get (key1.pub)); rep_weights.representation_put (key1.pub, 1); ASSERT_EQ (1, rep_weights.representation_get (key1.pub)); diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index cf81a51bdb..56bd706a73 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -2906,7 +2906,7 @@ TEST (node, dont_write_lock_node) nano::logger logger; auto store = nano::make_store (logger, path, nano::dev::constants, false, true); { - nano::ledger_cache ledger_cache; + nano::ledger_cache ledger_cache{ store->rep_weight }; auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger_cache, nano::dev::constants); } diff --git a/nano/secure/ledger.cpp b/nano/secure/ledger.cpp index e9d0291836..d22a7a1242 100644 --- a/nano/secure/ledger.cpp +++ b/nano/secure/ledger.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include @@ -51,7 +53,7 @@ class rollback_visitor : public nano::block_visitor auto info = ledger.account_info (transaction, pending.value ().source); debug_assert (info); ledger.store.pending.del (transaction, key); - ledger.cache.rep_weights.representation_add (info->representative, pending.value ().amount.number ()); + ledger.cache.rep_weights.representation_add (transaction, info->representative, pending.value ().amount.number ()); nano::account_info new_info (block_a.hashables.previous, info->representative, info->open_block, ledger.balance (transaction, block_a.hashables.previous).value (), nano::seconds_since_epoch (), info->block_count - 1, nano::epoch::epoch_0); ledger.update_account (transaction, pending.value ().source, *info, new_info); ledger.store.block.del (transaction, hash); @@ -70,7 +72,7 @@ class rollback_visitor : public nano::block_visitor auto source_account = ledger.account (transaction, block_a.hashables.source); auto info = ledger.account_info (transaction, destination_account); debug_assert (info); - ledger.cache.rep_weights.representation_add (info->representative, 0 - amount); + ledger.cache.rep_weights.representation_add (transaction, info->representative, 0 - amount); nano::account_info new_info (block_a.hashables.previous, info->representative, info->open_block, ledger.balance (transaction, block_a.hashables.previous).value (), nano::seconds_since_epoch (), info->block_count - 1, nano::epoch::epoch_0); ledger.update_account (transaction, destination_account, *info, new_info); ledger.store.block.del (transaction, hash); @@ -86,7 +88,7 @@ class rollback_visitor : public nano::block_visitor auto amount = ledger.amount (transaction, hash).value (); auto destination_account = block_a.account (); auto source_account = ledger.account (transaction, block_a.hashables.source); - ledger.cache.rep_weights.representation_add (block_a.representative_field ().value (), 0 - amount); + ledger.cache.rep_weights.representation_add (transaction, block_a.representative_field ().value (), 0 - amount); nano::account_info new_info; ledger.update_account (transaction, destination_account, new_info, new_info); ledger.store.block.del (transaction, hash); @@ -105,7 +107,7 @@ class rollback_visitor : public nano::block_visitor auto block = ledger.store.block.get (transaction, rep_block); release_assert (block != nullptr); auto representative = block->representative_field ().value (); - ledger.cache.rep_weights.representation_add_dual (block_a.hashables.representative, 0 - balance, representative, balance); + ledger.cache.rep_weights.representation_add_dual (transaction, block_a.hashables.representative, 0 - balance, representative, balance); ledger.store.block.del (transaction, hash); nano::account_info new_info (block_a.hashables.previous, representative, info->open_block, info->balance, nano::seconds_since_epoch (), info->block_count - 1, nano::epoch::epoch_0); ledger.update_account (transaction, account, *info, new_info); @@ -131,12 +133,12 @@ class rollback_visitor : public nano::block_visitor auto block (ledger.store.block.get (transaction, rep_block_hash)); debug_assert (block != nullptr); representative = block->representative_field ().value (); - ledger.cache.rep_weights.representation_add_dual (representative, balance, block_a.hashables.representative, 0 - block_a.hashables.balance.number ()); + ledger.cache.rep_weights.representation_add_dual (transaction, representative, balance, block_a.hashables.representative, 0 - block_a.hashables.balance.number ()); } else { // Add in amount delta only - ledger.cache.rep_weights.representation_add (block_a.hashables.representative, 0 - block_a.hashables.balance.number ()); + ledger.cache.rep_weights.representation_add (transaction, block_a.hashables.representative, 0 - block_a.hashables.balance.number ()); } auto info = ledger.account_info (transaction, block_a.hashables.account); @@ -346,12 +348,12 @@ void ledger_processor::state_block_impl (nano::state_block & block_a) if (!info.head.is_zero ()) { // Move existing representation & add in amount delta - ledger.cache.rep_weights.representation_add_dual (info.representative, 0 - info.balance.number (), block_a.hashables.representative, block_a.hashables.balance.number ()); + ledger.cache.rep_weights.representation_add_dual (transaction, info.representative, 0 - info.balance.number (), block_a.hashables.representative, block_a.hashables.balance.number ()); } else { // Add in amount delta only - ledger.cache.rep_weights.representation_add (block_a.hashables.representative, block_a.hashables.balance.number ()); + ledger.cache.rep_weights.representation_add (transaction, block_a.hashables.representative, block_a.hashables.balance.number ()); } if (is_send) @@ -482,7 +484,7 @@ void ledger_processor::change_block (nano::change_block & block_a) block_a.sideband_set (nano::block_sideband (account, 0, info->balance, info->block_count + 1, nano::seconds_since_epoch (), block_details, nano::epoch::epoch_0 /* unused */)); ledger.store.block.put (transaction, hash, block_a); auto balance = previous->balance (); - ledger.cache.rep_weights.representation_add_dual (block_a.hashables.representative, balance.number (), info->representative, 0 - balance.number ()); + ledger.cache.rep_weights.representation_add_dual (transaction, block_a.hashables.representative, balance.number (), info->representative, 0 - balance.number ()); nano::account_info new_info (hash, block_a.hashables.representative, info->open_block, info->balance, nano::seconds_since_epoch (), info->block_count + 1, nano::epoch::epoch_0); ledger.update_account (transaction, account, *info, new_info); ledger.store.frontier.del (transaction, block_a.hashables.previous); @@ -529,7 +531,7 @@ void ledger_processor::send_block (nano::send_block & block_a) if (result == nano::block_status::progress) { auto amount (info->balance.number () - block_a.hashables.balance.number ()); - ledger.cache.rep_weights.representation_add (info->representative, 0 - amount); + ledger.cache.rep_weights.representation_add (transaction, info->representative, 0 - amount); block_a.sideband_set (nano::block_sideband (account, 0, block_a.hashables.balance /* unused */, info->block_count + 1, nano::seconds_since_epoch (), block_details, nano::epoch::epoch_0 /* unused */)); ledger.store.block.put (transaction, hash, block_a); nano::account_info new_info (hash, info->representative, info->open_block, block_a.hashables.balance, nano::seconds_since_epoch (), info->block_count + 1, nano::epoch::epoch_0); @@ -602,7 +604,7 @@ void ledger_processor::receive_block (nano::receive_block & block_a) ledger.store.block.put (transaction, hash, block_a); nano::account_info new_info (hash, info->representative, info->open_block, new_balance, nano::seconds_since_epoch (), info->block_count + 1, nano::epoch::epoch_0); ledger.update_account (transaction, account, *info, new_info); - ledger.cache.rep_weights.representation_add (info->representative, pending.value ().amount.number ()); + ledger.cache.rep_weights.representation_add (transaction, info->representative, pending.value ().amount.number ()); ledger.store.frontier.del (transaction, block_a.hashables.previous); ledger.store.frontier.put (transaction, hash, account); ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::receive); @@ -664,7 +666,7 @@ void ledger_processor::open_block (nano::open_block & block_a) ledger.store.block.put (transaction, hash, block_a); nano::account_info new_info (hash, block_a.representative_field ().value (), hash, pending.value ().amount.number (), nano::seconds_since_epoch (), 1, nano::epoch::epoch_0); ledger.update_account (transaction, block_a.hashables.account, info, new_info); - ledger.cache.rep_weights.representation_add (block_a.representative_field ().value (), pending.value ().amount.number ()); + ledger.cache.rep_weights.representation_add (transaction, block_a.representative_field ().value (), pending.value ().amount.number ()); ledger.store.frontier.put (transaction, hash, block_a.hashables.account); ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::open); } @@ -750,6 +752,7 @@ void representative_visitor::state_block (nano::state_block const & block_a) 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) : constants{ constants }, store{ store_a }, + cache{ store_a.rep_weight }, stats{ stat_a }, check_bootstrap_weights{ true } { @@ -767,16 +770,23 @@ void nano::ledger::initialize (nano::generate_cache_flags const & generate_cache [this] (store::read_transaction const & /*unused*/, store::iterator i, store::iterator n) { uint64_t block_count_l{ 0 }; uint64_t account_count_l{ 0 }; - decltype (this->cache.rep_weights) rep_weights_l; for (; i != n; ++i) { nano::account_info const & info (i->second); block_count_l += info.block_count; ++account_count_l; - rep_weights_l.representation_add (info.representative, info.balance.number ()); } this->cache.block_count += block_count_l; this->cache.account_count += account_count_l; + }); + + store.rep_weight.for_each_par ( + [this] (store::read_transaction const & /*unused*/, store::iterator i, store::iterator n) { + nano::rep_weights rep_weights_l{ this->store.rep_weight }; + for (; i != n; ++i) + { + rep_weights_l.representation_put (i->first, i->second.number ()); + } this->cache.rep_weights.copy_from (rep_weights_l); }); } diff --git a/nano/secure/ledger_cache.cpp b/nano/secure/ledger_cache.cpp index e69de29bb2..5076e1cc18 100644 --- a/nano/secure/ledger_cache.cpp +++ b/nano/secure/ledger_cache.cpp @@ -0,0 +1,6 @@ +#include + +nano::ledger_cache::ledger_cache (nano::store::rep_weight & rep_weight_store_a) : + rep_weights{ rep_weight_store_a } +{ +} diff --git a/nano/secure/ledger_cache.hpp b/nano/secure/ledger_cache.hpp index 28cac3dcd4..34b86cb639 100644 --- a/nano/secure/ledger_cache.hpp +++ b/nano/secure/ledger_cache.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -10,6 +11,7 @@ namespace nano class ledger_cache { public: + explicit ledger_cache (nano::store::rep_weight & rep_weight_store_a); nano::rep_weights rep_weights; std::atomic cemented_count{ 0 }; std::atomic block_count{ 0 }; diff --git a/nano/secure/rep_weights.cpp b/nano/secure/rep_weights.cpp index dd69bbd65b..c645bb1e01 100644 --- a/nano/secure/rep_weights.cpp +++ b/nano/secure/rep_weights.cpp @@ -1,30 +1,42 @@ #include #include +#include -void nano::rep_weights::representation_add (nano::account const & source_rep_a, nano::uint128_t const & amount_a) +nano::rep_weights::rep_weights (nano::store::rep_weight & rep_weight_store_a) : + rep_weight_store{ rep_weight_store_a } { +} + +void nano::rep_weights::representation_add (store::write_transaction const & txn_a, nano::account const & source_rep_a, nano::uint128_t const & amount_a) +{ + auto weight{ rep_weight_store.get (txn_a, source_rep_a) }; + weight += amount_a; nano::lock_guard guard (mutex); - auto source_previous (get (source_rep_a)); - put (source_rep_a, source_previous + amount_a); + rep_weight_store.put (txn_a, source_rep_a, weight); + put (source_rep_a, weight); } -void nano::rep_weights::representation_add_dual (nano::account const & source_rep_1, nano::uint128_t const & amount_1, nano::account const & source_rep_2, nano::uint128_t const & amount_2) +void nano::rep_weights::representation_add_dual (store::write_transaction const & txn_a, nano::account const & source_rep_1, nano::uint128_t const & amount_1, nano::account const & source_rep_2, nano::uint128_t const & amount_2) { if (source_rep_1 != source_rep_2) { + auto rep_1_weight{ rep_weight_store.get (txn_a, source_rep_1) }; + auto rep_2_weight{ rep_weight_store.get (txn_a, source_rep_2) }; + rep_1_weight += amount_1; + rep_2_weight += amount_2; + rep_weight_store.put (txn_a, source_rep_1, rep_1_weight); + rep_weight_store.put (txn_a, source_rep_2, rep_2_weight); nano::lock_guard guard (mutex); - auto source_previous_1 (get (source_rep_1)); - put (source_rep_1, source_previous_1 + amount_1); - auto source_previous_2 (get (source_rep_2)); - put (source_rep_2, source_previous_2 + amount_2); + put (source_rep_1, rep_1_weight); + put (source_rep_2, rep_2_weight); } else { - representation_add (source_rep_1, amount_1 + amount_2); + representation_add (txn_a, source_rep_1, amount_1 + amount_2); } } -void nano::rep_weights::representation_put (nano::account const & account_a, nano::uint128_union const & representation_a) +void nano::rep_weights::representation_put (nano::account const & account_a, nano::uint128_t const & representation_a) { nano::lock_guard guard (mutex); put (account_a, representation_a); diff --git a/nano/secure/rep_weights.hpp b/nano/secure/rep_weights.hpp index e7716ee3b2..7ee057146e 100644 --- a/nano/secure/rep_weights.hpp +++ b/nano/secure/rep_weights.hpp @@ -12,21 +12,26 @@ namespace nano namespace store { class component; + class rep_weight; + class write_transaction; } class rep_weights { public: - void representation_add (nano::account const & source_rep_a, nano::uint128_t const & amount_a); - void representation_add_dual (nano::account const & source_rep_1, nano::uint128_t const & amount_1, nano::account const & source_rep_2, nano::uint128_t const & amount_2); + explicit rep_weights (nano::store::rep_weight & rep_weight_store_a); + void representation_add (store::write_transaction const & txn_a, nano::account const & source_rep_a, nano::uint128_t const & amount_a); + void representation_add_dual (store::write_transaction const & txn_a, nano::account const & source_rep_1, nano::uint128_t const & amount_1, nano::account const & source_rep_2, nano::uint128_t const & amount_2); nano::uint128_t representation_get (nano::account const & account_a) const; - void representation_put (nano::account const & account_a, nano::uint128_union const & representation_a); + /* Only use this method when loading rep weights from the database table */ + void representation_put (nano::account const & account_a, nano::uint128_t const & representation_a); std::unordered_map get_rep_amounts () const; void copy_from (rep_weights & other_a); private: mutable nano::mutex mutex; std::unordered_map rep_amounts; + nano::store::rep_weight & rep_weight_store; void put (nano::account const & account_a, nano::uint128_union const & representation_a); nano::uint128_t get (nano::account const & account_a) const; diff --git a/nano/store/component.cpp b/nano/store/component.cpp index 9e4b7e9dbc..bb6c78d510 100644 --- a/nano/store/component.cpp +++ b/nano/store/component.cpp @@ -39,6 +39,7 @@ void nano::store::component::initialize (store::write_transaction const & transa ledger_cache_a.final_votes_confirmation_canary = (constants.final_votes_canary_account == constants.genesis->account () && 1 >= constants.final_votes_canary_height); account.put (transaction_a, constants.genesis->account (), { hash_l, constants.genesis->account (), constants.genesis->hash (), std::numeric_limits::max (), nano::seconds_since_epoch (), 1, nano::epoch::epoch_0 }); ++ledger_cache_a.account_count; + rep_weight.put (transaction_a, constants.genesis->account (), std::numeric_limits::max ()); ledger_cache_a.rep_weights.representation_put (constants.genesis->account (), std::numeric_limits::max ()); frontier.put (transaction_a, hash_l, constants.genesis->account ()); } From 9f0157699bdecd01197785805e97307b757102cb Mon Sep 17 00:00:00 2001 From: Gustav Schauwecker Date: Tue, 12 Mar 2024 11:12:08 +0100 Subject: [PATCH 04/10] Extend ledger::migrate_lmdb_to_rocks_db() to copy rep_weights --- nano/secure/ledger.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/nano/secure/ledger.cpp b/nano/secure/ledger.cpp index d22a7a1242..7d031e2e7c 100644 --- a/nano/secure/ledger.cpp +++ b/nano/secure/ledger.cpp @@ -1445,6 +1445,15 @@ bool nano::ledger::migrate_lmdb_to_rocksdb (std::filesystem::path const & data_p } }); + store.rep_weight.for_each_par ( + [&rocksdb_store] (store::read_transaction const & /*unused*/, auto i, auto n) { + for (; i != n; ++i) + { + auto rocksdb_transaction (rocksdb_store->tx_begin_write ({}, { nano::tables::rep_weights })); + rocksdb_store->rep_weight.put (rocksdb_transaction, i->first, i->second.number ()); + } + }); + store.frontier.for_each_par ( [&rocksdb_store] (store::read_transaction const & /*unused*/, auto i, auto n) { for (; i != n; ++i) From 69f147991c7b6c336a4df93336fe8dfb650a157b Mon Sep 17 00:00:00 2001 From: Gustav Schauwecker Date: Tue, 12 Mar 2024 13:07:51 +0100 Subject: [PATCH 05/10] Delete reps with weight 0 from rep_weight table and cache --- nano/core_test/ledger.cpp | 20 ++++++++++ nano/secure/rep_weights.cpp | 77 ++++++++++++++++++++++++++----------- nano/secure/rep_weights.hpp | 5 ++- 3 files changed, 78 insertions(+), 24 deletions(-) diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index e688ccff6f..f6aecb4c87 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -668,6 +668,26 @@ TEST (ledger, representation_changes) ASSERT_EQ (2, rep_weights.representation_get (key1.pub)); } +TEST (ledger, delete_rep_weight_of_zero) +{ + auto store{ nano::test::make_store () }; + nano::rep_weights rep_weights{ store->rep_weight }; + auto txn{ store->tx_begin_write () }; + rep_weights.representation_add (txn, 1, 100); + rep_weights.representation_add_dual (txn, 2, 100, 3, 100); + ASSERT_EQ (3, rep_weights.size ()); + ASSERT_EQ (3, store->rep_weight.count (txn)); + + // set rep weights to 0 + rep_weights.representation_add (txn, 1, std::numeric_limits::max () - 99); + ASSERT_EQ (2, rep_weights.size ()); + ASSERT_EQ (2, store->rep_weight.count (txn)); + + rep_weights.representation_add_dual (txn, 2, std::numeric_limits::max () - 99, 3, std::numeric_limits::max () - 99); + ASSERT_EQ (0, rep_weights.size ()); + ASSERT_EQ (0, store->rep_weight.count (txn)); +} + TEST (ledger, representation) { auto ctx = nano::test::context::ledger_empty (); diff --git a/nano/secure/rep_weights.cpp b/nano/secure/rep_weights.cpp index c645bb1e01..29a10d9cff 100644 --- a/nano/secure/rep_weights.cpp +++ b/nano/secure/rep_weights.cpp @@ -7,39 +7,39 @@ nano::rep_weights::rep_weights (nano::store::rep_weight & rep_weight_store_a) : { } -void nano::rep_weights::representation_add (store::write_transaction const & txn_a, nano::account const & source_rep_a, nano::uint128_t const & amount_a) +void nano::rep_weights::representation_add (store::write_transaction const & txn_a, nano::account const & rep_a, nano::uint128_t const & amount_a) { - auto weight{ rep_weight_store.get (txn_a, source_rep_a) }; - weight += amount_a; + auto previous_weight{ rep_weight_store.get (txn_a, rep_a) }; + auto new_weight = previous_weight + amount_a; + put_store (txn_a, rep_a, previous_weight, new_weight); nano::lock_guard guard (mutex); - rep_weight_store.put (txn_a, source_rep_a, weight); - put (source_rep_a, weight); + put_cache (rep_a, new_weight); } -void nano::rep_weights::representation_add_dual (store::write_transaction const & txn_a, nano::account const & source_rep_1, nano::uint128_t const & amount_1, nano::account const & source_rep_2, nano::uint128_t const & amount_2) +void nano::rep_weights::representation_add_dual (store::write_transaction const & txn_a, nano::account const & rep_1, nano::uint128_t const & amount_1, nano::account const & rep_2, nano::uint128_t const & amount_2) { - if (source_rep_1 != source_rep_2) + if (rep_1 != rep_2) { - auto rep_1_weight{ rep_weight_store.get (txn_a, source_rep_1) }; - auto rep_2_weight{ rep_weight_store.get (txn_a, source_rep_2) }; - rep_1_weight += amount_1; - rep_2_weight += amount_2; - rep_weight_store.put (txn_a, source_rep_1, rep_1_weight); - rep_weight_store.put (txn_a, source_rep_2, rep_2_weight); + auto previous_weight_1{ rep_weight_store.get (txn_a, rep_1) }; + auto previous_weight_2{ rep_weight_store.get (txn_a, rep_2) }; + auto new_weight_1 = previous_weight_1 + amount_1; + auto new_weight_2 = previous_weight_2 + amount_2; + put_store (txn_a, rep_1, previous_weight_1, new_weight_1); + put_store (txn_a, rep_2, previous_weight_2, new_weight_2); nano::lock_guard guard (mutex); - put (source_rep_1, rep_1_weight); - put (source_rep_2, rep_2_weight); + put_cache (rep_1, new_weight_1); + put_cache (rep_2, new_weight_2); } else { - representation_add (txn_a, source_rep_1, amount_1 + amount_2); + representation_add (txn_a, rep_1, amount_1 + amount_2); } } void nano::rep_weights::representation_put (nano::account const & account_a, nano::uint128_t const & representation_a) { nano::lock_guard guard (mutex); - put (account_a, representation_a); + put_cache (account_a, representation_a); } nano::uint128_t nano::rep_weights::representation_get (nano::account const & account_a) const @@ -62,21 +62,46 @@ void nano::rep_weights::copy_from (nano::rep_weights & other_a) for (auto const & entry : other_a.rep_amounts) { auto prev_amount (get (entry.first)); - put (entry.first, prev_amount + entry.second); + put_cache (entry.first, prev_amount + entry.second); } } -void nano::rep_weights::put (nano::account const & account_a, nano::uint128_union const & representation_a) +void nano::rep_weights::put_cache (nano::account const & account_a, nano::uint128_union const & representation_a) { auto it = rep_amounts.find (account_a); - auto amount = representation_a.number (); - if (it != rep_amounts.end ()) + if (representation_a.is_zero ()) { - it->second = amount; + if (it != rep_amounts.end ()) + { + rep_amounts.erase (it); + } } else { - rep_amounts.emplace (account_a, amount); + auto amount = representation_a.number (); + if (it != rep_amounts.end ()) + { + it->second = amount; + } + else + { + rep_amounts.emplace (account_a, amount); + } + } +} + +void nano::rep_weights::put_store (store::write_transaction const & txn_a, nano::account const & rep_a, nano::uint128_t const & previous_weight_a, nano::uint128_t const & new_weight_a) +{ + if (new_weight_a.is_zero ()) + { + if (!previous_weight_a.is_zero ()) + { + rep_weight_store.del (txn_a, rep_a); + } + } + else + { + rep_weight_store.put (txn_a, rep_a, new_weight_a); } } @@ -93,6 +118,12 @@ nano::uint128_t nano::rep_weights::get (nano::account const & account_a) const } } +std::size_t nano::rep_weights::size () const +{ + nano::lock_guard guard (mutex); + return rep_amounts.size (); +} + std::unique_ptr nano::collect_container_info (nano::rep_weights const & rep_weights, std::string const & name) { size_t rep_amounts_count; diff --git a/nano/secure/rep_weights.hpp b/nano/secure/rep_weights.hpp index 7ee057146e..52fb0013f2 100644 --- a/nano/secure/rep_weights.hpp +++ b/nano/secure/rep_weights.hpp @@ -26,13 +26,16 @@ class rep_weights /* Only use this method when loading rep weights from the database table */ void representation_put (nano::account const & account_a, nano::uint128_t const & representation_a); std::unordered_map get_rep_amounts () const; + /* Only use this method when loading rep weights from the database table */ void copy_from (rep_weights & other_a); + size_t size () const; private: mutable nano::mutex mutex; std::unordered_map rep_amounts; nano::store::rep_weight & rep_weight_store; - void put (nano::account const & account_a, nano::uint128_union const & representation_a); + void put_cache (nano::account const & account_a, nano::uint128_union const & representation_a); + void put_store (store::write_transaction const & txn_a, nano::account const & rep_a, nano::uint128_t const & previous_weight_a, nano::uint128_t const & new_weight_a); nano::uint128_t get (nano::account const & account_a) const; friend std::unique_ptr collect_container_info (rep_weights const &, std::string const &); From f99ba3e852e4791f5c13e07f91262de7f44591c1 Mon Sep 17 00:00:00 2001 From: Gustav Schauwecker Date: Tue, 12 Mar 2024 14:49:45 +0100 Subject: [PATCH 06/10] Add missing RocksDB table locks for rep_weights table --- nano/node/blockprocessor.cpp | 2 +- nano/node/node.cpp | 4 ++-- nano/test_common/testutil.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nano/node/blockprocessor.cpp b/nano/node/blockprocessor.cpp index 978f4f62f3..8541484da3 100644 --- a/nano/node/blockprocessor.cpp +++ b/nano/node/blockprocessor.cpp @@ -282,7 +282,7 @@ auto nano::block_processor::process_batch (nano::unique_lock & lock processed_batch_t processed; auto scoped_write_guard = write_database_queue.wait (nano::writer::process_batch); - auto transaction (node.store.tx_begin_write ({ tables::accounts, tables::blocks, tables::frontiers, tables::pending })); + auto transaction (node.store.tx_begin_write ({ tables::accounts, tables::blocks, tables::frontiers, tables::pending, tables::rep_weights })); nano::timer timer_l; lock_a.lock (); diff --git a/nano/node/node.cpp b/nano/node/node.cpp index 054e3669f7..aa1b11b77e 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -354,7 +354,7 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons if (!is_initialized && !flags.read_only) { - auto const transaction (store.tx_begin_write ({ tables::accounts, tables::blocks, tables::confirmation_height, tables::frontiers })); + auto const transaction (store.tx_begin_write ({ tables::accounts, tables::blocks, tables::confirmation_height, tables::frontiers, tables::rep_weights })); // Store was empty meaning we just created it, add the genesis block store.initialize (transaction, ledger.cache, ledger.constants); } @@ -558,7 +558,7 @@ void nano::node::process_active (std::shared_ptr const & incoming) nano::block_status nano::node::process (std::shared_ptr block) { - auto const transaction = store.tx_begin_write ({ tables::accounts, tables::blocks, tables::frontiers, tables::pending }); + auto const transaction = store.tx_begin_write ({ tables::accounts, tables::blocks, tables::frontiers, tables::pending, tables::rep_weights }); return process (transaction, block); } diff --git a/nano/test_common/testutil.cpp b/nano/test_common/testutil.cpp index ce80cfeae0..7cd682220b 100644 --- a/nano/test_common/testutil.cpp +++ b/nano/test_common/testutil.cpp @@ -63,7 +63,7 @@ nano::account nano::test::random_account () bool nano::test::process (nano::node & node, std::vector> blocks) { - auto const transaction = node.store.tx_begin_write ({ tables::accounts, tables::blocks, tables::frontiers, tables::pending }); + auto const transaction = node.store.tx_begin_write ({ tables::accounts, tables::blocks, tables::frontiers, tables::pending, tables::rep_weights }); for (auto & block : blocks) { auto result = node.process (transaction, block); From ef64ecb799d131ce5bd2532a2f809799234805a7 Mon Sep 17 00:00:00 2001 From: Gustav Schauwecker Date: Fri, 22 Mar 2024 13:56:25 +0100 Subject: [PATCH 07/10] Address issues from code review --- nano/core_test/ledger.cpp | 6 ++++-- nano/secure/account_info.hpp | 3 +-- nano/secure/ledger.cpp | 2 +- nano/secure/rep_weights.cpp | 8 ++++---- nano/secure/rep_weights.hpp | 5 +---- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index f6aecb4c87..df55af7c1d 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -1,3 +1,5 @@ +#include "nano/lib/numbers.hpp" + #include #include #include @@ -679,11 +681,11 @@ TEST (ledger, delete_rep_weight_of_zero) ASSERT_EQ (3, store->rep_weight.count (txn)); // set rep weights to 0 - rep_weights.representation_add (txn, 1, std::numeric_limits::max () - 99); + rep_weights.representation_add (txn, 1, nano::uint128_t{ 0 } - 100); ASSERT_EQ (2, rep_weights.size ()); ASSERT_EQ (2, store->rep_weight.count (txn)); - rep_weights.representation_add_dual (txn, 2, std::numeric_limits::max () - 99, 3, std::numeric_limits::max () - 99); + rep_weights.representation_add_dual (txn, 2, nano::uint128_t{ 0 } - 100, 3, nano::uint128_t{ 0 } - 100); ASSERT_EQ (0, rep_weights.size ()); ASSERT_EQ (0, store->rep_weight.count (txn)); } diff --git a/nano/secure/account_info.hpp b/nano/secure/account_info.hpp index bd7a7b0ccd..ee850d8d2f 100644 --- a/nano/secure/account_info.hpp +++ b/nano/secure/account_info.hpp @@ -31,8 +31,7 @@ class account_info final }; /** - * Account info as of DB version 22. - * This class protects the DB upgrades from future changes of the account_info class. + * This is a snapshot of the account_info table at v22 which needs to be read for the v22 to v23 upgrade */ class account_info_v22 final { diff --git a/nano/secure/ledger.cpp b/nano/secure/ledger.cpp index 7d031e2e7c..bf644f8220 100644 --- a/nano/secure/ledger.cpp +++ b/nano/secure/ledger.cpp @@ -1603,6 +1603,6 @@ std::unique_ptr nano::collect_container_info (le auto sizeof_element = sizeof (decltype (ledger.bootstrap_weights)::value_type); auto composite = std::make_unique (name); composite->add_component (std::make_unique (container_info{ "bootstrap_weights", count, sizeof_element })); - composite->add_component (collect_container_info (ledger.cache.rep_weights, "rep_weights")); + composite->add_component (ledger.cache.rep_weights.collect_container_info ("rep_weights")); return composite; } diff --git a/nano/secure/rep_weights.cpp b/nano/secure/rep_weights.cpp index 29a10d9cff..7be8915cfb 100644 --- a/nano/secure/rep_weights.cpp +++ b/nano/secure/rep_weights.cpp @@ -124,15 +124,15 @@ std::size_t nano::rep_weights::size () const return rep_amounts.size (); } -std::unique_ptr nano::collect_container_info (nano::rep_weights const & rep_weights, std::string const & name) +std::unique_ptr nano::rep_weights::collect_container_info (std::string const & name) { size_t rep_amounts_count; { - nano::lock_guard guard (rep_weights.mutex); - rep_amounts_count = rep_weights.rep_amounts.size (); + nano::lock_guard guard (mutex); + rep_amounts_count = rep_amounts.size (); } - auto sizeof_element = sizeof (decltype (rep_weights.rep_amounts)::value_type); + auto sizeof_element = sizeof (decltype (rep_amounts)::value_type); auto composite = std::make_unique (name); composite->add_component (std::make_unique (container_info{ "rep_amounts", rep_amounts_count, sizeof_element })); return composite; diff --git a/nano/secure/rep_weights.hpp b/nano/secure/rep_weights.hpp index 52fb0013f2..e29f4e0bac 100644 --- a/nano/secure/rep_weights.hpp +++ b/nano/secure/rep_weights.hpp @@ -29,6 +29,7 @@ class rep_weights /* Only use this method when loading rep weights from the database table */ void copy_from (rep_weights & other_a); size_t size () const; + std::unique_ptr collect_container_info (std::string const &); private: mutable nano::mutex mutex; @@ -37,9 +38,5 @@ class rep_weights void put_cache (nano::account const & account_a, nano::uint128_union const & representation_a); void put_store (store::write_transaction const & txn_a, nano::account const & rep_a, nano::uint128_t const & previous_weight_a, nano::uint128_t const & new_weight_a); nano::uint128_t get (nano::account const & account_a) const; - - friend std::unique_ptr collect_container_info (rep_weights const &, std::string const &); }; - -std::unique_ptr collect_container_info (rep_weights const &, std::string const &); } From dc783a79716682ee52bbc7050387d2b490970bbc Mon Sep 17 00:00:00 2001 From: Gustav Schauwecker Date: Tue, 12 Mar 2024 13:32:49 +0100 Subject: [PATCH 08/10] Add min weight to reps_cache --- nano/core_test/ledger.cpp | 30 ++++++++++++++++++++++++++++++ nano/secure/rep_weights.cpp | 8 +++++--- nano/secure/rep_weights.hpp | 3 ++- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index df55af7c1d..22e41d9de8 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -17,6 +17,8 @@ #include +#include + using namespace std::chrono_literals; // Init returns an error if it can't open files at the path @@ -690,6 +692,34 @@ TEST (ledger, delete_rep_weight_of_zero) ASSERT_EQ (0, store->rep_weight.count (txn)); } +TEST (ledger, rep_cache_min_weight) +{ + auto store{ nano::test::make_store () }; + nano::uint128_t min_weight{ 10 }; + nano::rep_weights rep_weights{ store->rep_weight, min_weight }; + auto txn{ store->tx_begin_write () }; + + // one below min weight + rep_weights.representation_add (txn, 1, 9); + ASSERT_EQ (0, rep_weights.size ()); + ASSERT_EQ (1, store->rep_weight.count (txn)); + + // exactly min weight + rep_weights.representation_add (txn, 1, 1); + ASSERT_EQ (1, rep_weights.size ()); + ASSERT_EQ (1, store->rep_weight.count (txn)); + + // above min weight + rep_weights.representation_add (txn, 1, 1); + ASSERT_EQ (1, rep_weights.size ()); + ASSERT_EQ (1, store->rep_weight.count (txn)); + + // fall blow min weight + rep_weights.representation_add (txn, 1, nano::uint128_t{ 0 } - 5); + ASSERT_EQ (0, rep_weights.size ()); + ASSERT_EQ (1, store->rep_weight.count (txn)); +} + TEST (ledger, representation) { auto ctx = nano::test::context::ledger_empty (); diff --git a/nano/secure/rep_weights.cpp b/nano/secure/rep_weights.cpp index 7be8915cfb..632ace73a2 100644 --- a/nano/secure/rep_weights.cpp +++ b/nano/secure/rep_weights.cpp @@ -1,9 +1,11 @@ +#include #include #include #include -nano::rep_weights::rep_weights (nano::store::rep_weight & rep_weight_store_a) : - rep_weight_store{ rep_weight_store_a } +nano::rep_weights::rep_weights (nano::store::rep_weight & rep_weight_store_a, nano::uint128_t min_weight_a) : + rep_weight_store{ rep_weight_store_a }, + min_weight{ min_weight_a } { } @@ -69,7 +71,7 @@ void nano::rep_weights::copy_from (nano::rep_weights & other_a) void nano::rep_weights::put_cache (nano::account const & account_a, nano::uint128_union const & representation_a) { auto it = rep_amounts.find (account_a); - if (representation_a.is_zero ()) + if (representation_a < min_weight || representation_a.is_zero ()) { if (it != rep_amounts.end ()) { diff --git a/nano/secure/rep_weights.hpp b/nano/secure/rep_weights.hpp index e29f4e0bac..214e22b8e6 100644 --- a/nano/secure/rep_weights.hpp +++ b/nano/secure/rep_weights.hpp @@ -19,7 +19,7 @@ namespace store class rep_weights { public: - explicit rep_weights (nano::store::rep_weight & rep_weight_store_a); + explicit rep_weights (nano::store::rep_weight & rep_weight_store_a, nano::uint128_t min_weight_a = 0); void representation_add (store::write_transaction const & txn_a, nano::account const & source_rep_a, nano::uint128_t const & amount_a); void representation_add_dual (store::write_transaction const & txn_a, nano::account const & source_rep_1, nano::uint128_t const & amount_1, nano::account const & source_rep_2, nano::uint128_t const & amount_2); nano::uint128_t representation_get (nano::account const & account_a) const; @@ -35,6 +35,7 @@ class rep_weights mutable nano::mutex mutex; std::unordered_map rep_amounts; nano::store::rep_weight & rep_weight_store; + nano::uint128_t min_weight; void put_cache (nano::account const & account_a, nano::uint128_union const & representation_a); void put_store (store::write_transaction const & txn_a, nano::account const & rep_a, nano::uint128_t const & previous_weight_a, nano::uint128_t const & new_weight_a); nano::uint128_t get (nano::account const & account_a) const; From 5be0924c8242d12a83a04fd02edbf5c0592b5675 Mon Sep 17 00:00:00 2001 From: Gustav Schauwecker Date: Tue, 12 Mar 2024 14:19:30 +0100 Subject: [PATCH 09/10] Make minimum representative weight configurable --- nano/core_test/toml.cpp | 3 +++ nano/core_test/vote_processor.cpp | 4 ++++ nano/node/node.cpp | 2 +- nano/node/nodeconfig.cpp | 11 +++++++++++ nano/node/nodeconfig.hpp | 5 +++++ nano/secure/ledger.cpp | 4 ++-- nano/secure/ledger.hpp | 2 +- nano/secure/ledger_cache.cpp | 4 ++-- nano/secure/ledger_cache.hpp | 3 ++- nano/test_common/system.cpp | 1 + 10 files changed, 32 insertions(+), 7 deletions(-) diff --git a/nano/core_test/toml.cpp b/nano/core_test/toml.cpp index 9e2a5cbe83..7ea1846f2c 100644 --- a/nano/core_test/toml.cpp +++ b/nano/core_test/toml.cpp @@ -175,6 +175,7 @@ TEST (toml, daemon_config_deserialize_defaults) ASSERT_EQ (conf.node.background_threads, defaults.node.background_threads); ASSERT_EQ (conf.node.secondary_work_peers, defaults.node.secondary_work_peers); ASSERT_EQ (conf.node.online_weight_minimum, defaults.node.online_weight_minimum); + ASSERT_EQ (conf.node.representative_vote_weight_minimum, defaults.node.representative_vote_weight_minimum); ASSERT_EQ (conf.node.rep_crawler_weight_minimum, defaults.node.rep_crawler_weight_minimum); ASSERT_EQ (conf.node.password_fanout, defaults.node.password_fanout); ASSERT_EQ (conf.node.peering_port, defaults.node.peering_port); @@ -404,6 +405,7 @@ TEST (toml, daemon_config_deserialize_no_defaults) network_threads = 999 background_threads = 999 online_weight_minimum = "999" + representative_vote_weight_minimum = "999" rep_crawler_weight_minimum = "999" password_fanout = 999 peering_port = 999 @@ -597,6 +599,7 @@ TEST (toml, daemon_config_deserialize_no_defaults) ASSERT_NE (conf.node.max_pruning_age, defaults.node.max_pruning_age); ASSERT_NE (conf.node.max_pruning_depth, defaults.node.max_pruning_depth); ASSERT_NE (conf.node.online_weight_minimum, defaults.node.online_weight_minimum); + ASSERT_NE (conf.node.representative_vote_weight_minimum, defaults.node.representative_vote_weight_minimum); ASSERT_NE (conf.node.rep_crawler_weight_minimum, defaults.node.rep_crawler_weight_minimum); ASSERT_NE (conf.node.password_fanout, defaults.node.password_fanout); ASSERT_NE (conf.node.peering_port, defaults.node.peering_port); diff --git a/nano/core_test/vote_processor.cpp b/nano/core_test/vote_processor.cpp index f755eb8ac0..4da56adc2c 100644 --- a/nano/core_test/vote_processor.cpp +++ b/nano/core_test/vote_processor.cpp @@ -176,8 +176,10 @@ TEST (vote_processor, no_broadcast_local) nano::node_flags flags; flags.disable_request_loop = true; nano::node_config config1, config2; + config1.representative_vote_weight_minimum = 0; config1.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto & node (*system.add_node (config1, flags)); + config2.representative_vote_weight_minimum = 0; config2.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; config2.peering_port = system.get_available_port (); system.add_node (config2, flags); @@ -229,8 +231,10 @@ TEST (vote_processor, local_broadcast_without_a_representative) nano::node_flags flags; flags.disable_request_loop = true; nano::node_config config1, config2; + config1.representative_vote_weight_minimum = 0; config1.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; auto & node (*system.add_node (config1, flags)); + config2.representative_vote_weight_minimum = 0; config2.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled; config2.peering_port = system.get_available_port (); system.add_node (config2, flags); diff --git a/nano/node/node.cpp b/nano/node/node.cpp index aa1b11b77e..8c0ca258b9 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -144,7 +144,7 @@ nano::node::node (boost::asio::io_context & io_ctx_a, std::filesystem::path cons unchecked{ config.max_unchecked_blocks, stats, flags.disable_block_processor_unchecked_deletion }, wallets_store_impl (std::make_unique (application_path_a / "wallets.ldb", config_a.lmdb_config)), wallets_store (*wallets_store_impl), - ledger_impl{ std::make_unique (store, stats, network_params.ledger, flags_a.generate_cache) }, + ledger_impl{ std::make_unique (store, stats, network_params.ledger, flags_a.generate_cache, config_a.representative_vote_weight_minimum.number ()) }, ledger{ *ledger_impl }, outbound_limiter{ outbound_bandwidth_limiter_config (config) }, // empty `config.peering_port` means the user made no port choice at all; diff --git a/nano/node/nodeconfig.cpp b/nano/node/nodeconfig.cpp index 16f3c897b8..c240c583c1 100644 --- a/nano/node/nodeconfig.cpp +++ b/nano/node/nodeconfig.cpp @@ -91,6 +91,7 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const toml.put ("bootstrap_fraction_numerator", bootstrap_fraction_numerator, "Change bootstrap threshold (online stake / 256 * bootstrap_fraction_numerator).\ntype:uint32"); toml.put ("receive_minimum", receive_minimum.to_string_dec (), "Minimum receive amount. Only affects node wallets. A large amount is recommended to avoid automatic work generation for tiny transactions.\ntype:string,amount,raw"); toml.put ("online_weight_minimum", online_weight_minimum.to_string_dec (), "When calculating online weight, the node is forced to assume at least this much voting weight is online, thus setting a floor for voting weight to confirm transactions at online_weight_minimum * \"quorum delta\".\ntype:string,amount,raw"); + toml.put ("representative_vote_weight_minimum", representative_vote_weight_minimum.to_string_dec (), "Minimum vote weight that a representative must have for its vote to be counted.\nAll representatives above this weight will be kept in memory!\ntype:string,amount,raw"); toml.put ("password_fanout", password_fanout, "Password fanout factor.\ntype:uint64"); toml.put ("io_threads", io_threads, "Number of threads dedicated to I/O operations. Defaults to the number of CPU threads, and at least 4.\ntype:uint64"); toml.put ("network_threads", network_threads, "Number of threads dedicated to processing network messages. Defaults to the number of CPU threads, and at least 4.\ntype:uint64"); @@ -340,6 +341,16 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml) toml.get_error ().set ("online_weight_minimum contains an invalid decimal amount"); } + auto representative_vote_weight_minimum_l{ representative_vote_weight_minimum.to_string_dec () }; + if (toml.has_key ("representative_vote_weight_minimum")) + { + representative_vote_weight_minimum_l = toml.get ("representative_vote_weight_minimum"); + } + if (representative_vote_weight_minimum.decode_dec (representative_vote_weight_minimum_l)) + { + toml.get_error ().set ("representative_vote_weight_minimum contains an invalid decimal amount"); + } + auto vote_minimum_l (vote_minimum.to_string_dec ()); if (toml.has_key ("vote_minimum")) { diff --git a/nano/node/nodeconfig.hpp b/nano/node/nodeconfig.hpp index cf778df4ee..b93611aca0 100644 --- a/nano/node/nodeconfig.hpp +++ b/nano/node/nodeconfig.hpp @@ -64,6 +64,11 @@ class node_config std::chrono::milliseconds vote_generator_delay{ std::chrono::milliseconds (100) }; unsigned vote_generator_threshold{ 3 }; nano::amount online_weight_minimum{ 60000 * nano::Gxrb_ratio }; + /* + * The minimum vote weight that a representative must have for its vote to be counted. + * All representatives above this weight will be kept in memory! + */ + nano::amount representative_vote_weight_minimum{ 10 * nano::Mxrb_ratio }; unsigned password_fanout{ 1024 }; unsigned io_threads{ std::max (4u, nano::hardware_concurrency ()) }; unsigned network_threads{ std::max (4u, nano::hardware_concurrency ()) }; diff --git a/nano/secure/ledger.cpp b/nano/secure/ledger.cpp index bf644f8220..643e47bc06 100644 --- a/nano/secure/ledger.cpp +++ b/nano/secure/ledger.cpp @@ -749,10 +749,10 @@ void representative_visitor::state_block (nano::state_block const & block_a) } } // namespace -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::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 }, + cache{ store_a.rep_weight, min_rep_weight_a }, stats{ stat_a }, check_bootstrap_weights{ true } { diff --git a/nano/secure/ledger.hpp b/nano/secure/ledger.hpp index 6c325a0296..6293ac1b62 100644 --- a/nano/secure/ledger.hpp +++ b/nano/secure/ledger.hpp @@ -40,7 +40,7 @@ class ledger final friend class receivable_iterator; public: - ledger (nano::store::component &, nano::stats &, nano::ledger_constants & constants, nano::generate_cache_flags const & = nano::generate_cache_flags{}); + ledger (nano::store::component &, nano::stats &, nano::ledger_constants & constants, nano::generate_cache_flags const & = nano::generate_cache_flags{}, nano::uint128_t min_rep_weight_a = 0); /** * Returns the account for a given hash * Returns std::nullopt if the block doesn't exist or has been pruned diff --git a/nano/secure/ledger_cache.cpp b/nano/secure/ledger_cache.cpp index 5076e1cc18..16c46c0f5e 100644 --- a/nano/secure/ledger_cache.cpp +++ b/nano/secure/ledger_cache.cpp @@ -1,6 +1,6 @@ #include -nano::ledger_cache::ledger_cache (nano::store::rep_weight & rep_weight_store_a) : - rep_weights{ rep_weight_store_a } +nano::ledger_cache::ledger_cache (nano::store::rep_weight & rep_weight_store_a, nano::uint128_t min_rep_weight_a) : + rep_weights{ rep_weight_store_a, min_rep_weight_a } { } diff --git a/nano/secure/ledger_cache.hpp b/nano/secure/ledger_cache.hpp index 34b86cb639..12ebc9af22 100644 --- a/nano/secure/ledger_cache.hpp +++ b/nano/secure/ledger_cache.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -11,7 +12,7 @@ namespace nano class ledger_cache { public: - explicit ledger_cache (nano::store::rep_weight & rep_weight_store_a); + explicit ledger_cache (nano::store::rep_weight & rep_weight_store_a, nano::uint128_t min_rep_weight_a = 0); nano::rep_weights rep_weights; std::atomic cemented_count{ 0 }; std::atomic block_count{ 0 }; diff --git a/nano/test_common/system.cpp b/nano/test_common/system.cpp index f4522c62b3..334f77b4e9 100644 --- a/nano/test_common/system.cpp +++ b/nano/test_common/system.cpp @@ -579,6 +579,7 @@ void nano::test::system::stop () nano::node_config nano::test::system::default_config () { nano::node_config config{ get_available_port () }; + config.representative_vote_weight_minimum = 0; return config; } From b6ec7731480e67af9f082bd4f329b57c97b206fc Mon Sep 17 00:00:00 2001 From: Gustav Schauwecker Date: Fri, 15 Mar 2024 08:43:39 +0100 Subject: [PATCH 10/10] Use exact vote weight in certain RPC calls and wallets code --- nano/node/json_handler.cpp | 8 ++++---- nano/node/node.cpp | 3 ++- nano/node/wallet.cpp | 9 +++++++-- nano/secure/ledger.cpp | 5 +++++ nano/secure/ledger.hpp | 7 +++++++ 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/nano/node/json_handler.cpp b/nano/node/json_handler.cpp index 1d98e73cb9..0624c17820 100644 --- a/nano/node/json_handler.cpp +++ b/nano/node/json_handler.cpp @@ -698,7 +698,7 @@ void nano::json_handler::account_info () } if (weight) { - auto account_weight (node.ledger.weight (account)); + auto account_weight (node.ledger.weight_exact (transaction, account)); response_l.put ("weight", account_weight.convert_to ()); } if (receivable) @@ -2784,7 +2784,7 @@ void nano::json_handler::ledger () } if (weight) { - auto account_weight (node.ledger.weight (account)); + auto account_weight (node.ledger.weight_exact (transaction, account)); response_a.put ("weight", account_weight.convert_to ()); } accounts.push_back (std::make_pair (account.to_account (), response_a)); @@ -2837,7 +2837,7 @@ void nano::json_handler::ledger () } if (weight) { - auto account_weight (node.ledger.weight (account)); + auto account_weight (node.ledger.weight_exact (transaction, account)); response_a.put ("weight", account_weight.convert_to ()); } accounts.push_back (std::make_pair (account.to_account (), response_a)); @@ -4716,7 +4716,7 @@ void nano::json_handler::wallet_ledger () } if (weight) { - auto account_weight (node.ledger.weight (account)); + auto account_weight (node.ledger.weight_exact (block_transaction, account)); entry.put ("weight", account_weight.convert_to ()); } if (receivable) diff --git a/nano/node/node.cpp b/nano/node/node.cpp index 8c0ca258b9..abbc2e180e 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -739,7 +739,8 @@ std::pair nano::node::balance_pending (nano::a nano::uint128_t nano::node::weight (nano::account const & account_a) { - return ledger.weight (account_a); + auto txn{ ledger.store.tx_begin_read () }; + return ledger.weight_exact (txn, account_a); } nano::uint128_t nano::node::minimum_principal_weight () diff --git a/nano/node/wallet.cpp b/nano/node/wallet.cpp index 864ca4f016..a160855dca 100644 --- a/nano/node/wallet.cpp +++ b/nano/node/wallet.cpp @@ -1537,6 +1537,7 @@ void nano::wallets::foreach_representative (std::function> action_accounts_l; { auto transaction_l (tx_begin_read ()); + auto ledger_txn{ node.ledger.store.tx_begin_read () }; nano::lock_guard lock{ mutex }; for (auto i (items.begin ()), n (items.end ()); i != n; ++i) { @@ -1551,7 +1552,7 @@ void nano::wallets::foreach_representative (std::function> & list_a) { diff --git a/nano/secure/ledger.hpp b/nano/secure/ledger.hpp index 6293ac1b62..ecd2a2627b 100644 --- a/nano/secure/ledger.hpp +++ b/nano/secure/ledger.hpp @@ -53,9 +53,16 @@ class ledger final bool block_exists (store::transaction const & transaction, nano::block_hash const & hash) const; nano::uint128_t account_balance (store::transaction const &, nano::account const &, bool = false); nano::uint128_t account_receivable (store::transaction const &, nano::account const &, bool = false); + /** + * Returns the cached vote weight for the given representative. + * If the weight is below the cache limit it returns 0. + * During bootstrap it returns the preconfigured bootstrap weights. + */ nano::uint128_t weight (nano::account const &); std::optional successor (store::transaction const &, nano::qualified_root const &) const noexcept; std::optional successor (store::transaction const & transaction, nano::block_hash const & hash) const noexcept; + /* Returns the exact vote weight for the given representative by doing a database lookup */ + nano::uint128_t weight_exact (store::transaction const &, nano::account const &); std::shared_ptr forked_block (store::transaction const &, nano::block const &); std::shared_ptr head_block (store::transaction const &, nano::account const &); bool block_confirmed (store::transaction const &, nano::block_hash const &) const;