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>(
137  create_genesis, config, std::vector<uint256>{}, env.app().family());
138  auto const ledger = std::make_shared<Ledger>(
139  *genesis, env.app().timeKeeper().closeTime());
140  wipe(*ledger);
141  ReadView& v = *ledger;
142  succ(v, 0, boost::none);
143  ledger->rawInsert(sle(1, 1));
144  BEAST_EXPECT(v.exists(k(1)));
145  BEAST_EXPECT(seq(v.read(k(1))) == 1);
146  succ(v, 0, 1);
147  succ(v, 1, boost::none);
148  ledger->rawInsert(sle(2, 2));
149  BEAST_EXPECT(seq(v.read(k(2))) == 2);
150  ledger->rawInsert(sle(3, 3));
151  BEAST_EXPECT(seq(v.read(k(3))) == 3);
152  auto s = copy(v.read(k(2)));
153  seq(s, 4);
154  ledger->rawReplace(std::move(s));
155  BEAST_EXPECT(seq(v.read(k(2))) == 4);
156  ledger->rawErase(sle(2));
157  BEAST_EXPECT(!v.exists(k(2)));
158  BEAST_EXPECT(v.exists(k(1)));
159  BEAST_EXPECT(v.exists(k(3)));
160  }
161 
162  void
164  {
165  using namespace jtx;
166  Env env(*this);
167  wipe(env.app().openLedger());
168  auto const open = env.current();
169  ApplyViewImpl v(&*open, tapNONE);
170  succ(v, 0, boost::none);
171  v.insert(sle(1));
172  BEAST_EXPECT(v.exists(k(1)));
173  BEAST_EXPECT(seq(v.read(k(1))) == 1);
174  BEAST_EXPECT(seq(v.peek(k(1))) == 1);
175  succ(v, 0, 1);
176  succ(v, 1, boost::none);
177  v.insert(sle(2, 2));
178  BEAST_EXPECT(seq(v.read(k(2))) == 2);
179  v.insert(sle(3, 3));
180  auto s = v.peek(k(3));
181  BEAST_EXPECT(seq(s) == 3);
182  s = v.peek(k(2));
183  seq(s, 4);
184  v.update(s);
185  BEAST_EXPECT(seq(v.read(k(2))) == 4);
186  v.erase(s);
187  BEAST_EXPECT(!v.exists(k(2)));
188  BEAST_EXPECT(v.exists(k(1)));
189  BEAST_EXPECT(v.exists(k(3)));
190  }
191 
192  // Exercise all succ paths
193  void
195  {
196  using namespace jtx;
197  Env env(*this);
198  wipe(env.app().openLedger());
199  auto const open = env.current();
200  ApplyViewImpl v0(&*open, tapNONE);
201  v0.insert(sle(1));
202  v0.insert(sle(2));
203  v0.insert(sle(4));
204  v0.insert(sle(7));
205  {
206  Sandbox v1(&v0);
207  v1.insert(sle(3));
208  v1.insert(sle(5));
209  v1.insert(sle(6));
210 
211  // v0: 12-4--7
212  // v1: --3-56-
213 
214  succ(v0, 0, 1);
215  succ(v0, 1, 2);
216  succ(v0, 2, 4);
217  succ(v0, 3, 4);
218  succ(v0, 4, 7);
219  succ(v0, 5, 7);
220  succ(v0, 6, 7);
221  succ(v0, 7, boost::none);
222 
223  succ(v1, 0, 1);
224  succ(v1, 1, 2);
225  succ(v1, 2, 3);
226  succ(v1, 3, 4);
227  succ(v1, 4, 5);
228  succ(v1, 5, 6);
229  succ(v1, 6, 7);
230  succ(v1, 7, boost::none);
231 
232  v1.erase(v1.peek(k(4)));
233  succ(v1, 3, 5);
234 
235  v1.erase(v1.peek(k(6)));
236  succ(v1, 5, 7);
237  succ(v1, 6, 7);
238 
239  // v0: 12----7
240  // v1: --3-5--
241 
242  v1.apply(v0);
243  }
244 
245  // v0: 123-5-7
246 
247  succ(v0, 0, 1);
248  succ(v0, 1, 2);
249  succ(v0, 2, 3);
250  succ(v0, 3, 5);
251  succ(v0, 4, 5);
252  succ(v0, 5, 7);
253  succ(v0, 6, 7);
254  succ(v0, 7, boost::none);
255  }
256 
257  void
259  {
260  using namespace jtx;
261  Env env(*this);
262  wipe(env.app().openLedger());
263  auto const open = env.current();
264  ApplyViewImpl v0(&*open, tapNONE);
265  v0.rawInsert(sle(1, 1));
266  v0.rawInsert(sle(2, 2));
267  v0.rawInsert(sle(4, 4));
268 
269  {
270  Sandbox v1(&v0);
271  v1.erase(v1.peek(k(2)));
272  v1.insert(sle(3, 3));
273  auto s = v1.peek(k(4));
274  seq(s, 5);
275  v1.update(s);
276  BEAST_EXPECT(seq(v1.read(k(1))) == 1);
277  BEAST_EXPECT(!v1.exists(k(2)));
278  BEAST_EXPECT(seq(v1.read(k(3))) == 3);
279  BEAST_EXPECT(seq(v1.read(k(4))) == 5);
280  {
281  Sandbox v2(&v1);
282  auto s2 = v2.peek(k(3));
283  seq(s2, 6);
284  v2.update(s2);
285  v2.erase(v2.peek(k(4)));
286  BEAST_EXPECT(seq(v2.read(k(1))) == 1);
287  BEAST_EXPECT(!v2.exists(k(2)));
288  BEAST_EXPECT(seq(v2.read(k(3))) == 6);
289  BEAST_EXPECT(!v2.exists(k(4)));
290  // discard v2
291  }
292  BEAST_EXPECT(seq(v1.read(k(1))) == 1);
293  BEAST_EXPECT(!v1.exists(k(2)));
294  BEAST_EXPECT(seq(v1.read(k(3))) == 3);
295  BEAST_EXPECT(seq(v1.read(k(4))) == 5);
296 
297  {
298  Sandbox v2(&v1);
299  auto s2 = v2.peek(k(3));
300  seq(s2, 6);
301  v2.update(s2);
302  v2.erase(v2.peek(k(4)));
303  BEAST_EXPECT(seq(v2.read(k(1))) == 1);
304  BEAST_EXPECT(!v2.exists(k(2)));
305  BEAST_EXPECT(seq(v2.read(k(3))) == 6);
306  BEAST_EXPECT(!v2.exists(k(4)));
307  v2.apply(v1);
308  }
309  BEAST_EXPECT(seq(v1.read(k(1))) == 1);
310  BEAST_EXPECT(!v1.exists(k(2)));
311  BEAST_EXPECT(seq(v1.read(k(3))) == 6);
312  BEAST_EXPECT(!v1.exists(k(4)));
313  v1.apply(v0);
314  }
315  BEAST_EXPECT(seq(v0.read(k(1))) == 1);
316  BEAST_EXPECT(!v0.exists(k(2)));
317  BEAST_EXPECT(seq(v0.read(k(3))) == 6);
318  BEAST_EXPECT(!v0.exists(k(4)));
319  }
320 
321  // Verify contextual information
322  void
324  {
325  using namespace jtx;
326  using namespace std::chrono;
327  {
328  Env env(*this);
329  wipe(env.app().openLedger());
330  auto const open = env.current();
331  OpenView v0(open.get());
332  BEAST_EXPECT(v0.seq() != 98);
333  BEAST_EXPECT(v0.seq() == open->seq());
334  BEAST_EXPECT(v0.parentCloseTime() != NetClock::time_point{99s});
335  BEAST_EXPECT(v0.parentCloseTime() == open->parentCloseTime());
336  {
337  // shallow copy
338  OpenView v1(v0);
339  BEAST_EXPECT(v1.seq() == v0.seq());
340  BEAST_EXPECT(v1.parentCloseTime() == v1.parentCloseTime());
341 
342  ApplyViewImpl v2(&v1, tapRETRY);
343  BEAST_EXPECT(v2.parentCloseTime() == v1.parentCloseTime());
344  BEAST_EXPECT(v2.seq() == v1.seq());
345  BEAST_EXPECT(v2.flags() == tapRETRY);
346 
347  Sandbox v3(&v2);
348  BEAST_EXPECT(v3.seq() == v2.seq());
349  BEAST_EXPECT(v3.parentCloseTime() == v2.parentCloseTime());
350  BEAST_EXPECT(v3.flags() == tapRETRY);
351  }
352  {
353  ApplyViewImpl v1(&v0, tapRETRY);
354  PaymentSandbox v2(&v1);
355  BEAST_EXPECT(v2.seq() == v0.seq());
356  BEAST_EXPECT(v2.parentCloseTime() == v0.parentCloseTime());
357  BEAST_EXPECT(v2.flags() == tapRETRY);
358  PaymentSandbox v3(&v2);
359  BEAST_EXPECT(v3.seq() == v2.seq());
360  BEAST_EXPECT(v3.parentCloseTime() == v2.parentCloseTime());
361  BEAST_EXPECT(v3.flags() == v2.flags());
362  }
363  }
364  }
365 
366  // Return a list of keys found via sles
367  static std::vector<uint256>
368  sles(ReadView const& ledger)
369  {
371  v.reserve(32);
372  for (auto const& sle : ledger.sles)
373  v.push_back(sle->key());
374  return v;
375  }
376 
377  template <class... Args>
378  static std::vector<uint256>
379  list(Args... args)
380  {
381  return std::vector<uint256>({uint256(args)...});
382  }
383 
384  void
386  {
387  using namespace jtx;
388  Env env(*this);
389  Config config;
390  std::shared_ptr<Ledger const> const genesis = std::make_shared<Ledger>(
391  create_genesis, config, std::vector<uint256>{}, env.app().family());
392  auto const ledger = std::make_shared<Ledger>(
393  *genesis, env.app().timeKeeper().closeTime());
394  auto setup123 = [&ledger, this]() {
395  // erase middle element
396  wipe(*ledger);
397  ledger->rawInsert(sle(1));
398  ledger->rawInsert(sle(2));
399  ledger->rawInsert(sle(3));
400  BEAST_EXPECT(sles(*ledger) == list(1, 2, 3));
401  };
402  {
403  setup123();
404  OpenView view(ledger.get());
405  view.rawErase(sle(1));
406  view.rawInsert(sle(4));
407  view.rawInsert(sle(5));
408  BEAST_EXPECT(sles(view) == list(2, 3, 4, 5));
409  auto b = view.sles.begin();
410  BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
411  ++b;
412  BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
413  ++b;
414  BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
415  ++b;
416  BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
417  ++b;
418  BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
419  }
420  {
421  setup123();
422  OpenView view(ledger.get());
423  view.rawErase(sle(1));
424  view.rawErase(sle(2));
425  view.rawInsert(sle(4));
426  view.rawInsert(sle(5));
427  BEAST_EXPECT(sles(view) == list(3, 4, 5));
428  auto b = view.sles.begin();
429  BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
430  BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
431  ++b;
432  BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
433  ++b;
434  BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
435  ++b;
436  BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
437  }
438  {
439  setup123();
440  OpenView view(ledger.get());
441  view.rawErase(sle(1));
442  view.rawErase(sle(2));
443  view.rawErase(sle(3));
444  view.rawInsert(sle(4));
445  view.rawInsert(sle(5));
446  BEAST_EXPECT(sles(view) == list(4, 5));
447  auto b = view.sles.begin();
448  BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
449  BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
450  BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
451  ++b;
452  BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
453  ++b;
454  BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
455  }
456  {
457  setup123();
458  OpenView view(ledger.get());
459  view.rawErase(sle(3));
460  view.rawInsert(sle(4));
461  view.rawInsert(sle(5));
462  BEAST_EXPECT(sles(view) == list(1, 2, 4, 5));
463  auto b = view.sles.begin();
464  ++b;
465  BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
466  ++b;
467  BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
468  BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
469  ++b;
470  BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
471  ++b;
472  BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
473  }
474  {
475  setup123();
476  OpenView view(ledger.get());
477  view.rawReplace(sle(1, 10));
478  view.rawReplace(sle(3, 30));
479  BEAST_EXPECT(sles(view) == list(1, 2, 3));
480  BEAST_EXPECT(seq(view.read(k(1))) == 10);
481  BEAST_EXPECT(seq(view.read(k(2))) == 1);
482  BEAST_EXPECT(seq(view.read(k(3))) == 30);
483 
484  view.rawErase(sle(3));
485  BEAST_EXPECT(sles(view) == list(1, 2));
486  auto b = view.sles.begin();
487  ++b;
488  BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
489  ++b;
490  BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
491  BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
492  BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
493  BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
494 
495  view.rawInsert(sle(5));
496  view.rawInsert(sle(4));
497  view.rawInsert(sle(3));
498  BEAST_EXPECT(sles(view) == list(1, 2, 3, 4, 5));
499  b = view.sles.begin();
500  ++b;
501  BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
502  ++b;
503  BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
504  ++b;
505  BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
506  ++b;
507  BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
508  ++b;
509  BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
510  }
511  }
512 
513  void
515  {
516  using namespace jtx;
517  Env env(*this);
518 
519  auto const alice = Account("alice");
520  auto const bob = Account("bob");
521  auto const carol = Account("carol");
522  auto const gw = Account("gateway");
523  auto const USD = gw["USD"];
524  auto const EUR = gw["EUR"];
525 
526  env.fund(XRP(10000), alice, bob, carol, gw);
527  env.trust(USD(100), alice, bob, carol);
528  {
529  // Global freezing.
530  env(pay(gw, alice, USD(50)));
531  env(offer(alice, XRP(5), USD(5)));
532 
533  // Now freeze gw.
534  env(fset(gw, asfGlobalFreeze));
535  env.close();
536  env(offer(alice, XRP(4), USD(5)), ter(tecFROZEN));
537  env.close();
538 
539  // Alice's USD balance should be zero if frozen.
540  BEAST_EXPECT(
541  USD(0) ==
542  accountHolds(
543  *env.closed(),
544  alice,
545  USD.currency,
546  gw,
548  env.journal));
549 
550  // Thaw gw and try again.
551  env(fclear(gw, asfGlobalFreeze));
552  env.close();
553  env(offer("alice", XRP(4), USD(5)));
554  }
555  {
556  // Local freezing.
557  env(pay(gw, bob, USD(50)));
558  env.close();
559 
560  // Now gw freezes bob's USD trust line.
561  env(trust(gw, USD(100), bob, tfSetFreeze));
562  env.close();
563 
564  // Bob's balance should be zero if frozen.
565  BEAST_EXPECT(
566  USD(0) ==
567  accountHolds(
568  *env.closed(),
569  bob,
570  USD.currency,
571  gw,
573  env.journal));
574 
575  // gw thaws bob's trust line. bob gets his money back.
576  env(trust(gw, USD(100), bob, tfClearFreeze));
577  env.close();
578  BEAST_EXPECT(
579  USD(50) ==
580  accountHolds(
581  *env.closed(),
582  bob,
583  USD.currency,
584  gw,
586  env.journal));
587  }
588  {
589  // accountHolds().
590  env(pay(gw, carol, USD(50)));
591  env.close();
592 
593  // carol has no EUR.
594  BEAST_EXPECT(
595  EUR(0) ==
596  accountHolds(
597  *env.closed(),
598  carol,
599  EUR.currency,
600  gw,
602  env.journal));
603 
604  // But carol does have USD.
605  BEAST_EXPECT(
606  USD(50) ==
607  accountHolds(
608  *env.closed(),
609  carol,
610  USD.currency,
611  gw,
613  env.journal));
614 
615  // carol's XRP balance should be her holdings minus her reserve.
616  auto const carolsXRP = accountHolds(
617  *env.closed(),
618  carol,
619  xrpCurrency(),
620  xrpAccount(),
622  env.journal);
623  // carol's XRP balance: 10000
624  // base reserve: -200
625  // 1 trust line times its reserve: 1 * -50
626  // -------
627  // carol's available balance: 9750
628  BEAST_EXPECT(carolsXRP == XRP(9750));
629 
630  // carol should be able to spend *more* than her XRP balance on
631  // a fee by eating into her reserve.
632  env(noop(carol), fee(carolsXRP + XRP(10)));
633  env.close();
634 
635  // carol's XRP balance should now show as zero.
636  BEAST_EXPECT(
637  XRP(0) ==
638  accountHolds(
639  *env.closed(),
640  carol,
641  xrpCurrency(),
642  gw,
644  env.journal));
645  }
646  {
647  // accountFunds().
648  // Gateways have whatever funds they claim to have.
649  auto const gwUSD = accountFunds(
650  *env.closed(), gw, USD(314159), fhZERO_IF_FROZEN, env.journal);
651  BEAST_EXPECT(gwUSD == USD(314159));
652 
653  // carol has funds from the gateway.
654  auto carolsUSD = accountFunds(
655  *env.closed(), carol, USD(0), fhZERO_IF_FROZEN, env.journal);
656  BEAST_EXPECT(carolsUSD == USD(50));
657 
658  // If carol's funds are frozen she has no funds...
659  env(fset(gw, asfGlobalFreeze));
660  env.close();
661  carolsUSD = accountFunds(
662  *env.closed(), carol, USD(0), fhZERO_IF_FROZEN, env.journal);
663  BEAST_EXPECT(carolsUSD == USD(0));
664 
665  // ... unless the query ignores the FROZEN state.
666  carolsUSD = accountFunds(
667  *env.closed(), carol, USD(0), fhIGNORE_FREEZE, env.journal);
668  BEAST_EXPECT(carolsUSD == USD(50));
669 
670  // Just to be tidy, thaw gw.
671  env(fclear(gw, asfGlobalFreeze));
672  env.close();
673  }
674  }
675 
676  void
678  {
679  using namespace jtx;
680  Env env(*this);
681 
682  auto const gw1 = Account("gw1");
683 
684  env.fund(XRP(10000), gw1);
685  env.close();
686 
687  auto rdView = env.closed();
688  // Test with no rate set on gw1.
689  BEAST_EXPECT(transferRate(*rdView, gw1) == parityRate);
690 
691  env(rate(gw1, 1.02));
692  env.close();
693 
694  rdView = env.closed();
695  BEAST_EXPECT(transferRate(*rdView, gw1) == Rate{1020000000});
696  }
697 
698  void
700  {
701  // This test requires incompatible ledgers. The good news we can
702  // construct and manage two different Env instances at the same
703  // time. So we can use two Env instances to produce mutually
704  // incompatible ledgers.
705  using namespace jtx;
706  auto const alice = Account("alice");
707  auto const bob = Account("bob");
708 
709  // The first Env.
710  Env eA(*this);
711 
712  eA.fund(XRP(10000), alice);
713  eA.close();
714  auto const rdViewA3 = eA.closed();
715 
716  eA.fund(XRP(10000), bob);
717  eA.close();
718  auto const rdViewA4 = eA.closed();
719 
720  // The two Env's can't share the same ports, so modifiy the config
721  // of the second Env to use higher port numbers
722  Env eB{*this, envconfig(port_increment, 3)};
723 
724  // Make ledgers that are incompatible with the first ledgers. Note
725  // that bob is funded before alice.
726  eB.fund(XRP(10000), bob);
727  eB.close();
728  auto const rdViewB3 = eB.closed();
729 
730  eB.fund(XRP(10000), alice);
731  eB.close();
732  auto const rdViewB4 = eB.closed();
733 
734  // Check for compatibility.
735  auto jStream = eA.journal.error();
736  BEAST_EXPECT(areCompatible(*rdViewA3, *rdViewA4, jStream, ""));
737  BEAST_EXPECT(areCompatible(*rdViewA4, *rdViewA3, jStream, ""));
738  BEAST_EXPECT(areCompatible(*rdViewA4, *rdViewA4, jStream, ""));
739  BEAST_EXPECT(!areCompatible(*rdViewA3, *rdViewB4, jStream, ""));
740  BEAST_EXPECT(!areCompatible(*rdViewA4, *rdViewB3, jStream, ""));
741  BEAST_EXPECT(!areCompatible(*rdViewA4, *rdViewB4, jStream, ""));
742 
743  // Try the other interface.
744  // Note that the different interface has different outcomes.
745  auto const& iA3 = rdViewA3->info();
746  auto const& iA4 = rdViewA4->info();
747 
748  BEAST_EXPECT(areCompatible(iA3.hash, iA3.seq, *rdViewA4, jStream, ""));
749  BEAST_EXPECT(areCompatible(iA4.hash, iA4.seq, *rdViewA3, jStream, ""));
750  BEAST_EXPECT(areCompatible(iA4.hash, iA4.seq, *rdViewA4, jStream, ""));
751  BEAST_EXPECT(!areCompatible(iA3.hash, iA3.seq, *rdViewB4, jStream, ""));
752  BEAST_EXPECT(areCompatible(iA4.hash, iA4.seq, *rdViewB3, jStream, ""));
753  BEAST_EXPECT(!areCompatible(iA4.hash, iA4.seq, *rdViewB4, jStream, ""));
754  }
755 
756  void
758  {
759  using namespace jtx;
760 
761  // Create a ledger with 1 item, put a
762  // ApplyView on that, then another ApplyView,
763  // erase the item, apply.
764  {
765  Env env(*this);
766  Config config;
767  std::shared_ptr<Ledger const> const genesis =
768  std::make_shared<Ledger>(
770  config,
772  env.app().family());
773  auto const ledger = std::make_shared<Ledger>(
774  *genesis, env.app().timeKeeper().closeTime());
775  wipe(*ledger);
776  ledger->rawInsert(sle(1));
777  ReadView& v0 = *ledger;
778  ApplyViewImpl v1(&v0, tapNONE);
779  {
780  Sandbox v2(&v1);
781  v2.erase(v2.peek(k(1)));
782  v2.apply(v1);
783  }
784  BEAST_EXPECT(!v1.exists(k(1)));
785  }
786 
787  // Make sure OpenLedger::empty works
788  {
789  Env env(*this);
790  BEAST_EXPECT(env.app().openLedger().empty());
791  env.fund(XRP(10000), Account("test"));
792  BEAST_EXPECT(!env.app().openLedger().empty());
793  }
794  }
795 
796  void
797  run() override
798  {
799  // This had better work, or else
800  BEAST_EXPECT(k(0).key < k(1).key);
801 
802  testLedger();
803  testMeta();
804  testMetaSucc();
805  testStacked();
806  testContext();
807  testSles();
808  testFlags();
811  testRegressions();
812  }
813 };
814 
815 class GetAmendments_test : public beast::unit_test::suite
816 {
817  void
819  {
820  using namespace jtx;
821  Env env{*this, envconfig(validator, "")};
822 
823  // Start out with no amendments.
824  auto majorities = getMajorityAmendments(*env.closed());
825  BEAST_EXPECT(majorities.empty());
826 
827  // Now close ledgers until the amendments show up.
828  int i = 0;
829  for (i = 0; i <= 256; ++i)
830  {
831  env.close();
832  majorities = getMajorityAmendments(*env.closed());
833  if (!majorities.empty())
834  break;
835  }
836 
837  // There should be at least 5 amendments. Don't do exact comparison
838  // to avoid maintenance as more amendments are added in the future.
839  BEAST_EXPECT(i == 254);
840  BEAST_EXPECT(majorities.size() >= 5);
841 
842  // None of the amendments should be enabled yet.
843  auto enableds = getEnabledAmendments(*env.closed());
844  BEAST_EXPECT(enableds.empty());
845 
846  // Now wait 2 weeks modulo 256 ledgers for the amendments to be
847  // enabled. Speed the process by closing ledgers every 80 minutes,
848  // which should get us to just past 2 weeks after 256 ledgers.
849  for (i = 0; i <= 256; ++i)
850  {
851  using namespace std::chrono_literals;
852  env.close(80min);
853  enableds = getEnabledAmendments(*env.closed());
854  if (!enableds.empty())
855  break;
856  }
857  BEAST_EXPECT(i == 255);
858  BEAST_EXPECT(enableds.size() >= 5);
859  }
860 
861  void
862  run() override
863  {
864  testGetAmendments();
865  }
866 };
867 
868 BEAST_DEFINE_TESTSUITE(View, ledger, ripple);
869 BEAST_DEFINE_TESTSUITE(GetAmendments, ledger, ripple);
870 
871 } // namespace test
872 } // namespace ripple
ripple::test::View_test::testMetaSucc
void testMetaSucc()
Definition: View_test.cpp:194
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:261
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:514
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:815
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:677
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:105
std::vector::reserve
T reserve(T... args)
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:52
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:210
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::sfSequence
const SF_U32 sfSequence(access, STI_UINT32, 4, "Sequence")
Definition: SField.h:355
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:385
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:141
ripple::ReadView::sles_type::upper_bound
iterator upper_bound(key_type const &key) const
Definition: ReadView.cpp:146
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:238
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::test::jtx::offer
Json::Value offer(Account const &account, STAmount const &in, STAmount const &out, std::uint32_t flags)
Create an offer.
Definition: offer.cpp:28
ripple::ReadView::parentCloseTime
NetClock::time_point parentCloseTime() const
Returns the close time of the previous ledger.
Definition: ReadView.h:249
ripple::test::View_test::sles
static std::vector< uint256 > sles(ReadView const &ledger)
Definition: View_test.cpp:368
ripple::Ledger::rawErase
void rawErase(std::shared_ptr< SLE > const &sle) override
Delete an existing state item.
Definition: Ledger.cpp:490
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:232
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:493
ripple::test::View_test::run
void run() override
Definition: View_test.cpp:797
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:757
ripple::Ledger
Holds a ledger.
Definition: Ledger.h:77
ripple::test::View_test::testContext
void testContext()
Definition: View_test.cpp:323
ripple::Config
Definition: Config.h:66
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:222
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:143
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:383
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:862
std::uint64_t
ripple::tfSetFreeze
const std::uint32_t tfSetFreeze
Definition: TxFlags.h:94
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:163
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::keylet::unchecked
Keylet unchecked(uint256 const &key)
Any ledger entry.
Definition: Indexes.cpp:290
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:216
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:406
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:188
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:256
ripple::test::jtx::Env::close
void close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:111
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:201
ripple::create_genesis
const create_genesis_t create_genesis
Definition: Ledger.cpp:56
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
Return the key of the next state item.
Definition: Ledger.cpp:395
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:148
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:818
ripple::test::View_test::testAreCompatible
void testAreCompatible()
Definition: View_test.cpp:699
ripple::test::View_test::testStacked
void testStacked()
Definition: View_test.cpp:258
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:379
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:297
ripple::xrpCurrency
Currency const & xrpCurrency()
XRP currency.
Definition: UintTypes.cpp:112
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:114
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:99
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:141
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