Merge pull request #4553 from dsiganos/pending_key_info_improvements

Documentation for pending key and info classes and some other improvements whilst investigating
This commit is contained in:
Dimitrios Siganos 2024-04-14 11:11:32 +09:00 committed by GitHub
commit 804dcaceb1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 159 additions and 21 deletions

View file

@ -39,6 +39,7 @@ add_executable(
processing_queue.cpp
processor_service.cpp
rep_crawler.cpp
receivable.cpp
peer_container.cpp
rep_weight_store.cpp
scheduler_buckets.cpp

View file

@ -0,0 +1,99 @@
#include <nano/test_common/system.hpp>
#include <nano/test_common/testutil.hpp>
#include <gtest/gtest.h>
using namespace std::chrono_literals;
// this test sends 3 send blocks in 3 different epochs and checks that
// the pending table records the epochs correctly for each send
TEST (receivable, pending_table_query_epochs)
{
nano::test::system system{ 1 };
auto & node = *system.nodes[0];
nano::keypair key2;
nano::block_builder builder;
// epoch 0 send
auto send0 = builder
.send ()
.previous (nano::dev::genesis->hash ())
.destination (key2.pub)
.balance (nano::dev::constants.genesis_amount - 1)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (nano::dev::genesis->hash ()))
.build ();
nano::test::process (node, { send0 });
ASSERT_TIMELY (5s, nano::test::exists (node, { send0 }));
auto epoch1 = system.upgrade_genesis_epoch (node, nano::epoch::epoch_1);
ASSERT_TRUE (epoch1);
ASSERT_TIMELY (5s, nano::test::exists (node, { epoch1 }));
// epoch 1 send
auto send1 = builder
.state ()
.account (nano::dev::genesis_key.pub)
.representative (nano::dev::genesis_key.pub)
.previous (epoch1->hash ())
.link (key2.pub)
.balance (nano::dev::constants.genesis_amount - 11)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (epoch1->hash ()))
.build ();
ASSERT_TRUE (nano::test::process (node, { send1 }));
ASSERT_TIMELY (5s, nano::test::exists (node, { send1 }));
auto epoch2 = system.upgrade_genesis_epoch (node, nano::epoch::epoch_2);
ASSERT_TRUE (epoch2);
ASSERT_TIMELY (5s, nano::test::exists (node, { epoch2 }));
// epoch 2 send
auto send2 = builder
.state ()
.account (nano::dev::genesis_key.pub)
.representative (nano::dev::genesis_key.pub)
.previous (epoch2->hash ())
.link (key2.pub)
.balance (nano::dev::constants.genesis_amount - 111)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (epoch2->hash ()))
.build ();
nano::test::process (node, { send2 });
ASSERT_TIMELY (5s, nano::test::exists (node, { send2 }));
auto tx = node.store.tx_begin_read ();
// check epoch 0 send
{
nano::pending_key key{ key2.pub, send0->hash () };
auto opt_info = node.store.pending.get (tx, key);
ASSERT_TRUE (opt_info.has_value ());
auto info = opt_info.value ();
ASSERT_EQ (info.source, nano::dev::genesis_key.pub);
ASSERT_EQ (info.amount, 1);
ASSERT_EQ (info.epoch, nano::epoch::epoch_0);
}
// check epoch 1 send
{
nano::pending_key key{ key2.pub, send1->hash () };
auto opt_info = node.store.pending.get (tx, key);
ASSERT_TRUE (opt_info.has_value ());
auto info = opt_info.value ();
ASSERT_EQ (info.source, nano::dev::genesis_key.pub);
ASSERT_EQ (info.amount, 10);
ASSERT_EQ (info.epoch, nano::epoch::epoch_1);
}
// check epoch 2 send
{
nano::pending_key key{ key2.pub, send2->hash () };
auto opt_info = node.store.pending.get (tx, key);
ASSERT_TRUE (opt_info.has_value ());
auto info = opt_info.value ();
ASSERT_EQ (info.source, nano::dev::genesis_key.pub);
ASSERT_EQ (info.amount, 100);
ASSERT_EQ (info.epoch, nano::epoch::epoch_2);
}
}

View file

