20 #include <ripple/app/misc/Manifest.h>
21 #include <ripple/app/misc/TxQ.h>
22 #include <ripple/basics/StringUtilities.h>
23 #include <ripple/beast/unit_test.h>
24 #include <ripple/protocol/ErrorCodes.h>
25 #include <ripple/protocol/jss.h>
38 if (BEAST_EXPECT(jv.
isMember(jss::status)))
39 BEAST_EXPECT(jv[jss::status] ==
"error");
40 if (BEAST_EXPECT(jv.
isMember(jss::error)))
41 BEAST_EXPECT(jv[jss::error] == err);
46 jv[jss::error_message] ==
"");
48 else if (BEAST_EXPECT(jv.
isMember(jss::error_message)))
49 BEAST_EXPECT(jv[jss::error_message] == msg);
65 testcase(
"Basic Request");
66 using namespace test::jtx;
71 BEAST_EXPECT(env.current()->info().seq == 4);
76 jvParams[jss::ledger_index] = 1;
78 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
79 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
true);
80 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"1");
81 BEAST_EXPECT(jrr[jss::ledger][jss::accepted] ==
true);
83 jrr[jss::ledger][jss::totalCoins] ==
84 env.balance(env.master).value().getText());
89 jvParams[jss::ledger_index] =
"1";
91 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
92 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
true);
93 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"1");
94 BEAST_EXPECT(jrr[jss::ledger][jss::accepted] ==
true);
96 jrr[jss::ledger][jss::totalCoins] ==
97 env.balance(env.master).value().getText());
102 auto const jrr = env.rpc(
"ledger",
"current")[jss::result];
103 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
false);
105 jrr[jss::ledger][jss::ledger_index] ==
108 jrr[jss::ledger_current_index] == env.current()->info().seq);
115 testcase(
"Bad Input");
116 using namespace test::jtx;
118 Account
const gw{
"gateway"};
119 auto const USD = gw[
"USD"];
120 Account
const bob{
"bob"};
122 env.fund(XRP(10000), gw, bob);
124 env.trust(USD(1000), bob);
130 jvParams[jss::ledger_index] =
"potato";
132 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
139 jvParams[jss::ledger_index] = -1;
141 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
148 jvParams[jss::ledger_index] = 10u;
150 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
156 auto const jrr = env.rpc(
"ledger",
"arbitrary_text")[jss::result];
163 jvParams[jss::ledger_index] =
"validated";
164 jvParams[jss::queue] =
true;
166 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
173 env.rpc(
"json",
"ledger",
"{ \"ledger_index\" : 2e15 }");
175 BEAST_EXPECT(ret[jss::error_message] ==
"Invalid parameters.");
180 auto const ret = env.rpc(
181 "json",
"ledger",
"{ \"ledger_index\" : 1000000000000000 }");
189 testcase(
"ledger_current Request");
190 using namespace test::jtx;
195 BEAST_EXPECT(env.current()->info().seq == 4);
198 auto const jrr = env.rpc(
"ledger_current")[jss::result];
200 jrr[jss::ledger_current_index] == env.current()->info().seq);
207 testcase(
"Missing ledger_entry ledger_hash");
208 using namespace test::jtx;
210 Account
const alice{
"alice"};
211 env.fund(XRP(10000), alice);
215 jvParams[jss::account_root] = alice.human();
216 jvParams[jss::ledger_hash] =
217 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
219 env.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
226 testcase(
"Ledger Request, Full Option");
227 using namespace test::jtx;
234 jvParams[jss::ledger_index] = 3u;
235 jvParams[jss::full] =
true;
237 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
238 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
239 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
240 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 3u);
246 testcase(
"Ledger Request, Full Option Without Admin");
247 using namespace test::jtx;
249 Env env{*
this, envconfig(no_admin)};
254 jvParams[jss::ledger_index] = 1u;
255 jvParams[jss::full] =
true;
257 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
259 jrr,
"noPermission",
"You don't have permission for this command.");
265 testcase(
"Ledger Request, Accounts Option");
266 using namespace test::jtx;
273 jvParams[jss::ledger_index] = 3u;
274 jvParams[jss::accounts] =
true;
276 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
277 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
278 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
279 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 3u);
285 testcase(
"ledger_entry Request AccountRoot");
286 using namespace test::jtx;
288 Account
const alice{
"alice"};
289 env.fund(XRP(10000), alice);
295 Json::Value const jrr = env.rpc(
"ledger_closed")[jss::result];
296 BEAST_EXPECT(jrr[jss::ledger_hash] == ledgerHash);
297 BEAST_EXPECT(jrr[jss::ledger_index] == 3);
304 jvParams[jss::account_root] = alice.human();
305 jvParams[jss::ledger_hash] = ledgerHash;
307 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
308 BEAST_EXPECT(jrr.
isMember(jss::node));
309 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
311 accountRootIndex = jrr[jss::index].
asString();
314 constexpr
char alicesAcctRootBinary[]{
315 "1100612200800000240000000425000000032D00000000559CE54C3B934E4"
316 "73A995B477E92EC229F99CED5B62BF4D2ACE4DC42719103AE2F6240000002"
317 "540BE4008114AE123A8556F3CF91154711376AFB0F894F832B3D"};
321 jvParams[jss::account_root] = alice.human();
322 jvParams[jss::binary] = 1;
323 jvParams[jss::ledger_hash] = ledgerHash;
325 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
326 BEAST_EXPECT(jrr.
isMember(jss::node_binary));
327 BEAST_EXPECT(jrr[jss::node_binary] == alicesAcctRootBinary);
332 jvParams[jss::index] = accountRootIndex;
334 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
335 BEAST_EXPECT(!jrr.
isMember(jss::node_binary));
336 BEAST_EXPECT(jrr.
isMember(jss::node));
337 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
343 jvParams[jss::index] = accountRootIndex;
344 jvParams[jss::binary] = 0;
346 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
347 BEAST_EXPECT(jrr.
isMember(jss::node));
348 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
355 jvParams[jss::ledger_hash] = ledgerHash;
357 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
363 jvParams[jss::account_root] = Account(
"bob").human();
364 jvParams[jss::ledger_hash] = ledgerHash;
366 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
374 testcase(
"ledger_entry Request Check");
375 using namespace test::jtx;
377 Account
const alice{
"alice"};
378 env.fund(XRP(10000), alice);
381 auto const checkId =
keylet::check(env.master, env.seq(env.master));
383 env(check::create(env.master, alice, XRP(100)));
390 jvParams[jss::check] =
to_string(checkId.key);
391 jvParams[jss::ledger_hash] = ledgerHash;
393 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
404 jvParams[jss::account_root] = alice.human();
406 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
407 accountRootIndex = jrr[jss::index].
asString();
410 jvParams[jss::check] = accountRootIndex;
411 jvParams[jss::ledger_hash] = ledgerHash;
413 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
421 testcase(
"ledger_entry Deposit Preauth");
423 using namespace test::jtx;
426 Account
const alice{
"alice"};
427 Account
const becky{
"becky"};
429 env.fund(XRP(10000), alice, becky);
432 env(deposit::auth(alice, becky));
440 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
441 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
442 jvParams[jss::ledger_hash] = ledgerHash;
444 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
448 jss::DepositPreauth);
451 depositPreauthIndex = jrr[jss::node][jss::index].
asString();
456 jvParams[jss::deposit_preauth] = depositPreauthIndex;
457 jvParams[jss::ledger_hash] = ledgerHash;
459 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
463 jss::DepositPreauth);
470 jvParams[jss::deposit_preauth] = -5;
471 jvParams[jss::ledger_hash] = ledgerHash;
473 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
479 jvParams[jss::deposit_preauth] =
"0123456789ABCDEFG";
480 jvParams[jss::ledger_hash] = ledgerHash;
482 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
488 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
489 jvParams[jss::ledger_hash] = ledgerHash;
491 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
497 jvParams[jss::deposit_preauth][jss::owner] = 7;
498 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
499 jvParams[jss::ledger_hash] = ledgerHash;
501 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
507 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
508 jvParams[jss::ledger_hash] = ledgerHash;
510 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
516 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
517 jvParams[jss::deposit_preauth][jss::authorized] = 47;
518 jvParams[jss::ledger_hash] = ledgerHash;
520 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
526 jvParams[jss::deposit_preauth][jss::owner] =
527 "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
529 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
530 jvParams[jss::ledger_hash] = ledgerHash;
532 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
538 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
539 jvParams[jss::deposit_preauth][jss::authorized] =
540 "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
542 jvParams[jss::ledger_hash] = ledgerHash;
544 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
552 testcase(
"ledger_entry Request Directory");
553 using namespace test::jtx;
555 Account
const alice{
"alice"};
556 Account
const gw{
"gateway"};
557 auto const USD = gw[
"USD"];
558 env.fund(XRP(10000), alice, gw);
561 env.trust(USD(1000), alice);
566 for (
int d = 1
'000'032; d >= 1
'000'000; --d)
568 env(offer(alice, USD(1), drops(d)));
575 Json::Value const jrr = env.rpc(
"ledger_closed")[jss::result];
576 BEAST_EXPECT(jrr[jss::ledger_hash] == ledgerHash);
577 BEAST_EXPECT(jrr[jss::ledger_index] == 5);
581 "A33EC6BB85FB5674074C4A3A43373BB17645308F3EAE1933E3E35252162B217D";
585 jvParams[jss::directory] = dirRootIndex;
586 jvParams[jss::ledger_hash] = ledgerHash;
588 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
595 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
597 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
598 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
604 jvParams[jss::directory][jss::owner] = alice.human();
605 jvParams[jss::ledger_hash] = ledgerHash;
607 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
608 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
614 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
615 jvParams[jss::directory][jss::sub_index] = 1;
617 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
618 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
625 jvParams[jss::directory][jss::owner] = alice.human();
626 jvParams[jss::directory][jss::sub_index] = 1;
627 jvParams[jss::ledger_hash] = ledgerHash;
629 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
630 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
637 jvParams[jss::ledger_hash] = ledgerHash;
639 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
646 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
647 jvParams[jss::directory][jss::sub_index] = 1.5;
648 jvParams[jss::ledger_hash] = ledgerHash;
650 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
659 jvParams[jss::directory][jss::owner] = badAddress;
660 jvParams[jss::ledger_hash] = ledgerHash;
662 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
669 jvParams[jss::directory][jss::owner] = alice.human();
670 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
671 jvParams[jss::ledger_hash] = ledgerHash;
673 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
680 jvParams[jss::directory][jss::sub_index] = 1;
681 jvParams[jss::ledger_hash] = ledgerHash;
683 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
691 testcase(
"ledger_entry Request Escrow");
692 using namespace test::jtx;
694 Account
const alice{
"alice"};
695 env.fund(XRP(10000), alice);
704 jv[jss::TransactionType] = jss::EscrowCreate;
706 jv[jss::Account] = account.human();
707 jv[jss::Destination] = to.human();
710 cancelAfter.time_since_epoch().count() + 2;
714 using namespace std::chrono_literals;
715 env(escrowCreate(alice, alice, XRP(333), env.now() + 2s));
724 jvParams[jss::escrow][jss::owner] = alice.human();
725 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
727 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
729 jrr[jss::node][jss::Amount] == XRP(333).value().getText());
730 escrowIndex = jrr[jss::index].
asString();
735 jvParams[jss::escrow] = escrowIndex;
736 jvParams[jss::ledger_hash] = ledgerHash;
738 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
740 jrr[jss::node][jss::Amount] == XRP(333).value().getText());
748 jvParams[jss::escrow][jss::owner] = badAddress;
749 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
750 jvParams[jss::ledger_hash] = ledgerHash;
752 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
759 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
760 jvParams[jss::ledger_hash] = ledgerHash;
762 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
769 jvParams[jss::escrow][jss::owner] = alice.human();
770 jvParams[jss::ledger_hash] = ledgerHash;
772 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
779 jvParams[jss::escrow][jss::owner] = alice.human();
780 jvParams[jss::escrow][jss::seq] =
782 jvParams[jss::ledger_hash] = ledgerHash;
784 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
792 testcase(
"ledger_entry Request Offer");
793 using namespace test::jtx;
795 Account
const alice{
"alice"};
796 Account
const gw{
"gateway"};
797 auto const USD = gw[
"USD"];
798 env.fund(XRP(10000), alice, gw);
801 env(offer(alice, USD(321), XRP(322)));
810 jvParams[jss::offer][jss::account] = alice.human();
811 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
812 jvParams[jss::ledger_hash] = ledgerHash;
814 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
815 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
816 offerIndex = jrr[jss::index].
asString();
821 jvParams[jss::offer] = offerIndex;
823 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
824 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
832 jvParams[jss::offer][jss::account] = badAddress;
833 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
834 jvParams[jss::ledger_hash] = ledgerHash;
836 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
843 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
844 jvParams[jss::ledger_hash] = ledgerHash;
846 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
853 jvParams[jss::offer][jss::account] = alice.human();
854 jvParams[jss::ledger_hash] = ledgerHash;
856 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
863 jvParams[jss::offer][jss::account] = alice.human();
864 jvParams[jss::offer][jss::seq] =
std::to_string(env.seq(alice) - 1);
865 jvParams[jss::ledger_hash] = ledgerHash;
867 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
875 testcase(
"ledger_entry Request Pay Chan");
876 using namespace test::jtx;
877 using namespace std::literals::chrono_literals;
879 Account
const alice{
"alice"};
881 env.fund(XRP(10000), alice);
891 jv[jss::TransactionType] = jss::PaymentChannelCreate;
892 jv[jss::Account] = account.human();
893 jv[jss::Destination] = to.human();
900 env(payChanCreate(alice, env.master, XRP(57), 18s, alice.pk()));
910 jvParams[jss::payment_channel] =
to_string(payChanIndex);
911 jvParams[jss::ledger_hash] = ledgerHash;
913 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
921 jvParams[jss::payment_channel] = ledgerHash;
922 jvParams[jss::ledger_hash] = ledgerHash;
924 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
932 testcase(
"ledger_entry Request RippleState");
933 using namespace test::jtx;
935 Account
const alice{
"alice"};
936 Account
const gw{
"gateway"};
937 auto const USD = gw[
"USD"];
938 env.fund(XRP(10000), alice, gw);
941 env.trust(USD(999), alice);
944 env(pay(gw, alice, USD(97)));
953 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
954 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
955 jvParams[jss::ripple_state][jss::currency] =
"USD";
956 jvParams[jss::ledger_hash] = ledgerHash;
958 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
967 jvParams[jss::ripple_state] =
"ripple_state";
968 jvParams[jss::ledger_hash] = ledgerHash;
970 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
978 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
979 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
980 jvParams[jss::ledger_hash] = ledgerHash;
982 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
989 jvParams[jss::ripple_state][jss::accounts] = 2;
990 jvParams[jss::ripple_state][jss::currency] =
"USD";
991 jvParams[jss::ledger_hash] = ledgerHash;
993 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1001 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1002 jvParams[jss::ripple_state][jss::currency] =
"USD";
1003 jvParams[jss::ledger_hash] = ledgerHash;
1005 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1013 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1014 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1015 jvParams[jss::ripple_state][jss::accounts][2u] = alice.human();
1016 jvParams[jss::ripple_state][jss::currency] =
"USD";
1017 jvParams[jss::ledger_hash] = ledgerHash;
1019 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1027 jvParams[jss::ripple_state][jss::accounts][0u] = 44;
1028 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1029 jvParams[jss::ripple_state][jss::currency] =
"USD";
1030 jvParams[jss::ledger_hash] = ledgerHash;
1032 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1040 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1041 jvParams[jss::ripple_state][jss::accounts][1u] = 21;
1042 jvParams[jss::ripple_state][jss::currency] =
"USD";
1043 jvParams[jss::ledger_hash] = ledgerHash;
1045 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1053 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1054 jvParams[jss::ripple_state][jss::accounts][1u] = alice.human();
1055 jvParams[jss::ripple_state][jss::currency] =
"USD";
1056 jvParams[jss::ledger_hash] = ledgerHash;
1058 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1066 jvParams[jss::ripple_state][jss::accounts][0u] =
1068 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1069 jvParams[jss::ripple_state][jss::currency] =
"USD";
1070 jvParams[jss::ledger_hash] = ledgerHash;
1072 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1080 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1081 jvParams[jss::ripple_state][jss::accounts][1u] =
1083 jvParams[jss::ripple_state][jss::currency] =
"USD";
1084 jvParams[jss::ledger_hash] = ledgerHash;
1086 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1094 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1095 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1096 jvParams[jss::ripple_state][jss::currency] =
"USDollars";
1097 jvParams[jss::ledger_hash] = ledgerHash;
1099 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1107 testcase(
"ledger_entry Request Ticket");
1108 using namespace test::jtx;
1114 env(ticket::create(env.master, 2));
1124 jvParams[jss::ticket] =
1126 jvParams[jss::ledger_hash] = ledgerHash;
1128 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1135 jvParams[jss::ledger_hash] = ledgerHash;
1137 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1146 jvParams[jss::ticket][jss::account] = env.master.human();
1147 jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 1;
1148 jvParams[jss::ledger_hash] = ledgerHash;
1150 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1152 jrr[jss::node][jss::index] ==
1159 jvParams[jss::ticket][jss::account] = env.master.human();
1160 jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 2;
1161 jvParams[jss::ledger_hash] = ledgerHash;
1163 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1170 jvParams[jss::ledger_hash] = ledgerHash;
1172 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1181 jvParams[jss::ticket][jss::account] = badAddress;
1182 jvParams[jss::ticket][jss::ticket_seq] = env.seq(env.master) - 1;
1183 jvParams[jss::ledger_hash] = ledgerHash;
1185 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1192 jvParams[jss::ticket][jss::ticket_seq] = env.seq(env.master) - 1;
1193 jvParams[jss::ledger_hash] = ledgerHash;
1195 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1202 jvParams[jss::ticket][jss::account] = env.master.human();
1203 jvParams[jss::ledger_hash] = ledgerHash;
1205 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1212 jvParams[jss::ticket][jss::account] = env.master.human();
1213 jvParams[jss::ticket][jss::ticket_seq] =
1215 jvParams[jss::ledger_hash] = ledgerHash;
1217 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1225 testcase(
"ledger_entry Request Unknown Option");
1226 using namespace test::jtx;
1233 jvParams[jss::features] = ledgerHash;
1234 jvParams[jss::ledger_hash] = ledgerHash;
1236 env.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1247 testcase(
"Lookup ledger");
1248 using namespace test::jtx;
1251 env.fund(XRP(10000),
"alice");
1253 env.fund(XRP(10000),
"bob");
1255 env.fund(XRP(10000),
"jim");
1257 env.fund(XRP(10000),
"jill");
1262 jvParams[jss::ledger] =
"closed";
1266 boost::lexical_cast<std::string>(jvParams))[jss::result];
1267 BEAST_EXPECT(jrr.isMember(jss::ledger));
1268 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1269 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1271 jvParams[jss::ledger] =
"validated";
1275 boost::lexical_cast<std::string>(jvParams))[jss::result];
1276 BEAST_EXPECT(jrr.isMember(jss::ledger));
1277 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1278 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1280 jvParams[jss::ledger] =
"current";
1284 boost::lexical_cast<std::string>(jvParams))[jss::result];
1285 BEAST_EXPECT(jrr.isMember(jss::ledger));
1286 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1289 jvParams[jss::ledger] =
"invalid";
1293 boost::lexical_cast<std::string>(jvParams))[jss::result];
1294 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1295 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1298 jvParams[jss::ledger] = 4;
1302 boost::lexical_cast<std::string>(jvParams))[jss::result];
1303 BEAST_EXPECT(jrr.isMember(jss::ledger));
1304 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1305 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"4");
1308 jvParams[jss::ledger] = 20;
1312 boost::lexical_cast<std::string>(jvParams))[jss::result];
1313 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1314 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1319 "E86DE7F3D7A4D9CE17EF7C8BA08A8F4D"
1320 "8F643B9552F0D895A31CDA78F541DE4E"};
1323 jvParams[jss::ledger_hash] = hash3;
1327 boost::lexical_cast<std::string>(jvParams))[jss::result];
1328 BEAST_EXPECT(jrr.isMember(jss::ledger));
1329 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1330 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"3");
1333 jvParams[jss::ledger_hash] =
"DEADBEEF" + hash3;
1337 boost::lexical_cast<std::string>(jvParams))[jss::result];
1338 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1339 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashMalformed");
1342 jvParams[jss::ledger_hash] = 2;
1346 boost::lexical_cast<std::string>(jvParams))[jss::result];
1347 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1348 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashNotString");
1351 jvParams[jss::ledger_hash] =
1352 "2E81FC6EC0DD943197EGC7E3FBE9AE30"
1353 "7F2775F2F7485BB37307984C3C0F2340";
1357 boost::lexical_cast<std::string>(jvParams))[jss::result];
1358 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1359 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashMalformed");
1362 jvParams[jss::ledger_hash] =
1363 "8C3EEDB3124D92E49E75D81A8826A2E6"
1364 "5A75FD71FC3FD6F36FEB803C5F1D812D";
1368 boost::lexical_cast<std::string>(jvParams))[jss::result];
1369 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1370 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1376 jvParams[jss::ledger_index] =
"closed";
1380 boost::lexical_cast<std::string>(jvParams))[jss::result];
1381 BEAST_EXPECT(jrr.isMember(jss::ledger));
1382 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1383 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1384 BEAST_EXPECT(jrr.isMember(jss::ledger_index));
1386 jvParams[jss::ledger_index] =
"validated";
1390 boost::lexical_cast<std::string>(jvParams))[jss::result];
1391 BEAST_EXPECT(jrr.isMember(jss::ledger));
1392 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1393 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1395 jvParams[jss::ledger_index] =
"current";
1399 boost::lexical_cast<std::string>(jvParams))[jss::result];
1400 BEAST_EXPECT(jrr.isMember(jss::ledger));
1401 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1402 BEAST_EXPECT(jrr.isMember(jss::ledger_current_index));
1405 jvParams[jss::ledger_index] =
"invalid";
1409 boost::lexical_cast<std::string>(jvParams))[jss::result];
1410 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1411 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1414 for (
auto i : {1, 2, 3, 4, 5, 6})
1416 jvParams[jss::ledger_index] = i;
1420 boost::lexical_cast<std::string>(jvParams))[jss::result];
1421 BEAST_EXPECT(jrr.isMember(jss::ledger));
1423 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1429 jvParams[jss::ledger_index] = 7;
1433 boost::lexical_cast<std::string>(jvParams))[jss::result];
1434 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1435 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1442 testcase(
"Ledger with queueing disabled");
1443 using namespace test::jtx;
1447 jv[jss::ledger_index] =
"current";
1448 jv[jss::queue] =
true;
1449 jv[jss::expand] =
true;
1451 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1452 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1458 testcase(
"Ledger with Queued Transactions");
1459 using namespace test::jtx;
1461 auto& section = cfg->section(
"transaction_queue");
1462 section.set(
"minimum_txn_in_ledger_standalone",
"3");
1463 section.set(
"normal_consensus_increase_percent",
"0");
1468 jv[jss::ledger_index] =
"current";
1469 jv[jss::queue] =
true;
1470 jv[jss::expand] =
true;
1472 Account
const alice{
"alice"};
1473 Account
const bob{
"bob"};
1474 Account
const charlie{
"charlie"};
1475 Account
const daria{
"daria"};
1476 env.fund(XRP(10000), alice);
1477 env.fund(XRP(10000), bob);
1479 env.fund(XRP(10000), charlie);
1480 env.fund(XRP(10000), daria);
1483 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1484 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1489 auto metrics = env.app().getTxQ().getMetrics(*env.current());
1490 if (metrics.openLedgerFeeLevel > metrics.minProcessingFeeLevel)
1495 BEAST_EXPECT(env.current()->info().seq == 5);
1498 auto aliceSeq = env.seq(alice);
1499 env(pay(alice,
"george", XRP(1000)),
1500 json(R
"({"LastLedgerSequence":7})"),
1502 env(offer(alice, XRP(50000), alice["USD"](5000)),
1505 env(noop(alice), seq(aliceSeq + 2), ter(
terQUEUED));
1507 auto batch = [&env](Account a) {
1508 auto aSeq = env.seq(a);
1510 for (
int i = 0; i < 10; ++i)
1512 env(noop(a), fee(1000 + i), seq(aSeq + i), ter(
terQUEUED));
1521 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1522 BEAST_EXPECT(jrr[jss::queue_data].size() == 33);
1528 BEAST_EXPECT(env.current()->info().seq == 8);
1530 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1531 BEAST_EXPECT(jrr[jss::queue_data].size() == 11);
1535 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1537 auto const& parentHash = env.current()->info().parentHash;
1538 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1541 auto const& txj = jrr[jss::queue_data][1u];
1542 BEAST_EXPECT(txj[jss::account] == alice.human());
1543 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1544 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1545 BEAST_EXPECT(txj[
"retries_remaining"] == 10);
1546 BEAST_EXPECT(txj.isMember(jss::tx));
1547 auto const& tx = txj[jss::tx];
1548 BEAST_EXPECT(tx[jss::Account] == alice.human());
1549 BEAST_EXPECT(tx[jss::TransactionType] == jss::AccountSet);
1550 return tx[jss::hash].asString();
1553 auto const& txj = jrr[jss::queue_data][0u];
1554 BEAST_EXPECT(txj[jss::account] == alice.human());
1555 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1556 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1557 BEAST_EXPECT(txj[
"retries_remaining"] == 10);
1558 BEAST_EXPECT(txj.isMember(jss::tx));
1559 auto const& tx = txj[jss::tx];
1560 BEAST_EXPECT(tx[jss::Account] == alice.human());
1561 BEAST_EXPECT(tx[jss::TransactionType] == jss::OfferCreate);
1562 const auto txid0 = tx[jss::hash].asString();
1566 BEAST_EXPECT((tx0 ^ parentHash) < (tx1 ^ parentHash));
1574 jv[jss::expand] =
false;
1576 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1577 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1579 auto const& parentHash = env.current()->info().parentHash;
1580 auto const txid1 = [&]() {
1581 auto const& txj = jrr[jss::queue_data][1u];
1582 BEAST_EXPECT(txj[jss::account] == alice.human());
1583 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1584 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1585 BEAST_EXPECT(txj.isMember(jss::tx));
1586 return txj[jss::tx].asString();
1588 auto const& txj = jrr[jss::queue_data][0u];
1589 BEAST_EXPECT(txj[jss::account] == alice.human());
1590 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1591 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1592 BEAST_EXPECT(txj[
"retries_remaining"] == 9);
1593 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1594 BEAST_EXPECT(txj.isMember(jss::tx));
1595 BEAST_EXPECT(txj[jss::tx] == txid0);
1599 BEAST_EXPECT((tx0 ^ parentHash) < (tx1 ^ parentHash));
1604 jv[jss::expand] =
true;
1605 jv[jss::binary] =
true;
1607 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1608 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1610 auto const& txj = jrr[jss::queue_data][1u];
1611 BEAST_EXPECT(txj[jss::account] == alice.human());
1612 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1613 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1614 BEAST_EXPECT(txj[
"retries_remaining"] == 8);
1615 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1616 BEAST_EXPECT(txj.isMember(jss::tx));
1617 BEAST_EXPECT(txj[jss::tx].isMember(jss::tx_blob));
1619 auto const& txj2 = jrr[jss::queue_data][0u];
1620 BEAST_EXPECT(txj2[jss::account] == alice.human());
1621 BEAST_EXPECT(txj2[jss::fee_level] ==
"256");
1622 BEAST_EXPECT(txj2[
"preflight_result"] ==
"tesSUCCESS");
1623 BEAST_EXPECT(txj2[
"retries_remaining"] == 10);
1624 BEAST_EXPECT(!txj2.isMember(
"last_result"));
1625 BEAST_EXPECT(txj2.isMember(jss::tx));
1626 BEAST_EXPECT(txj2[jss::tx].isMember(jss::tx_blob));
1629 for (
int i = 0; i != 9; ++i)
1634 jv[jss::expand] =
false;
1635 jv[jss::binary] =
false;
1637 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1639 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1641 auto const& txj = jrr[jss::queue_data][0u];
1642 BEAST_EXPECT(txj[jss::account] == alice.human());
1643 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1644 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1645 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1646 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1647 BEAST_EXPECT(txj.isMember(jss::tx));
1648 BEAST_EXPECT(txj[jss::tx] != txid0);
1649 return txj[jss::tx].asString();
1654 jv[jss::full] =
true;
1656 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1657 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1659 auto const& txj = jrr[jss::queue_data][0u];
1660 BEAST_EXPECT(txj[jss::account] == alice.human());
1661 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1662 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1663 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1664 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1665 BEAST_EXPECT(txj.isMember(jss::tx));
1666 auto const& tx = txj[jss::tx];
1667 BEAST_EXPECT(tx[jss::Account] == alice.human());
1668 BEAST_EXPECT(tx[jss::TransactionType] == jss::AccountSet);
1669 BEAST_EXPECT(tx[jss::hash] == txid2);
1676 testcase(
"Ledger Request, Accounts Hashes");
1677 using namespace test::jtx;
1686 jvParams[jss::ledger_index] = 3u;
1687 jvParams[jss::accounts] =
true;
1688 jvParams[jss::expand] =
true;
1689 jvParams[jss::type] =
"hashes";
1691 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1692 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1693 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1694 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1696 jrr[jss::ledger][jss::accountState][0u][
"LedgerEntryType"] ==
1698 index = jrr[jss::ledger][jss::accountState][0u][
"index"].asString();
1702 jvParams[jss::ledger_index] = 3u;
1703 jvParams[jss::accounts] =
true;
1704 jvParams[jss::expand] =
false;
1705 jvParams[jss::type] =
"hashes";
1707 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1708 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1709 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1710 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1711 BEAST_EXPECT(jrr[jss::ledger][jss::accountState][0u] == index);