Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix conflicts.add_two unit test #4361

Merged
merged 4 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 31 additions & 79 deletions nano/core_test/conflicts.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

#include <nano/node/election.hpp>
#include <nano/node/scheduler/component.hpp>
#include <nano/node/scheduler/priority.hpp>
#include <nano/test_common/chains.hpp>
#include <nano/test_common/system.hpp>
#include <nano/test_common/testutil.hpp>

Expand Down Expand Up @@ -89,91 +91,41 @@ TEST (conflicts, add_two)
{
nano::test::system system{};
auto const & node = system.add_node ();
nano::keypair key1, key2, key3;
auto gk = nano::dev::genesis_key;

system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv);

// define a functor that sends from given account to given destination,
// optionally force-confirming the send blocks *and* receiving on the destination account;
// the functor returns a pair of the send and receive blocks created or nullptrs if something failed
//
auto const do_send = [&node, &system] (auto const & previous, auto const & from, auto const & to, bool forceConfirm = true)
-> std::pair<std::optional<std::shared_ptr<nano::block>>, std::optional<std::shared_ptr<nano::block>>> {
auto const send = nano::send_block_builder{}.make_block ().previous (previous).destination (to.pub).balance (0).sign (from.prv, from.pub).work (*system.work.generate (previous)).build_shared ();

if (nano::process_result::progress != node->process (*send).code)
{
return std::make_pair (std::nullopt, std::nullopt);
}

if (!forceConfirm)
{
return std::make_pair (std::move (send), std::nullopt);
}

auto const is_confirmed = [&node] (auto const & hash) {
return node->block_confirmed (hash);
};

node->process_confirmed (nano::election_status{ send });
auto const is_send_not_confirmed = system.poll_until_true (5s, std::bind (is_confirmed, send->hash ()));
if (is_send_not_confirmed)
{
return std::make_pair (std::nullopt, std::nullopt);
}

auto const receive = nano::open_block_builder{}.make_block ().account (to.pub).source (send->hash ()).representative (to.pub).sign (to.prv, to.pub).work (*system.work.generate (to.pub)).build_shared ();

if (nano::process_result::progress != node->process (*receive).code)
{
return std::make_pair (std::nullopt, std::nullopt);
}

node->process_confirmed (nano::election_status{ receive });
auto const is_receive_not_confirmed = system.poll_until_true (5s, std::bind (is_confirmed, receive->hash ()));
if (is_receive_not_confirmed)
{
return std::make_pair (std::move (send), std::nullopt);
}

return std::make_pair (std::move (send), std::move (receive));
};

// send from genesis to account1 and receive it on account1
//
nano::keypair account1{};
auto const [send1, receive1] = do_send (nano::dev::genesis->hash (), nano::dev::genesis_key, account1);
ASSERT_TRUE (send1.has_value () && receive1.has_value ());
// both blocks having been fully confirmed, we expect 1 (genesis) + 2 (send/receive) = 3 cemented blocks
//
ASSERT_EQ (3, node->ledger.cache.cemented_count);

nano::keypair account2{};
auto const [send2, receive2] = do_send ((*send1)->hash (), nano::dev::genesis_key, account2);
ASSERT_TRUE (send2.has_value () && receive2.has_value ());
// create 2 new accounts, that receive 1 raw each, all blocks are force confirmed
auto [send1, open1] = nano::test::setup_new_account (system, *node, 1, gk, key1, gk.pub, true);
auto [send2, open2] = nano::test::setup_new_account (system, *node, 1, gk, key2, gk.pub, true);
ASSERT_EQ (5, node->ledger.cache.cemented_count);

// send from account1 to account3 but do not receive it on account3 and do not force-confirm the send block
//
nano::keypair account3{};
auto const [send3, dummy1] = do_send ((*receive1)->hash (), account1, account3, false);
ASSERT_TRUE (send3.has_value ());
// expect the number of cemented blocks not to have changed since the last operation
//
ASSERT_EQ (5, node->ledger.cache.cemented_count);
// send 1 raw to account key3 from key1
auto send_a = nano::state_block_builder ()
.account (key1.pub)
.previous (open1->hash ())
.representative (nano::dev::genesis_key.pub)
.balance (0)
.link (key3.pub)
.sign (key1.prv, key1.pub)
.work (*system.work.generate (open1->hash ()))
.build_shared ();

auto const [send4, dummy2] = do_send ((*receive2)->hash (), account2, account3, false);
ASSERT_TRUE (send4.has_value ());
ASSERT_EQ (5, node->ledger.cache.cemented_count);
// send 1 raw to account key3 from key2
auto send_b = nano::state_block_builder ()
.account (key2.pub)
.previous (open2->hash ())
.representative (nano::dev::genesis_key.pub)
.balance (0)
.link (key3.pub)
.sign (key2.prv, key2.pub)
.work (*system.work.generate (open2->hash ()))
.build_shared ();

