2#include <test/jtx/Account.h>
3#include <test/jtx/Env.h>
4#include <test/jtx/TestHelpers.h>
5#include <test/jtx/acctdelete.h>
6#include <test/jtx/amount.h>
7#include <test/jtx/balance.h>
8#include <test/jtx/credentials.h>
9#include <test/jtx/deposit.h>
10#include <test/jtx/fee.h>
11#include <test/jtx/flags.h>
12#include <test/jtx/ter.h>
13#include <test/jtx/ticket.h>
14#include <test/jtx/txflags.h>
16#include <xrpld/rpc/Context.h>
17#include <xrpld/rpc/Role.h>
18#include <xrpld/rpc/handlers/Handlers.h>
20#include <xrpl/basics/Buffer.h>
21#include <xrpl/basics/Slice.h>
22#include <xrpl/basics/base_uint.h>
23#include <xrpl/basics/chrono.h>
24#include <xrpl/basics/strHex.h>
25#include <xrpl/beast/unit_test/suite.h>
26#include <xrpl/beast/utility/Zero.h>
27#include <xrpl/core/Job.h>
28#include <xrpl/core/ServiceRegistry.h>
29#include <xrpl/json/json_value.h>
30#include <xrpl/json/to_string.h>
31#include <xrpl/ledger/Dir.h>
32#include <xrpl/ledger/ReadView.h>
33#include <xrpl/protocol/ApiVersion.h>
34#include <xrpl/protocol/Feature.h>
35#include <xrpl/protocol/Indexes.h>
36#include <xrpl/protocol/KeyType.h>
37#include <xrpl/protocol/LedgerFormats.h>
38#include <xrpl/protocol/PayChan.h>
39#include <xrpl/protocol/PublicKey.h>
40#include <xrpl/protocol/SField.h>
41#include <xrpl/protocol/STAmount.h>
42#include <xrpl/protocol/SecretKey.h>
43#include <xrpl/protocol/SeqProxy.h>
44#include <xrpl/protocol/Serializer.h>
45#include <xrpl/protocol/TER.h>
46#include <xrpl/protocol/TxFlags.h>
47#include <xrpl/protocol/jss.h>
48#include <xrpl/resource/Charge.h>
49#include <xrpl/resource/Consumer.h>
50#include <xrpl/resource/Fees.h>
77 return {k.key, view.
read(k)};
95 auto const slep = view.
read({ltPAYCHAN, chan});
98 return (*slep)[sfAmount];
104 auto const slep = view.
read({ltPAYCHAN, chan});
107 if (
auto const r = (*slep)[~sfExpiration])
118 Env env{*
this, features};
119 auto const alice =
Account(
"alice");
120 auto const bob =
Account(
"bob");
121 auto usda = alice[
"USD"];
122 env.
fund(
XRP(10000), alice, bob);
123 auto const pk = alice.pk();
124 auto const settleDelay = 100s;
125 auto const chan =
channel(alice, bob, env.
seq(alice));
126 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
131 auto const preAlice = env.
balance(alice);
132 env(
fund(alice, chan,
XRP(1000)));
133 auto const feeDrops = env.
current()->fees().base;
134 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
139 BEAST_EXPECT(chanBal ==
XRP(0));
140 BEAST_EXPECT(chanAmt ==
XRP(2000));
163 auto const iou = usda(100).value();
164 auto const negXRP =
XRP(-100).value();
165 auto const posXRP =
XRP(100).value();
175 auto const delta =
XRP(500);
176 auto const reqBal = chanBal + delta;
177 auto const authAmt = reqBal +
XRP(-100);
178 assert(reqBal <= chanAmt);
183 auto const preBob = env.
balance(bob);
184 auto const delta =
XRP(500);
185 auto const reqBal = chanBal + delta;
186 auto const authAmt = reqBal +
XRP(100);
187 assert(reqBal <= chanAmt);
188 env(
claim(alice, chan, reqBal, authAmt));
191 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
196 auto preBob = env.
balance(bob);
197 auto const delta =
XRP(500);
198 auto const reqBal = chanBal + delta;
199 auto const authAmt = reqBal +
XRP(100);
200 assert(reqBal <= chanAmt);
201 auto const sig =
signClaimAuth(alice.pk(), alice.sk(), chan, authAmt);
202 env(
claim(bob, chan, reqBal, authAmt,
Slice(sig), alice.pk()));
205 auto const feeDrops = env.
current()->fees().base;
206 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
211 env(
claim(bob, chan, reqBal, authAmt,
Slice(sig), alice.pk()),
215 BEAST_EXPECT(env.
balance(bob) == preBob - feeDrops);
219 auto const preBob = env.
balance(bob);
222 assert(reqAmt <= chanAmt);
223 auto const sig =
signClaimAuth(alice.pk(), alice.sk(), chan, authAmt);
227 BEAST_EXPECT(env.
balance(bob) == preBob);
238 env(
claim(bob, chan,
XRP(1500).value(),
XRP(1500).value(),
Slice(sig), bob.pk()),
246 env(
claim(bob, chan,
XRP(1500).value(),
XRP(1500).value(),
Slice(sig), alice.pk()),
253 auto const preAlice = env.
balance(alice);
254 auto const preBob = env.
balance(bob);
257 auto const feeDrops = env.
current()->fees().base;
258 auto const delta = chanAmt - chanBal;
260 BEAST_EXPECT(env.
balance(alice) == preAlice + delta);
261 BEAST_EXPECT(env.
balance(bob) == preBob - feeDrops);
272 Env env{*
this, features};
273 auto const alice =
Account(
"alice");
274 auto const bob =
Account(
"bob");
275 auto const cho =
Account(
"cho");
276 env.
fund(
XRP(10000), alice, bob, cho);
277 auto const pk = alice.pk();
278 auto const settleDelay = 100s;
281 env(
fset(bob, asfDisallowIncomingPayChan));
286 auto const chan =
channel(alice, bob, env.
seq(alice));
292 env(
fset(alice, asfDisallowIncomingPayChan));
297 auto const chan =
channel(bob, alice, env.
seq(bob));
303 env(
fclear(bob, asfDisallowIncomingPayChan));
308 auto const chan =
channel(alice, bob, env.
seq(alice));
315 auto const chan =
channel(cho, alice, env.
seq(cho));
321 env(
fclear(alice, asfDisallowIncomingPayChan));
326 auto const chan =
channel(cho, alice, env.
seq(cho));
338 auto const alice =
Account(
"alice");
339 auto const bob =
Account(
"bob");
340 auto const carol =
Account(
"carol");
343 Env env{*
this, features};
344 env.
fund(
XRP(10000), alice, bob);
345 auto const pk = alice.pk();
346 auto const settleDelay = 100s;
348 env.
current()->header().parentCloseTime + 3600s;
349 auto const channelFunds =
XRP(1000);
350 auto const chan =
channel(alice, bob, env.
seq(alice));
351 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
353 env.
close(cancelAfter);
358 auto preAlice = env.
balance(alice);
359 auto preBob = env.
balance(bob);
360 auto const delta =
XRP(500);
361 auto const reqBal = chanBal + delta;
362 auto const authAmt = reqBal +
XRP(100);
363 assert(reqBal <= chanAmt);
364 auto const sig =
signClaimAuth(alice.pk(), alice.sk(), chan, authAmt);
365 env(
claim(bob, chan, reqBal, authAmt,
Slice(sig), alice.pk()));
366 auto const feeDrops = env.
current()->fees().base;
368 BEAST_EXPECT(env.
balance(bob) == preBob - feeDrops);
369 BEAST_EXPECT(env.
balance(alice) == preAlice + channelFunds);
374 Env env{*
this, features};
375 env.
fund(
XRP(10000), alice, bob, carol);
376 auto const pk = alice.pk();
377 auto const settleDelay = 100s;
379 env.
current()->header().parentCloseTime + 3600s;
380 auto const channelFunds =
XRP(1000);
381 auto const chan =
channel(alice, bob, env.
seq(alice));
382 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
387 env.
close(cancelAfter);
389 auto const preAlice = env.
balance(alice);
392 BEAST_EXPECT(env.
balance(alice) == preAlice + channelFunds);
397 for (
bool const withFixPayChan : {
true,
false})
399 auto const amend = withFixPayChan ? features : features - fixPayChanCancelAfter;
400 Env env{*
this, amend};
401 env.
fund(
XRP(10000), alice, bob);
404 auto const pk = alice.pk();
405 auto const settleDelay = 100s;
406 auto const channelFunds =
XRP(1000);
408 env.
current()->header().parentCloseTime - 1s;
410 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter), txResult);
416 for (
bool const withFixPayChan : {
true,
false})
418 auto const amend = withFixPayChan ? features : features - fixPayChanCancelAfter;
419 Env env{*
this, amend};
420 env.
fund(
XRP(10000), alice, bob);
423 auto const pk = alice.pk();
424 auto const settleDelay = 100s;
425 auto const channelFunds =
XRP(1000);
427 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter),
439 Env env{*
this, features};
440 auto const alice =
Account(
"alice");
441 auto const bob =
Account(
"bob");
442 auto const carol =
Account(
"carol");
443 env.
fund(
XRP(10000), alice, bob, carol);
444 auto const pk = alice.pk();
445 auto const settleDelay = 3600s;
446 auto const closeTime = env.
current()->header().parentCloseTime;
447 auto const minExpiration = closeTime + settleDelay;
449 auto const channelFunds =
XRP(1000);
450 auto const chan =
channel(alice, bob, env.
seq(alice));
451 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
456 auto counts = [](
auto const& t) {
return t.time_since_epoch().count(); };
482 env.
close(minExpiration);
494 Env env{*
this, features};
495 auto const alice =
Account(
"alice");
496 auto const bob =
Account(
"bob");
497 env.
fund(
XRP(10000), alice, bob);
498 auto const pk = alice.pk();
499 auto const settleDelay = 3600s;
501 env.
current()->header().parentCloseTime + settleDelay;
502 auto const channelFunds =
XRP(1000);
503 auto const chan =
channel(alice, bob, env.
seq(alice));
504 env(
create(alice, bob, channelFunds, settleDelay, pk));
509 env.
close(settleTimepoint - (settleDelay / 2));
514 auto preBob = env.
balance(bob);
515 auto const delta =
XRP(500);
516 auto const reqBal = chanBal + delta;
517 auto const authAmt = reqBal +
XRP(100);
518 assert(reqBal <= chanAmt);
519 auto const sig =
signClaimAuth(alice.pk(), alice.sk(), chan, authAmt);
520 env(
claim(bob, chan, reqBal, authAmt,
Slice(sig), alice.pk()));
523 auto const feeDrops = env.
current()->fees().base;
524 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
526 env.
close(settleTimepoint);
531 auto const preAlice = env.
balance(alice);
532 auto preBob = env.
balance(bob);
533 auto const delta =
XRP(500);
534 auto const reqBal = chanBal + delta;
535 auto const authAmt = reqBal +
XRP(100);
536 assert(reqBal <= chanAmt);
537 auto const sig =
signClaimAuth(alice.pk(), alice.sk(), chan, authAmt);
538 env(
claim(bob, chan, reqBal, authAmt,
Slice(sig), alice.pk()));
540 auto const feeDrops = env.
current()->fees().base;
541 BEAST_EXPECT(env.
balance(alice) == preAlice + chanAmt - chanBal);
542 BEAST_EXPECT(env.
balance(bob) == preBob - feeDrops);
552 Env env{*
this, features};
553 auto const alice =
Account(
"alice");
554 auto const bob =
Account(
"bob");
555 env.
fund(
XRP(10000), alice, bob);
556 auto const pk = alice.pk();
557 auto const settleDelay = 3600s;
558 auto const channelFunds =
XRP(1000);
559 auto const chan =
channel(alice, bob, env.
seq(alice));
560 env(
create(alice, bob, channelFunds, settleDelay, pk));
567 auto const preBob = env.
balance(bob);
568 env(
claim(alice, chan, channelFunds.value(), channelFunds.value()));
570 BEAST_EXPECT(env.
balance(bob) == preBob + channelFunds);
572 auto const preAlice = env.
balance(alice);
576 auto const feeDrops = env.
current()->fees().base;
577 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
587 Env env{*
this, features};
588 auto const alice =
Account(
"alice");
589 auto const bob =
Account(
"bob");
590 env.
fund(
XRP(10000), alice, bob);
591 auto const pk = alice.pk();
592 auto const settleDelay = 3600s;
593 auto const channelFunds =
XRP(1000);
594 auto const chan =
channel(alice, bob, env.
seq(alice));
595 env(
create(alice, bob, channelFunds, settleDelay, pk));
603 auto const preBob = env.
balance(bob);
605 auto const delta =
XRP(500);
606 auto const reqBal = chanBal + delta;
607 assert(reqBal <= chanAmt);
608 auto const sig =
signClaimAuth(alice.pk(), alice.sk(), chan, reqBal);
609 env(
claim(bob, chan, reqBal, std::nullopt,
Slice(sig), alice.pk()));
611 auto const feeDrops = env.
current()->fees().base;
612 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
619 auto const preBob = env.
balance(bob);
621 auto const delta =
XRP(500);
622 auto const reqBal = chanBal + delta;
623 assert(reqBal <= chanAmt);
624 auto const sig =
signClaimAuth(alice.pk(), alice.sk(), chan, reqBal);
625 env(
claim(bob, chan, reqBal, std::nullopt,
Slice(sig), alice.pk()));
627 auto const feeDrops = env.
current()->fees().base;
628 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
641 auto const alice =
Account(
"alice");
642 auto const bob =
Account(
"bob");
646 Env env{*
this, features};
647 env.
fund(
XRP(10000), alice, bob);
648 env(
fset(bob, asfDisallowXRP));
649 auto const chan =
channel(alice, bob, env.
seq(alice));
650 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
658 Env env{*
this, features};
659 env.
fund(
XRP(10000), alice, bob);
660 auto const chan =
channel(alice, bob, env.
seq(alice));
661 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
664 env(
fset(bob, asfDisallowXRP));
665 auto const reqBal =
XRP(500).value();
666 env(
claim(alice, chan, reqBal, reqBal));
678 Env env{*
this, features};
679 auto const alice =
Account(
"alice");
680 auto const bob =
Account(
"bob");
681 env.
fund(
XRP(10000), alice, bob);
682 env(
fset(bob, asfRequireDest));
683 auto const pk = alice.pk();
684 auto const settleDelay = 3600s;
685 auto const channelFunds =
XRP(1000);
687 auto const chan =
channel(alice, bob, env.
seq(alice));
692 auto const chan =
channel(alice, bob, env.
seq(alice));
693 env(
create(alice, bob, channelFunds, settleDelay, pk, std::nullopt, 1));
705 auto const alice =
Account(
"alice");
706 auto const bob =
Account(
"bob");
707 auto const carol =
Account(
"carol");
708 auto usda = alice[
"USD"];
710 Env env{*
this, features};
711 env.
fund(
XRP(10000), alice, bob, carol);
713 env(
fset(bob, asfDepositAuth));
716 auto const pk = alice.pk();
717 auto const settleDelay = 100s;
718 auto const chan =
channel(alice, bob, env.
seq(alice));
719 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
727 env(
fund(alice, chan,
XRP(1000)));
735 auto const baseFee = env.
current()->fees().base;
736 auto const preBob = env.
balance(bob);
738 auto const delta =
XRP(500).value();
745 BEAST_EXPECT(env.
balance(bob) == preBob);
755 env(
claim(bob, chan, delta, delta,
Slice(sig), pk));
757 BEAST_EXPECT(env.
balance(bob) == preBob + delta - baseFee);
761 auto const delta =
XRP(600).value();
786 env(
claim(alice, chan, delta, delta,
Slice(sig), pk));
789 BEAST_EXPECT(env.
balance(bob) == preBob + delta - (3 * baseFee));
794 auto const delta =
XRP(800).value();
804 env(
fclear(bob, asfDepositAuth));
808 env(
claim(alice, chan, delta, delta));
810 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(800) - (5 * baseFee));
818 testcase(
"Deposit Authorization with Credentials");
822 char const credType[] =
"abcde";
827 Account const dillon(
"dillon");
832 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
834 auto const pk = alice.
pk();
835 auto const settleDelay = 100s;
836 auto const chan =
channel(alice, bob, env.
seq(alice));
837 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
841 env(
fund(alice, chan,
XRP(1000)));
845 "D007AE4B6E1274B4AF872588267B810C2F82716726351D1C7D38D3E5499FC6"
848 auto const delta =
XRP(500).value();
853 env.
current()->header().parentCloseTime.time_since_epoch().count() + 100;
854 jv[sfExpiration.jsonName] = t;
860 std::string const credIdx = jv[jss::result][jss::index].asString();
863 env(
fset(bob, asfDepositAuth));
867 env(
claim(alice, chan, delta, delta),
876 env(
claim(alice, chan, delta, delta),
886 env(
claim(dillon, chan, delta, delta),
894 env(
claim(alice, chan, delta, delta),
905 for (
int i = 0; i < 10; ++i)
919 std::string const credIdx = jv[jss::result][jss::index].asString();
928 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
930 auto const pk = alice.
pk();
931 auto const settleDelay = 100s;
932 auto const chan =
channel(alice, bob, env.
seq(alice));
933 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
937 env(
fund(alice, chan,
XRP(1000)));
940 auto const delta =
XRP(500).value();
950 std::string const credIdx = jv[jss::result][jss::index].asString();
960 env.
fund(
XRP(5000),
"alice",
"bob");
963 auto const pk = alice.
pk();
964 auto const settleDelay = 100s;
965 auto const chan =
channel(alice, bob, env.
seq(alice));
966 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
969 env(
fund(alice, chan,
XRP(1000)));
972 "48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6EA288B"
976 env(
fset(bob, asfDepositAuth));
981 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
991 testcase(
"Multiple channels to the same account");
994 Env env{*
this, features};
995 auto const alice =
Account(
"alice");
996 auto const bob =
Account(
"bob");
997 env.
fund(
XRP(10000), alice, bob);
998 auto const pk = alice.pk();
999 auto const settleDelay = 3600s;
1000 auto const channelFunds =
XRP(1000);
1001 auto const chan1 =
channel(alice, bob, env.
seq(alice));
1002 env(
create(alice, bob, channelFunds, settleDelay, pk));
1004 auto const chan2 =
channel(alice, bob, env.
seq(alice));
1005 env(
create(alice, bob, channelFunds, settleDelay, pk));
1007 BEAST_EXPECT(chan1 != chan2);
1015 using namespace jtx;
1017 Env env{*
this, features};
1018 auto const alice =
Account(
"alice");
1019 auto const bob =
Account(
"bob");
1021 env.
fund(
XRP(10000), alice, bob, charlie);
1022 auto const pk = alice.pk();
1023 auto const settleDelay = 3600s;
1024 auto const channelFunds =
XRP(1000);
1026 env(
create(alice, bob, channelFunds, settleDelay, pk));
1030 auto testInvalidAccountParam = [&](
auto const& param) {
1032 params[jss::account] = param;
1034 env.
rpc(
"json",
"account_channels",
to_string(params))[jss::result];
1035 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1036 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'account'.");
1039 testInvalidAccountParam(1);
1040 testInvalidAccountParam(1.1);
1041 testInvalidAccountParam(
true);
1048 auto testInvalidDestAccountParam = [&](
auto const& param) {
1050 params[jss::account] = alice.human();
1051 params[jss::destination_account] = param;
1053 env.
rpc(
"json",
"account_channels",
to_string(params))[jss::result];
1054 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1055 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'destination_account'.");
1058 testInvalidDestAccountParam(1);
1059 testInvalidDestAccountParam(1.1);
1060 testInvalidDestAccountParam(
true);
1066 auto const r = env.
rpc(
"account_channels", alice.human(), bob.human());
1067 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 1);
1068 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1069 BEAST_EXPECT(r[jss::result][jss::validated]);
1072 auto const r = env.
rpc(
"account_channels", alice.human());
1073 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 1);
1074 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1075 BEAST_EXPECT(r[jss::result][jss::validated]);
1078 auto const r = env.
rpc(
"account_channels", bob.human(), alice.human());
1079 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 0);
1080 BEAST_EXPECT(r[jss::result][jss::validated]);
1083 env(
create(alice, bob, channelFunds, settleDelay, pk));
1086 auto const r = env.
rpc(
"account_channels", alice.human(), bob.human());
1087 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 2);
1088 BEAST_EXPECT(r[jss::result][jss::validated]);
1089 BEAST_EXPECT(chan1Str != chan2Str);
1090 for (
auto const& c : {chan1Str, chan2Str})
1093 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1094 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1102 testcase(
"Account channels RPC markers");
1107 auto const alice =
Account(
"alice");
1112 for (
int i = 0; i < n; ++i)
1119 Env env{*
this, features};
1121 for (
auto const& a : bobs)
1129 auto const settleDelay = 3600s;
1130 auto const channelFunds =
XRP(1);
1131 for (
auto const& b : bobs)
1133 env(
create(alice, b, channelFunds, settleDelay, alice.pk()));
1143 jvc[jss::account] = src.human();
1145 jvc[jss::destination_account] = dst->human();
1147 jvc[jss::limit] = *limit;
1149 jvc[jss::marker] = marker;
1151 return env.
rpc(
"json",
"account_channels",
to_string(jvc))[jss::result];
1156 auto const r = testLimit(env, alice);
1157 BEAST_EXPECT(r.isMember(jss::channels));
1158 BEAST_EXPECT(r[jss::channels].
size() == bobs.size());
1163 for (
auto const& a : bobs)
1168 for (
int limit = 1; limit < bobs.size() + 1; ++limit)
1170 auto leftToFind = bobsB58;
1171 auto const numFull = bobs.size() / limit;
1172 auto const numNonFull = ((bobs.size() % limit) != 0u) ? 1 : 0;
1176 auto const testIt = [&](
bool expectMarker,
int expectedBatchSize) {
1177 auto const r = testLimit(env, alice, limit, marker);
1178 BEAST_EXPECT(!expectMarker || r.isMember(jss::marker));
1179 if (r.isMember(jss::marker))
1180 marker = r[jss::marker];
1181 BEAST_EXPECT(r[jss::channels].
size() == expectedBatchSize);
1182 auto const c = r[jss::channels];
1183 auto const s = r[jss::channels].size();
1184 for (
int j = 0; j < s; ++j)
1186 auto const dstAcc = c[j][jss::destination_account].asString();
1187 BEAST_EXPECT(leftToFind.count(dstAcc));
1188 leftToFind.erase(dstAcc);
1192 for (
int i = 0; i < numFull; ++i)
1194 bool const expectMarker = (numNonFull != 0 || i < numFull - 1);
1195 testIt(expectMarker, limit);
1198 if (numNonFull != 0)
1200 testIt(
false, bobs.size() % limit);
1202 BEAST_EXPECT(leftToFind.empty());
1207 auto const r = testLimit(env, alice, 0);
1208 BEAST_EXPECT(r.isMember(jss::error_message));
1217 testcase(
"Account channels RPC owner only");
1222 auto const alice =
Account(
"alice");
1223 auto const bob =
Account(
"bob");
1224 Env env{*
this, features};
1225 env.
fund(
XRP(10000), alice, bob);
1230 auto const settleDelay = 3600s;
1231 auto const channelFunds =
XRP(1000);
1232 env(
create(alice, bob, channelFunds, settleDelay, alice.pk()));
1233 env(
create(bob, alice, channelFunds, settleDelay, bob.pk()));
1235 auto const r = [&] {
1237 jvc[jss::account] = alice.human();
1239 return env.
rpc(
"json",
"account_channels",
to_string(jvc))[jss::result];
1241 BEAST_EXPECT(r.isMember(jss::channels));
1242 BEAST_EXPECT(r[jss::channels].
size() == 1);
1243 BEAST_EXPECT(r[jss::channels][0u][jss::destination_account].asString() == bob.human());
1249 using namespace jtx;
1252 Env env{*
this, features};
1253 auto const alice =
Account(
"alice");
1254 auto const bob =
Account(
"bob");
1256 env.
fund(
XRP(10000), alice, bob, charlie);
1257 auto const pk = alice.pk();
1258 auto const settleDelay = 3600s;
1259 auto const channelFunds =
XRP(1000);
1261 env(
create(alice, bob, channelFunds, settleDelay, pk));
1265 args[jss::channel_id] = chan1Str;
1266 args[jss::key_type] =
"ed255191";
1267 args[jss::seed] =
"snHq1rzQoN2qiUkC3XF5RyxBzUtN";
1268 args[jss::amount] = 51110000;
1273 args[jss::api_version] = apiVersion;
1276 auto const error = apiVersion < 2u ?
"invalidParams" :
"badKeyType";
1277 BEAST_EXPECT(rs[jss::error] == error);
1284 testcase(
"PayChan Auth/Verify RPC");
1285 using namespace jtx;
1287 Env env{*
this, features};
1288 auto const alice =
Account(
"alice");
1289 auto const bob =
Account(
"bob");
1291 env.
fund(
XRP(10000), alice, bob, charlie);
1292 auto const pk = alice.pk();
1293 auto const settleDelay = 3600s;
1294 auto const channelFunds =
XRP(1000);
1296 env(
create(alice, bob, channelFunds, settleDelay, pk));
1300 auto const r = env.
rpc(
"account_channels", alice.human(), bob.human());
1301 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 1);
1302 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1303 BEAST_EXPECT(r[jss::result][jss::validated]);
1304 chan1PkStr = r[jss::result][jss::channels][0u][jss::public_key].asString();
1307 auto const r = env.
rpc(
"account_channels", alice.human());
1308 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 1);
1309 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1310 BEAST_EXPECT(r[jss::result][jss::validated]);
1311 chan1PkStr = r[jss::result][jss::channels][0u][jss::public_key].asString();
1314 auto const r = env.
rpc(
"account_channels", bob.human(), alice.human());
1315 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 0);
1316 BEAST_EXPECT(r[jss::result][jss::validated]);
1319 env(
create(alice, bob, channelFunds, settleDelay, pk));
1322 auto const r = env.
rpc(
"account_channels", alice.human(), bob.human());
1323 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 2);
1324 BEAST_EXPECT(r[jss::result][jss::validated]);
1325 BEAST_EXPECT(chan1Str != chan2Str);
1326 for (
auto const& c : {chan1Str, chan2Str})
1329 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1330 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1339 s +=
"0123456789ABCDEF"[((
byte & 0xf0) >> 4)];
1340 s +=
"0123456789ABCDEF"[((
byte & 0x0f) >> 0)];
1347 auto const rs = env.
rpc(
"channel_authorize",
"alice", chan1Str,
"1000");
1348 auto const sig = rs[jss::result][jss::signature].
asString();
1349 BEAST_EXPECT(!sig.empty());
1351 auto const rv = env.
rpc(
"channel_verify", chan1PkStr, chan1Str,
"1000", sig);
1352 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1358 auto const rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1000", sig);
1359 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1364 auto rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1000x", sig);
1365 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1366 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 ", sig);
1367 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1368 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"x1000", sig);
1369 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1370 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"x", sig);
1371 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1372 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
" ", sig);
1373 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1374 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 1000", sig);
1375 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1376 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1,000", sig);
1377 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1378 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
" 1000", sig);
1379 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1380 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"", sig);
1381 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1386 auto chan1StrBad = chan1Str;
1387 chan1StrBad.pop_back();
1388 auto rv = env.
rpc(
"channel_verify", pkAsHex, chan1StrBad,
"1000", sig);
1389 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1390 rv = env.
rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1391 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1393 chan1StrBad = chan1Str;
1394 chan1StrBad.push_back(
'0');
1395 rv = env.
rpc(
"channel_verify", pkAsHex, chan1StrBad,
"1000", sig);
1396 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1397 rv = env.
rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1398 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1400 chan1StrBad = chan1Str;
1401 chan1StrBad.back() =
'x';
1402 rv = env.
rpc(
"channel_verify", pkAsHex, chan1StrBad,
"1000", sig);
1403 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1404 rv = env.
rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1405 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1410 args[jss::amount] =
"2000";
1411 args[jss::channel_id] = 2000;
1412 args[jss::key_type] =
"secp256k1";
1413 args[jss::passphrase] =
"passphrase_can_be_anything";
1417 BEAST_EXPECT(ra[jss::error] ==
"invalidParams");
1422 args[jss::public_key] = chan1PkStr;
1423 args[jss::channel_id] = 2000;
1424 args[jss::amount] =
"1000";
1425 args[jss::signature] = sig;
1429 BEAST_EXPECT(rv[jss::error] ==
"invalidParams");
1433 auto illFormedPk = chan1PkStr.
substr(0, chan1PkStr.
size() - 1);
1434 auto const rv = env.
rpc(
"channel_verify", illFormedPk, chan1Str,
"1000", sig);
1435 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1440 auto illFormedPk = pkAsHex.substr(0, chan1PkStr.
size() - 1);
1441 auto const rv = env.
rpc(
"channel_verify", illFormedPk, chan1Str,
"1000", sig);
1442 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1447 auto const rs = env.
rpc(
"channel_authorize",
"alice", chan2Str,
"1000");
1448 auto const sig = rs[jss::result][jss::signature].
asString();
1449 BEAST_EXPECT(!sig.empty());
1451 auto const rv = env.
rpc(
"channel_verify", chan1PkStr, chan1Str,
"1000", sig);
1452 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1457 auto const rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1000", sig);
1458 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1464 env(
create(charlie, alice, channelFunds, settleDelay, charlie.pk()));
1469 auto const r = env.
rpc(
"account_channels", charlie.human(), alice.human());
1470 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 1);
1471 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1472 BEAST_EXPECT(r[jss::result][jss::validated]);
1473 cpk = r[jss::result][jss::channels][0u][jss::public_key].asString();
1477 auto const rs = env.
rpc(
"channel_authorize",
"charlie", chan,
"1000");
1478 auto const sig = rs[jss::result][jss::signature].
asString();
1479 BEAST_EXPECT(!sig.empty());
1481 auto const rv = env.
rpc(
"channel_verify", cpk, chan,
"1000", sig);
1482 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1486 auto const rs1 = env.
rpc(
"channel_authorize",
"charlie",
"nyx", chan,
"1000");
1487 BEAST_EXPECT(rs1[jss::error] ==
"badKeyType");
1491 auto const rs2 = env.
rpc(
"channel_authorize",
"charlie",
"secp256k1", chan,
"1000");
1492 auto const sig2 = rs2[jss::result][jss::signature].
asString();
1493 BEAST_EXPECT(!sig2.empty());
1495 auto const rv = env.
rpc(
"channel_verify", cpk, chan,
"1000", sig2);
1496 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1500 auto const rs3 = env.
rpc(
"channel_authorize",
"charlie",
"ed25519", chan,
"1000");
1501 auto const sig3 = rs3[jss::result][jss::signature].
asString();
1502 BEAST_EXPECT(!sig3.empty());
1504 auto const rv = env.
rpc(
"channel_verify", cpk, chan,
"1000", sig3);
1505 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1511 auto rs = env.
rpc(
"channel_authorize",
"alice", chan1Str,
"1000x");
1512 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1513 rs = env.
rpc(
"channel_authorize",
"alice", chan1Str,
"x1000");
1514 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1515 rs = env.
rpc(
"channel_authorize",
"alice", chan1Str,
"x");
1516 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1520 args[jss::amount] =
"2000";
1521 args[jss::key_type] =
"secp256k1";
1522 args[jss::passphrase] =
"passphrase_can_be_anything";
1524 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1529 args[jss::channel_id] = chan1Str;
1530 args[jss::key_type] =
"secp256k1";
1531 args[jss::passphrase] =
"passphrase_can_be_anything";
1533 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1538 args[jss::amount] =
"2000";
1539 args[jss::channel_id] = chan1Str;
1540 args[jss::passphrase] =
"passphrase_can_be_anything";
1542 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1547 args[jss::amount] =
"2000";
1548 args[jss::channel_id] = chan1Str;
1549 args[jss::key_type] =
"secp256k1";
1550 args[jss::passphrase] =
"passphrase_can_be_anything";
1551 args[jss::seed] =
"seed can be anything";
1553 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1558 args[jss::amount] =
"2000";
1559 args[jss::channel_id] = chan1Str +
"1";
1560 args[jss::key_type] =
"secp256k1";
1561 args[jss::passphrase] =
"passphrase_can_be_anything";
1563 BEAST_EXPECT(rs[jss::error] ==
"channelMalformed");
1568 args[jss::amount] = 2000;
1569 args[jss::channel_id] = chan1Str;
1570 args[jss::key_type] =
"secp256k1";
1571 args[jss::passphrase] =
"passphrase_can_be_anything";
1573 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1578 args[jss::amount] =
"TwoThousand";
1579 args[jss::channel_id] = chan1Str;
1580 args[jss::key_type] =
"secp256k1";
1581 args[jss::passphrase] =
"passphrase_can_be_anything";
1583 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1592 using namespace jtx;
1594 Env env{*
this, features};
1595 auto const alice =
Account(
"alice");
1596 auto const bob =
Account(
"bob");
1597 auto const carol =
Account(
"carol");
1598 auto const dan =
Account(
"dan");
1599 env.
fund(
XRP(10000), alice, bob, carol, dan);
1600 auto const pk = alice.pk();
1601 auto const settleDelay = 3600s;
1602 auto const channelFunds =
XRP(1000);
1608 env(
create(alice, bob, channelFunds, settleDelay, pk));
1609 auto const r = env.
rpc(
"account_channels", alice.human(), bob.human());
1610 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 1);
1611 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1612 BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember(jss::destination_tag));
1617 env(
create(alice, carol, channelFunds, settleDelay, pk, cancelAfter, dstTag));
1618 auto const r = env.
rpc(
"account_channels", alice.human(), carol.human());
1619 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 1);
1620 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1621 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::destination_tag] == dstTag);
1628 testcase(
"channel_verify sets kFEE_HEAVY_BURDEN_RPC load type");
1630 using namespace jtx;
1633 Env env{*
this, features};
1634 auto const alice =
Account(
"alice");
1635 auto const bob =
Account(
"bob");
1637 env.
fund(
XRP(10000), alice, bob);
1639 auto const pk = alice.pk();
1640 auto const settleDelay = 3600s;
1641 auto const channelFunds =
XRP(1000);
1644 env(
create(alice, bob, channelFunds, settleDelay, pk));
1648 auto const authResult = env.
rpc(
"channel_authorize",
"alice", chanStr,
"1000");
1649 auto const sig = authResult[jss::result][jss::signature].
asString();
1650 BEAST_EXPECT(!sig.empty());
1651 auto const pkHex =
strHex(pk.slice());
1654 auto& app = env.
app();
1660 .loadType = loadType,
1661 .netOps = app.getOPs(),
1662 .ledgerMaster = app.getLedgerMaster(),
1671 params[jss::public_key] = pkHex;
1672 params[jss::channel_id] = chanStr;
1673 params[jss::amount] =
"1000";
1674 params[jss::signature] = sig;
1675 context.
params = std::move(params);
1681 app.getJobQueue().postCoro(
JtClient,
"RPC-Client", [&](
auto const& coro) {
1682 context.
coro = coro;
1687 using namespace std::chrono_literals;
1690 BEAST_EXPECT(result[jss::signature_verified].asBool());
1703 testcase(
"channel_authorize sets kFEE_HEAVY_BURDEN_RPC load type");
1705 using namespace jtx;
1708 Env env{*
this, features};
1709 auto const alice =
Account(
"alice");
1710 auto const bob =
Account(
"bob");
1712 env.
fund(
XRP(10000), alice, bob);
1714 auto const pk = alice.pk();
1715 auto const settleDelay = 3600s;
1718 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1721 auto& app = env.
app();
1727 .loadType = loadType,
1728 .netOps = app.getOPs(),
1729 .ledgerMaster = app.getLedgerMaster(),
1738 params[jss::channel_id] = chanStr;
1739 params[jss::amount] =
"1000";
1740 params[jss::secret] = alice.name();
1741 context.
params = std::move(params);
1747 app.getJobQueue().postCoro(
JtClient,
"RPC-Client", [&](
auto const& coro) {
1748 context.
coro = coro;
1753 using namespace std::chrono_literals;
1757 BEAST_EXPECT(result.
isMember(jss::signature));
1758 BEAST_EXPECT(!result[jss::signature].asString().
empty());
1769 using namespace jtx;
1771 Env env{*
this, features};
1772 auto const alice =
Account(
"alice");
1773 auto const bob =
Account(
"bob");
1774 auto usda = alice[
"USD"];
1775 env.
fund(
XRP(10000), alice, bob);
1776 auto const pk = alice.pk();
1777 auto const settleDelay = 100s;
1779 auto const chan =
channel(alice, bob, env.
seq(alice));
1780 auto jv =
create(alice, bob,
XRP(1000), settleDelay, pk);
1781 auto const pkHex =
strHex(pk.slice());
1782 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1784 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1786 auto badPrefix = pkHex;
1789 jv[
"PublicKey"] = badPrefix;
1792 jv[
"PublicKey"] = pkHex;
1795 auto const authAmt =
XRP(100);
1796 auto const sig =
signClaimAuth(alice.pk(), alice.sk(), chan, authAmt);
1797 jv =
claim(bob, chan, authAmt.value(), authAmt.value(),
Slice(sig), alice.pk());
1798 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1800 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1805 jv[
"PublicKey"] = badPrefix;
1809 jv.removeMember(
"PublicKey");
1813 auto const txn = R
"*(
1816 "channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
1818 "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
1820 "aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
1824 auto const r = env.
rpc(
"json",
"channel_verify", txn);
1825 BEAST_EXPECT(r[
"result"][
"error"] ==
"publicMalformed");
1834 using namespace jtx;
1837 auto const alice =
Account(
"alice");
1838 auto const bob =
Account(
"bob");
1839 auto const settleDelay = 100s;
1840 auto const pk = alice.pk();
1845 return std::find(ownerDir.begin(), ownerDir.end(), chan) != ownerDir.end();
1855 Env env{*
this, features};
1856 env.
fund(
XRP(10000), alice, bob);
1857 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1860 BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle));
1861 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
1862 BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle));
1863 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 1);
1865 env(
claim(bob, chan), Txflags(tfClose));
1867 BEAST_EXPECT(!inOwnerDir(*env.current(), alice, chanSle));
1868 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 0);
1869 BEAST_EXPECT(!inOwnerDir(*env.current(), bob, chanSle));
1870 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 0);
1876 Env env(*
this, features);
1877 env.fund(
XRP(10000), alice, bob);
1879 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1882 BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle));
1883 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
1884 BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle));
1885 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 1);
1889 BEAST_EXPECT(!inOwnerDir(*env.current(), alice, chanSle));
1890 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 0);
1891 BEAST_EXPECT(!inOwnerDir(*env.current(), bob, chanSle));
1892 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 0);
1907 for (
auto minRmSeq = env.seq(toRm) + 257; env.current()->seq() < minRmSeq;
1913 Fee(
drops(env.current()->fees().increment)),
1920 auto const alice =
Account(
"alice");
1921 auto const bob =
Account(
"bob");
1922 auto const carol =
Account(
"carol");
1925 Env env{*
this, features};
1926 env.fund(
XRP(10000), alice, bob, carol);
1930 auto const pk = alice.pk();
1931 auto const settleDelay = 100s;
1932 auto const chan =
channel(alice, bob, env.seq(alice));
1933 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1941 auto const feeDrops = env.current()->fees().base;
1944 BEAST_EXPECT(chanBal ==
XRP(0));
1945 BEAST_EXPECT(chanAmt ==
XRP(1000));
1947 auto preBob = env.balance(bob);
1948 auto const delta =
XRP(50);
1949 auto reqBal = chanBal + delta;
1950 auto authAmt = reqBal +
XRP(100);
1951 assert(reqBal <= chanAmt);
1953 env(
claim(alice, chan, reqBal, authAmt));
1956 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1957 BEAST_EXPECT(env.balance(bob) == preBob + delta);
1960 auto const preAlice = env.balance(alice);
1961 env(
fund(alice, chan,
XRP(1000)));
1963 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
1965 chanAmt = chanAmt +
XRP(1000);
1969 env(
claim(alice, chan), Txflags(tfClose));
1973 auto const closeTime = env.current()->header().parentCloseTime;
1974 auto const minExpiration = closeTime + settleDelay;
1975 env.close(minExpiration);
1986 using namespace jtx;
1988 Env env{*
this, features};
1989 auto const alice =
Account(
"alice");
1990 auto const bob =
Account(
"bob");
1991 auto usda = alice[
"USD"];
1992 env.fund(
XRP(10000), alice, bob);
1997 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
1999 std::uint32_t
const aliceSeq{env.seq(alice)};
2001 std::uint32_t bobTicketSeq{env.seq(bob) + 1};
2003 std::uint32_t
const bobSeq{env.seq(bob)};
2005 auto const pk = alice.pk();
2006 auto const settleDelay = 100s;
2007 auto const chan =
channel(alice, bob, aliceTicketSeq);
2009 env(
create(alice, bob,
XRP(1000), settleDelay, pk), ticket::Use(aliceTicketSeq++));
2011 env.require(
Tickets(alice, env.seq(alice) - aliceTicketSeq));
2012 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2018 auto const preAlice = env.balance(alice);
2019 env(
fund(alice, chan,
XRP(1000)), ticket::Use(aliceTicketSeq++));
2021 env.require(
Tickets(alice, env.seq(alice) - aliceTicketSeq));
2022 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2024 auto const feeDrops = env.current()->fees().base;
2025 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
2030 BEAST_EXPECT(chanBal ==
XRP(0));
2031 BEAST_EXPECT(chanAmt ==
XRP(2000));
2035 auto const preBob = env.balance(bob);
2036 auto const delta =
XRP(500);
2037 auto const reqBal = chanBal + delta;
2038 auto const authAmt = reqBal +
XRP(100);
2039 assert(reqBal <= chanAmt);
2040 env(
claim(alice, chan, reqBal, authAmt), ticket::Use(aliceTicketSeq++));
2042 env.require(
Tickets(alice, env.seq(alice) - aliceTicketSeq));
2043 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2046 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2047 BEAST_EXPECT(env.balance(bob) == preBob + delta);
2052 auto preBob = env.balance(bob);
2053 auto const delta =
XRP(500);
2054 auto const reqBal = chanBal + delta;
2055 auto const authAmt = reqBal +
XRP(100);
2056 assert(reqBal <= chanAmt);
2057 auto const sig =
signClaimAuth(alice.pk(), alice.sk(), chan, authAmt);
2058 env(
claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk()),
2059 ticket::Use(bobTicketSeq++));
2061 env.require(
Tickets(bob, env.seq(bob) - bobTicketSeq));
2062 BEAST_EXPECT(env.seq(bob) == bobSeq);
2065 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2066 auto const feeDrops = env.current()->fees().base;
2067 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
2071 preBob = env.balance(bob);
2073 env(
claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk()),
2074 ticket::Use(bobTicketSeq++),
2077 env.require(
Tickets(bob, env.seq(bob) - bobTicketSeq));
2078 BEAST_EXPECT(env.seq(bob) == bobSeq);
2081 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2082 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2086 auto const preBob = env.balance(bob);
2087 STAmount
const authAmt = chanBal +
XRP(500);
2088 STAmount
const reqAmt = authAmt +
drops(1);
2089 assert(reqAmt <= chanAmt);
2092 auto const sig =
signClaimAuth(alice.pk(), alice.sk(), chan, authAmt);
2093 env(
claim(bob, chan, reqAmt, authAmt, Slice(sig), alice.pk()),
2094 ticket::Use(bobTicketSeq),
2097 env.require(
Tickets(bob, env.seq(bob) - bobTicketSeq));
2098 BEAST_EXPECT(env.seq(bob) == bobSeq);
2101 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2102 BEAST_EXPECT(env.balance(bob) == preBob);
2108 env.require(
Tickets(bob, env.seq(bob) - bobTicketSeq));
2109 BEAST_EXPECT(env.seq(bob) == bobSeq);
2112 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2116 auto const preAlice = env.balance(alice);
2117 auto const preBob = env.balance(bob);
2118 env(
claim(bob, chan), Txflags(tfClose), ticket::Use(bobTicketSeq++));
2120 env.require(
Tickets(bob, env.seq(bob) - bobTicketSeq));
2121 BEAST_EXPECT(env.seq(bob) == bobSeq);
2124 auto const feeDrops = env.current()->fees().base;
2125 auto const delta = chanAmt - chanBal;
2127 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
2128 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2130 env.require(
Tickets(alice, env.seq(alice) - aliceTicketSeq));
2131 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2132 env.require(
Tickets(bob, env.seq(bob) - bobTicketSeq));
2133 BEAST_EXPECT(env.seq(bob) == bobSeq);
TestcaseT testcase
Memberspace for declaring test cases.
std::string toStyledString() const
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
Like std::vector<char> but better.
A class that simplifies iterating ledger directory pages.
std::chrono::time_point< NetClock > time_point
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
std::shared_ptr< STLedgerEntry const > const & ConstRef
static constexpr SeqProxy rawSequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
Slice slice() const noexcept
An immutable linear range of bytes.
value_type cost() const
Return the cost of the charge in resource::Manager units.
An endpoint that consumes resources.
Immutable cryptographic account descriptor.
PublicKey const & pk() const
Return the public key.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
beast::Journal const journal
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
bool waitFor(std::chrono::duration< Rep, Period > const &relTime)
Set the expected result code for a JTx The test will fail if the code doesn't match.
T emplace_back(T... args)
@ Array
array value (ordered list)
@ Object
object value (collection of name/value pairs).
Keylet payChannel(AccountID const &src, AccountID const &dst, SeqProxy const &seq) noexcept
A PaymentChannel.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet account(AccountID const &id) noexcept
AccountID root.
Charge const kFeeHeavyBurdenRpc
Charge const kFeeReferenceRpc
static constexpr auto kApiVersionIfUnspecified
json::Value accept(jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
json::Value create(jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
json::Value ledgerEntry(jtx::Env &env, jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
json::Value authCredentials(jtx::Account const &account, std::vector< AuthorizeCredentials > const &auth)
json::Value auth(Account const &account, Account const &auth)
Preauthorize for deposit.
json::Value unauth(Account const &account, Account const &unauth)
Remove pre-authorization for deposit.
json::Value claim(AccountID const &account, UInt256 const &channel, std::optional< STAmount > const &balance, std::optional< STAmount > const &amount, std::optional< Slice > const &signature, std::optional< PublicKey > const &pk)
json::Value create(AccountID const &account, AccountID const &to, STAmount const &amount, NetClock::duration const &settleDelay, PublicKey const &pk, std::optional< NetClock::time_point > const &cancelAfter, std::optional< std::uint32_t > const &dstTag)
STAmount channelBalance(ReadView const &view, UInt256 const &chan)
bool channelExists(ReadView const &view, UInt256 const &chan)
UInt256 channel(AccountID const &account, AccountID const &dst, std::uint32_t seqProxyValue)
json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
void sign(json::Value &jv, Account const &account, json::Value &sigObject, HashPrefix prefix)
Sign automatically into a specific Json field of the jv object.
std::vector< STAmount > fund(jtx::Env &env, jtx::Account const &gw, std::vector< jtx::Account > const &accounts, std::vector< STAmount > const &amts, Fund how)
XrpT const XRP
Converts to XRP Issue or STAmount.
json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
FeatureBitset testableAmendments()
json::Value acctdelete(Account const &account, Account const &dest)
Delete account.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
OwnerCount< ltTICKET > Tickets
Match the number of tickets on the account.
json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
constexpr XRPAmount
Convert XRP to drops (integral types).
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
void serializePayChanAuthorization(Serializer &msg, UInt256 const &key, XRPAmount const &amt)
void forAllApiVersions(Fn const &fn, Args &&... args)
std::string strHex(FwdIt begin, FwdIt end)
std::string to_string(BaseUInt< Bits, Tag > const &a)
json::Value doChannelVerify(rpc::JsonContext &context)
static std::string sliceToHex(Slice const &slice)
bool isTesSuccess(TER x) noexcept
TERSubset< CanCvtToTER > TER
json::Value doChannelAuthorize(rpc::JsonContext &context)
std::shared_ptr< JobQueue::Coro > coro
resource::Charge & loadType
void testSettleDelay(FeatureBitset features)
void testOptionalFields(FeatureBitset features)
void testSimple(FeatureBitset features)
void testMetaAndOwnership(FeatureBitset features)
void testMultiple(FeatureBitset features)
void testCancelAfter(FeatureBitset features)
void testWithFeats(FeatureBitset features)
static Buffer signClaimAuth(PublicKey const &pk, SecretKey const &sk, UInt256 const &channel, STAmount const &authAmt)
void testDepositAuth(FeatureBitset features)
void testDefaultAmount(FeatureBitset features)
void testCloseDry(FeatureBitset features)
void testDepositAuthCreds()
void testUsingTickets(FeatureBitset features)
void testDstTag(FeatureBitset features)
void testChannelAuthorizeLoadType(FeatureBitset features)
void testAccountChannelAuthorize(FeatureBitset features)
static STAmount channelAmount(ReadView const &view, UInt256 const &chan)
void testAccountChannelsRPC(FeatureBitset features)
void testExpiration(FeatureBitset features)
static std::optional< std::int64_t > channelExpiration(ReadView const &view, UInt256 const &chan)
void testDisallowIncoming(FeatureBitset features)
void testChannelVerifyLoadType(FeatureBitset features)
void testAuthVerifyRPC(FeatureBitset features)
void testAccountDelete(FeatureBitset features)
void run() override
Runs the suite.
static std::pair< UInt256, SLE::const_pointer > channelKeyAndSle(ReadView const &view, jtx::Account const &account, jtx::Account const &dst)
void testDisallowXRP(FeatureBitset features)
void testAccountChannelsRPCSenderOnly(FeatureBitset features)
void testMalformedPK(FeatureBitset features)
void testAccountChannelsRPCMarkers(FeatureBitset features)