diff --git a/src/side_chain.cpp b/src/side_chain.cpp index 33f38ef..ee23f7b 100644 --- a/src/side_chain.cpp +++ b/src/side_chain.cpp @@ -3334,6 +3334,26 @@ void SideChain::trigger_recovery(uint64_t failure_height, uint64_t affected_main } } + // Detect recovery loops: if we're targeting the same checkpoint as last time, + // step back one more CHECKPOINT_INTERVAL to make actual progress. + const uint64_t last_recovery = m_lastRecoveryCheckpoint.load(); + if (last_recovery > 0 && recovery_checkpoint >= last_recovery && recovery_checkpoint <= last_recovery + CHECKPOINT_INTERVAL) { + if (recovery_checkpoint >= CHECKPOINT_INTERVAL) { + LOGWARN(0, "Recovery loop detected: checkpoint " << recovery_checkpoint + << " was already tried (last=" << last_recovery << ")."); + recovery_checkpoint -= CHECKPOINT_INTERVAL; + LOGWARN(0, "Stepping back one more CHECKPOINT_INTERVAL to " << recovery_checkpoint); + } else { + LOGERR(0, "Recovery loop at checkpoint 0 - cannot go further back."); + LOGERR(0, "Stopping recovery; manual restart required."); + m_recoveryMode = false; + m_pendingRecoveryHeight = 0; + m_readyToMine = true; + return; + } + } + m_lastRecoveryCheckpoint = recovery_checkpoint; + LOGINFO(0, "Recovery target checkpoint: " << recovery_checkpoint); m_pendingRecoveryHeight = recovery_checkpoint; diff --git a/src/side_chain.h b/src/side_chain.h index c0324e8..27da1ee 100644 --- a/src/side_chain.h +++ b/src/side_chain.h @@ -249,6 +249,7 @@ private: std::atomic m_recoveryMode{false}; std::atomic m_pendingRecoveryHeight{0}; bool m_checkpointsNeedValidation{false}; + std::atomic m_lastRecoveryCheckpoint{0}; // Detects and breaks recovery loops // Mainchain reorg tracking std::atomic m_reorgGracePeriodEnd{0};