rippled
Loading...
Searching...
No Matches
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 <test/jtx.h>
21
22#include <xrpld/app/ledger/Ledger.h>
23#include <xrpld/core/ConfigSections.h>
24
25#include <xrpl/ledger/ApplyViewImpl.h>
26#include <xrpl/ledger/OpenView.h>
27#include <xrpl/ledger/PaymentSandbox.h>
28#include <xrpl/ledger/Sandbox.h>
29#include <xrpl/protocol/Feature.h>
30
31#include <type_traits>
32
33namespace ripple {
34namespace test {
35
37{
38 // Convert a small integer to a key
39 static Keylet
41 {
42 return Keylet{ltACCOUNT_ROOT, uint256(id)};
43 }
44
45 // Create SLE with key and payload
48 {
49 auto const le = std::make_shared<SLE>(k(id));
50 le->setFieldU32(sfSequence, seq);
51 return le;
52 }
53
54 // Return payload for SLE
55 template <class T>
56 static std::uint32_t
58 {
59 return le->getFieldU32(sfSequence);
60 }
61
62 // Set payload on SLE
63 static void
65 {
66 le->setFieldU32(sfSequence, seq);
67 }
68
69 // Erase all state items
70 static void
71 wipe(OpenLedger& openLedger)
72 {
73 openLedger.modify([](OpenView& view, beast::Journal) {
74 // HACK!
76 next.emplace(0);
77 for (;;)
78 {
79 next = view.succ(*next);
80 if (!next)
81 break;
83 *view.read(keylet::unchecked(*next))));
84 }
85 return true;
86 });
87 }
88
89 static void
90 wipe(Ledger& ledger)
91 {
92 // HACK!
94 next.emplace(0);
95 for (;;)
96 {
97 next = ledger.succ(*next);
98 if (!next)
99 break;
100 ledger.rawErase(
102 }
103 }
104
105 // Test succ correctness
106 void
108 ReadView const& v,
109 std::uint32_t id,
111 {
112 auto const next = v.succ(k(id).key);
113 if (answer)
114 {
115 if (BEAST_EXPECT(next))
116 BEAST_EXPECT(*next == k(*answer).key);
117 }
118 else
119 {
120 BEAST_EXPECT(!next);
121 }
122 }
123
124 template <class T>
127 {
129 }
130
131 // Exercise Ledger implementation of ApplyView
132 void
134 {
135 testcase("Ledger");
136
137 using namespace jtx;
138 Env env(*this);
139 Config config;
142 config,
144 env.app().getNodeFamily());
145 auto const ledger = std::make_shared<Ledger>(
146 *genesis, env.app().timeKeeper().closeTime());
147 wipe(*ledger);
148 ReadView& v = *ledger;
149 succ(v, 0, std::nullopt);
150 ledger->rawInsert(sle(1, 1));
151 BEAST_EXPECT(v.exists(k(1)));
152 BEAST_EXPECT(seq(v.read(k(1))) == 1);
153 succ(v, 0, 1);
154 succ(v, 1, std::nullopt);
155 ledger->rawInsert(sle(2, 2));
156 BEAST_EXPECT(seq(v.read(k(2))) == 2);
157 ledger->rawInsert(sle(3, 3));
158 BEAST_EXPECT(seq(v.read(k(3))) == 3);
159 auto s = copy(v.read(k(2)));
160 seq(s, 4);
161 ledger->rawReplace(s);
162 BEAST_EXPECT(seq(v.read(k(2))) == 4);
163 ledger->rawErase(sle(2));
164 BEAST_EXPECT(!v.exists(k(2)));
165 BEAST_EXPECT(v.exists(k(1)));
166 BEAST_EXPECT(v.exists(k(3)));
167 }
168
169 void
171 {
172 testcase("Meta");
173
174 using namespace jtx;
175 Env env(*this);
176 wipe(env.app().openLedger());
177 auto const open = env.current();
179 succ(v, 0, std::nullopt);
180 v.insert(sle(1));
181 BEAST_EXPECT(v.exists(k(1)));
182 BEAST_EXPECT(seq(v.read(k(1))) == 1);
183 BEAST_EXPECT(seq(v.peek(k(1))) == 1);
184 succ(v, 0, 1);
185 succ(v, 1, std::nullopt);
186 v.insert(sle(2, 2));
187 BEAST_EXPECT(seq(v.read(k(2))) == 2);
188 v.insert(sle(3, 3));
189 auto s = v.peek(k(3));
190 BEAST_EXPECT(seq(s) == 3);
191 s = v.peek(k(2));
192 seq(s, 4);
193 v.update(s);
194 BEAST_EXPECT(seq(v.read(k(2))) == 4);
195 v.erase(s);
196 BEAST_EXPECT(!v.exists(k(2)));
197 BEAST_EXPECT(v.exists(k(1)));
198 BEAST_EXPECT(v.exists(k(3)));
199 }
200
201 // Exercise all succ paths
202 void
204 {
205 testcase("Meta succ");
206
207 using namespace jtx;
208 Env env(*this);
209 wipe(env.app().openLedger());
210 auto const open = env.current();
212 v0.insert(sle(1));
213 v0.insert(sle(2));
214 v0.insert(sle(4));
215 v0.insert(sle(7));
216 {
217 Sandbox v1(&v0);
218 v1.insert(sle(3));
219 v1.insert(sle(5));
220 v1.insert(sle(6));
221
222 // v0: 12-4--7
223 // v1: --3-56-
224
225 succ(v0, 0, 1);
226 succ(v0, 1, 2);
227 succ(v0, 2, 4);
228 succ(v0, 3, 4);
229 succ(v0, 4, 7);
230 succ(v0, 5, 7);
231 succ(v0, 6, 7);
232 succ(v0, 7, std::nullopt);
233
234 succ(v1, 0, 1);
235 succ(v1, 1, 2);
236 succ(v1, 2, 3);
237 succ(v1, 3, 4);
238 succ(v1, 4, 5);
239 succ(v1, 5, 6);
240 succ(v1, 6, 7);
241 succ(v1, 7, std::nullopt);
242
243 v1.erase(v1.peek(k(4)));
244 succ(v1, 3, 5);
245
246 v1.erase(v1.peek(k(6)));
247 succ(v1, 5, 7);
248 succ(v1, 6, 7);
249
250 // v0: 12----7
251 // v1: --3-5--
252
253 v1.apply(v0);
254 }
255
256 // v0: 123-5-7
257
258 succ(v0, 0, 1);
259 succ(v0, 1, 2);
260 succ(v0, 2, 3);
261 succ(v0, 3, 5);
262 succ(v0, 4, 5);
263 succ(v0, 5, 7);
264 succ(v0, 6, 7);
265 succ(v0, 7, std::nullopt);
266 }
267
268 void
270 {
271 testcase("Stacked");
272
273 using namespace jtx;
274 Env env(*this);
275 wipe(env.app().openLedger());
276 auto const open = env.current();
278 v0.rawInsert(sle(1, 1));
279 v0.rawInsert(sle(2, 2));
280 v0.rawInsert(sle(4, 4));
281
282 {
283 Sandbox v1(&v0);
284 v1.erase(v1.peek(k(2)));
285 v1.insert(sle(3, 3));
286 auto s = v1.peek(k(4));
287 seq(s, 5);
288 v1.update(s);
289 BEAST_EXPECT(seq(v1.read(k(1))) == 1);
290 BEAST_EXPECT(!v1.exists(k(2)));
291 BEAST_EXPECT(seq(v1.read(k(3))) == 3);
292 BEAST_EXPECT(seq(v1.read(k(4))) == 5);
293 {
294 Sandbox v2(&v1);
295 auto s2 = v2.peek(k(3));
296 seq(s2, 6);
297 v2.update(s2);
298 v2.erase(v2.peek(k(4)));
299 BEAST_EXPECT(seq(v2.read(k(1))) == 1);
300 BEAST_EXPECT(!v2.exists(k(2)));
301 BEAST_EXPECT(seq(v2.read(k(3))) == 6);
302 BEAST_EXPECT(!v2.exists(k(4)));
303 // discard v2
304 }
305 BEAST_EXPECT(seq(v1.read(k(1))) == 1);
306 BEAST_EXPECT(!v1.exists(k(2)));
307 BEAST_EXPECT(seq(v1.read(k(3))) == 3);
308 BEAST_EXPECT(seq(v1.read(k(4))) == 5);
309
310 {
311 Sandbox v2(&v1);
312 auto s2 = v2.peek(k(3));
313 seq(s2, 6);
314 v2.update(s2);
315 v2.erase(v2.peek(k(4)));
316 BEAST_EXPECT(seq(v2.read(k(1))) == 1);
317 BEAST_EXPECT(!v2.exists(k(2)));
318 BEAST_EXPECT(seq(v2.read(k(3))) == 6);
319 BEAST_EXPECT(!v2.exists(k(4)));
320 v2.apply(v1);
321 }
322 BEAST_EXPECT(seq(v1.read(k(1))) == 1);
323 BEAST_EXPECT(!v1.exists(k(2)));
324 BEAST_EXPECT(seq(v1.read(k(3))) == 6);
325 BEAST_EXPECT(!v1.exists(k(4)));
326 v1.apply(v0);
327 }
328 BEAST_EXPECT(seq(v0.read(k(1))) == 1);
329 BEAST_EXPECT(!v0.exists(k(2)));
330 BEAST_EXPECT(seq(v0.read(k(3))) == 6);
331 BEAST_EXPECT(!v0.exists(k(4)));
332 }
333
334 // Verify contextual information
335 void
337 {
338 testcase("Context");
339
340 using namespace jtx;
341 using namespace std::chrono;
342 {
343 Env env(*this);
344 wipe(env.app().openLedger());
345 auto const open = env.current();
346 OpenView v0(open.get());
347 BEAST_EXPECT(v0.seq() != 98);
348 BEAST_EXPECT(v0.seq() == open->seq());
349 BEAST_EXPECT(v0.parentCloseTime() != NetClock::time_point{99s});
350 BEAST_EXPECT(v0.parentCloseTime() == open->parentCloseTime());
351 {
352 // shallow copy
353 OpenView v1(v0);
354 BEAST_EXPECT(v1.seq() == v0.seq());
355 BEAST_EXPECT(v1.parentCloseTime() == v1.parentCloseTime());
356
357 ApplyViewImpl v2(&v1, tapRETRY);
358 BEAST_EXPECT(v2.parentCloseTime() == v1.parentCloseTime());
359 BEAST_EXPECT(v2.seq() == v1.seq());
360 BEAST_EXPECT(v2.flags() == tapRETRY);
361
362 Sandbox v3(&v2);
363 BEAST_EXPECT(v3.seq() == v2.seq());
364 BEAST_EXPECT(v3.parentCloseTime() == v2.parentCloseTime());
365 BEAST_EXPECT(v3.flags() == tapRETRY);
366 }
367 {
368 ApplyViewImpl v1(&v0, tapRETRY);
369 PaymentSandbox v2(&v1);
370 BEAST_EXPECT(v2.seq() == v0.seq());
371 BEAST_EXPECT(v2.parentCloseTime() == v0.parentCloseTime());
372 BEAST_EXPECT(v2.flags() == tapRETRY);
373 PaymentSandbox v3(&v2);
374 BEAST_EXPECT(v3.seq() == v2.seq());
375 BEAST_EXPECT(v3.parentCloseTime() == v2.parentCloseTime());
376 BEAST_EXPECT(v3.flags() == v2.flags());
377 }
378 }
379 }
380
381 // Return a list of keys found via sles
383 sles(ReadView const& ledger)
384 {
386 v.reserve(32);
387 for (auto const& sle : ledger.sles)
388 v.push_back(sle->key());
389 return v;
390 }
391
392 template <class... Args>
394 list(Args... args)
395 {
396 return std::vector<uint256>({uint256(args)...});
397 }
398
399 void
401 {
402 testcase("Upper and lower bound");
403
404 using namespace jtx;
405 Env env(*this);
406 Config config;
409 config,
411 env.app().getNodeFamily());
412 auto const ledger = std::make_shared<Ledger>(
413 *genesis, env.app().timeKeeper().closeTime());
414
415 auto setup = [&ledger](std::vector<int> const& vec) {
416 wipe(*ledger);
417 for (auto x : vec)
418 {
419 ledger->rawInsert(sle(x));
420 }
421 };
422 {
423 setup({1, 2, 3});
424 BEAST_EXPECT(sles(*ledger) == list(1, 2, 3));
425 auto e = ledger->stateMap().end();
426 auto b1 = ledger->stateMap().begin();
427 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(1)) == e);
428 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(2)) == b1);
429 ++b1;
430 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(3)) == b1);
431 ++b1;
432 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(4)) == b1);
433 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(5)) == b1);
434 b1 = ledger->stateMap().begin();
435 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(0)) == b1);
436 ++b1;
437 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(1)) == b1);
438 ++b1;
439 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(2)) == b1);
440 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(3)) == e);
441 }
442
443 {
444 setup({2, 4, 6});
445 BEAST_EXPECT(sles(*ledger) == list(2, 4, 6));
446 auto e = ledger->stateMap().end();
447 auto b1 = ledger->stateMap().begin();
448 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(1)) == e);
449 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(2)) == e);
450 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(3)) == b1);
451 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(4)) == b1);
452 ++b1;
453 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(5)) == b1);
454 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(6)) == b1);
455 ++b1;
456 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(7)) == b1);
457 b1 = ledger->stateMap().begin();
458 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(1)) == b1);
459 ++b1;
460 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(2)) == b1);
461 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(3)) == b1);
462 ++b1;
463
464 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(4)) == b1);
465 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(5)) == b1);
466 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(6)) == e);
467 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(7)) == e);
468 }
469 {
470 setup({2, 3, 5, 6, 10, 15});
471 BEAST_EXPECT(sles(*ledger) == list(2, 3, 5, 6, 10, 15));
472 auto e = ledger->stateMap().end();
473 auto b = ledger->stateMap().begin();
474 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(1)) == e);
475 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(2)) == e);
476 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(3)) == b);
477 ++b;
478 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(4)) == b);
479 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(5)) == b);
480 ++b;
481 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(6)) == b);
482 ++b;
483 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(7)) == b);
484 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(8)) == b);
485 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(9)) == b);
486 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(10)) == b);
487 ++b;
488 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(11)) == b);
489 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(12)) == b);
490 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(13)) == b);
491 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(14)) == b);
492 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(15)) == b);
493 ++b;
494 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(16)) == b);
495 b = ledger->stateMap().begin();
496 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(0)) == b);
497 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(1)) == b);
498 ++b;
499 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(2)) == b);
500 ++b;
501 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(3)) == b);
502 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(4)) == b);
503 ++b;
504 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(5)) == b);
505 ++b;
506 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(6)) == b);
507 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(7)) == b);
508 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(8)) == b);
509 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(9)) == b);
510 ++b;
511 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(10)) == b);
512 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(11)) == b);
513 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(12)) == b);
514 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(13)) == b);
515 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(14)) == b);
516 ++b;
517 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(15)) == e);
518 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(16)) == e);
519 }
520 {
521 // some full trees, some empty trees, etc
522 setup({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
523 13, 14, 15, 16, 20, 25, 30, 32, 33, 34, 35, 36, 37,
524 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 66, 100});
525 BEAST_EXPECT(
526 sles(*ledger) ==
527 list(
528 0,
529 1,
530 2,
531 3,
532 4,
533 5,
534 6,
535 7,
536 8,
537 9,
538 10,
539 11,
540 12,
541 13,
542 14,
543 15,
544 16,
545 20,
546 25,
547 30,
548 32,
549 33,
550 34,
551 35,
552 36,
553 37,
554 38,
555 39,
556 40,
557 41,
558 42,
559 43,
560 44,
561 45,
562 46,
563 47,
564 48,
565 66,
566 100));
567 auto b = ledger->stateMap().begin();
568 auto e = ledger->stateMap().end();
569 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(0)) == e);
570 BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(1)) == b);
571 BEAST_EXPECT(
572 ledger->stateMap().lower_bound(uint256(5))->key() ==
573 uint256(4));
574 BEAST_EXPECT(
575 ledger->stateMap().lower_bound(uint256(15))->key() ==
576 uint256(14));
577 BEAST_EXPECT(
578 ledger->stateMap().lower_bound(uint256(16))->key() ==
579 uint256(15));
580 BEAST_EXPECT(
581 ledger->stateMap().lower_bound(uint256(19))->key() ==
582 uint256(16));
583 BEAST_EXPECT(
584 ledger->stateMap().lower_bound(uint256(20))->key() ==
585 uint256(16));
586 BEAST_EXPECT(
587 ledger->stateMap().lower_bound(uint256(24))->key() ==
588 uint256(20));
589 BEAST_EXPECT(
590 ledger->stateMap().lower_bound(uint256(31))->key() ==
591 uint256(30));
592 BEAST_EXPECT(
593 ledger->stateMap().lower_bound(uint256(32))->key() ==
594 uint256(30));
595 BEAST_EXPECT(
596 ledger->stateMap().lower_bound(uint256(40))->key() ==
597 uint256(39));
598 BEAST_EXPECT(
599 ledger->stateMap().lower_bound(uint256(47))->key() ==
600 uint256(46));
601 BEAST_EXPECT(
602 ledger->stateMap().lower_bound(uint256(48))->key() ==
603 uint256(47));
604 BEAST_EXPECT(
605 ledger->stateMap().lower_bound(uint256(64))->key() ==
606 uint256(48));
607
608 BEAST_EXPECT(
609 ledger->stateMap().lower_bound(uint256(90))->key() ==
610 uint256(66));
611 BEAST_EXPECT(
612 ledger->stateMap().lower_bound(uint256(96))->key() ==
613 uint256(66));
614 BEAST_EXPECT(
615 ledger->stateMap().lower_bound(uint256(100))->key() ==
616 uint256(66));
617
618 BEAST_EXPECT(
619 ledger->stateMap().upper_bound(uint256(0))->key() ==
620 uint256(1));
621 BEAST_EXPECT(
622 ledger->stateMap().upper_bound(uint256(5))->key() ==
623 uint256(6));
624 BEAST_EXPECT(
625 ledger->stateMap().upper_bound(uint256(15))->key() ==
626 uint256(16));
627 BEAST_EXPECT(
628 ledger->stateMap().upper_bound(uint256(16))->key() ==
629 uint256(20));
630 BEAST_EXPECT(
631 ledger->stateMap().upper_bound(uint256(18))->key() ==
632 uint256(20));
633 BEAST_EXPECT(
634 ledger->stateMap().upper_bound(uint256(20))->key() ==
635 uint256(25));
636 BEAST_EXPECT(
637 ledger->stateMap().upper_bound(uint256(31))->key() ==
638 uint256(32));
639 BEAST_EXPECT(
640 ledger->stateMap().upper_bound(uint256(32))->key() ==
641 uint256(33));
642 BEAST_EXPECT(
643 ledger->stateMap().upper_bound(uint256(47))->key() ==
644 uint256(48));
645 BEAST_EXPECT(
646 ledger->stateMap().upper_bound(uint256(48))->key() ==
647 uint256(66));
648 BEAST_EXPECT(
649 ledger->stateMap().upper_bound(uint256(53))->key() ==
650 uint256(66));
651 BEAST_EXPECT(
652 ledger->stateMap().upper_bound(uint256(66))->key() ==
653 uint256(100));
654 BEAST_EXPECT(
655 ledger->stateMap().upper_bound(uint256(70))->key() ==
656 uint256(100));
657 BEAST_EXPECT(
658 ledger->stateMap().upper_bound(uint256(85))->key() ==
659 uint256(100));
660 BEAST_EXPECT(
661 ledger->stateMap().upper_bound(uint256(98))->key() ==
662 uint256(100));
663 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(100)) == e);
664 BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(155)) == e);
665 }
666 }
667
668 void
670 {
671 testcase("Sles");
672
673 using namespace jtx;
674 Env env(*this);
675 Config config;
678 config,
680 env.app().getNodeFamily());
681 auto const ledger = std::make_shared<Ledger>(
682 *genesis, env.app().timeKeeper().closeTime());
683 auto setup123 = [&ledger, this]() {
684 // erase middle element
685 wipe(*ledger);
686 ledger->rawInsert(sle(1));
687 ledger->rawInsert(sle(2));
688 ledger->rawInsert(sle(3));
689 BEAST_EXPECT(sles(*ledger) == list(1, 2, 3));
690 };
691 {
692 setup123();
693 OpenView view(ledger.get());
694 view.rawErase(sle(1));
695 view.rawInsert(sle(4));
696 view.rawInsert(sle(5));
697 BEAST_EXPECT(sles(view) == list(2, 3, 4, 5));
698 auto b = view.sles.begin();
699 BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
700 ++b;
701 BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
702 ++b;
703 BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
704 ++b;
705 BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
706 ++b;
707 BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
708 }
709 {
710 setup123();
711 OpenView view(ledger.get());
712 view.rawErase(sle(1));
713 view.rawErase(sle(2));
714 view.rawInsert(sle(4));
715 view.rawInsert(sle(5));
716 BEAST_EXPECT(sles(view) == list(3, 4, 5));
717 auto b = view.sles.begin();
718 BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
719 BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
720 ++b;
721 BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
722 ++b;
723 BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
724 ++b;
725 BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
726 }
727 {
728 setup123();
729 OpenView view(ledger.get());
730 view.rawErase(sle(1));
731 view.rawErase(sle(2));
732 view.rawErase(sle(3));
733 view.rawInsert(sle(4));
734 view.rawInsert(sle(5));
735 BEAST_EXPECT(sles(view) == list(4, 5));
736 auto b = view.sles.begin();
737 BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
738 BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
739 BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
740 ++b;
741 BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
742 ++b;
743 BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
744 }
745 {
746 setup123();
747 OpenView view(ledger.get());
748 view.rawErase(sle(3));
749 view.rawInsert(sle(4));
750 view.rawInsert(sle(5));
751 BEAST_EXPECT(sles(view) == list(1, 2, 4, 5));
752 auto b = view.sles.begin();
753 ++b;
754 BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
755 ++b;
756 BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
757 BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
758 ++b;
759 BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
760 ++b;
761 BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
762 }
763 {
764 setup123();
765 OpenView view(ledger.get());
766 view.rawReplace(sle(1, 10));
767 view.rawReplace(sle(3, 30));
768 BEAST_EXPECT(sles(view) == list(1, 2, 3));
769 BEAST_EXPECT(seq(view.read(k(1))) == 10);
770 BEAST_EXPECT(seq(view.read(k(2))) == 1);
771 BEAST_EXPECT(seq(view.read(k(3))) == 30);
772
773 view.rawErase(sle(3));
774 BEAST_EXPECT(sles(view) == list(1, 2));
775 auto b = view.sles.begin();
776 ++b;
777 BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
778 ++b;
779 BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
780 BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
781 BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
782 BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
783
784 view.rawInsert(sle(5));
785 view.rawInsert(sle(4));
786 view.rawInsert(sle(3));
787 BEAST_EXPECT(sles(view) == list(1, 2, 3, 4, 5));
788 b = view.sles.begin();
789 ++b;
790 BEAST_EXPECT(view.sles.upper_bound(uint256(1)) == b);
791 ++b;
792 BEAST_EXPECT(view.sles.upper_bound(uint256(2)) == b);
793 ++b;
794 BEAST_EXPECT(view.sles.upper_bound(uint256(3)) == b);
795 ++b;
796 BEAST_EXPECT(view.sles.upper_bound(uint256(4)) == b);
797 ++b;
798 BEAST_EXPECT(view.sles.upper_bound(uint256(5)) == b);
799 }
800 }
801
802 void
804 {
805 testcase("Flags");
806
807 using namespace jtx;
808 Env env(*this);
809
810 auto const alice = Account("alice");
811 auto const bob = Account("bob");
812 auto const carol = Account("carol");
813 auto const gw = Account("gateway");
814 auto const USD = gw["USD"];
815 auto const EUR = gw["EUR"];
816
817 env.fund(XRP(10000), alice, bob, carol, gw);
818 env.close();
819 env.trust(USD(100), alice, bob, carol);
820 {
821 // Global freezing.
822 env(pay(gw, alice, USD(50)));
823 env(offer(alice, XRP(5), USD(5)));
824
825 // Now freeze gw.
826 env(fset(gw, asfGlobalFreeze));
827 env.close();
828 env(offer(alice, XRP(4), USD(5)), ter(tecFROZEN));
829 env.close();
830
831 // Alice's USD balance should be zero if frozen.
832 BEAST_EXPECT(
833 USD(0) ==
835 *env.closed(),
836 alice,
837 USD.currency,
838 gw,
840 env.journal));
841
842 // Thaw gw and try again.
843 env(fclear(gw, asfGlobalFreeze));
844 env.close();
845 env(offer("alice", XRP(4), USD(5)));
846 }
847 {
848 // Local freezing.
849 env(pay(gw, bob, USD(50)));
850 env.close();
851
852 // Now gw freezes bob's USD trust line.
853 env(trust(gw, USD(100), bob, tfSetFreeze));
854 env.close();
855
856 // Bob's balance should be zero if frozen.
857 BEAST_EXPECT(
858 USD(0) ==
860 *env.closed(),
861 bob,
862 USD.currency,
863 gw,
865 env.journal));
866
867 // gw thaws bob's trust line. bob gets his money back.
868 env(trust(gw, USD(100), bob, tfClearFreeze));
869 env.close();
870 BEAST_EXPECT(
871 USD(50) ==
873 *env.closed(),
874 bob,
875 USD.currency,
876 gw,
878 env.journal));
879 }
880 {
881 // accountHolds().
882 env(pay(gw, carol, USD(50)));
883 env.close();
884
885 // carol has no EUR.
886 BEAST_EXPECT(
887 EUR(0) ==
889 *env.closed(),
890 carol,
891 EUR.currency,
892 gw,
894 env.journal));
895
896 // But carol does have USD.
897 BEAST_EXPECT(
898 USD(50) ==
900 *env.closed(),
901 carol,
902 USD.currency,
903 gw,
905 env.journal));
906
907 // carol's XRP balance should be her holdings minus her reserve.
908 auto const carolsXRP = accountHolds(
909 *env.closed(),
910 carol,
911 xrpCurrency(),
912 xrpAccount(),
914 env.journal);
915 // carol's XRP balance: 10000
916 // base reserve: -200
917 // 1 trust line times its reserve: 1 * -50
918 // -------
919 // carol's available balance: 9750
920 BEAST_EXPECT(carolsXRP == XRP(9750));
921
922 // carol should be able to spend *more* than her XRP balance on
923 // a fee by eating into her reserve.
924 env(noop(carol), fee(carolsXRP + XRP(10)));
925 env.close();
926
927 // carol's XRP balance should now show as zero.
928 BEAST_EXPECT(
929 XRP(0) ==
931 *env.closed(),
932 carol,
933 xrpCurrency(),
934 gw,
936 env.journal));
937 }
938 {
939 // accountFunds().
940 // Gateways have whatever funds they claim to have.
941 auto const gwUSD = accountFunds(
942 *env.closed(), gw, USD(314159), fhZERO_IF_FROZEN, env.journal);
943 BEAST_EXPECT(gwUSD == USD(314159));
944
945 // carol has funds from the gateway.
946 auto carolsUSD = accountFunds(
947 *env.closed(), carol, USD(0), fhZERO_IF_FROZEN, env.journal);
948 BEAST_EXPECT(carolsUSD == USD(50));
949
950 // If carol's funds are frozen she has no funds...
951 env(fset(gw, asfGlobalFreeze));
952 env.close();
953 carolsUSD = accountFunds(
954 *env.closed(), carol, USD(0), fhZERO_IF_FROZEN, env.journal);
955 BEAST_EXPECT(carolsUSD == USD(0));
956
957 // ... unless the query ignores the FROZEN state.
958 carolsUSD = accountFunds(
959 *env.closed(), carol, USD(0), fhIGNORE_FREEZE, env.journal);
960 BEAST_EXPECT(carolsUSD == USD(50));
961
962 // Just to be tidy, thaw gw.
963 env(fclear(gw, asfGlobalFreeze));
964 env.close();
965 }
966 }
967
968 void
970 {
971 testcase("Transfer rate");
972
973 using namespace jtx;
974 Env env(*this);
975
976 auto const gw1 = Account("gw1");
977
978 env.fund(XRP(10000), gw1);
979 env.close();
980
981 auto rdView = env.closed();
982 // Test with no rate set on gw1.
983 BEAST_EXPECT(transferRate(*rdView, gw1) == parityRate);
984
985 env(rate(gw1, 1.02));
986 env.close();
987
988 rdView = env.closed();
989 BEAST_EXPECT(transferRate(*rdView, gw1) == Rate{1020000000});
990 }
991
992 void
994 {
995 // This test requires incompatible ledgers. The good news we can
996 // construct and manage two different Env instances at the same
997 // time. So we can use two Env instances to produce mutually
998 // incompatible ledgers.
999 testcase("Are compatible");
1000
1001 using namespace jtx;
1002 auto const alice = Account("alice");
1003 auto const bob = Account("bob");
1004
1005 // The first Env.
1006 Env eA(*this, envconfig(), nullptr, beast::severities::kDisabled);
1007
1008 eA.fund(XRP(10000), alice);
1009 eA.close();
1010 auto const rdViewA3 = eA.closed();
1011
1012 eA.fund(XRP(10000), bob);
1013 eA.close();
1014 auto const rdViewA4 = eA.closed();
1015
1016 // The two Env's can't share the same ports, so modify the config
1017 // of the second Env to use higher port numbers
1018 Env eB{*this, envconfig(), nullptr, beast::severities::kDisabled};
1019
1020 // Make ledgers that are incompatible with the first ledgers. Note
1021 // that bob is funded before alice.
1022 eB.fund(XRP(10000), bob);
1023 eB.close();
1024 auto const rdViewB3 = eB.closed();
1025
1026 eB.fund(XRP(10000), alice);
1027 eB.close();
1028 auto const rdViewB4 = eB.closed();
1029
1030 // Check for compatibility.
1031 auto jStream = eA.journal.error();
1032 BEAST_EXPECT(areCompatible(*rdViewA3, *rdViewA4, jStream, ""));
1033 BEAST_EXPECT(areCompatible(*rdViewA4, *rdViewA3, jStream, ""));
1034 BEAST_EXPECT(areCompatible(*rdViewA4, *rdViewA4, jStream, ""));
1035 BEAST_EXPECT(!areCompatible(*rdViewA3, *rdViewB4, jStream, ""));
1036 BEAST_EXPECT(!areCompatible(*rdViewA4, *rdViewB3, jStream, ""));
1037 BEAST_EXPECT(!areCompatible(*rdViewA4, *rdViewB4, jStream, ""));
1038
1039 // Try the other interface.
1040 // Note that the different interface has different outcomes.
1041 auto const& iA3 = rdViewA3->info();
1042 auto const& iA4 = rdViewA4->info();
1043
1044 BEAST_EXPECT(areCompatible(iA3.hash, iA3.seq, *rdViewA4, jStream, ""));
1045 BEAST_EXPECT(areCompatible(iA4.hash, iA4.seq, *rdViewA3, jStream, ""));
1046 BEAST_EXPECT(areCompatible(iA4.hash, iA4.seq, *rdViewA4, jStream, ""));
1047 BEAST_EXPECT(!areCompatible(iA3.hash, iA3.seq, *rdViewB4, jStream, ""));
1048 BEAST_EXPECT(areCompatible(iA4.hash, iA4.seq, *rdViewB3, jStream, ""));
1049 BEAST_EXPECT(!areCompatible(iA4.hash, iA4.seq, *rdViewB4, jStream, ""));
1050 }
1051
1052 void
1054 {
1055 testcase("Regressions");
1056
1057 using namespace jtx;
1058
1059 // Create a ledger with 1 item, put a
1060 // ApplyView on that, then another ApplyView,
1061 // erase the item, apply.
1062 {
1063 Env env(*this);
1064 Config config;
1065 std::shared_ptr<Ledger const> const genesis =
1068 config,
1070 env.app().getNodeFamily());
1071 auto const ledger = std::make_shared<Ledger>(
1072 *genesis, env.app().timeKeeper().closeTime());
1073 wipe(*ledger);
1074 ledger->rawInsert(sle(1));
1075 ReadView& v0 = *ledger;
1076 ApplyViewImpl v1(&v0, tapNONE);
1077 {
1078 Sandbox v2(&v1);
1079 v2.erase(v2.peek(k(1)));
1080 v2.apply(v1);
1081 }
1082 BEAST_EXPECT(!v1.exists(k(1)));
1083 }
1084
1085 // Make sure OpenLedger::empty works
1086 {
1087 Env env(*this);
1088 BEAST_EXPECT(env.app().openLedger().empty());
1089 env.fund(XRP(10000), Account("test"));
1090 BEAST_EXPECT(!env.app().openLedger().empty());
1091 }
1092 }
1093
1094 void
1095 run() override
1096 {
1097 // This had better work, or else
1098 BEAST_EXPECT(k(0).key < k(1).key);
1099
1100 testLedger();
1101 testMeta();
1102 testMetaSucc();
1103 testStacked();
1104 testContext();
1105 testSles();
1107 testFlags();
1111 }
1112};
1113
1115{
1116 void
1118 {
1119 using namespace jtx;
1120 Env env{*this, envconfig(validator, "")};
1121
1122 // Start out with no amendments.
1123 auto majorities = getMajorityAmendments(*env.closed());
1124 BEAST_EXPECT(majorities.empty());
1125
1126 // Now close ledgers until the amendments show up.
1127 int i = 0;
1128 for (i = 0; i <= 256; ++i)
1129 {
1130 env.close();
1131 majorities = getMajorityAmendments(*env.closed());
1132 if (!majorities.empty())
1133 break;
1134 }
1135
1136 // There should be at least 5 amendments. Don't do exact comparison
1137 // to avoid maintenance as more amendments are added in the future.
1138 BEAST_EXPECT(i == 254);
1139 BEAST_EXPECT(majorities.size() >= 5);
1140
1141 // None of the amendments should be enabled yet.
1142 auto enableds = getEnabledAmendments(*env.closed());
1143 BEAST_EXPECT(enableds.empty());
1144
1145 // Now wait 2 weeks modulo 256 ledgers for the amendments to be
1146 // enabled. Speed the process by closing ledgers every 80 minutes,
1147 // which should get us to just past 2 weeks after 256 ledgers.
1148 for (i = 0; i <= 256; ++i)
1149 {
1150 using namespace std::chrono_literals;
1151 env.close(80min);
1152 enableds = getEnabledAmendments(*env.closed());
1153 if (!enableds.empty())
1154 break;
1155 }
1156 BEAST_EXPECT(i == 255);
1157 BEAST_EXPECT(enableds.size() >= 5);
1158 }
1159
1160 void
1161 run() override
1162 {
1164 }
1165};
1166
1167BEAST_DEFINE_TESTSUITE(View, ledger, ripple);
1168BEAST_DEFINE_TESTSUITE(GetAmendments, ledger, ripple);
1169
1170} // namespace test
1171} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:60
Stream error() const
Definition Journal.h:346
A testsuite class.
Definition suite.h:55
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:155
virtual OpenLedger & openLedger()=0
virtual TimeKeeper & timeKeeper()=0
Editable, discardable view that can build metadata for one tx.
Holds a ledger.
Definition Ledger.h:80
void rawErase(std::shared_ptr< SLE > const &sle) override
Delete an existing state item.
Definition Ledger.cpp:515
std::shared_ptr< SLE const > read(Keylet const &k) const override
Return the state item associated with a key.
Definition Ledger.cpp:432
std::optional< uint256 > succ(uint256 const &key, std::optional< uint256 > const &last=std::nullopt) const override
Definition Ledger.cpp:421
Represents the open ledger.
Definition OpenLedger.h:52
bool modify(modify_type const &f)
Modify the open ledger.
bool empty() const
Returns true if there are no transactions.
Writable ledger view that accumulates state and tx changes.
Definition OpenView.h:65
std::optional< key_type > succ(key_type const &key, std::optional< key_type > const &last=std::nullopt) const override
Return the key of the next state item.
Definition OpenView.cpp:162
std::shared_ptr< SLE const > read(Keylet const &k) const override
Return the state item associated with a key.
Definition OpenView.cpp:169
void rawErase(std::shared_ptr< SLE > const &sle) override
Delete an existing state item.
Definition OpenView.cpp:231
void rawReplace(std::shared_ptr< SLE > const &sle) override
Unconditionally replace a state item.
Definition OpenView.cpp:243
void rawInsert(std::shared_ptr< SLE > const &sle) override
Unconditionally insert a state item.
Definition OpenView.cpp:237
A wrapper which makes credits unavailable to balances.
A view into a ledger.
Definition ReadView.h:51
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
NetClock::time_point parentCloseTime() const
Returns the close time of the previous ledger.
Definition ReadView.h:111
virtual std::optional< key_type > succ(key_type const &key, std::optional< key_type > const &last=std::nullopt) const =0
Return the key of the next state item.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
LedgerIndex seq() const
Returns the sequence number of the base ledger.
Definition ReadView.h:118
sles_type sles
Iterable range of ledger state items.
Definition ReadView.h:245
Discardable, editable view to a ledger.
Definition Sandbox.h:35
void apply(RawView &to)
Definition Sandbox.h:55
time_point closeTime() const
Returns the predicted close time, in network time.
Definition TimeKeeper.h:76
void erase(std::shared_ptr< SLE > const &sle) override
Remove a peeked SLE.
void update(std::shared_ptr< SLE > const &sle) override
Indicate changes to a peeked SLE.
void insert(std::shared_ptr< SLE > const &sle) override
Insert a new state SLE.
void rawInsert(std::shared_ptr< SLE > const &sle) override
Unconditionally insert a state item.
bool exists(Keylet const &k) const override
Determine if a state item exists.
ApplyFlags flags() const override
Returns the tx apply flags.
std::shared_ptr< SLE const > read(Keylet const &k) const override
Return the state item associated with a key.
std::shared_ptr< SLE > peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
void run() override
Runs the suite.
static std::shared_ptr< SLE > sle(std::uint64_t id, std::uint32_t seq=1)
Definition View_test.cpp:47
static void wipe(Ledger &ledger)
Definition View_test.cpp:90
static void seq(std::shared_ptr< SLE > const &le, std::uint32_t seq)
Definition View_test.cpp:64
void succ(ReadView const &v, std::uint32_t id, std::optional< std::uint32_t > answer)
static Keylet k(std::uint64_t id)
Definition View_test.cpp:40
static void wipe(OpenLedger &openLedger)
Definition View_test.cpp:71
static std::shared_ptr< std::remove_const_t< T > > copy(std::shared_ptr< T > const &sp)
static std::vector< uint256 > sles(ReadView const &ledger)
void run() override
Runs the suite.
static std::uint32_t seq(std::shared_ptr< T > const &le)
Definition View_test.cpp:57
static std::vector< uint256 > list(Args... args)
Immutable cryptographic account descriptor.
Definition Account.h:39
A transaction testing environment.
Definition Env.h:121
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
Definition Env.cpp:115
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition Env.h:331
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:121
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Definition Env.cpp:320
Application & app()
Definition Env.h:261
beast::Journal const journal
Definition Env.h:162
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:289
Set the fee on a JTx.
Definition fee.h:37
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition ter.h:35
T is_same_v
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Definition Indexes.cpp:368
std::unique_ptr< Config > validator(std::unique_ptr< Config >, std::string const &)
adjust configuration with params needed to be a validator
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition flags.h:121
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition trust.cpp:32
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition flags.cpp:29
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition pay.cpp:30
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:54
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Definition rate.cpp:32
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
Definition offer.cpp:29
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:111
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
constexpr std::uint32_t asfGlobalFreeze
Definition TxFlags.h:83
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
Definition View.cpp:551
@ fhZERO_IF_FROZEN
Definition View.h:77
@ fhIGNORE_FREEZE
Definition View.h:77
bool areCompatible(ReadView const &validLedger, ReadView const &testLedger, beast::Journal::Stream &s, char const *reason)
Return false if the test ledger is provably incompatible with the valid ledger, that is,...
Definition View.cpp:796
AccountID const & xrpAccount()
Compute AccountID from public key.
base_uint< 256 > uint256
Definition base_uint.h:558
std::set< uint256 > getEnabledAmendments(ReadView const &view)
Definition View.cpp:918
@ open
We haven't closed our ledger yet, but others might have.
Currency const & xrpCurrency()
XRP currency.
constexpr std::uint32_t tfClearFreeze
Definition TxFlags.h:119
Rate transferRate(ReadView const &view, AccountID const &issuer)
Returns IOU issuer transfer fee as Rate.
Definition View.cpp:759
@ tecFROZEN
Definition TER.h:303
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
Definition View.cpp:384
majorityAmendments_t getMajorityAmendments(ReadView const &view)
Definition View.cpp:935
create_genesis_t const create_genesis
Definition Ledger.cpp:51
@ tapRETRY
Definition ApplyView.h:39
@ tapNONE
Definition ApplyView.h:31
constexpr std::uint32_t tfSetFreeze
Definition TxFlags.h:118
Rate const parityRate
A transfer rate signifying a 1:1 exchange.
T push_back(T... args)
T reserve(T... args)
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:39
uint256 key
Definition Keylet.h:40
Represents a transfer rate.
Definition Rate.h:40
iterator upper_bound(key_type const &key) const
Definition ReadView.cpp:41
iterator begin() const
Definition ReadView.cpp:29
Set the sequence number on a JTx.
Definition seq.h:34