3#include <xrpl/basics/chrono.h>
4#include <xrpl/ledger/Dir.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/Indexes.h>
7#include <xrpl/protocol/PayChan.h>
8#include <xrpl/protocol/TxFlags.h>
9#include <xrpl/protocol/jss.h>
13using namespace jtx::paychan;
29 return {k.key, view.
read(k)};
47 auto const slep = view.
read({ltPAYCHAN, chan});
50 return (*slep)[sfAmount];
56 auto const slep = view.
read({ltPAYCHAN, chan});
59 if (
auto const r = (*slep)[~sfExpiration])
70 Env env{*
this, features};
71 auto const alice =
Account(
"alice");
72 auto const bob =
Account(
"bob");
73 auto USDA = alice[
"USD"];
74 env.fund(
XRP(10000), alice, bob);
75 auto const pk = alice.pk();
76 auto const settleDelay = 100s;
77 auto const chan =
channel(alice, bob, env.seq(alice));
78 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
83 auto const preAlice = env.balance(alice);
84 env(
fund(alice, chan,
XRP(1000)));
85 auto const feeDrops = env.current()->fees().base;
86 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
91 BEAST_EXPECT(chanBal ==
XRP(0));
92 BEAST_EXPECT(chanAmt ==
XRP(2000));
96 env(
create(alice, bob, USDA(1000), settleDelay, pk),
99 env(
create(alice, bob,
XRP(-1000), settleDelay, pk),
105 env(
create(alice,
"noAccount",
XRP(1000), settleDelay, pk),
108 env(
create(alice, alice,
XRP(1000), settleDelay, pk),
114 channel(alice,
"noAccount", env.seq(alice) - 1),
122 auto const iou = USDA(100).value();
123 auto const negXRP =
XRP(-100).value();
124 auto const posXRP =
XRP(100).value();
134 auto const delta =
XRP(500);
135 auto const reqBal = chanBal + delta;
136 auto const authAmt = reqBal +
XRP(-100);
137 assert(reqBal <= chanAmt);
142 auto const preBob = env.balance(bob);
143 auto const delta =
XRP(500);
144 auto const reqBal = chanBal + delta;
145 auto const authAmt = reqBal +
XRP(100);
146 assert(reqBal <= chanAmt);
147 env(
claim(alice, chan, reqBal, authAmt));
149 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
150 BEAST_EXPECT(env.balance(bob) == preBob + delta);
155 auto preBob = env.balance(bob);
156 auto const delta =
XRP(500);
157 auto const reqBal = chanBal + delta;
158 auto const authAmt = reqBal +
XRP(100);
159 assert(reqBal <= chanAmt);
162 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
164 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
165 auto const feeDrops = env.current()->fees().base;
166 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
170 preBob = env.balance(bob);
171 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
174 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
175 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
179 auto const preBob = env.balance(bob);
182 assert(reqAmt <= chanAmt);
185 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
188 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
189 BEAST_EXPECT(env.balance(bob) == preBob);
195 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
209 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
223 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
227 auto const preAlice = env.balance(alice);
228 auto const preBob = env.balance(bob);
231 auto const feeDrops = env.current()->fees().base;
232 auto const delta = chanAmt - chanBal;
233 assert(delta > beast::zero);
234 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
235 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
249 env.fund(
XRP(10000), alice);
252 auto const sle = env.le(alice);
259 auto const alice =
Account(
"alice");
260 auto const bob =
Account(
"bob");
261 auto const cho =
Account(
"cho");
262 env.fund(
XRP(10000), alice, bob, cho);
263 auto const pk = alice.pk();
264 auto const settleDelay = 100s;
272 auto const chan =
channel(alice, bob, env.seq(alice));
273 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
284 auto const chan =
channel(bob, alice, env.seq(bob));
285 env(
create(bob, alice,
XRP(1000), settleDelay, pk),
296 auto const chan =
channel(alice, bob, env.seq(alice));
297 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
304 auto const chan =
channel(cho, alice, env.seq(cho));
305 env(
create(cho, alice,
XRP(1000), settleDelay, pk),
316 auto const chan =
channel(cho, alice, env.seq(cho));
317 env(
create(cho, alice,
XRP(1000), settleDelay, pk),
329 auto const alice =
Account(
"alice");
330 auto const bob =
Account(
"bob");
331 auto const carol =
Account(
"carol");
334 Env env{*
this, features};
335 env.fund(
XRP(10000), alice, bob);
336 auto const pk = alice.pk();
337 auto const settleDelay = 100s;
339 env.current()->info().parentCloseTime + 3600s;
340 auto const channelFunds =
XRP(1000);
341 auto const chan =
channel(alice, bob, env.seq(alice));
342 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
344 env.close(cancelAfter);
349 auto preAlice = env.balance(alice);
350 auto preBob = env.balance(bob);
351 auto const delta =
XRP(500);
352 auto const reqBal = chanBal + delta;
353 auto const authAmt = reqBal +
XRP(100);
354 assert(reqBal <= chanAmt);
357 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
358 auto const feeDrops = env.current()->fees().base;
360 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
361 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
366 Env env{*
this, features};
367 env.fund(
XRP(10000), alice, bob, carol);
368 auto const pk = alice.pk();
369 auto const settleDelay = 100s;
371 env.current()->info().parentCloseTime + 3600s;
372 auto const channelFunds =
XRP(1000);
373 auto const chan =
channel(alice, bob, env.seq(alice));
374 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
379 env.close(cancelAfter);
381 auto const preAlice = env.balance(alice);
384 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
389 for (
bool const withFixPayChan : {
true,
false})
391 auto const amend = withFixPayChan
393 : features - fixPayChanCancelAfter;
394 Env env{*
this, amend};
395 env.
fund(
XRP(10000), alice, bob);
398 auto const pk = alice.pk();
399 auto const settleDelay = 100s;
400 auto const channelFunds =
XRP(1000);
402 env.current()->info().parentCloseTime - 1s;
403 auto const txResult =
406 alice, bob, channelFunds, settleDelay, pk, cancelAfter),
413 for (
bool const withFixPayChan : {
true,
false})
415 auto const amend = withFixPayChan
417 : features - fixPayChanCancelAfter;
418 Env env{*
this, amend};
419 env.
fund(
XRP(10000), alice, bob);
422 auto const pk = alice.pk();
423 auto const settleDelay = 100s;
424 auto const channelFunds =
XRP(1000);
426 env.current()->info().parentCloseTime;
428 alice, bob, channelFunds, settleDelay, pk, cancelAfter),
440 Env env{*
this, features};
441 auto const alice =
Account(
"alice");
442 auto const bob =
Account(
"bob");
443 auto const carol =
Account(
"carol");
444 env.fund(
XRP(10000), alice, bob, carol);
445 auto const pk = alice.pk();
446 auto const settleDelay = 3600s;
447 auto const closeTime = env.current()->info().parentCloseTime;
448 auto const minExpiration = closeTime + settleDelay;
450 auto const channelFunds =
XRP(1000);
451 auto const chan =
channel(alice, bob, env.seq(alice));
452 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
457 auto counts = [](
auto const& t) {
458 return t.time_since_epoch().count();
467 counts(minExpiration) + 100);
473 counts(minExpiration) + 50);
480 counts(minExpiration) + 50);
484 counts(minExpiration) + 50);
493 env.close(minExpiration);
506 Env env{*
this, features};
507 auto const alice =
Account(
"alice");
508 auto const bob =
Account(
"bob");
509 env.fund(
XRP(10000), alice, bob);
510 auto const pk = alice.pk();
511 auto const settleDelay = 3600s;
513 env.current()->info().parentCloseTime + settleDelay;
514 auto const channelFunds =
XRP(1000);
515 auto const chan =
channel(alice, bob, env.seq(alice));
516 env(
create(alice, bob, channelFunds, settleDelay, pk));
521 env.close(settleTimepoint - settleDelay / 2);
526 auto preBob = env.balance(bob);
527 auto const delta =
XRP(500);
528 auto const reqBal = chanBal + delta;
529 auto const authAmt = reqBal +
XRP(100);
530 assert(reqBal <= chanAmt);
533 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
535 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
536 auto const feeDrops = env.current()->fees().base;
537 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
539 env.close(settleTimepoint);
544 auto const preAlice = env.balance(alice);
545 auto preBob = env.balance(bob);
546 auto const delta =
XRP(500);
547 auto const reqBal = chanBal + delta;
548 auto const authAmt = reqBal +
XRP(100);
549 assert(reqBal <= chanAmt);
552 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
554 auto const feeDrops = env.current()->fees().base;
555 BEAST_EXPECT(env.balance(alice) == preAlice + chanAmt - chanBal);
556 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
566 Env env{*
this, features};
567 auto const alice =
Account(
"alice");
568 auto const bob =
Account(
"bob");
569 env.fund(
XRP(10000), alice, bob);
570 auto const pk = alice.pk();
571 auto const settleDelay = 3600s;
572 auto const channelFunds =
XRP(1000);
573 auto const chan =
channel(alice, bob, env.seq(alice));
574 env(
create(alice, bob, channelFunds, settleDelay, pk));
581 auto const preBob = env.balance(bob);
582 env(
claim(alice, chan, channelFunds.value(), channelFunds.value()));
583 BEAST_EXPECT(
channelBalance(*env.current(), chan) == channelFunds);
584 BEAST_EXPECT(env.balance(bob) == preBob + channelFunds);
586 auto const preAlice = env.balance(alice);
590 auto const feeDrops = env.current()->fees().base;
591 BEAST_EXPECT(env.balance(alice) == preAlice - feeDrops);
601 Env env{*
this, features};
602 auto const alice =
Account(
"alice");
603 auto const bob =
Account(
"bob");
604 env.fund(
XRP(10000), alice, bob);
605 auto const pk = alice.pk();
606 auto const settleDelay = 3600s;
607 auto const channelFunds =
XRP(1000);
608 auto const chan =
channel(alice, bob, env.seq(alice));
609 env(
create(alice, bob, channelFunds, settleDelay, pk));
617 auto const preBob = env.balance(bob);
619 auto const delta =
XRP(500);
620 auto const reqBal = chanBal + delta;
621 assert(reqBal <= chanAmt);
626 auto const feeDrops = env.current()->fees().base;
627 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
634 auto const preBob = env.balance(bob);
636 auto const delta =
XRP(500);
637 auto const reqBal = chanBal + delta;
638 assert(reqBal <= chanAmt);
643 auto const feeDrops = env.current()->fees().base;
644 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
657 auto const alice =
Account(
"alice");
658 auto const bob =
Account(
"bob");
661 Env env(*
this, features - featureDepositAuth);
662 env.
fund(
XRP(10000), alice, bob);
664 auto const chan =
channel(alice, bob, env.
seq(alice));
665 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()),
672 Env env{*
this, features};
673 env.fund(
XRP(10000), alice, bob);
675 auto const chan =
channel(alice, bob, env.seq(alice));
676 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
683 Env env(*
this, features - featureDepositAuth);
684 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()));
690 auto const reqBal =
XRP(500).value();
697 Env env{*
this, features};
698 env.fund(
XRP(10000), alice, bob);
699 auto const chan =
channel(alice, bob, env.seq(alice));
700 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
704 auto const reqBal =
XRP(500).value();
705 env(
claim(alice, chan, reqBal, reqBal));
717 Env env{*
this, features};
718 auto const alice =
Account(
"alice");
719 auto const bob =
Account(
"bob");
720 env.fund(
XRP(10000), alice, bob);
722 auto const pk = alice.pk();
723 auto const settleDelay = 3600s;
724 auto const channelFunds =
XRP(1000);
726 auto const chan =
channel(alice, bob, env.seq(alice));
727 env(
create(alice, bob, channelFunds, settleDelay, pk),
732 auto const chan =
channel(alice, bob, env.seq(alice));
734 alice, bob, channelFunds, settleDelay, pk,
std::nullopt, 1));
746 auto const alice =
Account(
"alice");
747 auto const bob =
Account(
"bob");
748 auto const carol =
Account(
"carol");
749 auto USDA = alice[
"USD"];
751 Env env{*
this, features};
752 env.fund(
XRP(10000), alice, bob, carol);
757 auto const pk = alice.pk();
758 auto const settleDelay = 100s;
759 auto const chan =
channel(alice, bob, env.seq(alice));
760 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
768 env(
fund(alice, chan,
XRP(1000)));
772 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
777 auto const baseFee = env.current()->fees().base;
778 auto const preBob = env.balance(bob);
780 auto const delta =
XRP(500).value();
788 BEAST_EXPECT(env.balance(bob) == preBob);
800 BEAST_EXPECT(env.balance(bob) == preBob + delta - baseFee);
804 auto const delta =
XRP(600).value();
836 env.balance(bob) == preBob + delta - (3 * baseFee));
841 auto const delta =
XRP(800).value();
855 env(
claim(alice, chan, delta, delta));
858 env.balance(bob) == preBob +
XRP(800) - (5 * baseFee));
866 testcase(
"Deposit Authorization with Credentials");
870 char const credType[] =
"abcde";
875 Account const dillon(
"dillon");
880 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
882 auto const pk = alice.
pk();
883 auto const settleDelay = 100s;
884 auto const chan =
channel(alice, bob, env.seq(alice));
885 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
889 env(
fund(alice, chan,
XRP(1000)));
893 "D007AE4B6E1274B4AF872588267B810C2F82716726351D1C7D38D3E5499FC6"
896 auto const delta =
XRP(500).value();
902 .parentCloseTime.time_since_epoch()
905 jv[sfExpiration.jsonName] = t;
912 std::string const credIdx = jv[jss::result][jss::index].asString();
919 env(
claim(alice, chan, delta, delta),
928 env(
claim(alice, chan, delta, delta),
938 env(
claim(dillon, chan, delta, delta),
946 env(
claim(alice, chan, delta, delta),
951 env(
claim(alice, chan, delta, delta),
959 for (
int i = 0; i < 10; ++i)
962 env(
claim(alice, chan, delta, delta),
977 jv[jss::result][jss::index].asString();
980 env(
claim(alice, chan, delta, delta),
987 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
989 auto const pk = alice.
pk();
990 auto const settleDelay = 100s;
991 auto const chan =
channel(alice, bob, env.seq(alice));
992 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
996 env(
fund(alice, chan,
XRP(1000)));
999 auto const delta =
XRP(500).value();
1010 std::string const credIdx = jv[jss::result][jss::index].asString();
1020 env.
fund(
XRP(5000),
"alice",
"bob");
1023 auto const pk = alice.
pk();
1024 auto const settleDelay = 100s;
1025 auto const chan =
channel(alice, bob, env.
seq(alice));
1026 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1029 env(
fund(alice, chan,
XRP(1000)));
1032 "48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6EA288B"
1041 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
1051 testcase(
"Multiple channels to the same account");
1052 using namespace jtx;
1054 Env env{*
this, features};
1055 auto const alice =
Account(
"alice");
1056 auto const bob =
Account(
"bob");
1057 env.fund(
XRP(10000), alice, bob);
1058 auto const pk = alice.pk();
1059 auto const settleDelay = 3600s;
1060 auto const channelFunds =
XRP(1000);
1061 auto const chan1 =
channel(alice, bob, env.seq(alice));
1062 env(
create(alice, bob, channelFunds, settleDelay, pk));
1064 auto const chan2 =
channel(alice, bob, env.seq(alice));
1065 env(
create(alice, bob, channelFunds, settleDelay, pk));
1067 BEAST_EXPECT(chan1 != chan2);
1075 using namespace jtx;
1077 Env env{*
this, features};
1078 auto const alice =
Account(
"alice");
1079 auto const bob =
Account(
"bob");
1081 env.fund(
XRP(10000), alice, bob, charlie);
1082 auto const pk = alice.pk();
1083 auto const settleDelay = 3600s;
1084 auto const channelFunds =
XRP(1000);
1086 env(
create(alice, bob, channelFunds, settleDelay, pk));
1090 auto testInvalidAccountParam = [&](
auto const& param) {
1092 params[jss::account] = param;
1094 "json",
"account_channels",
to_string(params))[jss::result];
1095 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1097 jrr[jss::error_message] ==
"Invalid field 'account'.");
1100 testInvalidAccountParam(1);
1101 testInvalidAccountParam(1.1);
1102 testInvalidAccountParam(
true);
1109 env.rpc(
"account_channels", alice.human(), bob.human());
1110 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1112 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1113 BEAST_EXPECT(r[jss::result][jss::validated]);
1116 auto const r = env.rpc(
"account_channels", alice.human());
1117 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1119 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1120 BEAST_EXPECT(r[jss::result][jss::validated]);
1124 env.rpc(
"account_channels", bob.human(), alice.human());
1125 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1126 BEAST_EXPECT(r[jss::result][jss::validated]);
1129 env(
create(alice, bob, channelFunds, settleDelay, pk));
1133 env.rpc(
"account_channels", alice.human(), bob.human());
1134 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1135 BEAST_EXPECT(r[jss::result][jss::validated]);
1136 BEAST_EXPECT(chan1Str != chan2Str);
1137 for (
auto const& c : {chan1Str, chan2Str})
1139 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1140 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1147 testcase(
"Account channels RPC markers");
1149 using namespace test::jtx;
1152 auto const alice =
Account(
"alice");
1157 for (
int i = 0; i < n; ++i)
1164 Env env{*
this, features};
1165 env.fund(
XRP(10000), alice);
1166 for (
auto const& a : bobs)
1168 env.fund(
XRP(10000), a);
1174 auto const settleDelay = 3600s;
1175 auto const channelFunds =
XRP(1);
1176 for (
auto const& b : bobs)
1178 env(
create(alice, b, channelFunds, settleDelay, alice.pk()));
1189 jvc[jss::account] = src.human();
1191 jvc[jss::destination_account] = dst->human();
1193 jvc[jss::limit] = *limit;
1195 jvc[jss::marker] = marker;
1198 "json",
"account_channels",
to_string(jvc))[jss::result];
1203 auto const r = testLimit(env, alice);
1204 BEAST_EXPECT(r.isMember(jss::channels));
1205 BEAST_EXPECT(r[jss::channels].size() == bobs.size());
1210 for (
auto const& a : bobs)
1215 for (
int limit = 1; limit < bobs.size() + 1; ++limit)
1217 auto leftToFind = bobsB58;
1218 auto const numFull = bobs.
size() / limit;
1219 auto const numNonFull = bobs.size() % limit ? 1 : 0;
1223 auto const testIt = [&](
bool expectMarker,
int expectedBatchSize) {
1224 auto const r = testLimit(env, alice, limit, marker);
1225 BEAST_EXPECT(!expectMarker || r.isMember(jss::marker));
1226 if (r.isMember(jss::marker))
1227 marker = r[jss::marker];
1228 BEAST_EXPECT(r[jss::channels].size() == expectedBatchSize);
1229 auto const c = r[jss::channels];
1230 auto const s = r[jss::channels].size();
1231 for (
int j = 0; j < s; ++j)
1234 c[j][jss::destination_account].asString();
1235 BEAST_EXPECT(leftToFind.count(dstAcc));
1236 leftToFind.erase(dstAcc);
1240 for (
int i = 0; i < numFull; ++i)
1242 bool const expectMarker = (numNonFull != 0 || i < numFull - 1);
1243 testIt(expectMarker, limit);
1248 testIt(
false, bobs.size() % limit);
1250 BEAST_EXPECT(leftToFind.empty());
1255 auto const r = testLimit(env, alice, 0);
1256 BEAST_EXPECT(r.isMember(jss::error_message));
1265 testcase(
"Account channels RPC owner only");
1267 using namespace test::jtx;
1270 auto const alice =
Account(
"alice");
1271 auto const bob =
Account(
"bob");
1272 Env env{*
this, features};
1273 env.fund(
XRP(10000), alice, bob);
1278 auto const settleDelay = 3600s;
1279 auto const channelFunds =
XRP(1000);
1280 env(
create(alice, bob, channelFunds, settleDelay, alice.pk()));
1281 env(
create(bob, alice, channelFunds, settleDelay, bob.pk()));
1283 auto const r = [&] {
1285 jvc[jss::account] = alice.human();
1288 "json",
"account_channels",
to_string(jvc))[jss::result];
1290 BEAST_EXPECT(r.isMember(jss::channels));
1291 BEAST_EXPECT(r[jss::channels].size() == 1);
1293 r[jss::channels][0u][jss::destination_account].asString() ==
1300 using namespace jtx;
1303 Env env{*
this, features};
1304 auto const alice =
Account(
"alice");
1305 auto const bob =
Account(
"bob");
1307 env.fund(
XRP(10000), alice, bob, charlie);
1308 auto const pk = alice.pk();
1309 auto const settleDelay = 3600s;
1310 auto const channelFunds =
XRP(1000);
1312 env(
create(alice, bob, channelFunds, settleDelay, pk));
1316 args[jss::channel_id] = chan1Str;
1317 args[jss::key_type] =
"ed255191";
1318 args[jss::seed] =
"snHq1rzQoN2qiUkC3XF5RyxBzUtN";
1319 args[jss::amount] = 51110000;
1325 args[jss::api_version] = apiVersion;
1326 auto const rs = env.rpc(
1328 "channel_authorize",
1329 args.toStyledString())[jss::result];
1330 auto const error = apiVersion < 2u ?
"invalidParams" :
"badKeyType";
1331 BEAST_EXPECT(rs[jss::error] == error);
1338 testcase(
"PayChan Auth/Verify RPC");
1339 using namespace jtx;
1341 Env env{*
this, features};
1342 auto const alice =
Account(
"alice");
1343 auto const bob =
Account(
"bob");
1345 env.fund(
XRP(10000), alice, bob, charlie);
1346 auto const pk = alice.pk();
1347 auto const settleDelay = 3600s;
1348 auto const channelFunds =
XRP(1000);
1350 env(
create(alice, bob, channelFunds, settleDelay, pk));
1355 env.rpc(
"account_channels", alice.human(), bob.human());
1356 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1358 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1359 BEAST_EXPECT(r[jss::result][jss::validated]);
1361 r[jss::result][jss::channels][0u][jss::public_key].asString();
1364 auto const r = env.rpc(
"account_channels", alice.human());
1365 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1367 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1368 BEAST_EXPECT(r[jss::result][jss::validated]);
1370 r[jss::result][jss::channels][0u][jss::public_key].asString();
1374 env.rpc(
"account_channels", bob.human(), alice.human());
1375 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1376 BEAST_EXPECT(r[jss::result][jss::validated]);
1379 env(
create(alice, bob, channelFunds, settleDelay, pk));
1383 env.rpc(
"account_channels", alice.human(), bob.human());
1384 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1385 BEAST_EXPECT(r[jss::result][jss::validated]);
1386 BEAST_EXPECT(chan1Str != chan2Str);
1387 for (
auto const& c : {chan1Str, chan2Str})
1389 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1390 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1398 s +=
"0123456789ABCDEF"[((
slice[i] & 0xf0) >> 4)];
1399 s +=
"0123456789ABCDEF"[((
slice[i] & 0x0f) >> 0)];
1407 env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000");
1408 auto const sig = rs[jss::result][jss::signature].asString();
1409 BEAST_EXPECT(!
sig.empty());
1411 auto const rv = env.rpc(
1412 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1413 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1420 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1421 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1427 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000x",
sig);
1428 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1429 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 ",
sig);
1430 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1431 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x1000",
sig);
1432 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1433 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x",
sig);
1434 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1435 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" ",
sig);
1436 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1438 "channel_verify", pkAsHex, chan1Str,
"1000 1000",
sig);
1439 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1440 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1,000",
sig);
1441 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1442 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" 1000",
sig);
1443 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1444 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"",
sig);
1445 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1450 auto chan1StrBad = chan1Str;
1451 chan1StrBad.pop_back();
1453 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1454 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1455 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1456 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1458 chan1StrBad = chan1Str;
1459 chan1StrBad.push_back(
'0');
1461 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1462 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1463 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1464 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1466 chan1StrBad = chan1Str;
1467 chan1StrBad.back() =
'x';
1469 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1470 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1471 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1472 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1476 auto illFormedPk = chan1PkStr.
substr(0, chan1PkStr.
size() - 1);
1477 auto const rv = env.rpc(
1478 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1480 !rv[jss::result][jss::signature_verified].asBool());
1485 auto illFormedPk = pkAsHex.substr(0, chan1PkStr.
size() - 1);
1486 auto const rv = env.rpc(
1487 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1489 !rv[jss::result][jss::signature_verified].asBool());
1495 env.rpc(
"channel_authorize",
"alice", chan2Str,
"1000");
1496 auto const sig = rs[jss::result][jss::signature].asString();
1497 BEAST_EXPECT(!
sig.empty());
1499 auto const rv = env.rpc(
1500 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1502 !rv[jss::result][jss::signature_verified].asBool());
1508 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1510 !rv[jss::result][jss::signature_verified].asBool());
1518 charlie, alice, channelFunds, settleDelay, charlie.pk()));
1524 env.rpc(
"account_channels", charlie.human(), alice.human());
1525 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1527 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1528 BEAST_EXPECT(r[jss::result][jss::validated]);
1529 cpk = r[jss::result][jss::channels][0u][jss::public_key]
1535 env.rpc(
"channel_authorize",
"charlie", chan,
"1000");
1536 auto const sig = rs[jss::result][jss::signature].asString();
1537 BEAST_EXPECT(!
sig.empty());
1540 env.rpc(
"channel_verify", cpk, chan,
"1000",
sig);
1542 !rv[jss::result][jss::signature_verified].asBool());
1547 env.rpc(
"channel_authorize",
"charlie",
"nyx", chan,
"1000");
1548 BEAST_EXPECT(rs1[jss::error] ==
"badKeyType");
1552 auto const rs2 = env.rpc(
1553 "channel_authorize",
"charlie",
"secp256k1", chan,
"1000");
1554 auto const sig2 = rs2[jss::result][jss::signature].asString();
1555 BEAST_EXPECT(!sig2.empty());
1558 env.rpc(
"channel_verify", cpk, chan,
"1000", sig2);
1560 !rv[jss::result][jss::signature_verified].asBool());
1564 auto const rs3 = env.rpc(
1565 "channel_authorize",
"charlie",
"ed25519", chan,
"1000");
1566 auto const sig3 = rs3[jss::result][jss::signature].asString();
1567 BEAST_EXPECT(!sig3.empty());
1570 env.rpc(
"channel_verify", cpk, chan,
"1000", sig3);
1571 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1577 auto rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000x");
1578 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1579 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x1000");
1580 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1581 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x");
1582 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1586 args[jss::amount] =
"2000";
1587 args[jss::key_type] =
"secp256k1";
1588 args[jss::passphrase] =
"passphrase_can_be_anything";
1591 "channel_authorize",
1592 args.toStyledString())[jss::result];
1593 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1598 args[jss::channel_id] = chan1Str;
1599 args[jss::key_type] =
"secp256k1";
1600 args[jss::passphrase] =
"passphrase_can_be_anything";
1603 "channel_authorize",
1604 args.toStyledString())[jss::result];
1605 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1610 args[jss::amount] =
"2000";
1611 args[jss::channel_id] = chan1Str;
1612 args[jss::passphrase] =
"passphrase_can_be_anything";
1615 "channel_authorize",
1616 args.toStyledString())[jss::result];
1617 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1622 args[jss::amount] =
"2000";
1623 args[jss::channel_id] = chan1Str;
1624 args[jss::key_type] =
"secp256k1";
1625 args[jss::passphrase] =
"passphrase_can_be_anything";
1626 args[jss::seed] =
"seed can be anything";
1629 "channel_authorize",
1630 args.toStyledString())[jss::result];
1631 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1636 args[jss::amount] =
"2000";
1637 args[jss::channel_id] = chan1Str +
"1";
1638 args[jss::key_type] =
"secp256k1";
1639 args[jss::passphrase] =
"passphrase_can_be_anything";
1642 "channel_authorize",
1643 args.toStyledString())[jss::result];
1644 BEAST_EXPECT(rs[jss::error] ==
"channelMalformed");
1649 args[jss::amount] = 2000;
1650 args[jss::channel_id] = chan1Str;
1651 args[jss::key_type] =
"secp256k1";
1652 args[jss::passphrase] =
"passphrase_can_be_anything";
1655 "channel_authorize",
1656 args.toStyledString())[jss::result];
1657 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1662 args[jss::amount] =
"TwoThousand";
1663 args[jss::channel_id] = chan1Str;
1664 args[jss::key_type] =
"secp256k1";
1665 args[jss::passphrase] =
"passphrase_can_be_anything";
1668 "channel_authorize",
1669 args.toStyledString())[jss::result];
1670 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1679 using namespace jtx;
1681 Env env{*
this, features};
1682 auto const alice =
Account(
"alice");
1683 auto const bob =
Account(
"bob");
1684 auto const carol =
Account(
"carol");
1685 auto const dan =
Account(
"dan");
1686 env.fund(
XRP(10000), alice, bob, carol, dan);
1687 auto const pk = alice.pk();
1688 auto const settleDelay = 3600s;
1689 auto const channelFunds =
XRP(1000);
1695 env(
create(alice, bob, channelFunds, settleDelay, pk));
1697 env.rpc(
"account_channels", alice.human(), bob.human());
1698 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1700 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1701 BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember(
1702 jss::destination_tag));
1716 env.rpc(
"account_channels", alice.human(), carol.human());
1717 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1719 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1721 r[jss::result][jss::channels][0u][jss::destination_tag] ==
1730 using namespace jtx;
1732 Env env{*
this, features};
1733 auto const alice =
Account(
"alice");
1734 auto const bob =
Account(
"bob");
1735 auto USDA = alice[
"USD"];
1736 env.fund(
XRP(10000), alice, bob);
1737 auto const pk = alice.pk();
1738 auto const settleDelay = 100s;
1740 auto const chan =
channel(alice, bob, env.seq(alice));
1741 auto jv =
create(alice, bob,
XRP(1000), settleDelay, pk);
1742 auto const pkHex =
strHex(pk.slice());
1743 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1745 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1747 auto badPrefix = pkHex;
1750 jv[
"PublicKey"] = badPrefix;
1753 jv[
"PublicKey"] = pkHex;
1756 auto const authAmt =
XRP(100);
1765 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1767 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1772 jv[
"PublicKey"] = badPrefix;
1776 jv.removeMember(
"PublicKey");
1780 auto const txn = R
"*(
1783 "channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
1785 "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
1787 "aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
1791 auto const r = env.rpc(
"json",
"channel_verify", txn);
1792 BEAST_EXPECT(r[
"result"][
"error"] ==
"publicMalformed");
1801 using namespace jtx;
1804 auto const alice =
Account(
"alice");
1805 auto const bob =
Account(
"bob");
1806 auto const settleDelay = 100s;
1807 auto const pk = alice.pk();
1809 auto inOwnerDir = [](
ReadView const& view,
1813 return std::find(ownerDir.begin(), ownerDir.end(), chan) !=
1817 auto ownerDirCount = [](
ReadView const& view,
1826 Env env(*
this, features - fixPayChanRecipientOwnerDir);
1827 env.
fund(
XRP(10000), alice, bob);
1828 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1830 auto const [chan, chanSle] =
1832 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1833 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1834 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1835 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1836 if (features[fixIncludeKeyletFields])
1838 BEAST_EXPECT((*chanSle)[sfSequence] == env.
seq(alice) - 1);
1842 BEAST_EXPECT(!chanSle->isFieldPresent(sfSequence));
1847 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1848 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1849 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1850 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1855 Env env{*
this, features};
1856 env.fund(
XRP(10000), alice, bob);
1857 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1859 auto const [chan, chanSle] =
1861 BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle));
1862 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
1863 BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle));
1864 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 1);
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);
1877 Env env(*
this, features - fixPayChanRecipientOwnerDir);
1878 env.
fund(
XRP(10000), alice, bob);
1880 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1882 auto const [chan, chanSle] =
1884 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1885 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1886 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1887 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1891 env.
current()->rules().enabled(fixPayChanRecipientOwnerDir));
1896 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1897 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1898 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1903 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1904 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1905 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1906 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1914 using namespace test::jtx;
1916 auto rmAccount = [
this](
1923 for (
auto minRmSeq = env.
seq(toRm) + 257;
1924 env.
current()->seq() < minRmSeq;
1938 auto const alice =
Account(
"alice");
1939 auto const bob =
Account(
"bob");
1940 auto const carol =
Account(
"carol");
1942 for (
bool const withOwnerDirFix : {
false,
true})
1944 auto const amd = withOwnerDirFix
1946 : features - fixPayChanRecipientOwnerDir;
1947 Env env{*
this, amd};
1948 env.
fund(
XRP(10000), alice, bob, carol);
1952 auto const pk = alice.pk();
1953 auto const settleDelay = 100s;
1954 auto const chan =
channel(alice, bob, env.
seq(alice));
1955 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1968 auto const feeDrops = env.
current()->fees().base;
1971 BEAST_EXPECT(chanBal ==
XRP(0));
1972 BEAST_EXPECT(chanAmt ==
XRP(1000));
1974 auto preBob = env.
balance(bob);
1975 auto const delta =
XRP(50);
1976 auto reqBal = chanBal + delta;
1977 auto authAmt = reqBal +
XRP(100);
1978 assert(reqBal <= chanAmt);
1981 if (withOwnerDirFix)
1983 env(
claim(alice, chan, reqBal, authAmt));
1987 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1992 auto const preAlice = env.
balance(alice);
1997 BEAST_EXPECT(env.
balance(bob) == preBob);
1998 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2002 if (withOwnerDirFix)
2004 auto const preAlice = env.
balance(alice);
2005 env(
fund(alice, chan,
XRP(1000)));
2008 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
2011 chanAmt = chanAmt +
XRP(1000);
2015 auto const preAlice = env.
balance(alice);
2018 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2028 auto const closeTime = env.
current()->info().parentCloseTime;
2029 auto const minExpiration = closeTime + settleDelay;
2030 env.
close(minExpiration);
2038 Env env{*
this, features - fixPayChanRecipientOwnerDir};
2039 env.
fund(
XRP(10000), alice, bob, carol);
2043 auto const pk = alice.pk();
2044 auto const settleDelay = 100s;
2045 auto const chan =
channel(alice, bob, env.
seq(alice));
2046 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
2052 rmAccount(env, bob, carol);
2055 auto const feeDrops = env.
current()->fees().base;
2058 BEAST_EXPECT(chanBal ==
XRP(0));
2059 BEAST_EXPECT(chanAmt ==
XRP(1000));
2060 auto preBob = env.
balance(bob);
2061 auto const delta =
XRP(50);
2062 auto reqBal = chanBal + delta;
2063 auto authAmt = reqBal +
XRP(100);
2064 assert(reqBal <= chanAmt);
2068 auto const preAlice = env.
balance(alice);
2073 BEAST_EXPECT(env.
balance(bob) == preBob);
2074 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2079 auto const preAlice = env.
balance(alice);
2082 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2087 env(
pay(alice, bob,
XRP(20)));
2094 reqBal = chanBal + delta;
2095 authAmt = reqBal +
XRP(100);
2096 env(
claim(alice, chan, reqBal, authAmt));
2099 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
2106 reqBal = chanBal + delta;
2107 authAmt = reqBal +
XRP(100);
2110 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
2113 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
2119 auto const preAlice = env.
balance(alice);
2120 env(
fund(alice, chan,
XRP(1000)));
2122 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
2125 chanAmt = chanAmt +
XRP(1000);
2134 auto const closeTime = env.
current()->info().parentCloseTime;
2135 auto const minExpiration = closeTime + settleDelay;
2136 env.
close(minExpiration);
2147 using namespace jtx;
2149 Env env{*
this, features};
2150 auto const alice =
Account(
"alice");
2151 auto const bob =
Account(
"bob");
2152 auto USDA = alice[
"USD"];
2153 env.fund(
XRP(10000), alice, bob);
2166 auto const pk = alice.pk();
2167 auto const settleDelay = 100s;
2168 auto const chan =
channel(alice, bob, aliceTicketSeq);
2170 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
2173 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2174 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2180 auto const preAlice = env.balance(alice);
2183 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2184 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2186 auto const feeDrops = env.current()->fees().base;
2187 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
2192 BEAST_EXPECT(chanBal ==
XRP(0));
2193 BEAST_EXPECT(chanAmt ==
XRP(2000));
2197 auto const preBob = env.balance(bob);
2198 auto const delta =
XRP(500);
2199 auto const reqBal = chanBal + delta;
2200 auto const authAmt = reqBal +
XRP(100);
2201 assert(reqBal <= chanAmt);
2202 env(
claim(alice, chan, reqBal, authAmt),
2205 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2206 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2209 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2210 BEAST_EXPECT(env.balance(bob) == preBob + delta);
2215 auto preBob = env.balance(bob);
2216 auto const delta =
XRP(500);
2217 auto const reqBal = chanBal + delta;
2218 auto const authAmt = reqBal +
XRP(100);
2219 assert(reqBal <= chanAmt);
2222 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
2225 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2226 BEAST_EXPECT(env.seq(bob) == bobSeq);
2229 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2230 auto const feeDrops = env.current()->fees().base;
2231 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
2235 preBob = env.balance(bob);
2237 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
2241 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2242 BEAST_EXPECT(env.seq(bob) == bobSeq);
2245 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2246 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2250 auto const preBob = env.balance(bob);
2253 assert(reqAmt <= chanAmt);
2258 env(
claim(bob, chan, reqAmt, 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);
2271 env(
fund(bob, chan,
XRP(1000)),
2275 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2276 BEAST_EXPECT(env.seq(bob) == bobSeq);
2279 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2283 auto const preAlice = env.balance(alice);
2284 auto const preBob = env.balance(bob);
2285 env(
claim(bob, chan),
2289 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2290 BEAST_EXPECT(env.seq(bob) == bobSeq);
2293 auto const feeDrops = env.current()->fees().base;
2294 auto const delta = chanAmt - chanBal;
2295 assert(delta > beast::zero);
2296 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
2297 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2299 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2300 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2301 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2302 BEAST_EXPECT(env.seq(bob) == bobSeq);
2335 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()
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.
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)