21#include <xrpld/ledger/Dir.h>
22#include <xrpld/rpc/detail/RPCHelpers.h>
23#include <xrpl/basics/chrono.h>
24#include <xrpl/protocol/Feature.h>
25#include <xrpl/protocol/Indexes.h>
26#include <xrpl/protocol/PayChan.h>
27#include <xrpl/protocol/TxFlags.h>
28#include <xrpl/protocol/jss.h>
46 return {k.key, view.
read(k)};
64 auto const slep = view.
read({ltPAYCHAN, chan});
67 return (*slep)[sfAmount];
73 auto const slep = view.
read({ltPAYCHAN, chan});
76 if (
auto const r = (*slep)[~sfExpiration])
86 using namespace std::literals::chrono_literals;
87 Env env{*
this, features};
88 auto const alice =
Account(
"alice");
89 auto const bob =
Account(
"bob");
90 auto USDA = alice[
"USD"];
91 env.fund(
XRP(10000), alice, bob);
92 auto const pk = alice.pk();
93 auto const settleDelay = 100s;
94 auto const chan =
channel(alice, bob, env.seq(alice));
95 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
100 auto const preAlice = env.balance(alice);
101 env(
fund(alice, chan,
XRP(1000)));
102 auto const feeDrops = env.current()->fees().base;
103 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
108 BEAST_EXPECT(chanBal ==
XRP(0));
109 BEAST_EXPECT(chanAmt ==
XRP(2000));
113 env(
create(alice, bob, USDA(1000), settleDelay, pk),
116 env(
create(alice, bob,
XRP(-1000), settleDelay, pk),
122 env(
create(alice,
"noAccount",
XRP(1000), settleDelay, pk),
125 env(
create(alice, alice,
XRP(1000), settleDelay, pk),
131 channel(alice,
"noAccount", env.seq(alice) - 1),
139 auto const iou = USDA(100).value();
140 auto const negXRP =
XRP(-100).value();
141 auto const posXRP =
XRP(100).value();
151 auto const delta =
XRP(500);
152 auto const reqBal = chanBal + delta;
153 auto const authAmt = reqBal +
XRP(-100);
154 assert(reqBal <= chanAmt);
159 auto const preBob = env.balance(bob);
160 auto const delta =
XRP(500);
161 auto const reqBal = chanBal + delta;
162 auto const authAmt = reqBal +
XRP(100);
163 assert(reqBal <= chanAmt);
164 env(
claim(alice, chan, reqBal, authAmt));
166 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
167 BEAST_EXPECT(env.balance(bob) == preBob + delta);
172 auto preBob = env.balance(bob);
173 auto const delta =
XRP(500);
174 auto const reqBal = chanBal + delta;
175 auto const authAmt = reqBal +
XRP(100);
176 assert(reqBal <= chanAmt);
179 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
181 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
182 auto const feeDrops = env.current()->fees().base;
183 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
187 preBob = env.balance(bob);
188 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
191 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
192 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
196 auto const preBob = env.balance(bob);
199 assert(reqAmt <= chanAmt);
202 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
205 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
206 BEAST_EXPECT(env.balance(bob) == preBob);
212 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
226 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
240 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
244 auto const preAlice = env.balance(alice);
245 auto const preBob = env.balance(bob);
248 auto const feeDrops = env.current()->fees().base;
249 auto const delta = chanAmt - chanBal;
250 assert(delta > beast::zero);
251 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
252 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
266 env.fund(
XRP(10000), alice);
269 auto const sle = env.le(alice);
270 uint32_t
flags = sle->getFlags();
274 using namespace std::literals::chrono_literals;
276 auto const alice =
Account(
"alice");
277 auto const bob =
Account(
"bob");
278 auto const cho =
Account(
"cho");
279 env.fund(
XRP(10000), alice, bob, cho);
280 auto const pk = alice.pk();
281 auto const settleDelay = 100s;
289 auto const chan =
channel(alice, bob, env.seq(alice));
290 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
301 auto const chan =
channel(bob, alice, env.seq(bob));
302 env(
create(bob, alice,
XRP(1000), settleDelay, pk),
313 auto const chan =
channel(alice, bob, env.seq(alice));
314 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
321 auto const chan =
channel(cho, alice, env.seq(cho));
322 env(
create(cho, alice,
XRP(1000), settleDelay, pk),
333 auto const chan =
channel(cho, alice, env.seq(cho));
334 env(
create(cho, alice,
XRP(1000), settleDelay, pk),
345 using namespace std::literals::chrono_literals;
346 auto const alice =
Account(
"alice");
347 auto const bob =
Account(
"bob");
348 auto const carol =
Account(
"carol");
351 Env env{*
this, features};
352 env.fund(
XRP(10000), alice, bob);
353 auto const pk = alice.pk();
354 auto const settleDelay = 100s;
356 env.current()->info().parentCloseTime + 3600s;
357 auto const channelFunds =
XRP(1000);
358 auto const chan =
channel(alice, bob, env.seq(alice));
359 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
361 env.close(cancelAfter);
366 auto preAlice = env.balance(alice);
367 auto preBob = env.balance(bob);
368 auto const delta =
XRP(500);
369 auto const reqBal = chanBal + delta;
370 auto const authAmt = reqBal +
XRP(100);
371 assert(reqBal <= chanAmt);
374 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
375 auto const feeDrops = env.current()->fees().base;
377 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
378 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
383 Env env{*
this, features};
384 env.fund(
XRP(10000), alice, bob, carol);
385 auto const pk = alice.pk();
386 auto const settleDelay = 100s;
388 env.current()->info().parentCloseTime + 3600s;
389 auto const channelFunds =
XRP(1000);
390 auto const chan =
channel(alice, bob, env.seq(alice));
391 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
396 env.close(cancelAfter);
398 auto const preAlice = env.balance(alice);
401 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
410 using namespace std::literals::chrono_literals;
411 Env env{*
this, features};
412 auto const alice =
Account(
"alice");
413 auto const bob =
Account(
"bob");
414 auto const carol =
Account(
"carol");
415 env.fund(
XRP(10000), alice, bob, carol);
416 auto const pk = alice.pk();
417 auto const settleDelay = 3600s;
418 auto const closeTime = env.current()->info().parentCloseTime;
419 auto const minExpiration = closeTime + settleDelay;
421 auto const channelFunds =
XRP(1000);
422 auto const chan =
channel(alice, bob, env.seq(alice));
423 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
428 auto counts = [](
auto const& t) {
429 return t.time_since_epoch().count();
438 counts(minExpiration) + 100);
444 counts(minExpiration) + 50);
451 counts(minExpiration) + 50);
455 counts(minExpiration) + 50);
464 env.close(minExpiration);
476 using namespace std::literals::chrono_literals;
477 Env env{*
this, features};
478 auto const alice =
Account(
"alice");
479 auto const bob =
Account(
"bob");
480 env.fund(
XRP(10000), alice, bob);
481 auto const pk = alice.pk();
482 auto const settleDelay = 3600s;
484 env.current()->info().parentCloseTime + settleDelay;
485 auto const channelFunds =
XRP(1000);
486 auto const chan =
channel(alice, bob, env.seq(alice));
487 env(
create(alice, bob, channelFunds, settleDelay, pk));
492 env.close(settleTimepoint - settleDelay / 2);
497 auto preBob = env.balance(bob);
498 auto const delta =
XRP(500);
499 auto const reqBal = chanBal + delta;
500 auto const authAmt = reqBal +
XRP(100);
501 assert(reqBal <= chanAmt);
504 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
506 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
507 auto const feeDrops = env.current()->fees().base;
508 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
510 env.close(settleTimepoint);
515 auto const preAlice = env.balance(alice);
516 auto preBob = env.balance(bob);
517 auto const delta =
XRP(500);
518 auto const reqBal = chanBal + delta;
519 auto const authAmt = reqBal +
XRP(100);
520 assert(reqBal <= chanAmt);
523 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
525 auto const feeDrops = env.current()->fees().base;
526 BEAST_EXPECT(env.balance(alice) == preAlice + chanAmt - chanBal);
527 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
536 using namespace std::literals::chrono_literals;
537 Env env{*
this, features};
538 auto const alice =
Account(
"alice");
539 auto const bob =
Account(
"bob");
540 env.fund(
XRP(10000), alice, bob);
541 auto const pk = alice.pk();
542 auto const settleDelay = 3600s;
543 auto const channelFunds =
XRP(1000);
544 auto const chan =
channel(alice, bob, env.seq(alice));
545 env(
create(alice, bob, channelFunds, settleDelay, pk));
552 auto const preBob = env.balance(bob);
553 env(
claim(alice, chan, channelFunds.value(), channelFunds.value()));
554 BEAST_EXPECT(
channelBalance(*env.current(), chan) == channelFunds);
555 BEAST_EXPECT(env.balance(bob) == preBob + channelFunds);
557 auto const preAlice = env.balance(alice);
561 auto const feeDrops = env.current()->fees().base;
562 BEAST_EXPECT(env.balance(alice) == preAlice - feeDrops);
571 using namespace std::literals::chrono_literals;
572 Env env{*
this, features};
573 auto const alice =
Account(
"alice");
574 auto const bob =
Account(
"bob");
575 env.fund(
XRP(10000), alice, bob);
576 auto const pk = alice.pk();
577 auto const settleDelay = 3600s;
578 auto const channelFunds =
XRP(1000);
579 auto const chan =
channel(alice, bob, env.seq(alice));
580 env(
create(alice, bob, channelFunds, settleDelay, pk));
588 auto const preBob = env.balance(bob);
590 auto const delta =
XRP(500);
591 auto const reqBal = chanBal + delta;
592 assert(reqBal <= chanAmt);
595 env(
claim(bob, chan, reqBal, std::nullopt,
Slice(
sig), alice.pk()));
597 auto const feeDrops = env.current()->fees().base;
598 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
605 auto const preBob = env.balance(bob);
607 auto const delta =
XRP(500);
608 auto const reqBal = chanBal + delta;
609 assert(reqBal <= chanAmt);
612 env(
claim(bob, chan, reqBal, std::nullopt,
Slice(
sig), alice.pk()));
614 auto const feeDrops = env.current()->fees().base;
615 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
626 using namespace std::literals::chrono_literals;
628 auto const alice =
Account(
"alice");
629 auto const bob =
Account(
"bob");
632 Env env(*
this, features - featureDepositAuth);
633 env.
fund(
XRP(10000), alice, bob);
635 auto const chan =
channel(alice, bob, env.
seq(alice));
636 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()),
643 Env env{*
this, features};
644 env.fund(
XRP(10000), alice, bob);
646 auto const chan =
channel(alice, bob, env.seq(alice));
647 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
654 Env env(*
this, features - featureDepositAuth);
655 env.
fund(
XRP(10000), alice, bob);
656 auto const chan =
channel(alice, bob, env.
seq(alice));
657 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
661 auto const reqBal =
XRP(500).value();
668 Env env{*
this, features};
669 env.fund(
XRP(10000), alice, bob);
670 auto const chan =
channel(alice, bob, env.seq(alice));
671 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
675 auto const reqBal =
XRP(500).value();
676 env(
claim(alice, chan, reqBal, reqBal));
686 using namespace std::literals::chrono_literals;
688 Env env{*
this, features};
689 auto const alice =
Account(
"alice");
690 auto const bob =
Account(
"bob");
691 env.fund(
XRP(10000), alice, bob);
693 auto const pk = alice.pk();
694 auto const settleDelay = 3600s;
695 auto const channelFunds =
XRP(1000);
697 auto const chan =
channel(alice, bob, env.seq(alice));
698 env(
create(alice, bob, channelFunds, settleDelay, pk),
703 auto const chan =
channel(alice, bob, env.seq(alice));
705 alice, bob, channelFunds, settleDelay, pk, std::nullopt, 1));
715 using namespace std::literals::chrono_literals;
717 auto const alice =
Account(
"alice");
718 auto const bob =
Account(
"bob");
719 auto const carol =
Account(
"carol");
720 auto USDA = alice[
"USD"];
722 Env env{*
this, features};
723 env.fund(
XRP(10000), alice, bob, carol);
728 auto const pk = alice.pk();
729 auto const settleDelay = 100s;
730 auto const chan =
channel(alice, bob, env.seq(alice));
731 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
739 env(
fund(alice, chan,
XRP(1000)));
743 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
748 auto const baseFee = env.current()->fees().base;
749 auto const preBob = env.balance(bob);
751 auto const delta =
XRP(500).value();
759 BEAST_EXPECT(env.balance(bob) == preBob);
771 BEAST_EXPECT(env.balance(bob) == preBob + delta - baseFee);
775 auto const delta =
XRP(600).value();
807 env.balance(bob) == preBob + delta - (3 * baseFee));
812 auto const delta =
XRP(800).value();
826 env(
claim(alice, chan, delta, delta));
829 env.balance(bob) == preBob +
XRP(800) - (5 * baseFee));
837 testcase(
"Deposit Authorization with Credentials");
839 using namespace std::literals::chrono_literals;
841 const char credType[] =
"abcde";
846 Account const dillon(
"dillon");
851 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
853 auto const pk = alice.
pk();
854 auto const settleDelay = 100s;
855 auto const chan =
channel(alice, bob, env.seq(alice));
856 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
860 env(
fund(alice, chan,
XRP(1000)));
864 "D007AE4B6E1274B4AF872588267B810C2F82716726351D1C7D38D3E5499FC6"
867 auto const delta =
XRP(500).value();
871 uint32_t
const t = env.current()
873 .parentCloseTime.time_since_epoch()
876 jv[sfExpiration.jsonName] = t;
883 std::string const credIdx = jv[jss::result][jss::index].asString();
890 env(
claim(alice, chan, delta, delta),
899 env(
claim(alice, chan, delta, delta),
909 env(
claim(dillon, chan, delta, delta),
917 env(
claim(alice, chan, delta, delta),
922 env(
claim(alice, chan, delta, delta),
930 for (
int i = 0; i < 10; ++i)
933 env(
claim(alice, chan, delta, delta),
948 jv[jss::result][jss::index].asString();
951 env(
claim(alice, chan, delta, delta),
958 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
960 auto const pk = alice.
pk();
961 auto const settleDelay = 100s;
962 auto const chan =
channel(alice, bob, env.seq(alice));
963 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
967 env(
fund(alice, chan,
XRP(1000)));
970 auto const delta =
XRP(500).value();
981 std::string const credIdx = jv[jss::result][jss::index].asString();
991 env.
fund(
XRP(5000),
"alice",
"bob");
994 auto const pk = alice.
pk();
995 auto const settleDelay = 100s;
996 auto const chan =
channel(alice, bob, env.
seq(alice));
997 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1000 env(
fund(alice, chan,
XRP(1000)));
1003 "48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6EA288B"
1012 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
1022 testcase(
"Multiple channels to the same account");
1023 using namespace jtx;
1024 using namespace std::literals::chrono_literals;
1025 Env env{*
this, features};
1026 auto const alice =
Account(
"alice");
1027 auto const bob =
Account(
"bob");
1028 env.fund(
XRP(10000), alice, bob);
1029 auto const pk = alice.pk();
1030 auto const settleDelay = 3600s;
1031 auto const channelFunds =
XRP(1000);
1032 auto const chan1 =
channel(alice, bob, env.seq(alice));
1033 env(
create(alice, bob, channelFunds, settleDelay, pk));
1035 auto const chan2 =
channel(alice, bob, env.seq(alice));
1036 env(
create(alice, bob, channelFunds, settleDelay, pk));
1038 BEAST_EXPECT(chan1 != chan2);
1046 using namespace jtx;
1047 using namespace std::literals::chrono_literals;
1048 Env env{*
this, features};
1049 auto const alice =
Account(
"alice");
1050 auto const bob =
Account(
"bob");
1052 env.fund(
XRP(10000), alice, bob, charlie);
1053 auto const pk = alice.pk();
1054 auto const settleDelay = 3600s;
1055 auto const channelFunds =
XRP(1000);
1057 env(
create(alice, bob, channelFunds, settleDelay, pk));
1061 auto testInvalidAccountParam = [&](
auto const& param) {
1063 params[jss::account] = param;
1065 "json",
"account_channels",
to_string(params))[jss::result];
1066 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1068 jrr[jss::error_message] ==
"Invalid field 'account'.");
1071 testInvalidAccountParam(1);
1072 testInvalidAccountParam(1.1);
1073 testInvalidAccountParam(
true);
1080 env.rpc(
"account_channels", alice.human(), bob.human());
1081 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1083 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1084 BEAST_EXPECT(r[jss::result][jss::validated]);
1087 auto const r = env.rpc(
"account_channels", alice.human());
1088 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1090 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1091 BEAST_EXPECT(r[jss::result][jss::validated]);
1095 env.rpc(
"account_channels", bob.human(), alice.human());
1096 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1097 BEAST_EXPECT(r[jss::result][jss::validated]);
1100 env(
create(alice, bob, channelFunds, settleDelay, pk));
1104 env.rpc(
"account_channels", alice.human(), bob.human());
1105 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1106 BEAST_EXPECT(r[jss::result][jss::validated]);
1107 BEAST_EXPECT(chan1Str != chan2Str);
1108 for (
auto const& c : {chan1Str, chan2Str})
1110 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1111 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1118 testcase(
"Account channels RPC markers");
1120 using namespace test::jtx;
1121 using namespace std::literals;
1123 auto const alice =
Account(
"alice");
1128 for (
int i = 0; i < n; ++i)
1135 Env env{*
this, features};
1136 env.fund(
XRP(10000), alice);
1137 for (
auto const& a : bobs)
1139 env.fund(
XRP(10000), a);
1145 auto const settleDelay = 3600s;
1146 auto const channelFunds =
XRP(1);
1147 for (
auto const& b : bobs)
1149 env(
create(alice, b, channelFunds, settleDelay, alice.pk()));
1160 jvc[jss::account] = src.human();
1162 jvc[jss::destination_account] = dst->human();
1164 jvc[jss::limit] = *limit;
1166 jvc[jss::marker] = marker;
1169 "json",
"account_channels",
to_string(jvc))[jss::result];
1174 auto const r = testLimit(env, alice);
1175 BEAST_EXPECT(r.isMember(jss::channels));
1176 BEAST_EXPECT(r[jss::channels].size() == bobs.size());
1181 for (
auto const& a : bobs)
1186 for (
int limit = 1; limit < bobs.size() + 1; ++limit)
1188 auto leftToFind = bobsB58;
1189 auto const numFull = bobs.
size() / limit;
1190 auto const numNonFull = bobs.size() % limit ? 1 : 0;
1194 auto const testIt = [&](
bool expectMarker,
int expectedBatchSize) {
1195 auto const r = testLimit(env, alice, limit, marker);
1196 BEAST_EXPECT(!expectMarker || r.isMember(jss::marker));
1197 if (r.isMember(jss::marker))
1198 marker = r[jss::marker];
1199 BEAST_EXPECT(r[jss::channels].size() == expectedBatchSize);
1200 auto const c = r[jss::channels];
1201 auto const s = r[jss::channels].size();
1202 for (
int j = 0; j < s; ++j)
1205 c[j][jss::destination_account].asString();
1206 BEAST_EXPECT(leftToFind.count(dstAcc));
1207 leftToFind.erase(dstAcc);
1211 for (
int i = 0; i < numFull; ++i)
1213 bool const expectMarker = (numNonFull != 0 || i < numFull - 1);
1214 testIt(expectMarker, limit);
1219 testIt(
false, bobs.size() % limit);
1221 BEAST_EXPECT(leftToFind.empty());
1226 auto const r = testLimit(env, alice, 0);
1227 BEAST_EXPECT(r.isMember(jss::error_message));
1236 testcase(
"Account channels RPC owner only");
1238 using namespace test::jtx;
1239 using namespace std::literals;
1241 auto const alice =
Account(
"alice");
1242 auto const bob =
Account(
"bob");
1243 Env env{*
this, features};
1244 env.fund(
XRP(10000), alice, bob);
1249 auto const settleDelay = 3600s;
1250 auto const channelFunds =
XRP(1000);
1251 env(
create(alice, bob, channelFunds, settleDelay, alice.pk()));
1252 env(
create(bob, alice, channelFunds, settleDelay, bob.pk()));
1254 auto const r = [&] {
1256 jvc[jss::account] = alice.human();
1259 "json",
"account_channels",
to_string(jvc))[jss::result];
1261 BEAST_EXPECT(r.isMember(jss::channels));
1262 BEAST_EXPECT(r[jss::channels].size() == 1);
1264 r[jss::channels][0u][jss::destination_account].asString() ==
1271 using namespace jtx;
1272 using namespace std::literals::chrono_literals;
1274 Env env{*
this, features};
1275 auto const alice =
Account(
"alice");
1276 auto const bob =
Account(
"bob");
1278 env.fund(
XRP(10000), alice, bob, charlie);
1279 auto const pk = alice.pk();
1280 auto const settleDelay = 3600s;
1281 auto const channelFunds =
XRP(1000);
1283 env(
create(alice, bob, channelFunds, settleDelay, pk));
1287 args[jss::channel_id] = chan1Str;
1288 args[jss::key_type] =
"ed255191";
1289 args[jss::seed] =
"snHq1rzQoN2qiUkC3XF5RyxBzUtN";
1290 args[jss::amount] = 51110000;
1296 args[jss::api_version] = apiVersion;
1297 auto const rs = env.rpc(
1299 "channel_authorize",
1300 args.toStyledString())[jss::result];
1301 auto const error = apiVersion < 2u ?
"invalidParams" :
"badKeyType";
1302 BEAST_EXPECT(rs[jss::error] == error);
1309 testcase(
"PayChan Auth/Verify RPC");
1310 using namespace jtx;
1311 using namespace std::literals::chrono_literals;
1312 Env env{*
this, features};
1313 auto const alice =
Account(
"alice");
1314 auto const bob =
Account(
"bob");
1316 env.fund(
XRP(10000), alice, bob, charlie);
1317 auto const pk = alice.pk();
1318 auto const settleDelay = 3600s;
1319 auto const channelFunds =
XRP(1000);
1321 env(
create(alice, bob, channelFunds, settleDelay, pk));
1326 env.rpc(
"account_channels", alice.human(), bob.human());
1327 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1329 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1330 BEAST_EXPECT(r[jss::result][jss::validated]);
1332 r[jss::result][jss::channels][0u][jss::public_key].asString();
1335 auto const r = env.rpc(
"account_channels", alice.human());
1336 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1338 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1339 BEAST_EXPECT(r[jss::result][jss::validated]);
1341 r[jss::result][jss::channels][0u][jss::public_key].asString();
1345 env.rpc(
"account_channels", bob.human(), alice.human());
1346 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1347 BEAST_EXPECT(r[jss::result][jss::validated]);
1350 env(
create(alice, bob, channelFunds, settleDelay, pk));
1354 env.rpc(
"account_channels", alice.human(), bob.human());
1355 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1356 BEAST_EXPECT(r[jss::result][jss::validated]);
1357 BEAST_EXPECT(chan1Str != chan2Str);
1358 for (
auto const& c : {chan1Str, chan2Str})
1360 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1361 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1367 for (
int i = 0; i < slice.size(); ++i)
1369 s +=
"0123456789ABCDEF"[((slice[i] & 0xf0) >> 4)];
1370 s +=
"0123456789ABCDEF"[((slice[i] & 0x0f) >> 0)];
1378 env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000");
1379 auto const sig = rs[jss::result][jss::signature].asString();
1380 BEAST_EXPECT(!
sig.empty());
1382 auto const rv = env.rpc(
1383 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1384 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1391 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1392 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1398 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000x",
sig);
1399 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1400 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 ",
sig);
1401 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1402 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x1000",
sig);
1403 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1404 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x",
sig);
1405 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1406 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" ",
sig);
1407 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1409 "channel_verify", pkAsHex, chan1Str,
"1000 1000",
sig);
1410 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1411 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1,000",
sig);
1412 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1413 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" 1000",
sig);
1414 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1415 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"",
sig);
1416 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1421 auto chan1StrBad = chan1Str;
1422 chan1StrBad.pop_back();
1424 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1425 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1426 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1427 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1429 chan1StrBad = chan1Str;
1430 chan1StrBad.push_back(
'0');
1432 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1433 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1434 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1435 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1437 chan1StrBad = chan1Str;
1438 chan1StrBad.back() =
'x';
1440 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1441 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1442 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1443 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1447 auto illFormedPk = chan1PkStr.
substr(0, chan1PkStr.
size() - 1);
1448 auto const rv = env.rpc(
1449 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1451 !rv[jss::result][jss::signature_verified].asBool());
1456 auto illFormedPk = pkAsHex.substr(0, chan1PkStr.
size() - 1);
1457 auto const rv = env.rpc(
1458 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1460 !rv[jss::result][jss::signature_verified].asBool());
1466 env.rpc(
"channel_authorize",
"alice", chan2Str,
"1000");
1467 auto const sig = rs[jss::result][jss::signature].asString();
1468 BEAST_EXPECT(!
sig.empty());
1470 auto const rv = env.rpc(
1471 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1473 !rv[jss::result][jss::signature_verified].asBool());
1479 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1481 !rv[jss::result][jss::signature_verified].asBool());
1489 charlie, alice, channelFunds, settleDelay, charlie.pk()));
1495 env.rpc(
"account_channels", charlie.human(), alice.human());
1496 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1498 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1499 BEAST_EXPECT(r[jss::result][jss::validated]);
1500 cpk = r[jss::result][jss::channels][0u][jss::public_key]
1506 env.rpc(
"channel_authorize",
"charlie", chan,
"1000");
1507 auto const sig = rs[jss::result][jss::signature].asString();
1508 BEAST_EXPECT(!
sig.empty());
1511 env.rpc(
"channel_verify", cpk, chan,
"1000",
sig);
1513 !rv[jss::result][jss::signature_verified].asBool());
1518 env.rpc(
"channel_authorize",
"charlie",
"nyx", chan,
"1000");
1519 BEAST_EXPECT(rs1[jss::error] ==
"badKeyType");
1523 auto const rs2 = env.rpc(
1524 "channel_authorize",
"charlie",
"secp256k1", chan,
"1000");
1525 auto const sig2 = rs2[jss::result][jss::signature].asString();
1526 BEAST_EXPECT(!sig2.empty());
1529 env.rpc(
"channel_verify", cpk, chan,
"1000", sig2);
1531 !rv[jss::result][jss::signature_verified].asBool());
1535 auto const rs3 = env.rpc(
1536 "channel_authorize",
"charlie",
"ed25519", chan,
"1000");
1537 auto const sig3 = rs3[jss::result][jss::signature].asString();
1538 BEAST_EXPECT(!sig3.empty());
1541 env.rpc(
"channel_verify", cpk, chan,
"1000", sig3);
1542 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1548 auto rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000x");
1549 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1550 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x1000");
1551 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1552 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x");
1553 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1557 args[jss::amount] =
"2000";
1558 args[jss::key_type] =
"secp256k1";
1559 args[jss::passphrase] =
"passphrase_can_be_anything";
1562 "channel_authorize",
1563 args.toStyledString())[jss::result];
1564 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1569 args[jss::channel_id] = chan1Str;
1570 args[jss::key_type] =
"secp256k1";
1571 args[jss::passphrase] =
"passphrase_can_be_anything";
1574 "channel_authorize",
1575 args.toStyledString())[jss::result];
1576 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1581 args[jss::amount] =
"2000";
1582 args[jss::channel_id] = chan1Str;
1583 args[jss::passphrase] =
"passphrase_can_be_anything";
1586 "channel_authorize",
1587 args.toStyledString())[jss::result];
1588 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1593 args[jss::amount] =
"2000";
1594 args[jss::channel_id] = chan1Str;
1595 args[jss::key_type] =
"secp256k1";
1596 args[jss::passphrase] =
"passphrase_can_be_anything";
1597 args[jss::seed] =
"seed can be anything";
1600 "channel_authorize",
1601 args.toStyledString())[jss::result];
1602 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1607 args[jss::amount] =
"2000";
1608 args[jss::channel_id] = chan1Str +
"1";
1609 args[jss::key_type] =
"secp256k1";
1610 args[jss::passphrase] =
"passphrase_can_be_anything";
1613 "channel_authorize",
1614 args.toStyledString())[jss::result];
1615 BEAST_EXPECT(rs[jss::error] ==
"channelMalformed");
1620 args[jss::amount] = 2000;
1621 args[jss::channel_id] = chan1Str;
1622 args[jss::key_type] =
"secp256k1";
1623 args[jss::passphrase] =
"passphrase_can_be_anything";
1626 "channel_authorize",
1627 args.toStyledString())[jss::result];
1628 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1633 args[jss::amount] =
"TwoThousand";
1634 args[jss::channel_id] = chan1Str;
1635 args[jss::key_type] =
"secp256k1";
1636 args[jss::passphrase] =
"passphrase_can_be_anything";
1639 "channel_authorize",
1640 args.toStyledString())[jss::result];
1641 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1650 using namespace jtx;
1651 using namespace std::literals::chrono_literals;
1652 Env env{*
this, features};
1653 auto const alice =
Account(
"alice");
1654 auto const bob =
Account(
"bob");
1655 auto const carol =
Account(
"carol");
1656 auto const dan =
Account(
"dan");
1657 env.fund(
XRP(10000), alice, bob, carol, dan);
1658 auto const pk = alice.pk();
1659 auto const settleDelay = 3600s;
1660 auto const channelFunds =
XRP(1000);
1666 env(
create(alice, bob, channelFunds, settleDelay, pk));
1668 env.rpc(
"account_channels", alice.human(), bob.human());
1669 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1671 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1672 BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember(
1673 jss::destination_tag));
1687 env.rpc(
"account_channels", alice.human(), carol.human());
1688 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1690 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1692 r[jss::result][jss::channels][0u][jss::destination_tag] ==
1701 using namespace jtx;
1702 using namespace std::literals::chrono_literals;
1703 Env env{*
this, features};
1704 auto const alice =
Account(
"alice");
1705 auto const bob =
Account(
"bob");
1706 auto USDA = alice[
"USD"];
1707 env.fund(
XRP(10000), alice, bob);
1708 auto const pk = alice.pk();
1709 auto const settleDelay = 100s;
1711 auto const chan =
channel(alice, bob, env.seq(alice));
1712 auto jv =
create(alice, bob,
XRP(1000), settleDelay, pk);
1713 auto const pkHex =
strHex(pk.slice());
1714 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1716 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1718 auto badPrefix = pkHex;
1721 jv[
"PublicKey"] = badPrefix;
1724 jv[
"PublicKey"] = pkHex;
1727 auto const authAmt =
XRP(100);
1736 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1738 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1743 jv[
"PublicKey"] = badPrefix;
1747 jv.removeMember(
"PublicKey");
1751 auto const txn = R
"*(
1754 "channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
1756 "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
1758 "aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
1762 auto const r = env.rpc(
"json",
"channel_verify", txn);
1763 BEAST_EXPECT(r[
"result"][
"error"] ==
"publicMalformed");
1772 using namespace jtx;
1773 using namespace std::literals::chrono_literals;
1775 auto const alice =
Account(
"alice");
1776 auto const bob =
Account(
"bob");
1777 auto const settleDelay = 100s;
1778 auto const pk = alice.pk();
1780 auto inOwnerDir = [](
ReadView const& view,
1784 return std::find(ownerDir.begin(), ownerDir.end(), chan) !=
1788 auto ownerDirCount = [](
ReadView const& view,
1797 Env env(*
this, features - fixPayChanRecipientOwnerDir);
1798 env.
fund(
XRP(10000), alice, bob);
1799 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1801 auto const [chan, chanSle] =
1803 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1804 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1805 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1806 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1810 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1811 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1812 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1813 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1818 Env env{*
this, features};
1819 env.fund(
XRP(10000), alice, bob);
1820 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1822 auto const [chan, chanSle] =
1824 BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle));
1825 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
1826 BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle));
1827 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 1);
1831 BEAST_EXPECT(!inOwnerDir(*env.current(), alice, chanSle));
1832 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 0);
1833 BEAST_EXPECT(!inOwnerDir(*env.current(), bob, chanSle));
1834 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 0);
1840 Env env(*
this, features - fixPayChanRecipientOwnerDir);
1841 env.
fund(
XRP(10000), alice, bob);
1843 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1845 auto const [chan, chanSle] =
1847 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1848 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1849 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1850 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1854 env.
current()->rules().enabled(fixPayChanRecipientOwnerDir));
1859 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1860 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1861 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
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);
1877 using namespace test::jtx;
1878 using namespace std::literals::chrono_literals;
1879 auto rmAccount = [
this](
1886 for (
auto minRmSeq = env.
seq(toRm) + 257;
1887 env.
current()->seq() < minRmSeq;
1901 auto const alice =
Account(
"alice");
1902 auto const bob =
Account(
"bob");
1903 auto const carol =
Account(
"carol");
1905 for (
bool const withOwnerDirFix : {
false,
true})
1907 auto const amd = withOwnerDirFix
1909 : features - fixPayChanRecipientOwnerDir;
1910 Env env{*
this, amd};
1911 env.
fund(
XRP(10000), alice, bob, carol);
1913 auto const feeDrops = env.
current()->fees().base;
1916 auto const pk = alice.pk();
1917 auto const settleDelay = 100s;
1918 auto const chan =
channel(alice, bob, env.
seq(alice));
1919 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1934 BEAST_EXPECT(chanBal ==
XRP(0));
1935 BEAST_EXPECT(chanAmt ==
XRP(1000));
1937 auto preBob = env.
balance(bob);
1938 auto const delta =
XRP(50);
1939 auto reqBal = chanBal + delta;
1940 auto authAmt = reqBal +
XRP(100);
1941 assert(reqBal <= chanAmt);
1944 if (withOwnerDirFix)
1946 env(
claim(alice, chan, reqBal, authAmt));
1950 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1955 auto const preAlice = env.
balance(alice);
1960 BEAST_EXPECT(env.
balance(bob) == preBob);
1961 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1965 if (withOwnerDirFix)
1967 auto const preAlice = env.
balance(alice);
1968 env(
fund(alice, chan,
XRP(1000)));
1971 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1974 chanAmt = chanAmt +
XRP(1000);
1978 auto const preAlice = env.
balance(alice);
1981 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1991 auto const closeTime = env.
current()->info().parentCloseTime;
1992 auto const minExpiration = closeTime + settleDelay;
1993 env.
close(minExpiration);
2001 Env env{*
this, features - fixPayChanRecipientOwnerDir};
2002 env.
fund(
XRP(10000), alice, bob, carol);
2004 auto const feeDrops = env.
current()->fees().base;
2007 auto const pk = alice.pk();
2008 auto const settleDelay = 100s;
2009 auto const chan =
channel(alice, bob, env.
seq(alice));
2010 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
2016 rmAccount(env, bob, carol);
2021 BEAST_EXPECT(chanBal ==
XRP(0));
2022 BEAST_EXPECT(chanAmt ==
XRP(1000));
2023 auto preBob = env.
balance(bob);
2024 auto const delta =
XRP(50);
2025 auto reqBal = chanBal + delta;
2026 auto authAmt = reqBal +
XRP(100);
2027 assert(reqBal <= chanAmt);
2031 auto const preAlice = env.
balance(alice);
2036 BEAST_EXPECT(env.
balance(bob) == preBob);
2037 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2042 auto const preAlice = env.
balance(alice);
2045 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
2050 env(
pay(alice, bob,
XRP(20)));
2057 reqBal = chanBal + delta;
2058 authAmt = reqBal +
XRP(100);
2059 env(
claim(alice, chan, reqBal, authAmt));
2062 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
2069 reqBal = chanBal + delta;
2070 authAmt = reqBal +
XRP(100);
2073 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
2076 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
2082 auto const preAlice = env.
balance(alice);
2083 env(
fund(alice, chan,
XRP(1000)));
2085 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
2088 chanAmt = chanAmt +
XRP(1000);
2097 auto const closeTime = env.
current()->info().parentCloseTime;
2098 auto const minExpiration = closeTime + settleDelay;
2099 env.
close(minExpiration);
2110 using namespace jtx;
2111 using namespace std::literals::chrono_literals;
2112 Env env{*
this, features};
2113 auto const alice =
Account(
"alice");
2114 auto const bob =
Account(
"bob");
2115 auto USDA = alice[
"USD"];
2116 env.fund(
XRP(10000), alice, bob);
2129 auto const pk = alice.pk();
2130 auto const settleDelay = 100s;
2131 auto const chan =
channel(alice, bob, aliceTicketSeq);
2133 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
2136 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2137 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2143 auto const preAlice = env.balance(alice);
2146 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2147 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2149 auto const feeDrops = env.current()->fees().base;
2150 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
2155 BEAST_EXPECT(chanBal ==
XRP(0));
2156 BEAST_EXPECT(chanAmt ==
XRP(2000));
2160 auto const preBob = env.balance(bob);
2161 auto const delta =
XRP(500);
2162 auto const reqBal = chanBal + delta;
2163 auto const authAmt = reqBal +
XRP(100);
2164 assert(reqBal <= chanAmt);
2165 env(
claim(alice, chan, reqBal, authAmt),
2168 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2169 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2172 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2173 BEAST_EXPECT(env.balance(bob) == preBob + delta);
2178 auto preBob = env.balance(bob);
2179 auto const delta =
XRP(500);
2180 auto const reqBal = chanBal + delta;
2181 auto const authAmt = reqBal +
XRP(100);
2182 assert(reqBal <= chanAmt);
2185 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
2188 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2189 BEAST_EXPECT(env.seq(bob) == bobSeq);
2192 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2193 auto const feeDrops = env.current()->fees().base;
2194 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
2198 preBob = env.balance(bob);
2200 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
2204 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2205 BEAST_EXPECT(env.seq(bob) == bobSeq);
2208 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2209 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2213 auto const preBob = env.balance(bob);
2216 assert(reqAmt <= chanAmt);
2221 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
2225 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2226 BEAST_EXPECT(env.seq(bob) == bobSeq);
2229 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2230 BEAST_EXPECT(env.balance(bob) == preBob);
2234 env(
fund(bob, chan,
XRP(1000)),
2238 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2239 BEAST_EXPECT(env.seq(bob) == bobSeq);
2242 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2246 auto const preAlice = env.balance(alice);
2247 auto const preBob = env.balance(bob);
2248 env(
claim(bob, chan),
2252 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2253 BEAST_EXPECT(env.seq(bob) == bobSeq);
2256 auto const feeDrops = env.current()->fees().base;
2257 auto const delta = chanAmt - chanBal;
2258 assert(delta > beast::zero);
2259 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
2260 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2262 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2263 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2264 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2265 BEAST_EXPECT(env.seq(bob) == bobSeq);
2298 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)