3#include <xrpl/basics/ToString.h>
4#include <xrpl/beast/utility/instrumentation.h>
5#include <xrpl/json/json_value.h>
19template <
class Ledger>
23 using Seq =
typename Ledger::Seq;
24 using ID =
typename Ledger::ID;
46 XRPL_ASSERT(s <=
seq,
"xrpl::SpanTip::ancestor : valid input");
54namespace ledger_trie_detail {
57template <
class Ledger>
60 using Seq =
typename Ledger::Seq;
61 using ID =
typename Ledger::ID;
72 XRPL_ASSERT(
ledger_.
seq() ==
start_,
"xrpl::Span::Span : ledger is genesis");
139 XRPL_ASSERT(
start <
end,
"xrpl::Span::Span : non-empty span input");
162 return o << s.
tip().id <<
"[" << s.
start_ <<
"," << s.
end_ <<
")";
177template <
class Ledger>
208 return curr.get() == child;
210 XRPL_ASSERT(it !=
children.end(),
"xrpl::Node::erase : valid input");
227 res[
"span"] = sps.
str();
237 cs.
append(child->getJson());
322template <
class Ledger>
325 using Seq =
typename Ledger::Seq;
326 using ID =
typename Ledger::ID;
351 XRPL_ASSERT(curr,
"xrpl::LedgerTrie::find : non-null root");
352 Seq pos = curr->
span.diff(ledger);
358 while (!done && pos == curr->
span.end())
364 auto const childPos = child->span.diff(ledger);
388 if (ledger.id() == parent->span.tip().id)
390 for (
auto const& child : parent->children)
411 dumpImpl(o, child, offset + 1 + ss.
str().size() + 2);
428 auto const [loc, diffSeq] =
find(ledger);
431 XRPL_ASSERT(loc,
"xrpl::LedgerTrie::insert : valid input ledger");
463 newNode->tipSupport = loc->tipSupport;
464 newNode->branchSupport = loc->branchSupport;
465 newNode->children = std::move(loc->children);
466 XRPL_ASSERT(loc->children.empty(),
"xrpl::LedgerTrie::insert : moved-from children");
468 child->parent = newNode.get();
471 XRPL_ASSERT(prefix,
"xrpl::LedgerTrie::insert : prefix is set");
473 newNode->parent = loc;
474 loc->children.emplace_back(std::move(newNode));
488 newNode->parent = loc;
490 incNode = newNode.get();
491 loc->
children.push_back(std::move(newNode));
498 incNode = incNode->
parent;
526 "xrpl::LedgerTrie::remove : valid input ledger");
535 decNode = decNode->
parent;
550 child->span = merge(loc->
span, child->span);
551 child->parent = parent;
552 parent->
children.emplace_back(std::move(child));
571 return loc->tipSupport;
590 if (!(diffSeq > ledger.
seq() && ledger.
seq() < loc->
span.end()))
668 while (curr && !done)
678 uncommittedIt->first <
std::max(nextSeq, largestIssued))
680 uncommitted += uncommittedIt->second;
685 while (nextSeq < curr->span.end() && curr->
branchSupport > uncommitted)
689 uncommittedIt->first < curr->
span.end())
691 nextSeq = uncommittedIt->first +
Seq{1};
692 uncommitted += uncommittedIt->second;
696 nextSeq = curr->
span.end();
700 if (nextSeq < curr->span.end())
701 return curr->
span.before(nextSeq)->tip();
706 Node* best =
nullptr;
722 return std::make_tuple(a->branchSupport, a->span.startID()) >
723 std::make_tuple(b->branchSupport, b->span.startID());
727 margin = curr->
children[0]->branchSupport - curr->
children[1]->branchSupport;
732 if (best->
span.startID() > curr->
children[1]->span.startID())
738 if (best && ((margin > uncommitted) || (uncommitted == 0)))
743 return curr->
span.tip();
751 return !
root ||
root->branchSupport == 0;
768 res[
"trie"] =
root->getJson();
771 res[
"seq_support"][
to_string(seq)] = sup;
784 while (!nodes.
empty())
786 Node const* curr = nodes.
top();
801 for (
auto const& child : curr->
children)
803 if (child->parent != curr)
806 support += child->branchSupport;
807 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