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/basics/tagged_integer.h>
25 #include <ripple/json/json_value.h>
26 #include <boost/optional.hpp>
37 template <
class Ledger>
41 using Seq =
typename Ledger::Seq;
42 using ID =
typename Ledger::ID;
73 namespace ledger_trie_detail {
76 template <
class Ledger>
79 using Seq =
typename Ledger::Seq;
80 using ID =
typename Ledger::ID;
119 boost::optional<Span>
126 boost::optional<Span>
170 boost::optional<Span>
183 return o << s.
tip().id <<
"[" << s.
start_ <<
"," << s.
end_ <<
")";
198 template <
class Ledger>
231 return curr.get() == child;
251 res[
"span"] = sps.
str();
261 cs.
append(child->getJson());
346 template <
class Ledger>
349 using Seq =
typename Ledger::Seq;
350 using ID =
typename Ledger::ID;
375 Seq pos = curr->
span.diff(ledger);
381 while (!done && pos == curr->
span.end())
387 auto const childPos = child->span.diff(ledger);
411 if (ledger.id() == parent->span.tip().id)
413 for (
auto const& child : parent->children)
435 dumpImpl(o, child, offset + 1 + ss.
str().size() + 2);
452 auto const [loc, diffSeq] =
find(ledger);
472 boost::optional<Span> prefix = loc->
span.before(diffSeq);
473 boost::optional<Span> oldSuffix = loc->span.from(diffSeq);
474 boost::optional<Span> newSuffix =
Span{ledger}.from(diffSeq);
486 auto newNode = std::make_unique<Node>(*oldSuffix);
487 newNode->tipSupport = loc->tipSupport;
488 newNode->branchSupport = loc->branchSupport;
489 newNode->children = std::move(loc->children);
490 assert(loc->children.empty());
492 child->parent = newNode.get();
497 newNode->parent = loc;
498 loc->children.emplace_back(std::move(newNode));
511 auto newNode = std::make_unique<Node>(*newSuffix);
512 newNode->parent = loc;
514 incNode = newNode.get();
515 loc->
children.push_back(std::move(newNode));
522 incNode = incNode->
parent;
557 decNode = decNode->
parent;
572 child->span = merge(loc->
span, child->span);
573 child->parent = parent;
574 parent->
children.emplace_back(std::move(child));
593 return loc->tipSupport;
612 if (!(diffSeq > ledger.
seq() && ledger.
seq() < loc->
span.end()))
677 boost::optional<SpanTip<Ledger>>
690 while (curr && !done)
700 uncommittedIt->first <
std::max(nextSeq, largestIssued))
702 uncommitted += uncommittedIt->second;
707 while (nextSeq < curr->span.end() &&
712 uncommittedIt->first < curr->
span.end())
714 nextSeq = uncommittedIt->first +
Seq{1};
715 uncommitted += uncommittedIt->second;
719 nextSeq = curr->
span.end();
723 if (nextSeq < curr->span.end())
724 return curr->
span.before(nextSeq)->tip();
729 Node* best =
nullptr;
746 return std::make_tuple(
747 a->branchSupport, a->span.startID()) >
749 b->branchSupport, b->span.startID());
753 margin = curr->
children[0]->branchSupport -
759 if (best->
span.startID() > curr->
children[1]->span.startID())
765 if (best && ((margin > uncommitted) || (uncommitted == 0)))
770 return curr->
span.tip();
778 return !
root ||
root->branchSupport == 0;
795 res[
"trie"] =
root->getJson();
798 res[
"seq_support"][
to_string(seq)] = sup;
811 while (!nodes.
empty())
813 Node const* curr = nodes.
top();
827 expectedSeqSupport[curr->
span.end() -
Seq{1}] +=
830 for (
auto const& child : curr->
children)
832 if (child->parent != curr)
835 support += child->branchSupport;
836 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.
boost::optional< SpanTip< Ledger > > getPreferred(Seq const largestIssued) const
Return the preferred ledger ID.
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::string to_string(ListDisposition disposition)
boost::optional< Span > from(Seq spot) const
T partial_sort(T... args)
void dump(std::ostream &o) const
Dump an ascii representation of the trie to the stream.
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.
boost::optional< Span > sub(Seq from, Seq to) const
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.
friend std::ostream & operator<<(std::ostream &o, Node const &s)
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
boost::optional< Span > before(Seq spot) const
Span & operator=(Span const &)=default