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,
"xrpl::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,
"xrpl::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(),
"xrpl::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,
"xrpl::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,
"xrpl::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 "xrpl::LedgerTrie::insert : moved-from children");
478 child->parent = newNode.get();
481 XRPL_ASSERT(prefix,
"xrpl::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 "xrpl::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.
std::uint32_t tipSupport(Ledger const &ledger) const
Return count of tip support for the specific ledger.
Node * findByLedgerID(Ledger const &ledger, Node *parent=nullptr) const
Find the node in the trie with an exact match to the given ledger ID.
bool empty() const
Return whether the trie is tracking any ledgers.
bool checkInvariants() const
Check the compressed trie and support invariants.
std::unique_ptr< Node > root
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.
std::optional< SpanTip< Ledger > > getPreferred(Seq const largestIssued) const
Return the preferred ledger ID.
void dumpImpl(std::ostream &o, std::unique_ptr< Node > const &curr, int offset) const
void dump(std::ostream &o) const
Dump an ascii representation of the trie to the stream.
void insert(Ledger const &ledger, std::uint32_t count=1)
Insert and/or increment the support for the given ledger.
Json::Value getJson() const
Dump JSON representation of trie state.
std::map< Seq, std::uint32_t > seqSupport
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
LedgerIndex seq() const
Returns the sequence number of the base ledger.
The tip of a span of ledger ancestry.
SpanTip(Seq s, ID i, Ledger const lgr)
ID ancestor(Seq const &s) const
Lookup the ID of an ancestor of the tip ledger.
Seq diff(Ledger const &o) const
Span & operator=(Span const &)=default
Span(Seq start, Seq end, Ledger const &l)
std::optional< Span > before(Seq spot) const
std::optional< Span > from(Seq spot) const
SpanTip< Ledger > tip() const
std::optional< Span > sub(Seq from, Seq to) const
Span & operator=(Span &&)=default
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.
std::string to_string(base_uint< Bits, Tag > const &a)
RCLValidatedLedger::Seq mismatch(RCLValidatedLedger const &a, RCLValidatedLedger const &b)
T partial_sort(T... args)
friend std::ostream & operator<<(std::ostream &o, Node const &s)
void erase(Node const *child)
Remove the given node from this Node's children.
std::vector< std::unique_ptr< Node > > children
std::uint32_t branchSupport
Json::Value getJson() const