diff --git a/nano/core_test/block_store.cpp b/nano/core_test/block_store.cpp index ca9d6caa..aad7a877 100644 --- a/nano/core_test/block_store.cpp +++ b/nano/core_test/block_store.cpp @@ -24,13 +24,16 @@ using namespace std::chrono_literals; -namespace +namespace nano { -void modify_account_info_to_v14 (nano::lmdb::store & store, nano::transaction const & transaction_a, nano::account const & account_a, uint64_t confirmation_height, nano::block_hash const & rep_block); -void modify_confirmation_height_to_v15 (nano::lmdb::store & store, nano::transaction const & transaction, nano::account const & account, uint64_t confirmation_height); -void write_sideband_v14 (nano::lmdb::store & store_a, nano::transaction & transaction_a, nano::block const & block_a, MDB_dbi db_a); -void write_sideband_v15 (nano::lmdb::store & store_a, nano::transaction & transaction_a, nano::block const & block_a); -void write_block_w_sideband_v18 (nano::lmdb::store & store_a, MDB_dbi database, nano::write_transaction & transaction_a, nano::block const & block_a); +namespace lmdb +{ + void modify_account_info_to_v14 (nano::lmdb::store & store, nano::transaction const & transaction_a, nano::account const & account_a, uint64_t confirmation_height, nano::block_hash const & rep_block); + void modify_confirmation_height_to_v15 (nano::lmdb::store & store, nano::transaction const & transaction, nano::account const & account, uint64_t confirmation_height); + void write_sideband_v14 (nano::lmdb::store & store_a, nano::transaction & transaction_a, nano::block const & block_a, MDB_dbi db_a); + void write_sideband_v15 (nano::lmdb::store & store_a, nano::transaction & transaction_a, nano::block const & block_a); + void write_block_w_sideband_v18 (nano::lmdb::store & store_a, MDB_dbi database, nano::write_transaction & transaction_a, nano::block const & block_a); +} } TEST (block_store, construction) @@ -688,55 +691,63 @@ TEST (block_store, latest_find) ASSERT_EQ (second, find3); } -TEST (mdb_block_store, supported_version_upgrades) +namespace nano { - if (nano::rocksdb_config::using_rocksdb_in_tests ()) +namespace lmdb +{ + TEST (mdb_block_store, supported_version_upgrades) { - // Don't test this in rocksdb mode - return; - } - // Check that upgrading from an unsupported version is not supported - auto path (nano::unique_path ()); - nano::logger_mt logger; - { - nano::lmdb::store store (logger, path, nano::dev::constants); - nano::stat stats; - nano::ledger ledger (store, stats, nano::dev::constants); - auto transaction (store.tx_begin_write ()); - store.initialize (transaction, ledger.cache, nano::dev::constants); - // Lower the database to the max version unsupported for upgrades - store.version.put (transaction, store.version_minimum - 1); - } + if (nano::rocksdb_config::using_rocksdb_in_tests ()) + { + // Don't test this in rocksdb mode + return; + } + // Check that upgrading from an unsupported version is not supported + auto path (nano::unique_path ()); + nano::logger_mt logger; + { + nano::lmdb::store store (logger, path, nano::dev::constants); + nano::stat stats; + nano::ledger ledger (store, stats, nano::dev::constants); + auto transaction (store.tx_begin_write ()); + store.initialize (transaction, ledger.cache, nano::dev::constants); + // Lower the database to the max version unsupported for upgrades + store.version.put (transaction, store.version_minimum - 1); + } - // Upgrade should fail - { - nano::lmdb::store store (logger, path, nano::dev::constants); - ASSERT_TRUE (store.init_error ()); - } + // Upgrade should fail + { + nano::lmdb::store store (logger, path, nano::dev::constants); + ASSERT_TRUE (store.init_error ()); + } - auto path1 (nano::unique_path ()); - // Now try with the minimum version - { - nano::lmdb::store store (logger, path1, nano::dev::constants); - nano::stat stats; - nano::ledger ledger (store, stats, nano::dev::constants); - auto transaction (store.tx_begin_write ()); - store.initialize (transaction, ledger.cache, nano::dev::constants); - // Lower the database version to the minimum version supported for upgrade. - store.version.put (transaction, store.version_minimum); - store.confirmation_height.del (transaction, nano::dev::genesis->account ()); - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "accounts_v1", MDB_CREATE, &store.accounts_v1_handle)); - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "open", MDB_CREATE, &store.open_blocks_handle)); - modify_account_info_to_v14 (store, transaction, nano::dev::genesis->account (), 1, nano::dev::genesis->hash ()); - write_block_w_sideband_v18 (store, store.open_blocks_handle, transaction, *nano::dev::genesis); - } + auto path1 (nano::unique_path ()); + // Now try with the minimum version + { + nano::lmdb::store store (logger, path1, nano::dev::constants); + nano::stat stats; + nano::ledger ledger (store, stats, nano::dev::constants); + auto transaction (store.tx_begin_write ()); + store.initialize (transaction, ledger.cache, nano::dev::constants); + // Lower the database version to the minimum version supported for upgrade. + store.version.put (transaction, store.version_minimum); + store.confirmation_height.del (transaction, nano::dev::genesis->account ()); + ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "accounts_v1", MDB_CREATE, + &store.account_store.accounts_v1_handle)); + ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "open", MDB_CREATE, &store.block_store.open_blocks_handle)); + modify_account_info_to_v14 (store, transaction, nano::dev::genesis->account (), 1, + nano::dev::genesis->hash ()); + write_block_w_sideband_v18 (store, store.block_store.open_blocks_handle, transaction, *nano::dev::genesis); + } - // Upgrade should work - { - nano::lmdb::store store (logger, path1, nano::dev::constants); - ASSERT_FALSE (store.init_error ()); + // Upgrade should work + { + nano::lmdb::store store (logger, path1, nano::dev::constants); + ASSERT_FALSE (store.init_error ()); + } } } +} TEST (mdb_block_store, bad_path) { @@ -954,30 +965,36 @@ TEST (block_store, pruned_random) ASSERT_EQ (hash1, random_hash); } -// Databases need to be dropped in order to convert to dupsort compatible -TEST (block_store, DISABLED_change_dupsort) // Unchecked is no longer dupsort table +namespace nano { - auto path (nano::unique_path ()); - nano::logger_mt logger{}; - nano::lmdb::store store{ logger, path, nano::dev::constants }; - nano::unchecked_map unchecked{ store, false }; - auto transaction (store.tx_begin_write ()); - ASSERT_EQ (0, mdb_drop (store.env.tx (transaction), store.unchecked_handle, 1)); - ASSERT_EQ (0, mdb_dbi_open (store.env.tx (transaction), "unchecked", MDB_CREATE, &store.unchecked_handle)); - std::shared_ptr send1 = std::make_shared (0, 0, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, 0); - std::shared_ptr send2 = std::make_shared (1, 0, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, 0); - ASSERT_NE (send1->hash (), send2->hash ()); - unchecked.put (send1->hash (), send1); - unchecked.put (send1->hash (), send2); - ASSERT_EQ (0, mdb_drop (store.env.tx (transaction), store.unchecked_handle, 0)); - mdb_dbi_close (store.env, store.unchecked_handle); - ASSERT_EQ (0, mdb_dbi_open (store.env.tx (transaction), "unchecked", MDB_CREATE | MDB_DUPSORT, &store.unchecked_handle)); - unchecked.put (send1->hash (), send1); - unchecked.put (send1->hash (), send2); - ASSERT_EQ (0, mdb_drop (store.env.tx (transaction), store.unchecked_handle, 1)); - ASSERT_EQ (0, mdb_dbi_open (store.env.tx (transaction), "unchecked", MDB_CREATE | MDB_DUPSORT, &store.unchecked_handle)); - unchecked.put (send1->hash (), send1); - unchecked.put (send1->hash (), send2); +namespace lmdb +{ + // Databases need to be dropped in order to convert to dupsort compatible + TEST (block_store, DISABLED_change_dupsort) // Unchecked is no longer dupsort table + { + auto path (nano::unique_path ()); + nano::logger_mt logger{}; + nano::lmdb::store store{ logger, path, nano::dev::constants }; + nano::unchecked_map unchecked{ store, false }; + auto transaction (store.tx_begin_write ()); + ASSERT_EQ (0, mdb_drop (store.env.tx (transaction), store.unchecked_store.unchecked_handle, 1)); + ASSERT_EQ (0, mdb_dbi_open (store.env.tx (transaction), "unchecked", MDB_CREATE, &store.unchecked_store.unchecked_handle)); + std::shared_ptr send1 = std::make_shared (0, 0, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, 0); + std::shared_ptr send2 = std::make_shared (1, 0, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, 0); + ASSERT_NE (send1->hash (), send2->hash ()); + unchecked.put (send1->hash (), send1); + unchecked.put (send1->hash (), send2); + ASSERT_EQ (0, mdb_drop (store.env.tx (transaction), store.unchecked_store.unchecked_handle, 0)); + mdb_dbi_close (store.env, store.unchecked_store.unchecked_handle); + ASSERT_EQ (0, mdb_dbi_open (store.env.tx (transaction), "unchecked", MDB_CREATE | MDB_DUPSORT, &store.unchecked_store.unchecked_handle)); + unchecked.put (send1->hash (), send1); + unchecked.put (send1->hash (), send2); + ASSERT_EQ (0, mdb_drop (store.env.tx (transaction), store.unchecked_store.unchecked_handle, 1)); + ASSERT_EQ (0, mdb_dbi_open (store.env.tx (transaction), "unchecked", MDB_CREATE | MDB_DUPSORT, &store.unchecked_store.unchecked_handle)); + unchecked.put (send1->hash (), send1); + unchecked.put (send1->hash (), send2); + } +} } TEST (block_store, state_block) @@ -1275,175 +1292,157 @@ TEST (block_store, pruned_blocks) ASSERT_EQ (store->pruned.count (store->tx_begin_read ()), 0); } -TEST (mdb_block_store, upgrade_v14_v15) +namespace nano { - if (nano::rocksdb_config::using_rocksdb_in_tests ()) - { - // Don't test this in rocksdb mode - return; - } - // Extract confirmation height to a separate database - auto path (nano::unique_path ()); - nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::send_block send (nano::dev::genesis->hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (nano::dev::genesis->hash ())); - nano::state_block epoch (nano::dev::genesis_key.pub, send.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio, nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_1), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (send.hash ())); - nano::state_block state_send (nano::dev::genesis_key.pub, epoch.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2, nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (epoch.hash ())); +namespace lmdb +{ + TEST (mdb_block_store, upgrade_v14_v15) { + if (nano::rocksdb_config::using_rocksdb_in_tests ()) + { + // Don't test this in rocksdb mode + return; + } + // Extract confirmation height to a separate database + auto path (nano::unique_path ()); + nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; + nano::send_block send (nano::dev::genesis->hash (), nano::dev::genesis_key.pub, + nano::dev::constants.genesis_amount - nano::Gxrb_ratio, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (nano::dev::genesis->hash ())); + nano::state_block epoch (nano::dev::genesis_key.pub, send.hash (), nano::dev::genesis_key.pub, + nano::dev::constants.genesis_amount - nano::Gxrb_ratio, nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_1), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (send.hash ())); + nano::state_block state_send (nano::dev::genesis_key.pub, epoch.hash (), nano::dev::genesis_key.pub, + nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2, nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (epoch.hash ())); + { + nano::logger_mt logger; + nano::lmdb::store store (logger, path, nano::dev::constants); + nano::stat stats; + 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)); + nano::confirmation_height_info confirmation_height_info; + ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis->account (), + confirmation_height_info)); + ASSERT_EQ (confirmation_height_info.height, 1); + ASSERT_EQ (confirmation_height_info.frontier, nano::dev::genesis->hash ()); + // These databases get removed after an upgrade, so readd them + ASSERT_FALSE ( + mdb_dbi_open (store.env.tx (transaction), "state_v1", MDB_CREATE, &store.block_store.state_blocks_v1_handle)); + ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "accounts_v1", MDB_CREATE, + &store.account_store.accounts_v1_handle)); + ASSERT_FALSE ( + mdb_dbi_open (store.env.tx (transaction), "pending_v1", MDB_CREATE, &store.pending_store.pending_v1_handle)); + ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "open", MDB_CREATE, &store.block_store.open_blocks_handle)); + ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "send", MDB_CREATE, &store.block_store.send_blocks_handle)); + ASSERT_FALSE ( + mdb_dbi_open (store.env.tx (transaction), "state_blocks", MDB_CREATE, + &store.block_store.state_blocks_handle)); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_send).code); + // Lower the database to the previous version + store.version.put (transaction, 14); + store.confirmation_height.del (transaction, nano::dev::genesis->account ()); + modify_account_info_to_v14 (store, transaction, nano::dev::genesis->account (), + confirmation_height_info.height, state_send.hash ()); + + store.pending.del (transaction, nano::pending_key (nano::dev::genesis->account (), state_send.hash ())); + + write_sideband_v14 (store, transaction, state_send, store.block_store.state_blocks_v1_handle); + write_sideband_v14 (store, transaction, epoch, store.block_store.state_blocks_v1_handle); + write_block_w_sideband_v18 (store, store.block_store.open_blocks_handle, transaction, *nano::dev::genesis); + write_block_w_sideband_v18 (store, store.block_store.send_blocks_handle, transaction, send); + + // Remove from blocks table + store.block.del (transaction, state_send.hash ()); + store.block.del (transaction, epoch.hash ()); + + // Turn pending into v14 + ASSERT_FALSE (mdb_put (store.env.tx (transaction), store.pending_store.pending_v0_handle, + nano::mdb_val (nano::pending_key (nano::dev::genesis_key.pub, send.hash ())), + nano::mdb_val ( + nano::pending_info_v14 (nano::dev::genesis->account (), nano::Gxrb_ratio, + nano::epoch::epoch_0)), + 0)); + ASSERT_FALSE (mdb_put (store.env.tx (transaction), store.pending_store.pending_v1_handle, + nano::mdb_val (nano::pending_key (nano::dev::genesis_key.pub, state_send.hash ())), + nano::mdb_val ( + nano::pending_info_v14 (nano::dev::genesis->account (), nano::Gxrb_ratio, + nano::epoch::epoch_1)), + 0)); + + // This should fail as sizes are no longer correct for account_info + nano::mdb_val value; + ASSERT_FALSE (mdb_get (store.env.tx (transaction), store.account_store.accounts_v1_handle, + nano::mdb_val (nano::dev::genesis->account ()), value)); + nano::account_info info; + ASSERT_NE (value.size (), info.db_size ()); + store.account.del (transaction, nano::dev::genesis->account ()); + + // Confirmation height for the account should be deleted + ASSERT_TRUE (mdb_get (store.env.tx (transaction), store.confirmation_height_store.confirmation_height_handle, + nano::mdb_val (nano::dev::genesis->account ()), value)); + } + + // Now do the upgrade nano::logger_mt logger; nano::lmdb::store store (logger, path, nano::dev::constants); - nano::stat stats; - 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)); + ASSERT_FALSE (store.init_error ()); + auto transaction (store.tx_begin_read ()); + + // Size of account_info should now equal that set in db + nano::mdb_val value; + ASSERT_FALSE (mdb_get (store.env.tx (transaction), store.account_store.accounts_handle, + nano::mdb_val (nano::dev::genesis->account ()), value)); + nano::account_info info (value); + ASSERT_EQ (value.size (), info.db_size ()); + + // Confirmation height should exist nano::confirmation_height_info confirmation_height_info; - ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis->account (), confirmation_height_info)); + ASSERT_FALSE ( + store.confirmation_height.get (transaction, nano::dev::genesis->account (), + confirmation_height_info)); ASSERT_EQ (confirmation_height_info.height, 1); ASSERT_EQ (confirmation_height_info.frontier, nano::dev::genesis->hash ()); - // These databases get removed after an upgrade, so readd them - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "state_v1", MDB_CREATE, &store.state_blocks_v1_handle)); - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "accounts_v1", MDB_CREATE, &store.accounts_v1_handle)); - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "pending_v1", MDB_CREATE, &store.pending_v1_handle)); - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "open", MDB_CREATE, &store.open_blocks_handle)); - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "send", MDB_CREATE, &store.send_blocks_handle)); - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "state_blocks", MDB_CREATE, &store.state_blocks_handle)); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_send).code); - // Lower the database to the previous version - store.version.put (transaction, 14); - store.confirmation_height.del (transaction, nano::dev::genesis->account ()); - modify_account_info_to_v14 (store, transaction, nano::dev::genesis->account (), confirmation_height_info.height, state_send.hash ()); - store.pending.del (transaction, nano::pending_key (nano::dev::genesis->account (), state_send.hash ())); + // accounts_v1, state_blocks_v1 & pending_v1 tables should be deleted + auto error_get_accounts_v1 (mdb_get (store.env.tx (transaction), store.account_store.accounts_v1_handle, + nano::mdb_val (nano::dev::genesis->account ()), value)); + ASSERT_NE (error_get_accounts_v1, MDB_SUCCESS); + auto error_get_pending_v1 (mdb_get (store.env.tx (transaction), store.pending_store.pending_v1_handle, nano::mdb_val (nano::pending_key (nano::dev::genesis_key.pub, state_send.hash ())), value)); + ASSERT_NE (error_get_pending_v1, MDB_SUCCESS); + auto error_get_state_v1 ( + mdb_get (store.env.tx (transaction), store.block_store.state_blocks_v1_handle, nano::mdb_val (state_send.hash ()), + value)); + ASSERT_NE (error_get_state_v1, MDB_SUCCESS); - write_sideband_v14 (store, transaction, state_send, store.state_blocks_v1_handle); - write_sideband_v14 (store, transaction, epoch, store.state_blocks_v1_handle); - write_block_w_sideband_v18 (store, store.open_blocks_handle, transaction, *nano::dev::genesis); - write_block_w_sideband_v18 (store, store.send_blocks_handle, transaction, send); + // Check that the epochs are set correctly for the sideband, accounts and pending entries + auto block = store.block.get (transaction, state_send.hash ()); + ASSERT_NE (block, nullptr); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + block = store.block.get (transaction, send.hash ()); + ASSERT_NE (block, nullptr); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_0); + ASSERT_EQ (info.epoch (), nano::epoch::epoch_1); + nano::pending_info pending_info; + store.pending.get (transaction, nano::pending_key (nano::dev::genesis_key.pub, send.hash ()), pending_info); + ASSERT_EQ (pending_info.epoch, nano::epoch::epoch_0); + store.pending.get (transaction, nano::pending_key (nano::dev::genesis_key.pub, state_send.hash ()), + pending_info); + ASSERT_EQ (pending_info.epoch, nano::epoch::epoch_1); - // Remove from blocks table - store.block.del (transaction, state_send.hash ()); - store.block.del (transaction, epoch.hash ()); - - // Turn pending into v14 - ASSERT_FALSE (mdb_put (store.env.tx (transaction), store.pending_v0_handle, nano::mdb_val (nano::pending_key (nano::dev::genesis_key.pub, send.hash ())), nano::mdb_val (nano::pending_info_v14 (nano::dev::genesis->account (), nano::Gxrb_ratio, nano::epoch::epoch_0)), 0)); - ASSERT_FALSE (mdb_put (store.env.tx (transaction), store.pending_v1_handle, nano::mdb_val (nano::pending_key (nano::dev::genesis_key.pub, state_send.hash ())), nano::mdb_val (nano::pending_info_v14 (nano::dev::genesis->account (), nano::Gxrb_ratio, nano::epoch::epoch_1)), 0)); - - // This should fail as sizes are no longer correct for account_info - nano::mdb_val value; - ASSERT_FALSE (mdb_get (store.env.tx (transaction), store.accounts_v1_handle, nano::mdb_val (nano::dev::genesis->account ()), value)); - nano::account_info info; - ASSERT_NE (value.size (), info.db_size ()); - store.account.del (transaction, nano::dev::genesis->account ()); - - // Confirmation height for the account should be deleted - ASSERT_TRUE (mdb_get (store.env.tx (transaction), store.confirmation_height_handle, nano::mdb_val (nano::dev::genesis->account ()), value)); + // Version should be correct + ASSERT_LT (14, store.version.get (transaction)); } - // Now do the upgrade - nano::logger_mt logger; - nano::lmdb::store store (logger, path, nano::dev::constants); - ASSERT_FALSE (store.init_error ()); - auto transaction (store.tx_begin_read ()); - - // Size of account_info should now equal that set in db - nano::mdb_val value; - ASSERT_FALSE (mdb_get (store.env.tx (transaction), store.accounts_handle, nano::mdb_val (nano::dev::genesis->account ()), value)); - nano::account_info info (value); - ASSERT_EQ (value.size (), info.db_size ()); - - // Confirmation height should exist - nano::confirmation_height_info confirmation_height_info; - ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis->account (), confirmation_height_info)); - ASSERT_EQ (confirmation_height_info.height, 1); - ASSERT_EQ (confirmation_height_info.frontier, nano::dev::genesis->hash ()); - - // accounts_v1, state_blocks_v1 & pending_v1 tables should be deleted - auto error_get_accounts_v1 (mdb_get (store.env.tx (transaction), store.accounts_v1_handle, nano::mdb_val (nano::dev::genesis->account ()), value)); - ASSERT_NE (error_get_accounts_v1, MDB_SUCCESS); - auto error_get_pending_v1 (mdb_get (store.env.tx (transaction), store.pending_v1_handle, nano::mdb_val (nano::pending_key (nano::dev::genesis_key.pub, state_send.hash ())), value)); - ASSERT_NE (error_get_pending_v1, MDB_SUCCESS); - auto error_get_state_v1 (mdb_get (store.env.tx (transaction), store.state_blocks_v1_handle, nano::mdb_val (state_send.hash ()), value)); - ASSERT_NE (error_get_state_v1, MDB_SUCCESS); - - // Check that the epochs are set correctly for the sideband, accounts and pending entries - auto block = store.block.get (transaction, state_send.hash ()); - ASSERT_NE (block, nullptr); - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); - block = store.block.get (transaction, send.hash ()); - ASSERT_NE (block, nullptr); - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_0); - ASSERT_EQ (info.epoch (), nano::epoch::epoch_1); - nano::pending_info pending_info; - store.pending.get (transaction, nano::pending_key (nano::dev::genesis_key.pub, send.hash ()), pending_info); - ASSERT_EQ (pending_info.epoch, nano::epoch::epoch_0); - store.pending.get (transaction, nano::pending_key (nano::dev::genesis_key.pub, state_send.hash ()), pending_info); - ASSERT_EQ (pending_info.epoch, nano::epoch::epoch_1); - - // Version should be correct - ASSERT_LT (14, store.version.get (transaction)); -} - -TEST (mdb_block_store, upgrade_v15_v16) -{ - if (nano::rocksdb_config::using_rocksdb_in_tests ()) + TEST (mdb_block_store, upgrade_v15_v16) { - // Don't test this in rocksdb mode - return; - } - auto path (nano::unique_path ()); - nano::mdb_val value; - { - nano::logger_mt logger; - nano::lmdb::store store (logger, path, nano::dev::constants); - nano::stat stats; - nano::ledger ledger (store, stats, nano::dev::constants); - auto transaction (store.tx_begin_write ()); - store.initialize (transaction, ledger.cache, nano::dev::constants); - // The representation table should get removed after, so readd it so that we can later confirm this actually happens - auto txn = store.env.tx (transaction); - ASSERT_FALSE (mdb_dbi_open (txn, "representation", MDB_CREATE, &store.representation_handle)); - auto weight = ledger.cache.rep_weights.representation_get (nano::dev::genesis->account ()); - ASSERT_EQ (MDB_SUCCESS, mdb_put (txn, store.representation_handle, nano::mdb_val (nano::dev::genesis->account ()), nano::mdb_val (nano::uint128_union (weight)), 0)); - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "open", MDB_CREATE, &store.open_blocks_handle)); - write_block_w_sideband_v18 (store, store.open_blocks_handle, transaction, *nano::dev::genesis); - // Lower the database to the previous version - store.version.put (transaction, 15); - // Confirm the rep weight exists in the database - ASSERT_EQ (MDB_SUCCESS, mdb_get (store.env.tx (transaction), store.representation_handle, nano::mdb_val (nano::dev::genesis->account ()), value)); - store.confirmation_height.del (transaction, nano::dev::genesis->account ()); - } - - // Now do the upgrade - nano::logger_mt logger; - nano::lmdb::store store (logger, path, nano::dev::constants); - ASSERT_FALSE (store.init_error ()); - auto transaction (store.tx_begin_read ()); - - // The representation table should now be deleted - auto error_get_representation (mdb_get (store.env.tx (transaction), store.representation_handle, nano::mdb_val (nano::dev::genesis->account ()), value)); - ASSERT_NE (MDB_SUCCESS, error_get_representation); - ASSERT_EQ (store.representation_handle, 0); - - // Version should be correct - ASSERT_LT (15, store.version.get (transaction)); -} - -TEST (mdb_block_store, upgrade_v16_v17) -{ - if (nano::rocksdb_config::using_rocksdb_in_tests ()) - { - // Don't test this in rocksdb mode - return; - } - nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::state_block block1 (nano::dev::genesis_key.pub, nano::dev::genesis->hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio, nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (nano::dev::genesis->hash ())); - nano::state_block block2 (nano::dev::genesis_key.pub, block1.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio - 1, nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (block1.hash ())); - nano::state_block block3 (nano::dev::genesis_key.pub, block2.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio - 2, nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (block2.hash ())); - - auto code = [&block1, &block2, &block3] (auto confirmation_height, nano::block_hash const & expected_cemented_frontier) { + if (nano::rocksdb_config::using_rocksdb_in_tests ()) + { + // Don't test this in rocksdb mode + return; + } auto path (nano::unique_path ()); nano::mdb_val value; { @@ -1453,20 +1452,19 @@ TEST (mdb_block_store, upgrade_v16_v17) nano::ledger ledger (store, stats, nano::dev::constants); auto transaction (store.tx_begin_write ()); store.initialize (transaction, ledger.cache, nano::dev::constants); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block1).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block2).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block3).code); - modify_confirmation_height_to_v15 (store, transaction, nano::dev::genesis->account (), confirmation_height); - - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "open", MDB_CREATE, &store.open_blocks_handle)); - write_block_w_sideband_v18 (store, store.open_blocks_handle, transaction, *nano::dev::genesis); - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "state_blocks", MDB_CREATE, &store.state_blocks_handle)); - write_block_w_sideband_v18 (store, store.state_blocks_handle, transaction, block1); - write_block_w_sideband_v18 (store, store.state_blocks_handle, transaction, block2); - write_block_w_sideband_v18 (store, store.state_blocks_handle, transaction, block3); - + // The representation table should get removed after, so readd it so that we can later confirm this actually happens + auto txn = store.env.tx (transaction); + ASSERT_FALSE ( + mdb_dbi_open (txn, "representation", MDB_CREATE, &store.account_store.representation_handle)); + auto weight = ledger.cache.rep_weights.representation_get (nano::dev::genesis->account ()); + ASSERT_EQ (MDB_SUCCESS, mdb_put (txn, store.account_store.representation_handle, nano::mdb_val (nano::dev::genesis->account ()), nano::mdb_val (nano::uint128_union (weight)), 0)); + ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "open", MDB_CREATE, &store.block_store.open_blocks_handle)); + write_block_w_sideband_v18 (store, store.block_store.open_blocks_handle, transaction, *nano::dev::genesis); // Lower the database to the previous version - store.version.put (transaction, 16); + store.version.put (transaction, 15); + // Confirm the rep weight exists in the database + ASSERT_EQ (MDB_SUCCESS, mdb_get (store.env.tx (transaction), store.account_store.representation_handle, nano::mdb_val (nano::dev::genesis->account ()), value)); + store.confirmation_height.del (transaction, nano::dev::genesis->account ()); } // Now do the upgrade @@ -1475,373 +1473,429 @@ TEST (mdb_block_store, upgrade_v16_v17) ASSERT_FALSE (store.init_error ()); auto transaction (store.tx_begin_read ()); - nano::confirmation_height_info confirmation_height_info; - ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis->account (), confirmation_height_info)); - ASSERT_EQ (confirmation_height_info.height, confirmation_height); - - // Check confirmation height frontier is correct - ASSERT_EQ (confirmation_height_info.frontier, expected_cemented_frontier); + // The representation table should now be deleted + auto error_get_representation (mdb_get (store.env.tx (transaction), store.account_store.representation_handle, + nano::mdb_val (nano::dev::genesis->account ()), value)); + ASSERT_NE (MDB_SUCCESS, error_get_representation); + ASSERT_EQ (store.account_store.representation_handle, 0); // Version should be correct - ASSERT_LT (16, store.version.get (transaction)); - }; - - code (0, nano::block_hash (0)); - code (1, nano::dev::genesis->hash ()); - code (2, block1.hash ()); - code (3, block2.hash ()); - code (4, block3.hash ()); -} - -TEST (mdb_block_store, upgrade_v17_v18) -{ - if (nano::rocksdb_config::using_rocksdb_in_tests ()) - { - // Don't test this in rocksdb mode - return; + ASSERT_LT (15, store.version.get (transaction)); } - auto path (nano::unique_path ()); - nano::keypair key1; - nano::keypair key2; - nano::keypair key3; - nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::send_block send_zero (nano::dev::genesis->hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (nano::dev::genesis->hash ())); - nano::state_block state_receive_zero (nano::dev::genesis_key.pub, send_zero.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount, send_zero.hash (), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (send_zero.hash ())); - nano::state_block epoch (nano::dev::genesis_key.pub, state_receive_zero.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount, nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_1), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (state_receive_zero.hash ())); - nano::state_block state_send (nano::dev::genesis_key.pub, epoch.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio, nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (epoch.hash ())); - nano::state_block state_receive (nano::dev::genesis_key.pub, state_send.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount, state_send.hash (), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (state_send.hash ())); - nano::state_block state_change (nano::dev::genesis_key.pub, state_receive.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (state_receive.hash ())); - nano::state_block state_send_change (nano::dev::genesis_key.pub, state_change.hash (), key1.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio, key1.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (state_change.hash ())); - nano::state_block epoch_first (key1.pub, 0, 0, 0, nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_2), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (key1.pub)); - nano::state_block state_receive2 (key1.pub, epoch_first.hash (), key1.pub, nano::Gxrb_ratio, state_send_change.hash (), key1.prv, key1.pub, *pool.generate (epoch_first.hash ())); - nano::state_block state_send2 (nano::dev::genesis_key.pub, state_send_change.hash (), key1.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2, key2.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (state_send_change.hash ())); - nano::state_block state_open (key2.pub, 0, key2.pub, nano::Gxrb_ratio, state_send2.hash (), key2.prv, key2.pub, *pool.generate (key2.pub)); - nano::state_block state_send_epoch_link (key2.pub, state_open.hash (), key2.pub, 0, nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_2), key2.prv, key2.pub, *pool.generate (state_open.hash ())); + + TEST (mdb_block_store, upgrade_v16_v17) { + if (nano::rocksdb_config::using_rocksdb_in_tests ()) + { + // Don't test this in rocksdb mode + return; + } + nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; + nano::state_block block1 (nano::dev::genesis_key.pub, nano::dev::genesis->hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio, nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (nano::dev::genesis->hash ())); + nano::state_block block2 (nano::dev::genesis_key.pub, block1.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio - 1, nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (block1.hash ())); + nano::state_block block3 (nano::dev::genesis_key.pub, block2.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio - 2, nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (block2.hash ())); + + auto code = [&block1, &block2, &block3] (auto confirmation_height, nano::block_hash const & expected_cemented_frontier) { + auto path (nano::unique_path ()); + nano::mdb_val value; + { + nano::logger_mt logger; + nano::lmdb::store store (logger, path, nano::dev::constants); + nano::stat stats; + nano::ledger ledger (store, stats, nano::dev::constants); + auto transaction (store.tx_begin_write ()); + store.initialize (transaction, ledger.cache, nano::dev::constants); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block1).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block2).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, block3).code); + modify_confirmation_height_to_v15 (store, transaction, nano::dev::genesis->account (), confirmation_height); + + ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "open", MDB_CREATE, &store.block_store.open_blocks_handle)); + write_block_w_sideband_v18 (store, store.block_store.open_blocks_handle, transaction, *nano::dev::genesis); + ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "state_blocks", MDB_CREATE, &store.block_store.state_blocks_handle)); + write_block_w_sideband_v18 (store, store.block_store.state_blocks_handle, transaction, block1); + write_block_w_sideband_v18 (store, store.block_store.state_blocks_handle, transaction, block2); + write_block_w_sideband_v18 (store, store.block_store.state_blocks_handle, transaction, block3); + + // Lower the database to the previous version + store.version.put (transaction, 16); + } + + // Now do the upgrade + nano::logger_mt logger; + nano::lmdb::store store (logger, path, nano::dev::constants); + ASSERT_FALSE (store.init_error ()); + auto transaction (store.tx_begin_read ()); + + nano::confirmation_height_info confirmation_height_info; + ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis->account (), confirmation_height_info)); + ASSERT_EQ (confirmation_height_info.height, confirmation_height); + + // Check confirmation height frontier is correct + ASSERT_EQ (confirmation_height_info.frontier, expected_cemented_frontier); + + // Version should be correct + ASSERT_LT (16, store.version.get (transaction)); + }; + + code (0, nano::block_hash (0)); + code (1, nano::dev::genesis->hash ()); + code (2, block1.hash ()); + code (3, block2.hash ()); + code (4, block3.hash ()); + } + + TEST (mdb_block_store, upgrade_v17_v18) + { + if (nano::rocksdb_config::using_rocksdb_in_tests ()) + { + // Don't test this in rocksdb mode + return; + } + auto path (nano::unique_path ()); + nano::keypair key1; + nano::keypair key2; + nano::keypair key3; + nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; + nano::send_block send_zero (nano::dev::genesis->hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (nano::dev::genesis->hash ())); + nano::state_block state_receive_zero (nano::dev::genesis_key.pub, send_zero.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount, send_zero.hash (), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (send_zero.hash ())); + nano::state_block epoch (nano::dev::genesis_key.pub, state_receive_zero.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount, nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_1), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (state_receive_zero.hash ())); + nano::state_block state_send (nano::dev::genesis_key.pub, epoch.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio, nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (epoch.hash ())); + nano::state_block state_receive (nano::dev::genesis_key.pub, state_send.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount, state_send.hash (), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (state_send.hash ())); + nano::state_block state_change (nano::dev::genesis_key.pub, state_receive.hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount, 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (state_receive.hash ())); + nano::state_block state_send_change (nano::dev::genesis_key.pub, state_change.hash (), key1.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio, key1.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (state_change.hash ())); + nano::state_block epoch_first (key1.pub, 0, 0, 0, nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_2), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (key1.pub)); + nano::state_block state_receive2 (key1.pub, epoch_first.hash (), key1.pub, nano::Gxrb_ratio, state_send_change.hash (), key1.prv, key1.pub, *pool.generate (epoch_first.hash ())); + nano::state_block state_send2 (nano::dev::genesis_key.pub, state_send_change.hash (), key1.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2, key2.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (state_send_change.hash ())); + nano::state_block state_open (key2.pub, 0, key2.pub, nano::Gxrb_ratio, state_send2.hash (), key2.prv, key2.pub, *pool.generate (key2.pub)); + nano::state_block state_send_epoch_link (key2.pub, state_open.hash (), key2.pub, 0, nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_2), key2.prv, key2.pub, *pool.generate (state_open.hash ())); + { + nano::logger_mt logger; + nano::lmdb::store store (logger, path, nano::dev::constants); + auto transaction (store.tx_begin_write ()); + nano::stat stats; + nano::ledger ledger (store, stats, nano::dev::constants); + store.initialize (transaction, ledger.cache, nano::dev::constants); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send_zero).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_receive_zero).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_send).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_receive).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_change).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_send_change).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch_first).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_receive2).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_send2).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_open).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_send_epoch_link).code); + + ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "open", MDB_CREATE, &store.block_store.open_blocks_handle)); + ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "send", MDB_CREATE, &store.block_store.send_blocks_handle)); + ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "state_blocks", MDB_CREATE, &store.block_store.state_blocks_handle)); + + // Downgrade the store + store.version.put (transaction, 17); + + write_block_w_sideband_v18 (store, store.block_store.state_blocks_handle, transaction, state_receive); + write_block_w_sideband_v18 (store, store.block_store.state_blocks_handle, transaction, epoch_first); + write_block_w_sideband_v18 (store, store.block_store.state_blocks_handle, transaction, state_send2); + write_block_w_sideband_v18 (store, store.block_store.state_blocks_handle, transaction, state_send_epoch_link); + write_block_w_sideband_v18 (store, store.block_store.open_blocks_handle, transaction, *nano::dev::genesis); + write_block_w_sideband_v18 (store, store.block_store.send_blocks_handle, transaction, send_zero); + + // Replace with the previous sideband version for state blocks + // The upgrade can resume after upgrading some blocks, test this by only downgrading some of them + write_sideband_v15 (store, transaction, state_receive_zero); + write_sideband_v15 (store, transaction, epoch); + write_sideband_v15 (store, transaction, state_send); + write_sideband_v15 (store, transaction, state_change); + write_sideband_v15 (store, transaction, state_send_change); + write_sideband_v15 (store, transaction, state_receive2); + write_sideband_v15 (store, transaction, state_open); + + store.block.del (transaction, state_receive_zero.hash ()); + store.block.del (transaction, epoch.hash ()); + store.block.del (transaction, state_send.hash ()); + store.block.del (transaction, state_change.hash ()); + store.block.del (transaction, state_send_change.hash ()); + store.block.del (transaction, state_receive2.hash ()); + store.block.del (transaction, state_open.hash ()); + } + + // Now do the upgrade nano::logger_mt logger; nano::lmdb::store store (logger, path, nano::dev::constants); - auto transaction (store.tx_begin_write ()); - nano::stat stats; - nano::ledger ledger (store, stats, nano::dev::constants); - store.initialize (transaction, ledger.cache, nano::dev::constants); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send_zero).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_receive_zero).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_send).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_receive).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_change).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_send_change).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, epoch_first).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_receive2).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_send2).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_open).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_send_epoch_link).code); + ASSERT_FALSE (store.init_error ()); + auto transaction (store.tx_begin_read ()); - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "open", MDB_CREATE, &store.open_blocks_handle)); - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "send", MDB_CREATE, &store.send_blocks_handle)); - ASSERT_FALSE (mdb_dbi_open (store.env.tx (transaction), "state_blocks", MDB_CREATE, &store.state_blocks_handle)); + // Size of state block should equal that set in db (no change) + nano::mdb_val value; + ASSERT_FALSE (mdb_get (store.env.tx (transaction), store.block_store.blocks_handle, nano::mdb_val (state_send.hash ()), value)); + ASSERT_EQ (value.size (), sizeof (nano::block_type) + nano::state_block::size + nano::block_sideband::size (nano::block_type::state)); - // Downgrade the store - store.version.put (transaction, 17); - - write_block_w_sideband_v18 (store, store.state_blocks_handle, transaction, state_receive); - write_block_w_sideband_v18 (store, store.state_blocks_handle, transaction, epoch_first); - write_block_w_sideband_v18 (store, store.state_blocks_handle, transaction, state_send2); - write_block_w_sideband_v18 (store, store.state_blocks_handle, transaction, state_send_epoch_link); - write_block_w_sideband_v18 (store, store.open_blocks_handle, transaction, *nano::dev::genesis); - write_block_w_sideband_v18 (store, store.send_blocks_handle, transaction, send_zero); - - // Replace with the previous sideband version for state blocks - // The upgrade can resume after upgrading some blocks, test this by only downgrading some of them - write_sideband_v15 (store, transaction, state_receive_zero); - write_sideband_v15 (store, transaction, epoch); - write_sideband_v15 (store, transaction, state_send); - write_sideband_v15 (store, transaction, state_change); - write_sideband_v15 (store, transaction, state_send_change); - write_sideband_v15 (store, transaction, state_receive2); - write_sideband_v15 (store, transaction, state_open); - - store.block.del (transaction, state_receive_zero.hash ()); - store.block.del (transaction, epoch.hash ()); - store.block.del (transaction, state_send.hash ()); - store.block.del (transaction, state_change.hash ()); - store.block.del (transaction, state_send_change.hash ()); - store.block.del (transaction, state_receive2.hash ()); - store.block.del (transaction, state_open.hash ()); + // Check that sidebands are correctly populated + { + // Non-state unaffected + auto block = store.block.get (transaction, send_zero.hash ()); + ASSERT_NE (block, nullptr); + // All defaults + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_0); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); + } + { + // State receive from old zero send + auto block = store.block.get (transaction, state_receive_zero.hash ()); + ASSERT_NE (block, nullptr); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_0); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_TRUE (block->sideband ().details.is_receive); + } + { + // Epoch + auto block = store.block.get (transaction, epoch.hash ()); + ASSERT_NE (block, nullptr); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_TRUE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); + } + { + // State send + auto block = store.block.get (transaction, state_send.hash ()); + ASSERT_NE (block, nullptr); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_TRUE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); + } + { + // State receive + auto block = store.block.get (transaction, state_receive.hash ()); + ASSERT_NE (block, nullptr); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_TRUE (block->sideband ().details.is_receive); + } + { + // State change + auto block = store.block.get (transaction, state_change.hash ()); + ASSERT_NE (block, nullptr); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); + } + { + // State send + change + auto block = store.block.get (transaction, state_send_change.hash ()); + ASSERT_NE (block, nullptr); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_TRUE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); + } + { + // Epoch on unopened account + auto block = store.block.get (transaction, epoch_first.hash ()); + ASSERT_NE (block, nullptr); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_2); + ASSERT_TRUE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); + } + { + // State open following epoch + auto block = store.block.get (transaction, state_receive2.hash ()); + ASSERT_NE (block, nullptr); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_2); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_TRUE (block->sideband ().details.is_receive); + } + { + // Another state send + auto block = store.block.get (transaction, state_send2.hash ()); + ASSERT_NE (block, nullptr); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_TRUE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); + } + { + // State open + auto block = store.block.get (transaction, state_open.hash ()); + ASSERT_NE (block, nullptr); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_FALSE (block->sideband ().details.is_send); + ASSERT_TRUE (block->sideband ().details.is_receive); + } + { + // State send to an epoch link + auto block = store.block.get (transaction, state_send_epoch_link.hash ()); + ASSERT_NE (block, nullptr); + ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); + ASSERT_FALSE (block->sideband ().details.is_epoch); + ASSERT_TRUE (block->sideband ().details.is_send); + ASSERT_FALSE (block->sideband ().details.is_receive); + } + // Version should be correct + ASSERT_LT (17, store.version.get (transaction)); } - // Now do the upgrade - nano::logger_mt logger; - nano::lmdb::store store (logger, path, nano::dev::constants); - ASSERT_FALSE (store.init_error ()); - auto transaction (store.tx_begin_read ()); + TEST (mdb_block_store, upgrade_v18_v19) + { + if (nano::rocksdb_config::using_rocksdb_in_tests ()) + { + // Don't test this in rocksdb mode + return; + } + auto path (nano::unique_path ()); + nano::keypair key1; + nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; + nano::send_block send (nano::dev::genesis->hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (nano::dev::genesis->hash ())); + nano::receive_block receive (send.hash (), send.hash (), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (send.hash ())); + nano::change_block change (receive.hash (), 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (receive.hash ())); + nano::state_block state_epoch (nano::dev::genesis_key.pub, change.hash (), 0, nano::dev::constants.genesis_amount, nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_1), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (change.hash ())); + nano::state_block state_send (nano::dev::genesis_key.pub, state_epoch.hash (), 0, nano::dev::constants.genesis_amount - nano::Gxrb_ratio, key1.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (state_epoch.hash ())); + nano::state_block state_open (key1.pub, 0, 0, nano::Gxrb_ratio, state_send.hash (), key1.prv, key1.pub, *pool.generate (key1.pub)); - // Size of state block should equal that set in db (no change) - nano::mdb_val value; - ASSERT_FALSE (mdb_get (store.env.tx (transaction), store.blocks_handle, nano::mdb_val (state_send.hash ()), value)); - ASSERT_EQ (value.size (), sizeof (nano::block_type) + nano::state_block::size + nano::block_sideband::size (nano::block_type::state)); + { + nano::logger_mt logger; + nano::lmdb::store store (logger, path, nano::dev::constants); + nano::stat stats; + nano::ledger ledger (store, stats, nano::dev::constants); + auto transaction (store.tx_begin_write ()); + store.initialize (transaction, ledger.cache, nano::dev::constants); - // Check that sidebands are correctly populated - { - // Non-state unaffected - auto block = store.block.get (transaction, send_zero.hash ()); - ASSERT_NE (block, nullptr); - // All defaults - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_0); - ASSERT_FALSE (block->sideband ().details.is_epoch); - ASSERT_FALSE (block->sideband ().details.is_send); - ASSERT_FALSE (block->sideband ().details.is_receive); - } - { - // State receive from old zero send - auto block = store.block.get (transaction, state_receive_zero.hash ()); - ASSERT_NE (block, nullptr); - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_0); - ASSERT_FALSE (block->sideband ().details.is_epoch); - ASSERT_FALSE (block->sideband ().details.is_send); - ASSERT_TRUE (block->sideband ().details.is_receive); - } - { - // Epoch - auto block = store.block.get (transaction, epoch.hash ()); - ASSERT_NE (block, nullptr); - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); - ASSERT_TRUE (block->sideband ().details.is_epoch); - ASSERT_FALSE (block->sideband ().details.is_send); - ASSERT_FALSE (block->sideband ().details.is_receive); - } - { - // State send - auto block = store.block.get (transaction, state_send.hash ()); - ASSERT_NE (block, nullptr); - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (block->sideband ().details.is_epoch); - ASSERT_TRUE (block->sideband ().details.is_send); - ASSERT_FALSE (block->sideband ().details.is_receive); - } - { - // State receive - auto block = store.block.get (transaction, state_receive.hash ()); - ASSERT_NE (block, nullptr); - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (block->sideband ().details.is_epoch); - ASSERT_FALSE (block->sideband ().details.is_send); - ASSERT_TRUE (block->sideband ().details.is_receive); - } - { - // State change - auto block = store.block.get (transaction, state_change.hash ()); - ASSERT_NE (block, nullptr); - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (block->sideband ().details.is_epoch); - ASSERT_FALSE (block->sideband ().details.is_send); - ASSERT_FALSE (block->sideband ().details.is_receive); - } - { - // State send + change - auto block = store.block.get (transaction, state_send_change.hash ()); - ASSERT_NE (block, nullptr); - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (block->sideband ().details.is_epoch); - ASSERT_TRUE (block->sideband ().details.is_send); - ASSERT_FALSE (block->sideband ().details.is_receive); - } - { - // Epoch on unopened account - auto block = store.block.get (transaction, epoch_first.hash ()); - ASSERT_NE (block, nullptr); - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_2); - ASSERT_TRUE (block->sideband ().details.is_epoch); - ASSERT_FALSE (block->sideband ().details.is_send); - ASSERT_FALSE (block->sideband ().details.is_receive); - } - { - // State open following epoch - auto block = store.block.get (transaction, state_receive2.hash ()); - ASSERT_NE (block, nullptr); - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_2); - ASSERT_FALSE (block->sideband ().details.is_epoch); - ASSERT_FALSE (block->sideband ().details.is_send); - ASSERT_TRUE (block->sideband ().details.is_receive); - } - { - // Another state send - auto block = store.block.get (transaction, state_send2.hash ()); - ASSERT_NE (block, nullptr); - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (block->sideband ().details.is_epoch); - ASSERT_TRUE (block->sideband ().details.is_send); - ASSERT_FALSE (block->sideband ().details.is_receive); - } - { - // State open - auto block = store.block.get (transaction, state_open.hash ()); - ASSERT_NE (block, nullptr); - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (block->sideband ().details.is_epoch); - ASSERT_FALSE (block->sideband ().details.is_send); - ASSERT_TRUE (block->sideband ().details.is_receive); - } - { - // State send to an epoch link - auto block = store.block.get (transaction, state_send_epoch_link.hash ()); - ASSERT_NE (block, nullptr); - ASSERT_EQ (block->sideband ().details.epoch, nano::epoch::epoch_1); - ASSERT_FALSE (block->sideband ().details.is_epoch); - ASSERT_TRUE (block->sideband ().details.is_send); - ASSERT_FALSE (block->sideband ().details.is_receive); - } - // Version should be correct - ASSERT_LT (17, store.version.get (transaction)); -} + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, change).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_epoch).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_send).code); + ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_open).code); -TEST (mdb_block_store, upgrade_v18_v19) -{ - if (nano::rocksdb_config::using_rocksdb_in_tests ()) - { - // Don't test this in rocksdb mode - return; - } - auto path (nano::unique_path ()); - nano::keypair key1; - nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::send_block send (nano::dev::genesis->hash (), nano::dev::genesis_key.pub, nano::dev::constants.genesis_amount - nano::Gxrb_ratio, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (nano::dev::genesis->hash ())); - nano::receive_block receive (send.hash (), send.hash (), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (send.hash ())); - nano::change_block change (receive.hash (), 0, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (receive.hash ())); - nano::state_block state_epoch (nano::dev::genesis_key.pub, change.hash (), 0, nano::dev::constants.genesis_amount, nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_1), nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (change.hash ())); - nano::state_block state_send (nano::dev::genesis_key.pub, state_epoch.hash (), 0, nano::dev::constants.genesis_amount - nano::Gxrb_ratio, key1.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, *pool.generate (state_epoch.hash ())); - nano::state_block state_open (key1.pub, 0, 0, nano::Gxrb_ratio, state_send.hash (), key1.prv, key1.pub, *pool.generate (key1.pub)); + // These tables need to be re-opened and populated so that an upgrade can be done + auto txn = store.env.tx (transaction); + ASSERT_FALSE (mdb_dbi_open (txn, "open", MDB_CREATE, &store.block_store.open_blocks_handle)); + ASSERT_FALSE (mdb_dbi_open (txn, "receive", MDB_CREATE, &store.block_store.receive_blocks_handle)); + ASSERT_FALSE (mdb_dbi_open (txn, "send", MDB_CREATE, &store.block_store.send_blocks_handle)); + ASSERT_FALSE (mdb_dbi_open (txn, "change", MDB_CREATE, &store.block_store.change_blocks_handle)); + ASSERT_FALSE (mdb_dbi_open (txn, "state_blocks", MDB_CREATE, &store.block_store.state_blocks_handle)); - { + // Modify blocks back to the old tables + write_block_w_sideband_v18 (store, store.block_store.open_blocks_handle, transaction, *nano::dev::genesis); + write_block_w_sideband_v18 (store, store.block_store.send_blocks_handle, transaction, send); + write_block_w_sideband_v18 (store, store.block_store.receive_blocks_handle, transaction, receive); + write_block_w_sideband_v18 (store, store.block_store.change_blocks_handle, transaction, change); + write_block_w_sideband_v18 (store, store.block_store.state_blocks_handle, transaction, state_epoch); + write_block_w_sideband_v18 (store, store.block_store.state_blocks_handle, transaction, state_send); + write_block_w_sideband_v18 (store, store.block_store.state_blocks_handle, transaction, state_open); + + store.version.put (transaction, 18); + } + + // Now do the upgrade nano::logger_mt logger; nano::lmdb::store store (logger, path, nano::dev::constants); + ASSERT_FALSE (store.init_error ()); + auto transaction (store.tx_begin_read ()); + + // These tables should be deleted + ASSERT_EQ (store.block_store.send_blocks_handle, 0); + ASSERT_EQ (store.block_store.receive_blocks_handle, 0); + ASSERT_EQ (store.block_store.change_blocks_handle, 0); + ASSERT_EQ (store.block_store.open_blocks_handle, 0); + ASSERT_EQ (store.block_store.state_blocks_handle, 0); + + // Confirm these blocks all exist after the upgrade + ASSERT_TRUE (store.block.get (transaction, send.hash ())); + ASSERT_TRUE (store.block.get (transaction, receive.hash ())); + ASSERT_TRUE (store.block.get (transaction, change.hash ())); + ASSERT_TRUE (store.block.get (transaction, nano::dev::genesis->hash ())); + auto state_epoch_disk (store.block.get (transaction, state_epoch.hash ())); + ASSERT_NE (nullptr, state_epoch_disk); + ASSERT_EQ (nano::epoch::epoch_1, state_epoch_disk->sideband ().details.epoch); + ASSERT_EQ (nano::epoch::epoch_0, state_epoch_disk->sideband ().source_epoch); // Not used for epoch state blocks + ASSERT_TRUE (store.block.get (transaction, state_send.hash ())); + auto state_send_disk (store.block.get (transaction, state_send.hash ())); + ASSERT_NE (nullptr, state_send_disk); + ASSERT_EQ (nano::epoch::epoch_1, state_send_disk->sideband ().details.epoch); + ASSERT_EQ (nano::epoch::epoch_0, state_send_disk->sideband ().source_epoch); // Not used for send state blocks + ASSERT_TRUE (store.block.get (transaction, state_open.hash ())); + auto state_open_disk (store.block.get (transaction, state_open.hash ())); + ASSERT_NE (nullptr, state_open_disk); + ASSERT_EQ (nano::epoch::epoch_1, state_open_disk->sideband ().details.epoch); + ASSERT_EQ (nano::epoch::epoch_1, state_open_disk->sideband ().source_epoch); + + ASSERT_EQ (7, store.count (transaction, store.block_store.blocks_handle)); + + // Version should be correct + ASSERT_LT (18, store.version.get (transaction)); + } + + TEST (mdb_block_store, upgrade_v19_v20) + { + if (nano::rocksdb_config::using_rocksdb_in_tests ()) + { + // Don't test this in rocksdb mode + return; + } + auto path (nano::unique_path ()); + nano::logger_mt logger; nano::stat stats; - nano::ledger ledger (store, stats, nano::dev::constants); - auto transaction (store.tx_begin_write ()); - store.initialize (transaction, ledger.cache, nano::dev::constants); - - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, send).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, receive).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, change).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_epoch).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_send).code); - ASSERT_EQ (nano::process_result::progress, ledger.process (transaction, state_open).code); - - // These tables need to be re-opened and populated so that an upgrade can be done - auto txn = store.env.tx (transaction); - ASSERT_FALSE (mdb_dbi_open (txn, "open", MDB_CREATE, &store.open_blocks_handle)); - ASSERT_FALSE (mdb_dbi_open (txn, "receive", MDB_CREATE, &store.receive_blocks_handle)); - ASSERT_FALSE (mdb_dbi_open (txn, "send", MDB_CREATE, &store.send_blocks_handle)); - ASSERT_FALSE (mdb_dbi_open (txn, "change", MDB_CREATE, &store.change_blocks_handle)); - ASSERT_FALSE (mdb_dbi_open (txn, "state_blocks", MDB_CREATE, &store.state_blocks_handle)); - - // Modify blocks back to the old tables - write_block_w_sideband_v18 (store, store.open_blocks_handle, transaction, *nano::dev::genesis); - write_block_w_sideband_v18 (store, store.send_blocks_handle, transaction, send); - write_block_w_sideband_v18 (store, store.receive_blocks_handle, transaction, receive); - write_block_w_sideband_v18 (store, store.change_blocks_handle, transaction, change); - write_block_w_sideband_v18 (store, store.state_blocks_handle, transaction, state_epoch); - write_block_w_sideband_v18 (store, store.state_blocks_handle, transaction, state_send); - write_block_w_sideband_v18 (store, store.state_blocks_handle, transaction, state_open); - - store.version.put (transaction, 18); - } - - // Now do the upgrade - nano::logger_mt logger; - nano::lmdb::store store (logger, path, nano::dev::constants); - ASSERT_FALSE (store.init_error ()); - auto transaction (store.tx_begin_read ()); - - // These tables should be deleted - ASSERT_EQ (store.send_blocks_handle, 0); - ASSERT_EQ (store.receive_blocks_handle, 0); - ASSERT_EQ (store.change_blocks_handle, 0); - ASSERT_EQ (store.open_blocks_handle, 0); - ASSERT_EQ (store.state_blocks_handle, 0); - - // Confirm these blocks all exist after the upgrade - ASSERT_TRUE (store.block.get (transaction, send.hash ())); - ASSERT_TRUE (store.block.get (transaction, receive.hash ())); - ASSERT_TRUE (store.block.get (transaction, change.hash ())); - ASSERT_TRUE (store.block.get (transaction, nano::dev::genesis->hash ())); - auto state_epoch_disk (store.block.get (transaction, state_epoch.hash ())); - ASSERT_NE (nullptr, state_epoch_disk); - ASSERT_EQ (nano::epoch::epoch_1, state_epoch_disk->sideband ().details.epoch); - ASSERT_EQ (nano::epoch::epoch_0, state_epoch_disk->sideband ().source_epoch); // Not used for epoch state blocks - ASSERT_TRUE (store.block.get (transaction, state_send.hash ())); - auto state_send_disk (store.block.get (transaction, state_send.hash ())); - ASSERT_NE (nullptr, state_send_disk); - ASSERT_EQ (nano::epoch::epoch_1, state_send_disk->sideband ().details.epoch); - ASSERT_EQ (nano::epoch::epoch_0, state_send_disk->sideband ().source_epoch); // Not used for send state blocks - ASSERT_TRUE (store.block.get (transaction, state_open.hash ())); - auto state_open_disk (store.block.get (transaction, state_open.hash ())); - ASSERT_NE (nullptr, state_open_disk); - ASSERT_EQ (nano::epoch::epoch_1, state_open_disk->sideband ().details.epoch); - ASSERT_EQ (nano::epoch::epoch_1, state_open_disk->sideband ().source_epoch); - - ASSERT_EQ (7, store.count (transaction, store.blocks_handle)); - - // Version should be correct - ASSERT_LT (18, store.version.get (transaction)); -} - -TEST (mdb_block_store, upgrade_v19_v20) -{ - if (nano::rocksdb_config::using_rocksdb_in_tests ()) - { - // Don't test this in rocksdb mode - return; - } - auto path (nano::unique_path ()); - nano::logger_mt logger; - nano::stat stats; - { + { + nano::lmdb::store store (logger, path, nano::dev::constants); + nano::ledger ledger (store, stats, nano::dev::constants); + auto transaction (store.tx_begin_write ()); + store.initialize (transaction, ledger.cache, nano::dev::constants); + // Delete pruned table + ASSERT_FALSE (mdb_drop (store.env.tx (transaction), store.pruned_store.pruned_handle, 1)); + store.version.put (transaction, 19); + } + // Upgrading should create the table nano::lmdb::store store (logger, path, nano::dev::constants); - nano::ledger ledger (store, stats, nano::dev::constants); - auto transaction (store.tx_begin_write ()); - store.initialize (transaction, ledger.cache, nano::dev::constants); - // Delete pruned table - ASSERT_FALSE (mdb_drop (store.env.tx (transaction), store.pruned_handle, 1)); - store.version.put (transaction, 19); - } - // Upgrading should create the table - nano::lmdb::store store (logger, path, nano::dev::constants); - ASSERT_FALSE (store.init_error ()); - ASSERT_NE (store.pruned_handle, 0); + ASSERT_FALSE (store.init_error ()); + ASSERT_NE (store.pruned_store.pruned_handle, 0); - // Version should be correct - auto transaction (store.tx_begin_read ()); - ASSERT_LT (19, store.version.get (transaction)); -} - -TEST (mdb_block_store, upgrade_v20_v21) -{ - if (nano::rocksdb_config::using_rocksdb_in_tests ()) - { - // Don't test this in rocksdb mode - return; + // Version should be correct + auto transaction (store.tx_begin_read ()); + ASSERT_LT (19, store.version.get (transaction)); } - auto path (nano::unique_path ()); - nano::logger_mt logger; - nano::stat stats; + + TEST (mdb_block_store, upgrade_v20_v21) { + if (nano::rocksdb_config::using_rocksdb_in_tests ()) + { + // Don't test this in rocksdb mode + return; + } + auto path (nano::unique_path ()); + nano::logger_mt logger; + nano::stat stats; + { + nano::lmdb::store store (logger, path, nano::dev::constants); + nano::ledger ledger (store, stats, nano::dev::constants); + auto transaction (store.tx_begin_write ()); + store.initialize (transaction, ledger.cache, ledger.constants); + // Delete pruned table + ASSERT_FALSE (mdb_drop (store.env.tx (transaction), store.final_vote_store.final_votes_handle, 1)); + store.version.put (transaction, 20); + } + // Upgrading should create the table nano::lmdb::store store (logger, path, nano::dev::constants); - nano::ledger ledger (store, stats, nano::dev::constants); - auto transaction (store.tx_begin_write ()); - store.initialize (transaction, ledger.cache, ledger.constants); - // Delete pruned table - ASSERT_FALSE (mdb_drop (store.env.tx (transaction), store.final_votes_handle, 1)); - store.version.put (transaction, 20); - } - // Upgrading should create the table - nano::lmdb::store store (logger, path, nano::dev::constants); - ASSERT_FALSE (store.init_error ()); - ASSERT_NE (store.final_votes_handle, 0); + ASSERT_FALSE (store.init_error ()); + ASSERT_NE (store.final_vote_store.final_votes_handle, 0); - // Version should be correct - auto transaction (store.tx_begin_read ()); - ASSERT_LT (19, store.version.get (transaction)); + // Version should be correct + auto transaction (store.tx_begin_read ()); + ASSERT_LT (19, store.version.get (transaction)); + } +} } TEST (mdb_block_store, upgrade_backup) @@ -2067,75 +2121,78 @@ TEST (rocksdb_block_store, tombstone_count) } } -namespace +namespace nano { -void write_sideband_v14 (nano::lmdb::store & store_a, nano::transaction & transaction_a, nano::block const & block_a, MDB_dbi db_a) +namespace lmdb { - auto block = store_a.block.get (transaction_a, block_a.hash ()); - ASSERT_NE (block, nullptr); - - nano::block_sideband_v14 sideband_v14 (block->type (), block->sideband ().account, block->sideband ().successor, block->sideband ().balance, block->sideband ().timestamp, block->sideband ().height); - std::vector data; + void write_sideband_v14 (nano::lmdb::store & store_a, nano::transaction & transaction_a, nano::block const & block_a, MDB_dbi db_a) { - nano::vectorstream stream (data); - block_a.serialize (stream); - sideband_v14.serialize (stream); + auto block = store_a.block.get (transaction_a, block_a.hash ()); + ASSERT_NE (block, nullptr); + + nano::block_sideband_v14 sideband_v14 (block->type (), block->sideband ().account, block->sideband ().successor, block->sideband ().balance, block->sideband ().timestamp, block->sideband ().height); + std::vector data; + { + nano::vectorstream stream (data); + block_a.serialize (stream); + sideband_v14.serialize (stream); + } + + MDB_val val{ data.size (), data.data () }; + ASSERT_FALSE (mdb_put (store_a.env.tx (transaction_a), block->sideband ().details.epoch == nano::epoch::epoch_0 ? store_a.block_store.state_blocks_v0_handle : store_a.block_store.state_blocks_v1_handle, nano::mdb_val (block_a.hash ()), &val, 0)); } - MDB_val val{ data.size (), data.data () }; - ASSERT_FALSE (mdb_put (store_a.env.tx (transaction_a), block->sideband ().details.epoch == nano::epoch::epoch_0 ? store_a.state_blocks_v0_handle : store_a.state_blocks_v1_handle, nano::mdb_val (block_a.hash ()), &val, 0)); -} - -void write_sideband_v15 (nano::lmdb::store & store_a, nano::transaction & transaction_a, nano::block const & block_a) -{ - auto block = store_a.block.get (transaction_a, block_a.hash ()); - ASSERT_NE (block, nullptr); - - ASSERT_LE (block->sideband ().details.epoch, nano::epoch::max); - // Simulated by writing 0 on every of the most significant bits, leaving out epoch only, as if pre-upgrade - nano::block_sideband_v18 sideband_v15 (block->sideband ().account, block->sideband ().successor, block->sideband ().balance, block->sideband ().timestamp, block->sideband ().height, block->sideband ().details.epoch, false, false, false); - std::vector data; + void write_sideband_v15 (nano::lmdb::store & store_a, nano::transaction & transaction_a, nano::block const & block_a) { - nano::vectorstream stream (data); - block_a.serialize (stream); - sideband_v15.serialize (stream, block_a.type ()); + auto block = store_a.block.get (transaction_a, block_a.hash ()); + ASSERT_NE (block, nullptr); + + ASSERT_LE (block->sideband ().details.epoch, nano::epoch::max); + // Simulated by writing 0 on every of the most significant bits, leaving out epoch only, as if pre-upgrade + nano::block_sideband_v18 sideband_v15 (block->sideband ().account, block->sideband ().successor, block->sideband ().balance, block->sideband ().timestamp, block->sideband ().height, block->sideband ().details.epoch, false, false, false); + std::vector data; + { + nano::vectorstream stream (data); + block_a.serialize (stream); + sideband_v15.serialize (stream, block_a.type ()); + } + + MDB_val val{ data.size (), data.data () }; + ASSERT_FALSE (mdb_put (store_a.env.tx (transaction_a), store_a.block_store.state_blocks_handle, nano::mdb_val (block_a.hash ()), &val, 0)); } - MDB_val val{ data.size (), data.data () }; - ASSERT_FALSE (mdb_put (store_a.env.tx (transaction_a), store_a.state_blocks_handle, nano::mdb_val (block_a.hash ()), &val, 0)); -} - -void write_block_w_sideband_v18 (nano::lmdb::store & store_a, MDB_dbi database, nano::write_transaction & transaction_a, nano::block const & block_a) -{ - auto block = store_a.block.get (transaction_a, block_a.hash ()); - ASSERT_NE (block, nullptr); - auto new_sideband (block->sideband ()); - nano::block_sideband_v18 sideband_v18 (new_sideband.account, new_sideband.successor, new_sideband.balance, new_sideband.height, new_sideband.timestamp, new_sideband.details.epoch, new_sideband.details.is_send, new_sideband.details.is_receive, new_sideband.details.is_epoch); - - std::vector data; + void write_block_w_sideband_v18 (nano::lmdb::store & store_a, MDB_dbi database, nano::write_transaction & transaction_a, nano::block const & block_a) { - nano::vectorstream stream (data); - block->serialize (stream); - sideband_v18.serialize (stream, block->type ()); + auto block = store_a.block.get (transaction_a, block_a.hash ()); + ASSERT_NE (block, nullptr); + auto new_sideband (block->sideband ()); + nano::block_sideband_v18 sideband_v18 (new_sideband.account, new_sideband.successor, new_sideband.balance, new_sideband.height, new_sideband.timestamp, new_sideband.details.epoch, new_sideband.details.is_send, new_sideband.details.is_receive, new_sideband.details.is_epoch); + + std::vector data; + { + nano::vectorstream stream (data); + block->serialize (stream); + sideband_v18.serialize (stream, block->type ()); + } + + MDB_val val{ data.size (), data.data () }; + ASSERT_FALSE (mdb_put (store_a.env.tx (transaction_a), database, nano::mdb_val (block_a.hash ()), &val, 0)); + store_a.del (transaction_a, nano::tables::blocks, nano::mdb_val (block_a.hash ())); } - MDB_val val{ data.size (), data.data () }; - ASSERT_FALSE (mdb_put (store_a.env.tx (transaction_a), database, nano::mdb_val (block_a.hash ()), &val, 0)); - store_a.del (transaction_a, nano::tables::blocks, nano::mdb_val (block_a.hash ())); -} + void modify_account_info_to_v14 (nano::lmdb::store & store, nano::transaction const & transaction, nano::account const & account, uint64_t confirmation_height, nano::block_hash const & rep_block) + { + nano::account_info info; + ASSERT_FALSE (store.account.get (transaction, account, info)); + nano::account_info_v14 account_info_v14 (info.head, rep_block, info.open_block, info.balance, info.modified, info.block_count, confirmation_height, info.epoch ()); + auto status (mdb_put (store.env.tx (transaction), info.epoch () == nano::epoch::epoch_0 ? store.account_store.accounts_v0_handle : store.account_store.accounts_v1_handle, nano::mdb_val (account), nano::mdb_val (account_info_v14), 0)); + ASSERT_EQ (status, 0); + } -void modify_account_info_to_v14 (nano::lmdb::store & store, nano::transaction const & transaction, nano::account const & account, uint64_t confirmation_height, nano::block_hash const & rep_block) -{ - nano::account_info info; - ASSERT_FALSE (store.account.get (transaction, account, info)); - nano::account_info_v14 account_info_v14 (info.head, rep_block, info.open_block, info.balance, info.modified, info.block_count, confirmation_height, info.epoch ()); - auto status (mdb_put (store.env.tx (transaction), info.epoch () == nano::epoch::epoch_0 ? store.accounts_v0_handle : store.accounts_v1_handle, nano::mdb_val (account), nano::mdb_val (account_info_v14), 0)); - ASSERT_EQ (status, 0); -} - -void modify_confirmation_height_to_v15 (nano::lmdb::store & store, nano::transaction const & transaction, nano::account const & account, uint64_t confirmation_height) -{ - auto status (mdb_put (store.env.tx (transaction), store.confirmation_height_handle, nano::mdb_val (account), nano::mdb_val (confirmation_height), 0)); - ASSERT_EQ (status, 0); + void modify_confirmation_height_to_v15 (nano::lmdb::store & store, nano::transaction const & transaction, nano::account const & account, uint64_t confirmation_height) + { + auto status (mdb_put (store.env.tx (transaction), store.confirmation_height_store.confirmation_height_handle, nano::mdb_val (account), nano::mdb_val (confirmation_height), 0)); + ASSERT_EQ (status, 0); + } } } diff --git a/nano/node/lmdb/account_store.hpp b/nano/node/lmdb/account_store.hpp index 41ee8d76..ea93b257 100644 --- a/nano/node/lmdb/account_store.hpp +++ b/nano/node/lmdb/account_store.hpp @@ -2,6 +2,8 @@ #include +#include + namespace nano { namespace lmdb @@ -24,6 +26,30 @@ namespace lmdb nano::store_iterator rbegin (nano::transaction const & transaction_a) const override; nano::store_iterator end () const override; void for_each_par (std::function, nano::store_iterator)> const & action_a) const override; + + /** + * Maps account v1 to account information, head, rep, open, balance, timestamp and block count. (Removed) + * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t + */ + MDB_dbi accounts_v0_handle{ 0 }; + + /** + * Maps account v0 to account information, head, rep, open, balance, timestamp and block count. (Removed) + * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t + */ + MDB_dbi accounts_v1_handle{ 0 }; + + /** + * Maps account v0 to account information, head, rep, open, balance, timestamp, block count and epoch + * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t, nano::epoch + */ + MDB_dbi accounts_handle{ 0 }; + + /** + * Representative weights. (Removed) + * nano::account -> nano::uint128_t + */ + MDB_dbi representation_handle{ 0 }; }; } } diff --git a/nano/node/lmdb/block_store.hpp b/nano/node/lmdb/block_store.hpp index 28c1c54f..f3169a18 100644 --- a/nano/node/lmdb/block_store.hpp +++ b/nano/node/lmdb/block_store.hpp @@ -2,6 +2,8 @@ #include +#include + namespace nano { using mdb_val = db_val; @@ -38,6 +40,60 @@ namespace lmdb // Converts a block hash to a block height uint64_t account_height (nano::transaction const & transaction_a, nano::block_hash const & hash_a) const override; + /** + * Maps block hash to send block. (Removed) + * nano::block_hash -> nano::send_block + */ + MDB_dbi send_blocks_handle{ 0 }; + + /** + * Maps block hash to receive block. (Removed) + * nano::block_hash -> nano::receive_block + */ + MDB_dbi receive_blocks_handle{ 0 }; + + /** + * Maps block hash to open block. (Removed) + * nano::block_hash -> nano::open_block + */ + MDB_dbi open_blocks_handle{ 0 }; + + /** + * Maps block hash to change block. (Removed) + * nano::block_hash -> nano::change_block + */ + MDB_dbi change_blocks_handle{ 0 }; + + /** + * Maps block hash to v0 state block. (Removed) + * nano::block_hash -> nano::state_block + */ + MDB_dbi state_blocks_v0_handle{ 0 }; + + /** + * Maps block hash to v1 state block. (Removed) + * nano::block_hash -> nano::state_block + */ + MDB_dbi state_blocks_v1_handle{ 0 }; + + /** + * Maps block hash to state block. (Removed) + * nano::block_hash -> nano::state_block + */ + MDB_dbi state_blocks_handle{ 0 }; + + /** + * Meta information about block store, such as versions. + * nano::uint256_union (arbitrary key) -> blob + */ + MDB_dbi meta_handle{ 0 }; + + /** + * Contains block_sideband and block for all block types (legacy send/change/open/receive & state blocks) + * nano::block_hash -> nano::block_sideband, nano::block + */ + MDB_dbi blocks_handle{ 0 }; + protected: void block_raw_get (nano::transaction const & transaction_a, nano::block_hash const & hash_a, nano::mdb_val & value) const; size_t block_successor_offset (nano::transaction const & transaction_a, size_t entry_size_a, nano::block_type type_a) const; diff --git a/nano/node/lmdb/confirmation_height_store.hpp b/nano/node/lmdb/confirmation_height_store.hpp index 08d8daf6..ed814994 100644 --- a/nano/node/lmdb/confirmation_height_store.hpp +++ b/nano/node/lmdb/confirmation_height_store.hpp @@ -2,6 +2,8 @@ #include +#include + namespace nano { namespace lmdb @@ -24,6 +26,12 @@ namespace lmdb nano::store_iterator begin (nano::transaction const & transaction_a) const override; nano::store_iterator end () const override; void for_each_par (std::function, nano::store_iterator)> const & action_a) const override; + + /* + * Confirmation height of an account, and the hash for the block at that height + * nano::account -> uint64_t, nano::block_hash + */ + MDB_dbi confirmation_height_handle{ 0 }; }; } } diff --git a/nano/node/lmdb/final_vote_store.hpp b/nano/node/lmdb/final_vote_store.hpp index 9bc8c218..8e957641 100644 --- a/nano/node/lmdb/final_vote_store.hpp +++ b/nano/node/lmdb/final_vote_store.hpp @@ -2,6 +2,8 @@ #include +#include + namespace nano { namespace lmdb @@ -24,6 +26,12 @@ namespace lmdb nano::store_iterator begin (nano::transaction const & transaction_a) const override; nano::store_iterator end () const override; void for_each_par (std::function, nano::store_iterator)> const & action_a) const override; + + /** + * Maps root to block hash for generated final votes. + * nano::qualified_root -> nano::block_hash + */ + MDB_dbi final_votes_handle{ 0 }; }; } } diff --git a/nano/node/lmdb/frontier_store.hpp b/nano/node/lmdb/frontier_store.hpp index 805d2717..faf0d2cf 100644 --- a/nano/node/lmdb/frontier_store.hpp +++ b/nano/node/lmdb/frontier_store.hpp @@ -2,6 +2,8 @@ #include +#include + namespace nano { namespace lmdb @@ -9,6 +11,9 @@ namespace lmdb class store; class frontier_store : public nano::frontier_store { + private: + nano::lmdb::store & store; + public: frontier_store (nano::lmdb::store & store); void put (nano::write_transaction const &, nano::block_hash const &, nano::account const &) override; @@ -19,8 +24,11 @@ namespace lmdb nano::store_iterator end () const override; void for_each_par (std::function, nano::store_iterator)> const & action_a) const override; - private: - nano::lmdb::store & store; + /** + * Maps head block to owning account + * nano::block_hash -> nano::account + */ + MDB_dbi frontiers_handle{ 0 }; }; } } diff --git a/nano/node/lmdb/lmdb.cpp b/nano/node/lmdb/lmdb.cpp index 8b273aa3..848c119a 100644 --- a/nano/node/lmdb/lmdb.cpp +++ b/nano/node/lmdb/lmdb.cpp @@ -78,12 +78,12 @@ nano::lmdb::store::store (nano::logger_mt & logger_a, boost::filesystem::path co auto is_fresh_db (false); { auto transaction (tx_begin_read ()); - auto err = mdb_dbi_open (env.tx (transaction), "meta", 0, &meta_handle); + auto err = mdb_dbi_open (env.tx (transaction), "meta", 0, &block_store.meta_handle); is_fresh_db = err != MDB_SUCCESS; if (err == MDB_SUCCESS) { is_fully_upgraded = (version.get (transaction) == version_current); - mdb_dbi_close (env, meta_handle); + mdb_dbi_close (env, block_store.meta_handle); } } @@ -210,52 +210,52 @@ nano::mdb_txn_callbacks nano::lmdb::store::create_txn_callbacks () const void nano::lmdb::store::open_databases (bool & error_a, nano::transaction const & transaction_a, unsigned flags) { - error_a |= mdb_dbi_open (env.tx (transaction_a), "frontiers", flags, &frontiers_handle) != 0; - error_a |= mdb_dbi_open (env.tx (transaction_a), "unchecked", flags, &unchecked_handle) != 0; - error_a |= mdb_dbi_open (env.tx (transaction_a), "online_weight", flags, &online_weight_handle) != 0; - error_a |= mdb_dbi_open (env.tx (transaction_a), "meta", flags, &meta_handle) != 0; - error_a |= mdb_dbi_open (env.tx (transaction_a), "peers", flags, &peers_handle) != 0; - error_a |= mdb_dbi_open (env.tx (transaction_a), "pruned", flags, &pruned_handle) != 0; - error_a |= mdb_dbi_open (env.tx (transaction_a), "confirmation_height", flags, &confirmation_height_handle) != 0; - error_a |= mdb_dbi_open (env.tx (transaction_a), "accounts", flags, &accounts_v0_handle) != 0; - accounts_handle = accounts_v0_handle; - error_a |= mdb_dbi_open (env.tx (transaction_a), "pending", flags, &pending_v0_handle) != 0; - pending_handle = pending_v0_handle; - error_a |= mdb_dbi_open (env.tx (transaction_a), "final_votes", flags, &final_votes_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "frontiers", flags, &frontier_store.frontiers_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "unchecked", flags, &unchecked_store.unchecked_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "online_weight", flags, &online_weight_store.online_weight_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "meta", flags, &block_store.meta_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "peers", flags, &peer_store.peers_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "pruned", flags, &pruned_store.pruned_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "confirmation_height", flags, &confirmation_height_store.confirmation_height_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "accounts", flags, &account_store.accounts_v0_handle) != 0; + account_store.accounts_handle = account_store.accounts_v0_handle; + error_a |= mdb_dbi_open (env.tx (transaction_a), "pending", flags, &pending_store.pending_v0_handle) != 0; + pending_store.pending_handle = pending_store.pending_v0_handle; + error_a |= mdb_dbi_open (env.tx (transaction_a), "final_votes", flags, &final_vote_store.final_votes_handle) != 0; auto version_l = version.get (transaction_a); if (version_l < 19) { // These legacy (and state) block databases are no longer used, but need opening so they can be deleted during an upgrade - error_a |= mdb_dbi_open (env.tx (transaction_a), "send", flags, &send_blocks_handle) != 0; - error_a |= mdb_dbi_open (env.tx (transaction_a), "receive", flags, &receive_blocks_handle) != 0; - error_a |= mdb_dbi_open (env.tx (transaction_a), "open", flags, &open_blocks_handle) != 0; - error_a |= mdb_dbi_open (env.tx (transaction_a), "change", flags, &change_blocks_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "send", flags, &block_store.send_blocks_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "receive", flags, &block_store.receive_blocks_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "open", flags, &block_store.open_blocks_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "change", flags, &block_store.change_blocks_handle) != 0; if (version_l >= 15) { - error_a |= mdb_dbi_open (env.tx (transaction_a), "state_blocks", flags, &state_blocks_handle) != 0; - state_blocks_v0_handle = state_blocks_handle; + error_a |= mdb_dbi_open (env.tx (transaction_a), "state_blocks", flags, &block_store.state_blocks_handle) != 0; + block_store.state_blocks_v0_handle = block_store.state_blocks_handle; } } else { - error_a |= mdb_dbi_open (env.tx (transaction_a), "blocks", MDB_CREATE, &blocks_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "blocks", MDB_CREATE, &block_store.blocks_handle) != 0; } if (version_l < 16) { // The representation database is no longer used, but needs opening so that it can be deleted during an upgrade - error_a |= mdb_dbi_open (env.tx (transaction_a), "representation", flags, &representation_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "representation", flags, &account_store.representation_handle) != 0; } if (version_l < 15) { // These databases are no longer used, but need opening so they can be deleted during an upgrade - error_a |= mdb_dbi_open (env.tx (transaction_a), "state", flags, &state_blocks_v0_handle) != 0; - state_blocks_handle = state_blocks_v0_handle; - error_a |= mdb_dbi_open (env.tx (transaction_a), "accounts_v1", flags, &accounts_v1_handle) != 0; - error_a |= mdb_dbi_open (env.tx (transaction_a), "pending_v1", flags, &pending_v1_handle) != 0; - error_a |= mdb_dbi_open (env.tx (transaction_a), "state_v1", flags, &state_blocks_v1_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "state", flags, &block_store.state_blocks_v0_handle) != 0; + block_store.state_blocks_handle = block_store.state_blocks_v0_handle; + error_a |= mdb_dbi_open (env.tx (transaction_a), "accounts_v1", flags, &account_store.accounts_v1_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "pending_v1", flags, &pending_store.pending_v1_handle) != 0; + error_a |= mdb_dbi_open (env.tx (transaction_a), "state_v1", flags, &block_store.state_blocks_v1_handle) != 0; } } @@ -320,10 +320,10 @@ void nano::lmdb::store::upgrade_v14_to_v15 (nano::write_transaction & transactio logger.always_log ("Preparing v14 to v15 database upgrade..."); std::vector> account_infos; - upgrade_counters account_counters (count (transaction_a, accounts_v0_handle), count (transaction_a, accounts_v1_handle)); + upgrade_counters account_counters (count (transaction_a, account_store.accounts_v0_handle), count (transaction_a, account_store.accounts_v1_handle)); account_infos.reserve (account_counters.before_v0 + account_counters.before_v1); - nano::mdb_merge_iterator i_account (transaction_a, accounts_v0_handle, accounts_v1_handle); + nano::mdb_merge_iterator i_account (transaction_a, account_store.accounts_v0_handle, account_store.accounts_v1_handle); nano::mdb_merge_iterator n_account{}; for (; i_account != n_account; ++i_account) { @@ -335,7 +335,7 @@ void nano::lmdb::store::upgrade_v14_to_v15 (nano::write_transaction & transactio release_assert (rep_block != nullptr); account_infos.emplace_back (account, nano::account_info{ account_info_v14.head, rep_block->representative (), account_info_v14.open_block, account_info_v14.balance, account_info_v14.modified, account_info_v14.block_count, i_account.from_first_database ? nano::epoch::epoch_0 : nano::epoch::epoch_1 }); // Move confirmation height from account_info database to its own table - mdb_put (env.tx (transaction_a), confirmation_height_handle, nano::mdb_val (account), nano::mdb_val (account_info_v14.confirmation_height), MDB_APPEND); + mdb_put (env.tx (transaction_a), confirmation_height_store.confirmation_height_handle, nano::mdb_val (account), nano::mdb_val (account_info_v14.confirmation_height), MDB_APPEND); i_account.from_first_database ? ++account_counters.after_v0 : ++account_counters.after_v1; } @@ -343,13 +343,13 @@ void nano::lmdb::store::upgrade_v14_to_v15 (nano::write_transaction & transactio debug_assert (account_counters.are_equal ()); // No longer need accounts_v1, keep v0 but clear it - mdb_drop (env.tx (transaction_a), accounts_v1_handle, 1); - mdb_drop (env.tx (transaction_a), accounts_v0_handle, 0); + mdb_drop (env.tx (transaction_a), account_store.accounts_v1_handle, 1); + mdb_drop (env.tx (transaction_a), account_store.accounts_v0_handle, 0); for (auto const & account_account_info_pair : account_infos) { auto const & account_info (account_account_info_pair.second); - mdb_put (env.tx (transaction_a), accounts_handle, nano::mdb_val (account_account_info_pair.first), nano::mdb_val (account_info), MDB_APPEND); + mdb_put (env.tx (transaction_a), account_store.accounts_handle, nano::mdb_val (account_account_info_pair.first), nano::mdb_val (account_info), MDB_APPEND); } logger.always_log ("Epoch merge upgrade: Finished accounts, now doing state blocks"); @@ -360,9 +360,9 @@ void nano::lmdb::store::upgrade_v14_to_v15 (nano::write_transaction & transactio MDB_dbi state_blocks_new; mdb_dbi_open (env.tx (transaction_a), "state_blocks", MDB_CREATE, &state_blocks_new); - upgrade_counters state_counters (count (transaction_a, state_blocks_v0_handle), count (transaction_a, state_blocks_v1_handle)); + upgrade_counters state_counters (count (transaction_a, block_store.state_blocks_v0_handle), count (transaction_a, block_store.state_blocks_v1_handle)); - nano::mdb_merge_iterator i_state (transaction_a, state_blocks_v0_handle, state_blocks_v1_handle); + nano::mdb_merge_iterator i_state (transaction_a, block_store.state_blocks_v0_handle, block_store.state_blocks_v1_handle); nano::mdb_merge_iterator n_state{}; auto num = 0u; for (; i_state != n_state; ++i_state, ++num) @@ -397,19 +397,19 @@ void nano::lmdb::store::upgrade_v14_to_v15 (nano::write_transaction & transactio debug_assert (state_counters.are_equal ()); logger.always_log ("Epoch merge upgrade: Finished state blocks, now doing pending blocks"); - state_blocks_handle = state_blocks_new; + block_store.state_blocks_handle = state_blocks_new; // No longer need states v0/v1 databases - mdb_drop (env.tx (transaction_a), state_blocks_v1_handle, 1); - mdb_drop (env.tx (transaction_a), state_blocks_v0_handle, 1); + mdb_drop (env.tx (transaction_a), block_store.state_blocks_v1_handle, 1); + mdb_drop (env.tx (transaction_a), block_store.state_blocks_v0_handle, 1); - state_blocks_v0_handle = state_blocks_handle; + block_store.state_blocks_v0_handle = block_store.state_blocks_handle; - upgrade_counters pending_counters (count (transaction_a, pending_v0_handle), count (transaction_a, pending_v1_handle)); + upgrade_counters pending_counters (count (transaction_a, pending_store.pending_v0_handle), count (transaction_a, pending_store.pending_v1_handle)); std::vector> pending_infos; pending_infos.reserve (pending_counters.before_v0 + pending_counters.before_v1); - nano::mdb_merge_iterator i_pending (transaction_a, pending_v0_handle, pending_v1_handle); + nano::mdb_merge_iterator i_pending (transaction_a, pending_store.pending_v0_handle, pending_store.pending_v1_handle); nano::mdb_merge_iterator n_pending{}; for (; i_pending != n_pending; ++i_pending) { @@ -421,12 +421,12 @@ void nano::lmdb::store::upgrade_v14_to_v15 (nano::write_transaction & transactio debug_assert (pending_counters.are_equal ()); // No longer need the pending v1 table - mdb_drop (env.tx (transaction_a), pending_v1_handle, 1); - mdb_drop (env.tx (transaction_a), pending_v0_handle, 0); + mdb_drop (env.tx (transaction_a), pending_store.pending_v1_handle, 1); + mdb_drop (env.tx (transaction_a), pending_store.pending_v0_handle, 0); for (auto const & pending_key_pending_info_pair : pending_infos) { - mdb_put (env.tx (transaction_a), pending_handle, nano::mdb_val (pending_key_pending_info_pair.first), nano::mdb_val (pending_key_pending_info_pair.second), MDB_APPEND); + mdb_put (env.tx (transaction_a), pending_store.pending_handle, nano::mdb_val (pending_key_pending_info_pair.first), nano::mdb_val (pending_key_pending_info_pair.second), MDB_APPEND); } version.put (transaction_a, 15); @@ -436,12 +436,12 @@ void nano::lmdb::store::upgrade_v14_to_v15 (nano::write_transaction & transactio void nano::lmdb::store::upgrade_v15_to_v16 (nano::write_transaction const & transaction_a) { // Representation table is no longer used - debug_assert (representation_handle != 0); - if (representation_handle != 0) + debug_assert (account_store.representation_handle != 0); + if (account_store.representation_handle != 0) { - auto status (mdb_drop (env.tx (transaction_a), representation_handle, 1)); + auto status (mdb_drop (env.tx (transaction_a), account_store.representation_handle, 1)); release_assert (status == MDB_SUCCESS); - representation_handle = 0; + account_store.representation_handle = 0; } version.put (transaction_a, 16); } @@ -456,7 +456,7 @@ void nano::lmdb::store::upgrade_v16_to_v17 (nano::write_transaction const & tran // Set the confirmed frontier for each account in the confirmation height table std::vector> confirmation_height_infos; auto num = 0u; - for (nano::mdb_iterator i (transaction_a, confirmation_height_handle), n (nano::mdb_iterator{}); i != n; ++i, ++account_info_i, ++num) + for (nano::mdb_iterator i (transaction_a, confirmation_height_store.confirmation_height_handle), n (nano::mdb_iterator{}); i != n; ++i, ++account_info_i, ++num) { nano::account account (i->first); uint64_t confirmation_height (i->second); @@ -513,12 +513,12 @@ void nano::lmdb::store::upgrade_v16_to_v17 (nano::write_transaction const & tran } // Clear it then append - auto status (mdb_drop (env.tx (transaction_a), confirmation_height_handle, 0)); + auto status (mdb_drop (env.tx (transaction_a), confirmation_height_store.confirmation_height_handle, 0)); release_assert_success (status); for (auto const & confirmation_height_info_pair : confirmation_height_infos) { - mdb_put (env.tx (transaction_a), confirmation_height_handle, nano::mdb_val (confirmation_height_info_pair.first), nano::mdb_val (confirmation_height_info_pair.second), MDB_APPEND); + mdb_put (env.tx (transaction_a), confirmation_height_store.confirmation_height_handle, nano::mdb_val (confirmation_height_info_pair.first), nano::mdb_val (confirmation_height_info_pair.second), MDB_APPEND); } version.put (transaction_a, 17); @@ -529,10 +529,10 @@ void nano::lmdb::store::upgrade_v17_to_v18 (nano::write_transaction const & tran { logger.always_log ("Preparing v17 to v18 database upgrade..."); - auto count_pre (count (transaction_a, state_blocks_handle)); + auto count_pre (count (transaction_a, block_store.state_blocks_handle)); auto num = 0u; - for (nano::mdb_iterator> state_i (transaction_a, state_blocks_handle), state_n{}; state_i != state_n; ++state_i, ++num) + for (nano::mdb_iterator> state_i (transaction_a, block_store.state_blocks_handle), state_n{}; state_i != state_n; ++state_i, ++num) { nano::block_w_sideband_v18 block_w_sideband (state_i->second); auto & block (block_w_sideband.block); @@ -580,7 +580,7 @@ void nano::lmdb::store::upgrade_v17_to_v18 (nano::write_transaction const & tran } } - auto count_post (count (transaction_a, state_blocks_handle)); + auto count_post (count (transaction_a, block_store.state_blocks_handle)); release_assert (count_pre == count_post); version.put (transaction_a, 18); @@ -590,38 +590,38 @@ void nano::lmdb::store::upgrade_v17_to_v18 (nano::write_transaction const & tran void nano::lmdb::store::upgrade_v18_to_v19 (nano::write_transaction const & transaction_a) { logger.always_log ("Preparing v18 to v19 database upgrade..."); - auto count_pre (count (transaction_a, state_blocks_handle) + count (transaction_a, send_blocks_handle) + count (transaction_a, receive_blocks_handle) + count (transaction_a, change_blocks_handle) + count (transaction_a, open_blocks_handle)); + auto count_pre (count (transaction_a, block_store.state_blocks_handle) + count (transaction_a, block_store.send_blocks_handle) + count (transaction_a, block_store.receive_blocks_handle) + count (transaction_a, block_store.change_blocks_handle) + count (transaction_a, block_store.open_blocks_handle)); // Combine in order of likeliness of counts std::map legacy_open_receive_change_blocks; - for (auto i (nano::store_iterator> (std::make_unique>> (transaction_a, change_blocks_handle))), n (nano::store_iterator> (nullptr)); i != n; ++i) + for (auto i (nano::store_iterator> (std::make_unique>> (transaction_a, block_store.change_blocks_handle))), n (nano::store_iterator> (nullptr)); i != n; ++i) { nano::block_sideband_v18 const & old_sideband (i->second.sideband); nano::block_sideband new_sideband (old_sideband.account, old_sideband.successor, old_sideband.balance, old_sideband.height, old_sideband.timestamp, nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0); legacy_open_receive_change_blocks[i->first] = { nano::block_w_sideband{ i->second.block, new_sideband } }; } - for (auto i (nano::store_iterator> (std::make_unique>> (transaction_a, open_blocks_handle))), n (nano::store_iterator> (nullptr)); i != n; ++i) + for (auto i (nano::store_iterator> (std::make_unique>> (transaction_a, block_store.open_blocks_handle))), n (nano::store_iterator> (nullptr)); i != n; ++i) { nano::block_sideband_v18 const & old_sideband (i->second.sideband); nano::block_sideband new_sideband (old_sideband.account, old_sideband.successor, old_sideband.balance, old_sideband.height, old_sideband.timestamp, nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0); legacy_open_receive_change_blocks[i->first] = { nano::block_w_sideband{ i->second.block, new_sideband } }; } - for (auto i (nano::store_iterator> (std::make_unique>> (transaction_a, receive_blocks_handle))), n (nano::store_iterator> (nullptr)); i != n; ++i) + for (auto i (nano::store_iterator> (std::make_unique>> (transaction_a, block_store.receive_blocks_handle))), n (nano::store_iterator> (nullptr)); i != n; ++i) { nano::block_sideband_v18 const & old_sideband (i->second.sideband); nano::block_sideband new_sideband (old_sideband.account, old_sideband.successor, old_sideband.balance, old_sideband.height, old_sideband.timestamp, nano::epoch::epoch_0, false, false, false, nano::epoch::epoch_0); legacy_open_receive_change_blocks[i->first] = { nano::block_w_sideband{ i->second.block, new_sideband } }; } - release_assert (!mdb_drop (env.tx (transaction_a), receive_blocks_handle, 1)); - receive_blocks_handle = 0; - release_assert (!mdb_drop (env.tx (transaction_a), open_blocks_handle, 1)); - open_blocks_handle = 0; - release_assert (!mdb_drop (env.tx (transaction_a), change_blocks_handle, 1)); - change_blocks_handle = 0; + release_assert (!mdb_drop (env.tx (transaction_a), block_store.receive_blocks_handle, 1)); + block_store.receive_blocks_handle = 0; + release_assert (!mdb_drop (env.tx (transaction_a), block_store.open_blocks_handle, 1)); + block_store.open_blocks_handle = 0; + release_assert (!mdb_drop (env.tx (transaction_a), block_store.change_blocks_handle, 1)); + block_store.change_blocks_handle = 0; logger.always_log ("Write legacy open/receive/change to new format"); @@ -651,7 +651,7 @@ void nano::lmdb::store::upgrade_v18_to_v19 (nano::write_transaction const & tran { mdb_dbi_open (env.tx (transaction_a), "temp_legacy_send_blocks", MDB_CREATE, &temp_legacy_send_blocks); - for (auto i (nano::store_iterator> (std::make_unique>> (transaction_a, send_blocks_handle))), n (nano::store_iterator> (nullptr)); i != n; ++i) + for (auto i (nano::store_iterator> (std::make_unique>> (transaction_a, block_store.send_blocks_handle))), n (nano::store_iterator> (nullptr)); i != n; ++i) { auto const & block_w_sideband_v18 (i->second); @@ -668,8 +668,8 @@ void nano::lmdb::store::upgrade_v18_to_v19 (nano::write_transaction const & tran } } - release_assert (!mdb_drop (env.tx (transaction_a), send_blocks_handle, 1)); - send_blocks_handle = 0; + release_assert (!mdb_drop (env.tx (transaction_a), block_store.send_blocks_handle, 1)); + block_store.send_blocks_handle = 0; logger.always_log ("Merge legacy open/receive/change with legacy send blocks"); @@ -698,7 +698,7 @@ void nano::lmdb::store::upgrade_v18_to_v19 (nano::write_transaction const & tran auto type_state (nano::block_type::state); mdb_dbi_open (env.tx (transaction_a), "temp_state_blocks", MDB_CREATE, &temp_state_blocks); - for (auto i (nano::store_iterator> (std::make_unique>> (transaction_a, state_blocks_handle))), n (nano::store_iterator> (nullptr)); i != n; ++i) + for (auto i (nano::store_iterator> (std::make_unique>> (transaction_a, block_store.state_blocks_handle))), n (nano::store_iterator> (nullptr)); i != n; ++i) { auto const & block_w_sideband_v18 (i->second); nano::block_sideband_v18 const & old_sideband (block_w_sideband_v18.sideband); @@ -733,18 +733,18 @@ void nano::lmdb::store::upgrade_v18_to_v19 (nano::write_transaction const & tran } } - release_assert (!mdb_drop (env.tx (transaction_a), state_blocks_handle, 1)); - state_blocks_handle = 0; + release_assert (!mdb_drop (env.tx (transaction_a), block_store.state_blocks_handle, 1)); + block_store.state_blocks_handle = 0; logger.always_log ("Merging all legacy blocks with state blocks"); // Merge all legacy blocks with state blocks into the final table nano::mdb_merge_iterator i (transaction_a, temp_legacy_send_open_receive_change_blocks, temp_state_blocks); nano::mdb_merge_iterator n{}; - mdb_dbi_open (env.tx (transaction_a), "blocks", MDB_CREATE, &blocks_handle); + mdb_dbi_open (env.tx (transaction_a), "blocks", MDB_CREATE, &block_store.blocks_handle); for (; i != n; ++i) { - auto s = mdb_put (env.tx (transaction_a), blocks_handle, nano::mdb_val (i->first), nano::mdb_val (i->second), MDB_APPEND); + auto s = mdb_put (env.tx (transaction_a), block_store.blocks_handle, nano::mdb_val (i->first), nano::mdb_val (i->second), MDB_APPEND); release_assert_success (s); } @@ -752,7 +752,7 @@ void nano::lmdb::store::upgrade_v18_to_v19 (nano::write_transaction const & tran mdb_drop (env.tx (transaction_a), temp_legacy_send_open_receive_change_blocks, 1); mdb_drop (env.tx (transaction_a), temp_state_blocks, 1); - auto count_post (count (transaction_a, blocks_handle)); + auto count_post (count (transaction_a, block_store.blocks_handle)); release_assert (count_pre == count_post); MDB_dbi vote{ 0 }; @@ -766,7 +766,7 @@ void nano::lmdb::store::upgrade_v18_to_v19 (nano::write_transaction const & tran void nano::lmdb::store::upgrade_v19_to_v20 (nano::write_transaction const & transaction_a) { logger.always_log ("Preparing v19 to v20 database upgrade..."); - mdb_dbi_open (env.tx (transaction_a), "pruned", MDB_CREATE, &pruned_handle); + mdb_dbi_open (env.tx (transaction_a), "pruned", MDB_CREATE, &pruned_store.pruned_handle); version.put (transaction_a, 20); logger.always_log ("Finished creating new pruned table"); } @@ -774,7 +774,7 @@ void nano::lmdb::store::upgrade_v19_to_v20 (nano::write_transaction const & tran void nano::lmdb::store::upgrade_v20_to_v21 (nano::write_transaction const & transaction_a) { logger.always_log ("Preparing v20 to v21 database upgrade..."); - mdb_dbi_open (env.tx (transaction_a), "final_votes", MDB_CREATE, &final_votes_handle); + mdb_dbi_open (env.tx (transaction_a), "final_votes", MDB_CREATE, &final_vote_store.final_votes_handle); version.put (transaction_a, 21); logger.always_log ("Finished creating new final_vote table"); } @@ -861,30 +861,30 @@ MDB_dbi nano::lmdb::store::table_to_dbi (tables table_a) const switch (table_a) { case tables::frontiers: - return frontiers_handle; + return frontier_store.frontiers_handle; case tables::accounts: - return accounts_handle; + return account_store.accounts_handle; case tables::blocks: - return blocks_handle; + return block_store.blocks_handle; case tables::pending: - return pending_handle; + return pending_store.pending_handle; case tables::unchecked: - return unchecked_handle; + return unchecked_store.unchecked_handle; case tables::online_weight: - return online_weight_handle; + return online_weight_store.online_weight_handle; case tables::meta: - return meta_handle; + return block_store.meta_handle; case tables::peers: - return peers_handle; + return peer_store.peers_handle; case tables::pruned: - return pruned_handle; + return pruned_store.pruned_handle; case tables::confirmation_height: - return confirmation_height_handle; + return confirmation_height_store.confirmation_height_handle; case tables::final_votes: - return final_votes_handle; + return final_vote_store.final_votes_handle; default: release_assert (false); - return peers_handle; + return peer_store.peers_handle; } } @@ -916,7 +916,7 @@ bool nano::lmdb::store::copy_db (boost::filesystem::path const & destination_fil void nano::lmdb::store::rebuild_db (nano::write_transaction const & transaction_a) { // Tables with uint256_union key - std::vector tables = { accounts_handle, blocks_handle, pruned_handle, confirmation_height_handle }; + std::vector tables = { account_store.accounts_handle, block_store.blocks_handle, pruned_store.pruned_handle, confirmation_height_store.confirmation_height_handle }; for (auto const & table : tables) { MDB_dbi temp; @@ -945,20 +945,20 @@ void nano::lmdb::store::rebuild_db (nano::write_transaction const & transaction_ MDB_dbi temp; mdb_dbi_open (env.tx (transaction_a), "temp_table", MDB_CREATE, &temp); // Copy all values to temporary table - for (auto i (nano::store_iterator (std::make_unique> (transaction_a, pending_handle))), n (nano::store_iterator (nullptr)); i != n; ++i) + for (auto i (nano::store_iterator (std::make_unique> (transaction_a, pending_store.pending_handle))), n (nano::store_iterator (nullptr)); i != n; ++i) { auto s = mdb_put (env.tx (transaction_a), temp, nano::mdb_val (i->first), nano::mdb_val (i->second), MDB_APPEND); release_assert_success (s); } - release_assert (count (transaction_a, pending_handle) == count (transaction_a, temp)); - mdb_drop (env.tx (transaction_a), pending_handle, 0); + release_assert (count (transaction_a, pending_store.pending_handle) == count (transaction_a, temp)); + mdb_drop (env.tx (transaction_a), pending_store.pending_handle, 0); // Put values from copy for (auto i (nano::store_iterator (std::make_unique> (transaction_a, temp))), n (nano::store_iterator (nullptr)); i != n; ++i) { - auto s = mdb_put (env.tx (transaction_a), pending_handle, nano::mdb_val (i->first), nano::mdb_val (i->second), MDB_APPEND); + auto s = mdb_put (env.tx (transaction_a), pending_store.pending_handle, nano::mdb_val (i->first), nano::mdb_val (i->second), MDB_APPEND); release_assert_success (s); } - release_assert (count (transaction_a, pending_handle) == count (transaction_a, temp)); + release_assert (count (transaction_a, pending_store.pending_handle) == count (transaction_a, temp)); mdb_drop (env.tx (transaction_a), temp, 1); } } @@ -1014,27 +1014,27 @@ boost::optional nano::lmdb::store::block_raw_get_by_type_v18 (nan { case nano::block_type::send: { - status = mdb_get (env.tx (transaction_a), send_blocks_handle, hash, value); + status = mdb_get (env.tx (transaction_a), block_store.send_blocks_handle, hash, value); break; } case nano::block_type::receive: { - status = mdb_get (env.tx (transaction_a), receive_blocks_handle, hash, value); + status = mdb_get (env.tx (transaction_a), block_store.receive_blocks_handle, hash, value); break; } case nano::block_type::open: { - status = mdb_get (env.tx (transaction_a), open_blocks_handle, hash, value); + status = mdb_get (env.tx (transaction_a), block_store.open_blocks_handle, hash, value); break; } case nano::block_type::change: { - status = mdb_get (env.tx (transaction_a), change_blocks_handle, hash, value); + status = mdb_get (env.tx (transaction_a), block_store.change_blocks_handle, hash, value); break; } case nano::block_type::state: { - status = mdb_get (env.tx (transaction_a), state_blocks_handle, hash, value); + status = mdb_get (env.tx (transaction_a), block_store.state_blocks_handle, hash, value); break; } case nano::block_type::invalid: @@ -1115,34 +1115,34 @@ boost::optional nano::lmdb::store::block_raw_get_by_type_v14 (nan { case nano::block_type::send: { - status = mdb_get (env.tx (transaction_a), send_blocks_handle, hash, value); + status = mdb_get (env.tx (transaction_a), block_store.send_blocks_handle, hash, value); break; } case nano::block_type::receive: { - status = mdb_get (env.tx (transaction_a), receive_blocks_handle, hash, value); + status = mdb_get (env.tx (transaction_a), block_store.receive_blocks_handle, hash, value); break; } case nano::block_type::open: { - status = mdb_get (env.tx (transaction_a), open_blocks_handle, hash, value); + status = mdb_get (env.tx (transaction_a), block_store.open_blocks_handle, hash, value); break; } case nano::block_type::change: { - status = mdb_get (env.tx (transaction_a), change_blocks_handle, hash, value); + status = mdb_get (env.tx (transaction_a), block_store.change_blocks_handle, hash, value); break; } case nano::block_type::state: { - status = mdb_get (env.tx (transaction_a), state_blocks_v1_handle, hash, value); + status = mdb_get (env.tx (transaction_a), block_store.state_blocks_v1_handle, hash, value); if (is_state_v1 != nullptr) { *is_state_v1 = success (status); } if (not_found (status)) { - status = mdb_get (env.tx (transaction_a), state_blocks_v0_handle, hash, value); + status = mdb_get (env.tx (transaction_a), block_store.state_blocks_v0_handle, hash, value); } break; } diff --git a/nano/node/lmdb/lmdb.hpp b/nano/node/lmdb/lmdb.hpp index 93b1c199..670f3777 100644 --- a/nano/node/lmdb/lmdb.hpp +++ b/nano/node/lmdb/lmdb.hpp @@ -94,144 +94,6 @@ namespace lmdb public: nano::mdb_env env; - /** - * Maps head block to owning account - * nano::block_hash -> nano::account - */ - MDB_dbi frontiers_handle{ 0 }; - - /** - * Maps account v1 to account information, head, rep, open, balance, timestamp and block count. (Removed) - * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t - */ - MDB_dbi accounts_v0_handle{ 0 }; - - /** - * Maps account v0 to account information, head, rep, open, balance, timestamp and block count. (Removed) - * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t - */ - MDB_dbi accounts_v1_handle{ 0 }; - - /** - * Maps account v0 to account information, head, rep, open, balance, timestamp, block count and epoch - * nano::account -> nano::block_hash, nano::block_hash, nano::block_hash, nano::amount, uint64_t, uint64_t, nano::epoch - */ - MDB_dbi accounts_handle{ 0 }; - - /** - * Maps block hash to send block. (Removed) - * nano::block_hash -> nano::send_block - */ - MDB_dbi send_blocks_handle{ 0 }; - - /** - * Maps block hash to receive block. (Removed) - * nano::block_hash -> nano::receive_block - */ - MDB_dbi receive_blocks_handle{ 0 }; - - /** - * Maps block hash to open block. (Removed) - * nano::block_hash -> nano::open_block - */ - MDB_dbi open_blocks_handle{ 0 }; - - /** - * Maps block hash to change block. (Removed) - * nano::block_hash -> nano::change_block - */ - MDB_dbi change_blocks_handle{ 0 }; - - /** - * Maps block hash to v0 state block. (Removed) - * nano::block_hash -> nano::state_block - */ - MDB_dbi state_blocks_v0_handle{ 0 }; - - /** - * Maps block hash to v1 state block. (Removed) - * nano::block_hash -> nano::state_block - */ - MDB_dbi state_blocks_v1_handle{ 0 }; - - /** - * Maps block hash to state block. (Removed) - * nano::block_hash -> nano::state_block - */ - MDB_dbi state_blocks_handle{ 0 }; - - /** - * Maps min_version 0 (destination account, pending block) to (source account, amount). (Removed) - * nano::account, nano::block_hash -> nano::account, nano::amount - */ - MDB_dbi pending_v0_handle{ 0 }; - - /** - * Maps min_version 1 (destination account, pending block) to (source account, amount). (Removed) - * nano::account, nano::block_hash -> nano::account, nano::amount - */ - MDB_dbi pending_v1_handle{ 0 }; - - /** - * Maps (destination account, pending block) to (source account, amount, version). (Removed) - * nano::account, nano::block_hash -> nano::account, nano::amount, nano::epoch - */ - MDB_dbi pending_handle{ 0 }; - - /** - * Representative weights. (Removed) - * nano::account -> nano::uint128_t - */ - MDB_dbi representation_handle{ 0 }; - - /** - * Unchecked bootstrap blocks info. - * nano::block_hash -> nano::unchecked_info - */ - MDB_dbi unchecked_handle{ 0 }; - - /** - * Samples of online vote weight - * uint64_t -> nano::amount - */ - MDB_dbi online_weight_handle{ 0 }; - - /** - * Meta information about block store, such as versions. - * nano::uint256_union (arbitrary key) -> blob - */ - MDB_dbi meta_handle{ 0 }; - - /** - * Pruned blocks hashes - * nano::block_hash -> none - */ - MDB_dbi pruned_handle{ 0 }; - - /* - * Endpoints for peers - * nano::endpoint_key -> no_value - */ - MDB_dbi peers_handle{ 0 }; - - /* - * Confirmation height of an account, and the hash for the block at that height - * nano::account -> uint64_t, nano::block_hash - */ - MDB_dbi confirmation_height_handle{ 0 }; - - /* - * Contains block_sideband and block for all block types (legacy send/change/open/receive & state blocks) - * nano::block_hash -> nano::block_sideband, nano::block - */ - MDB_dbi blocks_handle{ 0 }; - - /** - * Maps root to block hash for generated final votes. - * nano::qualified_root -> nano::block_hash - */ - MDB_dbi final_votes_handle{ 0 }; - bool exists (nano::transaction const & transaction_a, tables table_a, nano::mdb_val const & key_a) const; int get (nano::transaction const & transaction_a, tables table_a, nano::mdb_val const & key_a, nano::mdb_val & value_a) const; @@ -317,6 +179,20 @@ namespace lmdb uint64_t after_v0{ 0 }; uint64_t after_v1{ 0 }; }; + + friend class mdb_block_store_supported_version_upgrades_Test; + friend class mdb_block_store_upgrade_v14_v15_Test; + friend class mdb_block_store_upgrade_v15_v16_Test; + friend class mdb_block_store_upgrade_v16_v17_Test; + friend class mdb_block_store_upgrade_v17_v18_Test; + friend class mdb_block_store_upgrade_v18_v19_Test; + friend class mdb_block_store_upgrade_v19_v20_Test; + friend class mdb_block_store_upgrade_v20_v21_Test; + friend class block_store_DISABLED_change_dupsort_Test; + friend void write_sideband_v14 (nano::lmdb::store &, nano::transaction &, nano::block const &, MDB_dbi); + friend void write_sideband_v15 (nano::lmdb::store &, nano::transaction &, nano::block const &); + friend void modify_account_info_to_v14 (nano::lmdb::store &, nano::transaction const &, nano::account const &, uint64_t, nano::block_hash const &); + friend void modify_confirmation_height_to_v15 (nano::lmdb::store &, nano::transaction const &, nano::account const &, uint64_t); }; } diff --git a/nano/node/lmdb/online_weight_store.hpp b/nano/node/lmdb/online_weight_store.hpp index ba463710..88ed78c5 100644 --- a/nano/node/lmdb/online_weight_store.hpp +++ b/nano/node/lmdb/online_weight_store.hpp @@ -2,6 +2,8 @@ #include +#include + namespace nano { namespace lmdb @@ -20,6 +22,12 @@ namespace lmdb nano::store_iterator end () const override; size_t count (nano::transaction const & transaction_a) const override; void clear (nano::write_transaction const & transaction_a) override; + + /** + * Samples of online vote weight + * uint64_t -> nano::amount + */ + MDB_dbi online_weight_handle{ 0 }; }; } } diff --git a/nano/node/lmdb/peer_store.hpp b/nano/node/lmdb/peer_store.hpp index 164cfe65..018b85e9 100644 --- a/nano/node/lmdb/peer_store.hpp +++ b/nano/node/lmdb/peer_store.hpp @@ -2,6 +2,8 @@ #include +#include + namespace nano { namespace lmdb @@ -21,6 +23,12 @@ namespace lmdb void clear (nano::write_transaction const & transaction_a) override; nano::store_iterator begin (nano::transaction const & transaction_a) const override; nano::store_iterator end () const override; + + /* + * Endpoints for peers + * nano::endpoint_key -> no_value + */ + MDB_dbi peers_handle{ 0 }; }; } } diff --git a/nano/node/lmdb/pending_store.hpp b/nano/node/lmdb/pending_store.hpp index e327354e..30896d65 100644 --- a/nano/node/lmdb/pending_store.hpp +++ b/nano/node/lmdb/pending_store.hpp @@ -2,6 +2,8 @@ #include +#include + namespace nano { namespace lmdb @@ -23,6 +25,24 @@ namespace lmdb nano::store_iterator begin (nano::transaction const & transaction_a) const override; nano::store_iterator end () const override; void for_each_par (std::function, nano::store_iterator)> const & action_a) const override; + + /** + * Maps min_version 0 (destination account, pending block) to (source account, amount). (Removed) + * nano::account, nano::block_hash -> nano::account, nano::amount + */ + MDB_dbi pending_v0_handle{ 0 }; + + /** + * Maps min_version 1 (destination account, pending block) to (source account, amount). (Removed) + * nano::account, nano::block_hash -> nano::account, nano::amount + */ + MDB_dbi pending_v1_handle{ 0 }; + + /** + * Maps (destination account, pending block) to (source account, amount, version). (Removed) + * nano::account, nano::block_hash -> nano::account, nano::amount, nano::epoch + */ + MDB_dbi pending_handle{ 0 }; }; } } diff --git a/nano/node/lmdb/pruned_store.hpp b/nano/node/lmdb/pruned_store.hpp index 0c8e05ee..859d017d 100644 --- a/nano/node/lmdb/pruned_store.hpp +++ b/nano/node/lmdb/pruned_store.hpp @@ -2,6 +2,8 @@ #include +#include + namespace nano { namespace lmdb @@ -24,6 +26,12 @@ namespace lmdb nano::store_iterator begin (nano::transaction const & transaction_a) const override; nano::store_iterator end () const override; void for_each_par (std::function, nano::store_iterator)> const & action_a) const override; + + /** + * Pruned blocks hashes + * nano::block_hash -> none + */ + MDB_dbi pruned_handle{ 0 }; }; } } diff --git a/nano/node/lmdb/unchecked_store.hpp b/nano/node/lmdb/unchecked_store.hpp index 62bc2182..5cb40acb 100644 --- a/nano/node/lmdb/unchecked_store.hpp +++ b/nano/node/lmdb/unchecked_store.hpp @@ -2,6 +2,8 @@ #include +#include + namespace nano { namespace lmdb @@ -24,6 +26,12 @@ namespace lmdb nano::store_iterator lower_bound (nano::transaction const & transaction_a, nano::unchecked_key const & key_a) const override; size_t count (nano::transaction const & transaction_a) override; void for_each_par (std::function, nano::store_iterator)> const & action_a) const override; + + /** + * Unchecked bootstrap blocks info. + * nano::block_hash -> nano::unchecked_info + */ + MDB_dbi unchecked_handle{ 0 }; }; } }