From adf4ff998becf6b74fe8738761fb00315893d362 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 7 Sep 2012 11:23:06 -0700 Subject: [PATCH] Make it less likely that a node will get temporarily stuck in a stale consensus process. --- src/LedgerConsensus.cpp | 28 ++++++++++++++++++++++++++-- src/LedgerConsensus.h | 3 +++ src/LedgerProposal.cpp | 16 ++++++++++++++-- src/LedgerProposal.h | 2 ++ 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 5130d398c5..6500a1ff37 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -321,12 +321,19 @@ void LedgerConsensus::handleLCL(const uint256& lclHash) BOOST_FOREACH(Peer::ref peer, peerList) mAcquiringLedger->peerHas(peer); } + if (mHaveCorrectLCL && mProposing) + { + Log(lsINFO) << "Bowing out of consensus"; + mOurPosition->bowOut(); + propose(); + } mHaveCorrectLCL = false; mProposing = false; mValidating = false; mCloseTimes.clear(); mPeerPositions.clear(); mDisputes.clear(); + mDeadNodes.clear(); return; } @@ -794,11 +801,18 @@ void LedgerConsensus::addDisputedTransaction(const uint256& txID, const std::vec bool LedgerConsensus::peerPosition(const LedgerProposal::pointer& newPosition) { - LedgerProposal::pointer& currentPosition = mPeerPositions[newPosition->getPeerID()]; + uint160 peerID = newPosition->getPeerID(); + if (mDeadNodes.find(peerID) != mDeadNodes.end()) + { + Log(lsINFO) << "Position from dead node"; + return false; + } + + LedgerProposal::pointer& currentPosition = mPeerPositions[peerID]; if (currentPosition) { - assert(newPosition->getPeerID() == currentPosition->getPeerID()); + assert(peerID == currentPosition->getPeerID()); if (newPosition->getProposeSeq() <= currentPosition->getProposeSeq()) return false; } @@ -808,9 +822,19 @@ bool LedgerConsensus::peerPosition(const LedgerProposal::pointer& newPosition) Log(lsTRACE) << "Peer reports close time as " << newPosition->getCloseTime(); ++mCloseTimes[newPosition->getCloseTime()]; } + else if (newPosition->getProposeSeq() == LedgerProposal::seqLeave) + { + BOOST_FOREACH(u256_lct_pair& it, mDisputes) + it.second->unVote(peerID); + mPeerPositions.erase(peerID); + mDeadNodes.insert(peerID); + return true; + } + Log(lsINFO) << "Processing peer proposal " << newPosition->getProposeSeq() << "/" << newPosition->getCurrentHash(); currentPosition = newPosition; + SHAMap::pointer set = getTransactionTree(newPosition->getCurrentHash(), true); if (set) { diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index 4e1db172dd..17aa02691d 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -115,6 +115,9 @@ protected: // deferred proposals (node ID -> proposals from that peer) boost::unordered_map< uint160, std::list > mDeferredProposals; + // nodes that have bowed out of this consensus process + boost::unordered_set mDeadNodes; + // final accept logic static void Saccept(boost::shared_ptr This, SHAMap::pointer txSet); void accept(const SHAMap::pointer& txSet); diff --git a/src/LedgerProposal.cpp b/src/LedgerProposal.cpp index d96b397434..5840c10372 100644 --- a/src/LedgerProposal.cpp +++ b/src/LedgerProposal.cpp @@ -62,6 +62,13 @@ void LedgerProposal::changePosition(const uint256& newPosition, uint32 closeTime ++mProposeSeq; } +void LedgerProposal::bowOut() +{ + mCurrentHash = uint256(); + mTime = boost::posix_time::second_clock::universal_time(); + mProposeSeq = seqLeave; +} + std::vector LedgerProposal::sign(void) { std::vector ret; @@ -78,9 +85,14 @@ Json::Value LedgerProposal::getJson() const { Json::Value ret = Json::objectValue; ret["previous_ledger"] = mPreviousLedger.GetHex(); - ret["transaction_hash"] = mCurrentHash.GetHex(); + + if (mProposeSeq != seqLeave) + { + ret["transaction_hash"] = mCurrentHash.GetHex(); + ret["propose_seq"] = mProposeSeq; + } + ret["close_time"] = mCloseTime; - ret["propose_seq"] = mProposeSeq; if (mPublicKey.isValid()) ret["peer_id"] = mPublicKey.humanNodePublic(); diff --git a/src/LedgerProposal.h b/src/LedgerProposal.h index 74d0f7c071..adaa557719 100644 --- a/src/LedgerProposal.h +++ b/src/LedgerProposal.h @@ -26,6 +26,7 @@ protected: boost::posix_time::ptime mTime; public: + static const uint32 seqLeave = 0xffffffff; // leaving the consensus process typedef boost::shared_ptr pointer; @@ -63,6 +64,7 @@ public: bool isStale(boost::posix_time::ptime cutoff) { return mTime <= cutoff; } void changePosition(const uint256& newPosition, uint32 newCloseTime); + void bowOut(); Json::Value getJson() const; };