rippled
View_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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/app/ledger/Ledger.h>
21 #include <ripple/core/ConfigSections.h>
22 #include <ripple/ledger/ApplyViewImpl.h>
23 #include <ripple/ledger/OpenView.h>
24 #include <ripple/ledger/PaymentSandbox.h>
25 #include <ripple/ledger/Sandbox.h>
26 #include <ripple/protocol/Feature.h>
27 #include <ripple/protocol/Protocol.h>
28 #include <test/jtx.h>
29 #include <type_traits>
30 
31 namespace ripple {
32 namespace test {
33 
34 class View_test : public beast::unit_test::suite
35 {
36  // Convert a small integer to a key
37  static Keylet
39  {
40  return Keylet{ltACCOUNT_ROOT, uint256(id)};
41  }
42 
43  // Create SLE with key and payload
46  {
47  auto const le = std::make_shared<SLE>(k(id));
48  le->setFieldU32(sfSequence, seq);
49  return le;
50  }
51 
52  // Return payload for SLE
53  template <class T>
54  static std::uint32_t
56  {
57  return le->getFieldU32(sfSequence);
58  }
59 
60  // Set payload on SLE
61  static void
63  {
64  le->setFieldU32(sfSequence, seq);
65  }
66 
67  // Erase all state items
68  static void
69  wipe(OpenLedger& openLedger)
70  {
71  openLedger.modify([](OpenView& view, beast::Journal) {
72  // HACK!
73  boost::optional<uint256> next;
74  next.emplace(0);
75  for (;;)
76  {
77  next = view.succ(*next);
78  if (!next)
79  break;
80  view.rawErase(std::make_shared<SLE>(
81  *view.read(keylet::unchecked(*next))));
82  }
83  return true;
84  });
85  }
86 
87  static void
88  wipe(Ledger& ledger)
89  {
90  // HACK!
91  boost::optional<uint256> next;
92  next.emplace(0);
93  for (;;)
94  {
95  next = ledger.succ(*next);
96  if (!next)
97  break;
98  ledger.rawErase(
99  std::make_shared<SLE>(*ledger.read(keylet::unchecked(*next))));
100  }
101  }
102 
103  // Test succ correctness
104  void
106  ReadView const& v,
107  std::uint32_t id,
108  boost::optional<std::uint32_t> answer)
109  {
110  auto const next = v.succ(k(id).key);
111  if (answer)
112  {
113  if (BEAST_EXPECT(next))
114  BEAST_EXPECT(*next == k(*answer).key);
115  }
116  else
117  {
118  BEAST_EXPECT(!next);
119  }
120  }
121 
122  template <class T>
125  {
126  return std::make_shared<std::remove_const_t<T>>(*sp);
127  }
128 
129  // Exercise Ledger implementation of ApplyView
130  void
132  {
133  using namespace jtx;
134  Env env(*this);
135  Config config;
136  std::shared_ptr<Ledger const> const genesis = std::make_shared<Ledger>(
138  config,
140  env.app().getNodeFamily());
141  auto const ledger = std::make_shared<Ledger>(
142  *genesis, env.app().timeKeeper().closeTime());
143  wipe(*ledger);
144  ReadView& v = *ledger;
145  succ(v, 0, boost::none);
146  ledger->rawInsert(sle(1, 1));
147  BEAST_EXPECT(v.exists(k(1)));
148  BEAST_EXPECT(seq(v.read(k(1))) == 1);
149  succ(v, 0, 1);
150  succ(v, 1, boost::none);
151  ledger->rawInsert(sle(2, 2));
152  BEAST_EXPECT(seq(v.read(k(2))) == 2);
153  ledger->rawInsert(sle(3, 3));
154  BEAST_EXPECT(seq(v.read(k(3))) == 3);
155  auto s = copy(v.read(k(2)));
156  seq(s, 4);
157  ledger->rawReplace(s);
158  BEAST_EXPECT(seq(v.read(k(2))) == 4);
159  ledger->rawErase(sle(2));
160  BEAST_EXPECT(!v.exists(k(2)));
161  BEAST_EXPECT(v.exists(k(1)));
162  BEAST_EXPECT(v.exists(k(3)));
163  }
164 
165  void
167  {
168  using namespace jtx;
169  Env env(*this);
170  wipe(env.app().openLedger());
171  auto const open = env.current();
172  ApplyViewImpl v(&*open, tapNONE);
173  succ(v, 0, boost::none);
174  v.insert(sle(1));
175  BEAST_EXPECT(v.exists(k(1)));
176  BEAST_EXPECT(seq(v.read(k(1))) == 1);
177  BEAST_EXPECT(seq(v.peek(k(1))) == 1);
178  succ(v, 0, 1);
179  succ(v, 1, boost::none);
180  v.insert(sle(2, 2));
181  BEAST_EXPECT(seq(v.read(k(2))) == 2);
182  v.insert(sle(3, 3));
183  auto s = v.peek(k(3));
184  BEAST_EXPECT(seq(s) == 3);
185  s = v.peek(k(2));
186  seq(s, 4);
187  v.update(s);
188  BEAST_EXPECT(seq(v.read(k(2))) == 4);
189  v.erase(s);
190  BEAST_EXPECT(!v.exists(k(2)));
191  BEAST_EXPECT(v.exists(k(1)));
192  BEAST_EXPECT(v.exists(k(3)));
193  }
194 
195  // Exercise all succ paths
196  void
198  {
199  using namespace jtx;
200  Env env(*this);
201  wipe(env.app().openLedger());
202  auto const open = env.current();
203  ApplyViewImpl v0(&*open, tapNONE);
204  v0.insert(sle(1));
205  v0.insert(sle(2));
206  v0.insert(sle(4));
207  v0.insert(sle(7));
208  {
209  Sandbox v1(&v0);
210  v1.insert(sle(3));
211  v1.insert(sle(5));
212  v1.insert(sle(6));
213 
214  // v0: 12-4--7
215  // v1: --3-56-
216 
217  succ(v0, 0, 1);
218  succ(v0, 1, 2);
219  succ(v0, 2, 4);
220  succ(v0, 3, 4);
221  succ(v0, 4, 7);
222  succ(v0, 5, 7);
223  succ(v0, 6, 7);
224  succ(v0, 7, boost::none);
225 
226  succ(v1, 0, 1);
227  succ(v1, 1, 2);
228  succ(v1, 2, 3);
229  succ(v1, 3, 4);
230  succ(v1, 4, 5);
231  succ(v1, 5, 6);
232  succ(v1, 6, 7);
233  succ(v1, 7, boost::none);
234 
235  v1.erase(v1.peek(k(4)));
236  succ(v1, 3, 5);
237 
238  v1.erase(v1.peek(k(6)));
239  succ(v1, 5, 7);
240  succ(v1, 6, 7);
241 
242  // v0: 12----7
243  // v1: --3-5--
244 
245  v1.apply(v0);
246  }
247 
248  // v0: 123-5-7
249 
250  succ(v0, 0, 1);
251  succ(v0, 1, 2);
252  succ(v0, 2, 3);
253  succ(v0, 3, 5);
254  succ(v0, 4, 5);
255  succ(v0, 5, 7);
256  succ(v0, 6, 7);
257  succ(v0, 7, boost::none);
258  }
259 
260  void
262  {
263  using namespace jtx;
264  Env env(*this);
265  wipe(env.app().openLedger());
266  auto const open = env.current();
267  ApplyViewImpl v0(&*open, tapNONE);
268  v0.rawInsert(sle(1, 1));
269  v0.rawInsert(sle(2, 2));
270  v0.rawInsert(sle(4, 4));
271 
272  {
273  Sandbox v1(&v0);
274  v1.erase(v1.peek(k(2)));
275  v1.insert(sle(3, 3));
276  auto s = v1.peek(k(4));
277  seq(s, 5);
278  v1.update(s);
279  BEAST_EXPECT(seq(v1.read(k(1))) == 1);
280  BEAST_EXPECT(!v1.exists(k(2)));
281  BEAST_EXPECT(seq(v1.read(k(3))) == 3);
282  BEAST_EXPECT(seq(v1.read(k(4))) == 5);
283  {
284  Sandbox v2(&v1);
285  auto s2 = v2.peek(k(3));
286  seq(s2, 6);
287  v2.update(s2);
288  v2.erase(v2.peek(k(4)));
289  BEAST_EXPECT(seq(v2.read(k(1))) == 1);
290  BEAST_EXPECT(!v2.exists(k(2)));
291  BEAST_EXPECT(seq(v2.read(k(3))) == 6);
292  BEAST_EXPECT(!v2.exists(k(4)));
293  // discard v2
294  }
295  BEAST_EXPECT(seq(v1.read(k(1))) == 1);
296  BEAST_EXPECT(!v1.exists(k(2)));
297  BEAST_EXPECT(seq(v1.read(k(3))) == 3);
298  BEAST_EXPECT(seq(v1.read(k(4))) == 5);
299 
300  {
301  Sandbox v2(&v1);
302  auto s2 = v2.peek(k(3));
303  seq(s2, 6);
304  v2.update(s2);
305  v2.erase(v2.peek(k(4)));
306  BEAST_EXPECT(seq(v2.read(k(1))) == 1);
307  BEAST_EXPECT(!v2.exists(k(2)));
308  BEAST_EXPECT(seq(v2.read(k(3))) == 6);
309  BEAST_EXPECT(!v2.exists(k(4)));
310  v2.apply(v1);
311  }
312  BEAST_EXPECT(seq(v1.read(k(1))) == 1);
313  BEAST_EXPECT(!v1.exists(k(2)));
314  BEAST_EXPECT(seq(v1.read(k(3))) == 6);
315  BEAST_EXPECT(!v1.exists(k(4)));
316  v1.apply(v0);
317  }
318  BEAST_EXPECT(seq(v0.read(k(1))) == 1);
319  BEAST_EXPECT(!v0.exists(k(2)));
320  BEAST_EXPECT(seq(v0.read(k(3))) == 6);
321  BEAST_EXPECT(!v0.exists(k(4)));
322  }
323 
324  // Verify contextual information
325  void
327  {
328  using namespace jtx;
329  using namespace std::chrono;
330  {
331  Env env(*this);
332  wipe(env.app().openLedger());
333  auto const open = env.current();
334  OpenView v0(open.get());
335  BEAST_EXPECT(v0.seq() != 98);
336  BEAST_EXPECT(v0.seq() == open->seq());
337  BEAST_EXPECT(v0.parentCloseTime() != NetClock::time_point{99s});
338  BEAST_EXPECT(v0.parentCloseTime() == open->parentCloseTime());
339  {
340  // shallow copy
341  OpenView v1(v0);
342  BEAST_EXPECT(v1.seq() == v0.seq());
343  BEAST_EXPECT(v1.parentCloseTime() == v1.parentCloseTime());
344 
345  ApplyViewImpl v2(&v1, tapRETRY);
346  BEAST_EXPECT(v2.parentCloseTime() == v1.parentCloseTime());
347  BEAST_EXPECT(v2.seq() == v1.seq());
348  BEAST_EXPECT(v2.flags() == tapRETRY);
349 
350  Sandbox v3(&v2);
351  BEAST_EXPECT(v3.seq() == v2.seq());
352  BEAST_EXPECT(v3.parentCloseTime() == v2.parentCloseTime());
353  BEAST_EXPECT(v3.flags() == tapRETRY);
354  }
355  {
356  ApplyViewImpl v1(&v0, tapRETRY);
357  PaymentSandbox v2(&v1);
358  BEAST_EXPECT(v2.seq() == v0.seq());
359  BEAST_EXPECT(v2.parentCloseTime() == v0.parentCloseTime());
360  BEAST_EXPECT(v2.flags() == tapRETRY);
361  PaymentSandbox v3(&v2);
362  BEAST_EXPECT(v3.seq() == v2.seq());
363  BEAST_EXPECT(v3.parentCloseTime() == v2.parentCloseTime());
364  BEAST_EXPECT(v3.flags() == v2.flags());
365  }
366  }
367  }
368 
369  // Return a list of keys found via sles
370  static std::vector<uint256>
371  sles(ReadView const& ledger)
372  {
374  v.reserve(32);
375  for (auto const& sle : ledger.sles)
376  v.push_back(sle->key());
377  return v;
378  }
379 
380  template <class... Args>
381  static std::vector<uint256>
382  list(Args... args)
383  {
384  return std::vector<uint256>({uint256(args)...});
385  }
386 
387  void
389  {
390  using namespace jtx;
391  Env env(*this);
392  Config config;
393  std::shared_ptr<Ledger const> const genesis = std::make_shared<Ledger>(
395  config,
397  env.app().getNodeFamily());
398  auto const ledger = std::make_shared<Ledger>(
399  *genesis, env.app().timeKeeper().closeTime());
400  auto setup123 = [&ledger, this]() {
401  // erase middle element
402  wipe(*ledger);
403  ledger->rawInsert(sle(1));
404  ledger->rawInsert(sle(2));
405  ledger->rawInsert(sle(3));
406  BEAST_EXPECT(sles(*ledger) == list(1, 2, 3));
407  };
408  {
409  setup123();
410  OpenView view(ledger.get());
411  view.rawErase(sle(1));
412  view.rawInsert(sle(4));
413  view.rawInsert(sle(5));
414  BEAST_EXPECT(sles(view) == list(2, 3, 4, 5));
415  auto b = view.sles.begin();
416  BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
417  ++b;
418  BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
419  ++b;
420  BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
421  ++b;
422  BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
423  ++b;
424  BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
425  }
426  {
427  setup123();
428  OpenView view(ledger.get());
429  view.rawErase(sle(1));
430  view.rawErase(sle(2));
431  view.rawInsert(sle(4));
432  view.rawInsert(sle(5));
433  BEAST_EXPECT(sles(view) == list(3, 4, 5));
434  auto b = view.sles.begin();
435  BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
436  BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
437  ++b;
438  BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
439  ++b;
440  BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
441  ++b;
442  BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
443  }
444  {
445  setup123();
446  OpenView view(ledger.get());
447  view.rawErase(sle(1));
448  view.rawErase(sle(2));
449  view.rawErase(sle(3));
450  view.rawInsert(sle(4));
451  view.rawInsert(sle(5));
452  BEAST_EXPECT(sles(view) == list(4, 5));
453  auto b = view.sles.begin();
454  BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
455  BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
456  BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
457  ++b;
458  BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
459  ++b;
460  BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
461  }
462  {
463  setup123();
464  OpenView view(ledger.get());
465  view.rawErase(sle(3));
466  view.rawInsert(sle(4));
467  view.rawInsert(sle(5));
468  BEAST_EXPECT(sles(view) == list(1, 2, 4, 5));
469  auto b = view.sles.begin();
470  ++b;
471  BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
472  ++b;
473  BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
474  BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
475  ++b;
476  BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
477  ++b;
478  BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
479  }
480  {
481  setup123();
482  OpenView view(ledger.get());
483  view.rawReplace(sle(1, 10));
484  view.rawReplace(sle(3, 30));
485  BEAST_EXPECT(sles(view) == list(1, 2, 3));
486  BEAST_EXPECT(seq(view.read(k(1))) == 10);
487  BEAST_EXPECT(seq(view.read(k(2))) == 1);
488  BEAST_EXPECT(seq(view.read(k(3))) == 30);
489 
490  view.rawErase(sle(3));
491  BEAST_EXPECT(sles(view) == list(1, 2));
492  auto b = view.sles.begin();
493  ++b;
494  BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
495  ++b;
496  BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
497  BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
498  BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
499  BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
500 
501  view.rawInsert(sle(5));
502  view.rawInsert(sle(4));
503  view.rawInsert(sle(3));
504  BEAST_EXPECT(sles(view) == list(1, 2, 3, 4, 5));
505  b = view.sles.begin();
506  ++b;
507  BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
508  ++b;
509  BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
510  ++b;
511  BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
512  ++b;
513  BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
514  ++b;
515  BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
516  }
517  }
518 
519  void
521  {
522  using namespace jtx;
523  Env env(*this);
524 
525  auto const alice = Account("alice");
526  auto const bob = Account("bob");
527  auto const carol = Account("carol");
528  auto const gw = Account("gateway");
529  auto const USD = gw["USD"];
530  auto const EUR = gw["EUR"];
531 
532  env.fund(XRP(10000), alice, bob, carol, gw);
533  env.trust(USD(100), alice, bob, carol);
534  {
535  // Global freezing.
536  env(pay(gw, alice, USD(50)));
537  env(offer(alice, XRP(5), USD(5)));
538 
539  // Now freeze gw.
540  env(fset(gw, asfGlobalFreeze));
541  env.close();
542  env(offer(alice, XRP(4), USD(5)), ter(tecFROZEN));
543  env.close();
544 
545  // Alice's USD balance should be zero if frozen.
546  BEAST_EXPECT(
547  USD(0) ==
548  accountHolds(
549  *env.closed(),
550  alice,
551  USD.currency,
552  gw,
554  env.journal));
555 
556  // Thaw gw and try again.
557  env(fclear(gw, asfGlobalFreeze));
558  env.close();
559  env(offer("alice", XRP(4), USD(5)));
560  }
561  {
562  // Local freezing.
563  env(pay(gw, bob, USD(50)));
564  env.close();
565 
566  // Now gw freezes bob's USD trust line.
567  env(trust(gw, USD(100), bob, tfSetFreeze));
568  env.close();
569 
570  // Bob's balance should be zero if frozen.
571  BEAST_EXPECT(
572  USD(0) ==
573  accountHolds(
574  *env.closed(),
575  bob,
576  USD.currency,
577  gw,
579  env.journal));
580 
581  // gw thaws bob's trust line. bob gets his money back.
582  env(trust(gw, USD(100), bob, tfClearFreeze));
583  env.close();
584  BEAST_EXPECT(
585  USD(50) ==
586  accountHolds(
587  *env.closed(),
588  bob,
589  USD.currency,
590  gw,
592  env.journal));
593  }
594  {
595  // accountHolds().
596  env(pay(gw, carol, USD(50)));
597  env.close();
598 
599  // carol has no EUR.
600  BEAST_EXPECT(
601  EUR(0) ==
602  accountHolds(
603  *env.closed(),
604  carol,
605  EUR.currency,
606  gw,
608  env.journal));
609 
610  // But carol does have USD.
611  BEAST_EXPECT(
612  USD(50) ==
613  accountHolds(
614  *env.closed(),
615  carol,
616  USD.currency,
617  gw,
619  env.journal));
620 
621  // carol's XRP balance should be her holdings minus her reserve.
622  auto const carolsXRP = accountHolds(
623  *env.closed(),
624  carol,
625  xrpCurrency(),
626  xrpAccount(),
628  env.journal);
629  // carol's XRP balance: 10000
630  // base reserve: -200
631  // 1 trust line times its reserve: 1 * -50
632  // -------
633  // carol's available balance: 9750
634  BEAST_EXPECT(carolsXRP == XRP(9750));
635 
636  // carol should be able to spend *more* than her XRP balance on
637  // a fee by eating into her reserve.
638  env(noop(carol), fee(carolsXRP + XRP(10)));
639  env.close();
640 
641  // carol's XRP balance should now show as zero.
642  BEAST_EXPECT(
643  XRP(0) ==
644  accountHolds(
645  *env.closed(),
646  carol,
647  xrpCurrency(),
648  gw,
650  env.journal));
651  }
652  {
653  // accountFunds().
654  // Gateways have whatever funds they claim to have.
655  auto const gwUSD = accountFunds(
656  *env.closed(), gw, USD(314159), fhZERO_IF_FROZEN, env.journal);
657  BEAST_EXPECT(gwUSD == USD(314159));
658 
659  // carol has funds from the gateway.
660  auto carolsUSD = accountFunds(
661  *env.closed(), carol, USD(0), fhZERO_IF_FROZEN, env.journal);
662  BEAST_EXPECT(carolsUSD == USD(50));
663 
664  // If carol's funds are frozen she has no funds...
665  env(fset(gw, asfGlobalFreeze));
666  env.close();
667  carolsUSD = accountFunds(
668  *env.closed(), carol, USD(0), fhZERO_IF_FROZEN, env.journal);
669  BEAST_EXPECT(carolsUSD == USD(0));
670 
671  // ... unless the query ignores the FROZEN state.
672  carolsUSD = accountFunds(
673  *env.closed(), carol, USD(0), fhIGNORE_FREEZE, env.journal);
674  BEAST_EXPECT(carolsUSD == USD(50));
675 
676  // Just to be tidy, thaw gw.
677  env(fclear(gw, asfGlobalFreeze));
678  env.close();
679  }
680  }
681 
682  void
684  {
685  using namespace jtx;
686  Env env(*this);
687 
688  auto const gw1 = Account("gw1");
689 
690  env.fund(XRP(10000), gw1);
691  env.close();
692 
693  auto rdView = env.closed();
694  // Test with no rate set on gw1.
695  BEAST_EXPECT(transferRate(*rdView, gw1) == parityRate);
696 
697  env(rate(gw1, 1.02));
698  env.close();
699 
700  rdView = env.closed();
701  BEAST_EXPECT(transferRate(*rdView, gw1) == Rate{1020000000});
702  }
703 
704  void
706  {
707  // This test requires incompatible ledgers. The good news we can
708  // construct and manage two different Env instances at the same
709  // time. So we can use two Env instances to produce mutually
710  // incompatible ledgers.
711  using namespace jtx;
712  auto const alice = Account("alice");
713  auto const bob = Account("bob");
714 
715  // The first Env.
716  Env eA(*this);
717 
718  eA.fund(XRP(10000), alice);
719  eA.close();
720  auto const rdViewA3 = eA.closed();
721 
722  eA.fund(XRP(10000), bob);
723  eA.close();
724  auto const rdViewA4 = eA.closed();
725 
726  // The two Env's can't share the same ports, so modifiy the config
727  // of the second Env to use higher port numbers
728  Env eB{*this, envconfig(port_increment, 3)};
729 
730  // Make ledgers that are incompatible with the first ledgers. Note
731  // that bob is funded before alice.
732  eB.fund(XRP(10000), bob);
733  eB.close();
734  auto const rdViewB3 = eB.closed();
735 
736  eB.fund(XRP(10000), alice);
737  eB.close();
738  auto const rdViewB4 = eB.closed();
739 
740  // Check for compatibility.
741  auto jStream = eA.journal.error();
742  BEAST_EXPECT(areCompatible(*rdViewA3, *rdViewA4, jStream, ""));
743  BEAST_EXPECT(areCompatible(*rdViewA4, *rdViewA3, jStream, ""));
744  BEAST_EXPECT(areCompatible(*rdViewA4, *rdViewA4, jStream, ""));
745  BEAST_EXPECT(!areCompatible(*rdViewA3, *rdViewB4, jStream, ""));
746  BEAST_EXPECT(!areCompatible(*rdViewA4, *rdViewB3, jStream, ""));
747  BEAST_EXPECT(!areCompatible(*rdViewA4, *rdViewB4, jStream, ""));
748 
749  // Try the other interface.
750  // Note that the different interface has different outcomes.
751  auto const& iA3 = rdViewA3->info();
752  auto const& iA4 = rdViewA4->info();
753 
754  BEAST_EXPECT(areCompatible(iA3.hash, iA3.seq, *rdViewA4, jStream, ""));
755  BEAST_EXPECT(areCompatible(iA4.hash, iA4.seq, *rdViewA3, jStream, ""));
756  BEAST_EXPECT(areCompatible(iA4.hash, iA4.seq, *rdViewA4, jStream, ""));
757  BEAST_EXPECT(!areCompatible(iA3.hash, iA3.seq, *rdViewB4, jStream, ""));
758  BEAST_EXPECT(areCompatible(iA4.hash, iA4.seq, *rdViewB3, jStream, ""));
759  BEAST_EXPECT(!areCompatible(iA4.hash, iA4.seq, *rdViewB4, jStream, ""));
760  }
761 
762  void
764  {
765  using namespace jtx;
766 
767  // Create a ledger with 1 item, put a
768  // ApplyView on that, then another ApplyView,
769  // erase the item, apply.
770  {
771  Env env(*this);
772  Config config;
773  std::shared_ptr<Ledger const> const genesis =
774  std::make_shared<Ledger>(
776  config,
778  env.app().getNodeFamily());
779  auto const ledger = std::make_shared<Ledger>(
780  *genesis, env.app().timeKeeper().closeTime());
781  wipe(*ledger);
782  ledger->rawInsert(sle(1));
783  ReadView& v0 = *ledger;
784  ApplyViewImpl v1(&v0, tapNONE);
785  {
786  Sandbox v2(&v1);
787  v2.erase(v2.peek(k(1)));
788  v2.apply(v1);
789  }
790  BEAST_EXPECT(!v1.exists(k(1)));
791  }
792 
793  // Make sure OpenLedger::empty works
794  {
795  Env env(*this);
796  BEAST_EXPECT(env.app().openLedger().empty());
797  env.fund(XRP(10000), Account("test"));
798  BEAST_EXPECT(!env.app().openLedger().empty());
799  }
800  }
801 
802  void
803  run() override
804  {
805  // This had better work, or else
806  BEAST_EXPECT(k(0).key < k(1).key);
807 
808  testLedger();
809  testMeta();
810  testMetaSucc();
811  testStacked();
812  testContext();
813  testSles();
814  testFlags();
817  testRegressions();
818  }
819 };
820 
821 class GetAmendments_test : public beast::unit_test::suite
822 {
823  void
825  {
826  using namespace jtx;
827  Env env{*this, envconfig(validator, "")};
828 
829  // Start out with no amendments.
830  auto majorities = getMajorityAmendments(*env.closed());
831  BEAST_EXPECT(majorities.empty());
832 
833  // Now close ledgers until the amendments show up.
834  int i = 0;
835  for (i = 0; i <= 256; ++i)
836  {
837  env.close();
838  majorities = getMajorityAmendments(*env.closed());
839  if (!majorities.empty())
840  break;
841  }
842 
843  // There should be at least 5 amendments. Don't do exact comparison
844  // to avoid maintenance as more amendments are added in the future.
845  BEAST_EXPECT(i == 254);
846  BEAST_EXPECT(majorities.size() >= 5);
847 
848  // None of the amendments should be enabled yet.
849  auto enableds = getEnabledAmendments(*env.closed());
850  BEAST_EXPECT(enableds.empty());
851 
852  // Now wait 2 weeks modulo 256 ledgers for the amendments to be
853  // enabled. Speed the process by closing ledgers every 80 minutes,
854  // which should get us to just past 2 weeks after 256 ledgers.
855  for (i = 0; i <= 256; ++i)
856  {
857  using namespace std::chrono_literals;
858  env.close(80min);
859  enableds = getEnabledAmendments(*env.closed());
860  if (!enableds.empty())
861  break;
862  }
863  BEAST_EXPECT(i == 255);
864  BEAST_EXPECT(enableds.size() >= 5);
865  }
866 
867  void
868  run() override
869  {
870  testGetAmendments();
871  }
872 };
873 
874 BEAST_DEFINE_TESTSUITE(View, ledger, ripple);
875 BEAST_DEFINE_TESTSUITE(GetAmendments, ledger, ripple);
876 
877 } // namespace test
878 } // namespace ripple
ripple::test::View_test::testMetaSucc
void testMetaSucc()
Definition: View_test.cpp:197
ripple::transferRate
Rate transferRate(ReadView const &view, AccountID const &issuer)
Definition: View.cpp:347
ripple::test::jtx::noop
Json::Value noop(Account const &account)
The null transaction.
Definition: noop.h:31
ripple::tecFROZEN
@ tecFROZEN
Definition: TER.h:264
ripple::getMajorityAmendments
majorityAmendments_t getMajorityAmendments(ReadView const &view)
Definition: View.cpp:550
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
ripple::test::View_test::testFlags
void testFlags()
Definition: View_test.cpp:520
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::getEnabledAmendments
std::set< uint256 > getEnabledAmendments(ReadView const &view)
Definition: View.cpp:533
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
std::shared_ptr
STL class.
ripple::test::View_test::seq
static void seq(std::shared_ptr< SLE > const &le, std::uint32_t seq)
Definition: View_test.cpp:62
ripple::test::GetAmendments_test
Definition: View_test.cpp:821
ripple::fhZERO_IF_FROZEN
@ fhZERO_IF_FROZEN
Definition: View.h:53
ripple::Rate
Represents a transfer rate.
Definition: Rate.h:37
ripple::test::jtx::ter
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition: ter.h:33
ripple::test::View_test::testTransferRate
void testTransferRate()
Definition: View_test.cpp:683
ripple::PaymentSandbox
A wrapper which makes credits unavailable to balances.
Definition: PaymentSandbox.h:112
ripple::Sandbox::apply
void apply(RawView &to)
Definition: Sandbox.h:55
ripple::test::jtx::Env::closed
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
Definition: Env.cpp:115
std::vector::reserve
T reserve(T... args)
ripple::sfSequence
const SF_UINT32 sfSequence
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:55
ripple::asfGlobalFreeze
const std::uint32_t asfGlobalFreeze
Definition: TxFlags.h:71
ripple::OpenView::rawErase
void rawErase(std::shared_ptr< SLE > const &sle) override
Delete an existing state item.
Definition: OpenView.cpp:233
ripple::test::jtx::validator
std::unique_ptr< Config > validator(std::unique_ptr< Config >, std::string const &)
adjust configuration with params needed to be a validator
Definition: envconfig.cpp:89
ripple::detail::ApplyViewBase::exists
bool exists(Keylet const &k) const override
Determine if a state item exists.
Definition: ApplyViewBase.cpp:59
std::vector
STL class.
ripple::test::jtx::trust
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition: trust.cpp:30
ripple::accountHolds
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
Definition: View.cpp:92
ripple::detail::ApplyViewBase::update
void update(std::shared_ptr< SLE > const &sle) override
Indicate changes to a peeked SLE.
Definition: ApplyViewBase.cpp:147
ripple::test::View_test::testSles
void testSles()
Definition: View_test.cpp:388
ripple::test::jtx::port_increment
std::unique_ptr< Config > port_increment(std::unique_ptr< Config >, int)
adjust the default configured server ports by a specified value
Definition: envconfig.cpp:98
ripple::test::jtx::Env::journal
const beast::Journal journal
Definition: Env.h:143
ripple::ReadView::sles_type::upper_bound
iterator upper_bound(key_type const &key) const
Definition: ReadView.cpp:144
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:240
ripple::ApplyViewImpl
Editable, discardable view that can build metadata for one tx.
Definition: ApplyViewImpl.h:37
ripple::Application::timeKeeper
virtual TimeKeeper & timeKeeper()=0
ripple::test::jtx::envconfig
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:49
ripple::tfClearFreeze
const std::uint32_t tfClearFreeze
Definition: TxFlags.h:95
ripple::Application::openLedger
virtual OpenLedger & openLedger()=0
ripple::ReadView::parentCloseTime
NetClock::time_point parentCloseTime() const
Returns the close time of the previous ledger.
Definition: ReadView.h:253
ripple::test::View_test::sles
static std::vector< uint256 > sles(ReadView const &ledger)
Definition: View_test.cpp:371
ripple::Ledger::rawErase
void rawErase(std::shared_ptr< SLE > const &sle) override
Delete an existing state item.
Definition: Ledger.cpp:493
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:31
ripple::parityRate
const Rate parityRate(QUALITY_ONE)
A transfer rate signifying a 1:1 exchange.
Definition: Rate.h:94
ripple::ReadView::sles_type::begin
iterator begin() const
Definition: ReadView.cpp:132
ripple::test::jtx::Env::trust
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Definition: Env.cpp:250
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:457
ripple::test::View_test::run
void run() override
Definition: View_test.cpp:803
std::vector::push_back
T push_back(T... args)
ripple::Keylet::key
uint256 key
Definition: Keylet.h:41
ripple::base_uint< 256 >
ripple::test::View_test::testRegressions
void testRegressions()
Definition: View_test.cpp:763
ripple::Ledger
Holds a ledger.
Definition: Ledger.h:77
ripple::test::View_test::testContext
void testContext()
Definition: View_test.cpp:326
ripple::Config
Definition: Config.h:69
ripple::test::View_test::sle
static std::shared_ptr< SLE > sle(std::uint64_t id, std::uint32_t seq=1)
Definition: View_test.cpp:45
ripple::OpenView::rawReplace
void rawReplace(std::shared_ptr< SLE > const &sle) override
Unconditionally replace a state item.
Definition: OpenView.cpp:245
ripple::Sandbox
Discardable, editable view to a ledger.
Definition: Sandbox.h:34
ripple::test::jtx::fset
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition: flags.cpp:28
ripple::test::View_test::wipe
static void wipe(Ledger &ledger)
Definition: View_test.cpp:88
ripple::xrpAccount
AccountID const & xrpAccount()
Compute AccountID from public key.
Definition: AccountID.cpp:90
beast::Journal::error
Stream error() const
Definition: Journal.h:333
std::chrono::time_point
ripple::ReadView::exists
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
ripple::ReadView::sles
sles_type sles
Iterable range of ledger state items.
Definition: ReadView.h:387
ripple::TimeKeeper::closeTime
virtual time_point closeTime() const =0
Returns the close time, in network time.
ripple::test::View_test::wipe
static void wipe(OpenLedger &openLedger)
Definition: View_test.cpp:69
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::test::GetAmendments_test::run
void run() override
Definition: View_test.cpp:868
std::uint64_t
ripple::tfSetFreeze
const std::uint32_t tfSetFreeze
Definition: TxFlags.h:94
ripple::keylet::unchecked
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Definition: Indexes.cpp:298
ripple::test::jtx::fclear
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition: flags.h:40
ripple::test::View_test::testMeta
void testMeta()
Definition: View_test.cpp:166
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::areCompatible
bool areCompatible(ReadView const &validLedger, ReadView const &testLedger, beast::Journal::Stream &s, const char *reason)
Return false if the test ledger is provably incompatible with the valid ledger, that is,...
Definition: View.cpp:358
ripple::OpenLedger::empty
bool empty() const
Returns true if there are no transactions.
Definition: OpenLedger.cpp:43
ripple::accountFunds
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
Definition: View.cpp:136
ripple::OpenLedger
Represents the open ledger.
Definition: OpenLedger.h:49
ripple::test::jtx::fee
Set the fee on a JTx.
Definition: fee.h:34
ripple::tapRETRY
@ tapRETRY
Definition: ApplyView.h:39
ripple::OpenView::rawInsert
void rawInsert(std::shared_ptr< SLE > const &sle) override
Unconditionally insert a state item.
Definition: OpenView.cpp:239
ripple::Ledger::read
std::shared_ptr< SLE const > read(Keylet const &k) const override
Return the state item associated with a key.
Definition: Ledger.cpp:409
ripple::detail::ApplyViewBase::insert
void insert(std::shared_ptr< SLE > const &sle) override
Insert a new state SLE.
Definition: ApplyViewBase.cpp:141
ripple::detail::ApplyViewBase::erase
void erase(std::shared_ptr< SLE > const &sle) override
Remove a peeked SLE.
Definition: ApplyViewBase.cpp:135
ripple::test::jtx::seq
Set the sequence number on a JTx.
Definition: seq.h:32
ripple::detail::ApplyViewBase::flags
ApplyFlags flags() const override
Returns the tx apply flags.
Definition: ApplyViewBase.cpp:123
ripple::test::View_test::copy
static std::shared_ptr< std::remove_const_t< T > > copy(std::shared_ptr< T > const &sp)
Definition: View_test.cpp:124
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:192
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::jtx::pay
Json::Value pay(Account const &account, Account const &to, AnyAmount amount)
Create a payment.
Definition: pay.cpp:29
ripple::test::View_test::testLedger
void testLedger()
Definition: View_test.cpp:131
ripple::ReadView::seq
LedgerIndex seq() const
Returns the sequence number of the base ledger.
Definition: ReadView.h:260
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:121
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:219
ripple::create_genesis
const create_genesis_t create_genesis
Definition: Ledger.cpp:57
ripple::test::View_test
Definition: View_test.cpp:34
ripple::Ledger::succ
boost::optional< uint256 > succ(uint256 const &key, boost::optional< uint256 > const &last=boost::none) const override
Definition: Ledger.cpp:398
ripple::fhIGNORE_FREEZE
@ fhIGNORE_FREEZE
Definition: View.h:53
ripple::OpenView::read
std::shared_ptr< SLE const > read(Keylet const &k) const override
Return the state item associated with a key.
Definition: OpenView.cpp:171
ripple::detail::ApplyViewBase::read
std::shared_ptr< SLE const > read(Keylet const &k) const override
Return the state item associated with a key.
Definition: ApplyViewBase.cpp:72
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::detail::ApplyViewBase::peek
std::shared_ptr< SLE > peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
Definition: ApplyViewBase.cpp:129
ripple::test::GetAmendments_test::testGetAmendments
void testGetAmendments()
Definition: View_test.cpp:824
ripple::test::View_test::testAreCompatible
void testAreCompatible()
Definition: View_test.cpp:705
ripple::test::View_test::testStacked
void testStacked()
Definition: View_test.cpp:261
ripple::test::View_test::k
static Keylet k(std::uint64_t id)
Definition: View_test.cpp:38
ripple::test::View_test::list
static std::vector< uint256 > list(Args... args)
Definition: View_test.cpp:382
ripple::ltACCOUNT_ROOT
@ ltACCOUNT_ROOT
Definition: LedgerFormats.h:53
ripple::test::View_test::succ
void succ(ReadView const &v, std::uint32_t id, boost::optional< std::uint32_t > answer)
Definition: View_test.cpp:105
ripple::ReadView::succ
virtual boost::optional< key_type > succ(key_type const &key, boost::optional< key_type > const &last=boost::none) const =0
Return the key of the next state item.
type_traits
ripple::OpenLedger::modify
bool modify(modify_type const &f)
Modify the open ledger.
Definition: OpenLedger.cpp:57
ripple::test::jtx::Env::current
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:299
ripple::xrpCurrency
Currency const & xrpCurrency()
XRP currency.
Definition: UintTypes.cpp:124
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:115
ripple::detail::ApplyViewBase::rawInsert
void rawInsert(std::shared_ptr< SLE > const &sle) override
Unconditionally insert a state item.
Definition: ApplyViewBase.cpp:161
ripple::open
void open(soci::session &s, BasicConfig const &config, std::string const &dbName)
Open a soci session.
Definition: SociDB.cpp:100
ripple::OpenView::succ
boost::optional< key_type > succ(key_type const &key, boost::optional< key_type > const &last=boost::none) const override
Return the key of the next state item.
Definition: OpenView.cpp:164
ripple::test::jtx::rate
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Definition: rate.cpp:30
std::chrono
ripple::test::View_test::seq
static std::uint32_t seq(std::shared_ptr< T > const &le)
Definition: View_test.cpp:55