Skip to content

Commit

Permalink
Add ledger account iterator for the unconfirmed ledger set.
Browse files Browse the repository at this point in the history
  • Loading branch information
clemahieu committed Apr 16, 2024
1 parent 99e2bed commit 69c7913
Show file tree
Hide file tree
Showing 17 changed files with 170 additions and 33 deletions.
6 changes: 3 additions & 3 deletions nano/core_test/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ TEST (system, DISABLED_generate_send_new)
system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv);
{
auto transaction (node1.store.tx_begin_read ());
auto iterator1 (node1.store.account.begin (transaction));
ASSERT_NE (node1.store.account.end (), iterator1);
auto iterator1 (node1.ledger.any.account_begin (transaction));
ASSERT_NE (node1.ledger.any.account_end (), iterator1);
++iterator1;
ASSERT_EQ (node1.store.account.end (), iterator1);
ASSERT_EQ (node1.ledger.any.account_end (), iterator1);
}
nano::keypair stake_preserver;
auto send_block (system.wallet (0)->send_action (nano::dev::genesis_key.pub, stake_preserver.pub, nano::dev::constants.genesis_amount / 3 * 2, true));
Expand Down
6 changes: 3 additions & 3 deletions nano/nano_node/entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ int main (int argc, char * const * argv)
// Cache the account heads to make searching quicker against unchecked keys.
auto transaction (node->store.tx_begin_read ());
std::unordered_set<nano::block_hash> frontier_hashes;
for (auto i (node->store.account.begin (transaction)), n (node->store.account.end ()); i != n; ++i)
for (auto i (node->ledger.any.account_begin (transaction)), n (node->ledger.any.account_end ()); i != n; ++i)
{
frontier_hashes.insert (i->second.head);
}
Expand Down Expand Up @@ -1629,7 +1629,7 @@ int main (int argc, char * const * argv)
}
size_t const accounts_deque_overflow (32 * 1024);
auto transaction (node->store.tx_begin_read ());
for (auto i (node->store.account.begin (transaction)), n (node->store.account.end ()); i != n; ++i)
for (auto i (node->ledger.any.account_begin (transaction)), n (node->ledger.any.account_end ()); i != n; ++i)
{
{
nano::unique_lock<nano::mutex> lock{ mutex };
Expand Down Expand Up @@ -1797,7 +1797,7 @@ int main (int argc, char * const * argv)
auto transaction (source_node->store.tx_begin_read ());
block_count = source_node->ledger.block_count ();
std::cout << boost::str (boost::format ("Performing bootstrap emulation, %1% blocks in ledger...") % block_count) << std::endl;
for (auto i (source_node->store.account.begin (transaction)), n (source_node->store.account.end ()); i != n; ++i)
for (auto i (source_node->ledger.any.account_begin (transaction)), n (source_node->ledger.any.account_end ()); i != n; ++i)
{
nano::account const & account (i->first);
nano::account_info const & info (i->second);
Expand Down
4 changes: 2 additions & 2 deletions nano/node/bootstrap/bootstrap_frontier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ void nano::frontier_req_client::next ()
{
std::size_t max_size (128);
auto transaction (node->store.tx_begin_read ());
for (auto i (node->store.account.begin (transaction, current.number () + 1)), n (node->store.account.end ()); i != n && accounts.size () != max_size; ++i)
for (auto i (node->ledger.any.account_upper_bound (transaction, current.number ())), n (node->ledger.any.account_end ()); i != n && accounts.size () != max_size; ++i)
{
nano::account_info const & info (i->second);
nano::account const & account (i->first);
Expand Down Expand Up @@ -380,7 +380,7 @@ void nano::frontier_req_server::next ()
auto transaction (node->store.tx_begin_read ());
if (!send_confirmed ())
{
for (auto i (node->store.account.begin (transaction, current.number () + 1)), n (node->store.account.end ()); i != n && accounts.size () != max_size; ++i)
for (auto i (node->ledger.any.account_upper_bound (transaction, current.number ())), n (node->ledger.any.account_end ()); i != n && accounts.size () != max_size; ++i)
{
nano::account_info const & info (i->second);
if (disable_age_filter || (now - info.modified) <= request->age)
Expand Down
2 changes: 1 addition & 1 deletion nano/node/bootstrap/bootstrap_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ nano::asc_pull_ack nano::bootstrap_server::process (const store::transaction & t

nano::asc_pull_ack::frontiers_payload response_payload{};

for (auto it = store.account.begin (transaction, request.start), end = store.account.end (); it != end && response_payload.frontiers.size () < request.count; ++it)
for (auto it = ledger.any.account_lower_bound (transaction, request.start), end = ledger.any.account_end (); it != end && response_payload.frontiers.size () < request.count; ++it)
{
response_payload.frontiers.emplace_back (it->first, it->second.head);
}
Expand Down
5 changes: 2 additions & 3 deletions nano/node/bootstrap_ascending/iterators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ void nano::bootstrap_ascending::database_iterator::next (store::transaction & tx
{
case table_type::account:
{
auto i = current.number () + 1;
auto item = ledger.store.account.begin (tx, i);
if (item != ledger.store.account.end ())
auto item = ledger.any.account_upper_bound (tx, current.number ());
if (item != ledger.any.account_end ())
{
current = item->first;
}
Expand Down
2 changes: 1 addition & 1 deletion nano/node/epoch_upgrader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ void nano::epoch_upgrader::upgrade_impl (nano::raw_key const & prv_a, nano::epoc
{
auto transaction (store.tx_begin_read ());
// Collect accounts to upgrade
for (auto i (store.account.begin (transaction)), n (store.account.end ()); i != n && accounts_list.size () < count_limit; ++i)
for (auto i (ledger.any.account_begin (transaction)), n (ledger.any.account_end ()); i != n && accounts_list.size () < count_limit; ++i)
{
nano::account const & account (i->first);
nano::account_info const & info (i->second);
Expand Down
10 changes: 5 additions & 5 deletions nano/node/json_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2256,7 +2256,7 @@ void nano::json_handler::delegators ()
{
auto transaction (node.store.tx_begin_read ());
boost::property_tree::ptree delegators;
for (auto i (node.store.account.begin (transaction, start_account.number () + 1)), n (node.store.account.end ()); i != n && delegators.size () < count; ++i)
for (auto i (node.ledger.any.account_upper_bound (transaction, start_account)), n (node.ledger.any.account_end ()); i != n && delegators.size () < count; ++i)
{
nano::account_info const & info (i->second);
if (info.representative == representative)
Expand All @@ -2282,7 +2282,7 @@ void nano::json_handler::delegators_count ()
{
uint64_t count (0);
auto transaction (node.store.tx_begin_read ());
for (auto i (node.store.account.begin (transaction)), n (node.store.account.end ()); i != n; ++i)
for (auto i (node.ledger.any.account_begin (transaction)), n (node.ledger.any.account_end ()); i != n; ++i)
{
nano::account_info const & info (i->second);
if (info.representative == account)
Expand Down Expand Up @@ -2393,7 +2393,7 @@ void nano::json_handler::frontiers ()
{
boost::property_tree::ptree frontiers;
auto transaction (node.store.tx_begin_read ());
for (auto i (node.store.account.begin (transaction, start)), n (node.store.account.end ()); i != n && frontiers.size () < count; ++i)
for (auto i (node.ledger.any.account_lower_bound (transaction, start)), n (node.ledger.any.account_end ()); i != n && frontiers.size () < count; ++i)
{
frontiers.put (i->first.to_account (), i->second.head.to_string ());
}
Expand Down Expand Up @@ -2794,7 +2794,7 @@ void nano::json_handler::ledger ()
auto transaction (node.store.tx_begin_read ());
if (!ec && !sorting) // Simple
{
for (auto i (node.store.account.begin (transaction, start)), n (node.store.account.end ()); i != n && accounts.size () < count; ++i)
for (auto i (node.ledger.any.account_lower_bound (transaction, start)), n (node.ledger.any.account_end ()); i != n && accounts.size () < count; ++i)
{
nano::account_info const & info (i->second);
if (info.modified >= modified_since && (receivable || info.balance.number () >= threshold.number ()))
Expand Down Expand Up @@ -2835,7 +2835,7 @@ void nano::json_handler::ledger ()
else if (!ec) // Sorting
{
std::vector<std::pair<nano::uint128_union, nano::account>> ledger_l;
for (auto i (node.store.account.begin (transaction, start)), n (node.store.account.end ()); i != n; ++i)
for (auto i (node.ledger.any.account_lower_bound (transaction, start)), n (node.ledger.any.account_end ()); i != n; ++i)
{
nano::account_info const & info (i->second);
nano::uint128_union balance (info.balance);
Expand Down
2 changes: 1 addition & 1 deletion nano/qt/qt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1972,7 +1972,7 @@ void nano_qt::advanced_actions::refresh_ledger ()
{
ledger_model->removeRows (0, ledger_model->rowCount ());
auto transaction (wallet.node.store.tx_begin_read ());
for (auto i (wallet.node.ledger.store.account.begin (transaction)), j (wallet.node.ledger.store.account.end ()); i != j; ++i)
for (auto i (wallet.node.ledger.any.account_begin (transaction)), j (wallet.node.ledger.any.account_end ()); i != j; ++i)
{
QList<QStandardItem *> items;
items.push_back (new QStandardItem (QString (i->first.to_account ().c_str ())));
Expand Down
12 changes: 6 additions & 6 deletions nano/rpc_test/rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6123,7 +6123,7 @@ TEST (rpc, epoch_upgrade)
{
auto transaction (node->store.tx_begin_read ());
ASSERT_EQ (2, node->store.account.count (transaction));
for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (); ++i)
for (auto i (node->ledger.any.account_begin (transaction)); i != node->ledger.any.account_end (); ++i)
{
nano::account_info info (i->second);
ASSERT_EQ (info.epoch (), nano::epoch::epoch_0);
Expand All @@ -6141,7 +6141,7 @@ TEST (rpc, epoch_upgrade)
{
auto transaction (node->store.tx_begin_read ());
ASSERT_EQ (4, node->store.account.count (transaction));
for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (); ++i)
for (auto i (node->ledger.any.account_begin (transaction)); i != node->ledger.any.account_end (); ++i)
{
nano::account_info info (i->second);
ASSERT_EQ (info.epoch (), nano::epoch::epoch_1);
Expand Down Expand Up @@ -6204,7 +6204,7 @@ TEST (rpc, epoch_upgrade)
{
auto transaction (node->store.tx_begin_read ());
ASSERT_EQ (5, node->store.account.count (transaction));
for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (); ++i)
for (auto i (node->ledger.any.account_begin (transaction)); i != node->ledger.any.account_end (); ++i)
{
nano::account_info info (i->second);
ASSERT_EQ (info.epoch (), nano::epoch::epoch_2);
Expand Down Expand Up @@ -6286,7 +6286,7 @@ TEST (rpc, epoch_upgrade_multithreaded)
{
auto transaction (node->store.tx_begin_read ());
ASSERT_EQ (2, node->store.account.count (transaction));
for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (); ++i)
for (auto i (node->ledger.any.account_begin (transaction)); i != node->ledger.any.account_end (); ++i)
{
nano::account_info info (i->second);
ASSERT_EQ (info.epoch (), nano::epoch::epoch_0);
Expand All @@ -6305,7 +6305,7 @@ TEST (rpc, epoch_upgrade_multithreaded)
{
auto transaction (node->store.tx_begin_read ());
ASSERT_EQ (4, node->store.account.count (transaction));
for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (); ++i)
for (auto i (node->ledger.any.account_begin (transaction)); i != node->ledger.any.account_end (); ++i)
{
nano::account_info info (i->second);
ASSERT_EQ (info.epoch (), nano::epoch::epoch_1);
Expand Down Expand Up @@ -6368,7 +6368,7 @@ TEST (rpc, epoch_upgrade_multithreaded)
{
auto transaction (node->store.tx_begin_read ());
ASSERT_EQ (5, node->store.account.count (transaction));
for (auto i (node->store.account.begin (transaction)); i != node->store.account.end (); ++i)
for (auto i (node->ledger.any.account_begin (transaction)); i != node->ledger.any.account_end (); ++i)
{
nano::account_info info (i->second);
ASSERT_EQ (info.epoch (), nano::epoch::epoch_2);
Expand Down
3 changes: 3 additions & 0 deletions nano/secure/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ add_library(
${CMAKE_BINARY_DIR}/bootstrap_weights_beta.cpp
account_info.hpp
account_info.cpp
account_iterator.cpp
account_iterator.hpp
account_iterator_impl.hpp
common.hpp
common.cpp
generate_cache_flags.hpp
Expand Down
4 changes: 4 additions & 0 deletions nano/secure/account_iterator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#include <nano/secure/account_iterator_impl.hpp>
#include <nano/secure/ledger_set_any.hpp>

template class nano::account_iterator<nano::ledger_set_any>;
43 changes: 43 additions & 0 deletions nano/secure/account_iterator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#pragma once
#include <nano/lib/numbers.hpp>
#include <nano/secure/account_info.hpp>

#include <optional>
#include <utility>

namespace nano::store
{
class transaction;
}

namespace nano
{
// This class iterates account entries
template <typename Set>
class account_iterator
{
public:
// Creates an end () iterator
// 'transaction' and 'set' are nullptr so all end () iterators compare equal
account_iterator ();
account_iterator (store::transaction const & transaction, Set const & set, std::optional<std::pair<nano::account, nano::account_info>> const & item);

// Compares if these iterators hold the same 'item'.
// Undefined behavior if this and other don't hold the same 'set' and 'transaction'
bool operator== (account_iterator const & other) const;

public: // Dereferencing, undefined behavior when called on an end () iterator
// Advances the iterator to the next greater nano::account
// If there are no more accounts, convert this to an end () iterator
account_iterator & operator++ ();
std::pair<nano::account, nano::account_info> const & operator* () const;
std::pair<nano::account, nano::account_info> const * operator->() const;

private:
store::transaction const * transaction;
Set const * set{ nullptr };
// Current item at the position of the iterator
// std::nullopt if an end () iterator
std::optional<std::pair<nano::account, nano::account_info>> item;
};
}
51 changes: 51 additions & 0 deletions nano/secure/account_iterator_impl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <nano/secure/account_info.hpp>
#include <nano/secure/account_iterator.hpp>

template <typename Set>
nano::account_iterator<Set>::account_iterator ()
{
}

template <typename Set>
nano::account_iterator<Set>::account_iterator (store::transaction const & transaction, Set const & set, std::optional<std::pair<nano::account, nano::account_info>> const & item) :
transaction{ &transaction },
set{ &set },
item{ item }
{
}

template <typename Set>
bool nano::account_iterator<Set>::operator== (account_iterator const & other) const
{
debug_assert (set == nullptr || other.set == nullptr || set == other.set);
return item == other.item;
}

// Iteration is performed by calling set->account_lower_bound (tx, next) where next is one higher than the current iterator
template <typename Set>
auto nano::account_iterator<Set>::operator++ () -> account_iterator<Set> &
{
auto next = item.value ().first.number () + 1;
if (next != 0)
{
*this = set->account_lower_bound (*transaction, next);
}
else
{
// Convert to and end iterator if there are no more items
*this = account_iterator<Set>{};
}
return *this;
}

template <typename Set>
std::pair<nano::account, nano::account_info> const & nano::account_iterator<Set>::operator* () const
{
return item.value ();
}

template <typename Set>
std::pair<nano::account, nano::account_info> const * nano::account_iterator<Set>::operator->() const
{
return &item.value ();
}
25 changes: 25 additions & 0 deletions nano/secure/ledger_set_any.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ std::optional<nano::uint128_t> nano::ledger_set_any::account_balance (store::tra
return block->balance ().number ();
}

auto nano::ledger_set_any::account_begin (store::transaction const & transaction) const -> account_iterator
{
return account_lower_bound (transaction, 0);
}

auto nano::ledger_set_any::account_end () const -> account_iterator
{
return account_iterator{};
}

std::optional<nano::account_info> nano::ledger_set_any::account_get (store::transaction const & transaction, nano::account const & account) const
{
return ledger.store.account.get (transaction, account);
Expand Down Expand Up @@ -47,6 +57,21 @@ uint64_t nano::ledger_set_any::account_height (store::transaction const & transa
return block->sideband ().height;
}

auto nano::ledger_set_any::account_lower_bound (store::transaction const & transaction, nano::account const & account) const -> account_iterator
{
auto disk = ledger.store.account.begin (transaction, account);
if (disk == ledger.store.account.end ())
{
return account_iterator{};
}
return account_iterator{ transaction, *this, *disk };
}

auto nano::ledger_set_any::account_upper_bound (store::transaction const & transaction, nano::account const & account) const -> account_iterator
{
return account_lower_bound (transaction, account.number () + 1);
}

std::optional<nano::account> nano::ledger_set_any::block_account (store::transaction const & transaction, nano::block_hash const & hash) const
{
auto block_l = block_get (transaction, hash);
Expand Down
12 changes: 12 additions & 0 deletions nano/secure/ledger_set_any.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <nano/secure/account_iterator.hpp>
#include <nano/secure/receivable_iterator.hpp>

#include <optional>
Expand All @@ -24,15 +25,25 @@ namespace nano
class ledger_set_any
{
public:
using account_iterator = nano::account_iterator<ledger_set_any>;
using receivable_iterator = nano::receivable_iterator<ledger_set_any>;

ledger_set_any (nano::ledger const & ledger);

public: // Operations on accounts
std::optional<nano::uint128_t> account_balance (store::transaction const & transaction, nano::account const & account) const;
account_iterator account_begin (store::transaction const & transaction) const;
account_iterator account_end () const;
std::optional<nano::account_info> account_get (store::transaction const & transaction, nano::account const & account) const;
nano::block_hash account_head (store::transaction const & transaction, nano::account const & account) const;
uint64_t account_height (store::transaction const & transaction, nano::account const & account) const;
// Returns the next account entry equal or greater than 'account'
// Mirrors std::map::lower_bound
account_iterator account_lower_bound (store::transaction const & transaction, nano::account const & account) const;
// Returns the next account entry greater than 'account'
// Returns account_lower_bound (transaction, account + 1)
// Mirrors std::map::upper_bound
account_iterator account_upper_bound (store::transaction const & transaction, nano::account const & account) const;

public: // Operations on blocks
std::optional<nano::account> block_account (store::transaction const & transaction, nano::block_hash const & hash) const;
Expand All @@ -47,6 +58,7 @@ class ledger_set_any

public: // Operations on pending entries
std::optional<nano::pending_info> pending_get (store::transaction const & transaction, nano::pending_key const & key) const;
bool receivable_any (store::transaction const & transaction, nano::account const & account) const;
receivable_iterator receivable_end () const;
bool receivable_exists (store::transaction const & transaction, nano::account const & account) const;
// Returns the next receivable entry equal or greater than 'key'
Expand Down
Loading

0 comments on commit 69c7913

Please sign in to comment.