rippled
Validations_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-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 #include <ripple/basics/tagged_integer.h>
21 #include <ripple/beast/clock/manual_clock.h>
22 #include <ripple/beast/unit_test.h>
23 #include <ripple/consensus/Validations.h>
24 #include <test/csf/Validation.h>
25 
26 #include <memory>
27 #include <tuple>
28 #include <type_traits>
29 #include <vector>
30 
31 namespace ripple {
32 namespace test {
33 namespace csf {
34 class Validations_test : public beast::unit_test::suite
35 {
37 
38  // Helper to convert steady_clock to a reasonable NetClock
39  // This allows a single manual clock in the unit tests
42  {
43  // We don't care about the actual epochs, but do want the
44  // generated NetClock time to be well past its epoch to ensure
45  // any subtractions are positive
46  using namespace std::chrono;
47  return NetClock::time_point(duration_cast<NetClock::duration>(
48  c.now().time_since_epoch() + 86400s));
49  }
50 
51  // Represents a node that can issue validations
52  class Node
53  {
54  clock_type const& c_;
56  bool trusted_ = true;
58  boost::optional<std::uint32_t> loadFee_;
59 
60  public:
62  {
63  }
64 
65  void
67  {
68  trusted_ = false;
69  }
70 
71  void
73  {
74  trusted_ = true;
75  }
76 
77  void
79  {
80  loadFee_ = fee;
81  }
82 
83  PeerID
84  nodeID() const
85  {
86  return nodeID_;
87  }
88 
89  void
91  {
92  signIdx_++;
93  }
94 
95  PeerKey
96  currKey() const
97  {
99  }
100 
101  PeerKey
102  masterKey() const
103  {
104  return std::make_pair(nodeID_, 0);
105  }
107  now() const
108  {
109  return toNetClock(c_);
110  }
111 
112  // Issue a new validation with given sequence number and id and
113  // with signing and seen times offset from the common clock
114  Validation
116  Ledger::ID id,
118  NetClock::duration signOffset,
119  NetClock::duration seenOffset,
120  bool full) const
121  {
122  Validation v{
123  id,
124  seq,
125  now() + signOffset,
126  now() + seenOffset,
127  currKey(),
128  nodeID_,
129  full,
130  loadFee_};
131  if (trusted_)
132  v.setTrusted();
133  return v;
134  }
135 
136  Validation
138  Ledger ledger,
139  NetClock::duration signOffset,
140  NetClock::duration seenOffset) const
141  {
142  return validate(
143  ledger.id(), ledger.seq(), signOffset, seenOffset, true);
144  }
145 
146  Validation
147  validate(Ledger ledger) const
148  {
149  return validate(
150  ledger.id(),
151  ledger.seq(),
154  true);
155  }
156 
157  Validation
158  partial(Ledger ledger) const
159  {
160  return validate(
161  ledger.id(),
162  ledger.seq(),
165  false);
166  }
167  };
168 
169  // Generic Validations adaptor
170  class Adaptor
171  {
174 
175  public:
176  // Non-locking mutex to avoid locks in generic Validations
177  struct Mutex
178  {
179  void
181  {
182  }
183 
184  void
186  {
187  }
188  };
189 
192 
194  {
195  }
196 
198  now() const
199  {
200  return toNetClock(c_);
201  }
202 
203  boost::optional<Ledger>
204  acquire(Ledger::ID const& id)
205  {
206  return oracle_.lookup(id);
207  }
208  };
209 
210  // Specialize generic Validations using the above types
212 
213  // Gather the dependencies of TestValidations in a single class and provide
214  // accessors for simplifying test logic
216  {
221 
222  public:
224  {
225  }
226 
227  ValStatus
228  add(Validation const& v)
229  {
230  return tv_.add(v.nodeID(), v);
231  }
232 
235  {
236  return tv_;
237  }
238 
239  Node
241  {
242  return Node(nextNodeId_++, clock_);
243  }
244 
246  parms() const
247  {
248  return p_;
249  }
250 
251  auto&
253  {
254  return clock_;
255  }
256  };
257 
259 
260  void
262  {
263  using namespace std::chrono_literals;
264 
265  testcase("Add validation");
267  Ledger ledgerA = h["a"];
268  Ledger ledgerAB = h["ab"];
269  Ledger ledgerAZ = h["az"];
270  Ledger ledgerABC = h["abc"];
271  Ledger ledgerABCD = h["abcd"];
272  Ledger ledgerABCDE = h["abcde"];
273 
274  {
275  TestHarness harness(h.oracle);
276  Node n = harness.makeNode();
277 
278  auto const v = n.validate(ledgerA);
279 
280  // Add a current validation
281  BEAST_EXPECT(ValStatus::current == harness.add(v));
282 
283  // Re-adding violates the increasing seq requirement for full
284  // validations
285  BEAST_EXPECT(ValStatus::badSeq == harness.add(v));
286 
287  harness.clock().advance(1s);
288 
289  BEAST_EXPECT(
290  ValStatus::current == harness.add(n.validate(ledgerAB)));
291 
292  // Test the node changing signing key
293 
294  // Confirm old ledger on hand, but not new ledger
295  BEAST_EXPECT(
296  harness.vals().numTrustedForLedger(ledgerAB.id()) == 1);
297  BEAST_EXPECT(
298  harness.vals().numTrustedForLedger(ledgerABC.id()) == 0);
299 
300  // Rotate signing keys
301  n.advanceKey();
302 
303  harness.clock().advance(1s);
304 
305  // Cannot re-do the same full validation sequence
306  BEAST_EXPECT(
307  ValStatus::badSeq == harness.add(n.validate(ledgerAB)));
308  // Cannot send the same partial validation sequence
309  BEAST_EXPECT(ValStatus::badSeq == harness.add(n.partial(ledgerAB)));
310 
311  // Now trusts the newest ledger too
312  harness.clock().advance(1s);
313  BEAST_EXPECT(
314  ValStatus::current == harness.add(n.validate(ledgerABC)));
315  BEAST_EXPECT(
316  harness.vals().numTrustedForLedger(ledgerAB.id()) == 1);
317  BEAST_EXPECT(
318  harness.vals().numTrustedForLedger(ledgerABC.id()) == 1);
319 
320  // Processing validations out of order should ignore the older
321  // validation
322  harness.clock().advance(2s);
323  auto const valABCDE = n.validate(ledgerABCDE);
324 
325  harness.clock().advance(4s);
326  auto const valABCD = n.validate(ledgerABCD);
327 
328  BEAST_EXPECT(ValStatus::current == harness.add(valABCD));
329 
330  BEAST_EXPECT(ValStatus::stale == harness.add(valABCDE));
331  }
332 
333  {
334  // Process validations out of order with shifted times
335 
336  TestHarness harness(h.oracle);
337  Node n = harness.makeNode();
338 
339  // Establish a new current validation
340  BEAST_EXPECT(
341  ValStatus::current == harness.add(n.validate(ledgerA)));
342 
343  // Process a validation that has "later" seq but early sign time
344  BEAST_EXPECT(
346  harness.add(n.validate(ledgerAB, -1s, -1s)));
347 
348  // Process a validation that has a later seq and later sign
349  // time
350  BEAST_EXPECT(
352  harness.add(n.validate(ledgerABC, 1s, 1s)));
353  }
354 
355  {
356  // Test stale on arrival validations
357  TestHarness harness(h.oracle);
358  Node n = harness.makeNode();
359 
360  BEAST_EXPECT(
362  harness.add(n.validate(
363  ledgerA, -harness.parms().validationCURRENT_EARLY, 0s)));
364 
365  BEAST_EXPECT(
367  harness.add(n.validate(
368  ledgerA, harness.parms().validationCURRENT_WALL, 0s)));
369 
370  BEAST_EXPECT(
372  harness.add(n.validate(
373  ledgerA, 0s, harness.parms().validationCURRENT_LOCAL)));
374  }
375 
376  {
377  // Test that full or partials cannot be sent for older sequence
378  // numbers, unless time-out has happened
379  for (bool doFull : {true, false})
380  {
381  TestHarness harness(h.oracle);
382  Node n = harness.makeNode();
383 
384  auto process = [&](Ledger& lgr) {
385  if (doFull)
386  return harness.add(n.validate(lgr));
387  return harness.add(n.partial(lgr));
388  };
389 
390  BEAST_EXPECT(ValStatus::current == process(ledgerABC));
391  harness.clock().advance(1s);
392  BEAST_EXPECT(ledgerAB.seq() < ledgerABC.seq());
393  BEAST_EXPECT(ValStatus::badSeq == process(ledgerAB));
394 
395  // If we advance far enough for AB to expire, we can fully
396  // validate or partially validate that sequence number again
397  BEAST_EXPECT(ValStatus::conflicting == process(ledgerAZ));
398  harness.clock().advance(
399  harness.parms().validationSET_EXPIRES + 1ms);
400  BEAST_EXPECT(ValStatus::current == process(ledgerAZ));
401  }
402  }
403  }
404 
405  void
407  {
408  testcase("Stale validation");
409  // Verify validation becomes stale based solely on time passing, but
410  // use different functions to trigger the check for staleness
411 
413  Ledger ledgerA = h["a"];
414  Ledger ledgerAB = h["ab"];
415 
416  using Trigger = std::function<void(TestValidations&)>;
417 
418  std::vector<Trigger> triggers = {
419  [&](TestValidations& vals) { vals.currentTrusted(); },
420  [&](TestValidations& vals) { vals.getCurrentNodeIDs(); },
421  [&](TestValidations& vals) { vals.getPreferred(genesisLedger); },
422  [&](TestValidations& vals) {
423  vals.getNodesAfter(ledgerA, ledgerA.id());
424  }};
425  for (Trigger trigger : triggers)
426  {
427  TestHarness harness(h.oracle);
428  Node n = harness.makeNode();
429 
430  BEAST_EXPECT(
431  ValStatus::current == harness.add(n.validate(ledgerAB)));
432  trigger(harness.vals());
433  BEAST_EXPECT(
434  harness.vals().getNodesAfter(ledgerA, ledgerA.id()) == 1);
435  BEAST_EXPECT(
436  harness.vals().getPreferred(genesisLedger) ==
437  std::make_pair(ledgerAB.seq(), ledgerAB.id()));
438  harness.clock().advance(harness.parms().validationCURRENT_LOCAL);
439 
440  // trigger check for stale
441  trigger(harness.vals());
442 
443  BEAST_EXPECT(
444  harness.vals().getNodesAfter(ledgerA, ledgerA.id()) == 0);
445  BEAST_EXPECT(
446  harness.vals().getPreferred(genesisLedger) == boost::none);
447  }
448  }
449 
450  void
452  {
453  // Test getting number of nodes working on a validation descending
454  // a prescribed one. This count should only be for trusted nodes, but
455  // includes partial and full validations
456 
457  using namespace std::chrono_literals;
458  testcase("Get nodes after");
459 
461  Ledger ledgerA = h["a"];
462  Ledger ledgerAB = h["ab"];
463  Ledger ledgerABC = h["abc"];
464  Ledger ledgerAD = h["ad"];
465 
466  TestHarness harness(h.oracle);
467  Node a = harness.makeNode(), b = harness.makeNode(),
468  c = harness.makeNode(), d = harness.makeNode();
469  c.untrust();
470 
471  // first round a,b,c agree, d has is partial
472  BEAST_EXPECT(ValStatus::current == harness.add(a.validate(ledgerA)));
473  BEAST_EXPECT(ValStatus::current == harness.add(b.validate(ledgerA)));
474  BEAST_EXPECT(ValStatus::current == harness.add(c.validate(ledgerA)));
475  BEAST_EXPECT(ValStatus::current == harness.add(d.partial(ledgerA)));
476 
477  for (Ledger const& ledger : {ledgerA, ledgerAB, ledgerABC, ledgerAD})
478  BEAST_EXPECT(
479  harness.vals().getNodesAfter(ledger, ledger.id()) == 0);
480 
481  harness.clock().advance(5s);
482 
483  BEAST_EXPECT(ValStatus::current == harness.add(a.validate(ledgerAB)));
484  BEAST_EXPECT(ValStatus::current == harness.add(b.validate(ledgerABC)));
485  BEAST_EXPECT(ValStatus::current == harness.add(c.validate(ledgerAB)));
486  BEAST_EXPECT(ValStatus::current == harness.add(d.partial(ledgerABC)));
487 
488  BEAST_EXPECT(harness.vals().getNodesAfter(ledgerA, ledgerA.id()) == 3);
489  BEAST_EXPECT(
490  harness.vals().getNodesAfter(ledgerAB, ledgerAB.id()) == 2);
491  BEAST_EXPECT(
492  harness.vals().getNodesAfter(ledgerABC, ledgerABC.id()) == 0);
493  BEAST_EXPECT(
494  harness.vals().getNodesAfter(ledgerAD, ledgerAD.id()) == 0);
495 
496  // If given a ledger inconsistent with the id, is still able to check
497  // using slower method
498  BEAST_EXPECT(harness.vals().getNodesAfter(ledgerAD, ledgerA.id()) == 1);
499  BEAST_EXPECT(
500  harness.vals().getNodesAfter(ledgerAD, ledgerAB.id()) == 2);
501  }
502 
503  void
505  {
506  using namespace std::chrono_literals;
507  testcase("Current trusted validations");
508 
510  Ledger ledgerA = h["a"];
511  Ledger ledgerB = h["b"];
512  Ledger ledgerAC = h["ac"];
513 
514  TestHarness harness(h.oracle);
515  Node a = harness.makeNode(), b = harness.makeNode();
516  b.untrust();
517 
518  BEAST_EXPECT(ValStatus::current == harness.add(a.validate(ledgerA)));
519  BEAST_EXPECT(ValStatus::current == harness.add(b.validate(ledgerB)));
520 
521  // Only a is trusted
522  BEAST_EXPECT(harness.vals().currentTrusted().size() == 1);
523  BEAST_EXPECT(
524  harness.vals().currentTrusted()[0].ledgerID() == ledgerA.id());
525  BEAST_EXPECT(harness.vals().currentTrusted()[0].seq() == ledgerA.seq());
526 
527  harness.clock().advance(3s);
528 
529  for (auto const& node : {a, b})
530  BEAST_EXPECT(
531  ValStatus::current == harness.add(node.validate(ledgerAC)));
532 
533  // New validation for a
534  BEAST_EXPECT(harness.vals().currentTrusted().size() == 1);
535  BEAST_EXPECT(
536  harness.vals().currentTrusted()[0].ledgerID() == ledgerAC.id());
537  BEAST_EXPECT(
538  harness.vals().currentTrusted()[0].seq() == ledgerAC.seq());
539 
540  // Pass enough time for it to go stale
541  harness.clock().advance(harness.parms().validationCURRENT_LOCAL);
542  BEAST_EXPECT(harness.vals().currentTrusted().empty());
543  }
544 
545  void
547  {
548  using namespace std::chrono_literals;
549  testcase("Current public keys");
550 
552  Ledger ledgerA = h["a"];
553  Ledger ledgerAC = h["ac"];
554 
555  TestHarness harness(h.oracle);
556  Node a = harness.makeNode(), b = harness.makeNode();
557  b.untrust();
558 
559  for (auto const& node : {a, b})
560  BEAST_EXPECT(
561  ValStatus::current == harness.add(node.validate(ledgerA)));
562 
563  {
564  hash_set<PeerID> const expectedKeys = {a.nodeID(), b.nodeID()};
565  BEAST_EXPECT(harness.vals().getCurrentNodeIDs() == expectedKeys);
566  }
567 
568  harness.clock().advance(3s);
569 
570  // Change keys and issue partials
571  a.advanceKey();
572  b.advanceKey();
573 
574  for (auto const& node : {a, b})
575  BEAST_EXPECT(
576  ValStatus::current == harness.add(node.partial(ledgerAC)));
577 
578  {
579  hash_set<PeerID> const expectedKeys = {a.nodeID(), b.nodeID()};
580  BEAST_EXPECT(harness.vals().getCurrentNodeIDs() == expectedKeys);
581  }
582 
583  // Pass enough time for them to go stale
584  harness.clock().advance(harness.parms().validationCURRENT_LOCAL);
585  BEAST_EXPECT(harness.vals().getCurrentNodeIDs().empty());
586  }
587 
588  void
590  {
591  // Test the Validations functions that calculate a value by ledger ID
592  using namespace std::chrono_literals;
593  testcase("By ledger functions");
594 
595  // Several Validations functions return a set of values associated
596  // with trusted ledgers sharing the same ledger ID. The tests below
597  // exercise this logic by saving the set of trusted Validations, and
598  // verifying that the Validations member functions all calculate the
599  // proper transformation of the available ledgers.
600 
602  TestHarness harness(h.oracle);
603 
604  Node a = harness.makeNode(), b = harness.makeNode(),
605  c = harness.makeNode(), d = harness.makeNode(),
606  e = harness.makeNode();
607 
608  c.untrust();
609  // Mix of load fees
610  a.setLoadFee(12);
611  b.setLoadFee(1);
612  c.setLoadFee(12);
613  e.setLoadFee(12);
614 
616 
617  //----------------------------------------------------------------------
618  // checkers
619  auto sorted = [](auto vec) {
620  std::sort(vec.begin(), vec.end());
621  return vec;
622  };
623  auto compare = [&]() {
624  for (auto& it : trustedValidations)
625  {
626  auto const& id = it.first;
627  auto const& expectedValidations = it.second;
628 
629  BEAST_EXPECT(
630  harness.vals().numTrustedForLedger(id) ==
631  expectedValidations.size());
632  BEAST_EXPECT(
633  sorted(harness.vals().getTrustedForLedger(id)) ==
634  sorted(expectedValidations));
635 
636  std::uint32_t baseFee = 0;
637  std::vector<uint32_t> expectedFees;
638  for (auto const& val : expectedValidations)
639  {
640  expectedFees.push_back(val.loadFee().value_or(baseFee));
641  }
642 
643  BEAST_EXPECT(
644  sorted(harness.vals().fees(id, baseFee)) ==
645  sorted(expectedFees));
646  }
647  };
648 
649  //----------------------------------------------------------------------
650  Ledger ledgerA = h["a"];
651  Ledger ledgerB = h["b"];
652  Ledger ledgerAC = h["ac"];
653 
654  // Add a dummy ID to cover unknown ledger identifiers
655  trustedValidations[Ledger::ID{100}] = {};
656 
657  // first round a,b,c agree
658  for (auto const& node : {a, b, c})
659  {
660  auto const val = node.validate(ledgerA);
661  BEAST_EXPECT(ValStatus::current == harness.add(val));
662  if (val.trusted())
663  trustedValidations[val.ledgerID()].emplace_back(val);
664  }
665  // d disagrees
666  {
667  auto const val = d.validate(ledgerB);
668  BEAST_EXPECT(ValStatus::current == harness.add(val));
669  trustedValidations[val.ledgerID()].emplace_back(val);
670  }
671  // e only issues partials
672  {
673  BEAST_EXPECT(ValStatus::current == harness.add(e.partial(ledgerA)));
674  }
675 
676  harness.clock().advance(5s);
677  // second round, a,b,c move to ledger 2
678  for (auto const& node : {a, b, c})
679  {
680  auto const val = node.validate(ledgerAC);
681  BEAST_EXPECT(ValStatus::current == harness.add(val));
682  if (val.trusted())
683  trustedValidations[val.ledgerID()].emplace_back(val);
684  }
685  // d now thinks ledger 1, but cannot re-issue a previously used seq
686  // and attempting it should generate a conflict.
687  {
688  BEAST_EXPECT(
689  ValStatus::conflicting == harness.add(d.partial(ledgerA)));
690  }
691  // e only issues partials
692  {
693  BEAST_EXPECT(
694  ValStatus::current == harness.add(e.partial(ledgerAC)));
695  }
696 
697  compare();
698  }
699 
700  void
702  {
703  // Verify expiring clears out validations stored by ledger
704  testcase("Expire validations");
706  TestHarness harness(h.oracle);
707  Node a = harness.makeNode();
708 
709  Ledger ledgerA = h["a"];
710 
711  BEAST_EXPECT(ValStatus::current == harness.add(a.validate(ledgerA)));
712  BEAST_EXPECT(harness.vals().numTrustedForLedger(ledgerA.id()));
713  harness.clock().advance(harness.parms().validationSET_EXPIRES);
714  harness.vals().expire();
715  BEAST_EXPECT(!harness.vals().numTrustedForLedger(ledgerA.id()));
716  }
717 
718  void
720  {
721  // Test final flush of validations
722  using namespace std::chrono_literals;
723  testcase("Flush validations");
724 
726  TestHarness harness(h.oracle);
727  Node a = harness.makeNode(), b = harness.makeNode(),
728  c = harness.makeNode();
729  c.untrust();
730 
731  Ledger ledgerA = h["a"];
732  Ledger ledgerAB = h["ab"];
733 
735  for (auto const& node : {a, b, c})
736  {
737  auto const val = node.validate(ledgerA);
738  BEAST_EXPECT(ValStatus::current == harness.add(val));
739  expected.emplace(node.nodeID(), val);
740  }
741 
742  // Send in a new validation for a, saving the new one into the expected
743  // map after setting the proper prior ledger ID it replaced
744  harness.clock().advance(1s);
745  auto newVal = a.validate(ledgerAB);
746  BEAST_EXPECT(ValStatus::current == harness.add(newVal));
747  expected.find(a.nodeID())->second = newVal;
748  }
749 
750  void
752  {
753  using namespace std::chrono_literals;
754  testcase("Preferred Ledger");
755 
757  TestHarness harness(h.oracle);
758  Node a = harness.makeNode(), b = harness.makeNode(),
759  c = harness.makeNode(), d = harness.makeNode();
760  c.untrust();
761 
762  Ledger ledgerA = h["a"];
763  Ledger ledgerB = h["b"];
764  Ledger ledgerAC = h["ac"];
765  Ledger ledgerACD = h["acd"];
766 
767  using Seq = Ledger::Seq;
768  using ID = Ledger::ID;
769 
770  auto pref = [](Ledger ledger) {
771  return std::make_pair(ledger.seq(), ledger.id());
772  };
773 
774  // Empty (no ledgers)
775  BEAST_EXPECT(harness.vals().getPreferred(ledgerA) == boost::none);
776 
777  // Single ledger
778  BEAST_EXPECT(ValStatus::current == harness.add(a.validate(ledgerB)));
779  BEAST_EXPECT(harness.vals().getPreferred(ledgerA) == pref(ledgerB));
780  BEAST_EXPECT(harness.vals().getPreferred(ledgerB) == pref(ledgerB));
781 
782  // Minimum valid sequence
783  BEAST_EXPECT(
784  harness.vals().getPreferred(ledgerA, Seq{10}) == ledgerA.id());
785 
786  // Untrusted doesn't impact preferred ledger
787  // (ledgerB has tie-break over ledgerA)
788  BEAST_EXPECT(ValStatus::current == harness.add(b.validate(ledgerA)));
789  BEAST_EXPECT(ValStatus::current == harness.add(c.validate(ledgerA)));
790  BEAST_EXPECT(ledgerB.id() > ledgerA.id());
791  BEAST_EXPECT(harness.vals().getPreferred(ledgerA) == pref(ledgerB));
792  BEAST_EXPECT(harness.vals().getPreferred(ledgerB) == pref(ledgerB));
793 
794  // Partial does break ties
795  BEAST_EXPECT(ValStatus::current == harness.add(d.partial(ledgerA)));
796  BEAST_EXPECT(harness.vals().getPreferred(ledgerA) == pref(ledgerA));
797  BEAST_EXPECT(harness.vals().getPreferred(ledgerB) == pref(ledgerA));
798 
799  harness.clock().advance(5s);
800 
801  // Parent of preferred-> stick with ledger
802  for (auto const& node : {a, b, c, d})
803  BEAST_EXPECT(
804  ValStatus::current == harness.add(node.validate(ledgerAC)));
805  // Parent of preferred stays put
806  BEAST_EXPECT(harness.vals().getPreferred(ledgerA) == pref(ledgerA));
807  // Earlier different chain, switch
808  BEAST_EXPECT(harness.vals().getPreferred(ledgerB) == pref(ledgerAC));
809  // Later on chain, stays where it is
810  BEAST_EXPECT(harness.vals().getPreferred(ledgerACD) == pref(ledgerACD));
811 
812  // Any later grandchild or different chain is preferred
813  harness.clock().advance(5s);
814  for (auto const& node : {a, b, c, d})
815  BEAST_EXPECT(
816  ValStatus::current == harness.add(node.validate(ledgerACD)));
817  for (auto const& ledger : {ledgerA, ledgerB, ledgerACD})
818  BEAST_EXPECT(
819  harness.vals().getPreferred(ledger) == pref(ledgerACD));
820  }
821 
822  void
824  {
825  using namespace std::chrono_literals;
826  testcase("Get preferred LCL");
827 
829  TestHarness harness(h.oracle);
830  Node a = harness.makeNode();
831 
832  Ledger ledgerA = h["a"];
833  Ledger ledgerB = h["b"];
834  Ledger ledgerC = h["c"];
835 
836  using ID = Ledger::ID;
837  using Seq = Ledger::Seq;
838 
839  hash_map<ID, std::uint32_t> peerCounts;
840 
841  // No trusted validations or counts sticks with current ledger
842  BEAST_EXPECT(
843  harness.vals().getPreferredLCL(ledgerA, Seq{0}, peerCounts) ==
844  ledgerA.id());
845 
846  ++peerCounts[ledgerB.id()];
847 
848  // No trusted validations, rely on peer counts
849  BEAST_EXPECT(
850  harness.vals().getPreferredLCL(ledgerA, Seq{0}, peerCounts) ==
851  ledgerB.id());
852 
853  ++peerCounts[ledgerC.id()];
854  // No trusted validations, tied peers goes with larger ID
855  BEAST_EXPECT(ledgerC.id() > ledgerB.id());
856 
857  BEAST_EXPECT(
858  harness.vals().getPreferredLCL(ledgerA, Seq{0}, peerCounts) ==
859  ledgerC.id());
860 
861  peerCounts[ledgerC.id()] += 1000;
862 
863  // Single trusted always wins over peer counts
864  BEAST_EXPECT(ValStatus::current == harness.add(a.validate(ledgerA)));
865  BEAST_EXPECT(
866  harness.vals().getPreferredLCL(ledgerA, Seq{0}, peerCounts) ==
867  ledgerA.id());
868  BEAST_EXPECT(
869  harness.vals().getPreferredLCL(ledgerB, Seq{0}, peerCounts) ==
870  ledgerA.id());
871  BEAST_EXPECT(
872  harness.vals().getPreferredLCL(ledgerC, Seq{0}, peerCounts) ==
873  ledgerA.id());
874 
875  // Stick with current ledger if trusted validation ledger has too old
876  // of a sequence
877  BEAST_EXPECT(
878  harness.vals().getPreferredLCL(ledgerB, Seq{2}, peerCounts) ==
879  ledgerB.id());
880  }
881 
882  void
884  {
885  using namespace std::chrono_literals;
886  testcase("Acquire validated ledger");
887 
889  TestHarness harness(h.oracle);
890  Node a = harness.makeNode();
891  Node b = harness.makeNode();
892 
893  using ID = Ledger::ID;
894  using Seq = Ledger::Seq;
895 
896  // Validate the ledger before it is actually available
897  Validation val = a.validate(ID{2}, Seq{2}, 0s, 0s, true);
898 
899  BEAST_EXPECT(ValStatus::current == harness.add(val));
900  // Validation is available
901  BEAST_EXPECT(harness.vals().numTrustedForLedger(ID{2}) == 1);
902  // but ledger based data is not
903  BEAST_EXPECT(harness.vals().getNodesAfter(genesisLedger, ID{0}) == 0);
904  // Initial preferred branch falls back to the ledger we are trying to
905  // acquire
906  BEAST_EXPECT(
907  harness.vals().getPreferred(genesisLedger) ==
908  std::make_pair(Seq{2}, ID{2}));
909 
910  // After adding another unavailable validation, the preferred ledger
911  // breaks ties via higher ID
912  BEAST_EXPECT(
914  harness.add(b.validate(ID{3}, Seq{2}, 0s, 0s, true)));
915  BEAST_EXPECT(
916  harness.vals().getPreferred(genesisLedger) ==
917  std::make_pair(Seq{2}, ID{3}));
918 
919  // Create the ledger
920  Ledger ledgerAB = h["ab"];
921  // Now it should be available
922  BEAST_EXPECT(harness.vals().getNodesAfter(genesisLedger, ID{0}) == 1);
923 
924  // Create a validation that is not available
925  harness.clock().advance(5s);
926  Validation val2 = a.validate(ID{4}, Seq{4}, 0s, 0s, true);
927  BEAST_EXPECT(ValStatus::current == harness.add(val2));
928  BEAST_EXPECT(harness.vals().numTrustedForLedger(ID{4}) == 1);
929  BEAST_EXPECT(
930  harness.vals().getPreferred(genesisLedger) ==
931  std::make_pair(ledgerAB.seq(), ledgerAB.id()));
932 
933  // Another node requesting that ledger still doesn't change things
934  Validation val3 = b.validate(ID{4}, Seq{4}, 0s, 0s, true);
935  BEAST_EXPECT(ValStatus::current == harness.add(val3));
936  BEAST_EXPECT(harness.vals().numTrustedForLedger(ID{4}) == 2);
937  BEAST_EXPECT(
938  harness.vals().getPreferred(genesisLedger) ==
939  std::make_pair(ledgerAB.seq(), ledgerAB.id()));
940 
941  // Switch to validation that is available
942  harness.clock().advance(5s);
943  Ledger ledgerABCDE = h["abcde"];
944  BEAST_EXPECT(ValStatus::current == harness.add(a.partial(ledgerABCDE)));
945  BEAST_EXPECT(ValStatus::current == harness.add(b.partial(ledgerABCDE)));
946  BEAST_EXPECT(
947  harness.vals().getPreferred(genesisLedger) ==
948  std::make_pair(ledgerABCDE.seq(), ledgerABCDE.id()));
949  }
950 
951  void
953  {
954  testcase("NumTrustedForLedger");
956  TestHarness harness(h.oracle);
957  Node a = harness.makeNode();
958  Node b = harness.makeNode();
959  Ledger ledgerA = h["a"];
960 
961  BEAST_EXPECT(ValStatus::current == harness.add(a.partial(ledgerA)));
962  BEAST_EXPECT(harness.vals().numTrustedForLedger(ledgerA.id()) == 0);
963 
964  BEAST_EXPECT(ValStatus::current == harness.add(b.validate(ledgerA)));
965  BEAST_EXPECT(harness.vals().numTrustedForLedger(ledgerA.id()) == 1);
966  }
967 
968  void
970  {
971  testcase("SeqEnforcer");
972  using Seq = Ledger::Seq;
973  using namespace std::chrono;
974 
976  SeqEnforcer<Seq> enforcer;
977 
978  ValidationParms p;
979 
980  BEAST_EXPECT(enforcer(clock.now(), Seq{1}, p));
981  BEAST_EXPECT(enforcer(clock.now(), Seq{10}, p));
982  BEAST_EXPECT(!enforcer(clock.now(), Seq{5}, p));
983  BEAST_EXPECT(!enforcer(clock.now(), Seq{9}, p));
984  clock.advance(p.validationSET_EXPIRES - 1ms);
985  BEAST_EXPECT(!enforcer(clock.now(), Seq{1}, p));
986  clock.advance(2ms);
987  BEAST_EXPECT(enforcer(clock.now(), Seq{1}, p));
988  }
989 
990  void
992  {
993  testcase("TrustChanged");
994  using namespace std::chrono;
995 
996  auto checker = [this](
997  TestValidations& vals,
998  hash_set<PeerID> const& listed,
999  std::vector<Validation> const& trustedVals) {
1000  Ledger::ID testID = trustedVals.empty() ? this->genesisLedger.id()
1001  : trustedVals[0].ledgerID();
1002  BEAST_EXPECT(vals.currentTrusted() == trustedVals);
1003  BEAST_EXPECT(vals.getCurrentNodeIDs() == listed);
1004  BEAST_EXPECT(
1005  vals.getNodesAfter(this->genesisLedger, genesisLedger.id()) ==
1006  trustedVals.size());
1007  if (trustedVals.empty())
1008  BEAST_EXPECT(
1009  vals.getPreferred(this->genesisLedger) == boost::none);
1010  else
1011  BEAST_EXPECT(
1012  vals.getPreferred(this->genesisLedger)->second == testID);
1013  BEAST_EXPECT(vals.getTrustedForLedger(testID) == trustedVals);
1014  BEAST_EXPECT(
1015  vals.numTrustedForLedger(testID) == trustedVals.size());
1016  };
1017 
1018  {
1019  // Trusted to untrusted
1021  TestHarness harness(h.oracle);
1022  Node a = harness.makeNode();
1023  Ledger ledgerAB = h["ab"];
1024  Validation v = a.validate(ledgerAB);
1025  BEAST_EXPECT(ValStatus::current == harness.add(v));
1026 
1027  hash_set<PeerID> listed({a.nodeID()});
1028  std::vector<Validation> trustedVals({v});
1029  checker(harness.vals(), listed, trustedVals);
1030 
1031  trustedVals.clear();
1032  harness.vals().trustChanged({}, {a.nodeID()});
1033  checker(harness.vals(), listed, trustedVals);
1034  }
1035 
1036  {
1037  // Untrusted to trusted
1039  TestHarness harness(h.oracle);
1040  Node a = harness.makeNode();
1041  a.untrust();
1042  Ledger ledgerAB = h["ab"];
1043  Validation v = a.validate(ledgerAB);
1044  BEAST_EXPECT(ValStatus::current == harness.add(v));
1045 
1046  hash_set<PeerID> listed({a.nodeID()});
1047  std::vector<Validation> trustedVals;
1048  checker(harness.vals(), listed, trustedVals);
1049 
1050  trustedVals.push_back(v);
1051  harness.vals().trustChanged({a.nodeID()}, {});
1052  checker(harness.vals(), listed, trustedVals);
1053  }
1054 
1055  {
1056  // Trusted but not acquired -> untrusted
1058  TestHarness harness(h.oracle);
1059  Node a = harness.makeNode();
1060  Validation v =
1061  a.validate(Ledger::ID{2}, Ledger::Seq{2}, 0s, 0s, true);
1062  BEAST_EXPECT(ValStatus::current == harness.add(v));
1063 
1064  hash_set<PeerID> listed({a.nodeID()});
1065  std::vector<Validation> trustedVals({v});
1066  auto& vals = harness.vals();
1067  BEAST_EXPECT(vals.currentTrusted() == trustedVals);
1068  BEAST_EXPECT(
1069  vals.getPreferred(genesisLedger)->second == v.ledgerID());
1070  BEAST_EXPECT(
1071  vals.getNodesAfter(genesisLedger, genesisLedger.id()) == 0);
1072 
1073  trustedVals.clear();
1074  harness.vals().trustChanged({}, {a.nodeID()});
1075  // make acquiring ledger available
1076  h["ab"];
1077  BEAST_EXPECT(vals.currentTrusted() == trustedVals);
1078  BEAST_EXPECT(vals.getPreferred(genesisLedger) == boost::none);
1079  BEAST_EXPECT(
1080  vals.getNodesAfter(genesisLedger, genesisLedger.id()) == 0);
1081  }
1082  }
1083 
1084  void
1085  run() override
1086  {
1088  testOnStale();
1093  testExpire();
1094  testFlush();
1099  testSeqEnforcer();
1100  testTrustChanged();
1101  }
1102 };
1103 
1105 } // namespace csf
1106 } // namespace test
1107 } // namespace ripple
ripple::Validations::expire
void expire()
Expire old validation sets.
Definition: Validations.h:695
ripple::test::csf::Validations_test::TestHarness::parms
ValidationParms parms() const
Definition: Validations_test.cpp:246
ripple::test::csf::Validations_test::TestHarness
Definition: Validations_test.cpp:215
ripple::test::csf::Validations_test::Adaptor::Mutex
Definition: Validations_test.cpp:177
ripple::test::csf::Validations_test::testOnStale
void testOnStale()
Definition: Validations_test.cpp:406
ripple::test::csf::Validations_test::Node::now
NetClock::time_point now() const
Definition: Validations_test.cpp:107
ripple::test::csf::Validations_test::testCurrentTrusted
void testCurrentTrusted()
Definition: Validations_test.cpp:504
ripple::test::csf::Validations_test::Node::Node
Node(PeerID nodeID, clock_type const &c)
Definition: Validations_test.cpp:61
ripple::test::csf::Validations_test::TestHarness::clock_
beast::manual_clock< std::chrono::steady_clock > clock_
Definition: Validations_test.cpp:218
ripple::SeqEnforcer
Enforce validation increasing sequence requirement.
Definition: Validations.h:96
ripple::test::csf::LedgerOracle::lookup
boost::optional< Ledger > lookup(Ledger::ID const &id) const
Find the ledger with the given ID.
Definition: ledgers.cpp:129
ripple::test::csf::Validations_test::testFlush
void testFlush()
Definition: Validations_test.cpp:719
ripple::test::csf::Validations_test::Node::validate
Validation validate(Ledger ledger) const
Definition: Validations_test.cpp:147
ripple::test::csf::Validations_test::Node::masterKey
PeerKey masterKey() const
Definition: Validations_test.cpp:102
std::unordered_set
STL class.
std::pair< PeerID, std::uint32_t >
ripple::Validations::fees
std::vector< std::uint32_t > fees(ID const &ledgerID, std::uint32_t baseFee)
Returns fees reported by trusted full validators in the given ledger.
Definition: Validations.h:998
vector
std::unordered_map::find
T find(T... args)
ripple::Validations::trustChanged
void trustChanged(hash_set< NodeID > const &added, hash_set< NodeID > const &removed)
Update trust status of validations.
Definition: Validations.h:712
ripple::test::csf::Validations_test::TestHarness::makeNode
Node makeNode()
Definition: Validations_test.cpp:240
ripple::test::csf::Validations_test::genesisLedger
const Ledger genesisLedger
Definition: Validations_test.cpp:258
ripple::Validations::getPreferredLCL
ID getPreferredLCL(Ledger const &lcl, Seq minSeq, hash_map< ID, std::uint32_t > const &peerCounts)
Determine the preferred last closed ledger for the next consensus round.
Definition: Validations.h:853
std::chrono::duration
std::unordered_map::emplace
T emplace(T... args)
ripple::ValStatus
ValStatus
Status of newly received validation.
Definition: Validations.h:164
ripple::ValidationParms::validationCURRENT_EARLY
std::chrono::seconds validationCURRENT_EARLY
Duration pre-close in which validations are acceptable.
Definition: Validations.h:68
ripple::test::csf::Validations_test::TestHarness::add
ValStatus add(Validation const &v)
Definition: Validations_test.cpp:228
ripple::test::csf::Validations_test::Node::untrust
void untrust()
Definition: Validations_test.cpp:66
tuple
ripple::test::csf::Ledger
A ledger is a set of observed transactions and a sequence number identifying the ledger.
Definition: ledgers.h:57
ripple::test::csf::Ledger::seq
Seq seq() const
Definition: ledgers.h:172
std::function
ripple::test::csf::Validations_test::testGetNodesAfter
void testGetNodesAfter()
Definition: Validations_test.cpp:451
ripple::test::csf::Validation::nodeID
PeerID nodeID() const
Definition: Validation.h:117
std::sort
T sort(T... args)
ripple::test::csf::Validations_test::Node
Definition: Validations_test.cpp:52
ripple::test::csf::Ledger::MakeGenesis
Definition: ledgers.h:68
ripple::test::csf::Validations_test::clock_type
beast::abstract_clock< std::chrono::steady_clock > const clock_type
Definition: Validations_test.cpp:36
ripple::test::csf::LedgerHistoryHelper
Helper for writing unit tests with controlled ledger histories.
Definition: ledgers.h:320
std::vector::push_back
T push_back(T... args)
ripple::ValStatus::badSeq
@ badSeq
A validation violates the increasing seq requirement.
ripple::test::csf::Validations_test::Node::nodeID
PeerID nodeID() const
Definition: Validations_test.cpp:84
ripple::Validations::getPreferred
boost::optional< std::pair< Seq, ID > > getPreferred(Ledger const &curr)
Return the sequence number and ID of the preferred working ledger.
Definition: Validations.h:767
ripple::test::csf::Validations_test::testTrustChanged
void testTrustChanged()
Definition: Validations_test.cpp:991
ripple::test::csf::Validations_test::Adaptor::c_
clock_type & c_
Definition: Validations_test.cpp:172
ripple::test::csf::Validations_test::TestHarness::TestHarness
TestHarness(LedgerOracle &o)
Definition: Validations_test.cpp:223
ripple::test::csf::Validations_test::TestHarness::vals
TestValidations & vals()
Definition: Validations_test.cpp:234
ripple::Validations::add
ValStatus add(NodeID const &nodeID, Validation const &val)
Add a new validation.
Definition: Validations.h:611
ripple::test::csf::Validations_test::Node::partial
Validation partial(Ledger ledger) const
Definition: Validations_test.cpp:158
ripple::test::csf::Validations_test::TestHarness::clock
auto & clock()
Definition: Validations_test.cpp:252
ripple::compare
int compare(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:497
ripple::test::csf::Validations_test::Node::setLoadFee
void setLoadFee(std::uint32_t fee)
Definition: Validations_test.cpp:78
ripple::Validations::getNodesAfter
std::size_t getNodesAfter(Ledger const &ledger, ID const &ledgerID)
Count the number of current trusted validators working on a ledger after the specified one.
Definition: Validations.h:891
ripple::test::csf::Validations_test::Node::loadFee_
boost::optional< std::uint32_t > loadFee_
Definition: Validations_test.cpp:58
ripple::Validations::numTrustedForLedger
std::size_t numTrustedForLedger(ID const &ledgerID)
Count the number of trusted full validations for the given ledger.
Definition: Validations.h:954
ripple::test::csf::LedgerOracle
Oracle maintaining unique ledgers for a simulation.
Definition: ledgers.h:243
ripple::test::csf::LedgerHistoryHelper::oracle
LedgerOracle oracle
Definition: ledgers.h:322
ripple::test::csf::Validations_test::Node::advanceKey
void advanceKey()
Definition: Validations_test.cpp:90
std::chrono::time_point
ripple::ValStatus::stale
@ stale
Not current or was older than current from this node.
ripple::test::csf::Validations_test::testGetCurrentPublicKeys
void testGetCurrentPublicKeys()
Definition: Validations_test.cpp:546
ripple::ValStatus::current
@ current
This was a new validation and was added.
ripple::ValidationParms::validationCURRENT_LOCAL
std::chrono::seconds validationCURRENT_LOCAL
Duration a validation remains current after first observed.
Definition: Validations.h:61
std::uint32_t
ripple::test::csf::Validations_test::Node::c_
clock_type const & c_
Definition: Validations_test.cpp:54
ripple::ValidationParms::validationCURRENT_WALL
std::chrono::seconds validationCURRENT_WALL
The number of seconds a validation remains current after its ledger's close time.
Definition: Validations.h:53
ripple::test::csf::Validations_test::Node::validate
Validation validate(Ledger ledger, NetClock::duration signOffset, NetClock::duration seenOffset) const
Definition: Validations_test.cpp:137
ripple::Validations::getTrustedForLedger
std::vector< WrappedValidationType > getTrustedForLedger(ID const &ledgerID)
Get trusted full validations for a specific ledger.
Definition: Validations.h:975
beast::abstract_clock< std::chrono::steady_clock >
memory
ripple::test::jtx::fee
Set the fee on a JTx.
Definition: fee.h:34
ripple::test::csf::Validations_test::testTrustedByLedgerFunctions
void testTrustedByLedgerFunctions()
Definition: Validations_test.cpp:589
ripple::test::csf::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(Validations, consensus, ripple)
ripple::test::csf::Validations_test::TestHarness::nextNodeId_
PeerID nextNodeId_
Definition: Validations_test.cpp:220
ripple::ValStatus::conflicting
@ conflicting
Multiple validations for different ledgers by a single validator.
ripple::test::jtx::seq
Set the sequence number on a JTx.
Definition: seq.h:32
ripple::test::csf::Ledger::id
ID id() const
Definition: ledgers.h:166
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::csf::Validations_test::TestHarness::tv_
TestValidations tv_
Definition: Validations_test.cpp:219
ripple::test::csf::Validations_test::Node::nodeID_
PeerID nodeID_
Definition: Validations_test.cpp:55
ripple::test::csf::Validations_test::testNumTrustedForLedger
void testNumTrustedForLedger()
Definition: Validations_test.cpp:952
ripple::test::csf::Validation
Validation of a specific ledger by a specific Peer.
Definition: Validation.h:46
ripple::ValidationParms::validationSET_EXPIRES
std::chrono::seconds validationSET_EXPIRES
Duration a set of validations for a given ledger hash remain valid.
Definition: Validations.h:76
ripple::test::csf::Ledger::ID
tagged_integer< std::uint32_t, IdTag > ID
Definition: ledgers.h:66
ripple::test::csf::Validations_test::run
void run() override
Definition: Validations_test.cpp:1085
ripple::test::csf::Validations_test::Adaptor
Definition: Validations_test.cpp:170
ripple::test::csf::Validations_test::Node::signIdx_
std::size_t signIdx_
Definition: Validations_test.cpp:57
ripple::test::csf::Ledger::Seq
tagged_integer< std::uint32_t, SeqTag > Seq
Definition: ledgers.h:63
ripple::test::csf::Validations_test::testSeqEnforcer
void testSeqEnforcer()
Definition: Validations_test.cpp:969
ripple::test::csf::Validation::ledgerID
Ledger::ID ledgerID() const
Definition: Validation.h:87
ripple::Validations
Maintains current and recent ledger validations.
Definition: Application.h:90
ripple::test::csf::Validations_test::Node::validate
Validation validate(Ledger::ID id, Ledger::Seq seq, NetClock::duration signOffset, NetClock::duration seenOffset, bool full) const
Definition: Validations_test.cpp:115
ripple::test::csf::Validations_test::Adaptor::Adaptor
Adaptor(clock_type &c, LedgerOracle &o)
Definition: Validations_test.cpp:193
std::size_t
std::make_pair
T make_pair(T... args)
ripple::test::csf::Validations_test::testExpire
void testExpire()
Definition: Validations_test.cpp:701
ripple::test::csf::Validations_test::Adaptor::now
NetClock::time_point now() const
Definition: Validations_test.cpp:198
ripple::test::csf::Validations_test
Definition: Validations_test.cpp:34
ripple::test::csf::Validations_test::Node::trusted_
bool trusted_
Definition: Validations_test.cpp:56
ripple::Validations::getCurrentNodeIDs
auto getCurrentNodeIDs() -> hash_set< NodeID >
Get the set of node ids associated with current validations.
Definition: Validations.h:936
ripple::test::csf::Validations_test::TestHarness::p_
ValidationParms p_
Definition: Validations_test.cpp:217
ripple::tagged_integer< std::uint32_t, PeerIDTag >
ripple::test::csf::Validations_test::testGetPreferredLedger
void testGetPreferredLedger()
Definition: Validations_test.cpp:751
beast::manual_clock< std::chrono::steady_clock >
ripple::test::csf::Validations_test::Adaptor::Mutex::unlock
void unlock()
Definition: Validations_test.cpp:185
ripple::test::csf::Validations_test::testAcquireValidatedLedger
void testAcquireValidatedLedger()
Definition: Validations_test.cpp:883
ripple::test::csf::Validations_test::testAddValidation
void testAddValidation()
Definition: Validations_test.cpp:261
ripple::ValidationParms
Timing parameters to control validation staleness and expiration.
Definition: Validations.h:43
ripple::test::csf::Validations_test::Node::trust
void trust()
Definition: Validations_test.cpp:72
std::unordered_map
STL class.
ripple::NetClock::time_point
std::chrono::time_point< NetClock > time_point
Definition: chrono.h:54
ripple::test::csf::Validations_test::Adaptor::oracle_
LedgerOracle & oracle_
Definition: Validations_test.cpp:173
type_traits
ripple::test::csf::Validations_test::testGetPreferredLCL
void testGetPreferredLCL()
Definition: Validations_test.cpp:823
ripple::Validations::currentTrusted
std::vector< WrappedValidationType > currentTrusted()
Get the currently trusted full validations.
Definition: Validations.h:917
ripple::test::csf::Validations_test::toNetClock
static NetClock::time_point toNetClock(clock_type const &c)
Definition: Validations_test.cpp:41
ripple::test::csf::Validations_test::Node::currKey
PeerKey currKey() const
Definition: Validations_test.cpp:96
ripple::test::csf::Validations_test::Adaptor::acquire
boost::optional< Ledger > acquire(Ledger::ID const &id)
Definition: Validations_test.cpp:204
std::chrono
ripple::test::csf::Validations_test::Adaptor::Mutex::lock
void lock()
Definition: Validations_test.cpp:180