mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Use LedgerTrie for preferred ledger (RIPD-1551):
These changes augment the Validations class with a LedgerTrie to better track the history of support for validated ledgers. This improves the selection of the preferred working ledger for consensus. The Validations class now tracks both full and partial validations. Partial validations are only used to determine the working ledger; full validations are required for any quorum related function. Validators are also now explicitly restricted to sending validations with increasing ledger sequence number.
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
//==============================================================================
|
||||
#include <BeastConfig.h>
|
||||
#include <test/csf/ledgers.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
@@ -36,6 +37,53 @@ Ledger::getJson() const
|
||||
return res;
|
||||
}
|
||||
|
||||
bool
|
||||
Ledger::isAncestor(Ledger const& ancestor) const
|
||||
{
|
||||
if (ancestor.seq() < seq())
|
||||
return operator[](ancestor.seq()) == ancestor.id();
|
||||
return false;
|
||||
}
|
||||
|
||||
Ledger::ID
|
||||
Ledger::operator[](Seq s) const
|
||||
{
|
||||
if(s > seq())
|
||||
return {};
|
||||
if(s== seq())
|
||||
return id();
|
||||
return instance_->ancestors[static_cast<Seq::value_type>(s)];
|
||||
|
||||
}
|
||||
|
||||
Ledger::Seq
|
||||
mismatch(Ledger const& a, Ledger const& b)
|
||||
{
|
||||
using Seq = Ledger::Seq;
|
||||
|
||||
// end is 1 past end of range
|
||||
Seq start{0};
|
||||
Seq end = std::min(a.seq() + Seq{1}, b.seq() + Seq{1});
|
||||
|
||||
// Find mismatch in [start,end)
|
||||
// Binary search
|
||||
Seq count = end - start;
|
||||
while(count > Seq{0})
|
||||
{
|
||||
Seq step = count/Seq{2};
|
||||
Seq curr = start + step;
|
||||
if(a[curr] == b[curr])
|
||||
{
|
||||
// go to second half
|
||||
start = ++curr;
|
||||
count -= step + Seq{1};
|
||||
}
|
||||
else
|
||||
count = step;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
LedgerOracle::LedgerOracle()
|
||||
{
|
||||
instances_.insert(InstanceEntry{Ledger::genesis, nextID()});
|
||||
@@ -67,6 +115,8 @@ LedgerOracle::accept(
|
||||
|
||||
next.parentCloseTime = parent.closeTime();
|
||||
next.parentID = parent.id();
|
||||
next.ancestors.push_back(parent.id());
|
||||
|
||||
auto it = instances_.left.find(next);
|
||||
if (it == instances_.left.end())
|
||||
{
|
||||
@@ -88,19 +138,6 @@ LedgerOracle::lookup(Ledger::ID const & id) const
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
LedgerOracle::isAncestor(Ledger const & ancestor, Ledger const& descendant) const
|
||||
{
|
||||
// The ancestor must have an earlier sequence number than the descendent
|
||||
if(ancestor.seq() >= descendant.seq())
|
||||
return false;
|
||||
|
||||
boost::optional<Ledger> current{descendant};
|
||||
while(current && current->seq() > ancestor.seq())
|
||||
current = lookup(current->parentID());
|
||||
return current && (current->id() == ancestor.id());
|
||||
}
|
||||
|
||||
std::size_t
|
||||
LedgerOracle::branches(std::set<Ledger> const & ledgers) const
|
||||
{
|
||||
@@ -121,7 +158,7 @@ LedgerOracle::branches(std::set<Ledger> const & ledgers) const
|
||||
bool const idxEarlier = tips[idx].seq() < ledger.seq();
|
||||
Ledger const & earlier = idxEarlier ? tips[idx] : ledger;
|
||||
Ledger const & later = idxEarlier ? ledger : tips[idx] ;
|
||||
if (isAncestor(earlier, later))
|
||||
if (later.isAncestor(earlier))
|
||||
{
|
||||
tips[idx] = later;
|
||||
found = true;
|
||||
|
||||
Reference in New Issue
Block a user