diff --git a/nano/core_test/block_store.cpp b/nano/core_test/block_store.cpp index 0de4bad673..573f412eb4 100644 --- a/nano/core_test/block_store.cpp +++ b/nano/core_test/block_store.cpp @@ -27,15 +27,6 @@ using namespace std::chrono_literals; -namespace nano::store::lmdb -{ -void modify_account_info_to_v14 (nano::store::lmdb::component & store, store::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::store::lmdb::component & store, store::transaction const & transaction, nano::account const & account, uint64_t confirmation_height); -void write_sideband_v14 (nano::store::lmdb::component & store_a, store::transaction & transaction_a, nano::block const & block_a, MDB_dbi db_a); -void write_sideband_v15 (nano::store::lmdb::component & store_a, store::transaction & transaction_a, nano::block const & block_a); -void write_block_w_sideband_v18 (nano::store::lmdb::component & store_a, MDB_dbi database, store::write_transaction & transaction_a, nano::block const & block_a); -} - TEST (block_store, construction) { nano::logger_mt logger; @@ -665,13 +656,6 @@ TEST (mdb_block_store, supported_version_upgrades) 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 @@ -1369,810 +1353,6 @@ TEST (block_store, pruned_blocks) namespace nano::store::lmdb { -TEST (mdb_block_store, upgrade_v14_v15) -{ - if (nano::rocksdb_config::using_rocksdb_in_tests ()) - { - // Don't test this in rocksdb mode - GTEST_SKIP (); - } - // Extract confirmation height to a separate database - auto path (nano::unique_path () / "data.ldb"); - nano::block_builder builder; - nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - auto send = builder - .send () - .previous (nano::dev::genesis->hash ()) - .destination (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (nano::dev::genesis->hash ())) - .build (); - auto epoch = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (send->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_1)) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (send->hash ())) - .build (); - auto state_send = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (epoch->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) - .link (nano::dev::genesis_key.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (epoch->hash ())) - .build (); - { - nano::logger_mt logger; - nano::store::lmdb::component store (logger, path, nano::dev::constants); - nano::stats stats; - nano::ledger ledger (store, stats, nano::dev::constants); - auto transaction (store.tx_begin_write ()); - store.initialize (transaction, ledger.cache, nano::dev::constants); - auto account_info = ledger.account_info (transaction, nano::dev::genesis->account ()); - ASSERT_TRUE (account_info); - nano::confirmation_height_info confirmation_height_info; - ASSERT_FALSE (store.confirmation_height.get (transaction, nano::dev::genesis->account (), - confirmation_height_info)); - 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::store::lmdb::db_val (nano::pending_key (nano::dev::genesis_key.pub, send->hash ())), - nano::store::lmdb::db_val ( - nano::store::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::store::lmdb::db_val (nano::pending_key (nano::dev::genesis_key.pub, state_send->hash ())), - nano::store::lmdb::db_val ( - nano::store::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::store::lmdb::db_val value; - ASSERT_FALSE (mdb_get (store.env.tx (transaction), store.account_store.accounts_v1_handle, - nano::store::lmdb::db_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::store::lmdb::db_val (nano::dev::genesis->account ()), value)); - } - - // Now do the upgrade - nano::logger_mt logger; - nano::store::lmdb::component 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::store::lmdb::db_val value; - ASSERT_FALSE (mdb_get (store.env.tx (transaction), store.account_store.accounts_handle, - nano::store::lmdb::db_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.account_store.accounts_v1_handle, - nano::store::lmdb::db_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::store::lmdb::db_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::store::lmdb::db_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 ()) - { - // Don't test this in rocksdb mode - GTEST_SKIP (); - } - auto path (nano::unique_path () / "data.ldb"); - nano::store::lmdb::db_val value; - { - nano::logger_mt logger; - nano::store::lmdb::component store (logger, path, nano::dev::constants); - nano::stats 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.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::store::lmdb::db_val (nano::dev::genesis->account ()), nano::store::lmdb::db_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, 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::store::lmdb::db_val (nano::dev::genesis->account ()), value)); - store.confirmation_height.del (transaction, nano::dev::genesis->account ()); - } - - // Now do the upgrade - nano::logger_mt logger; - nano::store::lmdb::component 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.account_store.representation_handle, - nano::store::lmdb::db_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 (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 - GTEST_SKIP (); - } - nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - nano::block_builder builder; - auto block1 = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (nano::dev::genesis->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis_key.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (nano::dev::genesis->hash ())) - .build (); - auto block2 = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (block1->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio - 1) - .link (nano::dev::genesis_key.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (block1->hash ())) - .build (); - auto block3 = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (block2->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio - 2) - .link (nano::dev::genesis_key.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (block2->hash ())) - .build (); - - auto code = [&block1, &block2, &block3] (auto confirmation_height, nano::block_hash const & expected_cemented_frontier) { - auto path (nano::unique_path () / "data.ldb"); - nano::store::lmdb::db_val value; - { - nano::logger_mt logger; - nano::store::lmdb::component store (logger, path, nano::dev::constants); - nano::stats 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::store::lmdb::component 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 - GTEST_SKIP (); - } - auto path (nano::unique_path () / "data.ldb"); - nano::block_builder builder; - nano::keypair key1; - nano::keypair key2; - nano::keypair key3; - nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - auto send_zero = builder - .send () - .previous (nano::dev::genesis->hash ()) - .destination (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (nano::dev::genesis->hash ())) - .build (); - auto state_receive_zero = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (send_zero->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount) - .link (send_zero->hash ()) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (send_zero->hash ())) - .build (); - auto epoch = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (state_receive_zero->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount) - .link (nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_1)) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (state_receive_zero->hash ())) - .build (); - auto state_send = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (epoch->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (nano::dev::genesis_key.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (epoch->hash ())) - .build (); - auto state_receive = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (state_send->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount) - .link (state_send->hash ()) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (state_send->hash ())) - .build (); - auto state_change = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (state_receive->hash ()) - .representative (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount) - .link (0) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (state_receive->hash ())) - .build (); - auto state_send_change = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (state_change->hash ()) - .representative (key1.pub) - .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (key1.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (state_change->hash ())) - .build (); - auto epoch_first = builder - .state () - .account (key1.pub) - .previous (0) - .representative (0) - .balance (0) - .link (nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_2)) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (key1.pub)) - .build (); - auto state_receive2 = builder - .state () - .account (key1.pub) - .previous (epoch_first->hash ()) - .representative (key1.pub) - .balance (nano::Gxrb_ratio) - .link (state_send_change->hash ()) - .sign (key1.prv, key1.pub) - .work (*pool.generate (epoch_first->hash ())) - .build (); - auto state_send2 = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (state_send_change->hash ()) - .representative (key1.pub) - .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio * 2) - .link (key2.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (state_send_change->hash ())) - .build (); - auto state_open = builder - .state () - .account (key2.pub) - .previous (0) - .representative (key2.pub) - .balance (nano::Gxrb_ratio) - .link (state_send2->hash ()) - .sign (key2.prv, key2.pub) - .work (*pool.generate (key2.pub)) - .build (); - auto state_send_epoch_link = builder - .state () - .account (key2.pub) - .previous (state_open->hash ()) - .representative (key2.pub) - .balance (0) - .link (nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_2)) - .sign (key2.prv, key2.pub) - .work (*pool.generate (state_open->hash ())) - .build (); - { - nano::logger_mt logger; - nano::store::lmdb::component store (logger, path, nano::dev::constants); - auto transaction (store.tx_begin_write ()); - nano::stats 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::store::lmdb::component store (logger, path, nano::dev::constants); - ASSERT_FALSE (store.init_error ()); - auto transaction (store.tx_begin_read ()); - - // Size of state block should equal that set in db (no change) - nano::store::lmdb::db_val value; - ASSERT_FALSE (mdb_get (store.env.tx (transaction), store.block_store.blocks_handle, nano::store::lmdb::db_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)); - - // 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)); -} - -TEST (mdb_block_store, upgrade_v18_v19) -{ - if (nano::rocksdb_config::using_rocksdb_in_tests ()) - { - // Don't test this in rocksdb mode - GTEST_SKIP (); - } - auto path (nano::unique_path () / "data.ldb"); - nano::keypair key1; - nano::block_builder builder; - nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits::max () }; - auto send = builder - .send () - .previous (nano::dev::genesis->hash ()) - .destination (nano::dev::genesis_key.pub) - .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (nano::dev::genesis->hash ())) - .build (); - auto receive = builder - .receive () - .previous (send->hash ()) - .source (send->hash ()) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (send->hash ())) - .build (); - auto change = builder - .change () - .previous (receive->hash ()) - .representative (0) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (receive->hash ())) - .build (); - auto state_epoch = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (change->hash ()) - .representative (0) - .balance (nano::dev::constants.genesis_amount) - .link (nano::dev::network_params.ledger.epochs.link (nano::epoch::epoch_1)) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (change->hash ())) - .build (); - auto state_send = builder - .state () - .account (nano::dev::genesis_key.pub) - .previous (state_epoch->hash ()) - .representative (0) - .balance (nano::dev::constants.genesis_amount - nano::Gxrb_ratio) - .link (key1.pub) - .sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub) - .work (*pool.generate (state_epoch->hash ())) - .build (); - auto state_open = builder - .state () - .account (key1.pub) - .previous (0) - .representative (0) - .balance (nano::Gxrb_ratio) - .link (state_send->hash ()) - .sign (key1.prv, key1.pub) - .work (*pool.generate (key1.pub)) - .build (); - { - nano::logger_mt logger; - nano::store::lmdb::component store (logger, path, nano::dev::constants); - nano::stats 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.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::store::lmdb::component 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 - GTEST_SKIP (); - } - auto path (nano::unique_path () / "data.ldb"); - nano::logger_mt logger; - nano::stats stats; - { - nano::store::lmdb::component 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::store::lmdb::component store (logger, path, nano::dev::constants); - 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 - GTEST_SKIP (); - } - auto path (nano::unique_path () / "data.ldb"); - nano::logger_mt logger; - nano::stats stats; - { - nano::store::lmdb::component 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::store::lmdb::component store (logger, path, nano::dev::constants); - 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)); -} - TEST (mdb_block_store, upgrade_v21_v22) { if (nano::rocksdb_config::using_rocksdb_in_tests ()) @@ -2284,7 +1464,7 @@ TEST (mdb_block_store, upgrade_backup) nano::logger_mt logger; nano::store::lmdb::component store (logger, path, nano::dev::constants); auto transaction (store.tx_begin_write ()); - store.version.put (transaction, 14); + store.version.put (transaction, store.version_minimum); } ASSERT_EQ (get_backup_path ().string (), dir.string ()); @@ -2496,76 +1676,3 @@ TEST (rocksdb_block_store, tombstone_count) ASSERT_TIMELY (5s, store->tombstone_map.at (nano::tables::accounts).num_since_last_flush.load () == 1); } } - -namespace nano::store::lmdb -{ -void write_sideband_v14 (nano::store::lmdb::component & store_a, store::transaction & transaction_a, nano::block const & block_a, MDB_dbi db_a) -{ - auto block = store_a.block.get (transaction_a, block_a.hash ()); - ASSERT_NE (block, nullptr); - - nano::store::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::store::lmdb::db_val (block_a.hash ()), &val, 0)); -} - -void write_sideband_v15 (nano::store::lmdb::component & store_a, store::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::store::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::store::lmdb::db_val (block_a.hash ()), &val, 0)); -} - -void write_block_w_sideband_v18 (nano::store::lmdb::component & store_a, MDB_dbi database, store::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::store::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::store::lmdb::db_val (block_a.hash ()), &val, 0)); - store_a.del (transaction_a, nano::tables::blocks, nano::store::lmdb::db_val (block_a.hash ())); -} - -void modify_account_info_to_v14 (nano::store::lmdb::component & store, store::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::store::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::store::lmdb::db_val (account), nano::store::lmdb::db_val (account_info_v14), 0)); - ASSERT_EQ (status, 0); -} - -void modify_confirmation_height_to_v15 (nano::store::lmdb::component & store, store::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::store::lmdb::db_val (account), nano::store::lmdb::db_val (confirmation_height), 0)); - ASSERT_EQ (status, 0); -} -} diff --git a/nano/store/component.hpp b/nano/store/component.hpp index 14bd7f21f2..5b1d4e44ac 100644 --- a/nano/store/component.hpp +++ b/nano/store/component.hpp @@ -68,7 +68,7 @@ namespace store store::frontier & frontier; store::account & account; store::pending & pending; - static int constexpr version_minimum{ 14 }; + static int constexpr version_minimum{ 21 }; static int constexpr version_current{ 22 }; public: diff --git a/nano/store/db_val.hpp b/nano/store/db_val.hpp index 182a8a18da..9a52ffb0ac 100644 --- a/nano/store/db_val.hpp +++ b/nano/store/db_val.hpp @@ -57,23 +57,12 @@ class db_val { } - db_val (account_info_v14 const & val_a) : - db_val (val_a.db_size (), const_cast (&val_a)) - { - } - db_val (nano::pending_info const & val_a) : db_val (val_a.db_size (), const_cast (&val_a)) { static_assert (std::is_standard_layout::value, "Standard layout is required"); } - db_val (pending_info_v14 const & val_a) : - db_val (val_a.db_size (), const_cast (&val_a)) - { - static_assert (std::is_standard_layout::value, "Standard layout is required"); - } - db_val (nano::pending_key const & val_a) : db_val (sizeof (val_a), const_cast (&val_a)) { @@ -131,14 +120,6 @@ class db_val return result; } - explicit operator account_info_v14 () const - { - account_info_v14 result; - debug_assert (size () == result.db_size ()); - std::copy (reinterpret_cast (data ()), reinterpret_cast (data ()) + result.db_size (), reinterpret_cast (&result)); - return result; - } - explicit operator block_info () const { nano::block_info result; @@ -148,14 +129,6 @@ class db_val return result; } - explicit operator pending_info_v14 () const - { - pending_info_v14 result; - debug_assert (size () == result.db_size ()); - std::copy (reinterpret_cast (data ()), reinterpret_cast (data ()) + result.db_size (), reinterpret_cast (&result)); - return result; - } - explicit operator nano::pending_info () const { nano::pending_info result; @@ -235,21 +208,6 @@ class db_val return result; } - template - explicit operator block_w_sideband_v18 () const - { - nano::bufferstream stream (reinterpret_cast (data ()), size ()); - auto error (false); - block_w_sideband_v18 block_w_sideband; - block_w_sideband.block = std::make_shared (error, stream); - release_assert (!error); - - error = block_w_sideband.sideband.deserialize (stream, block_w_sideband.block->type ()); - release_assert (!error); - - return block_w_sideband; - } - explicit operator block_w_sideband () const { nano::bufferstream stream (reinterpret_cast (data ()), size ()); @@ -261,21 +219,6 @@ class db_val return block_w_sideband; } - explicit operator state_block_w_sideband_v14 () const - { - nano::bufferstream stream (reinterpret_cast (data ()), size ()); - auto error (false); - state_block_w_sideband_v14 block_w_sideband; - block_w_sideband.state_block = std::make_shared (error, stream); - debug_assert (!error); - - block_w_sideband.sideband.type = nano::block_type::state; - error = block_w_sideband.sideband.deserialize (stream); - debug_assert (!error); - - return block_w_sideband; - } - explicit operator std::nullptr_t () const { return nullptr; diff --git a/nano/store/lmdb/lmdb.cpp b/nano/store/lmdb/lmdb.cpp index a32be57efe..310ef25c48 100644 --- a/nano/store/lmdb/lmdb.cpp +++ b/nano/store/lmdb/lmdb.cpp @@ -235,48 +235,13 @@ bool nano::store::lmdb::component::do_upgrades (store::write_transaction & trans { auto error (false); auto version_l = version.get (transaction_a); + if (version_l < version_minimum) + { + logger.always_log (boost::str (boost::format ("The version of the ledger (%1%) is lower than the minimum (%2%) which is supported for upgrades. Either upgrade to a v19, v20 or v21 node first or delete the ledger.") % version_l % version_minimum)); + return true; + } switch (version_l) { - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - logger.always_log (boost::str (boost::format ("The version of the ledger (%1%) is lower than the minimum (%2%) which is supported for upgrades. Either upgrade to a v19, v20 or v21 node first or delete the ledger.") % version_l % version_minimum)); - error = true; - break; - case 14: - upgrade_v14_to_v15 (transaction_a); - [[fallthrough]]; - // Upgrades to version 16, 17 & 18 are all part of the v21 node release - case 15: - upgrade_v15_to_v16 (transaction_a); - [[fallthrough]]; - case 16: - upgrade_v16_to_v17 (transaction_a); - [[fallthrough]]; - case 17: - upgrade_v17_to_v18 (transaction_a, constants); - [[fallthrough]]; - // Upgrades to version 19 & 20 are both part of the v22 node release - case 18: - upgrade_v18_to_v19 (transaction_a); - needs_vacuuming = true; - [[fallthrough]]; - case 19: - upgrade_v19_to_v20 (transaction_a); - [[fallthrough]]; - case 20: - upgrade_v20_to_v21 (transaction_a); - [[fallthrough]]; case 21: upgrade_v21_to_v22 (transaction_a); [[fallthrough]]; @@ -290,471 +255,6 @@ bool nano::store::lmdb::component::do_upgrades (store::write_transaction & trans return error; } -void nano::store::lmdb::component::upgrade_v14_to_v15 (store::write_transaction & transaction_a) -{ - logger.always_log ("Preparing v14 to v15 database upgrade..."); - - std::vector> account_infos; - 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::store::lmdb::merge_iterator i_account (transaction_a, account_store.accounts_v0_handle, account_store.accounts_v1_handle); - nano::store::lmdb::merge_iterator n_account{}; - for (; i_account != n_account; ++i_account) - { - nano::account account (i_account->first); - nano::store::account_info_v14 account_info_v14 (i_account->second); - - // Upgrade rep block to representative account - auto rep_block = block_get_v14 (transaction_a, account_info_v14.rep_block); - 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_store.confirmation_height_handle, nano::store::lmdb::db_val (account), nano::store::lmdb::db_val (account_info_v14.confirmation_height), MDB_APPEND); - i_account.from_first_database ? ++account_counters.after_v0 : ++account_counters.after_v1; - } - - logger.always_log ("Finished extracting confirmation height to its own database"); - - debug_assert (account_counters.are_equal ()); - // No longer need accounts_v1, keep v0 but clear it - 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), account_store.accounts_handle, nano::store::lmdb::db_val (account_account_info_pair.first), nano::store::lmdb::db_val (account_info), MDB_APPEND); - } - - logger.always_log ("Epoch merge upgrade: Finished accounts, now doing state blocks"); - - account_infos.clear (); - - // Have to create a new database as we are iterating over the existing ones and want to use MDB_APPEND for quick insertion - 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, block_store.state_blocks_v0_handle), count (transaction_a, block_store.state_blocks_v1_handle)); - - nano::store::lmdb::merge_iterator i_state (transaction_a, block_store.state_blocks_v0_handle, block_store.state_blocks_v1_handle); - nano::store::lmdb::merge_iterator n_state{}; - auto num = 0u; - for (; i_state != n_state; ++i_state, ++num) - { - nano::block_hash hash (i_state->first); - nano::store::state_block_w_sideband_v14 state_block_w_sideband_v14 (i_state->second); - auto & sideband_v14 = state_block_w_sideband_v14.sideband; - - nano::store::block_sideband_v18 sideband (sideband_v14.account, sideband_v14.successor, sideband_v14.balance, sideband_v14.height, sideband_v14.timestamp, i_state.from_first_database ? nano::epoch::epoch_0 : nano::epoch::epoch_1, false, false, false); - - // Write these out - std::vector data; - { - nano::vectorstream stream (data); - state_block_w_sideband_v14.state_block->serialize (stream); - sideband.serialize (stream, sideband_v14.type); - } - - nano::store::lmdb::db_val value{ data.size (), (void *)data.data () }; - auto s = mdb_put (env.tx (transaction_a), state_blocks_new, nano::store::lmdb::db_val (hash), value, MDB_APPEND); - release_assert_success (s); - - // Every so often output to the log to indicate progress - constexpr auto output_cutoff = 1000000; - if (num % output_cutoff == 0 && num != 0) - { - logger.always_log (boost::str (boost::format ("Database epoch merge upgrade %1% million state blocks upgraded") % (num / output_cutoff))); - } - i_state.from_first_database ? ++state_counters.after_v0 : ++state_counters.after_v1; - } - - debug_assert (state_counters.are_equal ()); - logger.always_log ("Epoch merge upgrade: Finished state blocks, now doing pending blocks"); - - block_store.state_blocks_handle = state_blocks_new; - - // No longer need states v0/v1 databases - 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); - - block_store.state_blocks_v0_handle = block_store.state_blocks_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::store::lmdb::merge_iterator i_pending (transaction_a, pending_store.pending_v0_handle, pending_store.pending_v1_handle); - nano::store::lmdb::merge_iterator n_pending{}; - for (; i_pending != n_pending; ++i_pending) - { - nano::store::pending_info_v14 info (i_pending->second); - pending_infos.emplace_back (nano::pending_key (i_pending->first), nano::pending_info{ info.source, info.amount, i_pending.from_first_database ? nano::epoch::epoch_0 : nano::epoch::epoch_1 }); - i_pending.from_first_database ? ++pending_counters.after_v0 : ++pending_counters.after_v1; - } - - debug_assert (pending_counters.are_equal ()); - - // No longer need the pending v1 table - 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_store.pending_handle, nano::store::lmdb::db_val (pending_key_pending_info_pair.first), nano::store::lmdb::db_val (pending_key_pending_info_pair.second), MDB_APPEND); - } - - version.put (transaction_a, 15); - logger.always_log ("Finished epoch merge upgrade"); -} - -void nano::store::lmdb::component::upgrade_v15_to_v16 (store::write_transaction const & transaction_a) -{ - // Representation table is no longer used - debug_assert (account_store.representation_handle != 0); - if (account_store.representation_handle != 0) - { - auto status (mdb_drop (env.tx (transaction_a), account_store.representation_handle, 1)); - release_assert (status == MDB_SUCCESS); - account_store.representation_handle = 0; - } - version.put (transaction_a, 16); -} - -void nano::store::lmdb::component::upgrade_v16_to_v17 (store::write_transaction const & transaction_a) -{ - logger.always_log ("Preparing v16 to v17 database upgrade..."); - - auto account_info_i = account.begin (transaction_a); - auto account_info_n = account.end (); - - // Set the confirmed frontier for each account in the confirmation height table - std::vector> confirmation_height_infos; - auto num = 0u; - for (nano::store::lmdb::iterator i (transaction_a, confirmation_height_store.confirmation_height_handle), n (nano::store::lmdb::iterator{}); i != n; ++i, ++account_info_i, ++num) - { - nano::account account (i->first); - uint64_t confirmation_height (i->second); - - // Check account hashes matches both the accounts table and confirmation height table - debug_assert (account == account_info_i->first); - - auto const & account_info = account_info_i->second; - - if (confirmation_height == 0) - { - confirmation_height_infos.emplace_back (account, confirmation_height_info{ 0, nano::block_hash (0) }); - } - else - { - if (account_info_i->second.block_count / 2 >= confirmation_height) - { - // The confirmation height of the account is closer to the bottom of the chain, so start there and work up - auto block = block_get_v18 (transaction_a, account_info.open_block); - debug_assert (block); - auto height = 1; - - while (height != confirmation_height) - { - block = block_get_v18 (transaction_a, block->sideband ().successor); - debug_assert (block); - ++height; - } - - debug_assert (block->sideband ().height == confirmation_height); - confirmation_height_infos.emplace_back (account, confirmation_height_info{ confirmation_height, block->hash () }); - } - else - { - // The confirmation height of the account is closer to the top of the chain so start there and work down - auto block = block_get_v18 (transaction_a, account_info.head); - auto height = block->sideband ().height; - while (height != confirmation_height) - { - block = block_get_v18 (transaction_a, block->previous ()); - debug_assert (block); - --height; - } - confirmation_height_infos.emplace_back (account, confirmation_height_info{ confirmation_height, block->hash () }); - } - } - - // Every so often output to the log to indicate progress (every 200k accounts) - constexpr auto output_cutoff = 200000; - if (num % output_cutoff == 0 && num != 0) - { - logger.always_log (boost::str (boost::format ("Confirmation height frontier set for %1%00k accounts") % ((num / output_cutoff) * 2))); - } - } - - // Clear it then append - 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_store.confirmation_height_handle, nano::store::lmdb::db_val (confirmation_height_info_pair.first), nano::store::lmdb::db_val (confirmation_height_info_pair.second), MDB_APPEND); - } - - version.put (transaction_a, 17); - logger.always_log ("Finished upgrading confirmation height frontiers"); -} - -void nano::store::lmdb::component::upgrade_v17_to_v18 (store::write_transaction const & transaction_a, nano::ledger_constants & constants) -{ - logger.always_log ("Preparing v17 to v18 database upgrade..."); - - auto count_pre (count (transaction_a, block_store.state_blocks_handle)); - - auto num = 0u; - for (nano::store::lmdb::iterator> state_i (transaction_a, block_store.state_blocks_handle), state_n{}; state_i != state_n; ++state_i, ++num) - { - nano::store::block_w_sideband_v18 block_w_sideband (state_i->second); - auto & block (block_w_sideband.block); - auto & sideband (block_w_sideband.sideband); - - bool is_send{ false }; - bool is_receive{ false }; - bool is_epoch{ false }; - - nano::amount prev_balance (0); - if (!block->hashables.previous.is_zero ()) - { - auto prev = block_get_v18 (transaction_a, block->hashables.previous); - prev_balance = nano::ledger::balance (*prev); - } - if (block->hashables.balance == prev_balance && constants.epochs.is_epoch_link (block->hashables.link)) - { - is_epoch = true; - } - else if (block->hashables.balance < prev_balance) - { - is_send = true; - } - else if (!block->hashables.link.is_zero ()) - { - is_receive = true; - } - - nano::store::block_sideband_v18 new_sideband (sideband.account, sideband.successor, sideband.balance, sideband.height, sideband.timestamp, sideband.details.epoch, is_send, is_receive, is_epoch); - // Write these out - std::vector data; - { - nano::vectorstream stream (data); - block->serialize (stream); - new_sideband.serialize (stream, block->type ()); - } - nano::store::lmdb::db_val value{ data.size (), (void *)data.data () }; - auto s = mdb_cursor_put (state_i.cursor, state_i->first, value, MDB_CURRENT); - release_assert_success (s); - - // Every so often output to the log to indicate progress - constexpr auto output_cutoff = 1000000; - if (num > 0 && num % output_cutoff == 0) - { - logger.always_log (boost::str (boost::format ("Database sideband upgrade %1% million state blocks upgraded (out of %2%)") % (num / output_cutoff) % count_pre)); - } - } - - auto count_post (count (transaction_a, block_store.state_blocks_handle)); - release_assert (count_pre == count_post); - - version.put (transaction_a, 18); - logger.always_log ("Finished upgrading the sideband"); -} - -void nano::store::lmdb::component::upgrade_v18_to_v19 (store::write_transaction const & transaction_a) -{ - logger.always_log ("Preparing v18 to v19 database upgrade..."); - 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 (store::iterator> (std::make_unique>> (transaction_a, block_store.change_blocks_handle))), n (store::iterator> (nullptr)); i != n; ++i) - { - nano::store::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::store::block_w_sideband{ i->second.block, new_sideband } }; - } - - for (auto i (store::iterator> (std::make_unique>> (transaction_a, block_store.open_blocks_handle))), n (store::iterator> (nullptr)); i != n; ++i) - { - nano::store::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::store::block_w_sideband{ i->second.block, new_sideband } }; - } - - for (auto i (store::iterator> (std::make_unique>> (transaction_a, block_store.receive_blocks_handle))), n (store::iterator> (nullptr)); i != n; ++i) - { - nano::store::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::store::block_w_sideband{ i->second.block, new_sideband } }; - } - - 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"); - - MDB_dbi temp_legacy_open_receive_change_blocks; - { - mdb_dbi_open (env.tx (transaction_a), "temp_legacy_open_receive_change_blocks", MDB_CREATE, &temp_legacy_open_receive_change_blocks); - - for (auto const & legacy_block : legacy_open_receive_change_blocks) - { - std::vector data; - { - nano::vectorstream stream (data); - nano::serialize_block (stream, *legacy_block.second.block); - legacy_block.second.sideband.serialize (stream, legacy_block.second.block->type ()); - } - - nano::store::lmdb::db_val value{ data.size (), (void *)data.data () }; - auto s = mdb_put (env.tx (transaction_a), temp_legacy_open_receive_change_blocks, nano::store::lmdb::db_val (legacy_block.first), value, MDB_APPEND); - release_assert_success (s); - } - } - - logger.always_log ("Write legacy send to new format"); - - // Write send blocks to a new table (this was not done in memory as it would push us above memory requirements) - MDB_dbi temp_legacy_send_blocks; - { - mdb_dbi_open (env.tx (transaction_a), "temp_legacy_send_blocks", MDB_CREATE, &temp_legacy_send_blocks); - - for (auto i (store::iterator> (std::make_unique>> (transaction_a, block_store.send_blocks_handle))), n (store::iterator> (nullptr)); i != n; ++i) - { - auto const & block_w_sideband_v18 (i->second); - - std::vector data; - { - nano::vectorstream stream (data); - nano::serialize_block (stream, *block_w_sideband_v18.block); - block_w_sideband_v18.sideband.serialize (stream, nano::block_type::send); // Equal to new version for legacy blocks - } - - nano::store::lmdb::db_val value{ data.size (), (void *)data.data () }; - auto s = mdb_put (env.tx (transaction_a), temp_legacy_send_blocks, nano::store::lmdb::db_val (i->first), value, MDB_APPEND); - release_assert_success (s); - } - } - - 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"); - - MDB_dbi temp_legacy_send_open_receive_change_blocks; - { - mdb_dbi_open (env.tx (transaction_a), "temp_legacy_send_open_receive_change_blocks", MDB_CREATE, &temp_legacy_send_open_receive_change_blocks); - - nano::store::lmdb::merge_iterator i (transaction_a, temp_legacy_open_receive_change_blocks, temp_legacy_send_blocks); - nano::store::lmdb::merge_iterator n{}; - for (; i != n; ++i) - { - auto s = mdb_put (env.tx (transaction_a), temp_legacy_send_open_receive_change_blocks, nano::store::lmdb::db_val (i->first), nano::store::lmdb::db_val (i->second), MDB_APPEND); - release_assert_success (s); - } - - // Delete tables - mdb_drop (env.tx (transaction_a), temp_legacy_send_blocks, 1); - mdb_drop (env.tx (transaction_a), temp_legacy_open_receive_change_blocks, 1); - } - - logger.always_log ("Write state blocks to new format"); - - // Write state blocks to a new table (this was not done in memory as it would push us above memory requirements) - MDB_dbi temp_state_blocks; - { - 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 (store::iterator> (std::make_unique>> (transaction_a, block_store.state_blocks_handle))), n (store::iterator> (nullptr)); i != n; ++i) - { - auto const & block_w_sideband_v18 (i->second); - nano::store::block_sideband_v18 const & old_sideband (block_w_sideband_v18.sideband); - nano::epoch source_epoch (nano::epoch::epoch_0); - // Source block v18 epoch - if (old_sideband.details.is_receive) - { - auto db_val (block_raw_get_by_type_v18 (transaction_a, block_w_sideband_v18.block->link ().as_block_hash (), type_state)); - if (db_val.is_initialized ()) - { - nano::bufferstream stream (reinterpret_cast (db_val.get ().data ()), db_val.get ().size ()); - auto source_block (nano::deserialize_block (stream, type_state)); - release_assert (source_block != nullptr); - nano::store::block_sideband_v18 source_sideband; - auto error (source_sideband.deserialize (stream, type_state)); - release_assert (!error); - source_epoch = source_sideband.details.epoch; - } - } - nano::block_sideband new_sideband (old_sideband.account, old_sideband.successor, old_sideband.balance, old_sideband.height, old_sideband.timestamp, old_sideband.details.epoch, old_sideband.details.is_send, old_sideband.details.is_receive, old_sideband.details.is_epoch, source_epoch); - - std::vector data; - { - nano::vectorstream stream (data); - nano::serialize_block (stream, *block_w_sideband_v18.block); - new_sideband.serialize (stream, nano::block_type::state); - } - - nano::store::lmdb::db_val value{ data.size (), (void *)data.data () }; - auto s = mdb_put (env.tx (transaction_a), temp_state_blocks, nano::store::lmdb::db_val (i->first), value, MDB_APPEND); - release_assert_success (s); - } - } - - 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::store::lmdb::merge_iterator i (transaction_a, temp_legacy_send_open_receive_change_blocks, temp_state_blocks); - nano::store::lmdb::merge_iterator n{}; - 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), block_store.blocks_handle, nano::store::lmdb::db_val (i->first), nano::store::lmdb::db_val (i->second), MDB_APPEND); - release_assert_success (s); - } - - // Delete tables - 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, block_store.blocks_handle)); - release_assert (count_pre == count_post); - - MDB_dbi vote{ 0 }; - release_assert (!mdb_dbi_open (env.tx (transaction_a), "vote", MDB_CREATE, &vote)); - release_assert (!mdb_drop (env.tx (transaction_a), vote, 1)); - - version.put (transaction_a, 19); - logger.always_log ("Finished upgrading all blocks to new blocks database"); -} - -void nano::store::lmdb::component::upgrade_v19_to_v20 (store::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_store.pruned_handle); - version.put (transaction_a, 20); - logger.always_log ("Finished creating new pruned table"); -} - -void nano::store::lmdb::component::upgrade_v20_to_v21 (store::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_vote_store.final_votes_handle); - version.put (transaction_a, 21); - logger.always_log ("Finished creating new final_vote table"); -} - void nano::store::lmdb::component::upgrade_v21_to_v22 (store::write_transaction const & transaction_a) { logger.always_log ("Preparing v21 to v22 database upgrade..."); @@ -952,213 +452,6 @@ bool nano::store::lmdb::component::init_error () const return error; } -std::shared_ptr nano::store::lmdb::component::block_get_v18 (store::transaction const & transaction_a, nano::block_hash const & hash_a) const -{ - nano::block_type type; - auto value (block_raw_get_v18 (transaction_a, hash_a, type)); - std::shared_ptr result; - if (value.size () != 0) - { - nano::bufferstream stream (reinterpret_cast (value.data ()), value.size ()); - result = nano::deserialize_block (stream, type); - release_assert (result != nullptr); - nano::store::block_sideband_v18 sideband; - auto error = (sideband.deserialize (stream, type)); - release_assert (!error); - result->sideband_set (nano::block_sideband (sideband.account, sideband.successor, sideband.balance, sideband.height, sideband.timestamp, sideband.details.epoch, sideband.details.is_send, sideband.details.is_receive, sideband.details.is_epoch, nano::epoch::epoch_0)); - } - return result; -} - -nano::store::lmdb::db_val nano::store::lmdb::component::block_raw_get_v18 (store::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a) const -{ - nano::store::lmdb::db_val result; - // Table lookups are ordered by match probability - nano::block_type block_types[]{ nano::block_type::state, nano::block_type::send, nano::block_type::receive, nano::block_type::open, nano::block_type::change }; - for (auto current_type : block_types) - { - auto db_val (block_raw_get_by_type_v18 (transaction_a, hash_a, current_type)); - if (db_val.is_initialized ()) - { - type_a = current_type; - result = db_val.get (); - break; - } - } - - return result; -} - -boost::optional nano::store::lmdb::component::block_raw_get_by_type_v18 (store::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a) const -{ - nano::store::lmdb::db_val value; - nano::store::lmdb::db_val hash (hash_a); - int status = status_code_not_found (); - switch (type_a) - { - case nano::block_type::send: - { - 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), block_store.receive_blocks_handle, hash, value); - break; - } - case nano::block_type::open: - { - 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), block_store.change_blocks_handle, hash, value); - break; - } - case nano::block_type::state: - { - status = mdb_get (env.tx (transaction_a), block_store.state_blocks_handle, hash, value); - break; - } - case nano::block_type::invalid: - case nano::block_type::not_a_block: - { - break; - } - } - - release_assert (success (status) || not_found (status)); - boost::optional result; - if (success (status)) - { - result = value; - } - return result; -} - -// All the v14 functions below are only needed during upgrades -std::size_t nano::store::lmdb::component::block_successor_offset_v14 (store::transaction const & transaction_a, std::size_t entry_size_a, nano::block_type type_a) const -{ - return entry_size_a - nano::store::block_sideband_v14::size (type_a); -} - -nano::block_hash nano::store::lmdb::component::block_successor_v14 (store::transaction const & transaction_a, nano::block_hash const & hash_a) const -{ - nano::block_type type; - auto value (block_raw_get_v14 (transaction_a, hash_a, type)); - nano::block_hash result; - if (value.size () != 0) - { - debug_assert (value.size () >= result.bytes.size ()); - nano::bufferstream stream (reinterpret_cast (value.data ()) + block_successor_offset_v14 (transaction_a, value.size (), type), result.bytes.size ()); - auto error (nano::try_read (stream, result.bytes)); - (void)error; - debug_assert (!error); - } - else - { - result.clear (); - } - return result; -} - -nano::store::lmdb::db_val nano::store::lmdb::component::block_raw_get_v14 (store::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a, bool * is_state_v1) const -{ - nano::store::lmdb::db_val result; - // Table lookups are ordered by match probability - nano::block_type block_types[]{ nano::block_type::state, nano::block_type::send, nano::block_type::receive, nano::block_type::open, nano::block_type::change }; - for (auto current_type : block_types) - { - auto db_val (block_raw_get_by_type_v14 (transaction_a, hash_a, current_type, is_state_v1)); - if (db_val.is_initialized ()) - { - type_a = current_type; - result = db_val.get (); - break; - } - } - - return result; -} - -boost::optional nano::store::lmdb::component::block_raw_get_by_type_v14 (store::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a, bool * is_state_v1) const -{ - nano::store::lmdb::db_val value; - nano::store::lmdb::db_val hash (hash_a); - int status = status_code_not_found (); - switch (type_a) - { - case nano::block_type::send: - { - 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), block_store.receive_blocks_handle, hash, value); - break; - } - case nano::block_type::open: - { - 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), block_store.change_blocks_handle, hash, value); - break; - } - case nano::block_type::state: - { - 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), block_store.state_blocks_v0_handle, hash, value); - } - break; - } - case nano::block_type::invalid: - case nano::block_type::not_a_block: - { - break; - } - } - - release_assert (success (status) || not_found (status)); - boost::optional result; - if (success (status)) - { - result = value; - } - return result; -} - -std::shared_ptr nano::store::lmdb::component::block_get_v14 (store::transaction const & transaction_a, nano::block_hash const & hash_a, nano::store::block_sideband_v14 * sideband_a, bool * is_state_v1) const -{ - nano::block_type type; - auto value (block_raw_get_v14 (transaction_a, hash_a, type, is_state_v1)); - std::shared_ptr result; - if (value.size () != 0) - { - nano::bufferstream stream (reinterpret_cast (value.data ()), value.size ()); - result = nano::deserialize_block (stream, type); - debug_assert (result != nullptr); - if (sideband_a) - { - sideband_a->type = type; - bool error = sideband_a->deserialize (stream); - (void)error; - debug_assert (!error); - } - } - return result; -} - nano::store::lmdb::component::upgrade_counters::upgrade_counters (uint64_t count_before_v0, uint64_t count_before_v1) : before_v0 (count_before_v0), before_v1 (count_before_v1) diff --git a/nano/store/lmdb/lmdb.hpp b/nano/store/lmdb/lmdb.hpp index 2aec49e264..6e935ed5fc 100644 --- a/nano/store/lmdb/lmdb.hpp +++ b/nano/store/lmdb/lmdb.hpp @@ -119,29 +119,10 @@ class component : public nano::store::component uint64_t count (store::transaction const &, MDB_dbi) const; std::string error_string (int status) const override; - // These are only use in the upgrade process. - std::shared_ptr block_get_v14 (store::transaction const & transaction_a, nano::block_hash const & hash_a, nano::store::block_sideband_v14 * sideband_a = nullptr, bool * is_state_v1 = nullptr) const; - std::size_t block_successor_offset_v14 (store::transaction const & transaction_a, std::size_t entry_size_a, nano::block_type type_a) const; - nano::block_hash block_successor_v14 (store::transaction const & transaction_a, nano::block_hash const & hash_a) const; - nano::store::lmdb::db_val block_raw_get_v14 (store::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a, bool * is_state_v1 = nullptr) const; - boost::optional block_raw_get_by_type_v14 (store::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a, bool * is_state_v1) const; - private: bool do_upgrades (store::write_transaction &, nano::ledger_constants & constants, bool &); - void upgrade_v14_to_v15 (store::write_transaction &); - void upgrade_v15_to_v16 (store::write_transaction const &); - void upgrade_v16_to_v17 (store::write_transaction const &); - void upgrade_v17_to_v18 (store::write_transaction const &, nano::ledger_constants & constants); - void upgrade_v18_to_v19 (store::write_transaction const &); - void upgrade_v19_to_v20 (store::write_transaction const &); - void upgrade_v20_to_v21 (store::write_transaction const &); void upgrade_v21_to_v22 (store::write_transaction const &); - std::shared_ptr block_get_v18 (store::transaction const & transaction_a, nano::block_hash const & hash_a) const; - nano::store::lmdb::db_val block_raw_get_v18 (store::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a) const; - boost::optional block_raw_get_by_type_v18 (store::transaction const & transaction_a, nano::block_hash const & hash_a, nano::block_type & type_a) const; - nano::uint128_t block_balance_v18 (store::transaction const & transaction_a, nano::block_hash const & hash_a) const; - void open_databases (bool &, store::transaction const &, unsigned); int drop (store::write_transaction const & transaction_a, tables table_a) override; @@ -181,18 +162,7 @@ class component : public nano::store::component }; 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 mdb_block_store_upgrade_v21_v22_Test; friend class block_store_DISABLED_change_dupsort_Test; - friend void write_sideband_v14 (nano::store::lmdb::component &, store::transaction &, nano::block const &, MDB_dbi); - friend void write_sideband_v15 (nano::store::lmdb::component &, store::transaction &, nano::block const &); - friend void modify_account_info_to_v14 (nano::store::lmdb::component &, store::transaction const &, nano::account const &, uint64_t, nano::block_hash const &); - friend void modify_confirmation_height_to_v15 (nano::store::lmdb::component &, store::transaction const &, nano::account const &, uint64_t); }; } // namespace nano::store::lmdb diff --git a/nano/store/versioning.cpp b/nano/store/versioning.cpp index ddf7c965bd..16433e0982 100644 --- a/nano/store/versioning.cpp +++ b/nano/store/versioning.cpp @@ -3,247 +3,3 @@ #include #include - -nano::store::pending_info_v14::pending_info_v14 (nano::account const & source_a, nano::amount const & amount_a, nano::epoch epoch_a) : - source (source_a), - amount (amount_a), - epoch (epoch_a) -{ -} - -bool nano::store::pending_info_v14::deserialize (nano::stream & stream_a) -{ - auto error (false); - try - { - nano::read (stream_a, source.bytes); - nano::read (stream_a, amount.bytes); - } - catch (std::runtime_error const &) - { - error = true; - } - - return error; -} - -size_t nano::store::pending_info_v14::db_size () const -{ - return sizeof (source) + sizeof (amount); -} - -bool nano::store::pending_info_v14::operator== (nano::store::pending_info_v14 const & other_a) const -{ - return source == other_a.source && amount == other_a.amount && epoch == other_a.epoch; -} - -nano::store::account_info_v14::account_info_v14 (nano::block_hash const & head_a, nano::block_hash const & rep_block_a, nano::block_hash const & open_block_a, nano::amount const & balance_a, uint64_t modified_a, uint64_t block_count_a, uint64_t confirmation_height_a, nano::epoch epoch_a) : - head (head_a), - rep_block (rep_block_a), - open_block (open_block_a), - balance (balance_a), - modified (modified_a), - block_count (block_count_a), - confirmation_height (confirmation_height_a), - epoch (epoch_a) -{ -} - -size_t nano::store::account_info_v14::db_size () const -{ - debug_assert (reinterpret_cast (this) == reinterpret_cast (&head)); - debug_assert (reinterpret_cast (&head) + sizeof (head) == reinterpret_cast (&rep_block)); - debug_assert (reinterpret_cast (&rep_block) + sizeof (rep_block) == reinterpret_cast (&open_block)); - debug_assert (reinterpret_cast (&open_block) + sizeof (open_block) == reinterpret_cast (&balance)); - debug_assert (reinterpret_cast (&balance) + sizeof (balance) == reinterpret_cast (&modified)); - debug_assert (reinterpret_cast (&modified) + sizeof (modified) == reinterpret_cast (&block_count)); - debug_assert (reinterpret_cast (&block_count) + sizeof (block_count) == reinterpret_cast (&confirmation_height)); - return sizeof (head) + sizeof (rep_block) + sizeof (open_block) + sizeof (balance) + sizeof (modified) + sizeof (block_count) + sizeof (confirmation_height); -} - -nano::store::block_sideband_v14::block_sideband_v14 (nano::block_type type_a, nano::account const & account_a, nano::block_hash const & successor_a, nano::amount const & balance_a, uint64_t height_a, uint64_t timestamp_a) : - type (type_a), - successor (successor_a), - account (account_a), - balance (balance_a), - height (height_a), - timestamp (timestamp_a) -{ -} - -size_t nano::store::block_sideband_v14::size (nano::block_type type_a) -{ - size_t result (0); - result += sizeof (successor); - if (type_a != nano::block_type::state && type_a != nano::block_type::open) - { - result += sizeof (account); - } - if (type_a != nano::block_type::open) - { - result += sizeof (height); - } - if (type_a == nano::block_type::receive || type_a == nano::block_type::change || type_a == nano::block_type::open) - { - result += sizeof (balance); - } - result += sizeof (timestamp); - return result; -} - -void nano::store::block_sideband_v14::serialize (nano::stream & stream_a) const -{ - nano::write (stream_a, successor.bytes); - if (type != nano::block_type::state && type != nano::block_type::open) - { - nano::write (stream_a, account.bytes); - } - if (type != nano::block_type::open) - { - nano::write (stream_a, boost::endian::native_to_big (height)); - } - if (type == nano::block_type::receive || type == nano::block_type::change || type == nano::block_type::open) - { - nano::write (stream_a, balance.bytes); - } - nano::write (stream_a, boost::endian::native_to_big (timestamp)); -} - -bool nano::store::block_sideband_v14::deserialize (nano::stream & stream_a) -{ - bool result (false); - try - { - nano::read (stream_a, successor.bytes); - if (type != nano::block_type::state && type != nano::block_type::open) - { - nano::read (stream_a, account.bytes); - } - if (type != nano::block_type::open) - { - nano::read (stream_a, height); - boost::endian::big_to_native_inplace (height); - } - else - { - height = 1; - } - if (type == nano::block_type::receive || type == nano::block_type::change || type == nano::block_type::open) - { - nano::read (stream_a, balance.bytes); - } - nano::read (stream_a, timestamp); - boost::endian::big_to_native_inplace (timestamp); - } - catch (std::runtime_error &) - { - result = true; - } - - return result; -} - -nano::store::block_sideband_v18::block_sideband_v18 (nano::account const & account_a, nano::block_hash const & successor_a, nano::amount const & balance_a, uint64_t height_a, uint64_t timestamp_a, nano::block_details const & details_a) : - successor (successor_a), - account (account_a), - balance (balance_a), - height (height_a), - timestamp (timestamp_a), - details (details_a) -{ -} - -nano::store::block_sideband_v18::block_sideband_v18 (nano::account const & account_a, nano::block_hash const & successor_a, nano::amount const & balance_a, uint64_t height_a, uint64_t timestamp_a, nano::epoch epoch_a, bool is_send, bool is_receive, bool is_epoch) : - successor (successor_a), - account (account_a), - balance (balance_a), - height (height_a), - timestamp (timestamp_a), - details (epoch_a, is_send, is_receive, is_epoch) -{ -} - -size_t nano::store::block_sideband_v18::size (nano::block_type type_a) -{ - size_t result (0); - result += sizeof (successor); - if (type_a != nano::block_type::state && type_a != nano::block_type::open) - { - result += sizeof (account); - } - if (type_a != nano::block_type::open) - { - result += sizeof (height); - } - if (type_a == nano::block_type::receive || type_a == nano::block_type::change || type_a == nano::block_type::open) - { - result += sizeof (balance); - } - result += sizeof (timestamp); - if (type_a == nano::block_type::state) - { - static_assert (sizeof (nano::epoch) == nano::block_details::size (), "block_details_v18 is larger than the epoch enum"); - result += nano::block_details::size (); - } - return result; -} - -void nano::store::block_sideband_v18::serialize (nano::stream & stream_a, nano::block_type type_a) const -{ - nano::write (stream_a, successor.bytes); - if (type_a != nano::block_type::state && type_a != nano::block_type::open) - { - nano::write (stream_a, account.bytes); - } - if (type_a != nano::block_type::open) - { - nano::write (stream_a, boost::endian::native_to_big (height)); - } - if (type_a == nano::block_type::receive || type_a == nano::block_type::change || type_a == nano::block_type::open) - { - nano::write (stream_a, balance.bytes); - } - nano::write (stream_a, boost::endian::native_to_big (timestamp)); - if (type_a == nano::block_type::state) - { - details.serialize (stream_a); - } -} - -bool nano::store::block_sideband_v18::deserialize (nano::stream & stream_a, nano::block_type type_a) -{ - bool result (false); - try - { - nano::read (stream_a, successor.bytes); - if (type_a != nano::block_type::state && type_a != nano::block_type::open) - { - nano::read (stream_a, account.bytes); - } - if (type_a != nano::block_type::open) - { - nano::read (stream_a, height); - boost::endian::big_to_native_inplace (height); - } - else - { - height = 1; - } - if (type_a == nano::block_type::receive || type_a == nano::block_type::change || type_a == nano::block_type::open) - { - nano::read (stream_a, balance.bytes); - } - nano::read (stream_a, timestamp); - boost::endian::big_to_native_inplace (timestamp); - if (type_a == nano::block_type::state) - { - result = details.deserialize (stream_a); - } - } - catch (std::runtime_error &) - { - result = true; - } - - return result; -} diff --git a/nano/store/versioning.hpp b/nano/store/versioning.hpp index 635a5deb55..0160535345 100644 --- a/nano/store/versioning.hpp +++ b/nano/store/versioning.hpp @@ -7,76 +7,5 @@ struct MDB_val; namespace nano::store { -class pending_info_v14 final -{ -public: - pending_info_v14 () = default; - pending_info_v14 (nano::account const &, nano::amount const &, nano::epoch); - size_t db_size () const; - bool deserialize (nano::stream &); - bool operator== (pending_info_v14 const &) const; - nano::account source{}; - nano::amount amount{ 0 }; - nano::epoch epoch{ nano::epoch::epoch_0 }; -}; -class account_info_v14 final -{ -public: - account_info_v14 () = default; - account_info_v14 (nano::block_hash const &, nano::block_hash const &, nano::block_hash const &, nano::amount const &, uint64_t, uint64_t, uint64_t, nano::epoch); - size_t db_size () const; - nano::block_hash head{ 0 }; - nano::block_hash rep_block{ 0 }; - nano::block_hash open_block{ 0 }; - nano::amount balance{ 0 }; - uint64_t modified{ 0 }; - uint64_t block_count{ 0 }; - uint64_t confirmation_height{ 0 }; - nano::epoch epoch{ nano::epoch::epoch_0 }; -}; -class block_sideband_v14 final -{ -public: - block_sideband_v14 () = default; - block_sideband_v14 (nano::block_type, nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t, uint64_t); - void serialize (nano::stream &) const; - bool deserialize (nano::stream &); - static size_t size (nano::block_type); - nano::block_type type{ nano::block_type::invalid }; - nano::block_hash successor{ 0 }; - nano::account account{}; - nano::amount balance{ 0 }; - uint64_t height{ 0 }; - uint64_t timestamp{ 0 }; -}; -class state_block_w_sideband_v14 -{ -public: - std::shared_ptr state_block; - block_sideband_v14 sideband; -}; -class block_sideband_v18 final -{ -public: - block_sideband_v18 () = default; - block_sideband_v18 (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t, uint64_t, nano::block_details const &); - block_sideband_v18 (nano::account const &, nano::block_hash const &, nano::amount const &, uint64_t, uint64_t, nano::epoch, bool is_send, bool is_receive, bool is_epoch); - void serialize (nano::stream &, nano::block_type) const; - bool deserialize (nano::stream &, nano::block_type); - static size_t size (nano::block_type); - nano::block_hash successor{ 0 }; - nano::account account{}; - nano::amount balance{ 0 }; - uint64_t height{ 0 }; - uint64_t timestamp{ 0 }; - nano::block_details details; -}; -// Move to versioning with a specific version if required for a future upgrade -template -class block_w_sideband_v18 -{ -public: - std::shared_ptr block; - block_sideband_v18 sideband; -}; +// Holds historical verisons of classes used when upgrading database stores. } // namespace nano::store