From 4889d3cf91769310329345760e479ee4d56ef8d4 Mon Sep 17 00:00:00 2001 From: Dimitrios Siganos Date: Wed, 17 Jan 2024 14:01:46 +0700 Subject: [PATCH] Fix conflicts.add_two unit test (#4361) * Add debugging convenience function nano::test::print_all_account_info to print the basic info of all accounts in the ledger. It is intended to be used from unit tests. * Introduce nano::test::setup_new_account() To make it easier to write unit tests * Fix unit test conflicts.add_two --- nano/core_test/conflicts.cpp | 110 ++++++++++------------------------ nano/test_common/chains.cpp | 29 +++++---- nano/test_common/chains.hpp | 12 ++++ nano/test_common/testutil.cpp | 21 +++++++ nano/test_common/testutil.hpp | 7 +++ 5 files changed, 87 insertions(+), 92 deletions(-) diff --git a/nano/core_test/conflicts.cpp b/nano/core_test/conflicts.cpp index 27342790f9..4232edb429 100644 --- a/nano/core_test/conflicts.cpp +++ b/nano/core_test/conflicts.cpp @@ -1,6 +1,8 @@ + #include #include #include +#include #include #include @@ -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>> { - 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); } diff --git a/nano/test_common/chains.cpp b/nano/test_common/chains.cpp index bb77caa067..dc6123792a 100644 --- a/nano/test_common/chains.cpp +++ b/nano/test_common/chains.cpp @@ -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::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; } diff --git a/nano/test_common/chains.hpp b/nano/test_common/chains.hpp index 8ead108386..2004159cac 100644 --- a/nano/test_common/chains.hpp +++ b/nano/test_common/chains.hpp @@ -32,6 +32,18 @@ std::vector> 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> 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); + /** * Sends `amount` raw from `source` account chain into a newly created account and sets that account as its own representative * @return created representative diff --git a/nano/test_common/testutil.cpp b/nano/test_common/testutil.cpp index 05a6db689b..56d89419f1 100644 --- a/nano/test_common/testutil.cpp +++ b/nano/test_common/testutil.cpp @@ -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; + } + } +} \ No newline at end of file diff --git a/nano/test_common/testutil.hpp b/nano/test_common/testutil.hpp index a335887316..3203fdfb3e 100644 --- a/nano/test_common/testutil.hpp +++ b/nano/test_common/testutil.hpp @@ -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> 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); + } }