3#include <xrpl/basics/ToString.h>
4#include <xrpl/beast/utility/instrumentation.h>
5#include <xrpl/json/json_value.h>
20template <
class Ledger>
24 using Seq = Ledger::Seq;
25 using ID = Ledger::ID;
47 XRPL_ASSERT(s <=
seq,
"xrpl::SpanTip::ancestor : valid input");
58template <
class Ledger>
61 using Seq = Ledger::Seq;
62 using ID = Ledger::ID;
73 XRPL_ASSERT(
ledger_.seq() ==
start_,
"xrpl::Span::Span : ledger is genesis");
140 XRPL_ASSERT(
start <
end,
"xrpl::Span::Span : non-empty span input");
163 return o << s.
tip().id <<
"[" << s.
start_ <<
"," << s.
end_ <<
")";
178template <
class Ledger>
209 XRPL_ASSERT(it !=
children.end(),
"xrpl::Node::erase : valid input");
226 res[
"span"] = sps.
str();
236 cs.
append(child->getJson());
321template <
class Ledger>
325 using ID = Ledger::ID;
350 XRPL_ASSERT(curr,
"xrpl::LedgerTrie::find : non-null root");
351 Seq pos = curr->
span.diff(ledger);
357 while (!done && pos == curr->
span.end())
363 auto const childPos = child->span.diff(ledger);
385 if (parent ==
nullptr)
386 parent =
root_.get();
387 if (ledger.id() == parent->span.tip().id)
389 for (
auto const& child : parent->children)
410 dumpImpl(o, child, offset + 1 + ss.
str().size() + 2);
427 auto const [loc, diffSeq] =
find(ledger);
430 XRPL_ASSERT(loc,
"xrpl::LedgerTrie::insert : valid input ledger");
462 newNode->tipSupport = loc->tipSupport;
463 newNode->branchSupport = loc->branchSupport;
464 newNode->children = std::move(loc->children);
465 XRPL_ASSERT(loc->children.empty(),
"xrpl::LedgerTrie::insert : moved-from children");
467 child->parent = newNode.get();
470 XRPL_ASSERT(prefix,
"xrpl::LedgerTrie::insert : prefix is set");
472 newNode->parent = loc;
473 loc->children.emplace_back(std::move(newNode));
487 newNode->parent = loc;
489 incNode = newNode.get();
490 loc->
children.push_back(std::move(newNode));
497 incNode = incNode->
parent;
525 "xrpl::LedgerTrie::remove : valid input ledger");
534 decNode = decNode->
parent;
549 child->span = merge(loc->
span, child->span);
550 child->parent = parent;
551 parent->
children.emplace_back(std::move(child));
572 return loc->tipSupport;
591 if (!(diffSeq > ledger.
seq() && ledger.
seq() < loc->
span.end()))
669 while (curr && !done)
679 uncommittedIt->first <
std::max(nextSeq, largestIssued))
681 uncommitted += uncommittedIt->second;
686 while (nextSeq < curr->span.end() && curr->
branchSupport > uncommitted)
690 uncommittedIt->first < curr->
span.end())
692 nextSeq = uncommittedIt->first +
Seq{1};
693 uncommitted += uncommittedIt->second;
698 nextSeq = curr->
span.end();
703 if (nextSeq < curr->span.end())
707 return curr->
span.before(nextSeq)->tip();
713 Node* best =
nullptr;
729 return std::make_tuple(a->branchSupport, a->span.startID()) >
730 std::make_tuple(b->branchSupport, b->span.startID());
734 margin = curr->
children[0]->branchSupport - curr->
children[1]->branchSupport;
739 if (best->
span.startID() > curr->
children[1]->span.startID())
745 if (best && ((margin > uncommitted) || (uncommitted == 0)))
754 return curr->
span.tip();
779 res[
"trie"] =
root_->getJson();
782 res[
"seq_support"][
to_string(seq)] = sup;
795 while (!nodes.
empty())
797 Node const* curr = nodes.
top();
812 for (
auto const& child : curr->
children)
814 if (child->parent != curr)
817 support += child->branchSupport;
818 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