20 #ifndef RIPPLE_APP_CONSENSUS_LEDGERS_TRIE_H_INCLUDED
21 #define RIPPLE_APP_CONSENSUS_LEDGERS_TRIE_H_INCLUDED
23 #include <ripple/basics/ToString.h>
24 #include <ripple/json/json_value.h>
36 template <
class Ledger>
40 using Seq =
typename Ledger::Seq;
41 using ID =
typename Ledger::ID;
72 namespace ledger_trie_detail {
75 template <
class Ledger>
78 using Seq =
typename Ledger::Seq;
79 using ID =
typename Ledger::ID;
182 return o << s.
tip().id <<
"[" << s.
start_ <<
"," << s.
end_ <<
")";
197 template <
class Ledger>
230 return curr.get() == child;
250 res[
"span"] = sps.
str();
260 cs.
append(child->getJson());
345 template <
class Ledger>
348 using Seq =
typename Ledger::Seq;
349 using ID =
typename Ledger::ID;
374 Seq pos = curr->
span.diff(ledger);
380 while (!done && pos == curr->
span.end())
386 auto const childPos = child->span.diff(ledger);
410 if (ledger.id() == parent->span.tip().id)
412 for (
auto const& child : parent->children)
434 dumpImpl(o, child, offset + 1 + ss.
str().size() + 2);
451 auto const [loc, diffSeq] =
find(ledger);
485 auto newNode = std::make_unique<Node>(*oldSuffix);
486 newNode->tipSupport = loc->tipSupport;
487 newNode->branchSupport = loc->branchSupport;
488 newNode->children = std::move(loc->children);
489 assert(loc->children.empty());
491 child->parent = newNode.get();
496 newNode->parent = loc;
497 loc->children.emplace_back(std::move(newNode));
510 auto newNode = std::make_unique<Node>(*newSuffix);
511 newNode->parent = loc;
513 incNode = newNode.get();
514 loc->
children.push_back(std::move(newNode));
521 incNode = incNode->
parent;
556 decNode = decNode->
parent;
571 child->span = merge(loc->
span, child->span);
572 child->parent = parent;
573 parent->
children.emplace_back(std::move(child));
592 return loc->tipSupport;
611 if (!(diffSeq > ledger.
seq() && ledger.
seq() < loc->
span.end()))
689 while (curr && !done)
699 uncommittedIt->first <
std::max(nextSeq, largestIssued))
701 uncommitted += uncommittedIt->second;
706 while (nextSeq < curr->span.end() &&
711 uncommittedIt->first < curr->
span.end())
713 nextSeq = uncommittedIt->first +
Seq{1};
714 uncommitted += uncommittedIt->second;
718 nextSeq = curr->
span.end();
722 if (nextSeq < curr->span.end())
723 return curr->
span.before(nextSeq)->tip();
728 Node* best =
nullptr;
745 return std::make_tuple(
746 a->branchSupport, a->span.startID()) >
748 b->branchSupport, b->span.startID());
752 margin = curr->
children[0]->branchSupport -
758 if (best->
span.startID() > curr->
children[1]->span.startID())
764 if (best && ((margin > uncommitted) || (uncommitted == 0)))
769 return curr->
span.tip();
777 return !
root ||
root->branchSupport == 0;
794 res[
"trie"] =
root->getJson();
797 res[
"seq_support"][
to_string(seq)] = sup;
810 while (!nodes.
empty())
812 Node const* curr = nodes.
top();
826 expectedSeqSupport[curr->
span.end() -
Seq{1}] +=
829 for (
auto const& child : curr->
children)
831 if (child->parent != curr)
834 support += child->branchSupport;
835 nodes.
push(child.get());
RCLValidatedLedger::Seq mismatch(RCLValidatedLedger const &a, RCLValidatedLedger const &b)
std::uint32_t branchSupport(Ledger const &ledger) const
Return the count of branch support for the specific ledger.
typename ripple::Ledger ::Seq Seq
The tip of a span of ledger ancestry.
Json::Value getJson() const
Dump JSON representation of trie state.
SpanTip(Seq s, ID i, Ledger const lgr)
@ arrayValue
array value (ordered list)
bool checkInvariants() const
Check the compressed trie and support invariants.
std::uint32_t tipSupport(Ledger const &ledger) const
Return count of tip support for the specific ledger.
friend std::ostream & operator<<(std::ostream &o, Span const &s)
std::optional< Span > sub(Seq from, Seq to) const
T partial_sort(T... args)
void dump(std::ostream &o) const
Dump an ascii representation of the trie to the stream.
std::optional< SpanTip< Ledger > > getPreferred(Seq const largestIssued) const
Return the preferred ledger ID.
Value & append(const Value &value)
Append value to array at the end.
void insert(Ledger const &ledger, std::uint32_t count=1)
Insert and/or increment the support for the given ledger.
std::vector< std::unique_ptr< Node > > children
@ objectValue
object value (collection of name/value pairs).
std::uint32_t branchSupport
typename ripple::Ledger ::ID ID
ID ancestor(Seq const &s) const
Lookup the ID of an ancestor of the tip ledger.
std::map< Seq, std::uint32_t > seqSupport
Span(Seq start, Seq end, Ledger const &l)
SpanTip< Ledger > tip() const
std::unique_ptr< Node > root
Node * findByLedgerID(Ledger const &ledger, Node *parent=nullptr) const
Find the node in the trie with an exact match to the given ledger ID.
Seq diff(Ledger const &o) const
friend Span merge(Span const &a, Span const &b)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Ancestry trie of ledgers.
LedgerIndex seq() const
Returns the sequence number of the base ledger.
ledger_trie_detail::Node< Ledger > Node
void dumpImpl(std::ostream &o, std::unique_ptr< Node > const &curr, int offset) const
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.
bool empty() const
Return whether the trie is tracking any ledgers.
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
friend std::ostream & operator<<(std::ostream &o, Node const &s)
std::optional< Span > before(Seq spot) const
bool remove(Ledger const &ledger, std::uint32_t count=1)
Decrease support for a ledger, removing and compressing if possible.
void erase(Node const *child)
Remove the given node from this Node's children.
Json::Value getJson() const
std::optional< Span > from(Seq spot) const
Span & operator=(Span const &)=default