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