diff --git a/doc/release-notes-6579.md b/doc/release-notes-6579.md new file mode 100644 index 000000000000..2010b206a468 --- /dev/null +++ b/doc/release-notes-6579.md @@ -0,0 +1,5 @@ +Notable Changes +--------------- + +* Dash Core will no longer migrate EvoDb databases generated in v19 and v20, users upgrading + from these versions are recommended to run `-reindex` to rebuild all databases and indexes. diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 13919caac1da..a3b396978d67 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -1199,238 +1199,6 @@ void CDeterministicMNManager::CleanupCache(int nHeight) return erased; } -bool CDeterministicMNManager::MigrateDBIfNeeded() -{ - static const std::string DB_OLD_LIST_SNAPSHOT = "dmn_S"; - static const std::string DB_OLD_LIST_DIFF = "dmn_D"; - static const std::string DB_OLD_BEST_BLOCK = "b_b2"; - static const std::string DB_OLD_BEST_BLOCK2 = "b_b3"; - const auto& consensusParams = Params().GetConsensus(); - - LOCK(cs_main); - - LogPrintf("CDeterministicMNManager::%s -- upgrading DB to migrate MN type\n", __func__); - - if (m_chainstate.m_chain.Tip() == nullptr) { - // should have no records - LogPrintf("CDeterministicMNManager::%s -- Chain empty. evoDB:%d.\n", __func__, m_evoDb.IsEmpty()); - return m_evoDb.IsEmpty(); - } - - if (m_evoDb.GetRawDB().Exists(EVODB_BEST_BLOCK) || m_evoDb.GetRawDB().Exists(DB_OLD_BEST_BLOCK2)) { - if (EraseOldDBData(m_evoDb.GetRawDB(), {DB_OLD_LIST_DIFF, DB_OLD_LIST_SNAPSHOT})) { - // we messed up, make sure this time we actually drop old data - LogPrintf("CDeterministicMNManager::%s -- migration already done. cleaned old data.\n", __func__); - m_evoDb.GetRawDB().CompactFull(); - LogPrintf("CDeterministicMNManager::%s -- done compacting database\n", __func__); - // flush it to disk - if (!m_evoDb.CommitRootTransaction()) { - LogPrintf("CDeterministicMNManager::%s -- failed to commit to evoDB\n", __func__); - return false; - } - } else { - LogPrintf("CDeterministicMNManager::%s -- migration already done. skipping.\n", __func__); - } - return true; - } - - // Removing the old EVODB_BEST_BLOCK value early results in older version to crash immediately, even if the upgrade - // process is cancelled in-between. But if the new version sees that the old EVODB_BEST_BLOCK is already removed, - // then we must assume that the upgrade process was already running before but was interrupted. - if (m_chainstate.m_chain.Height() > 1 && !m_evoDb.GetRawDB().Exists(DB_OLD_BEST_BLOCK)) { - LogPrintf("CDeterministicMNManager::%s -- previous migration attempt failed.\n", __func__); - return false; - } - m_evoDb.GetRawDB().Erase(DB_OLD_BEST_BLOCK); - - if (!DeploymentActiveAt(*m_chainstate.m_chain.Tip(), consensusParams, Consensus::DEPLOYMENT_DIP0003)) { - // not reached DIP3 height yet, so no upgrade needed - LogPrintf("CDeterministicMNManager::%s -- migration not needed. dip3 not reached\n", __func__); - auto dbTx = m_evoDb.BeginTransaction(); - m_evoDb.WriteBestBlock(m_chainstate.m_chain.Tip()->GetBlockHash()); - dbTx->Commit(); - if (!m_evoDb.CommitRootTransaction()) { - LogPrintf("CDeterministicMNManager::%s -- failed to commit to evoDB\n", __func__); - return false; - } - return true; - } - - if (DeploymentActiveAt(*m_chainstate.m_chain.Tip(), consensusParams, Consensus::DEPLOYMENT_V19)) { - // too late - LogPrintf("CDeterministicMNManager::%s -- migration is not possible\n", __func__); - return false; - } - - - CDBBatch batch(m_evoDb.GetRawDB()); - - for (const auto nHeight : irange::range(Params().GetConsensus().DIP0003Height, m_chainstate.m_chain.Height() + 1)) { - auto pindex = m_chainstate.m_chain[nHeight]; - // Unserialise CDeterministicMNListDiff using MN_OLD_FORMAT and set it's type to the default value TYPE_REGULAR_MASTERNODE - // It will be later written with format MN_CURRENT_FORMAT which includes the type field and MN state bls version. - CDataStream diff_data(SER_DISK, CLIENT_VERSION); - if (!m_evoDb.GetRawDB().ReadDataStream(std::make_pair(DB_OLD_LIST_DIFF, pindex->GetBlockHash()), diff_data)) { - LogPrintf("CDeterministicMNManager::%s -- missing CDeterministicMNListDiff at height %d\n", __func__, nHeight); - return false; - } - CDeterministicMNListDiff mndiff; - mndiff.Unserialize(diff_data, CDeterministicMN::MN_OLD_FORMAT); - batch.Write(std::make_pair(DB_LIST_DIFF, pindex->GetBlockHash()), mndiff); - CDataStream snapshot_data(SER_DISK, CLIENT_VERSION); - if (!m_evoDb.GetRawDB().ReadDataStream(std::make_pair(DB_OLD_LIST_SNAPSHOT, pindex->GetBlockHash()), snapshot_data)) { - // it's ok, we write snapshots every DISK_SNAPSHOT_PERIOD blocks only - continue; - } - CDeterministicMNList mnList; - mnList.Unserialize(snapshot_data, CDeterministicMN::MN_OLD_FORMAT); - batch.Write(std::make_pair(DB_LIST_SNAPSHOT, pindex->GetBlockHash()), mnList); - m_evoDb.GetRawDB().WriteBatch(batch); - batch.Clear(); - LogPrintf("CDeterministicMNManager::%s -- wrote snapshot at height %d\n", __func__, nHeight); - } - - m_evoDb.GetRawDB().WriteBatch(batch); - - // Writing EVODB_BEST_BLOCK (which is b_b4 now) marks the DB as upgraded - auto dbTx = m_evoDb.BeginTransaction(); - m_evoDb.WriteBestBlock(m_chainstate.m_chain.Tip()->GetBlockHash()); - dbTx->Commit(); - - LogPrintf("CDeterministicMNManager::%s -- done migrating\n", __func__); - - if (EraseOldDBData(m_evoDb.GetRawDB(), {DB_OLD_LIST_DIFF, DB_OLD_LIST_SNAPSHOT})) { - LogPrintf("CDeterministicMNManager::%s -- done cleaning old data\n", __func__); - } - - m_evoDb.GetRawDB().CompactFull(); - - LogPrintf("CDeterministicMNManager::%s -- done compacting database\n", __func__); - - // flush it to disk - if (!m_evoDb.CommitRootTransaction()) { - LogPrintf("CDeterministicMNManager::%s -- failed to commit to evoDB\n", __func__); - return false; - } - - return true; -} - -bool CDeterministicMNManager::MigrateDBIfNeeded2() -{ - static const std::string DB_OLD_LIST_SNAPSHOT = "dmn_S2"; - static const std::string DB_OLD_LIST_DIFF = "dmn_D2"; - static const std::string DB_OLD_BEST_BLOCK = "b_b3"; - const auto& consensusParams = Params().GetConsensus(); - - LOCK(cs_main); - - LogPrintf("CDeterministicMNManager::%s -- upgrading DB to migrate MN state bls version\n", __func__); - - if (m_chainstate.m_chain.Tip() == nullptr) { - // should have no records - LogPrintf("CDeterministicMNManager::%s -- Chain empty. evoDB:%d.\n", __func__, m_evoDb.IsEmpty()); - return m_evoDb.IsEmpty(); - } - - if (m_evoDb.GetRawDB().Exists(EVODB_BEST_BLOCK)) { - if (EraseOldDBData(m_evoDb.GetRawDB(), {DB_OLD_LIST_DIFF, DB_OLD_LIST_SNAPSHOT})) { - // we messed up, make sure this time we actually drop old data - LogPrintf("CDeterministicMNManager::%s -- migration already done. cleaned old data.\n", __func__); - m_evoDb.GetRawDB().CompactFull(); - LogPrintf("CDeterministicMNManager::%s -- done compacting database\n", __func__); - // flush it to disk - if (!m_evoDb.CommitRootTransaction()) { - LogPrintf("CDeterministicMNManager::%s -- failed to commit to evoDB\n", __func__); - return false; - } - } else { - LogPrintf("CDeterministicMNManager::%s -- migration already done. skipping.\n", __func__); - } - return true; - } - - // Removing the old EVODB_BEST_BLOCK value early results in older version to crash immediately, even if the upgrade - // process is cancelled in-between. But if the new version sees that the old EVODB_BEST_BLOCK is already removed, - // then we must assume that the upgrade process was already running before but was interrupted. - if (m_chainstate.m_chain.Height() > 1 && !m_evoDb.GetRawDB().Exists(DB_OLD_BEST_BLOCK)) { - LogPrintf("CDeterministicMNManager::%s -- previous migration attempt failed.\n", __func__); - return false; - } - m_evoDb.GetRawDB().Erase(DB_OLD_BEST_BLOCK); - - if (!DeploymentActiveAt(*m_chainstate.m_chain.Tip(), consensusParams, Consensus::DEPLOYMENT_DIP0003)) { - // not reached DIP3 height yet, so no upgrade needed - LogPrintf("CDeterministicMNManager::%s -- migration not needed. dip3 not reached\n", __func__); - auto dbTx = m_evoDb.BeginTransaction(); - m_evoDb.WriteBestBlock(m_chainstate.m_chain.Tip()->GetBlockHash()); - dbTx->Commit(); - if (!m_evoDb.CommitRootTransaction()) { - LogPrintf("CDeterministicMNManager::%s -- failed to commit to evoDB\n", __func__); - return false; - } - return true; - } - - if (DeploymentActiveAt(*m_chainstate.m_chain.Tip(), consensusParams, Consensus::DEPLOYMENT_V19)) { - // too late - LogPrintf("CDeterministicMNManager::%s -- migration is not possible\n", __func__); - return false; - } - - CDBBatch batch(m_evoDb.GetRawDB()); - - for (const auto nHeight : irange::range(Params().GetConsensus().DIP0003Height, m_chainstate.m_chain.Height() + 1)) { - auto pindex = m_chainstate.m_chain[nHeight]; - // Unserialise CDeterministicMNListDiff using MN_TYPE_FORMAT and set MN state bls version to LEGACY_BLS_VERSION. - // It will be later written with format MN_CURRENT_FORMAT which includes the type field. - CDataStream diff_data(SER_DISK, CLIENT_VERSION); - if (!m_evoDb.GetRawDB().ReadDataStream(std::make_pair(DB_OLD_LIST_DIFF, pindex->GetBlockHash()), diff_data)) { - LogPrintf("CDeterministicMNManager::%s -- missing CDeterministicMNListDiff at height %d\n", __func__, nHeight); - return false; - } - CDeterministicMNListDiff mndiff; - mndiff.Unserialize(diff_data, CDeterministicMN::MN_TYPE_FORMAT); - batch.Write(std::make_pair(DB_LIST_DIFF, pindex->GetBlockHash()), mndiff); - CDataStream snapshot_data(SER_DISK, CLIENT_VERSION); - if (!m_evoDb.GetRawDB().ReadDataStream(std::make_pair(DB_OLD_LIST_SNAPSHOT, pindex->GetBlockHash()), snapshot_data)) { - // it's ok, we write snapshots every DISK_SNAPSHOT_PERIOD blocks only - continue; - } - CDeterministicMNList mnList; - mnList.Unserialize(snapshot_data, CDeterministicMN::MN_TYPE_FORMAT); - batch.Write(std::make_pair(DB_LIST_SNAPSHOT, pindex->GetBlockHash()), mnList); - m_evoDb.GetRawDB().WriteBatch(batch); - batch.Clear(); - LogPrintf("CDeterministicMNManager::%s -- wrote snapshot at height %d\n", __func__, nHeight); - } - - m_evoDb.GetRawDB().WriteBatch(batch); - - // Writing EVODB_BEST_BLOCK (which is b_b4 now) marks the DB as upgraded - auto dbTx = m_evoDb.BeginTransaction(); - m_evoDb.WriteBestBlock(m_chainstate.m_chain.Tip()->GetBlockHash()); - dbTx->Commit(); - - LogPrintf("CDeterministicMNManager::%s -- done migrating\n", __func__); - - if (EraseOldDBData(m_evoDb.GetRawDB(), {DB_OLD_LIST_DIFF, DB_OLD_LIST_SNAPSHOT})) { - LogPrintf("CDeterministicMNManager::%s -- done cleaning old data\n", __func__); - } - - m_evoDb.GetRawDB().CompactFull(); - - LogPrintf("CDeterministicMNManager::%s -- done compacting database\n", __func__); - - // flush it to disk - if (!m_evoDb.CommitRootTransaction()) { - LogPrintf("CDeterministicMNManager::%s -- failed to commit to evoDB\n", __func__); - return false; - } - - return true; -} - template static bool CheckService(const ProTx& proTx, TxValidationState& state) { diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index a239387a86b1..2d606568f6f6 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -46,8 +46,6 @@ class CDeterministicMN uint64_t internalId{std::numeric_limits::max()}; public: - static constexpr uint16_t MN_OLD_FORMAT = 0; - static constexpr uint16_t MN_TYPE_FORMAT = 1; static constexpr uint16_t MN_VERSION_FORMAT = 2; static constexpr uint16_t MN_CURRENT_FORMAT = MN_VERSION_FORMAT; @@ -75,29 +73,19 @@ class CDeterministicMN template inline void SerializationOp(Stream& s, Operation ser_action, const uint8_t format_version) { + // We no longer support EvoDB formats below MN_VERSION_FORMAT + if (format_version < MN_VERSION_FORMAT) { + throw std::ios_base::failure("EvoDb too old, run Dash Core with -reindex to rebuild"); + } READWRITE(proTxHash); READWRITE(VARINT(internalId)); READWRITE(collateralOutpoint); READWRITE(nOperatorReward); - // We need to read CDeterministicMNState using the old format only when called with MN_OLD_FORMAT or MN_TYPE_FORMAT on Unserialize() - // Serialisation (writing) will be done always using new format - if (ser_action.ForRead() && format_version == MN_OLD_FORMAT) { - CDeterministicMNState_Oldformat old_state; - READWRITE(old_state); - pdmnState = std::make_shared(old_state); - } else if (ser_action.ForRead() && format_version == MN_TYPE_FORMAT) { - CDeterministicMNState_mntype_format old_state; - READWRITE(old_state); - pdmnState = std::make_shared(old_state); - } else { - READWRITE(pdmnState); - } - // We need to read/write nType if: - // format_version is set to MN_TYPE_FORMAT (For writing (serialisation) it is always the case) Needed for the MNLISTDIFF Migration in evoDB + READWRITE(pdmnState); // We can't know if we are serialising for the Disk or for the Network here (s.GetType() is not accessible) // Therefore if s.GetVersion() == CLIENT_VERSION -> Then we know we are serialising for the Disk // Otherwise, we can safely check with protocol versioning logic so we won't break old clients - if (format_version >= MN_TYPE_FORMAT && (s.GetVersion() == CLIENT_VERSION || s.GetVersion() >= DMN_TYPE_PROTO_VERSION)) { + if (s.GetVersion() == CLIENT_VERSION || s.GetVersion() >= DMN_TYPE_PROTO_VERSION) { READWRITE(nType); } else { nType = MnType::Regular; @@ -221,15 +209,9 @@ class CDeterministicMNList SerializationOpBase(s, CSerActionUnserialize()); - bool evodb_migration = (format_version == CDeterministicMN::MN_OLD_FORMAT || format_version == CDeterministicMN::MN_TYPE_FORMAT); size_t cnt = ReadCompactSize(s); for (size_t i = 0; i < cnt; i++) { - if (evodb_migration) { - const auto dmn = std::make_shared(deserialize, s, format_version); - mnMap = mnMap.set(dmn->proTxHash, dmn); - } else { - AddMN(std::make_shared(deserialize, s, format_version), false); - } + AddMN(std::make_shared(deserialize, s, format_version), false); } } @@ -620,9 +602,6 @@ class CDeterministicMNManager // Test if given TX is a ProRegTx which also contains the collateral at index n static bool IsProTxWithCollateral(const CTransactionRef& tx, uint32_t n); - bool MigrateDBIfNeeded(); - bool MigrateDBIfNeeded2(); - void DoMaintenance() EXCLUSIVE_LOCKS_REQUIRED(!cs); private: diff --git a/src/evo/dmnstate.h b/src/evo/dmnstate.h index 2b35df36639a..bd8c1e28050f 100644 --- a/src/evo/dmnstate.h +++ b/src/evo/dmnstate.h @@ -25,109 +25,6 @@ namespace llmq class CFinalCommitment; } // namespace llmq -// TODO: To remove this in the future -class CDeterministicMNState_Oldformat -{ -private: - int nPoSeBanHeight{-1}; - - friend class CDeterministicMNStateDiff; - friend class CDeterministicMNState; - -public: - int nRegisteredHeight{-1}; - int nLastPaidHeight{0}; - int nPoSePenalty{0}; - int nPoSeRevivedHeight{-1}; - uint16_t nRevocationReason{CProUpRevTx::REASON_NOT_SPECIFIED}; - uint256 confirmedHash; - uint256 confirmedHashWithProRegTxHash; - CKeyID keyIDOwner; - CBLSLazyPublicKey pubKeyOperator; - CKeyID keyIDVoting; - CService addr; - CScript scriptPayout; - CScript scriptOperatorPayout; - -public: - CDeterministicMNState_Oldformat() = default; - - SERIALIZE_METHODS(CDeterministicMNState_Oldformat, obj) - { - READWRITE( - obj.nRegisteredHeight, - obj.nLastPaidHeight, - obj.nPoSePenalty, - obj.nPoSeRevivedHeight, - obj.nPoSeBanHeight, - obj.nRevocationReason, - obj.confirmedHash, - obj.confirmedHashWithProRegTxHash, - obj.keyIDOwner, - obj.pubKeyOperator, - obj.keyIDVoting, - obj.addr, - obj.scriptPayout, - obj.scriptOperatorPayout); - } -}; - -// TODO: To remove this in the future -class CDeterministicMNState_mntype_format -{ -private: - int nPoSeBanHeight{-1}; - - friend class CDeterministicMNStateDiff; - friend class CDeterministicMNState; - -public: - int nRegisteredHeight{-1}; - int nLastPaidHeight{0}; - int nConsecutivePayments{0}; - int nPoSePenalty{0}; - int nPoSeRevivedHeight{-1}; - uint16_t nRevocationReason{CProUpRevTx::REASON_NOT_SPECIFIED}; - uint256 confirmedHash; - uint256 confirmedHashWithProRegTxHash; - CKeyID keyIDOwner; - CBLSLazyPublicKey pubKeyOperator; - CKeyID keyIDVoting; - CService addr; - CScript scriptPayout; - CScript scriptOperatorPayout; - - uint160 platformNodeID{}; - uint16_t platformP2PPort{0}; - uint16_t platformHTTPPort{0}; - -public: - CDeterministicMNState_mntype_format() = default; - - SERIALIZE_METHODS(CDeterministicMNState_mntype_format, obj) - { - READWRITE( - obj.nRegisteredHeight, - obj.nLastPaidHeight, - obj.nConsecutivePayments, - obj.nPoSePenalty, - obj.nPoSeRevivedHeight, - obj.nPoSeBanHeight, - obj.nRevocationReason, - obj.confirmedHash, - obj.confirmedHashWithProRegTxHash, - obj.keyIDOwner, - obj.pubKeyOperator, - obj.keyIDVoting, - obj.addr, - obj.scriptPayout, - obj.scriptOperatorPayout, - obj.platformNodeID, - obj.platformP2PPort, - obj.platformHTTPPort); - } -}; - class CDeterministicMNState { private: @@ -176,41 +73,6 @@ class CDeterministicMNState platformHTTPPort(proTx.platformHTTPPort) { } - explicit CDeterministicMNState(const CDeterministicMNState_Oldformat& s) : - nPoSeBanHeight(s.nPoSeBanHeight), - nRegisteredHeight(s.nRegisteredHeight), - nLastPaidHeight(s.nLastPaidHeight), - nPoSePenalty(s.nPoSePenalty), - nPoSeRevivedHeight(s.nPoSeRevivedHeight), - nRevocationReason(s.nRevocationReason), - confirmedHash(s.confirmedHash), - confirmedHashWithProRegTxHash(s.confirmedHashWithProRegTxHash), - keyIDOwner(s.keyIDOwner), - pubKeyOperator(s.pubKeyOperator), - keyIDVoting(s.keyIDVoting), - addr(s.addr), - scriptPayout(s.scriptPayout), - scriptOperatorPayout(s.scriptOperatorPayout) {} - - explicit CDeterministicMNState(const CDeterministicMNState_mntype_format& s) : - nPoSeBanHeight(s.nPoSeBanHeight), - nRegisteredHeight(s.nRegisteredHeight), - nLastPaidHeight(s.nLastPaidHeight), - nConsecutivePayments(s.nConsecutivePayments), - nPoSePenalty(s.nPoSePenalty), - nPoSeRevivedHeight(s.nPoSeRevivedHeight), - nRevocationReason(s.nRevocationReason), - confirmedHash(s.confirmedHash), - confirmedHashWithProRegTxHash(s.confirmedHashWithProRegTxHash), - keyIDOwner(s.keyIDOwner), - pubKeyOperator(s.pubKeyOperator), - keyIDVoting(s.keyIDVoting), - addr(s.addr), - scriptPayout(s.scriptPayout), - scriptOperatorPayout(s.scriptOperatorPayout), - platformNodeID(s.platformNodeID), - platformP2PPort(s.platformP2PPort), - platformHTTPPort(s.platformHTTPPort) {} template CDeterministicMNState(deserialize_type, Stream& s) diff --git a/src/init.cpp b/src/init.cpp index b540f5925d1e..c88569d73220 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1922,9 +1922,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) case ChainstateLoadingError::ERROR_COMMITING_EVO_DB: strLoadError = _("Failed to commit Evo database"); break; - case ChainstateLoadingError::ERROR_UPGRADING_EVO_DB: - strLoadError = _("Error upgrading Evo database"); - break; case ChainstateLoadingError::ERROR_UPGRADING_SIGNALS_DB: strLoadError = _("Error upgrading evo database for EHF"); break; diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index dde3c8b02188..3d0ad5c7766d 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -187,9 +187,6 @@ std::optional LoadChainstate(bool fReset, } } - if (!dmnman->MigrateDBIfNeeded() || !dmnman->MigrateDBIfNeeded2()) { - return ChainstateLoadingError::ERROR_UPGRADING_EVO_DB; - } if (!mnhf_manager->ForceSignalDBUpdate()) { return ChainstateLoadingError::ERROR_UPGRADING_SIGNALS_DB; } diff --git a/src/node/chainstate.h b/src/node/chainstate.h index 8b0c738a85ba..014b43d164df 100644 --- a/src/node/chainstate.h +++ b/src/node/chainstate.h @@ -44,7 +44,6 @@ enum class ChainstateLoadingError { ERROR_LOADCHAINTIP_FAILED, ERROR_GENERIC_BLOCKDB_OPEN_FAILED, ERROR_COMMITING_EVO_DB, - ERROR_UPGRADING_EVO_DB, ERROR_UPGRADING_SIGNALS_DB, SHUTDOWN_PROBED, };