Make it less likely that a node will get temporarily stuck in a stale consensus process.

This commit is contained in:
JoelKatz
2012-09-07 11:23:06 -07:00
parent e557395072
commit adf4ff998b
4 changed files with 45 additions and 4 deletions

View File

@@ -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)
{

View File

@@ -115,6 +115,9 @@ protected:
// deferred proposals (node ID -> proposals from that peer)
boost::unordered_map< uint160, std::list<LedgerProposal::pointer> > mDeferredProposals;
// nodes that have bowed out of this consensus process
boost::unordered_set<uint160> mDeadNodes;
// final accept logic
static void Saccept(boost::shared_ptr<LedgerConsensus> This, SHAMap::pointer txSet);
void accept(const SHAMap::pointer& txSet);

View File

@@ -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<unsigned char> LedgerProposal::sign(void)
{
std::vector<unsigned char> 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();

View File

@@ -26,6 +26,7 @@ protected:
boost::posix_time::ptime mTime;
public:
static const uint32 seqLeave = 0xffffffff; // leaving the consensus process
typedef boost::shared_ptr<LedgerProposal> 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;
};