diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index fba25ffdc9..89583c76d1 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -71,7 +71,7 @@ jobs: windows_test: name: Windows Unit Tests [TEST_USE_ROCKSDB=${{ matrix.TEST_USE_ROCKSDB }}] - timeout-minutes: 90 + timeout-minutes: 120 strategy: fail-fast: false matrix: diff --git a/ci/actions/dev-build-tag-gen.sh b/ci/actions/dev-build-tag-gen.sh index d62ab60b86..1ad7510204 100755 --- a/ci/actions/dev-build-tag-gen.sh +++ b/ci/actions/dev-build-tag-gen.sh @@ -100,11 +100,17 @@ function output_variable { set -o nounset set -o xtrace +# The reference branch is 'develop', that is the current release being developed. Here it is extracting the +# major and minor numbers from the CMakeLists.txt file. current_version_major=$(grep -P "(set)(.)*(CPACK_PACKAGE_VERSION_MAJOR)" "${source_dir}/CMakeLists.txt" | grep -oP "([0-9]+)") current_version_minor=$(grep -P "(set)(.)*(CPACK_PACKAGE_VERSION_MINOR)" "${source_dir}/CMakeLists.txt" | grep -oP "([0-9]+)") current_version_pre_release=$(grep -P "(set)(.)*(CPACK_PACKAGE_VERSION_PRE_RELEASE)" "${source_dir}/CMakeLists.txt" | grep -oP "([0-9]+)") -version_tags=$(git tag | sort -V -r | grep -E "^(V([0-9]+).([0-9]+)(RC[0-9]+)?)$") +# Get the list of version tags that can be either official releases or release candidates. The list comes +# ordered by version, in reverse order. +version_tags=$(git tag | sort -V -r | grep -E "^(V([0-9]+)\.([0-9]+)(RC[0-9]+)?)$") + +# Get the first tag of the list, that means, the latest version. last_tag=$(get_first_item "$version_tags") tag_version_major=$(echo "$last_tag" | grep -oP "\V([0-9]+)\." | grep -oP "[0-9]+") if [[ ${tag_version_major} -ge ${current_version_major} ]]; then @@ -128,14 +134,29 @@ last_tag="" version_tags="" previous_release_major=0 previous_release_minor=0 +# If option -r is set, then the script will handle tag generation as for the release branch, it'd do 'develop' branch +# otherwise. if [[ $previous_release_gen == false ]]; then - version_tags=$(git tag | sort -V -r | grep -E "^(V(${current_version_major}).(${current_version_minor})(DB[0-9]+))$" || true) +# List of all beta-build (DB) tags in reverse version order. + version_tags=$(git tag | sort -V -r | grep -E "^(V(${current_version_major})\.(${current_version_minor})(DB[0-9]+))$" || true) last_tag=$(get_first_item "$version_tags") else previous_release_major=$(( current_version_major - 1 )) - version_tags=$(git tag | sort -V -r | grep -E "^(V(${previous_release_major}).([0-9]+)(DB[0-9]+)?)$" || true) +# List of official release tags in reverse order. + version_tags=$(git tag | sort -V -r | grep -E "^(V(${previous_release_major})\.([0-9]+))$" || true) + if [[ -z "$version_tags" ]]; then +# Previous release minor is 0 if no official release is found in the branch. + previous_release_minor=0 + else +# Previous release minor version is increased by 1 because next beta-build should go on unreleased minor versions. + last_minor_release=$(get_first_item "$version_tags") + last_minor=$(echo "$last_minor_release" | grep -oP "\.([0-9]+)" | grep -oP "[0-9]+") + previous_release_minor=$(( last_minor + 1 )) + fi +# List of tags in reverse version order that may or many not include beta-build (DB) tags. + version_tags=$(git tag | sort -V -r | grep -E "^(V(${previous_release_major})\.(${previous_release_minor})(DB[0-9]+)?)$" || true) last_tag=$(get_first_item "$version_tags") - previous_release_minor=$(echo "$last_tag" | grep -oP "\.([0-9]+)" | grep -oP "[0-9]+") +# The reference release branch in Git repository should follow the pattern 'releases/vXY'. release_branch="releases/v${previous_release_major}" output_variable release_branch fi @@ -143,6 +164,8 @@ popd build_tag="" if [[ -z "$last_tag" ]]; then +# If the last tag was not found previously, it means there was no previous beta-build for this major and minor +# numbers, then the build number is 1. build_number=1 echo "info: no tag found, build_number=${build_number}" if [[ $previous_release_gen == false ]]; then @@ -156,6 +179,8 @@ if [[ -z "$last_tag" ]]; then fi pushd "$source_dir" +# This code block looks for the branch head in order to know if there is already a tag for it. There is no need +# to generate a new tag if the beta-build has already been created. develop_head="" if [[ $previous_release_gen == false ]]; then develop_head=$(git rev-parse "${git_upstream}/develop") @@ -170,6 +195,7 @@ if [[ "$develop_head" == "$tag_head" ]]; then exit 2 fi +# Prepares the build number to be used. latest_build_number=$(echo "$last_tag" | grep -oP "(DB[0-9]+)" | grep -oP "[0-9]+") build_number=$(( latest_build_number + 1 )) if [[ $previous_release_gen == false ]]; then diff --git a/ci/test.sh b/ci/test.sh index e5e558f577..329e96bd8d 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -2,9 +2,9 @@ build_dir=${1-${PWD}} if [[ ${TEST_USE_ROCKSDB-0} == 1 ]]; then - TIMEOUT_DEFAULT=1800 + TIMEOUT_DEFAULT=2400 else - TIMEOUT_DEFAULT=900 + TIMEOUT_DEFAULT=1200 fi BUSYBOX_BASH=${BUSYBOX_BASH-0} diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index cd31f5ce39..04df50caf4 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -1409,94 +1410,6 @@ TEST (active_transactions, fifo) ASSERT_TIMELY (1s, node.active.election (receive2->qualified_root ()) != nullptr); } -namespace -{ -/* - * Sends `amount` raw from genesis chain into a new account and makes it a representative - */ -nano::keypair setup_rep (nano::test::system & system, nano::node & node, nano::uint128_t const amount) -{ - auto latest = node.latest (nano::dev::genesis_key.pub); - auto balance = node.balance (nano::dev::genesis_key.pub); - - nano::keypair key; - nano::block_builder builder; - - auto send = builder - .send () - .previous (latest) - .destination (key.pub) - .balance (balance - amount) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (latest)) - .build_shared (); - - auto open = builder - .open () - .source (send->hash ()) - .representative (key.pub) - .account (key.pub) - .sign (key.prv, key.pub) - .work (*system.work.generate (key.pub)) - .build_shared (); - - EXPECT_TRUE (nano::test::process (node, { send, open })); - EXPECT_TIMELY (5s, nano::test::confirm (node, { send, open })); - EXPECT_TIMELY (5s, nano::test::confirmed (node, { send, open })); - - return key; -} - -/* - * Creates `count` 1 raw sends from genesis to unique accounts and corresponding open blocks. - * The genesis chain is then confirmed, but leaves open blocks unconfirmed. - */ -std::vector> setup_independent_blocks (nano::test::system & system, nano::node & node, int count) -{ - std::vector> blocks; - - auto latest = node.latest (nano::dev::genesis_key.pub); - auto balance = node.balance (nano::dev::genesis_key.pub); - - for (int n = 0; n < count; ++n) - { - nano::keypair key; - nano::block_builder builder; - - balance -= 1; - auto send = builder - .send () - .previous (latest) - .destination (key.pub) - .balance (balance) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (latest)) - .build_shared (); - latest = send->hash (); - - auto open = builder - .open () - .source (send->hash ()) - .representative (key.pub) - .account (key.pub) - .sign (key.prv, key.pub) - .work (*system.work.generate (key.pub)) - .build_shared (); - - EXPECT_TRUE (nano::test::process (node, { send, open })); - EXPECT_TIMELY (5s, nano::test::exists (node, { send, open })); // Ensure blocks are in the ledger - - blocks.push_back (open); - } - - // Confirm whole genesis chain at once - EXPECT_TIMELY (5s, nano::test::confirm (node, { latest })); - EXPECT_TIMELY (5s, nano::test::confirmed (node, { latest })); - - return blocks; -} -} - /* * Ensures we limit the number of vote hinted elections in AEC */ @@ -1513,10 +1426,10 @@ TEST (active_transactions, limit_vote_hinted_elections) // Setup representatives // Enough weight to trigger election hinting but not enough to confirm block on its own const auto amount = ((node.online_reps.trended () / 100) * node.config.election_hint_weight_percent) + 1000 * nano::Gxrb_ratio; - nano::keypair rep1 = setup_rep (system, node, amount / 2); - nano::keypair rep2 = setup_rep (system, node, amount / 2); + nano::keypair rep1 = nano::test::setup_rep (system, node, amount / 2); + nano::keypair rep2 = nano::test::setup_rep (system, node, amount / 2); - auto blocks = setup_independent_blocks (system, node, 2); + auto blocks = nano::test::setup_independent_blocks (system, node, 2); auto open0 = blocks[0]; auto open1 = blocks[1]; @@ -1575,7 +1488,7 @@ TEST (active_transactions, allow_limited_overflow) config.active_elections_hinted_limit_percentage = 20; // Should give us a limit of 4 hinted elections auto & node = *system.add_node (config); - auto blocks = setup_independent_blocks (system, node, aec_limit * 4); + auto blocks = nano::test::setup_independent_blocks (system, node, aec_limit * 4); // Split blocks in two halves std::vector> blocks1 (blocks.begin (), blocks.begin () + blocks.size () / 2); @@ -1624,7 +1537,7 @@ TEST (active_transactions, allow_limited_overflow_adapt) config.active_elections_hinted_limit_percentage = 20; // Should give us a limit of 4 hinted elections auto & node = *system.add_node (config); - auto blocks = setup_independent_blocks (system, node, aec_limit * 4); + auto blocks = nano::test::setup_independent_blocks (system, node, aec_limit * 4); // Split blocks in two halves std::vector> blocks1 (blocks.begin (), blocks.begin () + blocks.size () / 2); diff --git a/nano/core_test/backlog.cpp b/nano/core_test/backlog.cpp index 802ccf10ab..0ad651d864 100644 --- a/nano/core_test/backlog.cpp +++ b/nano/core_test/backlog.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -8,65 +9,6 @@ using namespace std::chrono_literals; -namespace -{ -using block_list_t = std::vector>; - -/* - * Creates `count` 1 raw sends from genesis to unique accounts and corresponding open blocks. - * The genesis chain is then confirmed, but leaves open blocks unconfirmed - * The list of unconfirmed open blocks is returned. - */ -block_list_t setup_independent_blocks (nano::test::system & system, nano::node & node, int count) -{ - std::vector> blocks; - - auto latest = node.latest (nano::dev::genesis_key.pub); - auto balance = node.balance (nano::dev::genesis_key.pub); - - for (int n = 0; n < count; ++n) - { - nano::keypair key; - nano::block_builder builder; - - balance -= 1; - auto send = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (latest) - .representative (nano::dev::genesis_key.pub) - .balance (balance) - .link (key.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (latest)) - .build_shared (); - latest = send->hash (); - - auto open = builder - .state () - .account (key.pub) - .previous (0) - .representative (key.pub) - .balance (1) - .link (send->hash ()) - .sign (key.prv, key.pub) - .work (*system.work.generate (key.pub)) - .build_shared (); - - EXPECT_TRUE (nano::test::process (node, { send, open })); - EXPECT_TIMELY (5s, nano::test::exists (node, { send, open })); // Ensure blocks are in the ledger - - blocks.push_back (open); - } - - // Confirm whole genesis chain at once - EXPECT_TIMELY (5s, nano::test::confirm (node, { latest })); - EXPECT_TIMELY (5s, nano::test::confirmed (node, { latest })); - - return blocks; -} -} - /* * Ensures all not confirmed accounts get activated by backlog scan periodically */ @@ -74,6 +16,7 @@ TEST (backlog, population) { nano::mutex mutex; std::unordered_set activated; + nano::test::system system{}; auto & node = *system.add_node (); @@ -83,7 +26,7 @@ TEST (backlog, population) activated.insert (account); }); - auto blocks = setup_independent_blocks (system, node, 256); + auto blocks = nano::test::setup_independent_blocks (system, node, 256); // Checks if `activated` set contains all accounts we previously set up auto all_activated = [&] () { diff --git a/nano/core_test/block_store.cpp b/nano/core_test/block_store.cpp index 5c77c75b2b..04f3e955f1 100644 --- a/nano/core_test/block_store.cpp +++ b/nano/core_test/block_store.cpp @@ -1677,8 +1677,8 @@ namespace lmdb nano::ledger ledger (store, stats, nano::dev::constants); auto transaction (store.tx_begin_write ()); store.initialize (transaction, ledger.cache, nano::dev::constants); - nano::account_info account_info; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis->account (), account_info)); + auto account_info = ledger.account_info (transaction, nano::dev::genesis->account ()); + ASSERT_TRUE (account_info); nano::confirmation_height_info confirmation_height_info; ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis->account (), confirmation_height_info)); diff --git a/nano/core_test/bootstrap_server.cpp b/nano/core_test/bootstrap_server.cpp index 447eb52730..5ca4a460cb 100644 --- a/nano/core_test/bootstrap_server.cpp +++ b/nano/core_test/bootstrap_server.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -9,98 +10,6 @@ using namespace std::chrono_literals; namespace { -using block_list_t = std::vector>; - -/** - * Creates `block_count` random send blocks in an account chain - */ -block_list_t setup_chain (nano::test::system & system, nano::node & node, nano::keypair key, int block_count) -{ - auto latest = node.latest (key.pub); - auto balance = node.balance (key.pub); - - std::vector> blocks; - for (int n = 0; n < block_count; ++n) - { - nano::keypair throwaway; - nano::block_builder builder; - - balance -= 1; - auto send = builder - .send () - .previous (latest) - .destination (throwaway.pub) - .balance (balance) - .sign (key.prv, key.pub) - .work (*system.work.generate (latest)) - .build_shared (); - - latest = send->hash (); - blocks.push_back (send); - } - - EXPECT_TRUE (nano::test::process (node, blocks)); - // Confirm whole chain at once - EXPECT_TIMELY (5s, nano::test::confirm (node, { blocks.back () })); - EXPECT_TIMELY (5s, nano::test::confirmed (node, blocks)); - - return blocks; -} - -/** - * Creates `count` account chains, each with `block_count` blocks - */ -std::vector> setup_chains (nano::test::system & system, nano::node & node, int count, int block_count) -{ - auto latest = node.latest (nano::dev::genesis_key.pub); - auto balance = node.balance (nano::dev::genesis_key.pub); - - std::vector> chains; - for (int n = 0; n < count; ++n) - { - nano::keypair key; - nano::block_builder builder; - - balance -= block_count * 2; // Send enough to later create `block_count` blocks - auto send = builder - .send () - .previous (latest) - .destination (key.pub) - .balance (balance) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*system.work.generate (latest)) - .build_shared (); - - auto open = builder - .open () - .source (send->hash ()) - .representative (key.pub) - .account (key.pub) - .sign (key.prv, key.pub) - .work (*system.work.generate (key.pub)) - .build_shared (); - - latest = send->hash (); - - // Ensure blocks are in the ledger and confirmed - EXPECT_TRUE (nano::test::process (node, { send, open })); - EXPECT_TIMELY (5s, nano::test::confirm (node, { send, open })); - EXPECT_TIMELY (5s, nano::test::confirmed (node, { send, open })); - - auto added_blocks = setup_chain (system, node, key, block_count); - - auto blocks = block_list_t{ open }; - blocks.insert (blocks.end (), added_blocks.begin (), added_blocks.end ()); - - chains.emplace_back (key.pub, blocks); - } - - return chains; -} - -/** - * Helper to track responses in thread safe way - */ class responses_helper final { public: @@ -160,7 +69,7 @@ TEST (bootstrap_server, serve_account_blocks) responses.add (response); }); - auto chains = setup_chains (system, node, 1, 128); + auto chains = nano::test::setup_chains (system, node, 1, 128); auto [first_account, first_blocks] = chains.front (); // Request blocks from account root @@ -204,11 +113,11 @@ TEST (bootstrap_server, serve_hash) responses.add (response); }); - auto chains = setup_chains (system, node, 1, 256); + auto chains = nano::test::setup_chains (system, node, 1, 256); auto [account, blocks] = chains.front (); // Skip a few blocks to request hash in the middle of the chain - blocks = block_list_t (std::next (blocks.begin (), 9), blocks.end ()); + blocks = nano::block_list_t{ std::next (blocks.begin (), 9), blocks.end () }; // Request blocks from the middle of the chain nano::asc_pull_req request{ node.network_params.network }; @@ -251,11 +160,11 @@ TEST (bootstrap_server, serve_hash_one) responses.add (response); }); - auto chains = setup_chains (system, node, 1, 256); + auto chains = nano::test::setup_chains (system, node, 1, 256); auto [account, blocks] = chains.front (); // Skip a few blocks to request hash in the middle of the chain - blocks = block_list_t (std::next (blocks.begin (), 9), blocks.end ()); + blocks = nano::block_list_t{ std::next (blocks.begin (), 9), blocks.end () }; // Request blocks from the middle of the chain nano::asc_pull_req request{ node.network_params.network }; @@ -295,7 +204,7 @@ TEST (bootstrap_server, serve_end_of_chain) responses.add (response); }); - auto chains = setup_chains (system, node, 1, 128); + auto chains = nano::test::setup_chains (system, node, 1, 128); auto [account, blocks] = chains.front (); // Request blocks from account frontier @@ -337,7 +246,7 @@ TEST (bootstrap_server, serve_missing) responses.add (response); }); - auto chains = setup_chains (system, node, 1, 128); + auto chains = nano::test::setup_chains (system, node, 1, 128); // Request blocks from account frontier nano::asc_pull_req request{ node.network_params.network }; @@ -377,7 +286,7 @@ TEST (bootstrap_server, serve_multiple) responses.add (response); }); - auto chains = setup_chains (system, node, 32, 16); + auto chains = nano::test::setup_chains (system, node, 32, 16); { // Request blocks from multiple chains at once @@ -440,7 +349,7 @@ TEST (bootstrap_server, serve_account_info) responses.add (response); }); - auto chains = setup_chains (system, node, 1, 128); + auto chains = nano::test::setup_chains (system, node, 1, 128); auto [account, blocks] = chains.front (); // Request blocks from account root @@ -488,7 +397,7 @@ TEST (bootstrap_server, serve_account_info_missing) responses.add (response); }); - auto chains = setup_chains (system, node, 1, 128); + auto chains = nano::test::setup_chains (system, node, 1, 128); auto [account, blocks] = chains.front (); // Request blocks from account root diff --git a/nano/core_test/confirmation_height.cpp b/nano/core_test/confirmation_height.cpp index a0d550f959..a470e16b9e 100644 --- a/nano/core_test/confirmation_height.cpp +++ b/nano/core_test/confirmation_height.cpp @@ -250,31 +250,34 @@ TEST (confirmation_height, multiple_accounts) ASSERT_TIMELY (10s, node->stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out) == 10); - nano::account_info account_info; nano::confirmation_height_info confirmation_height_info; auto & store = node->store; auto transaction = node->store.tx_begin_read (); ASSERT_TRUE (node->ledger.block_confirmed (transaction, receive3->hash ())); - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, account_info)); + auto account_info = node->ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (account_info); ASSERT_FALSE (node->store.confirmation_height.get (transaction, nano::dev::genesis_key.pub, confirmation_height_info)); ASSERT_EQ (4, confirmation_height_info.height); ASSERT_EQ (send3->hash (), confirmation_height_info.frontier); - ASSERT_EQ (4, account_info.block_count); - ASSERT_FALSE (store.account.get (transaction, key1.pub, account_info)); + ASSERT_EQ (4, account_info->block_count); + account_info = node->ledger.account_info (transaction, key1.pub); + ASSERT_TRUE (account_info); ASSERT_FALSE (node->store.confirmation_height.get (transaction, key1.pub, confirmation_height_info)); ASSERT_EQ (2, confirmation_height_info.height); ASSERT_EQ (send4->hash (), confirmation_height_info.frontier); - ASSERT_EQ (3, account_info.block_count); - ASSERT_FALSE (store.account.get (transaction, key2.pub, account_info)); + ASSERT_EQ (3, account_info->block_count); + account_info = node->ledger.account_info (transaction, key2.pub); + ASSERT_TRUE (account_info); ASSERT_FALSE (node->store.confirmation_height.get (transaction, key2.pub, confirmation_height_info)); ASSERT_EQ (3, confirmation_height_info.height); ASSERT_EQ (send6->hash (), confirmation_height_info.frontier); - ASSERT_EQ (4, account_info.block_count); - ASSERT_FALSE (store.account.get (transaction, key3.pub, account_info)); + ASSERT_EQ (4, account_info->block_count); + account_info = node->ledger.account_info (transaction, key3.pub); + ASSERT_TRUE (account_info); ASSERT_FALSE (node->store.confirmation_height.get (transaction, key3.pub, confirmation_height_info)); ASSERT_EQ (2, confirmation_height_info.height); ASSERT_EQ (receive3->hash (), confirmation_height_info.frontier); - ASSERT_EQ (2, account_info.block_count); + ASSERT_EQ (2, account_info->block_count); // The accounts for key1 and key2 have 1 more block in the chain than is confirmed. // So this can be rolled back, but the one before that cannot. Check that this is the case @@ -698,19 +701,20 @@ TEST (confirmation_height, send_receive_between_2_accounts) auto transaction (node->store.tx_begin_read ()); ASSERT_TRUE (node->ledger.block_confirmed (transaction, receive4->hash ())); - nano::account_info account_info; nano::confirmation_height_info confirmation_height_info; - ASSERT_FALSE (node->store.account.get (transaction, nano::dev::genesis_key.pub, account_info)); + auto account_info = node->ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (account_info); ASSERT_FALSE (node->store.confirmation_height.get (transaction, nano::dev::genesis_key.pub, confirmation_height_info)); ASSERT_EQ (6, confirmation_height_info.height); ASSERT_EQ (send5->hash (), confirmation_height_info.frontier); - ASSERT_EQ (7, account_info.block_count); + ASSERT_EQ (7, account_info->block_count); - ASSERT_FALSE (node->store.account.get (transaction, key1.pub, account_info)); + account_info = node->ledger.account_info (transaction, key1.pub); + ASSERT_TRUE (account_info); ASSERT_FALSE (node->store.confirmation_height.get (transaction, key1.pub, confirmation_height_info)); ASSERT_EQ (5, confirmation_height_info.height); ASSERT_EQ (receive4->hash (), confirmation_height_info.frontier); - ASSERT_EQ (5, account_info.block_count); + ASSERT_EQ (5, account_info->block_count); ASSERT_EQ (10, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in)); ASSERT_EQ (10, node->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in)); @@ -815,13 +819,13 @@ TEST (confirmation_height, send_receive_self) auto transaction (node->store.tx_begin_read ()); ASSERT_TRUE (node->ledger.block_confirmed (transaction, receive3->hash ())); - nano::account_info account_info; - ASSERT_FALSE (node->store.account.get (transaction, nano::dev::genesis_key.pub, account_info)); + auto account_info = node->ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (account_info); nano::confirmation_height_info confirmation_height_info; ASSERT_FALSE (node->store.confirmation_height.get (transaction, nano::dev::genesis_key.pub, confirmation_height_info)); ASSERT_EQ (7, confirmation_height_info.height); ASSERT_EQ (receive3->hash (), confirmation_height_info.frontier); - ASSERT_EQ (8, account_info.block_count); + ASSERT_EQ (8, account_info->block_count); ASSERT_EQ (6, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in)); ASSERT_EQ (6, node->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in)); ASSERT_EQ (6, node->stats.count (nano::stat::type::http_callback, nano::stat::detail::http_callback, nano::stat::dir::out)); @@ -1061,25 +1065,27 @@ TEST (confirmation_height, all_block_types) auto transaction (node->store.tx_begin_read ()); ASSERT_TRUE (node->ledger.block_confirmed (transaction, state_send2->hash ())); - nano::account_info account_info; nano::confirmation_height_info confirmation_height_info; - ASSERT_FALSE (node->store.account.get (transaction, nano::dev::genesis_key.pub, account_info)); + auto account_info = node->ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (account_info); ASSERT_FALSE (node->store.confirmation_height.get (transaction, nano::dev::genesis_key.pub, confirmation_height_info)); ASSERT_EQ (3, confirmation_height_info.height); ASSERT_EQ (send1->hash (), confirmation_height_info.frontier); - ASSERT_LE (4, account_info.block_count); + ASSERT_LE (4, account_info->block_count); - ASSERT_FALSE (node->store.account.get (transaction, key1.pub, account_info)); + account_info = node->ledger.account_info (transaction, key1.pub); + ASSERT_TRUE (account_info); ASSERT_FALSE (node->store.confirmation_height.get (transaction, key1.pub, confirmation_height_info)); ASSERT_EQ (state_send1->hash (), confirmation_height_info.frontier); ASSERT_EQ (6, confirmation_height_info.height); - ASSERT_LE (7, account_info.block_count); + ASSERT_LE (7, account_info->block_count); - ASSERT_FALSE (node->store.account.get (transaction, key2.pub, account_info)); + account_info = node->ledger.account_info (transaction, key2.pub); + ASSERT_TRUE (account_info); ASSERT_FALSE (node->store.confirmation_height.get (transaction, key2.pub, confirmation_height_info)); ASSERT_EQ (7, confirmation_height_info.height); ASSERT_EQ (state_send2->hash (), confirmation_height_info.frontier); - ASSERT_LE (8, account_info.block_count); + ASSERT_LE (8, account_info->block_count); ASSERT_EQ (15, node->stats.count (nano::stat::type::confirmation_height, nano::stat::detail::blocks_confirmed, nano::stat::dir::in)); ASSERT_EQ (15, node->stats.count (nano::stat::type::confirmation_height, get_stats_detail (mode_a), nano::stat::dir::in)); diff --git a/nano/core_test/ledger.cpp b/nano/core_test/ledger.cpp index 1d2bc781e9..1f3ea90b1d 100644 --- a/nano/core_test/ledger.cpp +++ b/nano/core_test/ledger.cpp @@ -45,12 +45,12 @@ TEST (ledger, genesis_balance) ASSERT_EQ (nano::dev::constants.genesis_amount, balance); auto amount = ledger.amount (transaction, nano::dev::genesis->account ()); ASSERT_EQ (nano::dev::constants.genesis_amount, amount); - nano::account_info info; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis->account (), info)); + auto info = ledger.account_info (transaction, nano::dev::genesis->account ()); + ASSERT_TRUE (info); ASSERT_EQ (1, ledger.cache.account_count); // Frontier time should have been updated when genesis balance was added - ASSERT_GE (nano::seconds_since_epoch (), info.modified); - ASSERT_LT (nano::seconds_since_epoch () - info.modified, 10); + ASSERT_GE (nano::seconds_since_epoch (), info->modified); + ASSERT_LT (nano::seconds_since_epoch () - info->modified, 10); // Genesis block should be confirmed by default nano::confirmation_height_info confirmation_height_info; ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis->account (), confirmation_height_info)); @@ -87,36 +87,36 @@ TEST (ledger, process_send) auto & store = ctx.store (); auto transaction = store.tx_begin_write (); nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::account_info info1; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); nano::keypair key2; nano::block_builder builder; auto send = builder .send () - .previous (info1.head) + .previous (info1->head) .destination (key2.pub) .balance (50) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); nano::block_hash hash1 = send->hash (); - ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, info1.head)); - ASSERT_EQ (1, info1.block_count); + ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, info1->head)); + ASSERT_EQ (1, info1->block_count); // This was a valid block, it should progress. auto return1 = ledger.process (transaction, *send); ASSERT_EQ (nano::dev::genesis_key.pub, send->sideband ().account); ASSERT_EQ (2, send->sideband ().height); ASSERT_EQ (nano::dev::constants.genesis_amount - 50, ledger.amount (transaction, hash1)); - ASSERT_TRUE (store.frontier.get (transaction, info1.head).is_zero ()); + ASSERT_TRUE (store.frontier.get (transaction, info1->head).is_zero ()); ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, hash1)); ASSERT_EQ (nano::process_result::progress, return1.code); ASSERT_EQ (nano::dev::genesis_key.pub, store.block.account_calculated (*send)); ASSERT_EQ (50, ledger.account_balance (transaction, nano::dev::genesis_key.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount - 50, ledger.account_receivable (transaction, key2.pub)); - nano::account_info info2; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info2)); - ASSERT_EQ (2, info2.block_count); - auto latest6 = store.block.get (transaction, info2.head); + auto info2 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info2); + ASSERT_EQ (2, info2->block_count); + auto latest6 = store.block.get (transaction, info2->head); ASSERT_NE (nullptr, latest6); auto latest7 = dynamic_cast (latest6.get ()); ASSERT_NE (nullptr, latest7); @@ -146,24 +146,24 @@ TEST (ledger, process_send) ASSERT_EQ (0, ledger.account_receivable (transaction, key2.pub)); ASSERT_EQ (50, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount - 50, ledger.weight (key2.pub)); - nano::account_info info3; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info3)); - auto latest2 = store.block.get (transaction, info3.head); + auto info3 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info3); + auto latest2 = store.block.get (transaction, info3->head); ASSERT_NE (nullptr, latest2); auto latest3 = dynamic_cast (latest2.get ()); ASSERT_NE (nullptr, latest3); ASSERT_EQ (*send, *latest3); - nano::account_info info4; - ASSERT_FALSE (store.account.get (transaction, key2.pub, info4)); - auto latest4 = store.block.get (transaction, info4.head); + auto info4 = ledger.account_info (transaction, key2.pub); + ASSERT_TRUE (info4); + auto latest4 = store.block.get (transaction, info4->head); ASSERT_NE (nullptr, latest4); auto latest5 = dynamic_cast (latest4.get ()); ASSERT_NE (nullptr, latest5); ASSERT_EQ (*open, *latest5); ASSERT_FALSE (ledger.rollback (transaction, hash2)); ASSERT_TRUE (store.frontier.get (transaction, hash2).is_zero ()); - nano::account_info info5; - ASSERT_TRUE (ledger.store.account.get (transaction, key2.pub, info5)); + auto info5 = ledger.account_info (transaction, key2.pub); + ASSERT_FALSE (info5); nano::pending_info pending1; ASSERT_FALSE (ledger.store.pending.get (transaction, nano::pending_key (key2.pub, hash1), pending1)); ASSERT_EQ (nano::dev::genesis_key.pub, pending1.source); @@ -173,17 +173,17 @@ TEST (ledger, process_send) ASSERT_EQ (50, ledger.account_balance (transaction, nano::dev::genesis_key.pub)); ASSERT_EQ (50, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (0, ledger.weight (key2.pub)); - nano::account_info info6; - ASSERT_FALSE (ledger.store.account.get (transaction, nano::dev::genesis_key.pub, info6)); - ASSERT_EQ (hash1, info6.head); - ASSERT_FALSE (ledger.rollback (transaction, info6.head)); + auto info6 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info6); + ASSERT_EQ (hash1, info6->head); + ASSERT_FALSE (ledger.rollback (transaction, info6->head)); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); - ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, info1.head)); + ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, info1->head)); ASSERT_TRUE (store.frontier.get (transaction, hash1).is_zero ()); - nano::account_info info7; - ASSERT_FALSE (ledger.store.account.get (transaction, nano::dev::genesis_key.pub, info7)); - ASSERT_EQ (1, info7.block_count); - ASSERT_EQ (info1.head, info7.head); + auto info7 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info7); + ASSERT_EQ (1, info7->block_count); + ASSERT_EQ (info1->head, info7->head); nano::pending_info pending2; ASSERT_TRUE (ledger.store.pending.get (transaction, nano::pending_key (key2.pub, hash1), pending2)); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.account_balance (transaction, nano::dev::genesis_key.pub)); @@ -198,17 +198,17 @@ TEST (ledger, process_receive) auto & store = ctx.store (); auto transaction = store.tx_begin_write (); nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::account_info info1; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); nano::keypair key2; nano::block_builder builder; auto send = builder .send () - .previous (info1.head) + .previous (info1->head) .destination (key2.pub) .balance (50) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); nano::block_hash hash1 (send->hash ()); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); @@ -286,17 +286,17 @@ TEST (ledger, rollback_receiver) auto & store = ctx.store (); auto transaction = store.tx_begin_write (); nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::account_info info1; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); nano::keypair key2; nano::block_builder builder; auto send = builder .send () - .previous (info1.head) + .previous (info1->head) .destination (key2.pub) .balance (50) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); nano::block_hash hash1 (send->hash ()); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); @@ -323,11 +323,10 @@ TEST (ledger, rollback_receiver) ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (0, ledger.weight (key2.pub)); ASSERT_EQ (0, ledger.weight (key3.pub)); - nano::account_info info2; - ASSERT_TRUE (store.account.get (transaction, key2.pub, info2)); + ASSERT_FALSE (ledger.account_info (transaction, key2.pub)); ASSERT_EQ (store.account.count (transaction), ledger.cache.account_count); nano::pending_info pending1; - ASSERT_TRUE (store.pending.get (transaction, nano::pending_key{ key2.pub, info2.head }, pending1)); + ASSERT_TRUE (store.pending.get (transaction, nano::pending_key{ key2.pub, hash1 }, pending1)); } TEST (ledger, rollback_representation) @@ -395,13 +394,13 @@ TEST (ledger, rollback_representation) ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive1).code); ASSERT_EQ (1, ledger.weight (key3.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount - 1, ledger.weight (key4.pub)); - nano::account_info info1; - ASSERT_FALSE (store.account.get (transaction, key2.pub, info1)); - ASSERT_EQ (key4.pub, info1.representative); + auto info1 = ledger.account_info (transaction, key2.pub); + ASSERT_TRUE (info1); + ASSERT_EQ (key4.pub, info1->representative); ASSERT_FALSE (ledger.rollback (transaction, receive1->hash ())); - nano::account_info info2; - ASSERT_FALSE (store.account.get (transaction, key2.pub, info2)); - ASSERT_EQ (key4.pub, info2.representative); + auto info2 = ledger.account_info (transaction, key2.pub); + ASSERT_TRUE (info2); + ASSERT_EQ (key4.pub, info2->representative); ASSERT_EQ (0, ledger.weight (key2.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount - 50, ledger.weight (key4.pub)); ASSERT_FALSE (ledger.rollback (transaction, open->hash ())); @@ -409,13 +408,13 @@ TEST (ledger, rollback_representation) ASSERT_EQ (0, ledger.weight (key4.pub)); ledger.rollback (transaction, send1->hash ()); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (key3.pub)); - nano::account_info info3; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info3)); - ASSERT_EQ (key3.pub, info3.representative); + auto info3 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info3); + ASSERT_EQ (key3.pub, info3->representative); ASSERT_FALSE (ledger.rollback (transaction, change2->hash ())); - nano::account_info info4; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info4)); - ASSERT_EQ (key5.pub, info4.representative); + auto info4 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info4); + ASSERT_EQ (key5.pub, info4->representative); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (key5.pub)); ASSERT_EQ (0, ledger.weight (key3.pub)); } @@ -455,17 +454,17 @@ TEST (ledger, process_duplicate) auto & store = ctx.store (); auto transaction = store.tx_begin_write (); nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::account_info info1; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); nano::keypair key2; nano::block_builder builder; auto send = builder .send () - .previous (info1.head) + .previous (info1->head) .destination (key2.pub) .balance (50) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); nano::block_hash hash1 (send->hash ()); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); @@ -510,34 +509,34 @@ TEST (ledger, representative_change) nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (0, ledger.weight (key2.pub)); - nano::account_info info1; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); nano::block_builder builder; auto block = builder .change () - .previous (info1.head) + .previous (info1->head) .representative (key2.pub) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); - ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, info1.head)); + ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, info1->head)); auto return1 (ledger.process (transaction, *block)); ASSERT_EQ (0, ledger.amount (transaction, block->hash ())); - ASSERT_TRUE (store.frontier.get (transaction, info1.head).is_zero ()); + ASSERT_TRUE (store.frontier.get (transaction, info1->head).is_zero ()); ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, block->hash ())); ASSERT_EQ (nano::process_result::progress, return1.code); ASSERT_EQ (nano::dev::genesis_key.pub, store.block.account_calculated (*block)); ASSERT_EQ (0, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (key2.pub)); - nano::account_info info2; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info2)); - ASSERT_EQ (block->hash (), info2.head); - ASSERT_FALSE (ledger.rollback (transaction, info2.head)); - ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, info1.head)); + auto info2 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info2); + ASSERT_EQ (block->hash (), info2->head); + ASSERT_FALSE (ledger.rollback (transaction, info2->head)); + ASSERT_EQ (nano::dev::genesis_key.pub, store.frontier.get (transaction, info1->head)); ASSERT_TRUE (store.frontier.get (transaction, block->hash ()).is_zero ()); - nano::account_info info3; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info3)); - ASSERT_EQ (info1.head, info3.head); + auto info3 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info3); + ASSERT_EQ (info1->head, info3->head); ASSERT_EQ (nano::dev::constants.genesis_amount, ledger.weight (nano::dev::genesis_key.pub)); ASSERT_EQ (0, ledger.weight (key2.pub)); } @@ -551,25 +550,25 @@ TEST (ledger, send_fork) nano::keypair key3; auto transaction = store.tx_begin_write (); nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::account_info info1; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); nano::block_builder builder; auto block = builder .send () - .previous (info1.head) + .previous (info1->head) .destination (key2.pub) .balance (100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block).code); auto block2 = builder .send () - .previous (info1.head) + .previous (info1->head) .destination (key3.pub) .balance (0) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); ASSERT_EQ (nano::process_result::fork, ledger.process (transaction, *block2).code); } @@ -583,16 +582,16 @@ TEST (ledger, receive_fork) nano::keypair key3; auto transaction = store.tx_begin_write (); nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::account_info info1; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); nano::block_builder builder; auto block = builder .send () - .previous (info1.head) + .previous (info1->head) .destination (key2.pub) .balance (100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block).code); auto block2 = builder @@ -640,16 +639,16 @@ TEST (ledger, open_fork) nano::keypair key3; auto transaction = store.tx_begin_write (); nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::account_info info1; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); nano::block_builder builder; auto block = builder .send () - .previous (info1.head) + .previous (info1->head) .destination (key2.pub) .balance (100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *block).code); auto block2 = builder @@ -2076,17 +2075,17 @@ TEST (ledger, send_open_receive_rollback) auto & store = ctx.store (); auto transaction = store.tx_begin_write (); nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::account_info info1; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); nano::keypair key1; nano::block_builder builder; auto send1 = builder .send () - .previous (info1.head) + .previous (info1->head) .destination (key1.pub) .balance (nano::dev::constants.genesis_amount - 50) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); auto return1 = ledger.process (transaction, *send1); ASSERT_EQ (nano::process_result::progress, return1.code); @@ -2163,20 +2162,20 @@ TEST (ledger, bootstrap_rep_weight) auto ctx = nano::test::context::ledger_empty (); auto & ledger = ctx.ledger (); auto & store = ctx.store (); - nano::account_info info1; nano::keypair key2; nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; { auto transaction = store.tx_begin_write (); - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); nano::block_builder builder; auto send = builder .send () - .previous (info1.head) + .previous (info1->head) .destination (key2.pub) .balance (std::numeric_limits::max () - 50) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); } @@ -2188,15 +2187,16 @@ TEST (ledger, bootstrap_rep_weight) } { auto transaction = store.tx_begin_write (); - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); nano::block_builder builder; auto send = builder .send () - .previous (info1.head) + .previous (info1->head) .destination (key2.pub) .balance (std::numeric_limits::max () - 100) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); } @@ -3369,15 +3369,17 @@ TEST (ledger, epoch_blocks_v1_general) .work (*pool.generate (epoch1->hash ())) .build (); ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, *epoch2).code); - nano::account_info genesis_info; - ASSERT_FALSE (ledger.store.account.get (transaction, nano::dev::genesis->account (), genesis_info)); - ASSERT_EQ (genesis_info.epoch (), nano::epoch::epoch_1); + auto genesis_info = ledger.account_info (transaction, nano::dev::genesis->account ()); + ASSERT_TRUE (genesis_info); + ASSERT_EQ (genesis_info->epoch (), nano::epoch::epoch_1); ASSERT_FALSE (ledger.rollback (transaction, epoch1->hash ())); - ASSERT_FALSE (ledger.store.account.get (transaction, nano::dev::genesis->account (), genesis_info)); - ASSERT_EQ (genesis_info.epoch (), nano::epoch::epoch_0); + genesis_info = ledger.account_info (transaction, nano::dev::genesis->account ()); + ASSERT_TRUE (genesis_info); + ASSERT_EQ (genesis_info->epoch (), nano::epoch::epoch_0); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch1).code); - ASSERT_FALSE (ledger.store.account.get (transaction, nano::dev::genesis->account (), genesis_info)); - ASSERT_EQ (genesis_info.epoch (), nano::epoch::epoch_1); + genesis_info = ledger.account_info (transaction, nano::dev::genesis->account ()); + ASSERT_TRUE (genesis_info); + ASSERT_EQ (genesis_info->epoch (), nano::epoch::epoch_1); ASSERT_FALSE (epoch1->sideband ().details.is_send); ASSERT_FALSE (epoch1->sideband ().details.is_receive); ASSERT_TRUE (epoch1->sideband ().details.is_epoch); @@ -3533,15 +3535,17 @@ TEST (ledger, epoch_blocks_v2_general) .work (*pool.generate (epoch2->hash ())) .build (); ASSERT_EQ (nano::process_result::block_position, ledger.process (transaction, *epoch3).code); - nano::account_info genesis_info; - ASSERT_FALSE (ledger.store.account.get (transaction, nano::dev::genesis->account (), genesis_info)); - ASSERT_EQ (genesis_info.epoch (), nano::epoch::epoch_2); + auto genesis_info = ledger.account_info (transaction, nano::dev::genesis->account ()); + ASSERT_TRUE (genesis_info); + ASSERT_EQ (genesis_info->epoch (), nano::epoch::epoch_2); ASSERT_FALSE (ledger.rollback (transaction, epoch1->hash ())); - ASSERT_FALSE (ledger.store.account.get (transaction, nano::dev::genesis->account (), genesis_info)); - ASSERT_EQ (genesis_info.epoch (), nano::epoch::epoch_0); + genesis_info = ledger.account_info (transaction, nano::dev::genesis->account ()); + ASSERT_TRUE (genesis_info); + ASSERT_EQ (genesis_info->epoch (), nano::epoch::epoch_0); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *epoch1).code); - ASSERT_FALSE (ledger.store.account.get (transaction, nano::dev::genesis->account (), genesis_info)); - ASSERT_EQ (genesis_info.epoch (), nano::epoch::epoch_1); + genesis_info = ledger.account_info (transaction, nano::dev::genesis->account ()); + ASSERT_TRUE (genesis_info); + ASSERT_EQ (genesis_info->epoch (), nano::epoch::epoch_1); auto change1 = builder .change () .previous (epoch1->hash ()) @@ -3713,12 +3717,13 @@ TEST (ledger, epoch_blocks_receive_upgrade) ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive2).code); ASSERT_EQ (nano::epoch::epoch_1, receive2->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_1, receive2->sideband ().source_epoch); - nano::account_info destination_info; - ASSERT_FALSE (ledger.store.account.get (transaction, destination.pub, destination_info)); - ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_1); + auto destination_info = ledger.account_info (transaction, destination.pub); + ASSERT_TRUE (destination_info); + ASSERT_EQ (destination_info->epoch (), nano::epoch::epoch_1); ASSERT_FALSE (ledger.rollback (transaction, receive2->hash ())); - ASSERT_FALSE (ledger.store.account.get (transaction, destination.pub, destination_info)); - ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_0); + destination_info = ledger.account_info (transaction, destination.pub); + ASSERT_TRUE (destination_info); + ASSERT_EQ (destination_info->epoch (), nano::epoch::epoch_0); nano::pending_info pending_send2; ASSERT_FALSE (ledger.store.pending.get (transaction, nano::pending_key (destination.pub, send2->hash ()), pending_send2)); ASSERT_EQ (nano::dev::genesis_key.pub, pending_send2.source); @@ -3727,8 +3732,9 @@ TEST (ledger, epoch_blocks_receive_upgrade) ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive2).code); ASSERT_EQ (nano::epoch::epoch_1, receive2->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_1, receive2->sideband ().source_epoch); - ASSERT_FALSE (ledger.store.account.get (transaction, destination.pub, destination_info)); - ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_1); + destination_info = ledger.account_info (transaction, destination.pub); + ASSERT_TRUE (destination_info); + ASSERT_EQ (destination_info->epoch (), nano::epoch::epoch_1); nano::keypair destination2; auto send3 = builder .state () @@ -3795,8 +3801,9 @@ TEST (ledger, epoch_blocks_receive_upgrade) .work (*pool.generate (send4->hash ())) .build (); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send5).code); - ASSERT_FALSE (ledger.store.account.get (transaction, destination.pub, destination_info)); - ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_1); + destination_info = ledger.account_info (transaction, destination.pub); + ASSERT_TRUE (destination_info); + ASSERT_EQ (destination_info->epoch (), nano::epoch::epoch_1); auto receive3 = builder .state () .account (destination.pub) @@ -3810,8 +3817,9 @@ TEST (ledger, epoch_blocks_receive_upgrade) ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *receive3).code); ASSERT_EQ (nano::epoch::epoch_2, receive3->sideband ().details.epoch); ASSERT_EQ (nano::epoch::epoch_2, receive3->sideband ().source_epoch); - ASSERT_FALSE (ledger.store.account.get (transaction, destination.pub, destination_info)); - ASSERT_EQ (destination_info.epoch (), nano::epoch::epoch_2); + destination_info = ledger.account_info (transaction, destination.pub); + ASSERT_TRUE (destination_info); + ASSERT_EQ (destination_info->epoch (), nano::epoch::epoch_2); // Upgrade an unopened account straight to epoch 2 nano::keypair destination4; auto send6 = builder @@ -4297,9 +4305,9 @@ TEST (ledger, unchecked_epoch) { // Waits for the last blocks to pass through block_processor and unchecked.put queues ASSERT_TIMELY (10s, 0 == node1.unchecked.count (node1.store.tx_begin_read ())); - nano::account_info info{}; - ASSERT_FALSE (node1.store.account.get (node1.store.tx_begin_read (), destination.pub, info)); - ASSERT_EQ (info.epoch (), nano::epoch::epoch_1); + auto info = node1.ledger.account_info (node1.store.tx_begin_read (), destination.pub); + ASSERT_TRUE (info); + ASSERT_EQ (info->epoch (), nano::epoch::epoch_1); } } @@ -4375,9 +4383,9 @@ TEST (ledger, unchecked_epoch_invalid) auto unchecked_count = node1.unchecked.count (transaction); ASSERT_EQ (unchecked_count, 0); ASSERT_EQ (unchecked_count, node1.unchecked.count (transaction)); - nano::account_info info{}; - ASSERT_FALSE (node1.store.account.get (transaction, destination.pub, info)); - ASSERT_NE (info.epoch (), nano::epoch::epoch_1); + auto info = node1.ledger.account_info (transaction, destination.pub); + ASSERT_TRUE (info); + ASSERT_NE (info->epoch (), nano::epoch::epoch_1); auto epoch2_store = node1.store.block.get (transaction, epoch2->hash ()); ASSERT_NE (nullptr, epoch2_store); ASSERT_EQ (nano::epoch::epoch_0, epoch2_store->sideband ().details.epoch); @@ -4516,17 +4524,17 @@ TEST (ledger, confirmation_height_not_updated) auto & store = ctx.store (); auto transaction = store.tx_begin_write (); nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::account_info account_info; - ASSERT_FALSE (store.account.get (transaction, nano::dev::genesis_key.pub, account_info)); + auto account_info = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (account_info); nano::keypair key; nano::block_builder builder; auto send1 = builder .send () - .previous (account_info.head) + .previous (account_info->head) .destination (key.pub) .balance (50) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (account_info.head)) + .work (*pool.generate (account_info->head)) .build (); nano::confirmation_height_info confirmation_height_info; ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis->account (), confirmation_height_info)); diff --git a/nano/core_test/ledger_walker.cpp b/nano/core_test/ledger_walker.cpp index 86c1ea1abc..f3634d60a5 100644 --- a/nano/core_test/ledger_walker.cpp +++ b/nano/core_test/ledger_walker.cpp @@ -64,10 +64,10 @@ TEST (ledger_walker, genesis_account_longer) }; auto const transaction = node->ledger.store.tx_begin_read (); - nano::account_info genesis_account_info{}; - ASSERT_FALSE (node->ledger.store.account.get (transaction, nano::dev::genesis_key.pub, genesis_account_info)); - EXPECT_EQ (get_number_of_walked_blocks (genesis_account_info.open_block), 1); - EXPECT_EQ (get_number_of_walked_blocks (genesis_account_info.head), 1); + auto genesis_account_info = node->ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (genesis_account_info); + EXPECT_EQ (get_number_of_walked_blocks (genesis_account_info->open_block), 1); + EXPECT_EQ (get_number_of_walked_blocks (genesis_account_info->head), 1); system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); for (auto itr = 1; itr <= 5; ++itr) @@ -76,7 +76,7 @@ TEST (ledger_walker, genesis_account_longer) ASSERT_TRUE (send); EXPECT_EQ (get_number_of_walked_blocks (send->hash ()), 1 + itr * 2 - 1); ASSERT_TIMELY (3s, 1 + itr * 2 == node->ledger.cache.cemented_count); - ASSERT_FALSE (node->ledger.store.account.get (transaction, nano::dev::genesis_key.pub, genesis_account_info)); + ASSERT_TRUE (node->ledger.account_info (transaction, nano::dev::genesis_key.pub)); // TODO: check issue with account head // EXPECT_EQ(get_number_of_walked_blocks (genesis_account_info.head), 1 + itr * 2); } @@ -107,8 +107,8 @@ TEST (ledger_walker, cross_account) ASSERT_TIMELY (3s, 5 == node->ledger.cache.cemented_count); auto const transaction = node->ledger.store.tx_begin_read (); - nano::account_info account_info{}; - ASSERT_FALSE (node->ledger.store.account.get (transaction, key.pub, account_info)); + auto account_info = node->ledger.account_info (transaction, key.pub); + ASSERT_TRUE (account_info); // TODO: check issue with account head // auto const first = node->ledger.store.block.get_no_sideband(transaction, account_info.head); @@ -174,9 +174,8 @@ TEST (ledger_walker, DISABLED_ladder_geometry) } ASSERT_TRUE (last_destination); - nano::account_info last_destination_info{}; - auto const last_destination_read_error = node->ledger.store.account.get (node->ledger.store.tx_begin_read (), *last_destination, last_destination_info); - ASSERT_FALSE (last_destination_read_error); + auto last_destination_info = node->ledger.account_info (node->ledger.store.tx_begin_read (), *last_destination); + ASSERT_TRUE (last_destination_info); // This is how we expect chains to look like (for 3 accounts and 10 amounts to be sent) // k1: 1000 SEND 3 SEND 6 SEND 9 SEND @@ -187,7 +186,7 @@ TEST (ledger_walker, DISABLED_ladder_geometry) auto amounts_expected_backwards_itr = amounts_expected_backwards.cbegin (); nano::ledger_walker ledger_walker{ node->ledger }; - ledger_walker.walk_backward (last_destination_info.head, + ledger_walker.walk_backward (last_destination_info->head, [&] (auto const & block) { if (block->sideband ().details.is_receive) { @@ -206,7 +205,7 @@ TEST (ledger_walker, DISABLED_ladder_geometry) auto amounts_expected_itr = amounts_expected_backwards.crbegin (); - ledger_walker.walk (last_destination_info.head, + ledger_walker.walk (last_destination_info->head, [&] (auto const & block) { if (block->sideband ().details.is_receive) { diff --git a/nano/core_test/processor_service.cpp b/nano/core_test/processor_service.cpp index e610eafd39..c873a80dc7 100644 --- a/nano/core_test/processor_service.cpp +++ b/nano/core_test/processor_service.cpp @@ -17,17 +17,17 @@ TEST (processor_service, bad_send_signature) auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger.cache, ledger.constants); nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::account_info info1; - ASSERT_FALSE (store->account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); nano::keypair key2; nano::block_builder builder; auto send = builder .send () - .previous (info1.head) + .previous (info1->head) .destination (nano::dev::genesis_key.pub) .balance (50) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); send->signature.bytes[32] ^= 0x1; ASSERT_EQ (nano::process_result::bad_signature, ledger.process (transaction, *send).code); @@ -43,21 +43,21 @@ TEST (processor_service, bad_receive_signature) auto transaction (store->tx_begin_write ()); store->initialize (transaction, ledger.cache, ledger.constants); nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::account_info info1; - ASSERT_FALSE (store->account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); nano::block_builder builder; auto send = builder .send () - .previous (info1.head) + .previous (info1->head) .destination (nano::dev::genesis_key.pub) .balance (50) .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (info1.head)) + .work (*pool.generate (info1->head)) .build (); nano::block_hash hash1 (send->hash ()); ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, *send).code); - nano::account_info info2; - ASSERT_FALSE (store->account.get (transaction, nano::dev::genesis_key.pub, info2)); + auto info2 = ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info2); auto receive = builder .receive () .previous (hash1) diff --git a/nano/core_test/system.cpp b/nano/core_test/system.cpp index 1f57fd264e..2673d4de1d 100644 --- a/nano/core_test/system.cpp +++ b/nano/core_test/system.cpp @@ -41,11 +41,8 @@ TEST (system, DISABLED_generate_send_existing) system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); nano::keypair stake_preserver; auto send_block (system.wallet (0)->send_action (nano::dev::genesis->account (), stake_preserver.pub, nano::dev::constants.genesis_amount / 3 * 2, true)); - nano::account_info info1; - { - auto transaction (node1.store.tx_begin_read ()); - ASSERT_FALSE (node1.store.account.get (transaction, nano::dev::genesis_key.pub, info1)); - } + auto info1 = node1.ledger.account_info (node1.store.tx_begin_read (), nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); std::vector accounts; accounts.push_back (nano::dev::genesis_key.pub); system.generate_send_existing (node1, accounts); @@ -65,24 +62,22 @@ TEST (system, DISABLED_generate_send_existing) ASSERT_EQ (nano::process_result::progress, node1.ledger.process (transaction, *open_block).code); } ASSERT_GT (node1.balance (stake_preserver.pub), node1.balance (nano::dev::genesis->account ())); - nano::account_info info2; - { - auto transaction (node1.store.tx_begin_read ()); - ASSERT_FALSE (node1.store.account.get (transaction, nano::dev::genesis_key.pub, info2)); - } - ASSERT_NE (info1.head, info2.head); + auto info2 = node1.ledger.account_info (node1.store.tx_begin_read (), nano::dev::genesis_key.pub); + ASSERT_TRUE (info2); + ASSERT_NE (info1->head, info2->head); system.deadline_set (15s); - while (info2.block_count < info1.block_count + 2) + while (info2->block_count < info1->block_count + 2) { ASSERT_NO_ERROR (system.poll ()); auto transaction (node1.store.tx_begin_read ()); - ASSERT_FALSE (node1.store.account.get (transaction, nano::dev::genesis_key.pub, info2)); + info2 = node1.ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info2); } - ASSERT_EQ (info1.block_count + 2, info2.block_count); - ASSERT_EQ (info2.balance, nano::dev::constants.genesis_amount / 3); + ASSERT_EQ (info1->block_count + 2, info2->block_count); + ASSERT_EQ (info2->balance, nano::dev::constants.genesis_amount / 3); { auto transaction (node1.store.tx_begin_read ()); - ASSERT_NE (node1.ledger.amount (transaction, info2.head), 0); + ASSERT_NE (node1.ledger.amount (transaction, info2->head), 0); } system.stop (); runner.join (); diff --git a/nano/core_test/wallet.cpp b/nano/core_test/wallet.cpp index 31de39eb75..020db0d502 100644 --- a/nano/core_test/wallet.cpp +++ b/nano/core_test/wallet.cpp @@ -180,16 +180,13 @@ TEST (wallet, spend_all_one) system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); nano::keypair key2; ASSERT_NE (nullptr, system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, std::numeric_limits::max ())); - nano::account_info info2; - { - auto transaction (node1.store.tx_begin_read ()); - node1.store.account.get (transaction, nano::dev::genesis_key.pub, info2); - ASSERT_NE (latest1, info2.head); - auto block (node1.store.block.get (transaction, info2.head)); - ASSERT_NE (nullptr, block); - ASSERT_EQ (latest1, block->previous ()); - } - ASSERT_TRUE (info2.balance.is_zero ()); + auto transaction (node1.store.tx_begin_read ()); + auto info2 = node1.ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_NE (latest1, info2->head); + auto block (node1.store.block.get (transaction, info2->head)); + ASSERT_NE (nullptr, block); + ASSERT_EQ (latest1, block->previous ()); + ASSERT_TRUE (info2->balance.is_zero ()); ASSERT_EQ (0, node1.balance (nano::dev::genesis_key.pub)); } @@ -217,16 +214,14 @@ TEST (wallet, spend) // Sending from empty accounts should always be an error. Accounts need to be opened with an open block, not a send block. ASSERT_EQ (nullptr, system.wallet (0)->send_action (0, key2.pub, 0)); ASSERT_NE (nullptr, system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, std::numeric_limits::max ())); - nano::account_info info2; - { - auto transaction (node1.store.tx_begin_read ()); - node1.store.account.get (transaction, nano::dev::genesis_key.pub, info2); - ASSERT_NE (latest1, info2.head); - auto block (node1.store.block.get (transaction, info2.head)); - ASSERT_NE (nullptr, block); - ASSERT_EQ (latest1, block->previous ()); - } - ASSERT_TRUE (info2.balance.is_zero ()); + auto transaction (node1.store.tx_begin_read ()); + auto info2 = node1.ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info2); + ASSERT_NE (latest1, info2->head); + auto block (node1.store.block.get (transaction, info2->head)); + ASSERT_NE (nullptr, block); + ASSERT_EQ (latest1, block->previous ()); + ASSERT_TRUE (info2->balance.is_zero ()); ASSERT_EQ (0, node1.balance (nano::dev::genesis_key.pub)); } @@ -258,8 +253,8 @@ TEST (wallet, spend_no_previous) { system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv); auto transaction (system.nodes[0]->store.tx_begin_read ()); - nano::account_info info1; - ASSERT_FALSE (system.nodes[0]->store.account.get (transaction, nano::dev::genesis_key.pub, info1)); + auto info1 = system.nodes[0]->ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info1); for (auto i (0); i < 50; ++i) { nano::keypair key; diff --git a/nano/lib/blocks.hpp b/nano/lib/blocks.hpp index 97770f0111..a4320dc4f1 100644 --- a/nano/lib/blocks.hpp +++ b/nano/lib/blocks.hpp @@ -128,6 +128,9 @@ class block private: nano::block_hash generate_hash () const; }; + +using block_list_t = std::vector>; + class send_hashables { public: diff --git a/nano/node/CMakeLists.txt b/nano/node/CMakeLists.txt index a8bd9dcf71..d4c36ef975 100644 --- a/nano/node/CMakeLists.txt +++ b/nano/node/CMakeLists.txt @@ -84,6 +84,8 @@ add_library( election.cpp election_scheduler.hpp election_scheduler.cpp + epoch_upgrader.hpp + epoch_upgrader.cpp gap_cache.hpp gap_cache.cpp hinted_scheduler.hpp diff --git a/nano/node/active_transactions.cpp b/nano/node/active_transactions.cpp index 7eb1ff0254..b07a6298e2 100644 --- a/nano/node/active_transactions.cpp +++ b/nano/node/active_transactions.cpp @@ -38,6 +38,11 @@ nano::active_transactions::~active_transactions () void nano::active_transactions::start () { + if (node.flags.disable_request_loop) + { + return; + } + debug_assert (!thread.joinable ()); thread = std::thread ([this] () { @@ -48,12 +53,12 @@ void nano::active_transactions::start () void nano::active_transactions::stop () { - stopped = true; - condition.notify_all (); - if (thread.joinable ()) { - thread.join (); + nano::lock_guard guard{ mutex }; + stopped = true; } + condition.notify_all (); + nano::join_or_pass (thread); clear (); } @@ -332,7 +337,7 @@ std::vector> nano::active_transactions::list_act void nano::active_transactions::request_loop () { nano::unique_lock lock{ mutex }; - while (!stopped && !node.flags.disable_request_loop) + while (!stopped) { auto const stamp_l = std::chrono::steady_clock::now (); diff --git a/nano/node/active_transactions.hpp b/nano/node/active_transactions.hpp index f99a8583b5..54a6b6f2c9 100644 --- a/nano/node/active_transactions.hpp +++ b/nano/node/active_transactions.hpp @@ -139,7 +139,7 @@ class active_transactions final std::unordered_map> blocks; public: - explicit active_transactions (nano::node &, nano::confirmation_height_processor &); + active_transactions (nano::node &, nano::confirmation_height_processor &); ~active_transactions (); void start (); @@ -233,7 +233,7 @@ class active_transactions final int active_hinted_elections_count{ 0 }; nano::condition_variable condition; - std::atomic stopped{ false }; + bool stopped{ false }; std::thread thread; friend class election; diff --git a/nano/node/bootstrap/bootstrap_bulk_pull.cpp b/nano/node/bootstrap/bootstrap_bulk_pull.cpp index f1420593fb..10f04329d5 100644 --- a/nano/node/bootstrap/bootstrap_bulk_pull.cpp +++ b/nano/node/bootstrap/bootstrap_bulk_pull.cpp @@ -353,9 +353,8 @@ void nano::bulk_pull_server::set_current_end () } else { - nano::account_info info; - auto no_address (connection->node->store.account.get (transaction, request->start.as_account (), info)); - if (no_address) + auto info = connection->node->ledger.account_info (transaction, request->start.as_account ()); + if (!info) { if (connection->node->config.logging.bulk_pull_logging ()) { @@ -365,7 +364,7 @@ void nano::bulk_pull_server::set_current_end () } else { - current = ascending () ? info.open_block : info.head; + current = ascending () ? info->open_block : info->head; if (!request->end.is_zero ()) { auto account (connection->node->ledger.account (transaction, request->end)); diff --git a/nano/node/bootstrap/bootstrap_server.cpp b/nano/node/bootstrap/bootstrap_server.cpp index 194fa1755b..1ff63a48dd 100644 --- a/nano/node/bootstrap/bootstrap_server.cpp +++ b/nano/node/bootstrap/bootstrap_server.cpp @@ -184,7 +184,7 @@ nano::asc_pull_ack nano::bootstrap_server::process (nano::transaction const & tr break; case asc_pull_req::hash_type::account: { - auto info = store.account.get (transaction, request.start.as_account ()); + auto info = ledger.account_info (transaction, request.start.as_account ()); if (info) { // Start from open block if pulling by account @@ -278,7 +278,7 @@ nano::asc_pull_ack nano::bootstrap_server::process (const nano::transaction & tr nano::asc_pull_ack::account_info_payload response_payload{}; response_payload.account = target; - auto account_info = store.account.get (transaction, target); + auto account_info = ledger.account_info (transaction, target); if (account_info) { response_payload.account_open = account_info->open_block; @@ -297,4 +297,4 @@ nano::asc_pull_ack nano::bootstrap_server::process (const nano::transaction & tr response.payload = response_payload; response.update_header (); return response; -} \ No newline at end of file +} diff --git a/nano/node/confirmation_height_bounded.cpp b/nano/node/confirmation_height_bounded.cpp index 86a9e3d9c5..7ba0767ab2 100644 --- a/nano/node/confirmation_height_bounded.cpp +++ b/nano/node/confirmation_height_bounded.cpp @@ -237,9 +237,9 @@ nano::block_hash nano::confirmation_height_bounded::get_least_unconfirmed_hash_f else { // No blocks have been confirmed, so the first block will be the open block - nano::account_info account_info; - release_assert (!ledger.store.account.get (transaction_a, account_a, account_info)); - least_unconfirmed_hash = account_info.open_block; + auto info = ledger.account_info (transaction_a, account_a); + release_assert (info); + least_unconfirmed_hash = info->open_block; block_height_a = 1; } return least_unconfirmed_hash; diff --git a/nano/node/election_scheduler.cpp b/nano/node/election_scheduler.cpp index 65f23299ec..966f931f92 100644 --- a/nano/node/election_scheduler.cpp +++ b/nano/node/election_scheduler.cpp @@ -24,15 +24,15 @@ void nano::election_scheduler::manual (std::shared_ptr const & bloc bool nano::election_scheduler::activate (nano::account const & account_a, nano::transaction const & transaction) { debug_assert (!account_a.is_zero ()); - nano::account_info account_info; - if (!node.store.account.get (transaction, account_a, account_info)) + auto info = node.ledger.account_info (transaction, account_a); + if (info) { nano::confirmation_height_info conf_info; node.store.confirmation_height.get (transaction, account_a, conf_info); - if (conf_info.height < account_info.block_count) + if (conf_info.height < info->block_count) { - debug_assert (conf_info.frontier != account_info.head); - auto hash = conf_info.height == 0 ? account_info.open_block : node.store.block.successor (transaction, conf_info.frontier); + debug_assert (conf_info.frontier != info->head); + auto hash = conf_info.height == 0 ? info->open_block : node.store.block.successor (transaction, conf_info.frontier); auto block = node.store.block.get (transaction, hash); debug_assert (block != nullptr); if (node.ledger.dependents_confirmed (transaction, *block)) @@ -40,7 +40,7 @@ bool nano::election_scheduler::activate (nano::account const & account_a, nano:: auto balance = node.ledger.balance (transaction, hash); auto previous_balance = node.ledger.balance (transaction, conf_info.frontier); nano::lock_guard lock{ mutex }; - priority.push (account_info.modified, block, std::max (balance, previous_balance)); + priority.push (info->modified, block, std::max (balance, previous_balance)); notify (); return true; // Activated } diff --git a/nano/node/epoch_upgrader.cpp b/nano/node/epoch_upgrader.cpp new file mode 100644 index 0000000000..ae83291de9 --- /dev/null +++ b/nano/node/epoch_upgrader.cpp @@ -0,0 +1,300 @@ +#include +#include +#include + +nano::epoch_upgrader::epoch_upgrader (nano::node & node_a, nano::ledger & ledger_a, nano::store & store_a, nano::network_params & network_params_a, nano::logger_mt & logger_a) : + node{ node_a }, + ledger{ ledger_a }, + store{ store_a }, + network_params{ network_params_a }, + logger{ logger_a } +{ +} + +void nano::epoch_upgrader::stop () +{ + stopped = true; + + auto epoch_upgrade = epoch_upgrading.lock (); + if (epoch_upgrade->valid ()) + { + epoch_upgrade->wait (); + } +} + +bool nano::epoch_upgrader::start (nano::raw_key const & prv_a, nano::epoch epoch_a, uint64_t count_limit, uint64_t threads) +{ + bool error = stopped.load (); + if (!error) + { + auto epoch_upgrade = epoch_upgrading.lock (); + error = epoch_upgrade->valid () && epoch_upgrade->wait_for (std::chrono::seconds (0)) == std::future_status::timeout; + if (!error) + { + *epoch_upgrade = std::async (std::launch::async, [this, prv_a, epoch_a, count_limit, threads] () { + upgrade_impl (prv_a, epoch_a, count_limit, threads); + }); + } + } + return error; +} + +// TODO: This method should be a class +void nano::epoch_upgrader::upgrade_impl (nano::raw_key const & prv_a, nano::epoch epoch_a, uint64_t count_limit, uint64_t threads) +{ + nano::thread_role::set (nano::thread_role::name::epoch_upgrader); + auto upgrader_process = [this] (std::atomic & counter, std::shared_ptr const & epoch, uint64_t difficulty, nano::public_key const & signer_a, nano::root const & root_a, nano::account const & account_a) { + epoch->block_work_set (node.work_generate_blocking (nano::work_version::work_1, root_a, difficulty).value_or (0)); + bool valid_signature (!nano::validate_message (signer_a, epoch->hash (), epoch->block_signature ())); + bool valid_work (node.network_params.work.difficulty (*epoch) >= difficulty); + nano::process_result result (nano::process_result::old); + if (valid_signature && valid_work) + { + result = node.process_local (epoch).code; + } + if (result == nano::process_result::progress) + { + ++counter; + } + else + { + bool fork (result == nano::process_result::fork); + logger.always_log (boost::str (boost::format ("Failed to upgrade account %1%. Valid signature: %2%. Valid work: %3%. Block processor fork: %4%") % account_a.to_account () % valid_signature % valid_work % fork)); + } + }; + + uint64_t const upgrade_batch_size = 1000; + nano::block_builder builder; + auto link (ledger.epoch_link (epoch_a)); + nano::raw_key raw_key; + raw_key = prv_a; + auto signer (nano::pub_key (prv_a)); + debug_assert (signer == ledger.epoch_signer (link)); + + nano::mutex upgrader_mutex; + nano::condition_variable upgrader_condition; + + class account_upgrade_item final + { + public: + nano::account account{}; + uint64_t modified{ 0 }; + }; + class account_tag + { + }; + class modified_tag + { + }; + // clang-format off + boost::multi_index_container, + boost::multi_index::member, + std::greater>, + boost::multi_index::hashed_unique, + boost::multi_index::member>>> + accounts_list; + // clang-format on + + bool finished_upgrade (false); + + while (!finished_upgrade && !stopped) + { + bool finished_accounts (false); + uint64_t total_upgraded_accounts (0); + while (!finished_accounts && count_limit != 0 && !stopped) + { + { + 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) + { + nano::account const & account (i->first); + nano::account_info const & info (i->second); + if (info.epoch () < epoch_a) + { + release_assert (nano::epochs::is_sequential (info.epoch (), epoch_a)); + accounts_list.emplace (account_upgrade_item{ account, info.modified }); + } + } + } + + /* Upgrade accounts + Repeat until accounts with previous epoch exist in latest table */ + std::atomic upgraded_accounts (0); + uint64_t workers (0); + uint64_t attempts (0); + for (auto i (accounts_list.get ().begin ()), n (accounts_list.get ().end ()); i != n && attempts < upgrade_batch_size && attempts < count_limit && !stopped; ++i) + { + auto transaction (store.tx_begin_read ()); + nano::account const & account (i->account); + auto info = ledger.account_info (transaction, account); + if (info && info->epoch () < epoch_a) + { + ++attempts; + auto difficulty (node.network_params.work.threshold (nano::work_version::work_1, nano::block_details (epoch_a, false, false, true))); + nano::root const & root (info->head); + std::shared_ptr epoch = builder.state () + .account (account) + .previous (info->head) + .representative (info->representative) + .balance (info->balance) + .link (link) + .sign (raw_key, signer) + .work (0) + .build (); + if (threads != 0) + { + { + nano::unique_lock lock{ upgrader_mutex }; + ++workers; + while (workers > threads) + { + upgrader_condition.wait (lock); + } + } + node.workers.push_task ([&upgrader_process, &upgrader_mutex, &upgrader_condition, &upgraded_accounts, &workers, epoch, difficulty, signer, root, account] () { + upgrader_process (upgraded_accounts, epoch, difficulty, signer, root, account); + { + nano::lock_guard lock{ upgrader_mutex }; + --workers; + } + upgrader_condition.notify_all (); + }); + } + else + { + upgrader_process (upgraded_accounts, epoch, difficulty, signer, root, account); + } + } + } + { + nano::unique_lock lock{ upgrader_mutex }; + while (workers > 0) + { + upgrader_condition.wait (lock); + } + } + total_upgraded_accounts += upgraded_accounts; + count_limit -= upgraded_accounts; + + if (!accounts_list.empty ()) + { + logger.always_log (boost::str (boost::format ("%1% accounts were upgraded to new epoch, %2% remain...") % total_upgraded_accounts % (accounts_list.size () - upgraded_accounts))); + accounts_list.clear (); + } + else + { + logger.always_log (boost::str (boost::format ("%1% total accounts were upgraded to new epoch") % total_upgraded_accounts)); + finished_accounts = true; + } + } + + // Pending blocks upgrade + bool finished_pending (false); + uint64_t total_upgraded_pending (0); + while (!finished_pending && count_limit != 0 && !stopped) + { + std::atomic upgraded_pending (0); + uint64_t workers (0); + uint64_t attempts (0); + auto transaction (store.tx_begin_read ()); + for (auto i (store.pending.begin (transaction, nano::pending_key (1, 0))), n (store.pending.end ()); i != n && attempts < upgrade_batch_size && attempts < count_limit && !stopped;) + { + bool to_next_account (false); + nano::pending_key const & key (i->first); + if (!store.account.exists (transaction, key.account)) + { + nano::pending_info const & info (i->second); + if (info.epoch < epoch_a) + { + ++attempts; + release_assert (nano::epochs::is_sequential (info.epoch, epoch_a)); + auto difficulty (network_params.work.threshold (nano::work_version::work_1, nano::block_details (epoch_a, false, false, true))); + nano::root const & root (key.account); + nano::account const & account (key.account); + std::shared_ptr epoch = builder.state () + .account (key.account) + .previous (0) + .representative (0) + .balance (0) + .link (link) + .sign (raw_key, signer) + .work (0) + .build (); + if (threads != 0) + { + { + nano::unique_lock lock{ upgrader_mutex }; + ++workers; + while (workers > threads) + { + upgrader_condition.wait (lock); + } + } + node.workers.push_task ([&upgrader_process, &upgrader_mutex, &upgrader_condition, &upgraded_pending, &workers, epoch, difficulty, signer, root, account] () { + upgrader_process (upgraded_pending, epoch, difficulty, signer, root, account); + { + nano::lock_guard lock{ upgrader_mutex }; + --workers; + } + upgrader_condition.notify_all (); + }); + } + else + { + upgrader_process (upgraded_pending, epoch, difficulty, signer, root, account); + } + } + } + else + { + to_next_account = true; + } + if (to_next_account) + { + // Move to next account if pending account exists or was upgraded + if (key.account.number () == std::numeric_limits::max ()) + { + break; + } + else + { + i = store.pending.begin (transaction, nano::pending_key (key.account.number () + 1, 0)); + } + } + else + { + // Move to next pending item + ++i; + } + } + { + nano::unique_lock lock{ upgrader_mutex }; + while (workers > 0) + { + upgrader_condition.wait (lock); + } + } + + total_upgraded_pending += upgraded_pending; + count_limit -= upgraded_pending; + + // Repeat if some pending accounts were upgraded + if (upgraded_pending != 0) + { + logger.always_log (boost::str (boost::format ("%1% unopened accounts with pending blocks were upgraded to new epoch...") % total_upgraded_pending)); + } + else + { + logger.always_log (boost::str (boost::format ("%1% total unopened accounts with pending blocks were upgraded to new epoch") % total_upgraded_pending)); + finished_pending = true; + } + } + + finished_upgrade = (total_upgraded_accounts == 0) && (total_upgraded_pending == 0); + } + + logger.always_log ("Epoch upgrade is completed"); +} diff --git a/nano/node/epoch_upgrader.hpp b/nano/node/epoch_upgrader.hpp new file mode 100644 index 0000000000..fb16b4d564 --- /dev/null +++ b/nano/node/epoch_upgrader.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +#include + +namespace nano +{ +class node; +class ledger; +class store; +class network_params; +class logger_mt; + +class epoch_upgrader final +{ +public: + epoch_upgrader (nano::node &, nano::ledger &, nano::store &, nano::network_params &, nano::logger_mt &); + + bool start (nano::raw_key const & prv, nano::epoch epoch, uint64_t count_limit, uint64_t threads); + void stop (); + +private: // Dependencies + nano::node & node; + nano::ledger & ledger; + nano::store & store; + nano::network_params & network_params; + nano::logger_mt & logger; + +private: + void upgrade_impl (nano::raw_key const & prv, nano::epoch epoch, uint64_t count_limit, uint64_t threads); + + std::atomic stopped{ false }; + nano::locked> epoch_upgrading; +}; +} \ No newline at end of file diff --git a/nano/node/hinted_scheduler.cpp b/nano/node/hinted_scheduler.cpp index 76eef07d6d..588669af6e 100644 --- a/nano/node/hinted_scheduler.cpp +++ b/nano/node/hinted_scheduler.cpp @@ -8,33 +8,34 @@ nano::hinted_scheduler::hinted_scheduler (config const & config_a, nano::node & inactive_vote_cache{ inactive_vote_cache_a }, active{ active_a }, online_reps{ online_reps_a }, - stats{ stats_a }, - stopped{ false } + stats{ stats_a } { } nano::hinted_scheduler::~hinted_scheduler () { - stop (); - if (thread.joinable ()) // Ensure thread was started - { - thread.join (); - } + // Thread must be stopped before destruction + debug_assert (!thread.joinable ()); } void nano::hinted_scheduler::start () { debug_assert (!thread.joinable ()); - thread = std::thread{ - [this] () { run (); } - }; + + thread = std::thread{ [this] () { + nano::thread_role::set (nano::thread_role::name::election_hinting); + run (); + } }; } void nano::hinted_scheduler::stop () { - nano::unique_lock lock{ mutex }; - stopped = true; + { + nano::lock_guard lock{ mutex }; + stopped = true; + } notify (); + nano::join_or_pass (thread); } void nano::hinted_scheduler::notify () @@ -91,7 +92,6 @@ bool nano::hinted_scheduler::run_one (nano::uint128_t const & minimum_tally) void nano::hinted_scheduler::run () { - nano::thread_role::set (nano::thread_role::name::election_hinting); nano::unique_lock lock{ mutex }; while (!stopped) { @@ -124,6 +124,6 @@ void nano::hinted_scheduler::run () nano::uint128_t nano::hinted_scheduler::tally_threshold () const { - const auto min_tally = (online_reps.trended () / 100) * node.config.election_hint_weight_percent; + auto min_tally = (online_reps.trended () / 100) * node.config.election_hint_weight_percent; return min_tally; } diff --git a/nano/node/hinted_scheduler.hpp b/nano/node/hinted_scheduler.hpp index 92d475a541..1ccb9c51b3 100644 --- a/nano/node/hinted_scheduler.hpp +++ b/nano/node/hinted_scheduler.hpp @@ -27,11 +27,12 @@ class hinted_scheduler final }; public: - explicit hinted_scheduler (config const &, nano::node &, nano::vote_cache &, nano::active_transactions &, nano::online_reps &, nano::stats &); + hinted_scheduler (config const &, nano::node &, nano::vote_cache &, nano::active_transactions &, nano::online_reps &, nano::stats &); ~hinted_scheduler (); void start (); void stop (); + /* * Notify about changes in AEC vacancy */ @@ -54,7 +55,7 @@ class hinted_scheduler final private: config const config_m; - bool stopped; + bool stopped{ false }; nano::condition_variable condition; mutable nano::mutex mutex; std::thread thread; diff --git a/nano/node/json_handler.cpp b/nano/node/json_handler.cpp index 5c16f78c2c..304d17eb40 100644 --- a/nano/node/json_handler.cpp +++ b/nano/node/json_handler.cpp @@ -261,11 +261,16 @@ nano::account_info nano::json_handler::account_info_impl (nano::transaction cons nano::account_info result; if (!ec) { - if (node.store.account.get (transaction_a, account_a, result)) + auto info = node.ledger.account_info (transaction_a, account_a); + if (!info) { ec = nano::error_common::account_not_found; node.bootstrap_initiator.bootstrap_lazy (account_a, false, account_a.to_account ()); } + else + { + result = *info; + } } return result; } @@ -2290,7 +2295,7 @@ void nano::json_handler::epoch_upgrade () { if (nano::pub_key (prv) == node.ledger.epoch_signer (node.ledger.epoch_link (epoch))) { - if (!node.epoch_upgrader (prv, epoch, count_limit, threads)) + if (!node.epoch_upgrader.start (prv, epoch, count_limit, threads)) { response_l.put ("started", "1"); } @@ -3377,14 +3382,14 @@ void nano::json_handler::receive () auto work (work_optional_impl ()); if (!ec && work) { - nano::account_info info; nano::root head; nano::epoch epoch = pending_info.epoch; - if (!node.store.account.get (block_transaction, account, info)) + auto info = node.ledger.account_info (block_transaction, account); + if (info) { - head = info.head; + head = info->head; // When receiving, epoch version is the higher between the previous and the source blocks - epoch = std::max (info.epoch (), epoch); + epoch = std::max (info->epoch (), epoch); } else { @@ -4395,10 +4400,11 @@ void nano::json_handler::wallet_info () { nano::account const & account (i->first); - nano::account_info account_info{}; - if (!node.store.account.get (block_transaction, account, account_info)) + auto account_info = node.ledger.account_info (block_transaction, account); + if (account_info) { - block_count += account_info.block_count; + block_count += account_info->block_count; + balance += account_info->balance.number (); } nano::confirmation_height_info confirmation_info{}; @@ -4407,7 +4413,6 @@ void nano::json_handler::wallet_info () cemented_block_count += confirmation_info.height; } - balance += account_info.balance.number (); receivable += node.ledger.account_receivable (block_transaction, account); nano::key_type key_type (wallet->store.key_type (i->second)); @@ -4632,11 +4637,11 @@ void nano::json_handler::wallet_history () for (auto i (wallet->store.begin (transaction)), n (wallet->store.end ()); i != n; ++i) { nano::account const & account (i->first); - nano::account_info info; - if (!node.store.account.get (block_transaction, account, info)) + auto info = node.ledger.account_info (block_transaction, account); + if (info) { - auto timestamp (info.modified); - auto hash (info.head); + auto timestamp (info->modified); + auto hash (info->head); while (timestamp >= modified_since && !hash.is_zero ()) { auto block (node.store.block.get (block_transaction, hash)); @@ -4706,23 +4711,23 @@ void nano::json_handler::wallet_ledger () for (auto i (wallet->store.begin (transaction)), n (wallet->store.end ()); i != n; ++i) { nano::account const & account (i->first); - nano::account_info info; - if (!node.store.account.get (block_transaction, account, info)) + auto info = node.ledger.account_info (block_transaction, account); + if (info) { - if (info.modified >= modified_since) + if (info->modified >= modified_since) { boost::property_tree::ptree entry; - entry.put ("frontier", info.head.to_string ()); - entry.put ("open_block", info.open_block.to_string ()); - entry.put ("representative_block", node.ledger.representative (block_transaction, info.head).to_string ()); + entry.put ("frontier", info->head.to_string ()); + entry.put ("open_block", info->open_block.to_string ()); + entry.put ("representative_block", node.ledger.representative (block_transaction, info->head).to_string ()); std::string balance; - nano::uint128_union (info.balance).encode_dec (balance); + nano::uint128_union (info->balance).encode_dec (balance); entry.put ("balance", balance); - entry.put ("modified_timestamp", std::to_string (info.modified)); - entry.put ("block_count", std::to_string (info.block_count)); + entry.put ("modified_timestamp", std::to_string (info->modified)); + entry.put ("block_count", std::to_string (info->block_count)); if (representative) { - entry.put ("representative", info.representative.to_account ()); + entry.put ("representative", info->representative.to_account ()); } if (weight) { @@ -4872,10 +4877,10 @@ void nano::json_handler::wallet_representative_set () for (auto i (wallet->store.begin (transaction)), n (wallet->store.end ()); i != n; ++i) { nano::account const & account (i->first); - nano::account_info info; - if (!rpc_l->node.store.account.get (block_transaction, account, info)) + auto info = rpc_l->node.ledger.account_info (block_transaction, account); + if (info) { - if (info.representative != representative) + if (info->representative != representative) { accounts.push_back (account); } diff --git a/nano/node/node.cpp b/nano/node/node.cpp index 457bda4505..fc24eebab7 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -201,6 +201,7 @@ nano::node::node (boost::asio::io_context & io_ctx_a, boost::filesystem::path co wallets (wallets_store.init_error (), *this), backlog{ nano::backlog_population_config (config), store, stats }, websocket{ config.websocket_config, observers, wallets, ledger, io_ctx, logger }, + epoch_upgrader{ *this, ledger, store, network_params, logger }, startup_time (std::chrono::steady_clock::now ()), node_seq (seq) { @@ -722,11 +723,7 @@ void nano::node::stop () checker.stop (); wallets.stop (); stats.stop (); - auto epoch_upgrade = epoch_upgrading.lock (); - if (epoch_upgrade->valid ()) - { - epoch_upgrade->wait (); - } + epoch_upgrader.stop (); workers.stop (); // work pool is not stopped on purpose due to testing setup } @@ -778,11 +775,11 @@ nano::uint128_t nano::node::weight (nano::account const & account_a) nano::block_hash nano::node::rep_block (nano::account const & account_a) { auto const transaction (store.tx_begin_read ()); - nano::account_info info; nano::block_hash result (0); - if (!store.account.get (transaction, account_a, info)) + auto info = ledger.account_info (transaction, account_a); + if (info) { - result = ledger.representative (transaction, info.head); + result = ledger.representative (transaction, info->head); } return result; } @@ -1422,21 +1419,6 @@ bool nano::node::init_error () const return store.init_error () || wallets_store.init_error (); } -bool nano::node::epoch_upgrader (nano::raw_key const & prv_a, nano::epoch epoch_a, uint64_t count_limit, uint64_t threads) -{ - bool error = stopped.load (); - if (!error) - { - auto epoch_upgrade = epoch_upgrading.lock (); - error = epoch_upgrade->valid () && epoch_upgrade->wait_for (std::chrono::seconds (0)) == std::future_status::timeout; - if (!error) - { - *epoch_upgrade = std::async (std::launch::async, &nano::node::epoch_upgrader_impl, this, prv_a, epoch_a, count_limit, threads); - } - } - return error; -} - void nano::node::set_bandwidth_params (std::size_t limit, double ratio) { config.bandwidth_limit_burst_ratio = ratio; @@ -1445,265 +1427,6 @@ void nano::node::set_bandwidth_params (std::size_t limit, double ratio) logger.always_log (boost::str (boost::format ("set_bandwidth_params(%1%, %2%)") % limit % ratio)); } -void nano::node::epoch_upgrader_impl (nano::raw_key const & prv_a, nano::epoch epoch_a, uint64_t count_limit, uint64_t threads) -{ - nano::thread_role::set (nano::thread_role::name::epoch_upgrader); - auto upgrader_process = [] (nano::node & node_a, std::atomic & counter, std::shared_ptr const & epoch, uint64_t difficulty, nano::public_key const & signer_a, nano::root const & root_a, nano::account const & account_a) { - epoch->block_work_set (node_a.work_generate_blocking (nano::work_version::work_1, root_a, difficulty).value_or (0)); - bool valid_signature (!nano::validate_message (signer_a, epoch->hash (), epoch->block_signature ())); - bool valid_work (node_a.network_params.work.difficulty (*epoch) >= difficulty); - nano::process_result result (nano::process_result::old); - if (valid_signature && valid_work) - { - result = node_a.process_local (epoch).code; - } - if (result == nano::process_result::progress) - { - ++counter; - } - else - { - bool fork (result == nano::process_result::fork); - node_a.logger.always_log (boost::str (boost::format ("Failed to upgrade account %1%. Valid signature: %2%. Valid work: %3%. Block processor fork: %4%") % account_a.to_account () % valid_signature % valid_work % fork)); - } - }; - - uint64_t const upgrade_batch_size = 1000; - nano::block_builder builder; - auto link (ledger.epoch_link (epoch_a)); - nano::raw_key raw_key; - raw_key = prv_a; - auto signer (nano::pub_key (prv_a)); - debug_assert (signer == ledger.epoch_signer (link)); - - nano::mutex upgrader_mutex; - nano::condition_variable upgrader_condition; - - class account_upgrade_item final - { - public: - nano::account account{}; - uint64_t modified{ 0 }; - }; - class account_tag - { - }; - class modified_tag - { - }; - // clang-format off - boost::multi_index_container, - boost::multi_index::member, - std::greater>, - boost::multi_index::hashed_unique, - boost::multi_index::member>>> - accounts_list; - // clang-format on - - bool finished_upgrade (false); - - while (!finished_upgrade && !stopped) - { - bool finished_accounts (false); - uint64_t total_upgraded_accounts (0); - while (!finished_accounts && count_limit != 0 && !stopped) - { - { - 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) - { - nano::account const & account (i->first); - nano::account_info const & info (i->second); - if (info.epoch () < epoch_a) - { - release_assert (nano::epochs::is_sequential (info.epoch (), epoch_a)); - accounts_list.emplace (account_upgrade_item{ account, info.modified }); - } - } - } - - /* Upgrade accounts - Repeat until accounts with previous epoch exist in latest table */ - std::atomic upgraded_accounts (0); - uint64_t workers (0); - uint64_t attempts (0); - for (auto i (accounts_list.get ().begin ()), n (accounts_list.get ().end ()); i != n && attempts < upgrade_batch_size && attempts < count_limit && !stopped; ++i) - { - auto transaction (store.tx_begin_read ()); - nano::account_info info; - nano::account const & account (i->account); - if (!store.account.get (transaction, account, info) && info.epoch () < epoch_a) - { - ++attempts; - auto difficulty (network_params.work.threshold (nano::work_version::work_1, nano::block_details (epoch_a, false, false, true))); - nano::root const & root (info.head); - std::shared_ptr epoch = builder.state () - .account (account) - .previous (info.head) - .representative (info.representative) - .balance (info.balance) - .link (link) - .sign (raw_key, signer) - .work (0) - .build (); - if (threads != 0) - { - { - nano::unique_lock lock{ upgrader_mutex }; - ++workers; - while (workers > threads) - { - upgrader_condition.wait (lock); - } - } - this->workers.push_task ([node_l = shared_from_this (), &upgrader_process, &upgrader_mutex, &upgrader_condition, &upgraded_accounts, &workers, epoch, difficulty, signer, root, account] () { - upgrader_process (*node_l, upgraded_accounts, epoch, difficulty, signer, root, account); - { - nano::lock_guard lock{ upgrader_mutex }; - --workers; - } - upgrader_condition.notify_all (); - }); - } - else - { - upgrader_process (*this, upgraded_accounts, epoch, difficulty, signer, root, account); - } - } - } - { - nano::unique_lock lock{ upgrader_mutex }; - while (workers > 0) - { - upgrader_condition.wait (lock); - } - } - total_upgraded_accounts += upgraded_accounts; - count_limit -= upgraded_accounts; - - if (!accounts_list.empty ()) - { - logger.always_log (boost::str (boost::format ("%1% accounts were upgraded to new epoch, %2% remain...") % total_upgraded_accounts % (accounts_list.size () - upgraded_accounts))); - accounts_list.clear (); - } - else - { - logger.always_log (boost::str (boost::format ("%1% total accounts were upgraded to new epoch") % total_upgraded_accounts)); - finished_accounts = true; - } - } - - // Pending blocks upgrade - bool finished_pending (false); - uint64_t total_upgraded_pending (0); - while (!finished_pending && count_limit != 0 && !stopped) - { - std::atomic upgraded_pending (0); - uint64_t workers (0); - uint64_t attempts (0); - auto transaction (store.tx_begin_read ()); - for (auto i (store.pending.begin (transaction, nano::pending_key (1, 0))), n (store.pending.end ()); i != n && attempts < upgrade_batch_size && attempts < count_limit && !stopped;) - { - bool to_next_account (false); - nano::pending_key const & key (i->first); - if (!store.account.exists (transaction, key.account)) - { - nano::pending_info const & info (i->second); - if (info.epoch < epoch_a) - { - ++attempts; - release_assert (nano::epochs::is_sequential (info.epoch, epoch_a)); - auto difficulty (network_params.work.threshold (nano::work_version::work_1, nano::block_details (epoch_a, false, false, true))); - nano::root const & root (key.account); - nano::account const & account (key.account); - std::shared_ptr epoch = builder.state () - .account (key.account) - .previous (0) - .representative (0) - .balance (0) - .link (link) - .sign (raw_key, signer) - .work (0) - .build (); - if (threads != 0) - { - { - nano::unique_lock lock{ upgrader_mutex }; - ++workers; - while (workers > threads) - { - upgrader_condition.wait (lock); - } - } - this->workers.push_task ([node_l = shared_from_this (), &upgrader_process, &upgrader_mutex, &upgrader_condition, &upgraded_pending, &workers, epoch, difficulty, signer, root, account] () { - upgrader_process (*node_l, upgraded_pending, epoch, difficulty, signer, root, account); - { - nano::lock_guard lock{ upgrader_mutex }; - --workers; - } - upgrader_condition.notify_all (); - }); - } - else - { - upgrader_process (*this, upgraded_pending, epoch, difficulty, signer, root, account); - } - } - } - else - { - to_next_account = true; - } - if (to_next_account) - { - // Move to next account if pending account exists or was upgraded - if (key.account.number () == std::numeric_limits::max ()) - { - break; - } - else - { - i = store.pending.begin (transaction, nano::pending_key (key.account.number () + 1, 0)); - } - } - else - { - // Move to next pending item - ++i; - } - } - { - nano::unique_lock lock{ upgrader_mutex }; - while (workers > 0) - { - upgrader_condition.wait (lock); - } - } - - total_upgraded_pending += upgraded_pending; - count_limit -= upgraded_pending; - - // Repeat if some pending accounts were upgraded - if (upgraded_pending != 0) - { - logger.always_log (boost::str (boost::format ("%1% unopened accounts with pending blocks were upgraded to new epoch...") % total_upgraded_pending)); - } - else - { - logger.always_log (boost::str (boost::format ("%1% total unopened accounts with pending blocks were upgraded to new epoch") % total_upgraded_pending)); - finished_pending = true; - } - } - - finished_upgrade = (total_upgraded_accounts == 0) && (total_upgraded_pending == 0); - } - - logger.always_log ("Epoch upgrade is completed"); -} - std::pair nano::node::get_bootstrap_weights () const { std::unordered_map weights; diff --git a/nano/node/node.hpp b/nano/node/node.hpp index 99cfda37ae..de06e3cbd7 100644 --- a/nano/node/node.hpp +++ b/nano/node/node.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -125,7 +126,6 @@ class node final : public std::enable_shared_from_this void ongoing_online_weight_calculation_queue (); bool online () const; bool init_error () const; - bool epoch_upgrader (nano::raw_key const &, nano::epoch, uint64_t, uint64_t); void set_bandwidth_params (std::size_t limit, double ratio); std::pair get_bootstrap_weights () const; uint64_t get_confirmation_height (nano::transaction const &, nano::account &); @@ -184,6 +184,7 @@ class node final : public std::enable_shared_from_this nano::wallets wallets; nano::backlog_population backlog; nano::websocket_server websocket; + nano::epoch_upgrader epoch_upgrader; std::chrono::steady_clock::time_point const startup_time; std::chrono::seconds unchecked_cutoff = std::chrono::seconds (7 * 24 * 60 * 60); // Week @@ -212,8 +213,6 @@ class node final : public std::enable_shared_from_this private: void long_inactivity_cleanup (); - void epoch_upgrader_impl (nano::raw_key const &, nano::epoch, uint64_t, uint64_t); - nano::locked> epoch_upgrading; }; nano::keypair load_or_create_node_id (boost::filesystem::path const & application_path, nano::logger_mt & logger); diff --git a/nano/node/nodeconfig.cpp b/nano/node/nodeconfig.cpp index 682c990ec1..545beda818 100644 --- a/nano/node/nodeconfig.cpp +++ b/nano/node/nodeconfig.cpp @@ -137,7 +137,7 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const work_peers_l->push_back (boost::str (boost::format ("%1%:%2%") % i->first % i->second)); } - auto preconfigured_peers_l (toml.create_array ("preconfigured_peers", "A list of \"address\" (hostname or ipv6 notation ip address) entries to identify preconfigured peers.")); + auto preconfigured_peers_l (toml.create_array ("preconfigured_peers", "A list of \"address\" (hostname or ipv6 notation ip address) entries to identify preconfigured peers.\nThe contents of the NANO_DEFAULT_PEER environment variable are added to preconfigured_peers.")); for (auto i (preconfigured_peers.begin ()), n (preconfigured_peers.end ()); i != n; ++i) { preconfigured_peers_l->push_back (*i); diff --git a/nano/node/request_aggregator.cpp b/nano/node/request_aggregator.cpp index 0cbf4bb814..59acea1858 100644 --- a/nano/node/request_aggregator.cpp +++ b/nano/node/request_aggregator.cpp @@ -242,11 +242,10 @@ std::pair>, std::vectoropen_block; } } if (!successor.is_zero ()) diff --git a/nano/node/wallet.cpp b/nano/node/wallet.cpp index e66f74e562..79a64e9489 100644 --- a/nano/node/wallet.cpp +++ b/nano/node/wallet.cpp @@ -849,12 +849,11 @@ std::shared_ptr nano::wallet::receive_action (nano::block_hash cons { store.work_get (transaction, account_a, work_a); } - nano::account_info info; - auto new_account (wallets.node.ledger.store.account.get (block_transaction, account_a, info)); - if (!new_account) + auto info = wallets.node.ledger.account_info (block_transaction, account_a); + if (info) { - block = std::make_shared (account_a, info.head, info.representative, info.balance.number () + pending_info.amount.number (), send_hash_a, prv, account_a, work_a); - details.epoch = std::max (info.epoch (), pending_info.epoch); + block = std::make_shared (account_a, info->head, info->representative, info->balance.number () + pending_info.amount.number (), send_hash_a, prv, account_a, work_a); + details.epoch = std::max (info->epoch (), pending_info.epoch); } else { @@ -905,10 +904,8 @@ std::shared_ptr nano::wallet::change_action (nano::account const & auto existing (store.find (transaction, source_a)); if (existing != store.end () && !wallets.node.ledger.latest (block_transaction, source_a).is_zero ()) { - nano::account_info info; - auto error1 (wallets.node.ledger.store.account.get (block_transaction, source_a, info)); - (void)error1; - debug_assert (!error1); + auto info = wallets.node.ledger.account_info (block_transaction, source_a); + debug_assert (info); nano::raw_key prv; auto error2 (store.fetch (transaction, source_a, prv)); (void)error2; @@ -917,8 +914,8 @@ std::shared_ptr nano::wallet::change_action (nano::account const & { store.work_get (transaction, source_a, work_a); } - block = std::make_shared (source_a, info.head, representative_a, info.balance, 0, prv, source_a, work_a); - details.epoch = info.epoch (); + block = std::make_shared (source_a, info->head, representative_a, info->balance, 0, prv, source_a, work_a); + details.epoch = info->epoch (); } } } @@ -977,10 +974,8 @@ std::shared_ptr nano::wallet::send_action (nano::account const & so auto balance (wallets.node.ledger.account_balance (block_transaction, source_a)); if (!balance.is_zero () && balance >= amount_a) { - nano::account_info info; - auto error1 (wallets.node.ledger.store.account.get (block_transaction, source_a, info)); - (void)error1; - debug_assert (!error1); + auto info = wallets.node.ledger.account_info (block_transaction, source_a); + debug_assert (info); nano::raw_key prv; auto error2 (store.fetch (transaction, source_a, prv)); (void)error2; @@ -989,8 +984,8 @@ std::shared_ptr nano::wallet::send_action (nano::account const & so { store.work_get (transaction, source_a, work_a); } - block = std::make_shared (source_a, info.head, info.representative, balance - amount_a, account_a, prv, source_a, work_a); - details.epoch = info.epoch (); + block = std::make_shared (source_a, info->head, info->representative, balance - amount_a, account_a, prv, source_a, work_a); + details.epoch = info->epoch (); if (id_mdb_val && block != nullptr) { auto status (mdb_put (wallets.env.tx (transaction), wallets.node.wallets.send_action_ids, *id_mdb_val, nano::mdb_val (block->hash ()), 0)); diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index 68d69e6616..bf8fe4d033 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -730,10 +730,10 @@ TEST (rpc, wallet_representative_set_force) while (representative != key.pub) { auto transaction (node->store.tx_begin_read ()); - nano::account_info info; - if (!node->store.account.get (transaction, nano::dev::genesis_key.pub, info)) + auto info = node->ledger.account_info (transaction, nano::dev::genesis_key.pub); + if (info) { - representative = info.representative; + representative = info->representative; } ASSERT_NO_ERROR (system.poll ()); } @@ -7195,9 +7195,9 @@ TEST (rpc, receive) { auto response (wait_response (system, rpc_ctx, request)); auto receive_text (response.get ("block")); - nano::account_info info; - ASSERT_FALSE (node->store.account.get (node->store.tx_begin_read (), key1.pub, info)); - ASSERT_EQ (info.head, nano::block_hash{ receive_text }); + auto info = node->ledger.account_info (node->store.tx_begin_read (), key1.pub); + ASSERT_TRUE (info); + ASSERT_EQ (info->head, nano::block_hash{ receive_text }); } // Trying to receive the same block should fail with unreceivable { @@ -7236,11 +7236,11 @@ TEST (rpc, receive_unopened) { auto response (wait_response (system, rpc_ctx, request)); auto receive_text (response.get ("block")); - nano::account_info info; - ASSERT_FALSE (node->store.account.get (node->store.tx_begin_read (), key1.pub, info)); - ASSERT_EQ (info.head, info.open_block); - ASSERT_EQ (info.head.to_string (), receive_text); - ASSERT_EQ (info.representative, nano::dev::genesis_key.pub); + auto info = node->ledger.account_info (node->store.tx_begin_read (), key1.pub); + ASSERT_TRUE (info); + ASSERT_EQ (info->head, info->open_block); + ASSERT_EQ (info->head.to_string (), receive_text); + ASSERT_EQ (info->representative, nano::dev::genesis_key.pub); } rpc_ctx.io_scope->reset (); @@ -7260,11 +7260,11 @@ TEST (rpc, receive_unopened) { auto response (wait_response (system, rpc_ctx, request)); auto receive_text (response.get ("block")); - nano::account_info info; - ASSERT_FALSE (node->store.account.get (node->store.tx_begin_read (), key2.pub, info)); - ASSERT_EQ (info.head, info.open_block); - ASSERT_EQ (info.head.to_string (), receive_text); - ASSERT_EQ (info.representative, rep); + auto info = node->ledger.account_info (node->store.tx_begin_read (), key2.pub); + ASSERT_TRUE (info); + ASSERT_EQ (info->head, info->open_block); + ASSERT_EQ (info->head.to_string (), receive_text); + ASSERT_EQ (info->representative, rep); } } @@ -7345,9 +7345,9 @@ TEST (rpc, receive_pruned) { auto response (wait_response (system, rpc_ctx, request)); auto receive_text (response.get ("block")); - nano::account_info info; - ASSERT_FALSE (node2->store.account.get (node2->store.tx_begin_read (), key1.pub, info)); - ASSERT_EQ (info.head, nano::block_hash{ receive_text }); + auto info = node2->ledger.account_info (node2->store.tx_begin_read (), key1.pub); + ASSERT_TRUE (info); + ASSERT_EQ (info->head, nano::block_hash{ receive_text }); } // Trying to receive the same block should fail with unreceivable { diff --git a/nano/secure/ledger.cpp b/nano/secure/ledger.cpp index 681631bd4b..00349e05ad 100644 --- a/nano/secure/ledger.cpp +++ b/nano/secure/ledger.cpp @@ -34,13 +34,12 @@ class rollback_visitor : public nano::block_visitor } if (!error) { - nano::account_info info; - [[maybe_unused]] auto error (ledger.store.account.get (transaction, pending.source, info)); - debug_assert (!error); + auto info = ledger.account_info (transaction, pending.source); + debug_assert (info); ledger.store.pending.del (transaction, key); - ledger.cache.rep_weights.representation_add (info.representative, pending.amount.number ()); - nano::account_info new_info (block_a.hashables.previous, info.representative, info.open_block, ledger.balance (transaction, block_a.hashables.previous), nano::seconds_since_epoch (), info.block_count - 1, nano::epoch::epoch_0); - ledger.update_account (transaction, pending.source, info, new_info); + ledger.cache.rep_weights.representation_add (info->representative, pending.amount.number ()); + nano::account_info new_info (block_a.hashables.previous, info->representative, info->open_block, ledger.balance (transaction, block_a.hashables.previous), nano::seconds_since_epoch (), info->block_count - 1, nano::epoch::epoch_0); + ledger.update_account (transaction, pending.source, *info, new_info); ledger.store.block.del (transaction, hash); ledger.store.frontier.del (transaction, hash); ledger.store.frontier.put (transaction, block_a.hashables.previous, pending.source); @@ -56,12 +55,11 @@ class rollback_visitor : public nano::block_visitor // Pending account entry can be incorrect if source block was pruned. But it's not affecting correct ledger processing [[maybe_unused]] bool is_pruned (false); auto source_account (ledger.account_safe (transaction, block_a.hashables.source, is_pruned)); - nano::account_info info; - [[maybe_unused]] auto error (ledger.store.account.get (transaction, destination_account, info)); - debug_assert (!error); - ledger.cache.rep_weights.representation_add (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), nano::seconds_since_epoch (), info.block_count - 1, nano::epoch::epoch_0); - ledger.update_account (transaction, destination_account, info, new_info); + auto info = ledger.account_info (transaction, destination_account); + debug_assert (info); + ledger.cache.rep_weights.representation_add (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), 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); ledger.store.pending.put (transaction, nano::pending_key (destination_account, block_a.hashables.source), { source_account, amount, nano::epoch::epoch_0 }); ledger.store.frontier.del (transaction, hash); @@ -90,17 +88,16 @@ class rollback_visitor : public nano::block_visitor auto hash (block_a.hash ()); auto rep_block (ledger.representative (transaction, block_a.hashables.previous)); auto account (ledger.account (transaction, block_a.hashables.previous)); - nano::account_info info; - [[maybe_unused]] auto error (ledger.store.account.get (transaction, account, info)); - debug_assert (!error); + auto info = ledger.account_info (transaction, account); + debug_assert (info); auto balance (ledger.balance (transaction, block_a.hashables.previous)); auto block = ledger.store.block.get (transaction, rep_block); release_assert (block != nullptr); auto representative = block->representative (); ledger.cache.rep_weights.representation_add_dual (block_a.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); + 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); ledger.store.frontier.del (transaction, hash); ledger.store.frontier.put (transaction, block_a.hashables.previous, account); ledger.store.block.successor_clear (transaction, block_a.hashables.previous); @@ -131,8 +128,8 @@ class rollback_visitor : public nano::block_visitor ledger.cache.rep_weights.representation_add (block_a.representative (), 0 - block_a.hashables.balance.number ()); } - nano::account_info info; - auto error (ledger.store.account.get (transaction, block_a.hashables.account, info)); + auto info = ledger.account_info (transaction, block_a.hashables.account); + debug_assert (info); if (is_send) { @@ -156,8 +153,8 @@ class rollback_visitor : public nano::block_visitor debug_assert (!error); auto previous_version (ledger.store.block.version (transaction, block_a.hashables.previous)); - nano::account_info new_info (block_a.hashables.previous, representative, info.open_block, balance, nano::seconds_since_epoch (), info.block_count - 1, previous_version); - ledger.update_account (transaction, block_a.hashables.account, info, new_info); + nano::account_info new_info (block_a.hashables.previous, representative, info->open_block, balance, nano::seconds_since_epoch (), info->block_count - 1, previous_version); + ledger.update_account (transaction, block_a.hashables.account, *info, new_info); auto previous (ledger.store.block.get (transaction, block_a.hashables.previous)); if (previous != nullptr) @@ -461,11 +458,9 @@ void ledger_processor::change_block (nano::change_block & block_a) result.code = account.is_zero () ? nano::process_result::fork : nano::process_result::progress; if (result.code == nano::process_result::progress) { - nano::account_info info; - auto latest_error (ledger.store.account.get (transaction, account, info)); - (void)latest_error; - debug_assert (!latest_error); - debug_assert (info.head == block_a.hashables.previous); + auto info = ledger.account_info (transaction, account); + debug_assert (info); + debug_assert (info->head == block_a.hashables.previous); result.code = validate_message (account, hash, block_a.signature) ? nano::process_result::bad_signature : nano::process_result::progress; // Is this block signed correctly (Malformed) if (result.code == nano::process_result::progress) { @@ -474,12 +469,12 @@ void ledger_processor::change_block (nano::change_block & block_a) if (result.code == nano::process_result::progress) { debug_assert (!validate_message (account, hash, block_a.signature)); - 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 */)); + 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 (ledger.balance (transaction, block_a.hashables.previous)); - ledger.cache.rep_weights.representation_add_dual (block_a.representative (), balance, info.representative, 0 - balance); - nano::account_info new_info (hash, block_a.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.cache.rep_weights.representation_add_dual (block_a.representative (), balance, info->representative, 0 - balance); + nano::account_info new_info (hash, block_a.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); ledger.store.frontier.put (transaction, hash, account); ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::change); @@ -517,20 +512,18 @@ void ledger_processor::send_block (nano::send_block & block_a) if (result.code == nano::process_result::progress) { debug_assert (!validate_message (account, hash, block_a.signature)); - nano::account_info info; - auto latest_error (ledger.store.account.get (transaction, account, info)); - (void)latest_error; - debug_assert (!latest_error); - debug_assert (info.head == block_a.hashables.previous); - result.code = info.balance.number () >= block_a.hashables.balance.number () ? nano::process_result::progress : nano::process_result::negative_spend; // Is this trying to spend a negative amount (Malicious) + auto info = ledger.account_info (transaction, account); + debug_assert (info); + debug_assert (info->head == block_a.hashables.previous); + result.code = info->balance.number () >= block_a.hashables.balance.number () ? nano::process_result::progress : nano::process_result::negative_spend; // Is this trying to spend a negative amount (Malicious) if (result.code == nano::process_result::progress) { - auto amount (info.balance.number () - block_a.hashables.balance.number ()); - ledger.cache.rep_weights.representation_add (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 */)); + auto amount (info->balance.number () - block_a.hashables.balance.number ()); + ledger.cache.rep_weights.representation_add (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); - ledger.update_account (transaction, account, info, new_info); + 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); + ledger.update_account (transaction, account, *info, new_info); ledger.store.pending.put (transaction, nano::pending_key (block_a.hashables.destination, hash), { account, amount, nano::epoch::epoch_0 }); ledger.store.frontier.del (transaction, block_a.hashables.previous); ledger.store.frontier.put (transaction, hash, account); @@ -569,9 +562,9 @@ void ledger_processor::receive_block (nano::receive_block & block_a) result.code = ledger.block_or_pruned_exists (transaction, block_a.hashables.source) ? nano::process_result::progress : nano::process_result::gap_source; // Have we seen the source block already? (Harmless) if (result.code == nano::process_result::progress) { - nano::account_info info; - ledger.store.account.get (transaction, account, info); - result.code = info.head == block_a.hashables.previous ? nano::process_result::progress : nano::process_result::gap_previous; // Block doesn't immediately follow latest block (Harmless) + auto info = ledger.account_info (transaction, account); + debug_assert (info); + result.code = info->head == block_a.hashables.previous ? nano::process_result::progress : nano::process_result::gap_previous; // Block doesn't immediately follow latest block (Harmless) if (result.code == nano::process_result::progress) { nano::pending_key key (account, block_a.hashables.source); @@ -586,21 +579,20 @@ void ledger_processor::receive_block (nano::receive_block & block_a) result.code = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed) if (result.code == nano::process_result::progress) { - auto new_balance (info.balance.number () + pending.amount.number ()); + auto new_balance (info->balance.number () + pending.amount.number ()); #ifdef NDEBUG if (ledger.store.block.exists (transaction, block_a.hashables.source)) { - nano::account_info source_info; - [[maybe_unused]] auto error (ledger.store.account.get (transaction, pending.source, source_info)); - debug_assert (!error); + auto info = ledger.account_info (transaction, pending.source); + debug_assert (info); } #endif ledger.store.pending.del (transaction, key); - block_a.sideband_set (nano::block_sideband (account, 0, new_balance, info.block_count + 1, nano::seconds_since_epoch (), block_details, nano::epoch::epoch_0 /* unused */)); + block_a.sideband_set (nano::block_sideband (account, 0, new_balance, 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, 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.amount.number ()); + 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.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); @@ -779,11 +771,10 @@ nano::uint128_t nano::ledger::account_balance (nano::transaction const & transac } else { - nano::account_info info; - auto none (store.account.get (transaction_a, account_a, info)); - if (!none) + auto info = account_info (transaction_a, account_a); + if (info) { - result = info.balance.number (); + result = info->balance.number (); } } return result; @@ -998,7 +989,6 @@ bool nano::ledger::rollback (nano::write_transaction const & transaction_a, nano auto account_l (account (transaction_a, block_a)); auto block_account_height (store.block.account_height (transaction_a, block_a)); rollback_visitor rollback (transaction_a, *this, list_a); - nano::account_info account_info; auto error (false); while (!error && store.block.exists (transaction_a, block_a)) { @@ -1006,9 +996,9 @@ bool nano::ledger::rollback (nano::write_transaction const & transaction_a, nano store.confirmation_height.get (transaction_a, account_l, confirmation_height_info); if (block_account_height > confirmation_height_info.height) { - auto latest_error = store.account.get (transaction_a, account_l, account_info); - debug_assert (!latest_error); - auto block (store.block.get (transaction_a, account_info.head)); + auto info = account_info (transaction_a, account_l); + debug_assert (info); + auto block (store.block.get (transaction_a, info->head)); list_a.push_back (block); block->visit (rollback); error = rollback.error; @@ -1070,11 +1060,9 @@ nano::account nano::ledger::account_safe (const nano::transaction & transaction, } } -nano::account_info nano::ledger::account_info (nano::transaction const & transaction, nano::account const & account) const +std::optional nano::ledger::account_info (nano::transaction const & transaction, nano::account const & account) const { - nano::account_info result; - store.account.get (transaction, account, result); - return result; + return store.account.get (transaction, account); } std::optional nano::ledger::pending_info (nano::transaction const & transaction, nano::pending_key const & key) const @@ -1115,22 +1103,21 @@ nano::uint128_t nano::ledger::amount_safe (nano::transaction const & transaction // Return latest block for account nano::block_hash nano::ledger::latest (nano::transaction const & transaction_a, nano::account const & account_a) { - nano::account_info info; - auto latest_error (store.account.get (transaction_a, account_a, info)); - return latest_error ? 0 : info.head; + auto info = account_info (transaction_a, account_a); + return !info ? 0 : info->head; } // Return latest root for account, account number if there are no blocks for this account. nano::root nano::ledger::latest_root (nano::transaction const & transaction_a, nano::account const & account_a) { - nano::account_info info; - if (store.account.get (transaction_a, account_a, info)) + auto info = account_info (transaction_a, account_a); + if (!info) { return account_a; } else { - return info.head; + return info->head; } } @@ -1312,10 +1299,10 @@ std::shared_ptr nano::ledger::successor (nano::transaction const & auto get_from_previous = false; if (root_a.previous ().is_zero ()) { - nano::account_info info; - if (!store.account.get (transaction_a, root_a.root ().as_account (), info)) + auto info = account_info (transaction_a, root_a.root ().as_account ()); + if (info) { - successor = info.open_block; + successor = info->open_block; } else { @@ -1348,11 +1335,9 @@ std::shared_ptr nano::ledger::forked_block (nano::transaction const auto result (store.block.get (transaction_a, store.block.successor (transaction_a, root.as_block_hash ()))); if (result == nullptr) { - nano::account_info info; - auto error (store.account.get (transaction_a, root.as_account (), info)); - (void)error; - debug_assert (!error); - result = store.block.get (transaction_a, info.open_block); + auto info = account_info (transaction_a, root.as_account ()); + debug_assert (info); + result = store.block.get (transaction_a, info->open_block); debug_assert (result != nullptr); } return result; diff --git a/nano/secure/ledger.hpp b/nano/secure/ledger.hpp index 04c76f9912..400093c4a0 100644 --- a/nano/secure/ledger.hpp +++ b/nano/secure/ledger.hpp @@ -32,7 +32,7 @@ class ledger final * Return account containing hash, expects that block hash exists in ledger */ nano::account account (nano::transaction const &, nano::block_hash const &) const; - nano::account_info account_info (nano::transaction const & transaction, nano::account const & account) const; + std::optional account_info (nano::transaction const & transaction, nano::account const & account) const; std::optional pending_info (nano::transaction const & transaction, nano::pending_key const & key) const; /** * For non-prunning nodes same as `ledger::account()` diff --git a/nano/slow_test/node.cpp b/nano/slow_test/node.cpp index d6fb854f12..057906c632 100644 --- a/nano/slow_test/node.cpp +++ b/nano/slow_test/node.cpp @@ -907,17 +907,18 @@ TEST (confirmation_height, long_chains) ASSERT_TIMELY (30s, node->ledger.block_confirmed (node->store.tx_begin_read (), receive1->hash ())); auto transaction (node->store.tx_begin_read ()); - nano::account_info account_info; - ASSERT_FALSE (node->store.account.get (transaction, nano::dev::genesis_key.pub, account_info)); + auto info = node->ledger.account_info (transaction, nano::dev::genesis_key.pub); + ASSERT_TRUE (info); nano::confirmation_height_info confirmation_height_info; ASSERT_FALSE (node->store.confirmation_height.get (transaction, nano::dev::genesis_key.pub, confirmation_height_info)); ASSERT_EQ (num_blocks + 2, confirmation_height_info.height); - ASSERT_EQ (num_blocks + 3, account_info.block_count); // Includes the unpocketed send + ASSERT_EQ (num_blocks + 3, info->block_count); // Includes the unpocketed send - ASSERT_FALSE (node->store.account.get (transaction, key1.pub, account_info)); + info = node->ledger.account_info (transaction, key1.pub); + ASSERT_TRUE (info); ASSERT_FALSE (node->store.confirmation_height.get (transaction, key1.pub, confirmation_height_info)); ASSERT_EQ (num_blocks + 1, confirmation_height_info.height); - ASSERT_EQ (num_blocks + 1, account_info.block_count); + ASSERT_EQ (num_blocks + 1, info->block_count); size_t cemented_count = 0; for (auto i (node->ledger.store.confirmation_height.begin (transaction)), n (node->ledger.store.confirmation_height.end ()); i != n; ++i) @@ -1913,9 +1914,9 @@ TEST (node, mass_epoch_upgrader) { auto const pre_upgrade = node.ledger.cache.block_count.load (); auto upgrade_count = std::min (batch_size, block_count_before + total_to_upgrade - pre_upgrade); - ASSERT_FALSE (node.epoch_upgrader (epoch_signer.prv, nano::epoch::epoch_1, upgrade_count, threads)); + ASSERT_FALSE (node.epoch_upgrader.start (epoch_signer.prv, nano::epoch::epoch_1, upgrade_count, threads)); // Already ongoing - should fail - ASSERT_TRUE (node.epoch_upgrader (epoch_signer.prv, nano::epoch::epoch_1, upgrade_count, threads)); + ASSERT_TRUE (node.epoch_upgrader.start (epoch_signer.prv, nano::epoch::epoch_1, upgrade_count, threads)); system.deadline_set (60s); while (node.ledger.cache.block_count != pre_upgrade + upgrade_count) { diff --git a/nano/test_common/CMakeLists.txt b/nano/test_common/CMakeLists.txt index 917d0fb757..337d34211d 100644 --- a/nano/test_common/CMakeLists.txt +++ b/nano/test_common/CMakeLists.txt @@ -1,5 +1,7 @@ add_library( test_common + chains.hpp + chains.cpp ledger.hpp ledger.cpp network.hpp diff --git a/nano/test_common/chains.cpp b/nano/test_common/chains.cpp new file mode 100644 index 0000000000..f416717e21 --- /dev/null +++ b/nano/test_common/chains.cpp @@ -0,0 +1,169 @@ +#include + +using namespace std::chrono_literals; + +nano::block_list_t nano::test::setup_chain (nano::test::system & system, nano::node & node, int count, nano::keypair target) +{ + auto latest = node.latest (target.pub); + auto balance = node.balance (target.pub); + + std::vector> blocks; + for (int n = 0; n < count; ++n) + { + nano::keypair throwaway; + nano::block_builder builder; + + balance -= 1; + auto send = builder + .send () + .previous (latest) + .destination (throwaway.pub) + .balance (balance) + .sign (target.prv, target.pub) + .work (*system.work.generate (latest)) + .build_shared (); + + latest = send->hash (); + + blocks.push_back (send); + } + + EXPECT_TRUE (nano::test::process (node, blocks)); + + // Confirm whole chain at once + EXPECT_TIMELY (5s, nano::test::confirm (node, { blocks.back () })); + EXPECT_TIMELY (5s, nano::test::confirmed (node, blocks)); + + return blocks; +} + +std::vector> nano::test::setup_chains (nano::test::system & system, nano::node & node, int chain_count, int block_count, nano::keypair source) +{ + auto latest = node.latest (source.pub); + auto balance = node.balance (source.pub); + + std::vector> chains; + for (int n = 0; n < chain_count; ++n) + { + nano::keypair key; + nano::block_builder builder; + + balance -= block_count * 2; // Send enough to later create `block_count` blocks + auto send = builder + .send () + .previous (latest) + .destination (key.pub) + .balance (balance) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*system.work.generate (latest)) + .build_shared (); + + auto open = builder + .open () + .source (send->hash ()) + .representative (key.pub) + .account (key.pub) + .sign (key.prv, key.pub) + .work (*system.work.generate (key.pub)) + .build_shared (); + + latest = send->hash (); + + // Ensure blocks are in the ledger and confirmed + EXPECT_TRUE (nano::test::process (node, { send, open })); + EXPECT_TIMELY (5s, nano::test::confirm (node, { send, open })); + EXPECT_TIMELY (5s, nano::test::confirmed (node, { send, open })); + + auto added_blocks = nano::test::setup_chain (system, node, block_count, key); + + auto blocks = block_list_t{ open }; + blocks.insert (blocks.end (), added_blocks.begin (), added_blocks.end ()); + + chains.emplace_back (key.pub, blocks); + } + + return chains; +} + +nano::block_list_t nano::test::setup_independent_blocks (nano::test::system & system, nano::node & node, int count, nano::keypair source) +{ + std::vector> blocks; + + auto latest = node.latest (source.pub); + auto balance = node.balance (source.pub); + + for (int n = 0; n < count; ++n) + { + nano::keypair key; + nano::block_builder builder; + + balance -= 1; + auto send = builder + .state () + .account (nano::dev::genesis_key.pub) + .previous (latest) + .representative (nano::dev::genesis_key.pub) + .balance (balance) + .link (key.pub) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*system.work.generate (latest)) + .build_shared (); + + latest = send->hash (); + + auto open = builder + .state () + .account (key.pub) + .previous (0) + .representative (key.pub) + .balance (1) + .link (send->hash ()) + .sign (key.prv, key.pub) + .work (*system.work.generate (key.pub)) + .build_shared (); + + EXPECT_TRUE (nano::test::process (node, { send, open })); + EXPECT_TIMELY (5s, nano::test::exists (node, { send, open })); // Ensure blocks are in the ledger + + blocks.push_back (open); + } + + // Confirm whole genesis chain at once + EXPECT_TIMELY (5s, nano::test::confirm (node, { latest })); + EXPECT_TIMELY (5s, nano::test::confirmed (node, { latest })); + + return blocks; +} + +nano::keypair nano::test::setup_rep (nano::test::system & system, nano::node & node, nano::uint128_t const amount, nano::keypair source) +{ + auto latest = node.latest (source.pub); + auto balance = node.balance (source.pub); + + nano::keypair key; + nano::block_builder builder; + + auto send = builder + .send () + .previous (latest) + .destination (key.pub) + .balance (balance - amount) + .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) + .work (*system.work.generate (latest)) + .build_shared (); + + auto open = builder + .open () + .source (send->hash ()) + .representative (key.pub) + .account (key.pub) + .sign (key.prv, key.pub) + .work (*system.work.generate (key.pub)) + .build_shared (); + + EXPECT_TRUE (nano::test::process (node, { send, open })); + EXPECT_TIMELY (5s, nano::test::confirm (node, { send, open })); + EXPECT_TIMELY (5s, nano::test::confirmed (node, { send, open })); + + return key; +} \ No newline at end of file diff --git a/nano/test_common/chains.hpp b/nano/test_common/chains.hpp new file mode 100644 index 0000000000..7c6c52ca7f --- /dev/null +++ b/nano/test_common/chains.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + +#include + +#include +#include + +/* + * Helper functions to deal with common chain setup scenarios + */ +namespace nano::test +{ +/** + * Creates `count` random 1 raw send blocks in a `target` account chain + * @returns created blocks + */ +nano::block_list_t setup_chain (nano::test::system & system, nano::node & node, int count, nano::keypair target = nano::dev::genesis_key); + +/** + * Creates `chain_count` account chains, each with `block_count` 1 raw random send blocks, all accounts are seeded from `source` account + * @returns list of created accounts and their blocks + */ +std::vector> setup_chains (nano::test::system & system, nano::node & node, int chain_count, int block_count, nano::keypair source = nano::dev::genesis_key); + +/** + * Creates `count` 1 raw send blocks from `source` account, each to randomly created account + * The `source` account chain is then confirmed, but leaves open blocks unconfirmed + * @returns list of unconfirmed (open) blocks + */ +nano::block_list_t setup_independent_blocks (nano::test::system & system, nano::node & node, int count, nano::keypair source = nano::dev::genesis_key); + +/** + * Sends `amount` raw from `source` account chain into a newly created account and sets that account as its own representative + * @return created representative + */ +nano::keypair setup_rep (nano::test::system & system, nano::node & node, nano::uint128_t amount, nano::keypair source = nano::dev::genesis_key); +} \ No newline at end of file diff --git a/nano/test_common/system.cpp b/nano/test_common/system.cpp index c05f7ed360..dc2f2882f7 100644 --- a/nano/test_common/system.cpp +++ b/nano/test_common/system.cpp @@ -400,11 +400,10 @@ void nano::test::system::generate_rollback (nano::node & node_a, std::vector::max () > accounts_a.size ()); auto index (random_pool::generate_word32 (0, static_cast (accounts_a.size () - 1))); auto account (accounts_a[index]); - nano::account_info info; - auto error (node_a.store.account.get (transaction, account, info)); - if (!error) + auto info = node_a.ledger.account_info (transaction, account); + if (info) { - auto hash (info.open_block); + auto hash (info->open_block); if (hash != node_a.network_params.ledger.genesis->hash ()) { accounts_a[index] = accounts_a[accounts_a.size () - 1];