@ -794,7 +794,7 @@ bool nano::ledger::block_exists (store::transaction const & transaction, nano::b
}
// Balance for an account by account number
nano::uint128_t nano::ledger::account_balance (store::transaction const & transaction_a, nano::account const & account_a, bool only_confirmed_a)
nano::uint128_t nano::ledger::account_balance (store::transaction const & transaction_a, nano::account const & account_a, bool only_confirmed_a) const
{
nano::uint128_t result (0);
if (only_confirmed_a)

View file

@ -43,7 +43,7 @@ public:
std::optional<nano::uint128_t> balance (store::transaction const &, nano::block_hash const &) const;
std::shared_ptr<nano::block> block (store::transaction const & transaction, nano::block_hash const & hash) const;
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_balance (store::transaction const &, nano::account const &, bool = false) const;
nano::uint128_t account_receivable (store::transaction const &, nano::account const &, bool = false);
/**
* Returns the cached vote weight for the given representative.

View file

@ -18,6 +18,7 @@ namespace nano
{
/**
* Information on an uncollected send
* This class captures the data stored in a pending table entry
*/
class pending_info final
{
@ -27,10 +28,20 @@ public:
size_t db_size () const;
bool deserialize (nano::stream &);
bool operator== (nano::pending_info const &) const;
nano::account source{};
nano::amount amount{ 0 };
nano::epoch epoch{ nano::epoch::epoch_0 };
nano::account source{}; // the account sending the funds
nano::amount amount{ 0 }; // amount receivable in this transaction
nano::epoch epoch{ nano::epoch::epoch_0 }; // epoch of sending block, this info is stored here to make it possible to prune the send block
friend std::ostream & operator<< (std::ostream & os, const nano::pending_info & info)
{
const int epoch = nano::normalized_epoch (info.epoch);
os << "Source: " << info.source << ", Amount: " << info.amount.to_string_dec () << " Epoch: " << epoch;
return os;
}
};
// This class represents the data written into the pending (receivable) database table key
// the receiving account and hash of the send block identify a pending db table entry
class pending_key final
{
public:
@ -40,9 +51,16 @@ public:
bool operator== (nano::pending_key const &) const;
bool operator< (nano::pending_key const &) const;
nano::account const & key () const;
nano::account account{};
nano::block_hash hash{ 0 };
nano::account account{}; // receiving account
nano::block_hash hash{ 0 }; // hash of the send block
friend std::ostream & operator<< (std::ostream & os, const nano::pending_key & key)
{
os << "Account: " << key.account << ", Hash: " << key.hash;
return os;
}
};
// This class iterates receivable enttries for an account
class receivable_iterator
{

View file

@ -7,6 +7,7 @@
#include <nano/node/scheduler/priority.hpp>
#include <nano/node/transport/fake.hpp>
#include <nano/secure/ledger.hpp>
#include <nano/secure/pending_info.hpp>
#include <nano/store/block.hpp>
#include <nano/test_common/system.hpp>
#include <nano/test_common/testutil.hpp>
@ -300,20 +301,33 @@ uint64_t nano::test::account_height (nano::node const & node, nano::account cons
return height_info.height;
}
void nano::test::print_all_account_info (nano::node & node)
void nano::test::print_all_receivable_entries (const nano::store::component & store)
{
auto const tx = node.ledger.store.tx_begin_read ();
auto const end = node.ledger.store.account.end ();
for (auto i = node.ledger.store.account.begin (tx); i != end; ++i)
std::cout << "Printing all receivable entries:\n";
auto const tx = store.tx_begin_read ();
auto const end = store.pending.end ();
for (auto i = store.pending.begin (tx); i != end; ++i)
{
std::cout << "Key: " << i->first << std::endl;
std::cout << "Info: " << i->second << std::endl;
}
}
void nano::test::print_all_account_info (const nano::ledger & ledger)
{
std::cout << "Printing all account info:\n";
auto const tx = ledger.store.tx_begin_read ();
auto const end = ledger.store.account.end ();
for (auto i = ledger.store.account.begin (tx); i != end; ++i)
{
nano::account acc = i->first;
nano::account_info acc_info = i->second;
nano::confirmation_height_info height_info;
std::cout << "Account: " << acc.to_account () << std::endl;
std::cout << " Unconfirmed Balance: " << acc_info.balance.to_string_dec () << std::endl;
std::cout << " Confirmed Balance: " << node.ledger.account_balance (tx, acc, true) << std::endl;
std::cout << " Confirmed Balance: " << ledger.account_balance (tx, acc, true) << std::endl;
std::cout << " Block Count: " << acc_info.block_count << std::endl;
if (!node.ledger.store.confirmation_height.get (tx, acc, height_info))
if (!ledger.store.confirmation_height.get (tx, acc, height_info))
{
std::cout << " Conf. Height: " << height_info.height << std::endl;
std::cout << " Conf. Frontier: " << height_info.frontier.to_string () << std::endl;
@ -321,11 +335,11 @@ void nano::test::print_all_account_info (nano::node & node)
}
}
void nano::test::print_all_blocks (nano::node & node)
void nano::test::print_all_blocks (const nano::store::component & store)
{
auto tx = node.store.tx_begin_read ();
auto i = node.store.block.begin (tx);
auto end = node.store.block.end ();
auto tx = store.tx_begin_read ();
auto i = store.block.begin (tx);
auto end = store.block.end ();
std::cout << "Listing all blocks" << std::endl;
for (; i != end; ++i)
{

View file

@ -169,6 +169,7 @@ class network_params;
class vote;
class block;
class election;
class ledger;
extern nano::uint128_t const & genesis_amount;
@ -418,13 +419,18 @@ namespace test
uint64_t account_height (nano::node const & node, nano::account const & acc);
/**
* \brief Debugging function to print all accounts in a ledger. Intented to be used to debug unit tests.
* \brief Debugging function to print all entries in the pending table. Intended to be used to debug unit tests.
*/
void print_all_account_info (nano::node & node);
void print_all_receivable_entries (const nano::store::component & store);
/**
* \brief Debugging function to print all blocks in a node. Intented to be used to debug unit tests.
* \brief Debugging function to print all accounts in a ledger. Intended to be used to debug unit tests.
*/
void print_all_blocks (nano::node & node);
void print_all_account_info (const nano::ledger & ledger);
/**
* \brief Debugging function to print all blocks in a node. Intended to be used to debug unit tests.
*/
void print_all_blocks (const nano::store::component & store);
}
}