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");
85 jvParams[jss::ledger_index] =
"1";
87 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
88 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
true);
89 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"1");
94 auto const jrr = env.rpc(
"ledger",
"current")[jss::result];
95 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
false);
97 jrr[jss::ledger][jss::ledger_index] ==
100 jrr[jss::ledger_current_index] == env.current()->info().seq);
107 testcase(
"Bad Input");
108 using namespace test::jtx;
110 Account
const gw{
"gateway"};
111 auto const USD = gw[
"USD"];
112 Account
const bob{
"bob"};
114 env.fund(XRP(10000), gw, bob);
116 env.trust(USD(1000), bob);
122 jvParams[jss::ledger_index] =
"potato";
124 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
131 jvParams[jss::ledger_index] = -1;
133 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
140 jvParams[jss::ledger_index] = 10u;
142 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
148 auto const jrr = env.rpc(
"ledger",
"arbitrary_text")[jss::result];
155 jvParams[jss::ledger_index] =
"validated";
156 jvParams[jss::queue] =
true;
158 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
165 env.rpc(
"json",
"ledger",
"{ \"ledger_index\" : 2e15 }");
167 BEAST_EXPECT(ret[jss::error_message] ==
"Invalid parameters.");
172 auto const ret = env.rpc(
173 "json",
"ledger",
"{ \"ledger_index\" : 1000000000000000 }");
181 testcase(
"ledger_current Request");
182 using namespace test::jtx;
187 BEAST_EXPECT(env.current()->info().seq == 4);
190 auto const jrr = env.rpc(
"ledger_current")[jss::result];
192 jrr[jss::ledger_current_index] == env.current()->info().seq);
199 testcase(
"Missing ledger_entry ledger_hash");
200 using namespace test::jtx;
202 Account
const alice{
"alice"};
203 env.fund(XRP(10000), alice);
207 jvParams[jss::account_root] = alice.human();
208 jvParams[jss::ledger_hash] =
209 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
211 env.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
218 testcase(
"Ledger Request, Full Option");
219 using namespace test::jtx;
226 jvParams[jss::ledger_index] = 3u;
227 jvParams[jss::full] =
true;
229 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
230 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
231 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
232 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 3u);
238 testcase(
"Ledger Request, Full Option Without Admin");
239 using namespace test::jtx;
241 Env env{*
this, envconfig(no_admin)};
246 jvParams[jss::ledger_index] = 1u;
247 jvParams[jss::full] =
true;
249 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
251 jrr,
"noPermission",
"You don't have permission for this command.");
257 testcase(
"Ledger Request, Accounts Option");
258 using namespace test::jtx;
265 jvParams[jss::ledger_index] = 3u;
266 jvParams[jss::accounts] =
true;
268 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
269 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
270 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
271 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 3u);
277 testcase(
"ledger_entry Request AccountRoot");
278 using namespace test::jtx;
280 Account
const alice{
"alice"};
281 env.fund(XRP(10000), alice);
287 Json::Value const jrr = env.rpc(
"ledger_closed")[jss::result];
288 BEAST_EXPECT(jrr[jss::ledger_hash] == ledgerHash);
289 BEAST_EXPECT(jrr[jss::ledger_index] == 3);
296 jvParams[jss::account_root] = alice.human();
297 jvParams[jss::ledger_hash] = ledgerHash;
299 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
300 BEAST_EXPECT(jrr.
isMember(jss::node));
301 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
303 accountRootIndex = jrr[jss::index].
asString();
306 constexpr
char alicesAcctRootBinary[]{
307 "1100612200800000240000000425000000032D00000000559CE54C3B934E4"
308 "73A995B477E92EC229F99CED5B62BF4D2ACE4DC42719103AE2F6240000002"
309 "540BE4008114AE123A8556F3CF91154711376AFB0F894F832B3D"};
313 jvParams[jss::account_root] = alice.human();
314 jvParams[jss::binary] = 1;
315 jvParams[jss::ledger_hash] = ledgerHash;
317 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
318 BEAST_EXPECT(jrr.
isMember(jss::node_binary));
319 BEAST_EXPECT(jrr[jss::node_binary] == alicesAcctRootBinary);
324 jvParams[jss::index] = accountRootIndex;
326 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
327 BEAST_EXPECT(!jrr.
isMember(jss::node_binary));
328 BEAST_EXPECT(jrr.
isMember(jss::node));
329 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
335 jvParams[jss::index] = accountRootIndex;
336 jvParams[jss::binary] = 0;
338 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
339 BEAST_EXPECT(jrr.
isMember(jss::node));
340 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
347 jvParams[jss::ledger_hash] = ledgerHash;
349 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
355 jvParams[jss::account_root] = Account(
"bob").human();
356 jvParams[jss::ledger_hash] = ledgerHash;
358 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
366 testcase(
"ledger_entry Request Check");
367 using namespace test::jtx;
369 Account
const alice{
"alice"};
370 env.fund(XRP(10000), alice);
373 auto const checkId =
keylet::check(env.master, env.seq(env.master));
375 env(check::create(env.master, alice, XRP(100)));
382 jvParams[jss::check] =
to_string(checkId.key);
383 jvParams[jss::ledger_hash] = ledgerHash;
385 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
396 jvParams[jss::account_root] = alice.human();
398 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
399 accountRootIndex = jrr[jss::index].
asString();
402 jvParams[jss::check] = accountRootIndex;
403 jvParams[jss::ledger_hash] = ledgerHash;
405 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
413 testcase(
"ledger_entry Deposit Preauth");
415 using namespace test::jtx;
418 Account
const alice{
"alice"};
419 Account
const becky{
"becky"};
421 env.fund(XRP(10000), alice, becky);
424 env(deposit::auth(alice, becky));
432 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
433 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
434 jvParams[jss::ledger_hash] = ledgerHash;
436 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
440 jss::DepositPreauth);
443 depositPreauthIndex = jrr[jss::node][jss::index].
asString();
448 jvParams[jss::deposit_preauth] = depositPreauthIndex;
449 jvParams[jss::ledger_hash] = ledgerHash;
451 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
455 jss::DepositPreauth);
462 jvParams[jss::deposit_preauth] = -5;
463 jvParams[jss::ledger_hash] = ledgerHash;
465 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
471 jvParams[jss::deposit_preauth] =
"0123456789ABCDEFG";
472 jvParams[jss::ledger_hash] = ledgerHash;
474 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
480 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
481 jvParams[jss::ledger_hash] = ledgerHash;
483 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
489 jvParams[jss::deposit_preauth][jss::owner] = 7;
490 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
491 jvParams[jss::ledger_hash] = ledgerHash;
493 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
499 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
500 jvParams[jss::ledger_hash] = ledgerHash;
502 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
508 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
509 jvParams[jss::deposit_preauth][jss::authorized] = 47;
510 jvParams[jss::ledger_hash] = ledgerHash;
512 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
518 jvParams[jss::deposit_preauth][jss::owner] =
519 "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
521 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
522 jvParams[jss::ledger_hash] = ledgerHash;
524 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
530 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
531 jvParams[jss::deposit_preauth][jss::authorized] =
532 "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
534 jvParams[jss::ledger_hash] = ledgerHash;
536 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
544 testcase(
"ledger_entry Request Directory");
545 using namespace test::jtx;
547 Account
const alice{
"alice"};
548 Account
const gw{
"gateway"};
549 auto const USD = gw[
"USD"];
550 env.fund(XRP(10000), alice, gw);
553 env.trust(USD(1000), alice);
558 for (
int d = 1
'000'032; d >= 1
'000'000; --d)
560 env(offer(alice, USD(1), drops(d)));
567 Json::Value const jrr = env.rpc(
"ledger_closed")[jss::result];
568 BEAST_EXPECT(jrr[jss::ledger_hash] == ledgerHash);
569 BEAST_EXPECT(jrr[jss::ledger_index] == 5);
573 "A33EC6BB85FB5674074C4A3A43373BB17645308F3EAE1933E3E35252162B217D";
577 jvParams[jss::directory] = dirRootIndex;
578 jvParams[jss::ledger_hash] = ledgerHash;
580 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
587 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
589 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
590 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
596 jvParams[jss::directory][jss::owner] = alice.human();
597 jvParams[jss::ledger_hash] = ledgerHash;
599 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
600 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
606 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
607 jvParams[jss::directory][jss::sub_index] = 1;
609 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
610 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
617 jvParams[jss::directory][jss::owner] = alice.human();
618 jvParams[jss::directory][jss::sub_index] = 1;
619 jvParams[jss::ledger_hash] = ledgerHash;
621 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
622 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
629 jvParams[jss::ledger_hash] = ledgerHash;
631 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
638 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
639 jvParams[jss::directory][jss::sub_index] = 1.5;
640 jvParams[jss::ledger_hash] = ledgerHash;
642 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
651 jvParams[jss::directory][jss::owner] = badAddress;
652 jvParams[jss::ledger_hash] = ledgerHash;
654 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
661 jvParams[jss::directory][jss::owner] = alice.human();
662 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
663 jvParams[jss::ledger_hash] = ledgerHash;
665 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
672 jvParams[jss::directory][jss::sub_index] = 1;
673 jvParams[jss::ledger_hash] = ledgerHash;
675 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
683 testcase(
"ledger_entry Request Escrow");
684 using namespace test::jtx;
686 Account
const alice{
"alice"};
687 env.fund(XRP(10000), alice);
696 jv[jss::TransactionType] = jss::EscrowCreate;
698 jv[jss::Account] = account.human();
699 jv[jss::Destination] = to.human();
702 cancelAfter.time_since_epoch().count() + 2;
706 using namespace std::chrono_literals;
707 env(escrowCreate(alice, alice, XRP(333), env.now() + 2s));
716 jvParams[jss::escrow][jss::owner] = alice.human();
717 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
719 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
721 jrr[jss::node][jss::Amount] == XRP(333).value().getText());
722 escrowIndex = jrr[jss::index].
asString();
727 jvParams[jss::escrow] = escrowIndex;
728 jvParams[jss::ledger_hash] = ledgerHash;
730 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
732 jrr[jss::node][jss::Amount] == XRP(333).value().getText());
740 jvParams[jss::escrow][jss::owner] = badAddress;
741 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
742 jvParams[jss::ledger_hash] = ledgerHash;
744 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
751 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
752 jvParams[jss::ledger_hash] = ledgerHash;
754 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
761 jvParams[jss::escrow][jss::owner] = alice.human();
762 jvParams[jss::ledger_hash] = ledgerHash;
764 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
771 jvParams[jss::escrow][jss::owner] = alice.human();
772 jvParams[jss::escrow][jss::seq] =
774 jvParams[jss::ledger_hash] = ledgerHash;
776 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
784 testcase(
"ledger_entry Request Offer");
785 using namespace test::jtx;
787 Account
const alice{
"alice"};
788 Account
const gw{
"gateway"};
789 auto const USD = gw[
"USD"];
790 env.fund(XRP(10000), alice, gw);
793 env(offer(alice, USD(321), XRP(322)));
802 jvParams[jss::offer][jss::account] = alice.human();
803 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
804 jvParams[jss::ledger_hash] = ledgerHash;
806 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
807 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
808 offerIndex = jrr[jss::index].
asString();
813 jvParams[jss::offer] = offerIndex;
815 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
816 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
824 jvParams[jss::offer][jss::account] = badAddress;
825 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
826 jvParams[jss::ledger_hash] = ledgerHash;
828 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
835 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
836 jvParams[jss::ledger_hash] = ledgerHash;
838 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
845 jvParams[jss::offer][jss::account] = alice.human();
846 jvParams[jss::ledger_hash] = ledgerHash;
848 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
855 jvParams[jss::offer][jss::account] = alice.human();
856 jvParams[jss::offer][jss::seq] =
std::to_string(env.seq(alice) - 1);
857 jvParams[jss::ledger_hash] = ledgerHash;
859 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
867 testcase(
"ledger_entry Request Pay Chan");
868 using namespace test::jtx;
869 using namespace std::literals::chrono_literals;
871 Account
const alice{
"alice"};
873 env.fund(XRP(10000), alice);
883 jv[jss::TransactionType] = jss::PaymentChannelCreate;
884 jv[jss::Account] = account.human();
885 jv[jss::Destination] = to.human();
892 env(payChanCreate(alice, env.master, XRP(57), 18s, alice.pk()));
902 jvParams[jss::payment_channel] =
to_string(payChanIndex);
903 jvParams[jss::ledger_hash] = ledgerHash;
905 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
913 jvParams[jss::payment_channel] = ledgerHash;
914 jvParams[jss::ledger_hash] = ledgerHash;
916 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
924 testcase(
"ledger_entry Request RippleState");
925 using namespace test::jtx;
927 Account
const alice{
"alice"};
928 Account
const gw{
"gateway"};
929 auto const USD = gw[
"USD"];
930 env.fund(XRP(10000), alice, gw);
933 env.trust(USD(999), alice);
936 env(pay(gw, alice, USD(97)));
945 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
946 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
947 jvParams[jss::ripple_state][jss::currency] =
"USD";
948 jvParams[jss::ledger_hash] = ledgerHash;
950 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
959 jvParams[jss::ripple_state] =
"ripple_state";
960 jvParams[jss::ledger_hash] = ledgerHash;
962 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
970 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
971 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
972 jvParams[jss::ledger_hash] = ledgerHash;
974 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
981 jvParams[jss::ripple_state][jss::accounts] = 2;
982 jvParams[jss::ripple_state][jss::currency] =
"USD";
983 jvParams[jss::ledger_hash] = ledgerHash;
985 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
993 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
994 jvParams[jss::ripple_state][jss::currency] =
"USD";
995 jvParams[jss::ledger_hash] = ledgerHash;
997 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1005 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1006 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1007 jvParams[jss::ripple_state][jss::accounts][2u] = alice.human();
1008 jvParams[jss::ripple_state][jss::currency] =
"USD";
1009 jvParams[jss::ledger_hash] = ledgerHash;
1011 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1019 jvParams[jss::ripple_state][jss::accounts][0u] = 44;
1020 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1021 jvParams[jss::ripple_state][jss::currency] =
"USD";
1022 jvParams[jss::ledger_hash] = ledgerHash;
1024 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1032 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1033 jvParams[jss::ripple_state][jss::accounts][1u] = 21;
1034 jvParams[jss::ripple_state][jss::currency] =
"USD";
1035 jvParams[jss::ledger_hash] = ledgerHash;
1037 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1045 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1046 jvParams[jss::ripple_state][jss::accounts][1u] = alice.human();
1047 jvParams[jss::ripple_state][jss::currency] =
"USD";
1048 jvParams[jss::ledger_hash] = ledgerHash;
1050 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1058 jvParams[jss::ripple_state][jss::accounts][0u] =
1060 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1061 jvParams[jss::ripple_state][jss::currency] =
"USD";
1062 jvParams[jss::ledger_hash] = ledgerHash;
1064 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1072 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1073 jvParams[jss::ripple_state][jss::accounts][1u] =
1075 jvParams[jss::ripple_state][jss::currency] =
"USD";
1076 jvParams[jss::ledger_hash] = ledgerHash;
1078 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1086 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1087 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1088 jvParams[jss::ripple_state][jss::currency] =
"USDollars";
1089 jvParams[jss::ledger_hash] = ledgerHash;
1091 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1099 testcase(
"ledger_entry Request Ticket");
1100 using namespace test::jtx;
1106 env(ticket::create(env.master, 2));
1116 jvParams[jss::ticket] =
1118 jvParams[jss::ledger_hash] = ledgerHash;
1120 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1127 jvParams[jss::ledger_hash] = ledgerHash;
1129 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1138 jvParams[jss::ticket][jss::account] = env.master.human();
1139 jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 1;
1140 jvParams[jss::ledger_hash] = ledgerHash;
1142 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1144 jrr[jss::node][jss::index] ==
1151 jvParams[jss::ticket][jss::account] = env.master.human();
1152 jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 2;
1153 jvParams[jss::ledger_hash] = ledgerHash;
1155 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1162 jvParams[jss::ledger_hash] = ledgerHash;
1164 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1173 jvParams[jss::ticket][jss::account] = badAddress;
1174 jvParams[jss::ticket][jss::ticket_seq] = env.seq(env.master) - 1;
1175 jvParams[jss::ledger_hash] = ledgerHash;
1177 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1184 jvParams[jss::ticket][jss::ticket_seq] = env.seq(env.master) - 1;
1185 jvParams[jss::ledger_hash] = ledgerHash;
1187 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1194 jvParams[jss::ticket][jss::account] = env.master.human();
1195 jvParams[jss::ledger_hash] = ledgerHash;
1197 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1204 jvParams[jss::ticket][jss::account] = env.master.human();
1205 jvParams[jss::ticket][jss::ticket_seq] =
1207 jvParams[jss::ledger_hash] = ledgerHash;
1209 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1217 testcase(
"ledger_entry Request Unknown Option");
1218 using namespace test::jtx;
1225 jvParams[jss::features] = ledgerHash;
1226 jvParams[jss::ledger_hash] = ledgerHash;
1228 env.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1239 testcase(
"Lookup ledger");
1240 using namespace test::jtx;
1243 env.fund(XRP(10000),
"alice");
1245 env.fund(XRP(10000),
"bob");
1247 env.fund(XRP(10000),
"jim");
1249 env.fund(XRP(10000),
"jill");
1254 jvParams[jss::ledger] =
"closed";
1258 boost::lexical_cast<std::string>(jvParams))[jss::result];
1259 BEAST_EXPECT(jrr.isMember(jss::ledger));
1260 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1261 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1263 jvParams[jss::ledger] =
"validated";
1267 boost::lexical_cast<std::string>(jvParams))[jss::result];
1268 BEAST_EXPECT(jrr.isMember(jss::ledger));
1269 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1270 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1272 jvParams[jss::ledger] =
"current";
1276 boost::lexical_cast<std::string>(jvParams))[jss::result];
1277 BEAST_EXPECT(jrr.isMember(jss::ledger));
1278 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1281 jvParams[jss::ledger] =
"invalid";
1285 boost::lexical_cast<std::string>(jvParams))[jss::result];
1286 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1287 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1290 jvParams[jss::ledger] = 4;
1294 boost::lexical_cast<std::string>(jvParams))[jss::result];
1295 BEAST_EXPECT(jrr.isMember(jss::ledger));
1296 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1297 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"4");
1300 jvParams[jss::ledger] = 20;
1304 boost::lexical_cast<std::string>(jvParams))[jss::result];
1305 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1306 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1311 "E86DE7F3D7A4D9CE17EF7C8BA08A8F4D"
1312 "8F643B9552F0D895A31CDA78F541DE4E"};
1315 jvParams[jss::ledger_hash] = hash3;
1319 boost::lexical_cast<std::string>(jvParams))[jss::result];
1320 BEAST_EXPECT(jrr.isMember(jss::ledger));
1321 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1322 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"3");
1325 jvParams[jss::ledger_hash] =
"DEADBEEF" + hash3;
1329 boost::lexical_cast<std::string>(jvParams))[jss::result];
1330 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1331 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashMalformed");
1334 jvParams[jss::ledger_hash] = 2;
1338 boost::lexical_cast<std::string>(jvParams))[jss::result];
1339 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1340 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashNotString");
1343 jvParams[jss::ledger_hash] =
1344 "2E81FC6EC0DD943197EGC7E3FBE9AE30"
1345 "7F2775F2F7485BB37307984C3C0F2340";
1349 boost::lexical_cast<std::string>(jvParams))[jss::result];
1350 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1351 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashMalformed");
1354 jvParams[jss::ledger_hash] =
1355 "8C3EEDB3124D92E49E75D81A8826A2E6"
1356 "5A75FD71FC3FD6F36FEB803C5F1D812D";
1360 boost::lexical_cast<std::string>(jvParams))[jss::result];
1361 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1362 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1368 jvParams[jss::ledger_index] =
"closed";
1372 boost::lexical_cast<std::string>(jvParams))[jss::result];
1373 BEAST_EXPECT(jrr.isMember(jss::ledger));
1374 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1375 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1376 BEAST_EXPECT(jrr.isMember(jss::ledger_index));
1378 jvParams[jss::ledger_index] =
"validated";
1382 boost::lexical_cast<std::string>(jvParams))[jss::result];
1383 BEAST_EXPECT(jrr.isMember(jss::ledger));
1384 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1385 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1387 jvParams[jss::ledger_index] =
"current";
1391 boost::lexical_cast<std::string>(jvParams))[jss::result];
1392 BEAST_EXPECT(jrr.isMember(jss::ledger));
1393 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1394 BEAST_EXPECT(jrr.isMember(jss::ledger_current_index));
1397 jvParams[jss::ledger_index] =
"invalid";
1401 boost::lexical_cast<std::string>(jvParams))[jss::result];
1402 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1403 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1406 for (
auto i : {1, 2, 3, 4, 5, 6})
1408 jvParams[jss::ledger_index] = i;
1412 boost::lexical_cast<std::string>(jvParams))[jss::result];
1413 BEAST_EXPECT(jrr.isMember(jss::ledger));
1415 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1421 jvParams[jss::ledger_index] = 7;
1425 boost::lexical_cast<std::string>(jvParams))[jss::result];
1426 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1427 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1434 testcase(
"Ledger with queueing disabled");
1435 using namespace test::jtx;
1439 jv[jss::ledger_index] =
"current";
1440 jv[jss::queue] =
true;
1441 jv[jss::expand] =
true;
1443 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1444 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1450 testcase(
"Ledger with Queued Transactions");
1451 using namespace test::jtx;
1453 auto& section = cfg->section(
"transaction_queue");
1454 section.set(
"minimum_txn_in_ledger_standalone",
"3");
1455 section.set(
"normal_consensus_increase_percent",
"0");
1460 jv[jss::ledger_index] =
"current";
1461 jv[jss::queue] =
true;
1462 jv[jss::expand] =
true;
1464 Account
const alice{
"alice"};
1465 Account
const bob{
"bob"};
1466 Account
const charlie{
"charlie"};
1467 Account
const daria{
"daria"};
1468 env.fund(XRP(10000), alice);
1469 env.fund(XRP(10000), bob);
1471 env.fund(XRP(10000), charlie);
1472 env.fund(XRP(10000), daria);
1475 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1476 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1481 auto metrics = env.app().getTxQ().getMetrics(*env.current());
1482 if (metrics.openLedgerFeeLevel > metrics.minProcessingFeeLevel)
1487 BEAST_EXPECT(env.current()->info().seq == 5);
1490 auto aliceSeq = env.seq(alice);
1491 env(pay(alice,
"george", XRP(1000)),
1492 json(R
"({"LastLedgerSequence":7})"),
1494 env(offer(alice, XRP(50000), alice["USD"](5000)),
1497 env(noop(alice), seq(aliceSeq + 2), ter(
terQUEUED));
1499 auto batch = [&env](Account a) {
1500 auto aSeq = env.seq(a);
1502 for (
int i = 0; i < 10; ++i)
1504 env(noop(a), fee(1000 + i), seq(aSeq + i), ter(
terQUEUED));
1513 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1514 BEAST_EXPECT(jrr[jss::queue_data].size() == 33);
1520 BEAST_EXPECT(env.current()->info().seq == 8);
1522 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1523 BEAST_EXPECT(jrr[jss::queue_data].size() == 11);
1527 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1529 auto const& parentHash = env.current()->info().parentHash;
1530 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1533 auto const& txj = jrr[jss::queue_data][1u];
1534 BEAST_EXPECT(txj[jss::account] == alice.human());
1535 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1536 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1537 BEAST_EXPECT(txj[
"retries_remaining"] == 10);
1538 BEAST_EXPECT(txj.isMember(jss::tx));
1539 auto const& tx = txj[jss::tx];
1540 BEAST_EXPECT(tx[jss::Account] == alice.human());
1541 BEAST_EXPECT(tx[jss::TransactionType] == jss::AccountSet);
1542 return tx[jss::hash].asString();
1545 auto const& txj = jrr[jss::queue_data][0u];
1546 BEAST_EXPECT(txj[jss::account] == alice.human());
1547 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1548 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1549 BEAST_EXPECT(txj[
"retries_remaining"] == 10);
1550 BEAST_EXPECT(txj.isMember(jss::tx));
1551 auto const& tx = txj[jss::tx];
1552 BEAST_EXPECT(tx[jss::Account] == alice.human());
1553 BEAST_EXPECT(tx[jss::TransactionType] == jss::OfferCreate);
1554 const auto txid0 = tx[jss::hash].asString();
1558 BEAST_EXPECT((tx0 ^ parentHash) < (tx1 ^ parentHash));
1566 jv[jss::expand] =
false;
1568 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1569 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1571 auto const& parentHash = env.current()->info().parentHash;
1572 auto const txid1 = [&]() {
1573 auto const& txj = jrr[jss::queue_data][1u];
1574 BEAST_EXPECT(txj[jss::account] == alice.human());
1575 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1576 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1577 BEAST_EXPECT(txj.isMember(jss::tx));
1578 return txj[jss::tx].asString();
1580 auto const& txj = jrr[jss::queue_data][0u];
1581 BEAST_EXPECT(txj[jss::account] == alice.human());
1582 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1583 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1584 BEAST_EXPECT(txj[
"retries_remaining"] == 9);
1585 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1586 BEAST_EXPECT(txj.isMember(jss::tx));
1587 BEAST_EXPECT(txj[jss::tx] == txid0);
1591 BEAST_EXPECT((tx0 ^ parentHash) < (tx1 ^ parentHash));
1596 jv[jss::expand] =
true;
1597 jv[jss::binary] =
true;
1599 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1600 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1602 auto const& txj = jrr[jss::queue_data][1u];
1603 BEAST_EXPECT(txj[jss::account] == alice.human());
1604 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1605 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1606 BEAST_EXPECT(txj[
"retries_remaining"] == 8);
1607 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1608 BEAST_EXPECT(txj.isMember(jss::tx));
1609 BEAST_EXPECT(txj[jss::tx].isMember(jss::tx_blob));
1611 auto const& txj2 = jrr[jss::queue_data][0u];
1612 BEAST_EXPECT(txj2[jss::account] == alice.human());
1613 BEAST_EXPECT(txj2[jss::fee_level] ==
"256");
1614 BEAST_EXPECT(txj2[
"preflight_result"] ==
"tesSUCCESS");
1615 BEAST_EXPECT(txj2[
"retries_remaining"] == 10);
1616 BEAST_EXPECT(!txj2.isMember(
"last_result"));
1617 BEAST_EXPECT(txj2.isMember(jss::tx));
1618 BEAST_EXPECT(txj2[jss::tx].isMember(jss::tx_blob));
1621 for (
int i = 0; i != 9; ++i)
1626 jv[jss::expand] =
false;
1627 jv[jss::binary] =
false;
1629 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1631 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1633 auto const& txj = jrr[jss::queue_data][0u];
1634 BEAST_EXPECT(txj[jss::account] == alice.human());
1635 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1636 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1637 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1638 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1639 BEAST_EXPECT(txj.isMember(jss::tx));
1640 BEAST_EXPECT(txj[jss::tx] != txid0);
1641 return txj[jss::tx].asString();
1646 jv[jss::full] =
true;
1648 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1649 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1651 auto const& txj = jrr[jss::queue_data][0u];
1652 BEAST_EXPECT(txj[jss::account] == alice.human());
1653 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1654 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1655 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1656 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1657 BEAST_EXPECT(txj.isMember(jss::tx));
1658 auto const& tx = txj[jss::tx];
1659 BEAST_EXPECT(tx[jss::Account] == alice.human());
1660 BEAST_EXPECT(tx[jss::TransactionType] == jss::AccountSet);
1661 BEAST_EXPECT(tx[jss::hash] == txid2);
1668 testcase(
"Ledger Request, Accounts Hashes");
1669 using namespace test::jtx;
1678 jvParams[jss::ledger_index] = 3u;
1679 jvParams[jss::accounts] =
true;
1680 jvParams[jss::expand] =
true;
1681 jvParams[jss::type] =
"hashes";
1683 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1684 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1685 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1686 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1688 jrr[jss::ledger][jss::accountState][0u][
"LedgerEntryType"] ==
1690 index = jrr[jss::ledger][jss::accountState][0u][
"index"].asString();
1694 jvParams[jss::ledger_index] = 3u;
1695 jvParams[jss::accounts] =
true;
1696 jvParams[jss::expand] =
false;
1697 jvParams[jss::type] =
"hashes";
1699 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1700 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1701 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1702 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1703 BEAST_EXPECT(jrr[jss::ledger][jss::accountState][0u] == index);