1#ifndef XRPL_APP_CONSENSUS_LEDGERS_TRIE_H_INCLUDED
2#define XRPL_APP_CONSENSUS_LEDGERS_TRIE_H_INCLUDED
4#include <xrpl/basics/ToString.h>
5#include <xrpl/beast/utility/instrumentation.h>
6#include <xrpl/json/json_value.h>
20template <
class Ledger>
24 using Seq =
typename Ledger::Seq;
25 using ID =
typename Ledger::ID;
48 XRPL_ASSERT(s <=
seq,
"ripple::SpanTip::ancestor : valid input");
56namespace ledger_trie_detail {
59template <
class Ledger>
62 using Seq =
typename Ledger::Seq;
63 using ID =
typename Ledger::ID;
144 XRPL_ASSERT(
start <
end,
"ripple::Span::Span : non-empty span input");
167 return o << s.
tip().id <<
"[" << s.
start_ <<
"," << s.
end_ <<
")";
182template <
class Ledger>
215 return curr.get() == child;
217 XRPL_ASSERT(it !=
children.end(),
"ripple::Node::erase : valid input");
235 res[
"span"] = sps.
str();
245 cs.
append(child->getJson());
330template <
class Ledger>
333 using Seq =
typename Ledger::Seq;
334 using ID =
typename Ledger::ID;
358 XRPL_ASSERT(curr,
"ripple::LedgerTrie::find : non-null root");
359 Seq pos = curr->
span.diff(ledger);
365 while (!done && pos == curr->
span.end())
371 auto const childPos = child->span.diff(ledger);
395 if (ledger.id() == parent->span.tip().id)
397 for (
auto const& child : parent->children)
419 dumpImpl(o, child, offset + 1 + ss.
str().size() + 2);
436 auto const [loc, diffSeq] =
find(ledger);
439 XRPL_ASSERT(loc,
"ripple::LedgerTrie::insert : valid input ledger");
471 newNode->tipSupport = loc->tipSupport;
472 newNode->branchSupport = loc->branchSupport;
473 newNode->children = std::move(loc->children);
475 loc->children.empty(),
476 "ripple::LedgerTrie::insert : moved-from children");
478 child->parent = newNode.get();
481 XRPL_ASSERT(prefix,
"ripple::LedgerTrie::insert : prefix is set");
483 newNode->parent = loc;
484 loc->children.emplace_back(std::move(newNode));
498 newNode->parent = loc;
500 incNode = newNode.get();
501 loc->
children.push_back(std::move(newNode));
508 incNode = incNode->
parent;
536 "ripple::LedgerTrie::remove : valid input ledger");
545 decNode = decNode->
parent;
560 child->span = merge(loc->
span, child->span);
561 child->parent = parent;
562 parent->
children.emplace_back(std::move(child));
581 return loc->tipSupport;
600 if (!(diffSeq > ledger.
seq() && ledger.
seq() < loc->
span.end()))
678 while (curr && !done)
688 uncommittedIt->first <
std::max(nextSeq, largestIssued))
690 uncommitted += uncommittedIt->second;
695 while (nextSeq < curr->span.end() &&
700 uncommittedIt->first < curr->
span.end())
702 nextSeq = uncommittedIt->first +
Seq{1};
703 uncommitted += uncommittedIt->second;
707 nextSeq = curr->
span.end();
711 if (nextSeq < curr->span.end())
712 return curr->
span.before(nextSeq)->tip();
717 Node* best =
nullptr;
734 return std::make_tuple(
735 a->branchSupport, a->span.startID()) >
737 b->branchSupport, b->span.startID());
741 margin = curr->
children[0]->branchSupport -
747 if (best->
span.startID() > curr->
children[1]->span.startID())
753 if (best && ((margin > uncommitted) || (uncommitted == 0)))
758 return curr->
span.tip();
766 return !
root ||
root->branchSupport == 0;
783 res[
"trie"] =
root->getJson();
786 res[
"seq_support"][
to_string(seq)] = sup;
799 while (!nodes.
empty())
801 Node const* curr = nodes.
top();
815 expectedSeqSupport[curr->
span.end() -
Seq{1}] +=
818 for (
auto const& child : curr->
children)
820 if (child->parent != curr)
823 support += child->branchSupport;
824 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