From ad12e318ba8cbb24a73b6a6c89e2524368b81046 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 31 Aug 2012 15:51:41 -0700 Subject: [PATCH] Allow a peer position to be removed from the consensus logic if the peer is not responding. This version uses static timing. A peer takes a position every 12 seconds and a position is valid for 20 seconds. It might make sense to either make that timing adaptive or include a "validity time" field in the position. However, I think this is really only going to be an issue in fairly small networks (which is why we are seeing it). --- src/LedgerConsensus.cpp | 48 +++++++++++++++++++++++++---------------- src/LedgerConsensus.h | 1 - src/LedgerProposal.cpp | 5 +++-- src/LedgerProposal.h | 2 ++ src/LedgerTiming.h | 6 ++++++ 5 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index a0ae08095b..e4d91b83e8 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -534,10 +534,34 @@ void LedgerConsensus::timerEntry() void LedgerConsensus::updateOurPositions() { + boost::posix_time::ptime peerCutoff = boost::posix_time::second_clock::universal_time(); + boost::posix_time::ptime ourCutoff = peerCutoff - boost::posix_time::seconds(PROPOSE_INTERVAL); + peerCutoff -= boost::posix_time::seconds(PROPOSE_FRESHNESS); + bool changes = false; SHAMap::pointer ourPosition; std::vector addedTx, removedTx; + // Verify freshness of peer positions and compute close times + std::map closeTimes; + boost::unordered_map::iterator + it = mPeerPositions.begin(), end = mPeerPositions.end(); + while (it != end) + { + if (it->second->isStale(peerCutoff)) + { // proposal is stale + uint160 peerID = it->second->getPeerID(); + BOOST_FOREACH(u256_lct_pair& it, mDisputes) + it.second->unVote(peerID); + mPeerPositions.erase(it++); + } + else + { // proposal is still fresh + ++closeTimes[it->second->getCloseTime() - (it->second->getCloseTime() % mCloseResolution)]; + ++it; + } + } + BOOST_FOREACH(u256_lct_pair& it, mDisputes) { if (it.second->updatePosition(mClosePercent, mProposing)) @@ -560,10 +584,6 @@ void LedgerConsensus::updateOurPositions() } } - std::map closeTimes; - - BOOST_FOREACH(u160_prop_pair& it, mPeerPositions) - ++closeTimes[it.second->getCloseTime() - (it.second->getCloseTime() % mCloseResolution)]; int neededWeight; if (mClosePercent < AV_MID_CONSENSUS_TIME) @@ -605,13 +625,12 @@ void LedgerConsensus::updateOurPositions() } } - if (closeTime != (mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() % mCloseResolution))) - { - if (!changes) - { - ourPosition = mComplete[mOurPosition->getCurrentHash()]->snapShot(true); - changes = true; - } + if ((!changes) && + ((closeTime != (mOurPosition->getCloseTime() - (mOurPosition->getCloseTime() % mCloseResolution))) || + (mOurPosition->isStale(ourCutoff)))) + { // close time changed or our position is stale + ourPosition = mComplete[mOurPosition->getCurrentHash()]->snapShot(true); + changes = true; } if (changes) @@ -778,13 +797,6 @@ bool LedgerConsensus::peerPosition(const LedgerProposal::pointer& newPosition) return true; } -void LedgerConsensus::removePeer(const uint160& peerID) -{ - mPeerPositions.erase(peerID); - BOOST_FOREACH(u256_lct_pair& it, mDisputes) - it.second->unVote(peerID); -} - bool LedgerConsensus::peerHasSet(const Peer::pointer& peer, const uint256& hashSet, newcoin::TxSetStatus status) { if (status != newcoin::tsHAVE) // Indirect requests are for future support diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index e4e71da0ab..7736c3a5f3 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -172,7 +172,6 @@ public: bool haveConsensus(); bool peerPosition(const LedgerProposal::pointer&); - void removePeer(const uint160& peerID); void deferProposal(const LedgerProposal::pointer& proposal, const NewcoinAddress& peerPublic); bool peerHasSet(const Peer::pointer& peer, const uint256& set, newcoin::TxSetStatus status); diff --git a/src/LedgerProposal.cpp b/src/LedgerProposal.cpp index cb3ef93ec6..d96b397434 100644 --- a/src/LedgerProposal.cpp +++ b/src/LedgerProposal.cpp @@ -56,8 +56,9 @@ bool LedgerProposal::checkSign(const std::string& signature, const uint256& sign void LedgerProposal::changePosition(const uint256& newPosition, uint32 closeTime) { - mCurrentHash = newPosition; - mCloseTime = closeTime; + mCurrentHash = newPosition; + mCloseTime = closeTime; + mTime = boost::posix_time::second_clock::universal_time(); ++mProposeSeq; } diff --git a/src/LedgerProposal.h b/src/LedgerProposal.h index 3ecd39efeb..6bb833cc2d 100644 --- a/src/LedgerProposal.h +++ b/src/LedgerProposal.h @@ -56,7 +56,9 @@ public: void setPrevLedger(const uint256& prevLedger) { mPreviousLedger = prevLedger; } void setSignature(const std::string& signature) { mSignature = signature; } + const boost::posix_time::ptime getCreateTime() { return mTime; } + bool isStale(boost::posix_time::ptime cutoff) { return mTime > cutoff; } void changePosition(const uint256& newPosition, uint32 newCloseTime); Json::Value getJson() const; diff --git a/src/LedgerTiming.h b/src/LedgerTiming.h index bed4673319..2a8fb207a2 100644 --- a/src/LedgerTiming.h +++ b/src/LedgerTiming.h @@ -28,6 +28,12 @@ // How often we check state or change positions (in milliseconds) # define LEDGER_GRANULARITY 1000 +// How long we consider a proposal fresh +# define PROPOSE_FRESHNESS 20 + +// How often we force generating a new proposal to keep ours fresh +# define PROPOSE_INTERVAL 12 + // Avalanche tuning #define AV_INIT_CONSENSUS_PCT 50 // percentage of nodes on our UNL that must vote yes