rippled
LedgerTrie.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2017 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #ifndef RIPPLE_APP_CONSENSUS_LEDGERS_TRIE_H_INCLUDED
21 #define RIPPLE_APP_CONSENSUS_LEDGERS_TRIE_H_INCLUDED
22 
23 #include <ripple/basics/ToString.h>
24 #include <ripple/json/json_value.h>
25 #include <algorithm>
26 #include <memory>
27 #include <optional>
28 #include <sstream>
29 #include <stack>
30 #include <vector>
31 
32 namespace ripple {
33 
36 template <class Ledger>
37 class SpanTip
38 {
39 public:
40  using Seq = typename Ledger::Seq;
41  using ID = typename Ledger::ID;
42 
43  SpanTip(Seq s, ID i, Ledger const lgr)
44  : seq{s}, id{i}, ledger{std::move(lgr)}
45  {
46  }
47 
48  // The sequence number of the tip ledger
50  // The ID of the tip ledger
51  ID id;
52 
61  ID
62  ancestor(Seq const& s) const
63  {
64  assert(s <= seq);
65  return ledger[s];
66  }
67 
68 private:
69  Ledger const ledger;
70 };
71 
72 namespace ledger_trie_detail {
73 
74 // Represents a span of ancestry of a ledger
75 template <class Ledger>
76 class Span
77 {
78  using Seq = typename Ledger::Seq;
79  using ID = typename Ledger::ID;
80 
81  // The span is the half-open interval [start,end) of ledger_
82  Seq start_{0};
83  Seq end_{1};
85 
86 public:
87  Span() : ledger_{typename Ledger::MakeGenesis{}}
88  {
89  // Require default ledger to be genesis seq
90  assert(ledger_.seq() == start_);
91  }
92 
93  Span(Ledger ledger)
94  : start_{0}, end_{ledger.seq() + Seq{1}}, ledger_{std::move(ledger)}
95  {
96  }
97 
98  Span(Span const& s) = default;
99  Span(Span&& s) = default;
100  Span&
101  operator=(Span const&) = default;
102  Span&
103  operator=(Span&&) = default;
104 
105  Seq
106  start() const
107  {
108  return start_;
109  }
110 
111  Seq
112  end() const
113  {
114  return end_;
115  }
116 
117  // Return the Span from [spot,end_) or none if no such valid span
119  from(Seq spot) const
120  {
121  return sub(spot, end_);
122  }
123 
124  // Return the Span from [start_,spot) or none if no such valid span
126  before(Seq spot) const
127  {
128  return sub(start_, spot);
129  }
130 
131  // Return the ID of the ledger that starts this span
132  ID
133  startID() const
134  {
135  return ledger_[start_];
136  }
137 
138  // Return the ledger sequence number of the first possible difference
139  // between this span and a given ledger.
140  Seq
141  diff(Ledger const& o) const
142  {
143  return clamp(mismatch(ledger_, o));
144  }
145 
146  // The tip of this span
148  tip() const
149  {
150  Seq tipSeq{end_ - Seq{1}};
151  return SpanTip<Ledger>{tipSeq, ledger_[tipSeq], ledger_};
152  }
153 
154 private:
155  Span(Seq start, Seq end, Ledger const& l)
156  : start_{start}, end_{end}, ledger_{l}
157  {
158  // Spans cannot be empty
159  assert(start < end);
160  }
161 
162  Seq
163  clamp(Seq val) const
164  {
165  return std::min(std::max(start_, val), end_);
166  }
167 
168  // Return a span of this over the half-open interval [from,to)
170  sub(Seq from, Seq to) const
171  {
172  Seq newFrom = clamp(from);
173  Seq newTo = clamp(to);
174  if (newFrom < newTo)
175  return Span(newFrom, newTo, ledger_);
176  return std::nullopt;
177  }
178 
179  friend std::ostream&
181  {
182  return o << s.tip().id << "[" << s.start_ << "," << s.end_ << ")";
183  }
184 
185  friend Span
186  merge(Span const& a, Span const& b)
187  {
188  // Return combined span, using ledger_ from higher sequence span
189  if (a.end_ < b.end_)
190  return Span(std::min(a.start_, b.start_), b.end_, b.ledger_);
191 
192  return Span(std::min(a.start_, b.start_), a.end_, a.ledger_);
193  }
194 };
195 
196 // A node in the trie
197 template <class Ledger>
198 struct Node
199 {
200  Node() = default;
201 
202  explicit Node(Ledger const& l) : span{l}, tipSupport{1}, branchSupport{1}
203  {
204  }
205 
206  explicit Node(Span<Ledger> s) : span{std::move(s)}
207  {
208  }
209 
213 
215  Node* parent = nullptr;
216 
223  void
224  erase(Node const* child)
225  {
226  auto it = std::find_if(
227  children.begin(),
228  children.end(),
229  [child](std::unique_ptr<Node> const& curr) {
230  return curr.get() == child;
231  });
232  assert(it != children.end());
233  std::swap(*it, children.back());
234  children.pop_back();
235  }
236 
237  friend std::ostream&
239  {
240  return o << s.span << "(T:" << s.tipSupport << ",B:" << s.branchSupport
241  << ")";
242  }
243 
245  getJson() const
246  {
247  Json::Value res;
248  std::stringstream sps;
249  sps << span;
250  res["span"] = sps.str();
251  res["startID"] = to_string(span.startID());
252  res["seq"] = static_cast<std::uint32_t>(span.tip().seq);
253  res["tipSupport"] = tipSupport;
254  res["branchSupport"] = branchSupport;
255  if (!children.empty())
256  {
257  Json::Value& cs = (res["children"] = Json::arrayValue);
258  for (auto const& child : children)
259  {
260  cs.append(child->getJson());
261  }
262  }
263  return res;
264  }
265 };
266 } // namespace ledger_trie_detail
267 
345 template <class Ledger>
347 {
348  using Seq = typename Ledger::Seq;
349  using ID = typename Ledger::ID;
350 
353 
354  // The root of the trie. The root is allowed to break the no-single child
355  // invariant.
357 
358  // Count of the tip support for each sequence number
360 
368  find(Ledger const& ledger) const
369  {
370  Node* curr = root.get();
371 
372  // Root is always defined and is in common with all ledgers
373  assert(curr);
374  Seq pos = curr->span.diff(ledger);
375 
376  bool done = false;
377 
378  // Continue searching for a better span as long as the current position
379  // matches the entire span
380  while (!done && pos == curr->span.end())
381  {
382  done = true;
383  // Find the child with the longest ancestry match
384  for (std::unique_ptr<Node> const& child : curr->children)
385  {
386  auto const childPos = child->span.diff(ledger);
387  if (childPos > pos)
388  {
389  done = false;
390  pos = childPos;
391  curr = child.get();
392  break;
393  }
394  }
395  }
396  return std::make_pair(curr, pos);
397  }
398 
405  Node*
406  findByLedgerID(Ledger const& ledger, Node* parent = nullptr) const
407  {
408  if (!parent)
409  parent = root.get();
410  if (ledger.id() == parent->span.tip().id)
411  return parent;
412  for (auto const& child : parent->children)
413  {
414  auto cl = findByLedgerID(ledger, child.get());
415  if (cl)
416  return cl;
417  }
418  return nullptr;
419  }
420 
421  void
422  dumpImpl(std::ostream& o, std::unique_ptr<Node> const& curr, int offset)
423  const
424  {
425  if (curr)
426  {
427  if (offset > 0)
428  o << std::setw(offset) << "|-";
429 
431  ss << *curr;
432  o << ss.str() << std::endl;
433  for (std::unique_ptr<Node> const& child : curr->children)
434  dumpImpl(o, child, offset + 1 + ss.str().size() + 2);
435  }
436  }
437 
438 public:
439  LedgerTrie() : root{std::make_unique<Node>()}
440  {
441  }
442 
448  void
449  insert(Ledger const& ledger, std::uint32_t count = 1)
450  {
451  auto const [loc, diffSeq] = find(ledger);
452 
453  // There is always a place to insert
454  assert(loc);
455 
456  // Node from which to start incrementing branchSupport
457  Node* incNode = loc;
458 
459  // loc->span has the longest common prefix with Span{ledger} of all
460  // existing nodes in the trie. The optional<Span>'s below represent
461  // the possible common suffixes between loc->span and Span{ledger}.
462  //
463  // loc->span
464  // a b c | d e f
465  // prefix | oldSuffix
466  //
467  // Span{ledger}
468  // a b c | g h i
469  // prefix | newSuffix
470 
471  std::optional<Span> prefix = loc->span.before(diffSeq);
472  std::optional<Span> oldSuffix = loc->span.from(diffSeq);
473  std::optional<Span> newSuffix = Span{ledger}.from(diffSeq);
474 
475  if (oldSuffix)
476  {
477  // Have
478  // abcdef -> ....
479  // Inserting
480  // abc
481  // Becomes
482  // abc -> def -> ...
483 
484  // Create oldSuffix node that takes over loc
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());
490  for (std::unique_ptr<Node>& child : newNode->children)
491  child->parent = newNode.get();
492 
493  // Loc truncates to prefix and newNode is its child
494  assert(prefix);
495  loc->span = *prefix;
496  newNode->parent = loc;
497  loc->children.emplace_back(std::move(newNode));
498  loc->tipSupport = 0;
499  }
500  if (newSuffix)
501  {
502  // Have
503  // abc -> ...
504  // Inserting
505  // abcdef-> ...
506  // Becomes
507  // abc -> ...
508  // \-> def
509 
510  auto newNode = std::make_unique<Node>(*newSuffix);
511  newNode->parent = loc;
512  // increment support starting from the new node
513  incNode = newNode.get();
514  loc->children.push_back(std::move(newNode));
515  }
516 
517  incNode->tipSupport += count;
518  while (incNode)
519  {
520  incNode->branchSupport += count;
521  incNode = incNode->parent;
522  }
523 
524  seqSupport[ledger.seq()] += count;
525  }
526 
534  bool
535  remove(Ledger const& ledger, std::uint32_t count = 1)
536  {
537  Node* loc = findByLedgerID(ledger);
538  // Must be exact match with tip support
539  if (!loc || loc->tipSupport == 0)
540  return false;
541 
542  // found our node, remove it
543  count = std::min(count, loc->tipSupport);
544  loc->tipSupport -= count;
545 
546  auto const it = seqSupport.find(ledger.seq());
547  assert(it != seqSupport.end() && it->second >= count);
548  it->second -= count;
549  if (it->second == 0)
550  seqSupport.erase(it->first);
551 
552  Node* decNode = loc;
553  while (decNode)
554  {
555  decNode->branchSupport -= count;
556  decNode = decNode->parent;
557  }
558 
559  while (loc->tipSupport == 0 && loc != root.get())
560  {
561  Node* parent = loc->parent;
562  if (loc->children.empty())
563  {
564  // this node can be erased
565  parent->erase(loc);
566  }
567  else if (loc->children.size() == 1)
568  {
569  // This node can be combined with its child
570  std::unique_ptr<Node> child = std::move(loc->children.front());
571  child->span = merge(loc->span, child->span);
572  child->parent = parent;
573  parent->children.emplace_back(std::move(child));
574  parent->erase(loc);
575  }
576  else
577  break;
578  loc = parent;
579  }
580  return true;
581  }
582 
589  tipSupport(Ledger const& ledger) const
590  {
591  if (auto const* loc = findByLedgerID(ledger))
592  return loc->tipSupport;
593  return 0;
594  }
595 
603  branchSupport(Ledger const& ledger) const
604  {
605  Node const* loc = findByLedgerID(ledger);
606  if (!loc)
607  {
608  Seq diffSeq;
609  std::tie(loc, diffSeq) = find(ledger);
610  // Check that ledger is a proper prefix of loc
611  if (!(diffSeq > ledger.seq() && ledger.seq() < loc->span.end()))
612  loc = nullptr;
613  }
614  return loc ? loc->branchSupport : 0;
615  }
616 
677  getPreferred(Seq const largestIssued) const
678  {
679  if (empty())
680  return std::nullopt;
681 
682  Node* curr = root.get();
683 
684  bool done = false;
685 
686  std::uint32_t uncommitted = 0;
687  auto uncommittedIt = seqSupport.begin();
688 
689  while (curr && !done)
690  {
691  // Within a single span, the preferred by branch strategy is simply
692  // to continue along the span as long as the branch support of
693  // the next ledger exceeds the uncommitted support for that ledger.
694  {
695  // Add any initial uncommitted support prior for ledgers
696  // earlier than nextSeq or earlier than largestIssued
697  Seq nextSeq = curr->span.start() + Seq{1};
698  while (uncommittedIt != seqSupport.end() &&
699  uncommittedIt->first < std::max(nextSeq, largestIssued))
700  {
701  uncommitted += uncommittedIt->second;
702  uncommittedIt++;
703  }
704 
705  // Advance nextSeq along the span
706  while (nextSeq < curr->span.end() &&
707  curr->branchSupport > uncommitted)
708  {
709  // Jump to the next seqSupport change
710  if (uncommittedIt != seqSupport.end() &&
711  uncommittedIt->first < curr->span.end())
712  {
713  nextSeq = uncommittedIt->first + Seq{1};
714  uncommitted += uncommittedIt->second;
715  uncommittedIt++;
716  }
717  else // otherwise we jump to the end of the span
718  nextSeq = curr->span.end();
719  }
720  // We did not consume the entire span, so we have found the
721  // preferred ledger
722  if (nextSeq < curr->span.end())
723  return curr->span.before(nextSeq)->tip();
724  }
725 
726  // We have reached the end of the current span, so we need to
727  // find the best child
728  Node* best = nullptr;
729  std::uint32_t margin = 0;
730  if (curr->children.size() == 1)
731  {
732  best = curr->children[0].get();
733  margin = best->branchSupport;
734  }
735  else if (!curr->children.empty())
736  {
737  // Sort placing children with largest branch support in the
738  // front, breaking ties with the span's starting ID
740  curr->children.begin(),
741  curr->children.begin() + 2,
742  curr->children.end(),
743  [](std::unique_ptr<Node> const& a,
744  std::unique_ptr<Node> const& b) {
745  return std::make_tuple(
746  a->branchSupport, a->span.startID()) >
747  std::make_tuple(
748  b->branchSupport, b->span.startID());
749  });
750 
751  best = curr->children[0].get();
752  margin = curr->children[0]->branchSupport -
753  curr->children[1]->branchSupport;
754 
755  // If best holds the tie-breaker, gets one larger margin
756  // since the second best needs additional branchSupport
757  // to overcome the tie
758  if (best->span.startID() > curr->children[1]->span.startID())
759  margin++;
760  }
761 
762  // If the best child has margin exceeding the uncommitted support,
763  // continue from that child, otherwise we are done
764  if (best && ((margin > uncommitted) || (uncommitted == 0)))
765  curr = best;
766  else // current is the best
767  done = true;
768  }
769  return curr->span.tip();
770  }
771 
774  bool
775  empty() const
776  {
777  return !root || root->branchSupport == 0;
778  }
779 
782  void
783  dump(std::ostream& o) const
784  {
785  dumpImpl(o, root, 0);
786  }
787 
791  getJson() const
792  {
793  Json::Value res;
794  res["trie"] = root->getJson();
795  res["seq_support"] = Json::objectValue;
796  for (auto const& [seq, sup] : seqSupport)
797  res["seq_support"][to_string(seq)] = sup;
798  return res;
799  }
800 
803  bool
805  {
806  std::map<Seq, std::uint32_t> expectedSeqSupport;
807 
809  nodes.push(root.get());
810  while (!nodes.empty())
811  {
812  Node const* curr = nodes.top();
813  nodes.pop();
814  if (!curr)
815  continue;
816 
817  // Node with 0 tip support must have multiple children
818  // unless it is the root node
819  if (curr != root.get() && curr->tipSupport == 0 &&
820  curr->children.size() < 2)
821  return false;
822 
823  // branchSupport = tipSupport + sum(child->branchSupport)
824  std::size_t support = curr->tipSupport;
825  if (curr->tipSupport != 0)
826  expectedSeqSupport[curr->span.end() - Seq{1}] +=
827  curr->tipSupport;
828 
829  for (auto const& child : curr->children)
830  {
831  if (child->parent != curr)
832  return false;
833 
834  support += child->branchSupport;
835  nodes.push(child.get());
836  }
837  if (support != curr->branchSupport)
838  return false;
839  }
840  return expectedSeqSupport == seqSupport;
841  }
842 };
843 
844 } // namespace ripple
845 #endif
ripple::ledger_trie_detail::Node::span
Span< Ledger > span
Definition: LedgerTrie.h:210
ripple::mismatch
RCLValidatedLedger::Seq mismatch(RCLValidatedLedger const &a, RCLValidatedLedger const &b)
Definition: RCLValidations.cpp:98
sstream
ripple::LedgerTrie::branchSupport
std::uint32_t branchSupport(Ledger const &ledger) const
Return the count of branch support for the specific ledger.
Definition: LedgerTrie.h:603
ripple::ledger_trie_detail::Span< ripple::Ledger >::Seq
typename ripple::Ledger ::Seq Seq
Definition: LedgerTrie.h:78
ripple::SpanTip
The tip of a span of ledger ancestry.
Definition: LedgerTrie.h:37
ripple::ledger_trie_detail::Span::end_
Seq end_
Definition: LedgerTrie.h:83
ripple::LedgerTrie::getJson
Json::Value getJson() const
Dump JSON representation of trie state.
Definition: LedgerTrie.h:791
ripple::SpanTip::SpanTip
SpanTip(Seq s, ID i, Ledger const lgr)
Definition: LedgerTrie.h:43
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
std::pair
vector
std::find_if
T find_if(T... args)
ripple::LedgerTrie::checkInvariants
bool checkInvariants() const
Check the compressed trie and support invariants.
Definition: LedgerTrie.h:804
stack
ripple::LedgerTrie::tipSupport
std::uint32_t tipSupport(Ledger const &ledger) const
Return count of tip support for the specific ledger.
Definition: LedgerTrie.h:589
std::stringstream
STL class.
ripple::ledger_trie_detail::Span::operator<<
friend std::ostream & operator<<(std::ostream &o, Span const &s)
Definition: LedgerTrie.h:180
ripple::ledger_trie_detail::Span
Definition: LedgerTrie.h:76
ripple::LedgerTrie::ID
typename Ledger::ID ID
Definition: LedgerTrie.h:349
ripple::ledger_trie_detail::Span::sub
std::optional< Span > sub(Seq from, Seq to) const
Definition: LedgerTrie.h:170
algorithm
std::partial_sort
T partial_sort(T... args)
std::tie
T tie(T... args)
ripple::ledger_trie_detail::Node::Node
Node(Ledger const &l)
Definition: LedgerTrie.h:202
ripple::SpanTip::id
ID id
Definition: LedgerTrie.h:51
ripple::LedgerTrie::dump
void dump(std::ostream &o) const
Dump an ascii representation of the trie to the stream.
Definition: LedgerTrie.h:783
ripple::LedgerTrie::getPreferred
std::optional< SpanTip< Ledger > > getPreferred(Seq const largestIssued) const
Return the preferred ledger ID.
Definition: LedgerTrie.h:677
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
ripple::LedgerTrie::insert
void insert(Ledger const &ledger, std::uint32_t count=1)
Insert and/or increment the support for the given ledger.
Definition: LedgerTrie.h:449
ripple::ledger_trie_detail::Node::children
std::vector< std::unique_ptr< Node > > children
Definition: LedgerTrie.h:214
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::Ledger
Holds a ledger.
Definition: Ledger.h:76
ripple::ledger_trie_detail::Node::branchSupport
std::uint32_t branchSupport
Definition: LedgerTrie.h:212
ripple::ledger_trie_detail::Span< ripple::Ledger >::ID
typename ripple::Ledger ::ID ID
Definition: LedgerTrie.h:79
std::ostream
STL class.
ripple::SpanTip::ancestor
ID ancestor(Seq const &s) const
Lookup the ID of an ancestor of the tip ledger.
Definition: LedgerTrie.h:62
ripple::SpanTip::ledger
const Ledger ledger
Definition: LedgerTrie.h:69
ripple::ledger_trie_detail::Node
Definition: LedgerTrie.h:198
ripple::LedgerTrie::seqSupport
std::map< Seq, std::uint32_t > seqSupport
Definition: LedgerTrie.h:359
ripple::LedgerTrie::Seq
typename Ledger::Seq Seq
Definition: LedgerTrie.h:348
std::stack::pop
T pop(T... args)
ripple::ledger_trie_detail::Span::start
Seq start() const
Definition: LedgerTrie.h:106
std::stack::top
T top(T... args)
ripple::ledger_trie_detail::Node::parent
Node * parent
Definition: LedgerTrie.h:215
ripple::ledger_trie_detail::Span::Span
Span(Seq start, Seq end, Ledger const &l)
Definition: LedgerTrie.h:155
ripple::ledger_trie_detail::Span::tip
SpanTip< Ledger > tip() const
Definition: LedgerTrie.h:148
ripple::ledger_trie_detail::Span::end
Seq end() const
Definition: LedgerTrie.h:112
std::map::erase
T erase(T... args)
ripple::ledger_trie_detail::Node::Node
Node(Span< Ledger > s)
Definition: LedgerTrie.h:206
ripple::LedgerTrie::root
std::unique_ptr< Node > root
Definition: LedgerTrie.h:356
ripple::SpanTip::ID
typename Ledger::ID ID
Definition: LedgerTrie.h:41
std::uint32_t
ripple::ledger_trie_detail::Span::Span
Span()
Definition: LedgerTrie.h:87
std::map< Seq, std::uint32_t >
ripple::LedgerTrie::findByLedgerID
Node * findByLedgerID(Ledger const &ledger, Node *parent=nullptr) const
Find the node in the trie with an exact match to the given ledger ID.
Definition: LedgerTrie.h:406
ripple::ledger_trie_detail::Node::tipSupport
std::uint32_t tipSupport
Definition: LedgerTrie.h:211
memory
ripple::ledger_trie_detail::Span::diff
Seq diff(Ledger const &o) const
Definition: LedgerTrie.h:141
ripple::ledger_trie_detail::Span::merge
friend Span merge(Span const &a, Span const &b)
Definition: LedgerTrie.h:186
std::swap
T swap(T... args)
std::min
T min(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::LedgerTrie
Ancestry trie of ledgers.
Definition: LedgerTrie.h:346
std::endl
T endl(T... args)
ripple::ReadView::seq
LedgerIndex seq() const
Returns the sequence number of the base ledger.
Definition: ReadView.h:193
std::map::begin
T begin(T... args)
ripple::LedgerTrie::Node
ledger_trie_detail::Node< Ledger > Node
Definition: LedgerTrie.h:351
ripple::ledger_trie_detail::Span::ledger_
Ledger ledger_
Definition: LedgerTrie.h:84
ripple::LedgerTrie::dumpImpl
void dumpImpl(std::ostream &o, std::unique_ptr< Node > const &curr, int offset) const
Definition: LedgerTrie.h:422
ripple::ledger_trie_detail::Span::startID
ID startID() const
Definition: LedgerTrie.h:133
std::stack::empty
T empty(T... args)
std::stack::push
T push(T... args)
ripple::ledger_trie_detail::Span::clamp
Seq clamp(Seq val) const
Definition: LedgerTrie.h:163
optional
std::stringstream::str
T str(T... args)
ripple::LedgerTrie::find
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.
Definition: LedgerTrie.h:368
std::size_t
ripple::LedgerTrie::empty
bool empty() const
Return whether the trie is tracking any ledgers.
Definition: LedgerTrie.h:775
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
std::make_pair
T make_pair(T... args)
ripple::ledger_trie_detail::Node::operator<<
friend std::ostream & operator<<(std::ostream &o, Node const &s)
Definition: LedgerTrie.h:238
ripple::ledger_trie_detail::Span::before
std::optional< Span > before(Seq spot) const
Definition: LedgerTrie.h:126
std::map::end
T end(T... args)
ripple::LedgerTrie::remove
bool remove(Ledger const &ledger, std::uint32_t count=1)
Decrease support for a ledger, removing and compressing if possible.
Definition: LedgerTrie.h:535
ripple::ledger_trie_detail::Node::Node
Node()=default
std::setw
T setw(T... args)
std::max
T max(T... args)
ripple::SpanTip::seq
Seq seq
Definition: LedgerTrie.h:49
ripple::LedgerTrie::LedgerTrie
LedgerTrie()
Definition: LedgerTrie.h:439
ripple::ledger_trie_detail::Node::erase
void erase(Node const *child)
Remove the given node from this Node's children.
Definition: LedgerTrie.h:224
std::unique_ptr
STL class.
ripple::SpanTip::Seq
typename Ledger::Seq Seq
Definition: LedgerTrie.h:40
ripple::ledger_trie_detail::Node::getJson
Json::Value getJson() const
Definition: LedgerTrie.h:245
ripple::ledger_trie_detail::Span::start_
Seq start_
Definition: LedgerTrie.h:82
ripple::ledger_trie_detail::Span::Span
Span(Ledger ledger)
Definition: LedgerTrie.h:93
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::ledger_trie_detail::Span::from
std::optional< Span > from(Seq spot) const
Definition: LedgerTrie.h:119
ripple::ledger_trie_detail::Span::operator=
Span & operator=(Span const &)=default