20 #include <ripple/basics/chrono.h>
21 #include <ripple/ledger/Directory.h>
22 #include <ripple/protocol/Feature.h>
23 #include <ripple/protocol/Indexes.h>
24 #include <ripple/protocol/PayChan.h>
25 #include <ripple/protocol/TxFlags.h>
26 #include <ripple/protocol/jss.h>
57 return {k.key, view.
read(k)};
120 jv[jss::TransactionType] = jss::PaymentChannelCreate;
122 jv[jss::Account] = account.human();
123 jv[jss::Destination] = to.
human();
125 jv[
"SettleDelay"] = settleDelay.
count();
128 jv[
"CancelAfter"] = cancelAfter->time_since_epoch().count();
130 jv[
"DestinationTag"] = *dstTag;
143 jv[jss::TransactionType] = jss::PaymentChannelFund;
145 jv[jss::Account] = account.human();
149 jv[
"Expiration"] =
expiration->time_since_epoch().count();
164 jv[jss::TransactionType] = jss::PaymentChannelClaim;
166 jv[jss::Account] = account.human();
173 jv[
"Signature"] =
strHex(*signature);
175 jv[
"PublicKey"] =
strHex(pk->slice());
184 using namespace std::literals::chrono_literals;
185 Env env{*
this, features};
186 auto const alice =
Account(
"alice");
187 auto const bob =
Account(
"bob");
188 auto USDA = alice[
"USD"];
189 env.fund(
XRP(10000), alice, bob);
190 auto const pk = alice.pk();
191 auto const settleDelay = 100s;
192 auto const chan =
channel(alice, bob, env.seq(alice));
193 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
198 auto const preAlice = env.balance(alice);
199 env(
fund(alice, chan,
XRP(1000)));
200 auto const feeDrops = env.current()->fees().base;
201 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
206 BEAST_EXPECT(chanBal ==
XRP(0));
207 BEAST_EXPECT(chanAmt ==
XRP(2000));
211 env(
create(alice, bob, USDA(1000), settleDelay, pk),
214 env(
create(alice, bob,
XRP(-1000), settleDelay, pk),
220 env(
create(alice,
"noAccount",
XRP(1000), settleDelay, pk),
223 env(
create(alice, alice,
XRP(1000), settleDelay, pk),
229 channel(alice,
"noAccount", env.seq(alice) - 1),
237 auto const iou = USDA(100).value();
238 auto const negXRP =
XRP(-100).value();
239 auto const posXRP =
XRP(100).value();
249 auto const delta =
XRP(500);
250 auto const reqBal = chanBal + delta;
251 auto const authAmt = reqBal +
XRP(-100);
252 assert(reqBal <= chanAmt);
257 auto const preBob = env.balance(bob);
258 auto const delta =
XRP(500);
259 auto const reqBal = chanBal + delta;
260 auto const authAmt = reqBal +
XRP(100);
261 assert(reqBal <= chanAmt);
262 env(
claim(alice, chan, reqBal, authAmt));
264 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
265 BEAST_EXPECT(env.balance(bob) == preBob + delta);
270 auto preBob = env.balance(bob);
271 auto const delta =
XRP(500);
272 auto const reqBal = chanBal + delta;
273 auto const authAmt = reqBal +
XRP(100);
274 assert(reqBal <= chanAmt);
277 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
279 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
280 auto const feeDrops = env.current()->fees().base;
281 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
285 preBob = env.balance(bob);
286 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
289 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
290 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
294 auto const preBob = env.balance(bob);
297 assert(reqAmt <= chanAmt);
300 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
303 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
304 BEAST_EXPECT(env.balance(bob) == preBob);
310 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
324 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
338 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
342 auto const preAlice = env.balance(alice);
343 auto const preBob = env.balance(bob);
346 auto const feeDrops = env.current()->fees().base;
347 auto const delta = chanAmt - chanBal;
348 assert(delta > beast::zero);
349 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
350 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
357 testcase(
"Disallow Incoming Flag");
364 env.fund(
XRP(10000), alice);
367 auto const sle = env.le(alice);
368 uint32_t
flags = sle->getFlags();
372 using namespace std::literals::chrono_literals;
374 auto const alice =
Account(
"alice");
375 auto const bob =
Account(
"bob");
376 auto const cho =
Account(
"cho");
377 env.fund(
XRP(10000), alice, bob, cho);
378 auto const pk = alice.pk();
379 auto const settleDelay = 100s;
387 auto const chan =
channel(alice, bob, env.seq(alice));
388 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
399 auto const chan =
channel(bob, alice, env.seq(bob));
400 env(
create(bob, alice,
XRP(1000), settleDelay, pk),
411 auto const chan =
channel(alice, bob, env.seq(alice));
412 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
419 auto const chan =
channel(cho, alice, env.seq(cho));
420 env(
create(cho, alice,
XRP(1000), settleDelay, pk),
431 auto const chan =
channel(cho, alice, env.seq(cho));
432 env(
create(cho, alice,
XRP(1000), settleDelay, pk),
441 testcase(
"cancel after");
443 using namespace std::literals::chrono_literals;
444 auto const alice =
Account(
"alice");
445 auto const bob =
Account(
"bob");
446 auto const carol =
Account(
"carol");
449 Env env{*
this, features};
450 env.fund(
XRP(10000), alice, bob);
451 auto const pk = alice.pk();
452 auto const settleDelay = 100s;
454 env.current()->info().parentCloseTime + 3600s;
455 auto const channelFunds =
XRP(1000);
456 auto const chan =
channel(alice, bob, env.seq(alice));
457 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
459 env.close(cancelAfter);
464 auto preAlice = env.balance(alice);
465 auto preBob = env.balance(bob);
466 auto const delta =
XRP(500);
467 auto const reqBal = chanBal + delta;
468 auto const authAmt = reqBal +
XRP(100);
469 assert(reqBal <= chanAmt);
472 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
473 auto const feeDrops = env.current()->fees().base;
475 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
476 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
481 Env env{*
this, features};
482 env.fund(
XRP(10000), alice, bob, carol);
483 auto const pk = alice.pk();
484 auto const settleDelay = 100s;
486 env.current()->info().parentCloseTime + 3600s;
487 auto const channelFunds =
XRP(1000);
488 auto const chan =
channel(alice, bob, env.seq(alice));
489 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
494 env.close(cancelAfter);
496 auto const preAlice = env.balance(alice);
499 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
506 testcase(
"expiration");
508 using namespace std::literals::chrono_literals;
509 Env env{*
this, features};
510 auto const alice =
Account(
"alice");
511 auto const bob =
Account(
"bob");
512 auto const carol =
Account(
"carol");
513 env.fund(
XRP(10000), alice, bob, carol);
514 auto const pk = alice.pk();
515 auto const settleDelay = 3600s;
516 auto const closeTime = env.current()->info().parentCloseTime;
517 auto const minExpiration = closeTime + settleDelay;
519 auto const channelFunds =
XRP(1000);
520 auto const chan =
channel(alice, bob, env.seq(alice));
521 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
526 auto counts = [](
auto const& t) {
527 return t.time_since_epoch().count();
536 counts(minExpiration) + 100);
542 counts(minExpiration) + 50);
549 counts(minExpiration) + 50);
553 counts(minExpiration) + 50);
562 env.close(minExpiration);
572 testcase(
"settle delay");
574 using namespace std::literals::chrono_literals;
575 Env env{*
this, features};
576 auto const alice =
Account(
"alice");
577 auto const bob =
Account(
"bob");
578 env.fund(
XRP(10000), alice, bob);
579 auto const pk = alice.pk();
580 auto const settleDelay = 3600s;
582 env.current()->info().parentCloseTime + settleDelay;
583 auto const channelFunds =
XRP(1000);
584 auto const chan =
channel(alice, bob, env.seq(alice));
585 env(
create(alice, bob, channelFunds, settleDelay, pk));
590 env.close(settleTimepoint - settleDelay / 2);
595 auto preBob = env.balance(bob);
596 auto const delta =
XRP(500);
597 auto const reqBal = chanBal + delta;
598 auto const authAmt = reqBal +
XRP(100);
599 assert(reqBal <= chanAmt);
602 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
604 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
605 auto const feeDrops = env.current()->fees().base;
606 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
608 env.close(settleTimepoint);
613 auto const preAlice = env.balance(alice);
614 auto preBob = env.balance(bob);
615 auto const delta =
XRP(500);
616 auto const reqBal = chanBal + delta;
617 auto const authAmt = reqBal +
XRP(100);
618 assert(reqBal <= chanAmt);
621 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
623 auto const feeDrops = env.current()->fees().base;
624 BEAST_EXPECT(env.balance(alice) == preAlice + chanAmt - chanBal);
625 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
632 testcase(
"close dry");
634 using namespace std::literals::chrono_literals;
635 Env env{*
this, features};
636 auto const alice =
Account(
"alice");
637 auto const bob =
Account(
"bob");
638 env.fund(
XRP(10000), alice, bob);
639 auto const pk = alice.pk();
640 auto const settleDelay = 3600s;
641 auto const channelFunds =
XRP(1000);
642 auto const chan =
channel(alice, bob, env.seq(alice));
643 env(
create(alice, bob, channelFunds, settleDelay, pk));
650 auto const preBob = env.balance(bob);
651 env(
claim(alice, chan, channelFunds.value(), channelFunds.value()));
652 BEAST_EXPECT(
channelBalance(*env.current(), chan) == channelFunds);
653 BEAST_EXPECT(env.balance(bob) == preBob + channelFunds);
655 auto const preAlice = env.balance(alice);
659 auto const feeDrops = env.current()->fees().base;
660 BEAST_EXPECT(env.balance(alice) == preAlice - feeDrops);
667 testcase(
"default amount");
669 using namespace std::literals::chrono_literals;
670 Env env{*
this, features};
671 auto const alice =
Account(
"alice");
672 auto const bob =
Account(
"bob");
673 env.fund(
XRP(10000), alice, bob);
674 auto const pk = alice.pk();
675 auto const settleDelay = 3600s;
676 auto const channelFunds =
XRP(1000);
677 auto const chan =
channel(alice, bob, env.seq(alice));
678 env(
create(alice, bob, channelFunds, settleDelay, pk));
686 auto const preBob = env.balance(bob);
688 auto const delta =
XRP(500);
689 auto const reqBal = chanBal + delta;
690 assert(reqBal <= chanAmt);
693 env(
claim(bob, chan, reqBal, std::nullopt,
Slice(
sig), alice.pk()));
695 auto const feeDrops = env.current()->fees().base;
696 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
703 auto const preBob = env.balance(bob);
705 auto const delta =
XRP(500);
706 auto const reqBal = chanBal + delta;
707 assert(reqBal <= chanAmt);
710 env(
claim(bob, chan, reqBal, std::nullopt,
Slice(
sig), alice.pk()));
712 auto const feeDrops = env.current()->fees().base;
713 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
722 testcase(
"Disallow XRP");
724 using namespace std::literals::chrono_literals;
726 auto const alice =
Account(
"alice");
727 auto const bob =
Account(
"bob");
731 env.
fund(
XRP(10000), alice, bob);
733 auto const chan =
channel(alice, bob, env.
seq(alice));
734 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()),
741 Env env{*
this, features};
742 env.fund(
XRP(10000), alice, bob);
744 auto const chan =
channel(alice, bob, env.seq(alice));
745 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
753 env.
fund(
XRP(10000), alice, bob);
754 auto const chan =
channel(alice, bob, env.
seq(alice));
755 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
759 auto const reqBal =
XRP(500).value();
766 Env env{*
this, features};
767 env.fund(
XRP(10000), alice, bob);
768 auto const chan =
channel(alice, bob, env.seq(alice));
769 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
773 auto const reqBal =
XRP(500).value();
774 env(
claim(alice, chan, reqBal, reqBal));
784 using namespace std::literals::chrono_literals;
786 Env env{*
this, features};
787 auto const alice =
Account(
"alice");
788 auto const bob =
Account(
"bob");
789 env.fund(
XRP(10000), alice, bob);
791 auto const pk = alice.pk();
792 auto const settleDelay = 3600s;
793 auto const channelFunds =
XRP(1000);
795 auto const chan =
channel(alice, bob, env.seq(alice));
796 env(
create(alice, bob, channelFunds, settleDelay, pk),
801 auto const chan =
channel(alice, bob, env.seq(alice));
803 alice, bob, channelFunds, settleDelay, pk, std::nullopt, 1));
811 testcase(
"Deposit Authorization");
813 using namespace std::literals::chrono_literals;
815 auto const alice =
Account(
"alice");
816 auto const bob =
Account(
"bob");
817 auto const carol =
Account(
"carol");
818 auto USDA = alice[
"USD"];
820 Env env{*
this, features};
821 env.fund(
XRP(10000), alice, bob, carol);
826 auto const pk = alice.pk();
827 auto const settleDelay = 100s;
828 auto const chan =
channel(alice, bob, env.seq(alice));
829 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
837 env(
fund(alice, chan,
XRP(1000)));
841 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
846 auto const baseFee = env.current()->fees().base;
847 auto const preBob = env.balance(bob);
849 auto const delta =
XRP(500).value();
857 BEAST_EXPECT(env.balance(bob) == preBob);
869 BEAST_EXPECT(env.balance(bob) == preBob + delta - baseFee);
873 auto const delta =
XRP(600).value();
884 env(deposit::auth(bob, carol));
898 env(deposit::auth(bob, alice));
905 env.balance(bob) == preBob + delta - (3 * baseFee));
910 auto const delta =
XRP(800).value();
912 env(deposit::unauth(bob, alice));
924 env(
claim(alice, chan, delta, delta));
927 env.balance(bob) == preBob +
XRP(800) - (5 * baseFee));
936 testcase(
"Multiple channels to the same account");
938 using namespace std::literals::chrono_literals;
939 Env env{*
this, features};
940 auto const alice =
Account(
"alice");
941 auto const bob =
Account(
"bob");
942 env.fund(
XRP(10000), alice, bob);
943 auto const pk = alice.pk();
944 auto const settleDelay = 3600s;
945 auto const channelFunds =
XRP(1000);
946 auto const chan1 =
channel(alice, bob, env.seq(alice));
947 env(
create(alice, bob, channelFunds, settleDelay, pk));
949 auto const chan2 =
channel(alice, bob, env.seq(alice));
950 env(
create(alice, bob, channelFunds, settleDelay, pk));
952 BEAST_EXPECT(chan1 != chan2);
958 testcase(
"AccountChannels RPC");
961 using namespace std::literals::chrono_literals;
962 Env env{*
this, features};
963 auto const alice =
Account(
"alice");
964 auto const bob =
Account(
"bob");
966 env.fund(
XRP(10000), alice, bob, charlie);
967 auto const pk = alice.pk();
968 auto const settleDelay = 3600s;
969 auto const channelFunds =
XRP(1000);
971 env(
create(alice, bob, channelFunds, settleDelay, pk));
975 env.rpc(
"account_channels", alice.human(), bob.human());
976 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
978 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
979 BEAST_EXPECT(r[jss::result][jss::validated]);
982 auto const r = env.rpc(
"account_channels", alice.human());
983 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
985 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
986 BEAST_EXPECT(r[jss::result][jss::validated]);
990 env.rpc(
"account_channels", bob.human(), alice.human());
991 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
992 BEAST_EXPECT(r[jss::result][jss::validated]);
995 env(
create(alice, bob, channelFunds, settleDelay, pk));
999 env.rpc(
"account_channels", alice.human(), bob.human());
1000 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1001 BEAST_EXPECT(r[jss::result][jss::validated]);
1002 BEAST_EXPECT(chan1Str != chan2Str);
1003 for (
auto const& c : {chan1Str, chan2Str})
1005 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1006 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1013 testcase(
"Account channels RPC markers");
1015 using namespace test::jtx;
1016 using namespace std::literals;
1018 auto const alice =
Account(
"alice");
1023 for (
int i = 0; i < n; ++i)
1030 Env env{*
this, features};
1031 env.fund(
XRP(10000), alice);
1032 for (
auto const& a : bobs)
1034 env.fund(
XRP(10000), a);
1040 auto const settleDelay = 3600s;
1041 auto const channelFunds =
XRP(1);
1042 for (
auto const& b : bobs)
1044 env(
create(alice, b, channelFunds, settleDelay, alice.pk()));
1055 jvc[jss::account] = src.human();
1057 jvc[jss::destination_account] = dst->human();
1059 jvc[jss::limit] = *limit;
1061 jvc[jss::marker] = marker;
1064 "json",
"account_channels",
to_string(jvc))[jss::result];
1069 auto const r = testLimit(env, alice);
1070 BEAST_EXPECT(r.isMember(jss::channels));
1071 BEAST_EXPECT(r[jss::channels].size() == bobs.size());
1076 for (
auto const& a : bobs)
1081 for (
int limit = 1; limit < bobs.size() + 1; ++limit)
1083 auto leftToFind = bobsB58;
1084 auto const numFull = bobs.
size() / limit;
1085 auto const numNonFull = bobs.size() % limit ? 1 : 0;
1089 auto const testIt = [&](
bool expectMarker,
int expectedBatchSize) {
1090 auto const r = testLimit(env, alice, limit, marker);
1091 BEAST_EXPECT(!expectMarker || r.isMember(jss::marker));
1092 if (r.isMember(jss::marker))
1093 marker = r[jss::marker];
1094 BEAST_EXPECT(r[jss::channels].size() == expectedBatchSize);
1095 auto const c = r[jss::channels];
1096 auto const s = r[jss::channels].size();
1097 for (
int j = 0; j < s; ++j)
1100 c[j][jss::destination_account].asString();
1101 BEAST_EXPECT(leftToFind.count(dstAcc));
1102 leftToFind.erase(dstAcc);
1106 for (
int i = 0; i < numFull; ++i)
1108 bool const expectMarker = (numNonFull != 0 || i < numFull - 1);
1109 testIt(expectMarker, limit);
1114 testIt(
false, bobs.size() % limit);
1116 BEAST_EXPECT(leftToFind.empty());
1121 auto const r = testLimit(env, alice, 0);
1122 BEAST_EXPECT(r.isMember(jss::error_message));
1131 testcase(
"Account channels RPC owner only");
1133 using namespace test::jtx;
1134 using namespace std::literals;
1136 auto const alice =
Account(
"alice");
1137 auto const bob =
Account(
"bob");
1138 Env env{*
this, features};
1139 env.fund(
XRP(10000), alice, bob);
1144 auto const settleDelay = 3600s;
1145 auto const channelFunds =
XRP(1000);
1146 env(
create(alice, bob, channelFunds, settleDelay, alice.pk()));
1147 env(
create(bob, alice, channelFunds, settleDelay, bob.pk()));
1149 auto const r = [&] {
1151 jvc[jss::account] = alice.human();
1154 "json",
"account_channels",
to_string(jvc))[jss::result];
1156 BEAST_EXPECT(r.isMember(jss::channels));
1157 BEAST_EXPECT(r[jss::channels].size() == 1);
1159 r[jss::channels][0u][jss::destination_account].asString() ==
1166 testcase(
"PayChan Auth/Verify RPC");
1167 using namespace jtx;
1168 using namespace std::literals::chrono_literals;
1169 Env env{*
this, features};
1170 auto const alice =
Account(
"alice");
1171 auto const bob =
Account(
"bob");
1173 env.fund(
XRP(10000), alice, bob, charlie);
1174 auto const pk = alice.pk();
1175 auto const settleDelay = 3600s;
1176 auto const channelFunds =
XRP(1000);
1178 env(
create(alice, bob, channelFunds, settleDelay, pk));
1183 env.rpc(
"account_channels", alice.human(), bob.human());
1184 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1186 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1187 BEAST_EXPECT(r[jss::result][jss::validated]);
1189 r[jss::result][jss::channels][0u][jss::public_key].asString();
1192 auto const r = env.rpc(
"account_channels", alice.human());
1193 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1195 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1196 BEAST_EXPECT(r[jss::result][jss::validated]);
1198 r[jss::result][jss::channels][0u][jss::public_key].asString();
1202 env.rpc(
"account_channels", bob.human(), alice.human());
1203 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1204 BEAST_EXPECT(r[jss::result][jss::validated]);
1207 env(
create(alice, bob, channelFunds, settleDelay, pk));
1211 env.rpc(
"account_channels", alice.human(), bob.human());
1212 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1213 BEAST_EXPECT(r[jss::result][jss::validated]);
1214 BEAST_EXPECT(chan1Str != chan2Str);
1215 for (
auto const& c : {chan1Str, chan2Str})
1217 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1218 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1224 for (
int i = 0; i < slice.size(); ++i)
1226 s +=
"0123456789ABCDEF"[((slice[i] & 0xf0) >> 4)];
1227 s +=
"0123456789ABCDEF"[((slice[i] & 0x0f) >> 0)];
1235 env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000");
1236 auto const sig = rs[jss::result][jss::signature].asString();
1237 BEAST_EXPECT(!
sig.empty());
1239 auto const rv = env.rpc(
1240 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1241 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1248 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1249 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1255 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000x",
sig);
1256 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1257 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 ",
sig);
1258 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1259 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x1000",
sig);
1260 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1261 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x",
sig);
1262 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1263 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" ",
sig);
1264 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1266 "channel_verify", pkAsHex, chan1Str,
"1000 1000",
sig);
1267 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1268 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1,000",
sig);
1269 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1270 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" 1000",
sig);
1271 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1272 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"",
sig);
1273 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1278 auto chan1StrBad = chan1Str;
1279 chan1StrBad.pop_back();
1281 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1282 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1283 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1284 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1286 chan1StrBad = chan1Str;
1287 chan1StrBad.push_back(
'0');
1289 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1290 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1291 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1292 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1294 chan1StrBad = chan1Str;
1295 chan1StrBad.back() =
'x';
1297 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1298 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1299 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1300 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1304 auto illFormedPk = chan1PkStr.
substr(0, chan1PkStr.
size() - 1);
1305 auto const rv = env.rpc(
1306 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1308 !rv[jss::result][jss::signature_verified].asBool());
1313 auto illFormedPk = pkAsHex.substr(0, chan1PkStr.
size() - 1);
1314 auto const rv = env.rpc(
1315 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1317 !rv[jss::result][jss::signature_verified].asBool());
1323 env.rpc(
"channel_authorize",
"alice", chan2Str,
"1000");
1324 auto const sig = rs[jss::result][jss::signature].asString();
1325 BEAST_EXPECT(!
sig.empty());
1327 auto const rv = env.rpc(
1328 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1330 !rv[jss::result][jss::signature_verified].asBool());
1336 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1338 !rv[jss::result][jss::signature_verified].asBool());
1346 charlie, alice, channelFunds, settleDelay, charlie.pk()));
1352 env.rpc(
"account_channels", charlie.human(), alice.human());
1353 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1355 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1356 BEAST_EXPECT(r[jss::result][jss::validated]);
1357 cpk = r[jss::result][jss::channels][0u][jss::public_key]
1363 env.rpc(
"channel_authorize",
"charlie", chan,
"1000");
1364 auto const sig = rs[jss::result][jss::signature].asString();
1365 BEAST_EXPECT(!
sig.empty());
1368 env.rpc(
"channel_verify", cpk, chan,
"1000",
sig);
1370 !rv[jss::result][jss::signature_verified].asBool());
1375 env.rpc(
"channel_authorize",
"charlie",
"nyx", chan,
"1000");
1376 BEAST_EXPECT(rs1[jss::error] ==
"badKeyType");
1380 auto const rs2 = env.rpc(
1381 "channel_authorize",
"charlie",
"secp256k1", chan,
"1000");
1382 auto const sig2 = rs2[jss::result][jss::signature].asString();
1383 BEAST_EXPECT(!sig2.empty());
1386 env.rpc(
"channel_verify", cpk, chan,
"1000", sig2);
1388 !rv[jss::result][jss::signature_verified].asBool());
1392 auto const rs3 = env.rpc(
1393 "channel_authorize",
"charlie",
"ed25519", chan,
"1000");
1394 auto const sig3 = rs3[jss::result][jss::signature].asString();
1395 BEAST_EXPECT(!sig3.empty());
1398 env.rpc(
"channel_verify", cpk, chan,
"1000", sig3);
1399 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1405 auto rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000x");
1406 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1407 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x1000");
1408 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1409 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x");
1410 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1414 args[jss::amount] =
"2000";
1415 args[jss::key_type] =
"secp256k1";
1416 args[jss::passphrase] =
"passphrase_can_be_anything";
1419 "channel_authorize",
1420 args.toStyledString())[jss::result];
1421 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1426 args[jss::channel_id] = chan1Str;
1427 args[jss::key_type] =
"secp256k1";
1428 args[jss::passphrase] =
"passphrase_can_be_anything";
1431 "channel_authorize",
1432 args.toStyledString())[jss::result];
1433 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1438 args[jss::amount] =
"2000";
1439 args[jss::channel_id] = chan1Str;
1440 args[jss::passphrase] =
"passphrase_can_be_anything";
1443 "channel_authorize",
1444 args.toStyledString())[jss::result];
1445 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1450 args[jss::amount] =
"2000";
1451 args[jss::channel_id] = chan1Str;
1452 args[jss::key_type] =
"secp256k1";
1453 args[jss::passphrase] =
"passphrase_can_be_anything";
1454 args[jss::seed] =
"seed can be anything";
1457 "channel_authorize",
1458 args.toStyledString())[jss::result];
1459 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1464 args[jss::amount] =
"2000";
1465 args[jss::channel_id] = chan1Str +
"1";
1466 args[jss::key_type] =
"secp256k1";
1467 args[jss::passphrase] =
"passphrase_can_be_anything";
1470 "channel_authorize",
1471 args.toStyledString())[jss::result];
1472 BEAST_EXPECT(rs[jss::error] ==
"channelMalformed");
1477 args[jss::amount] = 2000;
1478 args[jss::channel_id] = chan1Str;
1479 args[jss::key_type] =
"secp256k1";
1480 args[jss::passphrase] =
"passphrase_can_be_anything";
1483 "channel_authorize",
1484 args.toStyledString())[jss::result];
1485 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1490 args[jss::amount] =
"TwoThousand";
1491 args[jss::channel_id] = chan1Str;
1492 args[jss::key_type] =
"secp256k1";
1493 args[jss::passphrase] =
"passphrase_can_be_anything";
1496 "channel_authorize",
1497 args.toStyledString())[jss::result];
1498 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1506 testcase(
"Optional Fields");
1507 using namespace jtx;
1508 using namespace std::literals::chrono_literals;
1509 Env env{*
this, features};
1510 auto const alice =
Account(
"alice");
1511 auto const bob =
Account(
"bob");
1512 auto const carol =
Account(
"carol");
1513 auto const dan =
Account(
"dan");
1514 env.fund(
XRP(10000), alice, bob, carol, dan);
1515 auto const pk = alice.pk();
1516 auto const settleDelay = 3600s;
1517 auto const channelFunds =
XRP(1000);
1523 env(
create(alice, bob, channelFunds, settleDelay, pk));
1525 env.rpc(
"account_channels", alice.human(), bob.human());
1526 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1528 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1529 BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember(
1530 jss::destination_tag));
1544 env.rpc(
"account_channels", alice.human(), carol.human());
1545 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1547 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1549 r[jss::result][jss::channels][0u][jss::destination_tag] ==
1557 testcase(
"malformed pk");
1558 using namespace jtx;
1559 using namespace std::literals::chrono_literals;
1560 Env env{*
this, features};
1561 auto const alice =
Account(
"alice");
1562 auto const bob =
Account(
"bob");
1563 auto USDA = alice[
"USD"];
1564 env.fund(
XRP(10000), alice, bob);
1565 auto const pk = alice.pk();
1566 auto const settleDelay = 100s;
1568 auto const chan =
channel(alice, bob, env.seq(alice));
1569 auto jv =
create(alice, bob,
XRP(1000), settleDelay, pk);
1570 auto const pkHex =
strHex(pk.slice());
1571 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1573 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1575 auto badPrefix = pkHex;
1578 jv[
"PublicKey"] = badPrefix;
1581 jv[
"PublicKey"] = pkHex;
1584 auto const authAmt =
XRP(100);
1593 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1595 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1600 jv[
"PublicKey"] = badPrefix;
1604 jv.removeMember(
"PublicKey");
1608 auto const txn = R
"*(
1611 "channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
1613 "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
1615 "aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
1619 auto const r = env.rpc(
"json",
"channel_verify", txn);
1620 BEAST_EXPECT(r[
"result"][
"error"] ==
"publicMalformed");
1627 testcase(
"Metadata & Ownership");
1629 using namespace jtx;
1630 using namespace std::literals::chrono_literals;
1632 auto const alice =
Account(
"alice");
1633 auto const bob =
Account(
"bob");
1634 auto const settleDelay = 100s;
1635 auto const pk = alice.pk();
1637 auto inOwnerDir = [](
ReadView const& view,
1641 return std::find(ownerDir.begin(), ownerDir.end(), chan) !=
1645 auto ownerDirCount = [](
ReadView const& view,
1655 env.
fund(
XRP(10000), alice, bob);
1656 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1658 auto const [chan, chanSle] =
1660 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1661 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1662 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1663 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1667 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1668 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1669 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1670 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1675 Env env{*
this, features};
1676 env.fund(
XRP(10000), alice, bob);
1677 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1679 auto const [chan, chanSle] =
1681 BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle));
1682 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
1683 BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle));
1684 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 1);
1688 BEAST_EXPECT(!inOwnerDir(*env.current(), alice, chanSle));
1689 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 0);
1690 BEAST_EXPECT(!inOwnerDir(*env.current(), bob, chanSle));
1691 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 0);
1698 env.
fund(
XRP(10000), alice, bob);
1700 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1702 auto const [chan, chanSle] =
1704 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1705 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1706 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1707 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1716 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1717 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1718 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1723 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1724 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1725 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1726 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1733 testcase(
"Account Delete");
1734 using namespace test::jtx;
1735 using namespace std::literals::chrono_literals;
1736 auto rmAccount = [
this](
1743 for (
auto minRmSeq = env.
seq(toRm) + 257;
1744 env.
current()->seq() < minRmSeq;
1758 auto const alice =
Account(
"alice");
1759 auto const bob =
Account(
"bob");
1760 auto const carol =
Account(
"carol");
1762 for (
bool const withOwnerDirFix : {
false,
true})
1764 auto const amd = withOwnerDirFix
1767 Env env{*
this, amd};
1768 env.
fund(
XRP(10000), alice, bob, carol);
1770 auto const feeDrops = env.
current()->fees().base;
1773 auto const pk = alice.pk();
1774 auto const settleDelay = 100s;
1775 auto const chan =
channel(alice, bob, env.
seq(alice));
1776 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1791 BEAST_EXPECT(chanBal ==
XRP(0));
1792 BEAST_EXPECT(chanAmt ==
XRP(1000));
1794 auto preBob = env.
balance(bob);
1795 auto const delta =
XRP(50);
1796 auto reqBal = chanBal + delta;
1797 auto authAmt = reqBal +
XRP(100);
1798 assert(reqBal <= chanAmt);
1801 if (withOwnerDirFix)
1803 env(
claim(alice, chan, reqBal, authAmt));
1807 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1812 auto const preAlice = env.
balance(alice);
1817 BEAST_EXPECT(env.
balance(bob) == preBob);
1818 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1822 if (withOwnerDirFix)
1824 auto const preAlice = env.
balance(alice);
1825 env(
fund(alice, chan,
XRP(1000)));
1828 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1831 chanAmt = chanAmt +
XRP(1000);
1835 auto const preAlice = env.
balance(alice);
1838 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1848 auto const closeTime = env.
current()->info().parentCloseTime;
1849 auto const minExpiration = closeTime + settleDelay;
1850 env.
close(minExpiration);
1859 env.
fund(
XRP(10000), alice, bob, carol);
1861 auto const feeDrops = env.
current()->fees().base;
1864 auto const pk = alice.pk();
1865 auto const settleDelay = 100s;
1866 auto const chan =
channel(alice, bob, env.
seq(alice));
1867 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1873 rmAccount(env, bob, carol);
1878 BEAST_EXPECT(chanBal ==
XRP(0));
1879 BEAST_EXPECT(chanAmt ==
XRP(1000));
1880 auto preBob = env.
balance(bob);
1881 auto const delta =
XRP(50);
1882 auto reqBal = chanBal + delta;
1883 auto authAmt = reqBal +
XRP(100);
1884 assert(reqBal <= chanAmt);
1888 auto const preAlice = env.
balance(alice);
1893 BEAST_EXPECT(env.
balance(bob) == preBob);
1894 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1899 auto const preAlice = env.
balance(alice);
1902 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1907 env(
pay(alice, bob,
XRP(20)));
1914 reqBal = chanBal + delta;
1915 authAmt = reqBal +
XRP(100);
1916 env(
claim(alice, chan, reqBal, authAmt));
1919 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1926 reqBal = chanBal + delta;
1927 authAmt = reqBal +
XRP(100);
1930 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
1933 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
1939 auto const preAlice = env.
balance(alice);
1940 env(
fund(alice, chan,
XRP(1000)));
1942 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1945 chanAmt = chanAmt +
XRP(1000);
1954 auto const closeTime = env.
current()->info().parentCloseTime;
1955 auto const minExpiration = closeTime + settleDelay;
1956 env.
close(minExpiration);
1966 testcase(
"using tickets");
1967 using namespace jtx;
1968 using namespace std::literals::chrono_literals;
1969 Env env{*
this, features};
1970 auto const alice =
Account(
"alice");
1971 auto const bob =
Account(
"bob");
1972 auto USDA = alice[
"USD"];
1973 env.fund(
XRP(10000), alice, bob);
1979 env(ticket::create(alice, 10));
1983 env(ticket::create(bob, 10));
1986 auto const pk = alice.pk();
1987 auto const settleDelay = 100s;
1988 auto const chan =
channel(alice, bob, aliceTicketSeq);
1990 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
1993 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1994 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2000 auto const preAlice = env.balance(alice);
2003 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2004 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2006 auto const feeDrops = env.current()->fees().base;
2007 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
2012 BEAST_EXPECT(chanBal ==
XRP(0));
2013 BEAST_EXPECT(chanAmt ==
XRP(2000));
2017 auto const preBob = env.balance(bob);
2018 auto const delta =
XRP(500);
2019 auto const reqBal = chanBal + delta;
2020 auto const authAmt = reqBal +
XRP(100);
2021 assert(reqBal <= chanAmt);
2022 env(
claim(alice, chan, reqBal, authAmt),
2025 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2026 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2029 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2030 BEAST_EXPECT(env.balance(bob) == preBob + delta);
2035 auto preBob = env.balance(bob);
2036 auto const delta =
XRP(500);
2037 auto const reqBal = chanBal + delta;
2038 auto const authAmt = reqBal +
XRP(100);
2039 assert(reqBal <= chanAmt);
2042 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
2045 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2046 BEAST_EXPECT(env.seq(bob) == bobSeq);
2049 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2050 auto const feeDrops = env.current()->fees().base;
2051 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
2055 preBob = env.balance(bob);
2057 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
2061 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2062 BEAST_EXPECT(env.seq(bob) == bobSeq);
2065 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2066 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2070 auto const preBob = env.balance(bob);
2073 assert(reqAmt <= chanAmt);
2078 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
2082 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2083 BEAST_EXPECT(env.seq(bob) == bobSeq);
2086 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2087 BEAST_EXPECT(env.balance(bob) == preBob);
2091 env(
fund(bob, chan,
XRP(1000)),
2095 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2096 BEAST_EXPECT(env.seq(bob) == bobSeq);
2099 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2103 auto const preAlice = env.balance(alice);
2104 auto const preBob = env.balance(bob);
2105 env(
claim(bob, chan),
2109 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2110 BEAST_EXPECT(env.seq(bob) == bobSeq);
2113 auto const feeDrops = env.current()->fees().base;
2114 auto const delta = chanAmt - chanBal;
2115 assert(delta > beast::zero);
2116 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
2117 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2119 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2120 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2121 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2122 BEAST_EXPECT(env.seq(bob) == bobSeq);
2154 using namespace test::jtx;