3#include <xrpl/basics/ToString.h>
4#include <xrpl/beast/utility/instrumentation.h>
5#include <xrpl/json/json_value.h>
25template <
class Ledger>
29 using Seq = Ledger::Seq;
30 using ID = Ledger::ID;
53 XRPL_ASSERT(s <=
seq,
"xrpl::SpanTip::ancestor : valid input");
64template <
class Ledger>
67 using Seq = Ledger::Seq;
68 using ID = Ledger::ID;
79 XRPL_ASSERT(
ledger_.seq() ==
start_,
"xrpl::Span::Span : ledger is genesis");
146 XRPL_ASSERT(
start <
end,
"xrpl::Span::Span : non-empty span input");
169 return o << s.
tip().id <<
"[" << s.
start_ <<
"," << s.
end_ <<
")";
184template <
class Ledger>
216 XRPL_ASSERT(it !=
children.end(),
"xrpl::Node::erase : valid input");
233 res[
"span"] = sps.
str();
243 cs.
append(child->getJson());
329template <
class Ledger>
333 using ID = Ledger::ID;
359 XRPL_ASSERT(curr,
"xrpl::LedgerTrie::find : non-null root");
360 Seq pos = curr->
span.diff(ledger);
366 while (!done && pos == curr->
span.end())
372 auto const childPos = child->span.diff(ledger);
395 if (parent ==
nullptr)
396 parent =
root_.get();
397 if (ledger.id() == parent->span.tip().id)
399 for (
auto const& child : parent->children)
420 dumpImpl(o, child, offset + 1 + ss.
str().size() + 2);
438 auto const [loc, diffSeq] =
find(ledger);
441 XRPL_ASSERT(loc,
"xrpl::LedgerTrie::insert : valid input ledger");
473 newNode->tipSupport = loc->tipSupport;
474 newNode->branchSupport = loc->branchSupport;
475 newNode->children = std::move(loc->children);
476 XRPL_ASSERT(loc->children.empty(),
"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;
537 "xrpl::LedgerTrie::remove : valid input ledger");
546 decNode = decNode->
parent;
561 child->span = merge(loc->
span, child->span);
562 child->parent = parent;
563 parent->
children.emplace_back(std::move(child));
585 return loc->tipSupport;
605 if (!(diffSeq > ledger.
seq() && ledger.
seq() < loc->
span.end()))
684 while (curr && !done)
694 uncommittedIt->first <
std::max(nextSeq, largestIssued))
696 uncommitted += uncommittedIt->second;
701 while (nextSeq < curr->span.end() && curr->
branchSupport > uncommitted)
705 uncommittedIt->first < curr->
span.end())
707 nextSeq = uncommittedIt->first +
Seq{1};
708 uncommitted += uncommittedIt->second;
713 nextSeq = curr->
span.end();
718 if (nextSeq < curr->span.end())
722 return curr->
span.before(nextSeq)->tip();
728 Node* best =
nullptr;
744 return std::make_tuple(a->branchSupport, a->span.startID()) >
745 std::make_tuple(b->branchSupport, b->span.startID());
749 margin = curr->
children[0]->branchSupport - curr->
children[1]->branchSupport;
754 if (best->
span.startID() > curr->
children[1]->span.startID())
760 if (best && ((margin > uncommitted) || (uncommitted == 0)))
769 return curr->
span.tip();
797 res[
"trie"] =
root_->getJson();
800 res[
"seq_support"][
to_string(seq)] = sup;
814 while (!nodes.
empty())
816 Node const* curr = nodes.
top();
831 for (
auto const& child : curr->
children)
833 if (child->parent != curr)
836 support += child->branchSupport;
837 nodes.
push(child.get());
Value & append(Value const &value)
Append value to array at the end.
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::uint32_t branchSupport(Ledger const &ledger) const
Return the count of branch support for the specific ledger.
ledger_trie_detail::Span< Ledger > Span
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
json::Value getJson() const
Dump JSON representation of trie state.
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.
std::unique_ptr< Node > root_
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.
Span(Seq start, Seq end, Ledger l)
Seq diff(Ledger const &o) const
Span & operator=(Span const &)=default
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
@ Array
array value (ordered list)
@ Object
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(BaseUInt< 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
json::Value getJson() const
std::uint32_t branchSupport