diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 00916c24cb..44aae4eabc 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -302,6 +302,9 @@ void LedgerConsensus::handleLCL(const uint256& lclHash) mHaveCorrectLCL = false; mProposing = false; mValidating = false; + mCloseTimes.clear(); + mPeerPositions.clear(); + mDisputes.clear(); return; } @@ -318,6 +321,7 @@ void LedgerConsensus::takeInitialPosition(Ledger& initialLedger) { SHAMap::pointer initialSet = initialLedger.peekTransactionMap()->snapShot(false); uint256 txSet = initialSet->getHash(); + Log(lsINFO) << "initial position " << txSet; // if any peers have taken a contrary position, process disputes boost::unordered_set found; @@ -454,25 +458,24 @@ void LedgerConsensus::statePreClose() // This ledger is open. This computes how long since the last ledger closed int sinceClose; - int ledgerInterval = 0; + int idleInterval = 0; if (mHaveCorrectLCL && mPreviousLedger->getCloseAgree()) { // we can use consensus timing sinceClose = 1000 * (theApp->getOPs().getCloseTimeNC() - mPreviousLedger->getCloseTimeNC()); - ledgerInterval = 2 * mPreviousLedger->getCloseResolution(); - if (ledgerInterval < LEDGER_IDLE_INTERVAL) - ledgerInterval = LEDGER_IDLE_INTERVAL; + idleInterval = 2 * mPreviousLedger->getCloseResolution(); + if (idleInterval < LEDGER_IDLE_INTERVAL) + idleInterval = LEDGER_IDLE_INTERVAL; } else { sinceClose = theApp->getOPs().getLastCloseTime(); - ledgerInterval = LEDGER_IDLE_INTERVAL; + idleInterval = LEDGER_IDLE_INTERVAL; } - if (sinceClose >= ContinuousLedgerTiming::shouldClose(anyTransactions, mPreviousProposers, proposersClosed, - mPreviousMSeconds, sinceClose, ledgerInterval)) + if (ContinuousLedgerTiming::shouldClose(anyTransactions, mPreviousProposers, proposersClosed, + mPreviousMSeconds, sinceClose, idleInterval)) { // it is time to close the ledger - Log(lsINFO) << "CLC: closing ledger"; mState = lcsESTABLISH; mConsensusStartTime = boost::posix_time::microsec_clock::universal_time(); mCloseTime = theApp->getOPs().getCloseTimeNC(); @@ -496,7 +499,7 @@ void LedgerConsensus::stateEstablish() } if (haveConsensus()) { - Log(lsINFO) << "Converge cutoff"; + Log(lsINFO) << "Converge cutoff (" << mPeerPositions.size() << " participants)"; mState = lcsFINISHED; beginAccept(); } @@ -524,7 +527,7 @@ void LedgerConsensus::timerEntry() switch (mState) { - case lcsPRE_CLOSE: statePreClose(); if (mState != lcsESTABLISH) return; fallthru(); + case lcsPRE_CLOSE: statePreClose(); return; case lcsESTABLISH: stateEstablish(); if (mState != lcsFINISHED) return; fallthru(); case lcsFINISHED: stateFinished(); if (mState != lcsACCEPTED) return; fallthru(); case lcsACCEPTED: stateAccepted(); return; @@ -558,7 +561,7 @@ void LedgerConsensus::updateOurPositions() } else { // proposal is still fresh - ++closeTimes[it->second->getCloseTime() - (it->second->getCloseTime() % mCloseResolution)]; + ++closeTimes[roundCloseTime(it->second->getCloseTime())]; ++it; } } @@ -600,13 +603,13 @@ void LedgerConsensus::updateOurPositions() if (thresh == 0) { // no other times mHaveCloseTimeConsensus = true; - closeTime = mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() % mCloseResolution); + closeTime = roundCloseTime(mOurPosition->getCloseTime()); } else { if (mProposing) { - ++closeTimes[mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() % mCloseResolution)]; + ++closeTimes[roundCloseTime(mOurPosition->getCloseTime())]; ++thresh; } thresh = thresh * neededWeight / 100; @@ -627,7 +630,7 @@ void LedgerConsensus::updateOurPositions() } if ((!changes) && - ((closeTime != (mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() % mCloseResolution))) || + ((closeTime != (roundCloseTime(mOurPosition->getCloseTime()))) || (mOurPosition->isStale(ourCutoff)))) { // close time changed or our position is stale ourPosition = mComplete[mOurPosition->getCurrentHash()]->snapShot(true); @@ -957,11 +960,16 @@ void LedgerConsensus::applyTransactions(const SHAMap::pointer& set, Ledger::ref } while (successes > 0); } +uint32 LedgerConsensus::roundCloseTime(uint32 closeTime) +{ + return closeTime - (closeTime % mCloseResolution); +} + void LedgerConsensus::accept(const SHAMap::pointer& set) { assert(set->getHash() == mOurPosition->getCurrentHash()); - uint32 closeTime = mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() & mCloseResolution); + uint32 closeTime = roundCloseTime(mOurPosition->getCloseTime()); Log(lsINFO) << "Computing new LCL based on network consensus"; if (mHaveCorrectLCL) @@ -1035,14 +1043,13 @@ void LedgerConsensus::accept(const SHAMap::pointer& set) mState = lcsACCEPTED; sl.unlock(); - if (mValidating && mOurPosition->getCurrentHash().isNonZero()) + if (mValidating) { // see how close our close time is to other node's close time reports Log(lsINFO) << "We closed at " << boost::lexical_cast(mCloseTime); uint64 closeTotal = mCloseTime; int closeCount = 1; - for (std::map::iterator it = mCloseTimes.begin(), end = - mCloseTimes.end(); it != end; ++it) - { + for (std::map::iterator it = mCloseTimes.begin(), end = mCloseTimes.end(); it != end; ++it) + { // FIXME: Use median, not average Log(lsINFO) << boost::lexical_cast(it->second) << " time votes for " << boost::lexical_cast(it->first); closeCount += it->second; @@ -1052,6 +1059,7 @@ void LedgerConsensus::accept(const SHAMap::pointer& set) closeTotal /= closeCount; int offset = static_cast(closeTotal) - static_cast(mCloseTime); Log(lsINFO) << "Our close offset is estimated at " << offset << " (" << closeCount << ")"; + theApp->getOPs().closeTimeOffset(offset); } #ifdef DEBUG diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index e8ae389ced..12bd725582 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -136,12 +136,15 @@ protected: void applyTransaction(TransactionEngine& engine, const SerializedTransaction::pointer& txn, Ledger::ref targetLedger, CanonicalTXSet& failedTransactions, bool openLgr); + uint32 roundCloseTime(uint32 closeTime); + // manipulating our own position void statusChange(newcoin::NodeEvent, Ledger& ledger); void takeInitialPosition(Ledger& initialLedger); void updateOurPositions(); void playbackProposals(); int getThreshold(); + void beginAccept(); void endConsensus(); diff --git a/src/LedgerTiming.cpp b/src/LedgerTiming.cpp index a29f7ad2fa..05736d28ea 100644 --- a/src/LedgerTiming.cpp +++ b/src/LedgerTiming.cpp @@ -12,7 +12,7 @@ int ContinuousLedgerTiming::LedgerTimeResolution[] = { 10, 10, 20, 30, 60, 90, 1 // Called when a ledger is open and no close is in progress -- when a transaction is received and no close // is in process, or when a close completes. Returns the number of seconds the ledger should be be open. -int ContinuousLedgerTiming::shouldClose( +bool ContinuousLedgerTiming::shouldClose( bool anyTransactions, int previousProposers, // proposers in the last closing int proposersClosed, // proposers who have currently closed this ledgers @@ -27,7 +27,7 @@ int ContinuousLedgerTiming::shouldClose( boost::str(boost::format("CLC::shouldClose range Trans=%s, Prop: %d/%d, Secs: %d (last:%d)") % (anyTransactions ? "yes" : "no") % previousProposers % proposersClosed % currentMSeconds % previousMSeconds); - return currentMSeconds; + return true;; } if (!anyTransactions) @@ -36,7 +36,7 @@ int ContinuousLedgerTiming::shouldClose( { Log(lsTRACE) << "no transactions, many proposers: now (" << proposersClosed << "closed, " << previousProposers << " before)"; - return currentMSeconds; + return true; } #if 0 // This false triggers on the genesis ledger if (previousMSeconds > (1000 * (LEDGER_IDLE_INTERVAL + 2))) // the last ledger was very slow to close @@ -47,11 +47,10 @@ int ContinuousLedgerTiming::shouldClose( return previousMSeconds - 1000; } #endif - return idleInterval * 1000; // normal idle + return currentMSeconds >= (idleInterval * 1000); // normal idle } - Log(lsTRACE) << "close now"; - return currentMSeconds; // this ledger should close now + return true; // this ledger should close now } // Returns whether we have a consensus or not. If so, we expect all honest nodes diff --git a/src/LedgerTiming.h b/src/LedgerTiming.h index 2a8fb207a2..80e89b30f4 100644 --- a/src/LedgerTiming.h +++ b/src/LedgerTiming.h @@ -52,7 +52,7 @@ public: // Returns the number of seconds the ledger was or should be open // Call when a consensus is reached and when any transaction is relayed to be added - static int shouldClose( + static bool shouldClose( bool anyTransactions, int previousProposers, int proposersClosed, int previousSeconds, int currentSeconds,