diff --git a/nano/lib/blocks.cpp b/nano/lib/blocks.cpp index da700bce07..65a6060eef 100644 --- a/nano/lib/blocks.cpp +++ b/nano/lib/blocks.cpp @@ -1905,6 +1905,11 @@ size_t nano::block_sideband::size (nano::block_type type_a) return result; } +bool nano::block_sideband::operator== (nano::block_sideband const & other_a) const +{ + return account == other_a.account && balance == other_a.balance && height == other_a.height && timestamp == other_a.timestamp && details == other_a.details && source_epoch == other_a.source_epoch; +} + void nano::block_sideband::serialize (nano::stream & stream_a, nano::block_type type_a) const { if (type_a != nano::block_type::state && type_a != nano::block_type::open) diff --git a/nano/lib/blocks.hpp b/nano/lib/blocks.hpp index 609cccd9aa..3437effb6a 100644 --- a/nano/lib/blocks.hpp +++ b/nano/lib/blocks.hpp @@ -73,6 +73,7 @@ class block_sideband final void serialize (nano::stream &, nano::block_type) const; bool deserialize (nano::stream &, nano::block_type); static size_t size (nano::block_type); + bool operator== (nano::block_sideband const & other_a) const; nano::account account{}; nano::amount balance{ 0 }; uint64_t height{ 0 }; diff --git a/nano/store/component.hpp b/nano/store/component.hpp index 5d5883b259..fe5fb6ff48 100644 --- a/nano/store/component.hpp +++ b/nano/store/component.hpp @@ -71,7 +71,7 @@ namespace store store::account & account; store::pending & pending; static int constexpr version_minimum{ 21 }; - static int constexpr version_current{ 22 }; + static int constexpr version_current{ 23 }; public: store::online_weight & online_weight; diff --git a/nano/store/lmdb/lmdb.cpp b/nano/store/lmdb/lmdb.cpp index 2d084536c2..3c4d7322e0 100644 --- a/nano/store/lmdb/lmdb.cpp +++ b/nano/store/lmdb/lmdb.cpp @@ -224,6 +224,9 @@ bool nano::store::lmdb::component::do_upgrades (store::write_transaction & trans upgrade_v21_to_v22 (transaction_a); [[fallthrough]]; case 22: + upgrade_v22_to_v23 (transaction_a); + [[fallthrough]]; + case 23: break; default: logger.critical (nano::log::type::lmdb, "The version of the ledger ({}) is too high for this node", version_l); @@ -233,6 +236,69 @@ bool nano::store::lmdb::component::do_upgrades (store::write_transaction & trans return error; } +void nano::store::lmdb::component::upgrade_v22_to_v23 (store::write_transaction const & transaction_a) +{ + logger.info (nano::log::type::lmdb, "Upgrading database from v22 to v23..."); + auto count = 0u; + nano::block_hash next{ 0 }; + while (true) + { + MDB_cursor * cursor{ nullptr }; + { + auto status = mdb_cursor_open (env.tx (transaction_a), block_store.blocks_handle, &cursor); + release_assert (status == MDB_SUCCESS); + } + std::shared_ptr block; + nano::block_hash successor; + { + nano::store::db_val key = next; + nano::store::db_val value; + auto seek_status = mdb_cursor_get (cursor, &key.value, &value.value, MDB_SET_RANGE); + release_assert (seek_status == MDB_SUCCESS || seek_status == MDB_NOTFOUND); + if (seek_status == MDB_NOTFOUND) + { + break; + } + auto get_status = mdb_cursor_get (cursor, &key.value, &value.value, MDB_GET_CURRENT); + release_assert (get_status == MDB_SUCCESS); + nano::bufferstream stream (reinterpret_cast (value.data ()), value.size ()); + block = nano::deserialize_block (stream); + release_assert (block != nullptr); + auto retrieved = static_cast (key); + release_assert (retrieved == block->hash ()); + next = retrieved.number () + 1; + nano::read (stream, successor); + nano::block_sideband sideband; + auto sideband_error = sideband.deserialize (stream, block->type ()); + release_assert (!sideband_error); + block->sideband_set (sideband); + } + if (!successor.is_zero ()) + { + this->successor.put (transaction_a, block->hash (), successor); + } + { + std::vector vector; + { + nano::vectorstream stream (vector); + nano::serialize_block (stream, *block); + block->sideband ().serialize (stream, block->type ()); + } + nano::store::db_val key = block->hash (); + nano::store::db_val value{ vector.size (), (void *)vector.data () }; + auto put_status = mdb_cursor_put (cursor, key, &value.value, MDB_CURRENT); + release_assert (put_status == MDB_SUCCESS); + } + if (++count % 10000 == 0) + { + logger.info (nano::log::type::lmdb, "Upgraded {} successors", count); + } + mdb_cursor_close (cursor); + } + logger.info (nano::log::type::lmdb, "Upgraded {} successors in total", std::to_string (count)); + version.put (transaction_a, 23); +} + void nano::store::lmdb::component::upgrade_v21_to_v22 (store::write_transaction const & transaction_a) { logger.info (nano::log::type::lmdb, "Upgrading database from v21 to v22..."); diff --git a/nano/store/lmdb/lmdb.hpp b/nano/store/lmdb/lmdb.hpp index 9c21d1cbab..39d83f76ac 100644 --- a/nano/store/lmdb/lmdb.hpp +++ b/nano/store/lmdb/lmdb.hpp @@ -116,6 +116,7 @@ class component : public nano::store::component private: bool do_upgrades (store::write_transaction &, nano::ledger_constants & constants, bool &); void upgrade_v21_to_v22 (store::write_transaction const &); + void upgrade_v22_to_v23 (store::write_transaction const &); void open_databases (bool &, store::transaction const &, unsigned);