Skip to content

Commit

Permalink
[FOLD] Add SpanTip:
Browse files Browse the repository at this point in the history
Use the SpanTip class to allow finding the ID of the ancestor of a tip
of ledger history. The Validations::getPreferred function can use this
to more directly check if the current ledger is the parent of the
preferred ledger.
  • Loading branch information
bachase committed Jan 31, 2018
1 parent 944527d commit ea18089
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 89 deletions.
54 changes: 46 additions & 8 deletions src/ripple/consensus/LedgerTrie.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,46 @@

namespace ripple {

/** The tip of a span of ledger ancestry
*/
template <class Ledger>
class SpanTip
{
public:
using Seq = typename Ledger::Seq;
using ID = typename Ledger::ID;

SpanTip(Seq s, ID i, Ledger const lgr)
: seq{s}, id{i}, ledger{std::move(lgr)}
{
}

// The sequence number the tip ledger
Seq seq;
// The ID of the tip ledger
ID id;

/** Lookup the ID of an ancestor of the tip ledger
@param s The sequence number of the ancestor
@return The ID of the ancestor with that sequence number
@note s must be less than or equal to the sequence number of the
preferred ledger
*/
ID
ancestor(Seq const& s) const
{
assert(s <= seq);
return ledger[s];
}

private:
Ledger const ledger;
};

namespace ledger_trie_detail {

// Represents a span of ancestry of a ledger
template <class Ledger>
class Span
Expand Down Expand Up @@ -101,12 +140,12 @@ class Span
return clamp(mismatch(ledger_, o));
}

// The Seq and ID of the end of the span
std::pair<Seq, ID>
// The tip of this span
SpanTip<Ledger>
tip() const
{
Seq tipSeq{end_ - Seq{1}};
return {tipSeq, ledger_[tipSeq]};
return SpanTip<Ledger>{tipSeq, ledger_[tipSeq], ledger_};
}

private:
Expand Down Expand Up @@ -137,7 +176,7 @@ class Span
friend std::ostream&
operator<<(std::ostream& o, Span const& s)
{
return o << s.tip().second << "[" << s.start_ << "," << s.end_ << ")";
return o << s.tip().id << "[" << s.start_ << "," << s.end_ << ")";
}

friend Span
Expand Down Expand Up @@ -203,8 +242,8 @@ struct Node
getJson() const
{
Json::Value res;
res["id"] = to_string(span.tip().second);
res["seq"] = static_cast<std::uint32_t>(span.tip().first);
res["id"] = to_string(span.tip().id);
res["seq"] = static_cast<std::uint32_t>(span.tip().seq);
res["tipSupport"] = tipSupport;
res["branchSupport"] = branchSupport;
if (!children.empty())
Expand Down Expand Up @@ -407,7 +446,6 @@ class LedgerTrie
boost::optional<Span> oldSuffix = loc->span.from(diffSeq);
boost::optional<Span> newSuffix = Span{ledger}.from(diffSeq);


if (oldSuffix)
{
// Have
Expand Down Expand Up @@ -623,7 +661,7 @@ class LedgerTrie
issued by this node.
@return Pair with the sequence number and ID of the preferred ledger
*/
std::pair<Seq,ID>
SpanTip<Ledger>
getPreferred(Seq const largestIssued) const
{
Node* curr = root.get();
Expand Down
49 changes: 18 additions & 31 deletions src/ripple/consensus/Validations.h
Original file line number Diff line number Diff line change
Expand Up @@ -637,74 +637,61 @@ class Validations
and is *not* an ancestor of the current working ledger; otherwise it
remains the current working ledger.
@param currLedger The local node's current working ledger
@param curr The local node's current working ledger
@return The sequence and id of the preferred working ledger,
or Seq{0},ID{0} if no trusted validations are available to
determine the preferred ledger.
*/
std::pair<Seq, ID>
getPreferred(Ledger const& currLedger)
getPreferred(Ledger const& curr)
{
Seq preferredSeq{0};
ID preferredID{0};

ScopedLock lock{mutex_};
std::tie(preferredSeq, preferredID) =
SpanTip<Ledger> preferred =
withTrie(lock, [this](LedgerTrie<Ledger>& trie) {
return trie.getPreferred(localSeqEnforcer_.largest());
});

// No trusted validations to determine branch
if (preferredSeq == Seq{0})
return std::make_pair(preferredSeq, preferredID);

Seq currSeq = currLedger.seq();
ID currID = currLedger.id();
if (preferred.seq == Seq{0})
return std::make_pair(preferred.seq, preferred.id);

// If we are the parent of the preferred ledger, stick with our
// current ledger since we might be about to generate it
if (preferredSeq == currSeq + Seq{1})
{
for (auto const& it : lastLedger_)
{
Ledger const& ledger = it.second;
if (ledger.seq() == preferredSeq &&
ledger.id() == preferredID && ledger[currSeq] == currID)
return std::make_pair(currSeq, currID);
}
}
if (preferred.seq == curr.seq() + Seq{1} &&
preferred.ancestor(curr.seq()) == curr.id())
return std::make_pair(curr.seq(), curr.id());

// A ledger ahead of us is preferred regardless of whether it is
// a descendant of our working ledger or it is on a different chain
if (preferredSeq > currSeq)
return std::make_pair(preferredSeq, preferredID);
if (preferred.seq > curr.seq())
return std::make_pair(preferred.seq, preferred.id);

// Only switch to earlier or same sequence number
// if it is a different chain.
if (currLedger[preferredSeq] != preferredID)
return std::make_pair(preferredSeq, preferredID);
if (curr[preferred.seq] != preferred.id)
return std::make_pair(preferred.seq, preferred.id);

// Stick with current ledger
return std::make_pair(currSeq, currID);
return std::make_pair(curr.seq(), curr.id());
}

/** Get the ID of the preferred working ledger that exceeds a minimum valid
ledger sequence number
@param currLedger Current working ledger
@param curr Current working ledger
@param minValidSeq Minimum allowed sequence number
@return ID Of the preferred ledger, or currLedger if the preferred ledger
@return ID Of the preferred ledger, or curr if the preferred ledger
is not valid
*/
ID
getPreferred(Ledger const& currLedger, Seq minValidSeq)
getPreferred(Ledger const& curr, Seq minValidSeq)
{
std::pair<Seq, ID> preferred = getPreferred(currLedger);
std::pair<Seq, ID> preferred = getPreferred(curr);
if(preferred.first >= minValidSeq && preferred.second != ID{0})
return preferred.second;
return currLedger.id();
return curr.id();

}

Expand Down
Loading

0 comments on commit ea18089

Please sign in to comment.