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>
207 return curr.get() == child;
209 XRPL_ASSERT(it !=
children.end(),
"xrpl::Node::erase : valid input");
226 res[
"span"] = sps.
str();
236 cs.
append(child->getJson());
321template <
class Ledger>
324 using Seq =
typename Ledger::Seq;
325 using ID =
typename Ledger::ID;
349 XRPL_ASSERT(curr,
"xrpl::LedgerTrie::find : non-null root");
350 Seq pos = curr->
span.diff(ledger);
356 while (!done && pos == curr->
span.end())
362 auto const childPos = child->span.diff(ledger);
386 if (ledger.id() == parent->span.tip().id)
388 for (
auto const& child : parent->children)
409 dumpImpl(o, child, offset + 1 + ss.
str().size() + 2);
426 auto const [loc, diffSeq] =
find(ledger);
429 XRPL_ASSERT(loc,
"xrpl::LedgerTrie::insert : valid input ledger");
461 newNode->tipSupport = loc->tipSupport;
462 newNode->branchSupport = loc->branchSupport;
463 newNode->children = std::move(loc->children);
464 XRPL_ASSERT(loc->children.empty(),
"xrpl::LedgerTrie::insert : moved-from children");
466 child->parent = newNode.get();
469 XRPL_ASSERT(prefix,
"xrpl::LedgerTrie::insert : prefix is set");
471 newNode->parent = loc;
472 loc->children.emplace_back(std::move(newNode));
486 newNode->parent = loc;
488 incNode = newNode.get();
489 loc->
children.push_back(std::move(newNode));
496 incNode = incNode->
parent;
522 XRPL_ASSERT(it !=
seqSupport.
end() && it->second >= count,
"xrpl::LedgerTrie::remove : valid input ledger");
531 decNode = decNode->
parent;
546 child->span = merge(loc->
span, child->span);
547 child->parent = parent;
548 parent->
children.emplace_back(std::move(child));
567 return loc->tipSupport;
586 if (!(diffSeq > ledger.
seq() && ledger.
seq() < loc->
span.end()))
664 while (curr && !done)
675 uncommitted += uncommittedIt->second;
680 while (nextSeq < curr->span.end() && curr->
branchSupport > uncommitted)
683 if (uncommittedIt !=
seqSupport.
end() && uncommittedIt->first < curr->
span.end())
685 nextSeq = uncommittedIt->first +
Seq{1};
686 uncommitted += uncommittedIt->second;
690 nextSeq = curr->
span.end();
694 if (nextSeq < curr->span.end())
695 return curr->
span.before(nextSeq)->tip();
700 Node* best =
nullptr;
716 return std::make_tuple(a->branchSupport, a->span.startID()) >
717 std::make_tuple(b->branchSupport, b->span.startID());
721 margin = curr->
children[0]->branchSupport - curr->
children[1]->branchSupport;
726 if (best->
span.startID() > curr->
children[1]->span.startID())
732 if (best && ((margin > uncommitted) || (uncommitted == 0)))
737 return curr->
span.tip();
745 return !
root ||
root->branchSupport == 0;
762 res[
"trie"] =
root->getJson();
765 res[
"seq_support"][
to_string(seq)] = sup;
778 while (!nodes.
empty())
780 Node const* curr = nodes.
top();
795 for (
auto const& child : curr->
children)
797 if (child->parent != curr)
800 support += child->branchSupport;
801 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