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");
1409 auto illFormedPk = chan1PkStr.
substr(0, chan1PkStr.
size() - 1);
1410 auto const rv = env.
rpc(
"channel_verify", illFormedPk, chan1Str,
"1000", sig);
1411 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1416 auto illFormedPk = pkAsHex.substr(0, chan1PkStr.
size() - 1);
1417 auto const rv = env.
rpc(
"channel_verify", illFormedPk, chan1Str,
"1000", sig);
1418 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1423 auto const rs = env.
rpc(
"channel_authorize",
"alice", chan2Str,
"1000");
1424 auto const sig = rs[jss::result][jss::signature].
asString();
1425 BEAST_EXPECT(!sig.empty());
1427 auto const rv = env.
rpc(
"channel_verify", chan1PkStr, chan1Str,
"1000", sig);
1428 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1433 auto const rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1000", sig);
1434 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1440 env(
create(charlie, alice, channelFunds, settleDelay, charlie.pk()));
1445 auto const r = env.
rpc(
"account_channels", charlie.human(), alice.human());
1446 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 1);
1447 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1448 BEAST_EXPECT(r[jss::result][jss::validated]);
1449 cpk = r[jss::result][jss::channels][0u][jss::public_key].asString();
1453 auto const rs = env.
rpc(
"channel_authorize",
"charlie", chan,
"1000");
1454 auto const sig = rs[jss::result][jss::signature].
asString();
1455 BEAST_EXPECT(!sig.empty());
1457 auto const rv = env.
rpc(
"channel_verify", cpk, chan,
"1000", sig);
1458 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1462 auto const rs1 = env.
rpc(
"channel_authorize",
"charlie",
"nyx", chan,
"1000");
1463 BEAST_EXPECT(rs1[jss::error] ==
"badKeyType");
1467 auto const rs2 = env.
rpc(
"channel_authorize",
"charlie",
"secp256k1", chan,
"1000");
1468 auto const sig2 = rs2[jss::result][jss::signature].
asString();
1469 BEAST_EXPECT(!sig2.empty());
1471 auto const rv = env.
rpc(
"channel_verify", cpk, chan,
"1000", sig2);
1472 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1476 auto const rs3 = env.
rpc(
"channel_authorize",
"charlie",
"ed25519", chan,
"1000");
1477 auto const sig3 = rs3[jss::result][jss::signature].
asString();
1478 BEAST_EXPECT(!sig3.empty());
1480 auto const rv = env.
rpc(
"channel_verify", cpk, chan,
"1000", sig3);
1481 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1487 auto rs = env.
rpc(
"channel_authorize",
"alice", chan1Str,
"1000x");
1488 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1489 rs = env.
rpc(
"channel_authorize",
"alice", chan1Str,
"x1000");
1490 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1491 rs = env.
rpc(
"channel_authorize",
"alice", chan1Str,
"x");
1492 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1496 args[jss::amount] =
"2000";
1497 args[jss::key_type] =
"secp256k1";
1498 args[jss::passphrase] =
"passphrase_can_be_anything";
1500 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1505 args[jss::channel_id] = chan1Str;
1506 args[jss::key_type] =
"secp256k1";
1507 args[jss::passphrase] =
"passphrase_can_be_anything";
1509 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1514 args[jss::amount] =
"2000";
1515 args[jss::channel_id] = chan1Str;
1516 args[jss::passphrase] =
"passphrase_can_be_anything";
1518 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1523 args[jss::amount] =
"2000";
1524 args[jss::channel_id] = chan1Str;
1525 args[jss::key_type] =
"secp256k1";
1526 args[jss::passphrase] =
"passphrase_can_be_anything";
1527 args[jss::seed] =
"seed can be anything";
1529 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1534 args[jss::amount] =
"2000";
1535 args[jss::channel_id] = chan1Str +
"1";
1536 args[jss::key_type] =
"secp256k1";
1537 args[jss::passphrase] =
"passphrase_can_be_anything";
1539 BEAST_EXPECT(rs[jss::error] ==
"channelMalformed");
1544 args[jss::amount] = 2000;
1545 args[jss::channel_id] = chan1Str;
1546 args[jss::key_type] =
"secp256k1";
1547 args[jss::passphrase] =
"passphrase_can_be_anything";
1549 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1554 args[jss::amount] =
"TwoThousand";
1555 args[jss::channel_id] = chan1Str;
1556 args[jss::key_type] =
"secp256k1";
1557 args[jss::passphrase] =
"passphrase_can_be_anything";
1559 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1568 using namespace jtx;
1570 Env env{*
this, features};
1571 auto const alice =
Account(
"alice");
1572 auto const bob =
Account(
"bob");
1573 auto const carol =
Account(
"carol");
1574 auto const dan =
Account(
"dan");
1575 env.
fund(
XRP(10000), alice, bob, carol, dan);
1576 auto const pk = alice.pk();
1577 auto const settleDelay = 3600s;
1578 auto const channelFunds =
XRP(1000);
1584 env(
create(alice, bob, channelFunds, settleDelay, pk));
1585 auto const r = env.
rpc(
"account_channels", alice.human(), bob.human());
1586 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 1);
1587 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1588 BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember(jss::destination_tag));
1593 env(
create(alice, carol, channelFunds, settleDelay, pk, cancelAfter, dstTag));
1594 auto const r = env.
rpc(
"account_channels", alice.human(), carol.human());
1595 BEAST_EXPECT(r[jss::result][jss::channels].
size() == 1);
1596 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1597 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::destination_tag] == dstTag);
1604 testcase(
"channel_verify sets kFEE_HEAVY_BURDEN_RPC load type");
1606 using namespace jtx;
1609 Env env{*
this, features};
1610 auto const alice =
Account(
"alice");
1611 auto const bob =
Account(
"bob");
1613 env.
fund(
XRP(10000), alice, bob);
1615 auto const pk = alice.pk();
1616 auto const settleDelay = 3600s;
1617 auto const channelFunds =
XRP(1000);
1620 env(
create(alice, bob, channelFunds, settleDelay, pk));
1624 auto const authResult = env.
rpc(
"channel_authorize",
"alice", chanStr,
"1000");
1625 auto const sig = authResult[jss::result][jss::signature].
asString();
1626 BEAST_EXPECT(!sig.empty());
1627 auto const pkHex =
strHex(pk.slice());
1630 auto& app = env.
app();
1636 .loadType = loadType,
1637 .netOps = app.getOPs(),
1638 .ledgerMaster = app.getLedgerMaster(),
1647 params[jss::public_key] = pkHex;
1648 params[jss::channel_id] = chanStr;
1649 params[jss::amount] =
"1000";
1650 params[jss::signature] = sig;
1651 context.
params = std::move(params);
1657 app.getJobQueue().postCoro(
JtClient,
"RPC-Client", [&](
auto const& coro) {
1658 context.
coro = coro;
1663 using namespace std::chrono_literals;
1666 BEAST_EXPECT(result[jss::signature_verified].asBool());
1679 testcase(
"channel_authorize sets kFEE_HEAVY_BURDEN_RPC load type");
1681 using namespace jtx;
1684 Env env{*
this, features};
1685 auto const alice =
Account(
"alice");
1686 auto const bob =
Account(
"bob");
1688 env.
fund(
XRP(10000), alice, bob);
1690 auto const pk = alice.pk();
1691 auto const settleDelay = 3600s;
1694 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1697 auto& app = env.
app();
1703 .loadType = loadType,
1704 .netOps = app.getOPs(),
1705 .ledgerMaster = app.getLedgerMaster(),
1714 params[jss::channel_id] = chanStr;
1715 params[jss::amount] =
"1000";
1716 params[jss::secret] = alice.name();
1717 context.
params = std::move(params);
1723 app.getJobQueue().postCoro(
JtClient,
"RPC-Client", [&](
auto const& coro) {
1724 context.
coro = coro;
1729 using namespace std::chrono_literals;
1733 BEAST_EXPECT(result.
isMember(jss::signature));
1734 BEAST_EXPECT(!result[jss::signature].asString().
empty());
1745 using namespace jtx;
1747 Env env{*
this, features};
1748 auto const alice =
Account(
"alice");
1749 auto const bob =
Account(
"bob");
1750 auto usda = alice[
"USD"];
1751 env.
fund(
XRP(10000), alice, bob);
1752 auto const pk = alice.pk();
1753 auto const settleDelay = 100s;
1755 auto const chan =
channel(alice, bob, env.
seq(alice));
1756 auto jv =
create(alice, bob,
XRP(1000), settleDelay, pk);
1757 auto const pkHex =
strHex(pk.slice());
1758 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1760 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1762 auto badPrefix = pkHex;
1765 jv[
"PublicKey"] = badPrefix;
1768 jv[
"PublicKey"] = pkHex;
1771 auto const authAmt =
XRP(100);
1772 auto const sig =
signClaimAuth(alice.pk(), alice.sk(), chan, authAmt);
1773 jv =
claim(bob, chan, authAmt.value(), authAmt.value(),
Slice(sig), alice.pk());
1774 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1776 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1781 jv[
"PublicKey"] = badPrefix;
1785 jv.removeMember(
"PublicKey");
1789 auto const txn = R
"*(
1792 "channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
1794 "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
1796 "aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
1800 auto const r = env.
rpc(
"json",
"channel_verify", txn);
1801 BEAST_EXPECT(r[
"result"][
"error"] ==
"publicMalformed");
1810 using namespace jtx;
1813 auto const alice =
Account(
"alice");
1814 auto const bob =
Account(
"bob");
1815 auto const settleDelay = 100s;
1816 auto const pk = alice.pk();
1822 return std::find(ownerDir.begin(), ownerDir.end(), chan) != ownerDir.end();
1832 Env env{*
this, features};
1833 env.
fund(
XRP(10000), alice, bob);
1834 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1837 BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle));
1838 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
1839 BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle));
1840 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 1);
1842 env(
claim(bob, chan), Txflags(tfClose));
1844 BEAST_EXPECT(!inOwnerDir(*env.current(), alice, chanSle));
1845 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 0);
1846 BEAST_EXPECT(!inOwnerDir(*env.current(), bob, chanSle));
1847 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 0);
1853 Env env(*
this, features);
1854 env.fund(
XRP(10000), alice, bob);
1856 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1859 BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle));
1860 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
1861 BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle));
1862 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 1);
1866 BEAST_EXPECT(!inOwnerDir(*env.current(), alice, chanSle));
1867 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 0);
1868 BEAST_EXPECT(!inOwnerDir(*env.current(), bob, chanSle));
1869 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 0);
1884 for (
auto minRmSeq = env.seq(toRm) + 257; env.current()->seq() < minRmSeq;
1890 Fee(
drops(env.current()->fees().increment)),
1897 auto const alice =
Account(
"alice");
1898 auto const bob =
Account(
"bob");
1899 auto const carol =
Account(
"carol");
1902 Env env{*
this, features};
1903 env.fund(
XRP(10000), alice, bob, carol);
1907 auto const pk = alice.pk();
1908 auto const settleDelay = 100s;
1909 auto const chan =
channel(alice, bob, env.seq(alice));
1910 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1918 auto const feeDrops = env.current()->fees().base;
1921 BEAST_EXPECT(chanBal ==
XRP(0));
1922 BEAST_EXPECT(chanAmt ==
XRP(1000));
1924 auto preBob = env.balance(bob);
1925 auto const delta =
XRP(50);
1926 auto reqBal = chanBal + delta;
1927 auto authAmt = reqBal +
XRP(100);
1928 assert(reqBal <= chanAmt);
1930 env(
claim(alice, chan, reqBal, authAmt));
1933 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1934 BEAST_EXPECT(env.balance(bob) == preBob + delta);
1937 auto const preAlice = env.balance(alice);
1938 env(
fund(alice, chan,
XRP(1000)));
1940 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
1942 chanAmt = chanAmt +
XRP(1000);
1946 env(
claim(alice, chan), Txflags(tfClose));
1950 auto const closeTime = env.current()->header().parentCloseTime;
1951 auto const minExpiration = closeTime + settleDelay;
1952 env.close(minExpiration);
1963 using namespace jtx;
1965 Env env{*
this, features};
1966 auto const alice =
Account(
"alice");
1967 auto const bob =
Account(
"bob");
1968 auto usda = alice[
"USD"];
1969 env.fund(
XRP(10000), alice, bob);
1974 std::uint32_t aliceTicketSeq{env.seq(alice) + 1};
1976 std::uint32_t
const aliceSeq{env.seq(alice)};
1978 std::uint32_t bobTicketSeq{env.seq(bob) + 1};
1980 std::uint32_t
const bobSeq{env.seq(bob)};
1982 auto const pk = alice.pk();
1983 auto const settleDelay = 100s;
1984 auto const chan =
channel(alice, bob, aliceTicketSeq);
1986 env(
create(alice, bob,
XRP(1000), settleDelay, pk), ticket::Use(aliceTicketSeq++));
1988 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1989 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1995 auto const preAlice = env.balance(alice);
1996 env(
fund(alice, chan,
XRP(1000)), ticket::Use(aliceTicketSeq++));
1998 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1999 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2001 auto const feeDrops = env.current()->fees().base;
2002 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
2007 BEAST_EXPECT(chanBal ==
XRP(0));
2008 BEAST_EXPECT(chanAmt ==
XRP(2000));
2012 auto const preBob = env.balance(bob);
2013 auto const delta =
XRP(500);
2014 auto const reqBal = chanBal + delta;
2015 auto const authAmt = reqBal +
XRP(100);
2016 assert(reqBal <= chanAmt);
2017 env(
claim(alice, chan, reqBal, authAmt), ticket::Use(aliceTicketSeq++));
2019 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2020 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2023 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2024 BEAST_EXPECT(env.balance(bob) == preBob + delta);
2029 auto preBob = env.balance(bob);
2030 auto const delta =
XRP(500);
2031 auto const reqBal = chanBal + delta;
2032 auto const authAmt = reqBal +
XRP(100);
2033 assert(reqBal <= chanAmt);
2034 auto const sig =
signClaimAuth(alice.pk(), alice.sk(), chan, authAmt);
2035 env(
claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk()),
2036 ticket::Use(bobTicketSeq++));
2038 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2039 BEAST_EXPECT(env.seq(bob) == bobSeq);
2042 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2043 auto const feeDrops = env.current()->fees().base;
2044 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
2048 preBob = env.balance(bob);
2050 env(
claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk()),
2051 ticket::Use(bobTicketSeq++),
2054 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2055 BEAST_EXPECT(env.seq(bob) == bobSeq);
2058 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2059 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2063 auto const preBob = env.balance(bob);
2064 STAmount
const authAmt = chanBal +
XRP(500);
2065 STAmount
const reqAmt = authAmt +
drops(1);
2066 assert(reqAmt <= chanAmt);
2069 auto const sig =
signClaimAuth(alice.pk(), alice.sk(), chan, authAmt);
2070 env(
claim(bob, chan, reqAmt, authAmt, Slice(sig), alice.pk()),
2071 ticket::Use(bobTicketSeq),
2074 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2075 BEAST_EXPECT(env.seq(bob) == bobSeq);
2078 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2079 BEAST_EXPECT(env.balance(bob) == preBob);
2085 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2086 BEAST_EXPECT(env.seq(bob) == bobSeq);
2089 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2093 auto const preAlice = env.balance(alice);
2094 auto const preBob = env.balance(bob);
2095 env(
claim(bob, chan), Txflags(tfClose), ticket::Use(bobTicketSeq++));
2097 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2098 BEAST_EXPECT(env.seq(bob) == bobSeq);
2101 auto const feeDrops = env.current()->fees().base;
2102 auto const delta = chanAmt - chanBal;
2104 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
2105 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2107 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2108 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2109 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2110 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 & const_ref
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.
STAmount channelBalance(ReadView const &view, uint256 const &chan)
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)
uint256 channel(AccountID const &account, AccountID const &dst, std::uint32_t seqProxyValue)
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)
bool channelExists(ReadView const &view, uint256 const &chan)
json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
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()
void sign(json::Value &jv, Account const &account, json::Value &sigObject)
Sign automatically into a specific Json field of the jv object.
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 forAllApiVersions(Fn const &fn, Args &&... args)
std::string strHex(FwdIt begin, FwdIt end)
void serializePayChanAuthorization(Serializer &msg, uint256 const &key, XRPAmount const &amt)
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)
static std::optional< std::int64_t > channelExpiration(ReadView const &view, uint256 const &chan)
void testWithFeats(FeatureBitset features)
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)
static std::pair< uint256, SLE::const_pointer > channelKeyAndSle(ReadView const &view, jtx::Account const &account, jtx::Account const &dst)
void testAccountChannelAuthorize(FeatureBitset features)
void testAccountChannelsRPC(FeatureBitset features)
void testExpiration(FeatureBitset features)
static Buffer signClaimAuth(PublicKey const &pk, SecretKey const &sk, uint256 const &channel, STAmount const &authAmt)
void testDisallowIncoming(FeatureBitset features)
void testChannelVerifyLoadType(FeatureBitset features)
void testAuthVerifyRPC(FeatureBitset features)
void testAccountDelete(FeatureBitset features)
static STAmount channelAmount(ReadView const &view, uint256 const &chan)
void run() override
Runs the suite.
void testDisallowXRP(FeatureBitset features)
void testAccountChannelsRPCSenderOnly(FeatureBitset features)
void testMalformedPK(FeatureBitset features)
void testAccountChannelsRPCMarkers(FeatureBitset features)