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>
48 return {k.key, view.
read(k)};
66 auto const slep = view.
read({ltPAYCHAN, chan});
69 return (*slep)[sfAmount];
75 auto const slep = view.
read({ltPAYCHAN, chan});
78 if (
auto const r = (*slep)[~sfExpiration])
89 Env env{*
this, features};
90 auto const alice =
Account(
"alice");
91 auto const bob =
Account(
"bob");
92 auto USDA = alice[
"USD"];
93 env.fund(
XRP(10000), alice, bob);
94 auto const pk = alice.pk();
95 auto const settleDelay = 100s;
96 auto const chan =
channel(alice, bob, env.seq(alice));
97 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
102 auto const preAlice = env.balance(alice);
103 env(
fund(alice, chan,
XRP(1000)));
104 auto const feeDrops = env.current()->fees().base;
105 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
110 BEAST_EXPECT(chanBal ==
XRP(0));
111 BEAST_EXPECT(chanAmt ==
XRP(2000));
115 env(
create(alice, bob, USDA(1000), settleDelay, pk),
118 env(
create(alice, bob,
XRP(-1000), settleDelay, pk),
124 env(
create(alice,
"noAccount",
XRP(1000), settleDelay, pk),
127 env(
create(alice, alice,
XRP(1000), settleDelay, pk),
133 channel(alice,
"noAccount", env.seq(alice) - 1),
141 auto const iou = USDA(100).value();
142 auto const negXRP =
XRP(-100).value();
143 auto const posXRP =
XRP(100).value();
153 auto const delta =
XRP(500);
154 auto const reqBal = chanBal + delta;
155 auto const authAmt = reqBal +
XRP(-100);
156 assert(reqBal <= chanAmt);
161 auto const preBob = env.balance(bob);
162 auto const delta =
XRP(500);
163 auto const reqBal = chanBal + delta;
164 auto const authAmt = reqBal +
XRP(100);
165 assert(reqBal <= chanAmt);
166 env(
claim(alice, chan, reqBal, authAmt));
168 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
169 BEAST_EXPECT(env.balance(bob) == preBob + delta);
174 auto preBob = env.balance(bob);
175 auto const delta =
XRP(500);
176 auto const reqBal = chanBal + delta;
177 auto const authAmt = reqBal +
XRP(100);
178 assert(reqBal <= chanAmt);
181 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
183 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
184 auto const feeDrops = env.current()->fees().base;
185 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
189 preBob = env.balance(bob);
190 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
193 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
194 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
198 auto const preBob = env.balance(bob);
201 assert(reqAmt <= chanAmt);
204 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
207 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
208 BEAST_EXPECT(env.balance(bob) == preBob);
214 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
228 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
242 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
246 auto const preAlice = env.balance(alice);
247 auto const preBob = env.balance(bob);
250 auto const feeDrops = env.current()->fees().base;
251 auto const delta = chanAmt - chanBal;
252 assert(delta > beast::zero);
253 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
254 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
268 env.fund(
XRP(10000), alice);
271 auto const sle = env.le(alice);
278 auto const alice =
Account(
"alice");
279 auto const bob =
Account(
"bob");
280 auto const cho =
Account(
"cho");
281 env.fund(
XRP(10000), alice, bob, cho);
282 auto const pk = alice.pk();
283 auto const settleDelay = 100s;
291 auto const chan =
channel(alice, bob, env.seq(alice));
292 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
303 auto const chan =
channel(bob, alice, env.seq(bob));
304 env(
create(bob, alice,
XRP(1000), settleDelay, pk),
315 auto const chan =
channel(alice, bob, env.seq(alice));
316 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
323 auto const chan =
channel(cho, alice, env.seq(cho));
324 env(
create(cho, alice,
XRP(1000), settleDelay, pk),
335 auto const chan =
channel(cho, alice, env.seq(cho));
336 env(
create(cho, alice,
XRP(1000), settleDelay, pk),
348 auto const alice =
Account(
"alice");
349 auto const bob =
Account(
"bob");
350 auto const carol =
Account(
"carol");
353 Env env{*
this, features};
354 env.fund(
XRP(10000), alice, bob);
355 auto const pk = alice.pk();
356 auto const settleDelay = 100s;
358 env.current()->info().parentCloseTime + 3600s;
359 auto const channelFunds =
XRP(1000);
360 auto const chan =
channel(alice, bob, env.seq(alice));
361 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
363 env.close(cancelAfter);
368 auto preAlice = env.balance(alice);
369 auto preBob = env.balance(bob);
370 auto const delta =
XRP(500);
371 auto const reqBal = chanBal + delta;
372 auto const authAmt = reqBal +
XRP(100);
373 assert(reqBal <= chanAmt);
376 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
377 auto const feeDrops = env.current()->fees().base;
379 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
380 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
385 Env env{*
this, features};
386 env.fund(
XRP(10000), alice, bob, carol);
387 auto const pk = alice.pk();
388 auto const settleDelay = 100s;
390 env.current()->info().parentCloseTime + 3600s;
391 auto const channelFunds =
XRP(1000);
392 auto const chan =
channel(alice, bob, env.seq(alice));
393 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
398 env.close(cancelAfter);
400 auto const preAlice = env.balance(alice);
403 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
408 for (
bool const withFixPayChan : {
true,
false})
410 auto const amend = withFixPayChan
412 : features - fixPayChanCancelAfter;
413 Env env{*
this, amend};
414 env.
fund(
XRP(10000), alice, bob);
417 auto const pk = alice.pk();
418 auto const settleDelay = 100s;
419 auto const channelFunds =
XRP(1000);
421 env.current()->info().parentCloseTime - 1s;
422 auto const txResult =
425 alice, bob, channelFunds, settleDelay, pk, cancelAfter),
432 for (
bool const withFixPayChan : {
true,
false})
434 auto const amend = withFixPayChan
436 : features - fixPayChanCancelAfter;
437 Env env{*
this, amend};
438 env.
fund(
XRP(10000), alice, bob);
441 auto const pk = alice.pk();
442 auto const settleDelay = 100s;
443 auto const channelFunds =
XRP(1000);
445 env.current()->info().parentCloseTime;
447 alice, bob, channelFunds, settleDelay, pk, cancelAfter),
459 Env env{*
this, features};
460 auto const alice =
Account(
"alice");
461 auto const bob =
Account(
"bob");
462 auto const carol =
Account(
"carol");
463 env.fund(
XRP(10000), alice, bob, carol);
464 auto const pk = alice.pk();
465 auto const settleDelay = 3600s;
466 auto const closeTime = env.current()->info().parentCloseTime;
467 auto const minExpiration = closeTime + settleDelay;
469 auto const channelFunds =
XRP(1000);
470 auto const chan =
channel(alice, bob, env.seq(alice));
471 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
476 auto counts = [](
auto const& t) {
477 return t.time_since_epoch().count();
486 counts(minExpiration) + 100);
492 counts(minExpiration) + 50);
499 counts(minExpiration) + 50);
503 counts(minExpiration) + 50);
512 env.close(minExpiration);
525 Env env{*
this, features};
526 auto const alice =
Account(
"alice");
527 auto const bob =
Account(
"bob");
528 env.fund(
XRP(10000), alice, bob);
529 auto const pk = alice.pk();
530 auto const settleDelay = 3600s;
532 env.current()->info().parentCloseTime + settleDelay;
533 auto const channelFunds =
XRP(1000);
534 auto const chan =
channel(alice, bob, env.seq(alice));
535 env(
create(alice, bob, channelFunds, settleDelay, pk));
540 env.close(settleTimepoint - settleDelay / 2);
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 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
555 auto const feeDrops = env.current()->fees().base;
556 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
558 env.close(settleTimepoint);
563 auto const preAlice = env.balance(alice);
564 auto preBob = env.balance(bob);
565 auto const delta =
XRP(500);
566 auto const reqBal = chanBal + delta;
567 auto const authAmt = reqBal +
XRP(100);
568 assert(reqBal <= chanAmt);
571 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
573 auto const feeDrops = env.current()->fees().base;
574 BEAST_EXPECT(env.balance(alice) == preAlice + chanAmt - chanBal);
575 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
585 Env env{*
this, features};
586 auto const alice =
Account(
"alice");
587 auto const bob =
Account(
"bob");
588 env.fund(
XRP(10000), alice, bob);
589 auto const pk = alice.pk();
590 auto const settleDelay = 3600s;
591 auto const channelFunds =
XRP(1000);
592 auto const chan =
channel(alice, bob, env.seq(alice));
593 env(
create(alice, bob, channelFunds, settleDelay, pk));
600 auto const preBob = env.balance(bob);
601 env(
claim(alice, chan, channelFunds.value(), channelFunds.value()));
602 BEAST_EXPECT(
channelBalance(*env.current(), chan) == channelFunds);
603 BEAST_EXPECT(env.balance(bob) == preBob + channelFunds);
605 auto const preAlice = env.balance(alice);
609 auto const feeDrops = env.current()->fees().base;
610 BEAST_EXPECT(env.balance(alice) == preAlice - feeDrops);
620 Env env{*
this, features};
621 auto const alice =
Account(
"alice");
622 auto const bob =
Account(
"bob");
623 env.fund(
XRP(10000), alice, bob);
624 auto const pk = alice.pk();
625 auto const settleDelay = 3600s;
626 auto const channelFunds =
XRP(1000);
627 auto const chan =
channel(alice, bob, env.seq(alice));
628 env(
create(alice, bob, channelFunds, settleDelay, pk));
636 auto const preBob = env.balance(bob);
638 auto const delta =
XRP(500);
639 auto const reqBal = chanBal + delta;
640 assert(reqBal <= chanAmt);
645 auto const feeDrops = env.current()->fees().base;
646 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
653 auto const preBob = env.balance(bob);
655 auto const delta =
XRP(500);
656 auto const reqBal = chanBal + delta;
657 assert(reqBal <= chanAmt);
662 auto const feeDrops = env.current()->fees().base;
663 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
676 auto const alice =
Account(
"alice");
677 auto const bob =
Account(
"bob");
680 Env env(*
this, features - featureDepositAuth);
681 env.
fund(
XRP(10000), alice, bob);
683 auto const chan =
channel(alice, bob, env.
seq(alice));
684 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()),
691 Env env{*
this, features};
692 env.fund(
XRP(10000), alice, bob);
694 auto const chan =
channel(alice, bob, env.seq(alice));
695 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
702 Env env(*
this, features - featureDepositAuth);
703 env.
fund(
XRP(10000), alice, bob);
704 auto const chan =
channel(alice, bob, env.
seq(alice));
705 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
709 auto const reqBal =
XRP(500).value();
716 Env env{*
this, features};
717 env.fund(
XRP(10000), alice, bob);
718 auto const chan =
channel(alice, bob, env.seq(alice));
719 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
723 auto const reqBal =
XRP(500).value();
724 env(
claim(alice, chan, reqBal, reqBal));
736 Env env{*
this, features};
737 auto const alice =
Account(
"alice");
738 auto const bob =
Account(
"bob");
739 env.fund(
XRP(10000), alice, bob);
741 auto const pk = alice.pk();
742 auto const settleDelay = 3600s;
743 auto const channelFunds =
XRP(1000);
745 auto const chan =
channel(alice, bob, env.seq(alice));
746 env(
create(alice, bob, channelFunds, settleDelay, pk),
751 auto const chan =
channel(alice, bob, env.seq(alice));
753 alice, bob, channelFunds, settleDelay, pk,
std::nullopt, 1));
765 auto const alice =
Account(
"alice");
766 auto const bob =
Account(
"bob");
767 auto const carol =
Account(
"carol");
768 auto USDA = alice[
"USD"];
770 Env env{*
this, features};
771 env.fund(
XRP(10000), alice, bob, carol);
776 auto const pk = alice.pk();
777 auto const settleDelay = 100s;
778 auto const chan =
channel(alice, bob, env.seq(alice));
779 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
787 env(
fund(alice, chan,
XRP(1000)));
791 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
796 auto const baseFee = env.current()->fees().base;
797 auto const preBob = env.balance(bob);
799 auto const delta =
XRP(500).value();
807 BEAST_EXPECT(env.balance(bob) == preBob);
819 BEAST_EXPECT(env.balance(bob) == preBob + delta - baseFee);
823 auto const delta =
XRP(600).value();
855 env.balance(bob) == preBob + delta - (3 * baseFee));
860 auto const delta =
XRP(800).value();
874 env(
claim(alice, chan, delta, delta));
877 env.balance(bob) == preBob +
XRP(800) - (5 * baseFee));
885 testcase(
"Deposit Authorization with Credentials");
889 char const credType[] =
"abcde";
894 Account const dillon(
"dillon");
899 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
901 auto const pk = alice.
pk();
902 auto const settleDelay = 100s;
903 auto const chan =
channel(alice, bob, env.seq(alice));
904 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
908 env(
fund(alice, chan,
XRP(1000)));
912 "D007AE4B6E1274B4AF872588267B810C2F82716726351D1C7D38D3E5499FC6"
915 auto const delta =
XRP(500).value();
921 .parentCloseTime.time_since_epoch()
924 jv[sfExpiration.jsonName] = t;
931 std::string const credIdx = jv[jss::result][jss::index].asString();
938 env(
claim(alice, chan, delta, delta),
947 env(
claim(alice, chan, delta, delta),
957 env(
claim(dillon, chan, delta, delta),
965 env(
claim(alice, chan, delta, delta),
970 env(
claim(alice, chan, delta, delta),
978 for (
int i = 0; i < 10; ++i)
981 env(
claim(alice, chan, delta, delta),
996 jv[jss::result][jss::index].asString();
999 env(
claim(alice, chan, delta, delta),
1006 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
1008 auto const pk = alice.
pk();
1009 auto const settleDelay = 100s;
1010 auto const chan =
channel(alice, bob, env.seq(alice));
1011 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1015 env(
fund(alice, chan,
XRP(1000)));
1018 auto const delta =
XRP(500).value();
1029 std::string const credIdx = jv[jss::result][jss::index].asString();
1039 env.
fund(
XRP(5000),
"alice",
"bob");
1042 auto const pk = alice.
pk();
1043 auto const settleDelay = 100s;
1044 auto const chan =
channel(alice, bob, env.
seq(alice));
1045 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1048 env(
fund(alice, chan,
XRP(1000)));
1051 "48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6EA288B"
1060 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
1070 testcase(
"Multiple channels to the same account");
1071 using namespace jtx;
1073 Env env{*
this, features};
1074 auto const alice =
Account(
"alice");
1075 auto const bob =
Account(
"bob");
1076 env.fund(
XRP(10000), alice, bob);
1077 auto const pk = alice.pk();
1078 auto const settleDelay = 3600s;
1079 auto const channelFunds =
XRP(1000);
1080 auto const chan1 =
channel(alice, bob, env.seq(alice));
1081 env(
create(alice, bob, channelFunds, settleDelay, pk));
1083 auto const chan2 =
channel(alice, bob, env.seq(alice));
1084 env(
create(alice, bob, channelFunds, settleDelay, pk));
1086 BEAST_EXPECT(chan1 != chan2);
1094 using namespace jtx;
1096 Env env{*
this, features};
1097 auto const alice =
Account(
"alice");
1098 auto const bob =
Account(
"bob");
1100 env.fund(
XRP(10000), alice, bob, charlie);
1101 auto const pk = alice.pk();
1102 auto const settleDelay = 3600s;
1103 auto const channelFunds =
XRP(1000);
1105 env(
create(alice, bob, channelFunds, settleDelay, pk));
1109 auto testInvalidAccountParam = [&](
auto const& param) {
1111 params[jss::account] = param;
1113 "json",
"account_channels",
to_string(params))[jss::result];
1114 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1116 jrr[jss::error_message] ==
"Invalid field 'account'.");
1119 testInvalidAccountParam(1);
1120 testInvalidAccountParam(1.1);
1121 testInvalidAccountParam(
true);
1128 env.rpc(
"account_channels", alice.human(), bob.human());
1129 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1131 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1132 BEAST_EXPECT(r[jss::result][jss::validated]);
1135 auto const r = env.rpc(
"account_channels", alice.human());
1136 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1138 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1139 BEAST_EXPECT(r[jss::result][jss::validated]);
1143 env.rpc(
"account_channels", bob.human(), alice.human());
1144 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1145 BEAST_EXPECT(r[jss::result][jss::validated]);
1148 env(
create(alice, bob, channelFunds, settleDelay, pk));
1152 env.rpc(
"account_channels", alice.human(), bob.human());
1153 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1154 BEAST_EXPECT(r[jss::result][jss::validated]);
1155 BEAST_EXPECT(chan1Str != chan2Str);
1156 for (
auto const& c : {chan1Str, chan2Str})
1158 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1159 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1166 testcase(
"Account channels RPC markers");
1168 using namespace test::jtx;
1171 auto const alice =
Account(
"alice");
1176 for (
int i = 0; i < n; ++i)
1183 Env env{*
this, features};
1184 env.fund(
XRP(10000), alice);
1185 for (
auto const& a : bobs)
1187 env.fund(
XRP(10000), a);
1193 auto const settleDelay = 3600s;
1194 auto const channelFunds =
XRP(1);
1195 for (
auto const& b : bobs)
1197 env(
create(alice, b, channelFunds, settleDelay, alice.pk()));
1208 jvc[jss::account] = src.human();
1210 jvc[jss::destination_account] = dst->human();
1212 jvc[jss::limit] = *limit;
1214 jvc[jss::marker] = marker;
1217 "json",
"account_channels",
to_string(jvc))[jss::result];
1222 auto const r = testLimit(env, alice);
1223 BEAST_EXPECT(r.isMember(jss::channels));
1224 BEAST_EXPECT(r[jss::channels].size() == bobs.size());
1229 for (
auto const& a : bobs)
1234 for (
int limit = 1; limit < bobs.size() + 1; ++limit)
1236 auto leftToFind = bobsB58;
1237 auto const numFull = bobs.
size() / limit;
1238 auto const numNonFull = bobs.size() % limit ? 1 : 0;
1242 auto const testIt = [&](
bool expectMarker,
int expectedBatchSize) {
1243 auto const r = testLimit(env, alice, limit, marker);
1244 BEAST_EXPECT(!expectMarker || r.isMember(jss::marker));
1245 if (r.isMember(jss::marker))
1246 marker = r[jss::marker];
1247 BEAST_EXPECT(r[jss::channels].size() == expectedBatchSize);
1248 auto const c = r[jss::channels];
1249 auto const s = r[jss::channels].size();
1250 for (
int j = 0; j < s; ++j)
1253 c[j][jss::destination_account].asString();
1254 BEAST_EXPECT(leftToFind.count(dstAcc));
1255 leftToFind.erase(dstAcc);
1259 for (
int i = 0; i < numFull; ++i)
1261 bool const expectMarker = (numNonFull != 0 || i < numFull - 1);
1262 testIt(expectMarker, limit);
1267 testIt(
false, bobs.size() % limit);
1269 BEAST_EXPECT(leftToFind.empty());
1274 auto const r = testLimit(env, alice, 0);
1275 BEAST_EXPECT(r.isMember(jss::error_message));
1284 testcase(
"Account channels RPC owner only");
1286 using namespace test::jtx;
1289 auto const alice =
Account(
"alice");
1290 auto const bob =
Account(
"bob");
1291 Env env{*
this, features};
1292 env.fund(
XRP(10000), alice, bob);
1297 auto const settleDelay = 3600s;
1298 auto const channelFunds =
XRP(1000);
1299 env(
create(alice, bob, channelFunds, settleDelay, alice.pk()));
1300 env(
create(bob, alice, channelFunds, settleDelay, bob.pk()));
1302 auto const r = [&] {
1304 jvc[jss::account] = alice.human();
1307 "json",
"account_channels",
to_string(jvc))[jss::result];
1309 BEAST_EXPECT(r.isMember(jss::channels));
1310 BEAST_EXPECT(r[jss::channels].size() == 1);
1312 r[jss::channels][0u][jss::destination_account].asString() ==
1319 using namespace jtx;
1322 Env env{*
this, features};
1323 auto const alice =
Account(
"alice");
1324 auto const bob =
Account(
"bob");
1326 env.fund(
XRP(10000), alice, bob, charlie);
1327 auto const pk = alice.pk();
1328 auto const settleDelay = 3600s;
1329 auto const channelFunds =
XRP(1000);
1331 env(
create(alice, bob, channelFunds, settleDelay, pk));
1335 args[jss::channel_id] = chan1Str;
1336 args[jss::key_type] =
"ed255191";
1337 args[jss::seed] =
"snHq1rzQoN2qiUkC3XF5RyxBzUtN";
1338 args[jss::amount] = 51110000;
1344 args[jss::api_version] = apiVersion;
1345 auto const rs = env.rpc(
1347 "channel_authorize",
1348 args.toStyledString())[jss::result];
1349 auto const error = apiVersion < 2u ?
"invalidParams" :
"badKeyType";
1350 BEAST_EXPECT(rs[jss::error] == error);
1357 testcase(
"PayChan Auth/Verify RPC");
1358 using namespace jtx;
1360 Env env{*
this, features};
1361 auto const alice =
Account(
"alice");
1362 auto const bob =
Account(
"bob");
1364 env.fund(
XRP(10000), alice, bob, charlie);
1365 auto const pk = alice.pk();
1366 auto const settleDelay = 3600s;
1367 auto const channelFunds =
XRP(1000);
1369 env(
create(alice, bob, channelFunds, settleDelay, pk));
1374 env.rpc(
"account_channels", alice.human(), bob.human());
1375 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1377 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1378 BEAST_EXPECT(r[jss::result][jss::validated]);
1380 r[jss::result][jss::channels][0u][jss::public_key].asString();
1383 auto const r = env.rpc(
"account_channels", alice.human());
1384 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1386 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1387 BEAST_EXPECT(r[jss::result][jss::validated]);
1389 r[jss::result][jss::channels][0u][jss::public_key].asString();
1393 env.rpc(
"account_channels", bob.human(), alice.human());
1394 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1395 BEAST_EXPECT(r[jss::result][jss::validated]);
1398 env(
create(alice, bob, channelFunds, settleDelay, pk));
1402 env.rpc(
"account_channels", alice.human(), bob.human());
1403 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1404 BEAST_EXPECT(r[jss::result][jss::validated]);
1405 BEAST_EXPECT(chan1Str != chan2Str);
1406 for (
auto const& c : {chan1Str, chan2Str})
1408 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1409 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1417 s +=
"0123456789ABCDEF"[((
slice[i] & 0xf0) >> 4)];
1418 s +=
"0123456789ABCDEF"[((
slice[i] & 0x0f) >> 0)];
1426 env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000");
1427 auto const sig = rs[jss::result][jss::signature].asString();
1428 BEAST_EXPECT(!
sig.empty());
1430 auto const rv = env.rpc(
1431 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1432 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1439 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1440 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1446 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000x",
sig);
1447 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1448 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 ",
sig);
1449 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1450 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x1000",
sig);
1451 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1452 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x",
sig);
1453 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1454 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" ",
sig);
1455 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1457 "channel_verify", pkAsHex, chan1Str,
"1000 1000",
sig);
1458 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1459 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1,000",
sig);
1460 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1461 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" 1000",
sig);
1462 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1463 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"",
sig);
1464 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1469 auto chan1StrBad = chan1Str;
1470 chan1StrBad.pop_back();
1472 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1473 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1474 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1475 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1477 chan1StrBad = chan1Str;
1478 chan1StrBad.push_back(
'0');
1480 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1481 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1482 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1483 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1485 chan1StrBad = chan1Str;
1486 chan1StrBad.back() =
'x';
1488 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1489 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1490 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1491 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1495 auto illFormedPk = chan1PkStr.
substr(0, chan1PkStr.
size() - 1);
1496 auto const rv = env.rpc(
1497 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1499 !rv[jss::result][jss::signature_verified].asBool());
1504 auto illFormedPk = pkAsHex.substr(0, chan1PkStr.
size() - 1);
1505 auto const rv = env.rpc(
1506 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1508 !rv[jss::result][jss::signature_verified].asBool());
1514 env.rpc(
"channel_authorize",
"alice", chan2Str,
"1000");
1515 auto const sig = rs[jss::result][jss::signature].asString();
1516 BEAST_EXPECT(!
sig.empty());
1518 auto const rv = env.rpc(
1519 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1521 !rv[jss::result][jss::signature_verified].asBool());
1527 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1529 !rv[jss::result][jss::signature_verified].asBool());
1537 charlie, alice, channelFunds, settleDelay, charlie.pk()));
1543 env.rpc(
"account_channels", charlie.human(), alice.human());
1544 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1546 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1547 BEAST_EXPECT(r[jss::result][jss::validated]);
1548 cpk = r[jss::result][jss::channels][0u][jss::public_key]
1554 env.rpc(
"channel_authorize",
"charlie", chan,
"1000");
1555 auto const sig = rs[jss::result][jss::signature].asString();
1556 BEAST_EXPECT(!
sig.empty());
1559 env.rpc(
"channel_verify", cpk, chan,
"1000",
sig);
1561 !rv[jss::result][jss::signature_verified].asBool());
1566 env.rpc(
"channel_authorize",
"charlie",
"nyx", chan,
"1000");
1567 BEAST_EXPECT(rs1[jss::error] ==
"badKeyType");
1571 auto const rs2 = env.rpc(
1572 "channel_authorize",
"charlie",
"secp256k1", chan,
"1000");
1573 auto const sig2 = rs2[jss::result][jss::signature].asString();
1574 BEAST_EXPECT(!sig2.empty());
1577 env.rpc(
"channel_verify", cpk, chan,
"1000", sig2);
1579 !rv[jss::result][jss::signature_verified].asBool());
1583 auto const rs3 = env.rpc(
1584 "channel_authorize",
"charlie",
"ed25519", chan,
"1000");
1585 auto const sig3 = rs3[jss::result][jss::signature].asString();
1586 BEAST_EXPECT(!sig3.empty());
1589 env.rpc(
"channel_verify", cpk, chan,
"1000", sig3);
1590 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1596 auto rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000x");
1597 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1598 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x1000");
1599 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1600 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x");
1601 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1605 args[jss::amount] =
"2000";
1606 args[jss::key_type] =
"secp256k1";
1607 args[jss::passphrase] =
"passphrase_can_be_anything";
1610 "channel_authorize",
1611 args.toStyledString())[jss::result];
1612 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1617 args[jss::channel_id] = chan1Str;
1618 args[jss::key_type] =
"secp256k1";
1619 args[jss::passphrase] =
"passphrase_can_be_anything";
1622 "channel_authorize",
1623 args.toStyledString())[jss::result];
1624 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1629 args[jss::amount] =
"2000";
1630 args[jss::channel_id] = chan1Str;
1631 args[jss::passphrase] =
"passphrase_can_be_anything";
1634 "channel_authorize",
1635 args.toStyledString())[jss::result];
1636 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1641 args[jss::amount] =
"2000";
1642 args[jss::channel_id] = chan1Str;
1643 args[jss::key_type] =
"secp256k1";
1644 args[jss::passphrase] =
"passphrase_can_be_anything";
1645 args[jss::seed] =
"seed can be anything";
1648 "channel_authorize",
1649 args.toStyledString())[jss::result];
1650 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1655 args[jss::amount] =
"2000";
1656 args[jss::channel_id] = chan1Str +
"1";
1657 args[jss::key_type] =
"secp256k1";
1658 args[jss::passphrase] =
"passphrase_can_be_anything";
1661 "channel_authorize",
1662 args.toStyledString())[jss::result];
1663 BEAST_EXPECT(rs[jss::error] ==
"channelMalformed");
1668 args[jss::amount] = 2000;
1669 args[jss::channel_id] = chan1Str;
1670 args[jss::key_type] =
"secp256k1";
1671 args[jss::passphrase] =
"passphrase_can_be_anything";
1674 "channel_authorize",
1675 args.toStyledString())[jss::result];
1676 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1681 args[jss::amount] =
"TwoThousand";
1682 args[jss::channel_id] = chan1Str;
1683 args[jss::key_type] =
"secp256k1";
1684 args[jss::passphrase] =
"passphrase_can_be_anything";
1687 "channel_authorize",
1688 args.toStyledString())[jss::result];
1689 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1698 using namespace jtx;
1700 Env env{*
this, features};
1701 auto const alice =
Account(
"alice");
1702 auto const bob =
Account(
"bob");
1703 auto const carol =
Account(
"carol");
1704 auto const dan =
Account(
"dan");
1705 env.fund(
XRP(10000), alice, bob, carol, dan);
1706 auto const pk = alice.pk();
1707 auto const settleDelay = 3600s;
1708 auto const channelFunds =
XRP(1000);
1714 env(
create(alice, bob, channelFunds, settleDelay, pk));
1716 env.rpc(
"account_channels", alice.human(), bob.human());
1717 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1719 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1720 BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember(
1721 jss::destination_tag));
1735 env.rpc(
"account_channels", alice.human(), carol.human());
1736 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1738 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1740 r[jss::result][jss::channels][0u][jss::destination_tag] ==
1749 using namespace jtx;
1751 Env env{*
this, features};
1752 auto const alice =
Account(
"alice");
1753 auto const bob =
Account(
"bob");
1754 auto USDA = alice[
"USD"];
1755 env.fund(
XRP(10000), alice, bob);
1756 auto const pk = alice.pk();
1757 auto const settleDelay = 100s;
1759 auto const chan =
channel(alice, bob, env.seq(alice));
1760 auto jv =
create(alice, bob,
XRP(1000), settleDelay, pk);
1761 auto const pkHex =
strHex(pk.slice());
1762 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1764 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1766 auto badPrefix = pkHex;
1769 jv[
"PublicKey"] = badPrefix;
1772 jv[
"PublicKey"] = pkHex;
1775 auto const authAmt =
XRP(100);
1784 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1786 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1791 jv[
"PublicKey"] = badPrefix;
1795 jv.removeMember(
"PublicKey");
1799 auto const txn = R
"*(
1802 "channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
1804 "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
1806 "aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
1810 auto const r = env.rpc(
"json",
"channel_verify", txn);
1811 BEAST_EXPECT(r[
"result"][
"error"] ==
"publicMalformed");
1820 using namespace jtx;
1823 auto const alice =
Account(
"alice");
1824 auto const bob =
Account(
"bob");
1825 auto const settleDelay = 100s;
1826 auto const pk = alice.pk();
1828 auto inOwnerDir = [](
ReadView const& view,
1832 return std::find(ownerDir.begin(), ownerDir.end(), chan) !=
1836 auto ownerDirCount = [](
ReadView const& view,
1845 Env env(*
this, features - fixPayChanRecipientOwnerDir);
1846 env.
fund(
XRP(10000), alice, bob);
1847 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1849 auto const [chan, chanSle] =
1851 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1852 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1853 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1854 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1855 if (features[fixIncludeKeyletFields])
1857 BEAST_EXPECT((*chanSle)[sfSequence] == env.
seq(alice) - 1);
1861 BEAST_EXPECT(!chanSle->isFieldPresent(sfSequence));
1866 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1867 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1868 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1869 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1874 Env env{*
this, features};
1875 env.fund(
XRP(10000), alice, bob);
1876 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1878 auto const [chan, chanSle] =
1880 BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle));
1881 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
1882 BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle));
1883 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 1);
1887 BEAST_EXPECT(!inOwnerDir(*env.current(), alice, chanSle));
1888 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 0);
1889 BEAST_EXPECT(!inOwnerDir(*env.current(), bob, chanSle));
1890 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 0);
1896 Env env(*
this, features - fixPayChanRecipientOwnerDir);
1897 env.
fund(
XRP(10000), alice, bob);
1899 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1901 auto const [chan, chanSle] =
1903 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1904 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1905 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1906 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1910 env.
current()->rules().enabled(fixPayChanRecipientOwnerDir));
1915 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1916 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1917 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1922 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1923 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1924 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1925 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1933 using namespace test::jtx;
1935 auto rmAccount = [
this](
1942 for (
auto minRmSeq = env.
seq(toRm) + 257;
1943 env.
current()->seq() < minRmSeq;
1957 auto const alice =
Account(
"alice");
1958 auto const bob =
Account(
"bob");
1959 auto const carol =
Account(
"carol");
1961 for (
bool const withOwnerDirFix : {
false,
true})
1963 auto const amd = withOwnerDirFix
1965 : features - fixPayChanRecipientOwnerDir;
1966 Env env{*
this, amd};
1967 env.
fund(
XRP(10000), alice, bob, carol);
1971 auto const pk = alice.pk();
1972 auto const settleDelay = 100s;
1973 auto const chan =
channel(alice, bob, env.
seq(alice));
1974 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1987 auto const feeDrops = env.
current()->fees().base;
1990 BEAST_EXPECT(chanBal ==
XRP(0));
1991 BEAST_EXPECT(chanAmt ==
XRP(1000));
1993 auto preBob = env.
balance(bob);
1994 auto const delta =
XRP(50);
1995 auto reqBal = chanBal + delta;
1996 auto authAmt = reqBal +
XRP(100);
1997 assert(reqBal <= chanAmt);
2000 if (withOwnerDirFix)
2002 env(
claim(alice, chan, reqBal, authAmt));
2006 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
2011 auto const preAlice = env.
balance(alice);
2016 BEAST_EXPECT(env.
balance(bob) == preBob);
2017 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2021 if (withOwnerDirFix)
2023 auto const preAlice = env.
balance(alice);
2024 env(
fund(alice, chan,
XRP(1000)));
2027 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
2030 chanAmt = chanAmt +
XRP(1000);
2034 auto const preAlice = env.
balance(alice);
2037 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2047 auto const closeTime = env.
current()->info().parentCloseTime;
2048 auto const minExpiration = closeTime + settleDelay;
2049 env.
close(minExpiration);
2057 Env env{*
this, features - fixPayChanRecipientOwnerDir};
2058 env.
fund(
XRP(10000), alice, bob, carol);
2062 auto const pk = alice.pk();
2063 auto const settleDelay = 100s;
2064 auto const chan =
channel(alice, bob, env.
seq(alice));
2065 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
2071 rmAccount(env, bob, carol);
2074 auto const feeDrops = env.
current()->fees().base;
2077 BEAST_EXPECT(chanBal ==
XRP(0));
2078 BEAST_EXPECT(chanAmt ==
XRP(1000));
2079 auto preBob = env.
balance(bob);
2080 auto const delta =
XRP(50);
2081 auto reqBal = chanBal + delta;
2082 auto authAmt = reqBal +
XRP(100);
2083 assert(reqBal <= chanAmt);
2087 auto const preAlice = env.
balance(alice);
2092 BEAST_EXPECT(env.
balance(bob) == preBob);
2093 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2098 auto const preAlice = env.
balance(alice);
2101 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2106 env(
pay(alice, bob,
XRP(20)));
2113 reqBal = chanBal + delta;
2114 authAmt = reqBal +
XRP(100);
2115 env(
claim(alice, chan, reqBal, authAmt));
2118 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
2125 reqBal = chanBal + delta;
2126 authAmt = reqBal +
XRP(100);
2129 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
2132 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
2138 auto const preAlice = env.
balance(alice);
2139 env(
fund(alice, chan,
XRP(1000)));
2141 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
2144 chanAmt = chanAmt +
XRP(1000);
2153 auto const closeTime = env.
current()->info().parentCloseTime;
2154 auto const minExpiration = closeTime + settleDelay;
2155 env.
close(minExpiration);
2166 using namespace jtx;
2168 Env env{*
this, features};
2169 auto const alice =
Account(
"alice");
2170 auto const bob =
Account(
"bob");
2171 auto USDA = alice[
"USD"];
2172 env.fund(
XRP(10000), alice, bob);
2185 auto const pk = alice.pk();
2186 auto const settleDelay = 100s;
2187 auto const chan =
channel(alice, bob, aliceTicketSeq);
2189 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
2192 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2193 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2199 auto const preAlice = env.balance(alice);
2202 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2203 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2205 auto const feeDrops = env.current()->fees().base;
2206 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
2211 BEAST_EXPECT(chanBal ==
XRP(0));
2212 BEAST_EXPECT(chanAmt ==
XRP(2000));
2216 auto const preBob = env.balance(bob);
2217 auto const delta =
XRP(500);
2218 auto const reqBal = chanBal + delta;
2219 auto const authAmt = reqBal +
XRP(100);
2220 assert(reqBal <= chanAmt);
2221 env(
claim(alice, chan, reqBal, authAmt),
2224 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2225 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2228 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2229 BEAST_EXPECT(env.balance(bob) == preBob + delta);
2234 auto preBob = env.balance(bob);
2235 auto const delta =
XRP(500);
2236 auto const reqBal = chanBal + delta;
2237 auto const authAmt = reqBal +
XRP(100);
2238 assert(reqBal <= chanAmt);
2241 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
2244 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2245 BEAST_EXPECT(env.seq(bob) == bobSeq);
2248 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2249 auto const feeDrops = env.current()->fees().base;
2250 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
2254 preBob = env.balance(bob);
2256 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
2260 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2261 BEAST_EXPECT(env.seq(bob) == bobSeq);
2264 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2265 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2269 auto const preBob = env.balance(bob);
2272 assert(reqAmt <= chanAmt);
2277 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
2281 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2282 BEAST_EXPECT(env.seq(bob) == bobSeq);
2285 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2286 BEAST_EXPECT(env.balance(bob) == preBob);
2290 env(
fund(bob, chan,
XRP(1000)),
2294 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2295 BEAST_EXPECT(env.seq(bob) == bobSeq);
2298 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2302 auto const preAlice = env.balance(alice);
2303 auto const preBob = env.balance(bob);
2304 env(
claim(bob, chan),
2308 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2309 BEAST_EXPECT(env.seq(bob) == bobSeq);
2312 auto const feeDrops = env.current()->fees().base;
2313 auto const delta = chanAmt - chanBal;
2314 assert(delta > beast::zero);
2315 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
2316 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2318 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2319 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2320 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2321 BEAST_EXPECT(env.seq(bob) == bobSeq);
2354 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)
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.
STAmount channelBalance(ReadView const &view, uint256 const &chan)
uint256 channel(AccountID const &account, AccountID const &dst, std::uint32_t seqProxyValue)
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 claim(AccountID const &account, uint256 const &channel, std::optional< STAmount > const &balance, std::optional< STAmount > const &amount, std::optional< Slice > const &signature, std::optional< PublicKey > const &pk)
Json::Value create(AccountID const &account, AccountID const &to, STAmount const &amount, NetClock::duration const &settleDelay, PublicKey const &pk, std::optional< NetClock::time_point > const &cancelAfter, std::optional< std::uint32_t > const &dstTag)
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.
bool channelExists(ReadView const &view, uint256 const &chan)
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)