22#include <xrpld/ledger/Dir.h>
23#include <xrpld/rpc/detail/RPCHelpers.h>
25#include <xrpl/basics/chrono.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])
88 using namespace std::literals::chrono_literals;
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);
272 uint32_t
flags = sle->getFlags();
276 using namespace std::literals::chrono_literals;
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),
347 using namespace std::literals::chrono_literals;
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);
412 using namespace std::literals::chrono_literals;
413 Env env{*
this, features};
414 auto const alice =
Account(
"alice");
415 auto const bob =
Account(
"bob");
416 auto const carol =
Account(
"carol");
417 env.fund(
XRP(10000), alice, bob, carol);
418 auto const pk = alice.pk();
419 auto const settleDelay = 3600s;
420 auto const closeTime = env.current()->info().parentCloseTime;
421 auto const minExpiration = closeTime + settleDelay;
423 auto const channelFunds =
XRP(1000);
424 auto const chan =
channel(alice, bob, env.seq(alice));
425 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
430 auto counts = [](
auto const& t) {
431 return t.time_since_epoch().count();
440 counts(minExpiration) + 100);
446 counts(minExpiration) + 50);
453 counts(minExpiration) + 50);
457 counts(minExpiration) + 50);
466 env.close(minExpiration);
478 using namespace std::literals::chrono_literals;
479 Env env{*
this, features};
480 auto const alice =
Account(
"alice");
481 auto const bob =
Account(
"bob");
482 env.fund(
XRP(10000), alice, bob);
483 auto const pk = alice.pk();
484 auto const settleDelay = 3600s;
486 env.current()->info().parentCloseTime + settleDelay;
487 auto const channelFunds =
XRP(1000);
488 auto const chan =
channel(alice, bob, env.seq(alice));
489 env(
create(alice, bob, channelFunds, settleDelay, pk));
494 env.close(settleTimepoint - settleDelay / 2);
499 auto preBob = env.balance(bob);
500 auto const delta =
XRP(500);
501 auto const reqBal = chanBal + delta;
502 auto const authAmt = reqBal +
XRP(100);
503 assert(reqBal <= chanAmt);
506 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
508 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
509 auto const feeDrops = env.current()->fees().base;
510 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
512 env.close(settleTimepoint);
517 auto const preAlice = env.balance(alice);
518 auto preBob = env.balance(bob);
519 auto const delta =
XRP(500);
520 auto const reqBal = chanBal + delta;
521 auto const authAmt = reqBal +
XRP(100);
522 assert(reqBal <= chanAmt);
525 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
527 auto const feeDrops = env.current()->fees().base;
528 BEAST_EXPECT(env.balance(alice) == preAlice + chanAmt - chanBal);
529 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
538 using namespace std::literals::chrono_literals;
539 Env env{*
this, features};
540 auto const alice =
Account(
"alice");
541 auto const bob =
Account(
"bob");
542 env.fund(
XRP(10000), alice, bob);
543 auto const pk = alice.pk();
544 auto const settleDelay = 3600s;
545 auto const channelFunds =
XRP(1000);
546 auto const chan =
channel(alice, bob, env.seq(alice));
547 env(
create(alice, bob, channelFunds, settleDelay, pk));
554 auto const preBob = env.balance(bob);
555 env(
claim(alice, chan, channelFunds.value(), channelFunds.value()));
556 BEAST_EXPECT(
channelBalance(*env.current(), chan) == channelFunds);
557 BEAST_EXPECT(env.balance(bob) == preBob + channelFunds);
559 auto const preAlice = env.balance(alice);
563 auto const feeDrops = env.current()->fees().base;
564 BEAST_EXPECT(env.balance(alice) == preAlice - feeDrops);
573 using namespace std::literals::chrono_literals;
574 Env env{*
this, features};
575 auto const alice =
Account(
"alice");
576 auto const bob =
Account(
"bob");
577 env.fund(
XRP(10000), alice, bob);
578 auto const pk = alice.pk();
579 auto const settleDelay = 3600s;
580 auto const channelFunds =
XRP(1000);
581 auto const chan =
channel(alice, bob, env.seq(alice));
582 env(
create(alice, bob, channelFunds, settleDelay, pk));
590 auto const preBob = env.balance(bob);
592 auto const delta =
XRP(500);
593 auto const reqBal = chanBal + delta;
594 assert(reqBal <= chanAmt);
597 env(
claim(bob, chan, reqBal, std::nullopt,
Slice(
sig), alice.pk()));
599 auto const feeDrops = env.current()->fees().base;
600 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
607 auto const preBob = env.balance(bob);
609 auto const delta =
XRP(500);
610 auto const reqBal = chanBal + delta;
611 assert(reqBal <= chanAmt);
614 env(
claim(bob, chan, reqBal, std::nullopt,
Slice(
sig), alice.pk()));
616 auto const feeDrops = env.current()->fees().base;
617 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
628 using namespace std::literals::chrono_literals;
630 auto const alice =
Account(
"alice");
631 auto const bob =
Account(
"bob");
634 Env env(*
this, features - featureDepositAuth);
635 env.
fund(
XRP(10000), alice, bob);
637 auto const chan =
channel(alice, bob, env.
seq(alice));
638 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()),
645 Env env{*
this, features};
646 env.fund(
XRP(10000), alice, bob);
648 auto const chan =
channel(alice, bob, env.seq(alice));
649 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
656 Env env(*
this, features - featureDepositAuth);
657 env.
fund(
XRP(10000), alice, bob);
658 auto const chan =
channel(alice, bob, env.
seq(alice));
659 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
663 auto const reqBal =
XRP(500).value();
670 Env env{*
this, features};
671 env.fund(
XRP(10000), alice, bob);
672 auto const chan =
channel(alice, bob, env.seq(alice));
673 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
677 auto const reqBal =
XRP(500).value();
678 env(
claim(alice, chan, reqBal, reqBal));
688 using namespace std::literals::chrono_literals;
690 Env env{*
this, features};
691 auto const alice =
Account(
"alice");
692 auto const bob =
Account(
"bob");
693 env.fund(
XRP(10000), alice, bob);
695 auto const pk = alice.pk();
696 auto const settleDelay = 3600s;
697 auto const channelFunds =
XRP(1000);
699 auto const chan =
channel(alice, bob, env.seq(alice));
700 env(
create(alice, bob, channelFunds, settleDelay, pk),
705 auto const chan =
channel(alice, bob, env.seq(alice));
707 alice, bob, channelFunds, settleDelay, pk, std::nullopt, 1));
717 using namespace std::literals::chrono_literals;
719 auto const alice =
Account(
"alice");
720 auto const bob =
Account(
"bob");
721 auto const carol =
Account(
"carol");
722 auto USDA = alice[
"USD"];
724 Env env{*
this, features};
725 env.fund(
XRP(10000), alice, bob, carol);
730 auto const pk = alice.pk();
731 auto const settleDelay = 100s;
732 auto const chan =
channel(alice, bob, env.seq(alice));
733 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
741 env(
fund(alice, chan,
XRP(1000)));
745 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
750 auto const baseFee = env.current()->fees().base;
751 auto const preBob = env.balance(bob);
753 auto const delta =
XRP(500).value();
761 BEAST_EXPECT(env.balance(bob) == preBob);
773 BEAST_EXPECT(env.balance(bob) == preBob + delta - baseFee);
777 auto const delta =
XRP(600).value();
809 env.balance(bob) == preBob + delta - (3 * baseFee));
814 auto const delta =
XRP(800).value();
828 env(
claim(alice, chan, delta, delta));
831 env.balance(bob) == preBob +
XRP(800) - (5 * baseFee));
839 testcase(
"Deposit Authorization with Credentials");
841 using namespace std::literals::chrono_literals;
843 const char credType[] =
"abcde";
848 Account const dillon(
"dillon");
853 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
855 auto const pk = alice.
pk();
856 auto const settleDelay = 100s;
857 auto const chan =
channel(alice, bob, env.seq(alice));
858 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
862 env(
fund(alice, chan,
XRP(1000)));
866 "D007AE4B6E1274B4AF872588267B810C2F82716726351D1C7D38D3E5499FC6"
869 auto const delta =
XRP(500).value();
873 uint32_t
const t = env.current()
875 .parentCloseTime.time_since_epoch()
878 jv[sfExpiration.jsonName] = t;
885 std::string const credIdx = jv[jss::result][jss::index].asString();
892 env(
claim(alice, chan, delta, delta),
901 env(
claim(alice, chan, delta, delta),
911 env(
claim(dillon, chan, delta, delta),
919 env(
claim(alice, chan, delta, delta),
924 env(
claim(alice, chan, delta, delta),
932 for (
int i = 0; i < 10; ++i)
935 env(
claim(alice, chan, delta, delta),
950 jv[jss::result][jss::index].asString();
953 env(
claim(alice, chan, delta, delta),
960 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
962 auto const pk = alice.
pk();
963 auto const settleDelay = 100s;
964 auto const chan =
channel(alice, bob, env.seq(alice));
965 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
969 env(
fund(alice, chan,
XRP(1000)));
972 auto const delta =
XRP(500).value();
983 std::string const credIdx = jv[jss::result][jss::index].asString();
993 env.
fund(
XRP(5000),
"alice",
"bob");
996 auto const pk = alice.
pk();
997 auto const settleDelay = 100s;
998 auto const chan =
channel(alice, bob, env.
seq(alice));
999 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1002 env(
fund(alice, chan,
XRP(1000)));
1005 "48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6EA288B"
1014 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
1024 testcase(
"Multiple channels to the same account");
1025 using namespace jtx;
1026 using namespace std::literals::chrono_literals;
1027 Env env{*
this, features};
1028 auto const alice =
Account(
"alice");
1029 auto const bob =
Account(
"bob");
1030 env.fund(
XRP(10000), alice, bob);
1031 auto const pk = alice.pk();
1032 auto const settleDelay = 3600s;
1033 auto const channelFunds =
XRP(1000);
1034 auto const chan1 =
channel(alice, bob, env.seq(alice));
1035 env(
create(alice, bob, channelFunds, settleDelay, pk));
1037 auto const chan2 =
channel(alice, bob, env.seq(alice));
1038 env(
create(alice, bob, channelFunds, settleDelay, pk));
1040 BEAST_EXPECT(chan1 != chan2);
1048 using namespace jtx;
1049 using namespace std::literals::chrono_literals;
1050 Env env{*
this, features};
1051 auto const alice =
Account(
"alice");
1052 auto const bob =
Account(
"bob");
1054 env.fund(
XRP(10000), alice, bob, charlie);
1055 auto const pk = alice.pk();
1056 auto const settleDelay = 3600s;
1057 auto const channelFunds =
XRP(1000);
1059 env(
create(alice, bob, channelFunds, settleDelay, pk));
1063 auto testInvalidAccountParam = [&](
auto const& param) {
1065 params[jss::account] = param;
1067 "json",
"account_channels",
to_string(params))[jss::result];
1068 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1070 jrr[jss::error_message] ==
"Invalid field 'account'.");
1073 testInvalidAccountParam(1);
1074 testInvalidAccountParam(1.1);
1075 testInvalidAccountParam(
true);
1082 env.rpc(
"account_channels", alice.human(), bob.human());
1083 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1085 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1086 BEAST_EXPECT(r[jss::result][jss::validated]);
1089 auto const r = env.rpc(
"account_channels", alice.human());
1090 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1092 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1093 BEAST_EXPECT(r[jss::result][jss::validated]);
1097 env.rpc(
"account_channels", bob.human(), alice.human());
1098 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1099 BEAST_EXPECT(r[jss::result][jss::validated]);
1102 env(
create(alice, bob, channelFunds, settleDelay, pk));
1106 env.rpc(
"account_channels", alice.human(), bob.human());
1107 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1108 BEAST_EXPECT(r[jss::result][jss::validated]);
1109 BEAST_EXPECT(chan1Str != chan2Str);
1110 for (
auto const& c : {chan1Str, chan2Str})
1112 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1113 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1120 testcase(
"Account channels RPC markers");
1122 using namespace test::jtx;
1123 using namespace std::literals;
1125 auto const alice =
Account(
"alice");
1130 for (
int i = 0; i < n; ++i)
1137 Env env{*
this, features};
1138 env.fund(
XRP(10000), alice);
1139 for (
auto const& a : bobs)
1141 env.fund(
XRP(10000), a);
1147 auto const settleDelay = 3600s;
1148 auto const channelFunds =
XRP(1);
1149 for (
auto const& b : bobs)
1151 env(
create(alice, b, channelFunds, settleDelay, alice.pk()));
1162 jvc[jss::account] = src.human();
1164 jvc[jss::destination_account] = dst->human();
1166 jvc[jss::limit] = *limit;
1168 jvc[jss::marker] = marker;
1171 "json",
"account_channels",
to_string(jvc))[jss::result];
1176 auto const r = testLimit(env, alice);
1177 BEAST_EXPECT(r.isMember(jss::channels));
1178 BEAST_EXPECT(r[jss::channels].size() == bobs.size());
1183 for (
auto const& a : bobs)
1188 for (
int limit = 1; limit < bobs.size() + 1; ++limit)
1190 auto leftToFind = bobsB58;
1191 auto const numFull = bobs.
size() / limit;
1192 auto const numNonFull = bobs.size() % limit ? 1 : 0;
1196 auto const testIt = [&](
bool expectMarker,
int expectedBatchSize) {
1197 auto const r = testLimit(env, alice, limit, marker);
1198 BEAST_EXPECT(!expectMarker || r.isMember(jss::marker));
1199 if (r.isMember(jss::marker))
1200 marker = r[jss::marker];
1201 BEAST_EXPECT(r[jss::channels].size() == expectedBatchSize);
1202 auto const c = r[jss::channels];
1203 auto const s = r[jss::channels].size();
1204 for (
int j = 0; j < s; ++j)
1207 c[j][jss::destination_account].asString();
1208 BEAST_EXPECT(leftToFind.count(dstAcc));
1209 leftToFind.erase(dstAcc);
1213 for (
int i = 0; i < numFull; ++i)
1215 bool const expectMarker = (numNonFull != 0 || i < numFull - 1);
1216 testIt(expectMarker, limit);
1221 testIt(
false, bobs.size() % limit);
1223 BEAST_EXPECT(leftToFind.empty());
1228 auto const r = testLimit(env, alice, 0);
1229 BEAST_EXPECT(r.isMember(jss::error_message));
1238 testcase(
"Account channels RPC owner only");
1240 using namespace test::jtx;
1241 using namespace std::literals;
1243 auto const alice =
Account(
"alice");
1244 auto const bob =
Account(
"bob");
1245 Env env{*
this, features};
1246 env.fund(
XRP(10000), alice, bob);
1251 auto const settleDelay = 3600s;
1252 auto const channelFunds =
XRP(1000);
1253 env(
create(alice, bob, channelFunds, settleDelay, alice.pk()));
1254 env(
create(bob, alice, channelFunds, settleDelay, bob.pk()));
1256 auto const r = [&] {
1258 jvc[jss::account] = alice.human();
1261 "json",
"account_channels",
to_string(jvc))[jss::result];
1263 BEAST_EXPECT(r.isMember(jss::channels));
1264 BEAST_EXPECT(r[jss::channels].size() == 1);
1266 r[jss::channels][0u][jss::destination_account].asString() ==
1273 using namespace jtx;
1274 using namespace std::literals::chrono_literals;
1276 Env env{*
this, features};
1277 auto const alice =
Account(
"alice");
1278 auto const bob =
Account(
"bob");
1280 env.fund(
XRP(10000), alice, bob, charlie);
1281 auto const pk = alice.pk();
1282 auto const settleDelay = 3600s;
1283 auto const channelFunds =
XRP(1000);
1285 env(
create(alice, bob, channelFunds, settleDelay, pk));
1289 args[jss::channel_id] = chan1Str;
1290 args[jss::key_type] =
"ed255191";
1291 args[jss::seed] =
"snHq1rzQoN2qiUkC3XF5RyxBzUtN";
1292 args[jss::amount] = 51110000;
1298 args[jss::api_version] = apiVersion;
1299 auto const rs = env.rpc(
1301 "channel_authorize",
1302 args.toStyledString())[jss::result];
1303 auto const error = apiVersion < 2u ?
"invalidParams" :
"badKeyType";
1304 BEAST_EXPECT(rs[jss::error] == error);
1311 testcase(
"PayChan Auth/Verify RPC");
1312 using namespace jtx;
1313 using namespace std::literals::chrono_literals;
1314 Env env{*
this, features};
1315 auto const alice =
Account(
"alice");
1316 auto const bob =
Account(
"bob");
1318 env.fund(
XRP(10000), alice, bob, charlie);
1319 auto const pk = alice.pk();
1320 auto const settleDelay = 3600s;
1321 auto const channelFunds =
XRP(1000);
1323 env(
create(alice, bob, channelFunds, settleDelay, pk));
1328 env.rpc(
"account_channels", alice.human(), bob.human());
1329 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1331 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1332 BEAST_EXPECT(r[jss::result][jss::validated]);
1334 r[jss::result][jss::channels][0u][jss::public_key].asString();
1337 auto const r = env.rpc(
"account_channels", alice.human());
1338 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1340 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1341 BEAST_EXPECT(r[jss::result][jss::validated]);
1343 r[jss::result][jss::channels][0u][jss::public_key].asString();
1347 env.rpc(
"account_channels", bob.human(), alice.human());
1348 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1349 BEAST_EXPECT(r[jss::result][jss::validated]);
1352 env(
create(alice, bob, channelFunds, settleDelay, pk));
1356 env.rpc(
"account_channels", alice.human(), bob.human());
1357 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1358 BEAST_EXPECT(r[jss::result][jss::validated]);
1359 BEAST_EXPECT(chan1Str != chan2Str);
1360 for (
auto const& c : {chan1Str, chan2Str})
1362 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1363 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1369 for (
int i = 0; i < slice.size(); ++i)
1371 s +=
"0123456789ABCDEF"[((slice[i] & 0xf0) >> 4)];
1372 s +=
"0123456789ABCDEF"[((slice[i] & 0x0f) >> 0)];
1380 env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000");
1381 auto const sig = rs[jss::result][jss::signature].asString();
1382 BEAST_EXPECT(!
sig.empty());
1384 auto const rv = env.rpc(
1385 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1386 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1393 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1394 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1400 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000x",
sig);
1401 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1402 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 ",
sig);
1403 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1404 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x1000",
sig);
1405 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1406 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x",
sig);
1407 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1408 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" ",
sig);
1409 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1411 "channel_verify", pkAsHex, chan1Str,
"1000 1000",
sig);
1412 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1413 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1,000",
sig);
1414 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1415 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" 1000",
sig);
1416 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1417 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"",
sig);
1418 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1423 auto chan1StrBad = chan1Str;
1424 chan1StrBad.pop_back();
1426 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1427 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1428 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1429 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1431 chan1StrBad = chan1Str;
1432 chan1StrBad.push_back(
'0');
1434 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1435 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1436 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1437 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1439 chan1StrBad = chan1Str;
1440 chan1StrBad.back() =
'x';
1442 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1443 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1444 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1445 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1449 auto illFormedPk = chan1PkStr.
substr(0, chan1PkStr.
size() - 1);
1450 auto const rv = env.rpc(
1451 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1453 !rv[jss::result][jss::signature_verified].asBool());
1458 auto illFormedPk = pkAsHex.substr(0, chan1PkStr.
size() - 1);
1459 auto const rv = env.rpc(
1460 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1462 !rv[jss::result][jss::signature_verified].asBool());
1468 env.rpc(
"channel_authorize",
"alice", chan2Str,
"1000");
1469 auto const sig = rs[jss::result][jss::signature].asString();
1470 BEAST_EXPECT(!
sig.empty());
1472 auto const rv = env.rpc(
1473 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1475 !rv[jss::result][jss::signature_verified].asBool());
1481 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1483 !rv[jss::result][jss::signature_verified].asBool());
1491 charlie, alice, channelFunds, settleDelay, charlie.pk()));
1497 env.rpc(
"account_channels", charlie.human(), alice.human());
1498 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1500 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1501 BEAST_EXPECT(r[jss::result][jss::validated]);
1502 cpk = r[jss::result][jss::channels][0u][jss::public_key]
1508 env.rpc(
"channel_authorize",
"charlie", chan,
"1000");
1509 auto const sig = rs[jss::result][jss::signature].asString();
1510 BEAST_EXPECT(!
sig.empty());
1513 env.rpc(
"channel_verify", cpk, chan,
"1000",
sig);
1515 !rv[jss::result][jss::signature_verified].asBool());
1520 env.rpc(
"channel_authorize",
"charlie",
"nyx", chan,
"1000");
1521 BEAST_EXPECT(rs1[jss::error] ==
"badKeyType");
1525 auto const rs2 = env.rpc(
1526 "channel_authorize",
"charlie",
"secp256k1", chan,
"1000");
1527 auto const sig2 = rs2[jss::result][jss::signature].asString();
1528 BEAST_EXPECT(!sig2.empty());
1531 env.rpc(
"channel_verify", cpk, chan,
"1000", sig2);
1533 !rv[jss::result][jss::signature_verified].asBool());
1537 auto const rs3 = env.rpc(
1538 "channel_authorize",
"charlie",
"ed25519", chan,
"1000");
1539 auto const sig3 = rs3[jss::result][jss::signature].asString();
1540 BEAST_EXPECT(!sig3.empty());
1543 env.rpc(
"channel_verify", cpk, chan,
"1000", sig3);
1544 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1550 auto rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000x");
1551 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1552 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x1000");
1553 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1554 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x");
1555 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1559 args[jss::amount] =
"2000";
1560 args[jss::key_type] =
"secp256k1";
1561 args[jss::passphrase] =
"passphrase_can_be_anything";
1564 "channel_authorize",
1565 args.toStyledString())[jss::result];
1566 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1571 args[jss::channel_id] = chan1Str;
1572 args[jss::key_type] =
"secp256k1";
1573 args[jss::passphrase] =
"passphrase_can_be_anything";
1576 "channel_authorize",
1577 args.toStyledString())[jss::result];
1578 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1583 args[jss::amount] =
"2000";
1584 args[jss::channel_id] = chan1Str;
1585 args[jss::passphrase] =
"passphrase_can_be_anything";
1588 "channel_authorize",
1589 args.toStyledString())[jss::result];
1590 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1595 args[jss::amount] =
"2000";
1596 args[jss::channel_id] = chan1Str;
1597 args[jss::key_type] =
"secp256k1";
1598 args[jss::passphrase] =
"passphrase_can_be_anything";
1599 args[jss::seed] =
"seed can be anything";
1602 "channel_authorize",
1603 args.toStyledString())[jss::result];
1604 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1609 args[jss::amount] =
"2000";
1610 args[jss::channel_id] = chan1Str +
"1";
1611 args[jss::key_type] =
"secp256k1";
1612 args[jss::passphrase] =
"passphrase_can_be_anything";
1615 "channel_authorize",
1616 args.toStyledString())[jss::result];
1617 BEAST_EXPECT(rs[jss::error] ==
"channelMalformed");
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";
1628 "channel_authorize",
1629 args.toStyledString())[jss::result];
1630 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1635 args[jss::amount] =
"TwoThousand";
1636 args[jss::channel_id] = chan1Str;
1637 args[jss::key_type] =
"secp256k1";
1638 args[jss::passphrase] =
"passphrase_can_be_anything";
1641 "channel_authorize",
1642 args.toStyledString())[jss::result];
1643 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1652 using namespace jtx;
1653 using namespace std::literals::chrono_literals;
1654 Env env{*
this, features};
1655 auto const alice =
Account(
"alice");
1656 auto const bob =
Account(
"bob");
1657 auto const carol =
Account(
"carol");
1658 auto const dan =
Account(
"dan");
1659 env.fund(
XRP(10000), alice, bob, carol, dan);
1660 auto const pk = alice.pk();
1661 auto const settleDelay = 3600s;
1662 auto const channelFunds =
XRP(1000);
1668 env(
create(alice, bob, channelFunds, settleDelay, pk));
1670 env.rpc(
"account_channels", alice.human(), bob.human());
1671 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1673 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1674 BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember(
1675 jss::destination_tag));
1689 env.rpc(
"account_channels", alice.human(), carol.human());
1690 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1692 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1694 r[jss::result][jss::channels][0u][jss::destination_tag] ==
1703 using namespace jtx;
1704 using namespace std::literals::chrono_literals;
1705 Env env{*
this, features};
1706 auto const alice =
Account(
"alice");
1707 auto const bob =
Account(
"bob");
1708 auto USDA = alice[
"USD"];
1709 env.fund(
XRP(10000), alice, bob);
1710 auto const pk = alice.pk();
1711 auto const settleDelay = 100s;
1713 auto const chan =
channel(alice, bob, env.seq(alice));
1714 auto jv =
create(alice, bob,
XRP(1000), settleDelay, pk);
1715 auto const pkHex =
strHex(pk.slice());
1716 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1718 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1720 auto badPrefix = pkHex;
1723 jv[
"PublicKey"] = badPrefix;
1726 jv[
"PublicKey"] = pkHex;
1729 auto const authAmt =
XRP(100);
1738 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1740 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1745 jv[
"PublicKey"] = badPrefix;
1749 jv.removeMember(
"PublicKey");
1753 auto const txn = R
"*(
1756 "channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
1758 "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
1760 "aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
1764 auto const r = env.rpc(
"json",
"channel_verify", txn);
1765 BEAST_EXPECT(r[
"result"][
"error"] ==
"publicMalformed");
1774 using namespace jtx;
1775 using namespace std::literals::chrono_literals;
1777 auto const alice =
Account(
"alice");
1778 auto const bob =
Account(
"bob");
1779 auto const settleDelay = 100s;
1780 auto const pk = alice.pk();
1782 auto inOwnerDir = [](
ReadView const& view,
1786 return std::find(ownerDir.begin(), ownerDir.end(), chan) !=
1790 auto ownerDirCount = [](
ReadView const& view,
1799 Env env(*
this, features - fixPayChanRecipientOwnerDir);
1800 env.
fund(
XRP(10000), alice, bob);
1801 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1803 auto const [chan, chanSle] =
1805 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1806 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1807 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1808 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1812 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1813 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1814 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1815 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1820 Env env{*
this, features};
1821 env.fund(
XRP(10000), alice, bob);
1822 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1824 auto const [chan, chanSle] =
1826 BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle));
1827 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
1828 BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle));
1829 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 1);
1833 BEAST_EXPECT(!inOwnerDir(*env.current(), alice, chanSle));
1834 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 0);
1835 BEAST_EXPECT(!inOwnerDir(*env.current(), bob, chanSle));
1836 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 0);
1842 Env env(*
this, features - fixPayChanRecipientOwnerDir);
1843 env.
fund(
XRP(10000), alice, bob);
1845 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1847 auto const [chan, chanSle] =
1849 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1850 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1851 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1852 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1856 env.
current()->rules().enabled(fixPayChanRecipientOwnerDir));
1861 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1862 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1863 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
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);
1879 using namespace test::jtx;
1880 using namespace std::literals::chrono_literals;
1881 auto rmAccount = [
this](
1888 for (
auto minRmSeq = env.
seq(toRm) + 257;
1889 env.
current()->seq() < minRmSeq;
1903 auto const alice =
Account(
"alice");
1904 auto const bob =
Account(
"bob");
1905 auto const carol =
Account(
"carol");
1907 for (
bool const withOwnerDirFix : {
false,
true})
1909 auto const amd = withOwnerDirFix
1911 : features - fixPayChanRecipientOwnerDir;
1912 Env env{*
this, amd};
1913 env.
fund(
XRP(10000), alice, bob, carol);
1917 auto const pk = alice.pk();
1918 auto const settleDelay = 100s;
1919 auto const chan =
channel(alice, bob, env.
seq(alice));
1920 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1933 auto const feeDrops = env.
current()->fees().base;
1936 BEAST_EXPECT(chanBal ==
XRP(0));
1937 BEAST_EXPECT(chanAmt ==
XRP(1000));
1939 auto preBob = env.
balance(bob);
1940 auto const delta =
XRP(50);
1941 auto reqBal = chanBal + delta;
1942 auto authAmt = reqBal +
XRP(100);
1943 assert(reqBal <= chanAmt);
1946 if (withOwnerDirFix)
1948 env(
claim(alice, chan, reqBal, authAmt));
1952 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1957 auto const preAlice = env.
balance(alice);
1962 BEAST_EXPECT(env.
balance(bob) == preBob);
1963 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1967 if (withOwnerDirFix)
1969 auto const preAlice = env.
balance(alice);
1970 env(
fund(alice, chan,
XRP(1000)));
1973 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1976 chanAmt = chanAmt +
XRP(1000);
1980 auto const preAlice = env.
balance(alice);
1983 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1993 auto const closeTime = env.
current()->info().parentCloseTime;
1994 auto const minExpiration = closeTime + settleDelay;
1995 env.
close(minExpiration);
2003 Env env{*
this, features - fixPayChanRecipientOwnerDir};
2004 env.
fund(
XRP(10000), alice, bob, carol);
2008 auto const pk = alice.pk();
2009 auto const settleDelay = 100s;
2010 auto const chan =
channel(alice, bob, env.
seq(alice));
2011 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
2017 rmAccount(env, bob, carol);
2020 auto const feeDrops = env.
current()->fees().base;
2023 BEAST_EXPECT(chanBal ==
XRP(0));
2024 BEAST_EXPECT(chanAmt ==
XRP(1000));
2025 auto preBob = env.
balance(bob);
2026 auto const delta =
XRP(50);
2027 auto reqBal = chanBal + delta;
2028 auto authAmt = reqBal +
XRP(100);
2029 assert(reqBal <= chanAmt);
2033 auto const preAlice = env.
balance(alice);
2038 BEAST_EXPECT(env.
balance(bob) == preBob);
2039 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2044 auto const preAlice = env.
balance(alice);
2047 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2052 env(
pay(alice, bob,
XRP(20)));
2059 reqBal = chanBal + delta;
2060 authAmt = reqBal +
XRP(100);
2061 env(
claim(alice, chan, reqBal, authAmt));
2064 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
2071 reqBal = chanBal + delta;
2072 authAmt = reqBal +
XRP(100);
2075 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
2078 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
2084 auto const preAlice = env.
balance(alice);
2085 env(
fund(alice, chan,
XRP(1000)));
2087 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
2090 chanAmt = chanAmt +
XRP(1000);
2099 auto const closeTime = env.
current()->info().parentCloseTime;
2100 auto const minExpiration = closeTime + settleDelay;
2101 env.
close(minExpiration);
2112 using namespace jtx;
2113 using namespace std::literals::chrono_literals;
2114 Env env{*
this, features};
2115 auto const alice =
Account(
"alice");
2116 auto const bob =
Account(
"bob");
2117 auto USDA = alice[
"USD"];
2118 env.fund(
XRP(10000), alice, bob);
2131 auto const pk = alice.pk();
2132 auto const settleDelay = 100s;
2133 auto const chan =
channel(alice, bob, aliceTicketSeq);
2135 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
2138 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2139 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2145 auto const preAlice = env.balance(alice);
2148 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2149 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2151 auto const feeDrops = env.current()->fees().base;
2152 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
2157 BEAST_EXPECT(chanBal ==
XRP(0));
2158 BEAST_EXPECT(chanAmt ==
XRP(2000));
2162 auto const preBob = env.balance(bob);
2163 auto const delta =
XRP(500);
2164 auto const reqBal = chanBal + delta;
2165 auto const authAmt = reqBal +
XRP(100);
2166 assert(reqBal <= chanAmt);
2167 env(
claim(alice, chan, reqBal, authAmt),
2170 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2171 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2174 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2175 BEAST_EXPECT(env.balance(bob) == preBob + delta);
2180 auto preBob = env.balance(bob);
2181 auto const delta =
XRP(500);
2182 auto const reqBal = chanBal + delta;
2183 auto const authAmt = reqBal +
XRP(100);
2184 assert(reqBal <= chanAmt);
2187 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
2190 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2191 BEAST_EXPECT(env.seq(bob) == bobSeq);
2194 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2195 auto const feeDrops = env.current()->fees().base;
2196 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
2200 preBob = env.balance(bob);
2202 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
2206 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2207 BEAST_EXPECT(env.seq(bob) == bobSeq);
2210 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2211 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2215 auto const preBob = env.balance(bob);
2218 assert(reqAmt <= chanAmt);
2223 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
2227 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2228 BEAST_EXPECT(env.seq(bob) == bobSeq);
2231 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2232 BEAST_EXPECT(env.balance(bob) == preBob);
2236 env(
fund(bob, chan,
XRP(1000)),
2240 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2241 BEAST_EXPECT(env.seq(bob) == bobSeq);
2244 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2248 auto const preAlice = env.balance(alice);
2249 auto const preBob = env.balance(bob);
2250 env(
claim(bob, chan),
2254 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2255 BEAST_EXPECT(env.seq(bob) == bobSeq);
2258 auto const feeDrops = env.current()->fees().base;
2259 auto const delta = chanAmt - chanBal;
2260 assert(delta > beast::zero);
2261 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
2262 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2264 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2265 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2266 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2267 BEAST_EXPECT(env.seq(bob) == bobSeq);
2300 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)
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)
FeatureBitset supported_amendments()
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)
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)