20#ifndef RIPPLE_APP_CONSENSUS_LEDGERS_TRIE_H_INCLUDED
21#define RIPPLE_APP_CONSENSUS_LEDGERS_TRIE_H_INCLUDED
23#include <xrpl/basics/ToString.h>
24#include <xrpl/beast/utility/instrumentation.h>
25#include <xrpl/json/json_value.h>
39template <
class Ledger>
43 using Seq =
typename Ledger::Seq;
44 using ID =
typename Ledger::ID;
67 XRPL_ASSERT(s <=
seq,
"ripple::SpanTip::ancestor : valid input");
75namespace ledger_trie_detail {
78template <
class Ledger>
81 using Seq =
typename Ledger::Seq;
82 using ID =
typename Ledger::ID;
163 XRPL_ASSERT(
start <
end,
"ripple::Span::Span : non-empty span input");
186 return o << s.
tip().id <<
"[" << s.
start_ <<
"," << s.
end_ <<
")";
201template <
class Ledger>
234 return curr.get() == child;
236 XRPL_ASSERT(it !=
children.end(),
"ripple::Node::erase : valid input");
254 res[
"span"] = sps.
str();
264 cs.
append(child->getJson());
349template <
class Ledger>
352 using Seq =
typename Ledger::Seq;
353 using ID =
typename Ledger::ID;
377 XRPL_ASSERT(curr,
"ripple::LedgerTrie::find : non-null root");
378 Seq pos = curr->
span.diff(ledger);
384 while (!done && pos == curr->
span.end())
390 auto const childPos = child->span.diff(ledger);
414 if (ledger.id() == parent->span.tip().id)
416 for (
auto const& child : parent->children)
438 dumpImpl(o, child, offset + 1 + ss.
str().size() + 2);
455 auto const [loc, diffSeq] =
find(ledger);
458 XRPL_ASSERT(loc,
"ripple::LedgerTrie::insert : valid input ledger");
490 newNode->tipSupport = loc->tipSupport;
491 newNode->branchSupport = loc->branchSupport;
492 newNode->children = std::move(loc->children);
494 loc->children.empty(),
495 "ripple::LedgerTrie::insert : moved-from children");
497 child->parent = newNode.get();
500 XRPL_ASSERT(prefix,
"ripple::LedgerTrie::insert : prefix is set");
502 newNode->parent = loc;
503 loc->children.emplace_back(std::move(newNode));
517 newNode->parent = loc;
519 incNode = newNode.get();
520 loc->
children.push_back(std::move(newNode));
527 incNode = incNode->
parent;
555 "ripple::LedgerTrie::remove : valid input ledger");
564 decNode = decNode->
parent;
579 child->span = merge(loc->
span, child->span);
580 child->parent = parent;
581 parent->
children.emplace_back(std::move(child));
600 return loc->tipSupport;
619 if (!(diffSeq > ledger.
seq() && ledger.
seq() < loc->
span.end()))
697 while (curr && !done)
707 uncommittedIt->first <
std::max(nextSeq, largestIssued))
709 uncommitted += uncommittedIt->second;
714 while (nextSeq < curr->span.end() &&
719 uncommittedIt->first < curr->
span.end())
721 nextSeq = uncommittedIt->first +
Seq{1};
722 uncommitted += uncommittedIt->second;
726 nextSeq = curr->
span.end();
730 if (nextSeq < curr->span.end())
731 return curr->
span.before(nextSeq)->tip();
736 Node* best =
nullptr;
753 return std::make_tuple(
754 a->branchSupport, a->span.startID()) >
756 b->branchSupport, b->span.startID());
760 margin = curr->
children[0]->branchSupport -
766 if (best->
span.startID() > curr->
children[1]->span.startID())
772 if (best && ((margin > uncommitted) || (uncommitted == 0)))
777 return curr->
span.tip();
785 return !
root ||
root->branchSupport == 0;
802 res[
"trie"] =
root->getJson();
805 res[
"seq_support"][
to_string(seq)] = sup;
818 while (!nodes.
empty())
820 Node const* curr = nodes.
top();
834 expectedSeqSupport[curr->
span.end() -
Seq{1}] +=
837 for (
auto const& child : curr->
children)
839 if (child->parent != curr)
842 support += child->branchSupport;
843 nodes.
push(child.get());
Value & append(Value const &value)
Append value to array at the end.
Ancestry trie of ledgers.
void dumpImpl(std::ostream &o, std::unique_ptr< Node > const &curr, int offset) const
bool empty() const
Return whether the trie is tracking any ledgers.
Node * findByLedgerID(Ledger const &ledger, Node *parent=nullptr) const
Find the node in the trie with an exact match to the given ledger ID.
std::unique_ptr< Node > root
Json::Value getJson() const
Dump JSON representation of trie state.
std::uint32_t tipSupport(Ledger const &ledger) const
Return count of tip support for the specific ledger.
void insert(Ledger const &ledger, std::uint32_t count=1)
Insert and/or increment the support for the given ledger.
std::map< Seq, std::uint32_t > seqSupport
std::optional< SpanTip< Ledger > > getPreferred(Seq const largestIssued) const
Return the preferred ledger ID.
std::uint32_t branchSupport(Ledger const &ledger) const
Return the count of branch support for the specific ledger.
std::pair< Node *, Seq > find(Ledger const &ledger) const
Find the node in the trie that represents the longest common ancestry with the given ledger.
bool remove(Ledger const &ledger, std::uint32_t count=1)
Decrease support for a ledger, removing and compressing if possible.
ledger_trie_detail::Node< Ledger > Node
bool checkInvariants() const
Check the compressed trie and support invariants.
void dump(std::ostream &o) const
Dump an ascii representation of the trie to the stream.
LedgerIndex seq() const
Returns the sequence number of the base ledger.
The tip of a span of ledger ancestry.
ID ancestor(Seq const &s) const
Lookup the ID of an ancestor of the tip ledger.
SpanTip(Seq s, ID i, Ledger const lgr)
std::optional< Span > before(Seq spot) const
Span & operator=(Span &&)=default
SpanTip< Ledger > tip() const
Span & operator=(Span const &)=default
Span(Seq start, Seq end, Ledger const &l)
std::optional< Span > sub(Seq from, Seq to) const
std::optional< Span > from(Seq spot) const
Seq diff(Ledger const &o) const
friend Span merge(Span const &a, Span const &b)
friend std::ostream & operator<<(std::ostream &o, Span const &s)
Span(Span const &s)=default
@ arrayValue
array value (ordered list)
@ objectValue
object value (collection of name/value pairs).
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
RCLValidatedLedger::Seq mismatch(RCLValidatedLedger const &a, RCLValidatedLedger const &b)
std::string to_string(base_uint< Bits, Tag > const &a)
T partial_sort(T... args)
void erase(Node const *child)
Remove the given node from this Node's children.
friend std::ostream & operator<<(std::ostream &o, Node const &s)
Json::Value getJson() const
std::vector< std::unique_ptr< Node > > children
std::uint32_t branchSupport