From c96c423afbca7f7c2b76d7e6a884d8d7e0b4992d Mon Sep 17 00:00:00 2001 From: Mark Travis Date: Tue, 11 Jul 2017 01:39:04 -0700 Subject: [PATCH] Allow a newly-started validator to participate in consensus. --- src/ripple/app/consensus/RCLConsensus.cpp | 11 +++---- src/ripple/app/ledger/LedgerMaster.h | 33 +++++++++++--------- src/ripple/app/ledger/impl/LedgerMaster.cpp | 18 +++-------- src/ripple/app/main/Application.cpp | 34 ++++++++++++++++++++- src/ripple/app/main/Application.h | 5 +++ 5 files changed, 66 insertions(+), 35 deletions(-) diff --git a/src/ripple/app/consensus/RCLConsensus.cpp b/src/ripple/app/consensus/RCLConsensus.cpp index c959c01018..d269e818bd 100644 --- a/src/ripple/app/consensus/RCLConsensus.cpp +++ b/src/ripple/app/consensus/RCLConsensus.cpp @@ -934,12 +934,11 @@ RCLConsensus::peerProposal( bool RCLConsensus::Adaptor::preStartRound(RCLCxLedger const & prevLgr) { - // We have a key, we have some idea what the ledger is, and we are not - // amendment blocked - validating_ = - !app_.getOPs().isNeedNetworkLedger() && - (valPublic_.size() != 0) && - !app_.getOPs().isAmendmentBlocked(); + // We have a key and do not want out of sync validations after a restart, + // and are not amendment blocked. + validating_ = valPublic_.size() != 0 && + prevLgr.seq() >= app_.getMaxDisallowedLedger() && + !app_.getOPs().isAmendmentBlocked(); if (validating_) { diff --git a/src/ripple/app/ledger/LedgerMaster.h b/src/ripple/app/ledger/LedgerMaster.h index 9f522e1b4b..8be9bc0bdf 100644 --- a/src/ripple/app/ledger/LedgerMaster.h +++ b/src/ripple/app/ledger/LedgerMaster.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -299,11 +300,11 @@ private: std::shared_ptr mHistLedger; // Fully validated ledger, whether or not we have the ledger resident. - std::pair mLastValidLedger; + std::pair mLastValidLedger {uint256(), 0}; LedgerHistory mLedgerHistory; - CanonicalTXSet mHeldTransactions; + CanonicalTXSet mHeldTransactions {uint256()}; // A set of transactions to replay during the next close std::unique_ptr replayData; @@ -314,23 +315,23 @@ private: std::unique_ptr mLedgerCleaner; uint256 mLastValidateHash; - std::uint32_t mLastValidateSeq; + std::uint32_t mLastValidateSeq {0}; // Publish thread is running. - bool mAdvanceThread; + bool mAdvanceThread {false}; // Publish thread has work to do. - bool mAdvanceWork; - int mFillInProgress; + bool mAdvanceWork {false}; + int mFillInProgress {0}; - int mPathFindThread; // Pathfinder jobs dispatched - bool mPathFindNewRequest; + int mPathFindThread {0}; // Pathfinder jobs dispatched + bool mPathFindNewRequest {false}; - std::atomic mPubLedgerClose; - std::atomic mPubLedgerSeq; - std::atomic mValidLedgerSign; - std::atomic mValidLedgerSeq; - std::atomic mBuildingLedgerSeq; + std::atomic mPubLedgerClose {0}; + std::atomic mPubLedgerSeq {0}; + std::atomic mValidLedgerSign {0}; + std::atomic mValidLedgerSeq {0}; + std::atomic mBuildingLedgerSeq {0}; // The server is in standalone mode bool const standalone_; @@ -345,7 +346,11 @@ private: TaggedCache fetch_packs_; - std::uint32_t fetch_seq_; + std::uint32_t fetch_seq_ {0}; + + // Try to keep a validator from switching from test to live network + // without first wiping the database. + LedgerIndex const max_ledger_difference_ {1000000}; }; diff --git a/src/ripple/app/ledger/impl/LedgerMaster.cpp b/src/ripple/app/ledger/impl/LedgerMaster.cpp index 959ad2b6bd..88adbc63cc 100644 --- a/src/ripple/app/ledger/impl/LedgerMaster.cpp +++ b/src/ripple/app/ledger/impl/LedgerMaster.cpp @@ -66,22 +66,9 @@ LedgerMaster::LedgerMaster (Application& app, Stopwatch& stopwatch, : Stoppable ("LedgerMaster", parent) , app_ (app) , m_journal (journal) - , mLastValidLedger (std::make_pair (uint256(), 0)) , mLedgerHistory (collector, app) - , mHeldTransactions (uint256 ()) , mLedgerCleaner (detail::make_LedgerCleaner ( app, *this, app_.journal("LedgerCleaner"))) - , mLastValidateSeq (0) - , mAdvanceThread (false) - , mAdvanceWork (false) - , mFillInProgress (0) - , mPathFindThread (0) - , mPathFindNewRequest (false) - , mPubLedgerClose (0) - , mPubLedgerSeq (0) - , mValidLedgerSign (0) - , mValidLedgerSeq (0) - , mBuildingLedgerSeq (0) , standalone_ (app_.config().standalone()) , fetch_depth_ (app_.getSHAMapStore ().clampFetchDepth ( app_.config().FETCH_DEPTH)) @@ -89,7 +76,6 @@ LedgerMaster::LedgerMaster (Application& app, Stopwatch& stopwatch, , ledger_fetch_size_ (app_.config().getSize (siLedgerFetch)) , fetch_packs_ ("FetchPack", 65536, 45, stopwatch, app_.journal("TaggedCache")) - , fetch_seq_ (0) { } @@ -221,6 +207,10 @@ LedgerMaster::setValidLedger( mValidLedger.set (l); mValidLedgerSign = signTime.time_since_epoch().count(); + assert (mValidLedgerSeq || + !app_.getMaxDisallowedLedger() || + l->info().seq + max_ledger_difference_ > + app_.getMaxDisallowedLedger()); mValidLedgerSeq = l->info().seq; app_.getOPs().updateLocalTx (*l); diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index 2b472513ac..a2a229bdab 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -52,11 +52,14 @@ #include #include #include +#include #include #include #include #include #include +#include +#include namespace ripple { @@ -77,7 +80,7 @@ private: beast::Journal j_; // missing node handler - std::uint32_t maxSeq = 0; + LedgerIndex maxSeq = 0; std::mutex maxSeqLock; void acquire ( @@ -1006,8 +1009,17 @@ public: setSweepTimer(); } + LedgerIndex getMaxDisallowedLedger() override + { + return maxDisallowedLedger_; + } + private: + // For a newly-started validator, this is the greatest persisted ledger + // and new validations must be greater than this. + std::atomic maxDisallowedLedger_ {0}; + void addTxnSeqField(); void addValidationSeqFields(); bool updateTables (); @@ -1024,6 +1036,8 @@ private: std::string const& ledgerID, bool replay, bool isFilename); + + void setMaxDisallowedLedger(); }; //------------------------------------------------------------------------------ @@ -1073,6 +1087,9 @@ bool ApplicationImp::setup() return false; } + if (validatorKeys_.publicKey.size()) + setMaxDisallowedLedger(); + getLedgerDB ().getSession () << boost::str (boost::format ("PRAGMA cache_size=-%d;") % (config_->getSize (siLgrDBCache) * 1024)); @@ -1988,6 +2005,21 @@ bool ApplicationImp::updateTables () return true; } +void ApplicationImp::setMaxDisallowedLedger() +{ + boost::optional seq; + { + auto db = getLedgerDB().checkoutDb(); + *db << "SELECT MAX(LedgerSeq) FROM Ledgers;", soci::into(seq); + } + if (seq) + maxDisallowedLedger_ = *seq; + + JLOG (m_journal.trace()) << "Max persisted ledger is " + << maxDisallowedLedger_; +} + + //------------------------------------------------------------------------------ Application::Application () diff --git a/src/ripple/app/main/Application.h b/src/ripple/app/main/Application.h index 161c8d7e70..2769be22d4 100644 --- a/src/ripple/app/main/Application.h +++ b/src/ripple/app/main/Application.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -175,6 +176,10 @@ public: /** Retrieve the "wallet database" */ virtual DatabaseCon& getWalletDB () = 0; + + /** Ensure that a newly-started validator does not sign proposals older + * than the last ledger it persisted. */ + virtual LedgerIndex getMaxDisallowedLedger() = 0; }; std::unique_ptr