22#include <xrpld/rpc/detail/RPCHelpers.h>
24#include <xrpl/basics/chrono.h>
25#include <xrpl/ledger/Dir.h>
26#include <xrpl/protocol/Feature.h>
27#include <xrpl/protocol/Indexes.h>
28#include <xrpl/protocol/PayChan.h>
29#include <xrpl/protocol/TxFlags.h>
30#include <xrpl/protocol/jss.h>
34using namespace jtx::paychan;
50 return {k.key, view.
read(k)};
68 auto const slep = view.
read({ltPAYCHAN, chan});
71 return (*slep)[sfAmount];
77 auto const slep = view.
read({ltPAYCHAN, chan});
80 if (
auto const r = (*slep)[~sfExpiration])
91 Env env{*
this, features};
92 auto const alice =
Account(
"alice");
93 auto const bob =
Account(
"bob");
94 auto USDA = alice[
"USD"];
95 env.fund(
XRP(10000), alice, bob);
96 auto const pk = alice.pk();
97 auto const settleDelay = 100s;
98 auto const chan =
channel(alice, bob, env.seq(alice));
99 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
104 auto const preAlice = env.balance(alice);
105 env(
fund(alice, chan,
XRP(1000)));
106 auto const feeDrops = env.current()->fees().base;
107 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
112 BEAST_EXPECT(chanBal ==
XRP(0));
113 BEAST_EXPECT(chanAmt ==
XRP(2000));
117 env(
create(alice, bob, USDA(1000), settleDelay, pk),
120 env(
create(alice, bob,
XRP(-1000), settleDelay, pk),
126 env(
create(alice,
"noAccount",
XRP(1000), settleDelay, pk),
129 env(
create(alice, alice,
XRP(1000), settleDelay, pk),
135 channel(alice,
"noAccount", env.seq(alice) - 1),
143 auto const iou = USDA(100).value();
144 auto const negXRP =
XRP(-100).value();
145 auto const posXRP =
XRP(100).value();
155 auto const delta =
XRP(500);
156 auto const reqBal = chanBal + delta;
157 auto const authAmt = reqBal +
XRP(-100);
158 assert(reqBal <= chanAmt);
163 auto const preBob = env.balance(bob);
164 auto const delta =
XRP(500);
165 auto const reqBal = chanBal + delta;
166 auto const authAmt = reqBal +
XRP(100);
167 assert(reqBal <= chanAmt);
168 env(
claim(alice, chan, reqBal, authAmt));
170 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
171 BEAST_EXPECT(env.balance(bob) == preBob + delta);
176 auto preBob = env.balance(bob);
177 auto const delta =
XRP(500);
178 auto const reqBal = chanBal + delta;
179 auto const authAmt = reqBal +
XRP(100);
180 assert(reqBal <= chanAmt);
183 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
185 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
186 auto const feeDrops = env.current()->fees().base;
187 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
191 preBob = env.balance(bob);
192 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
195 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
196 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
200 auto const preBob = env.balance(bob);
203 assert(reqAmt <= chanAmt);
206 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
209 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
210 BEAST_EXPECT(env.balance(bob) == preBob);
216 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
230 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
244 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
248 auto const preAlice = env.balance(alice);
249 auto const preBob = env.balance(bob);
252 auto const feeDrops = env.current()->fees().base;
253 auto const delta = chanAmt - chanBal;
254 assert(delta > beast::zero);
255 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
256 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
270 env.fund(
XRP(10000), alice);
273 auto const sle = env.le(alice);
280 auto const alice =
Account(
"alice");
281 auto const bob =
Account(
"bob");
282 auto const cho =
Account(
"cho");
283 env.fund(
XRP(10000), alice, bob, cho);
284 auto const pk = alice.pk();
285 auto const settleDelay = 100s;
293 auto const chan =
channel(alice, bob, env.seq(alice));
294 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
305 auto const chan =
channel(bob, alice, env.seq(bob));
306 env(
create(bob, alice,
XRP(1000), settleDelay, pk),
317 auto const chan =
channel(alice, bob, env.seq(alice));
318 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
325 auto const chan =
channel(cho, alice, env.seq(cho));
326 env(
create(cho, alice,
XRP(1000), settleDelay, pk),
337 auto const chan =
channel(cho, alice, env.seq(cho));
338 env(
create(cho, alice,
XRP(1000), settleDelay, pk),
350 auto const alice =
Account(
"alice");
351 auto const bob =
Account(
"bob");
352 auto const carol =
Account(
"carol");
355 Env env{*
this, features};
356 env.fund(
XRP(10000), alice, bob);
357 auto const pk = alice.pk();
358 auto const settleDelay = 100s;
360 env.current()->info().parentCloseTime + 3600s;
361 auto const channelFunds =
XRP(1000);
362 auto const chan =
channel(alice, bob, env.seq(alice));
363 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
365 env.close(cancelAfter);
370 auto preAlice = env.balance(alice);
371 auto preBob = env.balance(bob);
372 auto const delta =
XRP(500);
373 auto const reqBal = chanBal + delta;
374 auto const authAmt = reqBal +
XRP(100);
375 assert(reqBal <= chanAmt);
378 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
379 auto const feeDrops = env.current()->fees().base;
381 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
382 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
387 Env env{*
this, features};
388 env.fund(
XRP(10000), alice, bob, carol);
389 auto const pk = alice.pk();
390 auto const settleDelay = 100s;
392 env.current()->info().parentCloseTime + 3600s;
393 auto const channelFunds =
XRP(1000);
394 auto const chan =
channel(alice, bob, env.seq(alice));
395 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
400 env.close(cancelAfter);
402 auto const preAlice = env.balance(alice);
405 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
410 for (
bool const withFixPayChan : {
true,
false})
412 auto const amend = withFixPayChan
414 : features - fixPayChanCancelAfter;
415 Env env{*
this, amend};
416 env.
fund(
XRP(10000), alice, bob);
419 auto const pk = alice.pk();
420 auto const settleDelay = 100s;
421 auto const channelFunds =
XRP(1000);
423 env.current()->info().parentCloseTime - 1s;
424 auto const txResult =
427 alice, bob, channelFunds, settleDelay, pk, cancelAfter),
434 for (
bool const withFixPayChan : {
true,
false})
436 auto const amend = withFixPayChan
438 : features - fixPayChanCancelAfter;
439 Env env{*
this, amend};
440 env.
fund(
XRP(10000), alice, bob);
443 auto const pk = alice.pk();
444 auto const settleDelay = 100s;
445 auto const channelFunds =
XRP(1000);
447 env.current()->info().parentCloseTime;
449 alice, bob, channelFunds, settleDelay, pk, cancelAfter),
461 Env env{*
this, features};
462 auto const alice =
Account(
"alice");
463 auto const bob =
Account(
"bob");
464 auto const carol =
Account(
"carol");
465 env.fund(
XRP(10000), alice, bob, carol);
466 auto const pk = alice.pk();
467 auto const settleDelay = 3600s;
468 auto const closeTime = env.current()->info().parentCloseTime;
469 auto const minExpiration = closeTime + settleDelay;
471 auto const channelFunds =
XRP(1000);
472 auto const chan =
channel(alice, bob, env.seq(alice));
473 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
478 auto counts = [](
auto const& t) {
479 return t.time_since_epoch().count();
488 counts(minExpiration) + 100);
494 counts(minExpiration) + 50);
501 counts(minExpiration) + 50);
505 counts(minExpiration) + 50);
514 env.close(minExpiration);
527 Env env{*
this, features};
528 auto const alice =
Account(
"alice");
529 auto const bob =
Account(
"bob");
530 env.fund(
XRP(10000), alice, bob);
531 auto const pk = alice.pk();
532 auto const settleDelay = 3600s;
534 env.current()->info().parentCloseTime + settleDelay;
535 auto const channelFunds =
XRP(1000);
536 auto const chan =
channel(alice, bob, env.seq(alice));
537 env(
create(alice, bob, channelFunds, settleDelay, pk));
542 env.close(settleTimepoint - settleDelay / 2);
547 auto preBob = env.balance(bob);
548 auto const delta =
XRP(500);
549 auto const reqBal = chanBal + delta;
550 auto const authAmt = reqBal +
XRP(100);
551 assert(reqBal <= chanAmt);
554 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
556 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
557 auto const feeDrops = env.current()->fees().base;
558 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
560 env.close(settleTimepoint);
565 auto const preAlice = env.balance(alice);
566 auto preBob = env.balance(bob);
567 auto const delta =
XRP(500);
568 auto const reqBal = chanBal + delta;
569 auto const authAmt = reqBal +
XRP(100);
570 assert(reqBal <= chanAmt);
573 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
575 auto const feeDrops = env.current()->fees().base;
576 BEAST_EXPECT(env.balance(alice) == preAlice + chanAmt - chanBal);
577 BEAST_EXPECT(env.balance(bob) == preBob - 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));
602 auto const preBob = env.balance(bob);
603 env(
claim(alice, chan, channelFunds.value(), channelFunds.value()));
604 BEAST_EXPECT(
channelBalance(*env.current(), chan) == channelFunds);
605 BEAST_EXPECT(env.balance(bob) == preBob + channelFunds);
607 auto const preAlice = env.balance(alice);
611 auto const feeDrops = env.current()->fees().base;
612 BEAST_EXPECT(env.balance(alice) == preAlice - feeDrops);
622 Env env{*
this, features};
623 auto const alice =
Account(
"alice");
624 auto const bob =
Account(
"bob");
625 env.fund(
XRP(10000), alice, bob);
626 auto const pk = alice.pk();
627 auto const settleDelay = 3600s;
628 auto const channelFunds =
XRP(1000);
629 auto const chan =
channel(alice, bob, env.seq(alice));
630 env(
create(alice, bob, channelFunds, settleDelay, pk));
638 auto const preBob = env.balance(bob);
640 auto const delta =
XRP(500);
641 auto const reqBal = chanBal + delta;
642 assert(reqBal <= chanAmt);
647 auto const feeDrops = env.current()->fees().base;
648 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
655 auto const preBob = env.balance(bob);
657 auto const delta =
XRP(500);
658 auto const reqBal = chanBal + delta;
659 assert(reqBal <= chanAmt);
664 auto const feeDrops = env.current()->fees().base;
665 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
678 auto const alice =
Account(
"alice");
679 auto const bob =
Account(
"bob");
682 Env env(*
this, features - featureDepositAuth);
683 env.
fund(
XRP(10000), alice, bob);
685 auto const chan =
channel(alice, bob, env.
seq(alice));
686 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()),
693 Env env{*
this, features};
694 env.fund(
XRP(10000), alice, bob);
696 auto const chan =
channel(alice, bob, env.seq(alice));
697 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
704 Env env(*
this, features - featureDepositAuth);
705 env.
fund(
XRP(10000), alice, bob);
706 auto const chan =
channel(alice, bob, env.
seq(alice));
707 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
711 auto const reqBal =
XRP(500).value();
718 Env env{*
this, features};
719 env.fund(
XRP(10000), alice, bob);
720 auto const chan =
channel(alice, bob, env.seq(alice));
721 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
725 auto const reqBal =
XRP(500).value();
726 env(
claim(alice, chan, reqBal, reqBal));
738 Env env{*
this, features};
739 auto const alice =
Account(
"alice");
740 auto const bob =
Account(
"bob");
741 env.fund(
XRP(10000), alice, bob);
743 auto const pk = alice.pk();
744 auto const settleDelay = 3600s;
745 auto const channelFunds =
XRP(1000);
747 auto const chan =
channel(alice, bob, env.seq(alice));
748 env(
create(alice, bob, channelFunds, settleDelay, pk),
753 auto const chan =
channel(alice, bob, env.seq(alice));
755 alice, bob, channelFunds, settleDelay, pk,
std::nullopt, 1));
767 auto const alice =
Account(
"alice");
768 auto const bob =
Account(
"bob");
769 auto const carol =
Account(
"carol");
770 auto USDA = alice[
"USD"];
772 Env env{*
this, features};
773 env.fund(
XRP(10000), alice, bob, carol);
778 auto const pk = alice.pk();
779 auto const settleDelay = 100s;
780 auto const chan =
channel(alice, bob, env.seq(alice));
781 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
789 env(
fund(alice, chan,
XRP(1000)));
793 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
798 auto const baseFee = env.current()->fees().base;
799 auto const preBob = env.balance(bob);
801 auto const delta =
XRP(500).value();
809 BEAST_EXPECT(env.balance(bob) == preBob);
821 BEAST_EXPECT(env.balance(bob) == preBob + delta - baseFee);
825 auto const delta =
XRP(600).value();
857 env.balance(bob) == preBob + delta - (3 * baseFee));
862 auto const delta =
XRP(800).value();
876 env(
claim(alice, chan, delta, delta));
879 env.balance(bob) == preBob +
XRP(800) - (5 * baseFee));
887 testcase(
"Deposit Authorization with Credentials");
891 char const credType[] =
"abcde";
896 Account const dillon(
"dillon");
901 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
903 auto const pk = alice.
pk();
904 auto const settleDelay = 100s;
905 auto const chan =
channel(alice, bob, env.seq(alice));
906 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
910 env(
fund(alice, chan,
XRP(1000)));
914 "D007AE4B6E1274B4AF872588267B810C2F82716726351D1C7D38D3E5499FC6"
917 auto const delta =
XRP(500).value();
923 .parentCloseTime.time_since_epoch()
926 jv[sfExpiration.jsonName] = t;
933 std::string const credIdx = jv[jss::result][jss::index].asString();
940 env(
claim(alice, chan, delta, delta),
949 env(
claim(alice, chan, delta, delta),
959 env(
claim(dillon, chan, delta, delta),
967 env(
claim(alice, chan, delta, delta),
972 env(
claim(alice, chan, delta, delta),
980 for (
int i = 0; i < 10; ++i)
983 env(
claim(alice, chan, delta, delta),
998 jv[jss::result][jss::index].asString();
1001 env(
claim(alice, chan, delta, delta),
1008 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
1010 auto const pk = alice.
pk();
1011 auto const settleDelay = 100s;
1012 auto const chan =
channel(alice, bob, env.seq(alice));
1013 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1017 env(
fund(alice, chan,
XRP(1000)));
1020 auto const delta =
XRP(500).value();
1031 std::string const credIdx = jv[jss::result][jss::index].asString();
1041 env.
fund(
XRP(5000),
"alice",
"bob");
1044 auto const pk = alice.
pk();
1045 auto const settleDelay = 100s;
1046 auto const chan =
channel(alice, bob, env.
seq(alice));
1047 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1050 env(
fund(alice, chan,
XRP(1000)));
1053 "48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6EA288B"
1062 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
1072 testcase(
"Multiple channels to the same account");
1073 using namespace jtx;
1075 Env env{*
this, features};
1076 auto const alice =
Account(
"alice");
1077 auto const bob =
Account(
"bob");
1078 env.fund(
XRP(10000), alice, bob);
1079 auto const pk = alice.pk();
1080 auto const settleDelay = 3600s;
1081 auto const channelFunds =
XRP(1000);
1082 auto const chan1 =
channel(alice, bob, env.seq(alice));
1083 env(
create(alice, bob, channelFunds, settleDelay, pk));
1085 auto const chan2 =
channel(alice, bob, env.seq(alice));
1086 env(
create(alice, bob, channelFunds, settleDelay, pk));
1088 BEAST_EXPECT(chan1 != chan2);
1096 using namespace jtx;
1098 Env env{*
this, features};
1099 auto const alice =
Account(
"alice");
1100 auto const bob =
Account(
"bob");
1102 env.fund(
XRP(10000), alice, bob, charlie);
1103 auto const pk = alice.pk();
1104 auto const settleDelay = 3600s;
1105 auto const channelFunds =
XRP(1000);
1107 env(
create(alice, bob, channelFunds, settleDelay, pk));
1111 auto testInvalidAccountParam = [&](
auto const& param) {
1113 params[jss::account] = param;
1115 "json",
"account_channels",
to_string(params))[jss::result];
1116 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1118 jrr[jss::error_message] ==
"Invalid field 'account'.");
1121 testInvalidAccountParam(1);
1122 testInvalidAccountParam(1.1);
1123 testInvalidAccountParam(
true);
1130 env.rpc(
"account_channels", alice.human(), bob.human());
1131 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1133 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1134 BEAST_EXPECT(r[jss::result][jss::validated]);
1137 auto const r = env.rpc(
"account_channels", alice.human());
1138 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1140 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1141 BEAST_EXPECT(r[jss::result][jss::validated]);
1145 env.rpc(
"account_channels", bob.human(), alice.human());
1146 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1147 BEAST_EXPECT(r[jss::result][jss::validated]);
1150 env(
create(alice, bob, channelFunds, settleDelay, pk));
1154 env.rpc(
"account_channels", alice.human(), bob.human());
1155 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1156 BEAST_EXPECT(r[jss::result][jss::validated]);
1157 BEAST_EXPECT(chan1Str != chan2Str);
1158 for (
auto const& c : {chan1Str, chan2Str})
1160 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1161 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1168 testcase(
"Account channels RPC markers");
1170 using namespace test::jtx;
1173 auto const alice =
Account(
"alice");
1178 for (
int i = 0; i < n; ++i)
1185 Env env{*
this, features};
1186 env.fund(
XRP(10000), alice);
1187 for (
auto const& a : bobs)
1189 env.fund(
XRP(10000), a);
1195 auto const settleDelay = 3600s;
1196 auto const channelFunds =
XRP(1);
1197 for (
auto const& b : bobs)
1199 env(
create(alice, b, channelFunds, settleDelay, alice.pk()));
1210 jvc[jss::account] = src.human();
1212 jvc[jss::destination_account] = dst->human();
1214 jvc[jss::limit] = *limit;
1216 jvc[jss::marker] = marker;
1219 "json",
"account_channels",
to_string(jvc))[jss::result];
1224 auto const r = testLimit(env, alice);
1225 BEAST_EXPECT(r.isMember(jss::channels));
1226 BEAST_EXPECT(r[jss::channels].size() == bobs.size());
1231 for (
auto const& a : bobs)
1236 for (
int limit = 1; limit < bobs.size() + 1; ++limit)
1238 auto leftToFind = bobsB58;
1239 auto const numFull = bobs.
size() / limit;
1240 auto const numNonFull = bobs.size() % limit ? 1 : 0;
1244 auto const testIt = [&](
bool expectMarker,
int expectedBatchSize) {
1245 auto const r = testLimit(env, alice, limit, marker);
1246 BEAST_EXPECT(!expectMarker || r.isMember(jss::marker));
1247 if (r.isMember(jss::marker))
1248 marker = r[jss::marker];
1249 BEAST_EXPECT(r[jss::channels].size() == expectedBatchSize);
1250 auto const c = r[jss::channels];
1251 auto const s = r[jss::channels].size();
1252 for (
int j = 0; j < s; ++j)
1255 c[j][jss::destination_account].asString();
1256 BEAST_EXPECT(leftToFind.count(dstAcc));
1257 leftToFind.erase(dstAcc);
1261 for (
int i = 0; i < numFull; ++i)
1263 bool const expectMarker = (numNonFull != 0 || i < numFull - 1);
1264 testIt(expectMarker, limit);
1269 testIt(
false, bobs.size() % limit);
1271 BEAST_EXPECT(leftToFind.empty());
1276 auto const r = testLimit(env, alice, 0);
1277 BEAST_EXPECT(r.isMember(jss::error_message));
1286 testcase(
"Account channels RPC owner only");
1288 using namespace test::jtx;
1291 auto const alice =
Account(
"alice");
1292 auto const bob =
Account(
"bob");
1293 Env env{*
this, features};
1294 env.fund(
XRP(10000), alice, bob);
1299 auto const settleDelay = 3600s;
1300 auto const channelFunds =
XRP(1000);
1301 env(
create(alice, bob, channelFunds, settleDelay, alice.pk()));
1302 env(
create(bob, alice, channelFunds, settleDelay, bob.pk()));
1304 auto const r = [&] {
1306 jvc[jss::account] = alice.human();
1309 "json",
"account_channels",
to_string(jvc))[jss::result];
1311 BEAST_EXPECT(r.isMember(jss::channels));
1312 BEAST_EXPECT(r[jss::channels].size() == 1);
1314 r[jss::channels][0u][jss::destination_account].asString() ==
1321 using namespace jtx;
1324 Env env{*
this, features};
1325 auto const alice =
Account(
"alice");
1326 auto const bob =
Account(
"bob");
1328 env.fund(
XRP(10000), alice, bob, charlie);
1329 auto const pk = alice.pk();
1330 auto const settleDelay = 3600s;
1331 auto const channelFunds =
XRP(1000);
1333 env(
create(alice, bob, channelFunds, settleDelay, pk));
1337 args[jss::channel_id] = chan1Str;
1338 args[jss::key_type] =
"ed255191";
1339 args[jss::seed] =
"snHq1rzQoN2qiUkC3XF5RyxBzUtN";
1340 args[jss::amount] = 51110000;
1346 args[jss::api_version] = apiVersion;
1347 auto const rs = env.rpc(
1349 "channel_authorize",
1350 args.toStyledString())[jss::result];
1351 auto const error = apiVersion < 2u ?
"invalidParams" :
"badKeyType";
1352 BEAST_EXPECT(rs[jss::error] == error);
1359 testcase(
"PayChan Auth/Verify RPC");
1360 using namespace jtx;
1362 Env env{*
this, features};
1363 auto const alice =
Account(
"alice");
1364 auto const bob =
Account(
"bob");
1366 env.fund(
XRP(10000), alice, bob, charlie);
1367 auto const pk = alice.pk();
1368 auto const settleDelay = 3600s;
1369 auto const channelFunds =
XRP(1000);
1371 env(
create(alice, bob, channelFunds, settleDelay, pk));
1376 env.rpc(
"account_channels", alice.human(), bob.human());
1377 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1379 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1380 BEAST_EXPECT(r[jss::result][jss::validated]);
1382 r[jss::result][jss::channels][0u][jss::public_key].asString();
1385 auto const r = env.rpc(
"account_channels", alice.human());
1386 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1388 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1389 BEAST_EXPECT(r[jss::result][jss::validated]);
1391 r[jss::result][jss::channels][0u][jss::public_key].asString();
1395 env.rpc(
"account_channels", bob.human(), alice.human());
1396 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1397 BEAST_EXPECT(r[jss::result][jss::validated]);
1400 env(
create(alice, bob, channelFunds, settleDelay, pk));
1404 env.rpc(
"account_channels", alice.human(), bob.human());
1405 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1406 BEAST_EXPECT(r[jss::result][jss::validated]);
1407 BEAST_EXPECT(chan1Str != chan2Str);
1408 for (
auto const& c : {chan1Str, chan2Str})
1410 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1411 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1419 s +=
"0123456789ABCDEF"[((
slice[i] & 0xf0) >> 4)];
1420 s +=
"0123456789ABCDEF"[((
slice[i] & 0x0f) >> 0)];
1428 env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000");
1429 auto const sig = rs[jss::result][jss::signature].asString();
1430 BEAST_EXPECT(!
sig.empty());
1432 auto const rv = env.rpc(
1433 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1434 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1441 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1442 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1448 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000x",
sig);
1449 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1450 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 ",
sig);
1451 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1452 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x1000",
sig);
1453 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1454 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x",
sig);
1455 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1456 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" ",
sig);
1457 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1459 "channel_verify", pkAsHex, chan1Str,
"1000 1000",
sig);
1460 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1461 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1,000",
sig);
1462 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1463 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" 1000",
sig);
1464 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1465 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"",
sig);
1466 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1471 auto chan1StrBad = chan1Str;
1472 chan1StrBad.pop_back();
1474 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1475 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1476 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1477 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1479 chan1StrBad = chan1Str;
1480 chan1StrBad.push_back(
'0');
1482 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1483 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1484 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1485 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1487 chan1StrBad = chan1Str;
1488 chan1StrBad.back() =
'x';
1490 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1491 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1492 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1493 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1497 auto illFormedPk = chan1PkStr.
substr(0, chan1PkStr.
size() - 1);
1498 auto const rv = env.rpc(
1499 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1501 !rv[jss::result][jss::signature_verified].asBool());
1506 auto illFormedPk = pkAsHex.substr(0, chan1PkStr.
size() - 1);
1507 auto const rv = env.rpc(
1508 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1510 !rv[jss::result][jss::signature_verified].asBool());
1516 env.rpc(
"channel_authorize",
"alice", chan2Str,
"1000");
1517 auto const sig = rs[jss::result][jss::signature].asString();
1518 BEAST_EXPECT(!
sig.empty());
1520 auto const rv = env.rpc(
1521 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1523 !rv[jss::result][jss::signature_verified].asBool());
1529 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1531 !rv[jss::result][jss::signature_verified].asBool());
1539 charlie, alice, channelFunds, settleDelay, charlie.pk()));
1545 env.rpc(
"account_channels", charlie.human(), alice.human());
1546 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1548 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1549 BEAST_EXPECT(r[jss::result][jss::validated]);
1550 cpk = r[jss::result][jss::channels][0u][jss::public_key]
1556 env.rpc(
"channel_authorize",
"charlie", chan,
"1000");
1557 auto const sig = rs[jss::result][jss::signature].asString();
1558 BEAST_EXPECT(!
sig.empty());
1561 env.rpc(
"channel_verify", cpk, chan,
"1000",
sig);
1563 !rv[jss::result][jss::signature_verified].asBool());
1568 env.rpc(
"channel_authorize",
"charlie",
"nyx", chan,
"1000");
1569 BEAST_EXPECT(rs1[jss::error] ==
"badKeyType");
1573 auto const rs2 = env.rpc(
1574 "channel_authorize",
"charlie",
"secp256k1", chan,
"1000");
1575 auto const sig2 = rs2[jss::result][jss::signature].asString();
1576 BEAST_EXPECT(!sig2.empty());
1579 env.rpc(
"channel_verify", cpk, chan,
"1000", sig2);
1581 !rv[jss::result][jss::signature_verified].asBool());
1585 auto const rs3 = env.rpc(
1586 "channel_authorize",
"charlie",
"ed25519", chan,
"1000");
1587 auto const sig3 = rs3[jss::result][jss::signature].asString();
1588 BEAST_EXPECT(!sig3.empty());
1591 env.rpc(
"channel_verify", cpk, chan,
"1000", sig3);
1592 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1598 auto rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000x");
1599 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1600 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x1000");
1601 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1602 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x");
1603 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1607 args[jss::amount] =
"2000";
1608 args[jss::key_type] =
"secp256k1";
1609 args[jss::passphrase] =
"passphrase_can_be_anything";
1612 "channel_authorize",
1613 args.toStyledString())[jss::result];
1614 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1619 args[jss::channel_id] = chan1Str;
1620 args[jss::key_type] =
"secp256k1";
1621 args[jss::passphrase] =
"passphrase_can_be_anything";
1624 "channel_authorize",
1625 args.toStyledString())[jss::result];
1626 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1631 args[jss::amount] =
"2000";
1632 args[jss::channel_id] = chan1Str;
1633 args[jss::passphrase] =
"passphrase_can_be_anything";
1636 "channel_authorize",
1637 args.toStyledString())[jss::result];
1638 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1643 args[jss::amount] =
"2000";
1644 args[jss::channel_id] = chan1Str;
1645 args[jss::key_type] =
"secp256k1";
1646 args[jss::passphrase] =
"passphrase_can_be_anything";
1647 args[jss::seed] =
"seed can be anything";
1650 "channel_authorize",
1651 args.toStyledString())[jss::result];
1652 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1657 args[jss::amount] =
"2000";
1658 args[jss::channel_id] = chan1Str +
"1";
1659 args[jss::key_type] =
"secp256k1";
1660 args[jss::passphrase] =
"passphrase_can_be_anything";
1663 "channel_authorize",
1664 args.toStyledString())[jss::result];
1665 BEAST_EXPECT(rs[jss::error] ==
"channelMalformed");
1670 args[jss::amount] = 2000;
1671 args[jss::channel_id] = chan1Str;
1672 args[jss::key_type] =
"secp256k1";
1673 args[jss::passphrase] =
"passphrase_can_be_anything";
1676 "channel_authorize",
1677 args.toStyledString())[jss::result];
1678 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1683 args[jss::amount] =
"TwoThousand";
1684 args[jss::channel_id] = chan1Str;
1685 args[jss::key_type] =
"secp256k1";
1686 args[jss::passphrase] =
"passphrase_can_be_anything";
1689 "channel_authorize",
1690 args.toStyledString())[jss::result];
1691 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1700 using namespace jtx;
1702 Env env{*
this, features};
1703 auto const alice =
Account(
"alice");
1704 auto const bob =
Account(
"bob");
1705 auto const carol =
Account(
"carol");
1706 auto const dan =
Account(
"dan");
1707 env.fund(
XRP(10000), alice, bob, carol, dan);
1708 auto const pk = alice.pk();
1709 auto const settleDelay = 3600s;
1710 auto const channelFunds =
XRP(1000);
1716 env(
create(alice, bob, channelFunds, settleDelay, pk));
1718 env.rpc(
"account_channels", alice.human(), bob.human());
1719 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1721 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1722 BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember(
1723 jss::destination_tag));
1737 env.rpc(
"account_channels", alice.human(), carol.human());
1738 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1740 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1742 r[jss::result][jss::channels][0u][jss::destination_tag] ==
1751 using namespace jtx;
1753 Env env{*
this, features};
1754 auto const alice =
Account(
"alice");
1755 auto const bob =
Account(
"bob");
1756 auto USDA = alice[
"USD"];
1757 env.fund(
XRP(10000), alice, bob);
1758 auto const pk = alice.pk();
1759 auto const settleDelay = 100s;
1761 auto const chan =
channel(alice, bob, env.seq(alice));
1762 auto jv =
create(alice, bob,
XRP(1000), settleDelay, pk);
1763 auto const pkHex =
strHex(pk.slice());
1764 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1766 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1768 auto badPrefix = pkHex;
1771 jv[
"PublicKey"] = badPrefix;
1774 jv[
"PublicKey"] = pkHex;
1777 auto const authAmt =
XRP(100);
1786 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1788 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1793 jv[
"PublicKey"] = badPrefix;
1797 jv.removeMember(
"PublicKey");
1801 auto const txn = R
"*(
1804 "channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
1806 "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
1808 "aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
1812 auto const r = env.rpc(
"json",
"channel_verify", txn);
1813 BEAST_EXPECT(r[
"result"][
"error"] ==
"publicMalformed");
1822 using namespace jtx;
1825 auto const alice =
Account(
"alice");
1826 auto const bob =
Account(
"bob");
1827 auto const settleDelay = 100s;
1828 auto const pk = alice.pk();
1830 auto inOwnerDir = [](
ReadView const& view,
1834 return std::find(ownerDir.begin(), ownerDir.end(), chan) !=
1838 auto ownerDirCount = [](
ReadView const& view,
1847 Env env(*
this, features - fixPayChanRecipientOwnerDir);
1848 env.
fund(
XRP(10000), alice, bob);
1849 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1851 auto const [chan, chanSle] =
1853 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1854 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1855 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1856 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1857 if (features[fixIncludeKeyletFields])
1859 BEAST_EXPECT((*chanSle)[sfSequence] == env.
seq(alice) - 1);
1863 BEAST_EXPECT(!chanSle->isFieldPresent(sfSequence));
1868 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1869 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1870 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1871 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1876 Env env{*
this, features};
1877 env.fund(
XRP(10000), alice, bob);
1878 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1880 auto const [chan, chanSle] =
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);
1898 Env env(*
this, features - fixPayChanRecipientOwnerDir);
1899 env.
fund(
XRP(10000), alice, bob);
1901 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1903 auto const [chan, chanSle] =
1905 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1906 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1907 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1908 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1912 env.
current()->rules().enabled(fixPayChanRecipientOwnerDir));
1917 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1918 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1919 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1924 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1925 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1926 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1927 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1935 using namespace test::jtx;
1937 auto rmAccount = [
this](
1944 for (
auto minRmSeq = env.
seq(toRm) + 257;
1945 env.
current()->seq() < minRmSeq;
1959 auto const alice =
Account(
"alice");
1960 auto const bob =
Account(
"bob");
1961 auto const carol =
Account(
"carol");
1963 for (
bool const withOwnerDirFix : {
false,
true})
1965 auto const amd = withOwnerDirFix
1967 : features - fixPayChanRecipientOwnerDir;
1968 Env env{*
this, amd};
1969 env.
fund(
XRP(10000), alice, bob, carol);
1973 auto const pk = alice.pk();
1974 auto const settleDelay = 100s;
1975 auto const chan =
channel(alice, bob, env.
seq(alice));
1976 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1989 auto const feeDrops = env.
current()->fees().base;
1992 BEAST_EXPECT(chanBal ==
XRP(0));
1993 BEAST_EXPECT(chanAmt ==
XRP(1000));
1995 auto preBob = env.
balance(bob);
1996 auto const delta =
XRP(50);
1997 auto reqBal = chanBal + delta;
1998 auto authAmt = reqBal +
XRP(100);
1999 assert(reqBal <= chanAmt);
2002 if (withOwnerDirFix)
2004 env(
claim(alice, chan, reqBal, authAmt));
2008 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
2013 auto const preAlice = env.
balance(alice);
2018 BEAST_EXPECT(env.
balance(bob) == preBob);
2019 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2023 if (withOwnerDirFix)
2025 auto const preAlice = env.
balance(alice);
2026 env(
fund(alice, chan,
XRP(1000)));
2029 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
2032 chanAmt = chanAmt +
XRP(1000);
2036 auto const preAlice = env.
balance(alice);
2039 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2049 auto const closeTime = env.
current()->info().parentCloseTime;
2050 auto const minExpiration = closeTime + settleDelay;
2051 env.
close(minExpiration);
2059 Env env{*
this, features - fixPayChanRecipientOwnerDir};
2060 env.
fund(
XRP(10000), alice, bob, carol);
2064 auto const pk = alice.pk();
2065 auto const settleDelay = 100s;
2066 auto const chan =
channel(alice, bob, env.
seq(alice));
2067 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
2073 rmAccount(env, bob, carol);
2076 auto const feeDrops = env.
current()->fees().base;
2079 BEAST_EXPECT(chanBal ==
XRP(0));
2080 BEAST_EXPECT(chanAmt ==
XRP(1000));
2081 auto preBob = env.
balance(bob);
2082 auto const delta =
XRP(50);
2083 auto reqBal = chanBal + delta;
2084 auto authAmt = reqBal +
XRP(100);
2085 assert(reqBal <= chanAmt);
2089 auto const preAlice = env.
balance(alice);
2094 BEAST_EXPECT(env.
balance(bob) == preBob);
2095 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2100 auto const preAlice = env.
balance(alice);
2103 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2108 env(
pay(alice, bob,
XRP(20)));
2115 reqBal = chanBal + delta;
2116 authAmt = reqBal +
XRP(100);
2117 env(
claim(alice, chan, reqBal, authAmt));
2120 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
2127 reqBal = chanBal + delta;
2128 authAmt = reqBal +
XRP(100);
2131 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
2134 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
2140 auto const preAlice = env.
balance(alice);
2141 env(
fund(alice, chan,
XRP(1000)));
2143 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
2146 chanAmt = chanAmt +
XRP(1000);
2155 auto const closeTime = env.
current()->info().parentCloseTime;
2156 auto const minExpiration = closeTime + settleDelay;
2157 env.
close(minExpiration);
2168 using namespace jtx;
2170 Env env{*
this, features};
2171 auto const alice =
Account(
"alice");
2172 auto const bob =
Account(
"bob");
2173 auto USDA = alice[
"USD"];
2174 env.fund(
XRP(10000), alice, bob);
2187 auto const pk = alice.pk();
2188 auto const settleDelay = 100s;
2189 auto const chan =
channel(alice, bob, aliceTicketSeq);
2191 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
2194 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2195 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2201 auto const preAlice = env.balance(alice);
2204 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2205 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2207 auto const feeDrops = env.current()->fees().base;
2208 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
2213 BEAST_EXPECT(chanBal ==
XRP(0));
2214 BEAST_EXPECT(chanAmt ==
XRP(2000));
2218 auto const preBob = env.balance(bob);
2219 auto const delta =
XRP(500);
2220 auto const reqBal = chanBal + delta;
2221 auto const authAmt = reqBal +
XRP(100);
2222 assert(reqBal <= chanAmt);
2223 env(
claim(alice, chan, reqBal, authAmt),
2226 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2227 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2230 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2231 BEAST_EXPECT(env.balance(bob) == preBob + delta);
2236 auto preBob = env.balance(bob);
2237 auto const delta =
XRP(500);
2238 auto const reqBal = chanBal + delta;
2239 auto const authAmt = reqBal +
XRP(100);
2240 assert(reqBal <= chanAmt);
2243 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
2246 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2247 BEAST_EXPECT(env.seq(bob) == bobSeq);
2250 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2251 auto const feeDrops = env.current()->fees().base;
2252 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
2256 preBob = env.balance(bob);
2258 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
2262 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2263 BEAST_EXPECT(env.seq(bob) == bobSeq);
2266 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2267 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2271 auto const preBob = env.balance(bob);
2274 assert(reqAmt <= chanAmt);
2279 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
2283 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2284 BEAST_EXPECT(env.seq(bob) == bobSeq);
2287 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2288 BEAST_EXPECT(env.balance(bob) == preBob);
2292 env(
fund(bob, chan,
XRP(1000)),
2296 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2297 BEAST_EXPECT(env.seq(bob) == bobSeq);
2300 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2304 auto const preAlice = env.balance(alice);
2305 auto const preBob = env.balance(bob);
2306 env(
claim(bob, chan),
2310 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2311 BEAST_EXPECT(env.seq(bob) == bobSeq);
2314 auto const feeDrops = env.current()->fees().base;
2315 auto const delta = chanAmt - chanBal;
2316 assert(delta > beast::zero);
2317 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
2318 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2320 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2321 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2322 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2323 BEAST_EXPECT(env.seq(bob) == bobSeq);
2356 using namespace test::jtx;
testcase_t testcase
Memberspace for declaring test cases.
Like std::vector<char> but better.
A class that simplifies iterating ledger directory pages.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
Slice slice() const noexcept
An immutable linear range of bytes.
Immutable cryptographic account descriptor.
PublicKey const & pk() const
Return the public key.
A transaction testing environment.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
void enableFeature(uint256 const feature)
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
Set the regular signature on a JTx.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Set a ticket sequence on a JTx.
T emplace_back(T... args)
@ arrayValue
array value (ordered list)
@ objectValue
object value (collection of name/value pairs).
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet payChan(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Json::Value create(jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
Json::Value accept(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 unauth(Account const &account, Account const &unauth)
Remove preauthorization for deposit.
Json::Value auth(Account const &account, Account const &auth)
Preauthorize for deposit.
Json::Value authCredentials(jtx::Account const &account, std::vector< AuthorizeCredentials > const &auth)
bool channelExists(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)
STAmount channelBalance(ReadView const &view, uint256 const &chan)
Json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
void fund(jtx::Env &env, jtx::Account const &gw, std::vector< jtx::Account > const &accounts, std::vector< STAmount > const &amts, Fund how)
FeatureBitset testable_amendments()
Json::Value acctdelete(Account const &account, Account const &dest)
Delete account.
void sign(Json::Value &jv, Account const &account)
Sign automatically.
owner_count< ltTICKET > tickets
Match the number of tickets on the account.
XRP_t const XRP
Converts to XRP Issue or STAmount.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr std::uint32_t asfDepositAuth
constexpr std::uint32_t asfRequireDest
constexpr std::uint32_t tfRenew
static std::string sliceToHex(Slice const &slice)
@ lsfDisallowIncomingPayChan
void serializePayChanAuthorization(Serializer &msg, uint256 const &key, XRPAmount const &amt)
std::string strHex(FwdIt begin, FwdIt end)
void forAllApiVersions(Fn const &fn, Args &&... args)
bool isTesSuccess(TER x) noexcept
std::string to_string(base_uint< Bits, Tag > const &a)
constexpr std::uint32_t asfDisallowIncomingPayChan
constexpr std::uint32_t tfClose
TERSubset< CanCvtToTER > TER
constexpr std::uint32_t asfDisallowXRP
static std::pair< uint256, std::shared_ptr< SLE const > > channelKeyAndSle(ReadView const &view, jtx::Account const &account, jtx::Account const &dst)
void testSimple(FeatureBitset features)
FeatureBitset const disallowIncoming
void testMultiple(FeatureBitset features)
void testAccountChannelsRPC(FeatureBitset features)
void testUsingTickets(FeatureBitset features)
void run() override
Runs the suite.
void testSettleDelay(FeatureBitset features)
void testDisallowXRP(FeatureBitset features)
void testDepositAuth(FeatureBitset features)
static std::optional< std::int64_t > channelExpiration(ReadView const &view, uint256 const &chan)
void testAccountDelete(FeatureBitset features)
void testCloseDry(FeatureBitset features)
void testExpiration(FeatureBitset features)
void testMetaAndOwnership(FeatureBitset features)
void testDefaultAmount(FeatureBitset features)
void testAuthVerifyRPC(FeatureBitset features)
void testMalformedPK(FeatureBitset features)
void testCancelAfter(FeatureBitset features)
void testWithFeats(FeatureBitset features)
void testDisallowIncoming(FeatureBitset features)
void testAccountChannelsRPCMarkers(FeatureBitset features)
void testAccountChannelAuthorize(FeatureBitset features)
void testAccountChannelsRPCSenderOnly(FeatureBitset features)
void testDstTag(FeatureBitset features)
static STAmount channelAmount(ReadView const &view, uint256 const &chan)
void testDepositAuthCreds()
static Buffer signClaimAuth(PublicKey const &pk, SecretKey const &sk, uint256 const &channel, STAmount const &authAmt)
void testOptionalFields(FeatureBitset features)