mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
We have to track the high node ID of trusted validators as a tie-breaker.
1) Change return from getCurrentValidations 2) Log tiebreaker logic to aid debugging 3) Change checkLastClosedLedger to use the new tie-breaker logic 4) Log when we refuse to switch to our own previous ledger 5) Track node ID in the serialized validation object 6) Simplify getCurrentValidations ledger suppression logic
This commit is contained in:
@@ -259,15 +259,15 @@ void LedgerConsensus::checkLCL()
|
||||
int netLgrCount = 0;
|
||||
|
||||
uint256 favoredLedger = (mState == lcsPRE_CLOSE) ? uint256() : mPrevLedgerHash; // Don't get stuck one ledger behind
|
||||
boost::unordered_map<uint256, int> vals =
|
||||
theApp->getValidations().getCurrentValidations(favoredLedger);
|
||||
boost::unordered_map<uint256, currentValidationCount> vals =
|
||||
theApp->getValidations().getCurrentValidations(favoredLedger);
|
||||
|
||||
typedef std::pair<const uint256, int> u256_int_pair;
|
||||
BOOST_FOREACH(u256_int_pair& it, vals)
|
||||
if (it.second > netLgrCount)
|
||||
typedef std::pair<const uint256, currentValidationCount> u256_cvc_pair;
|
||||
BOOST_FOREACH(u256_cvc_pair& it, vals)
|
||||
if (it.second.first > netLgrCount)
|
||||
{
|
||||
netLgr = it.first;
|
||||
netLgrCount = it.second;
|
||||
netLgrCount = it.second.first;
|
||||
}
|
||||
|
||||
if (netLgr != mPrevLedgerHash)
|
||||
@@ -287,8 +287,8 @@ void LedgerConsensus::checkLCL()
|
||||
Log(lsWARNING) << mPrevLedgerHash << " to " << netLgr;
|
||||
|
||||
#ifdef DEBUG
|
||||
BOOST_FOREACH(u256_int_pair& it, vals)
|
||||
Log(lsDEBUG) << "V: " << it.first << ", " << it.second;
|
||||
BOOST_FOREACH(u256_cvc_pair& it, vals)
|
||||
Log(lsDEBUG) << "V: " << it.first << ", " << it.second.first;
|
||||
#endif
|
||||
|
||||
if (mHaveCorrectLCL)
|
||||
|
||||
@@ -372,7 +372,7 @@ class ValidationCount
|
||||
{
|
||||
public:
|
||||
int trustedValidations, nodesUsing;
|
||||
NewcoinAddress highNode;
|
||||
uint160 highNodeUsing, highValidation;
|
||||
|
||||
ValidationCount() : trustedValidations(0), nodesUsing(0) { ; }
|
||||
bool operator>(const ValidationCount& v)
|
||||
@@ -383,8 +383,9 @@ public:
|
||||
{
|
||||
if (nodesUsing > v.nodesUsing) return true;
|
||||
if (nodesUsing < v.nodesUsing) return false;
|
||||
return highNodeUsing > v.highNodeUsing;
|
||||
}
|
||||
return highNode > v.highNode;
|
||||
return highValidation > v.highValidation;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -474,10 +475,16 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
|
||||
|
||||
boost::unordered_map<uint256, ValidationCount> ledgers;
|
||||
{
|
||||
boost::unordered_map<uint256, int> current = theApp->getValidations().getCurrentValidations(closedLedger);
|
||||
typedef std::pair<const uint256, int> u256_int_pair;
|
||||
BOOST_FOREACH(u256_int_pair& it, current)
|
||||
ledgers[it.first].trustedValidations += it.second;
|
||||
boost::unordered_map<uint256, currentValidationCount> current =
|
||||
theApp->getValidations().getCurrentValidations(closedLedger);
|
||||
typedef std::pair<const uint256, currentValidationCount> u256_cvc_pair;
|
||||
BOOST_FOREACH(u256_cvc_pair& it, current)
|
||||
{
|
||||
ValidationCount& vc = ledgers[it.first];
|
||||
vc.trustedValidations += it.second.first;
|
||||
if (it.second.second > vc.highValidation)
|
||||
vc.highValidation = it.second.second;
|
||||
}
|
||||
}
|
||||
|
||||
ValidationCount& ourVC = ledgers[closedLedger];
|
||||
@@ -485,7 +492,9 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
|
||||
if ((theConfig.LEDGER_CREATOR) && (mMode >= omTRACKING))
|
||||
{
|
||||
++ourVC.nodesUsing;
|
||||
ourVC.highNode = theApp->getWallet().getNodePublic();
|
||||
uint160 ourAddress = theApp->getWallet().getNodePublic().getNodeID();
|
||||
if (ourAddress > ourVC.highNodeUsing)
|
||||
ourVC.highNodeUsing = ourAddress;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(Peer::ref it, peerList)
|
||||
@@ -500,8 +509,8 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
|
||||
if (peerLedger.isNonZero())
|
||||
{
|
||||
ValidationCount& vc = ledgers[peerLedger];
|
||||
if ((vc.nodesUsing == 0) || (it->getNodePublic() > vc.highNode))
|
||||
vc.highNode = it->getNodePublic();
|
||||
if ((vc.nodesUsing == 0) || (it->getNodePublic().getNodeID() > vc.highNodeUsing))
|
||||
vc.highNodeUsing = it->getNodePublic().getNodeID();
|
||||
++vc.nodesUsing;
|
||||
}
|
||||
}
|
||||
@@ -516,6 +525,13 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
|
||||
{
|
||||
Log(lsTRACE) << "L: " << it->first << " t=" << it->second.trustedValidations <<
|
||||
", n=" << it->second.nodesUsing;
|
||||
|
||||
// Temporary logging to make sure tiebreaking isn't broken
|
||||
if (it->second.trustedValidations > 0)
|
||||
Log(lsTRACE) << " TieBreakTV: " << it->second.highValidation;
|
||||
else if (it->second.nodesUsing > 0)
|
||||
Log(lsTRACE) << " TieBreakNU: " << it->second.highNodeUsing;
|
||||
|
||||
if (it->second > bestVC)
|
||||
{
|
||||
bestVC = it->second;
|
||||
@@ -526,6 +542,7 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
|
||||
|
||||
if (switchLedgers && (closedLedger == prevClosedLedger))
|
||||
{ // don't switch to our own previous ledger
|
||||
Log(lsINFO) << "We won't switch to our own previous ledger";
|
||||
networkClosed = ourClosed->getHash();
|
||||
switchLedgers = false;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ const uint32 SerializedValidation::sFullFlag = 0x1;
|
||||
SerializedValidation::SerializedValidation(SerializerIterator& sit, bool checkSignature)
|
||||
: STObject(sValidationFormat, sit, sfValidation), mTrusted(false)
|
||||
{
|
||||
mNodeID = NewcoinAddress::createNodePublic(getFieldVL(sfSigningPubKey)).getNodeID();
|
||||
assert(mNodeID.isNonZero());
|
||||
if (checkSignature && !isValid())
|
||||
{
|
||||
Log(lsTRACE) << "Invalid validation " << getJson(0);
|
||||
@@ -41,7 +43,12 @@ SerializedValidation::SerializedValidation(const uint256& ledgerHash, uint32 sig
|
||||
setFieldH256(sfLedgerHash, ledgerHash);
|
||||
setFieldU32(sfSigningTime, signTime);
|
||||
if (naSeed.isValid())
|
||||
setFieldVL(sfSigningPubKey, NewcoinAddress::createNodePublic(naSeed).getNodePublic());
|
||||
{
|
||||
NewcoinAddress np = NewcoinAddress::createNodePublic(naSeed);
|
||||
setFieldVL(sfSigningPubKey, np.getNodePublic());
|
||||
mNodeID = np.getNodeID();
|
||||
assert(mNodeID.isNonZero());
|
||||
}
|
||||
if (!isFull)
|
||||
setFlag(sFullFlag);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ class SerializedValidation : public STObject
|
||||
{
|
||||
protected:
|
||||
uint256 mPreviousHash;
|
||||
uint160 mNodeID;
|
||||
bool mTrusted;
|
||||
|
||||
void setNode();
|
||||
@@ -26,6 +27,7 @@ public:
|
||||
uint32 getSignTime() const;
|
||||
uint32 getFlags() const;
|
||||
NewcoinAddress getSignerPublic() const;
|
||||
uint160 getNodeID() const { return mNodeID; }
|
||||
bool isValid() const;
|
||||
bool isFull() const;
|
||||
bool isTrusted() const { return mTrusted; }
|
||||
|
||||
@@ -150,35 +150,37 @@ int ValidationCollection::getLoadRatio(bool overLoaded)
|
||||
return (goodNodes * 100) / (goodNodes + badNodes);
|
||||
}
|
||||
|
||||
boost::unordered_map<uint256, int> ValidationCollection::getCurrentValidations(uint256 currentLedger)
|
||||
boost::unordered_map<uint256, currentValidationCount>
|
||||
ValidationCollection::getCurrentValidations(uint256 currentLedger)
|
||||
{
|
||||
uint32 cutoff = theApp->getOPs().getNetworkTimeNC() - LEDGER_VAL_INTERVAL;
|
||||
bool valCurrentLedger = currentLedger.isNonZero();
|
||||
|
||||
boost::unordered_map<uint256, int> ret;
|
||||
boost::unordered_map<uint256, currentValidationCount> ret;
|
||||
|
||||
boost::mutex::scoped_lock sl(mValidationLock);
|
||||
boost::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.begin();
|
||||
while (it != mCurrentValidations.end())
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mValidationLock);
|
||||
boost::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.begin();
|
||||
while (it != mCurrentValidations.end())
|
||||
{
|
||||
if (!it->second) // contains no record
|
||||
it = mCurrentValidations.erase(it);
|
||||
else if (it->second->getSignTime() < cutoff)
|
||||
{ // contains a stale record
|
||||
mStaleValidations.push_back(it->second);
|
||||
it->second = SerializedValidation::pointer();
|
||||
condWrite();
|
||||
it = mCurrentValidations.erase(it);
|
||||
}
|
||||
else
|
||||
{ // contains a live record
|
||||
if (valCurrentLedger && it->second->isPreviousHash(currentLedger))
|
||||
++ret[currentLedger]; // count for the favored ledger
|
||||
else
|
||||
++ret[it->second->getLedgerHash()];
|
||||
++it;
|
||||
}
|
||||
if (!it->second) // contains no record
|
||||
it = mCurrentValidations.erase(it);
|
||||
else if (it->second->getSignTime() < cutoff)
|
||||
{ // contains a stale record
|
||||
mStaleValidations.push_back(it->second);
|
||||
it->second = SerializedValidation::pointer();
|
||||
condWrite();
|
||||
it = mCurrentValidations.erase(it);
|
||||
}
|
||||
else
|
||||
{ // contains a live record
|
||||
bool countPreferred = valCurrentLedger && it->second->isPreviousHash(currentLedger);
|
||||
currentValidationCount& p = countPreferred ? ret[currentLedger] : ret[it->second->getLedgerHash()];
|
||||
|
||||
++(p.first); // count for the favored ledger
|
||||
uint160 ni = it->second->getNodeID();
|
||||
if (ni > p.second)
|
||||
p.second = ni;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
typedef boost::unordered_map<uint160, SerializedValidation::pointer> ValidationSet;
|
||||
|
||||
typedef std::pair<int, uint160> currentValidationCount; // nodes validating and highest node ID validating
|
||||
|
||||
class ValidationCollection
|
||||
{
|
||||
protected:
|
||||
@@ -38,7 +40,7 @@ public:
|
||||
int getNodesAfter(const uint256& ledger);
|
||||
int getLoadRatio(bool overLoaded);
|
||||
|
||||
boost::unordered_map<uint256, int> getCurrentValidations(uint256 currentLedger = uint256());
|
||||
boost::unordered_map<uint256, currentValidationCount> getCurrentValidations(uint256 currentLedger);
|
||||
|
||||
void flush();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user