// activate elections for the previous two send blocks (to account3) that we did not forcefully confirm
//
node->scheduler.priority.activate (account3.pub, node->store.tx_begin_read ());
ASSERT_TIMELY (5s, node->active.election ((*send3)->qualified_root ()) != nullptr);
ASSERT_TIMELY (5s, node->active.election ((*send4)->qualified_root ()) != nullptr);

// wait 3s before asserting just to make sure there would be enough time
// for the Active Elections Container to evict both elections in case they would wrongfully get confirmed
//
ASSERT_TRUE (nano::test::process (*node, { send_a, send_b }));
ASSERT_TRUE (nano::test::start_elections (system, *node, { send_a, send_b }));
ASSERT_TRUE (node->active.election (send_a->qualified_root ()));
ASSERT_TRUE (node->active.election (send_b->qualified_root ()));
ASSERT_TIMELY_EQ (5s, node->active.size (), 2);
}

Expand Down
29 changes: 16 additions & 13 deletions nano/test_common/chains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,39 +148,42 @@ nano::block_list_t nano::test::setup_independent_blocks (nano::test::system & sy
return blocks;
}

nano::keypair nano::test::setup_rep (nano::test::system & system, nano::node & node, nano::uint128_t const amount, nano::keypair source)
std::pair<std::shared_ptr<nano::block>, std::shared_ptr<nano::block>> nano::test::setup_new_account (nano::test::system & system, nano::node & node, nano::uint128_t const amount, nano::keypair source, nano::keypair dest, nano::account dest_rep, bool force_confirm)
{
auto latest = node.latest (source.pub);
auto balance = node.balance (source.pub);

nano::keypair key;
nano::block_builder builder;

auto send = builder
auto send = nano::block_builder ()
.state ()
.account (source.pub)
.previous (latest)
.representative (source.pub)
.balance (balance - amount)
.link (key.pub)
.link (dest.pub)
.sign (source.prv, source.pub)
.work (*system.work.generate (latest))
.build_shared ();

auto open = builder
auto open = nano::block_builder ()
.state ()
.account (key.pub)
.account (dest.pub)
.previous (0)
.representative (key.pub)
.representative (dest_rep)
.balance (amount)
.link (send->hash ())
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.sign (dest.prv, dest.pub)
.work (*system.work.generate (dest.pub))
.build_shared ();

EXPECT_TRUE (nano::test::process (node, { send, open }));
EXPECT_TRUE (nano::test::start_elections (system, node, { send, open }, true));
EXPECT_TRUE (nano::test::start_elections (system, node, { send, open }, force_confirm));
EXPECT_TIMELY (5s, nano::test::confirmed (node, { send, open }));
return std::make_pair (send, open);
}

return key;
nano::keypair nano::test::setup_rep (nano::test::system & system, nano::node & node, nano::uint128_t const amount, nano::keypair source)
{
nano::keypair destkey;
nano::test::setup_new_account (system, node, amount, source, destkey, destkey.pub, true);
return destkey;
}
12 changes: 12 additions & 0 deletions nano/test_common/chains.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ std::vector<std::pair<nano::account, nano::block_list_t>> setup_chains (nano::te
*/
nano::block_list_t setup_independent_blocks (nano::test::system & system, nano::node & node, int count, nano::keypair source = nano::dev::genesis_key);

/**
* \brief Create a pair of send/receive blocks to implement the transfer of "amount" raw from "source" to the unopened account "dest".
* \param system
* \param node
* \param amount the amount of raw to transfer
* \param source the source account
* \param dest the destination account
* \param dest_rep the rep that the dest account should have
* \param force_confirm force confirm the blocks
*/
std::pair<std::shared_ptr<nano::block>, std::shared_ptr<nano::block>> setup_new_account (nano::test::system & system, nano::node & node, nano::uint128_t const amount, nano::keypair source, nano::keypair dest, nano::account dest_rep, bool force_confirm);
pwojcikdev marked this conversation as resolved.
Show resolved Hide resolved

/**
* Sends `amount` raw from `source` account chain into a newly created account and sets that account as its own representative
* @return created representative
Expand Down
21 changes: 21 additions & 0 deletions nano/test_common/testutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,24 @@ bool nano::test::start_elections (nano::test::system & system_a, nano::node & no
{
return nano::test::start_elections (system_a, node_a, blocks_to_hashes (blocks_a), forced_a);
}

void nano::test::print_all_account_info (nano::node & node)
{
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)
{
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 << " Block Count: " << acc_info.block_count << std::endl;
if (!node.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;
}
}
}
7 changes: 7 additions & 0 deletions nano/test_common/testutil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,5 +416,12 @@ namespace test
* NOTE: Each election is given 5 seconds to complete, if it does not complete in 5 seconds, it will return an error.
*/
[[nodiscard]] bool start_elections (nano::test::system &, nano::node &, std::vector<std::shared_ptr<nano::block>> const &, bool const forced_a = false);

/**
* \brief Debugging function to print all accounts in a ledger. Intented to be used to debug unit tests.
* \param ledger
*/
void print_all_account_info (nano::node & node);

}
}
Loading