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>
28 #include <test/jtx/TestHelpers.h>
48 return {k.key, view.
read(k)};
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);
261 testcase(
"Disallow Incoming Flag");
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),
345 testcase(
"cancel after");
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);
410 testcase(
"expiration");
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);
476 testcase(
"settle delay");
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);
536 testcase(
"close dry");
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);
571 testcase(
"default amount");
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);
626 testcase(
"Disallow XRP");
628 using namespace std::literals::chrono_literals;
630 auto const alice =
Account(
"alice");
631 auto const bob =
Account(
"bob");
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()));
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));
715 testcase(
"Deposit Authorization");
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();
788 env(deposit::auth(bob, carol));
802 env(deposit::auth(bob, alice));
809 env.balance(bob) == preBob + delta - (3 * baseFee));
814 auto const delta =
XRP(800).value();
816 env(deposit::unauth(bob, alice));
828 env(
claim(alice, chan, delta, delta));
831 env.balance(bob) == preBob +
XRP(800) - (5 * baseFee));
840 testcase(
"Multiple channels to the same account");
842 using namespace std::literals::chrono_literals;
843 Env env{*
this, features};
844 auto const alice =
Account(
"alice");
845 auto const bob =
Account(
"bob");
846 env.fund(
XRP(10000), alice, bob);
847 auto const pk = alice.pk();
848 auto const settleDelay = 3600s;
849 auto const channelFunds =
XRP(1000);
850 auto const chan1 =
channel(alice, bob, env.seq(alice));
851 env(create(alice, bob, channelFunds, settleDelay, pk));
853 auto const chan2 =
channel(alice, bob, env.seq(alice));
854 env(create(alice, bob, channelFunds, settleDelay, pk));
856 BEAST_EXPECT(chan1 != chan2);
862 testcase(
"AccountChannels RPC");
865 using namespace std::literals::chrono_literals;
866 Env env{*
this, features};
867 auto const alice =
Account(
"alice");
868 auto const bob =
Account(
"bob");
870 env.fund(
XRP(10000), alice, bob, charlie);
871 auto const pk = alice.pk();
872 auto const settleDelay = 3600s;
873 auto const channelFunds =
XRP(1000);
875 env(create(alice, bob, channelFunds, settleDelay, pk));
879 env.rpc(
"account_channels", alice.human(), bob.human());
880 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
882 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
883 BEAST_EXPECT(r[jss::result][jss::validated]);
886 auto const r = env.rpc(
"account_channels", alice.human());
887 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
889 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
890 BEAST_EXPECT(r[jss::result][jss::validated]);
894 env.rpc(
"account_channels", bob.human(), alice.human());
895 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
896 BEAST_EXPECT(r[jss::result][jss::validated]);
899 env(create(alice, bob, channelFunds, settleDelay, pk));
903 env.rpc(
"account_channels", alice.human(), bob.human());
904 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
905 BEAST_EXPECT(r[jss::result][jss::validated]);
906 BEAST_EXPECT(chan1Str != chan2Str);
907 for (
auto const& c : {chan1Str, chan2Str})
909 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
910 r[jss::result][jss::channels][1u][jss::channel_id] == c);
917 testcase(
"Account channels RPC markers");
919 using namespace test::jtx;
920 using namespace std::literals;
922 auto const alice =
Account(
"alice");
927 for (
int i = 0; i < n; ++i)
934 Env env{*
this, features};
935 env.fund(
XRP(10000), alice);
936 for (
auto const& a : bobs)
938 env.fund(
XRP(10000), a);
944 auto const settleDelay = 3600s;
945 auto const channelFunds =
XRP(1);
946 for (
auto const& b : bobs)
948 env(create(alice, b, channelFunds, settleDelay, alice.pk()));
959 jvc[jss::account] = src.human();
961 jvc[jss::destination_account] = dst->human();
963 jvc[jss::limit] = *limit;
965 jvc[jss::marker] = marker;
968 "json",
"account_channels",
to_string(jvc))[jss::result];
973 auto const r = testLimit(env, alice);
974 BEAST_EXPECT(r.isMember(jss::channels));
975 BEAST_EXPECT(r[jss::channels].size() == bobs.size());
980 for (
auto const& a : bobs)
985 for (
int limit = 1; limit < bobs.size() + 1; ++limit)
987 auto leftToFind = bobsB58;
988 auto const numFull = bobs.
size() / limit;
989 auto const numNonFull = bobs.size() % limit ? 1 : 0;
993 auto const testIt = [&](
bool expectMarker,
int expectedBatchSize) {
994 auto const r = testLimit(env, alice, limit, marker);
995 BEAST_EXPECT(!expectMarker || r.isMember(jss::marker));
996 if (r.isMember(jss::marker))
997 marker = r[jss::marker];
998 BEAST_EXPECT(r[jss::channels].size() == expectedBatchSize);
999 auto const c = r[jss::channels];
1000 auto const s = r[jss::channels].size();
1001 for (
int j = 0; j < s; ++j)
1004 c[j][jss::destination_account].asString();
1005 BEAST_EXPECT(leftToFind.count(dstAcc));
1006 leftToFind.erase(dstAcc);
1010 for (
int i = 0; i < numFull; ++i)
1012 bool const expectMarker = (numNonFull != 0 || i < numFull - 1);
1013 testIt(expectMarker, limit);
1018 testIt(
false, bobs.size() % limit);
1020 BEAST_EXPECT(leftToFind.empty());
1025 auto const r = testLimit(env, alice, 0);
1026 BEAST_EXPECT(r.isMember(jss::error_message));
1035 testcase(
"Account channels RPC owner only");
1037 using namespace test::jtx;
1038 using namespace std::literals;
1040 auto const alice =
Account(
"alice");
1041 auto const bob =
Account(
"bob");
1042 Env env{*
this, features};
1043 env.fund(
XRP(10000), alice, bob);
1048 auto const settleDelay = 3600s;
1049 auto const channelFunds =
XRP(1000);
1050 env(create(alice, bob, channelFunds, settleDelay, alice.pk()));
1051 env(create(bob, alice, channelFunds, settleDelay, bob.pk()));
1053 auto const r = [&] {
1055 jvc[jss::account] = alice.human();
1058 "json",
"account_channels",
to_string(jvc))[jss::result];
1060 BEAST_EXPECT(r.isMember(jss::channels));
1061 BEAST_EXPECT(r[jss::channels].size() == 1);
1063 r[jss::channels][0u][jss::destination_account].asString() ==
1070 testcase(
"PayChan Auth/Verify RPC");
1071 using namespace jtx;
1072 using namespace std::literals::chrono_literals;
1073 Env env{*
this, features};
1074 auto const alice =
Account(
"alice");
1075 auto const bob =
Account(
"bob");
1077 env.fund(
XRP(10000), alice, bob, charlie);
1078 auto const pk = alice.pk();
1079 auto const settleDelay = 3600s;
1080 auto const channelFunds =
XRP(1000);
1082 env(create(alice, bob, channelFunds, settleDelay, pk));
1087 env.rpc(
"account_channels", alice.human(), bob.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]);
1093 r[jss::result][jss::channels][0u][jss::public_key].asString();
1096 auto const r = env.rpc(
"account_channels", alice.human());
1097 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1099 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1100 BEAST_EXPECT(r[jss::result][jss::validated]);
1102 r[jss::result][jss::channels][0u][jss::public_key].asString();
1106 env.rpc(
"account_channels", bob.human(), alice.human());
1107 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1108 BEAST_EXPECT(r[jss::result][jss::validated]);
1111 env(create(alice, bob, channelFunds, settleDelay, pk));
1115 env.rpc(
"account_channels", alice.human(), bob.human());
1116 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1117 BEAST_EXPECT(r[jss::result][jss::validated]);
1118 BEAST_EXPECT(chan1Str != chan2Str);
1119 for (
auto const& c : {chan1Str, chan2Str})
1121 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1122 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1128 for (
int i = 0; i < slice.size(); ++i)
1130 s +=
"0123456789ABCDEF"[((slice[i] & 0xf0) >> 4)];
1131 s +=
"0123456789ABCDEF"[((slice[i] & 0x0f) >> 0)];
1139 env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000");
1140 auto const sig = rs[jss::result][jss::signature].asString();
1141 BEAST_EXPECT(!
sig.empty());
1143 auto const rv = env.rpc(
1144 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1145 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1152 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1153 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1159 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000x",
sig);
1160 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1161 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 ",
sig);
1162 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1163 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x1000",
sig);
1164 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1165 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x",
sig);
1166 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1167 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" ",
sig);
1168 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1170 "channel_verify", pkAsHex, chan1Str,
"1000 1000",
sig);
1171 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1172 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1,000",
sig);
1173 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1174 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" 1000",
sig);
1175 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1176 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"",
sig);
1177 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1182 auto chan1StrBad = chan1Str;
1183 chan1StrBad.pop_back();
1185 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1186 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1187 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1188 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1190 chan1StrBad = chan1Str;
1191 chan1StrBad.push_back(
'0');
1193 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1194 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1195 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1196 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1198 chan1StrBad = chan1Str;
1199 chan1StrBad.back() =
'x';
1201 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1202 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1203 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1204 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1208 auto illFormedPk = chan1PkStr.
substr(0, chan1PkStr.
size() - 1);
1209 auto const rv = env.rpc(
1210 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1212 !rv[jss::result][jss::signature_verified].asBool());
1217 auto illFormedPk = pkAsHex.substr(0, chan1PkStr.
size() - 1);
1218 auto const rv = env.rpc(
1219 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1221 !rv[jss::result][jss::signature_verified].asBool());
1227 env.rpc(
"channel_authorize",
"alice", chan2Str,
"1000");
1228 auto const sig = rs[jss::result][jss::signature].asString();
1229 BEAST_EXPECT(!
sig.empty());
1231 auto const rv = env.rpc(
1232 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1234 !rv[jss::result][jss::signature_verified].asBool());
1240 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1242 !rv[jss::result][jss::signature_verified].asBool());
1250 charlie, alice, channelFunds, settleDelay, charlie.pk()));
1256 env.rpc(
"account_channels", charlie.human(), alice.human());
1257 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1259 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1260 BEAST_EXPECT(r[jss::result][jss::validated]);
1261 cpk = r[jss::result][jss::channels][0u][jss::public_key]
1267 env.rpc(
"channel_authorize",
"charlie", chan,
"1000");
1268 auto const sig = rs[jss::result][jss::signature].asString();
1269 BEAST_EXPECT(!
sig.empty());
1272 env.rpc(
"channel_verify", cpk, chan,
"1000",
sig);
1274 !rv[jss::result][jss::signature_verified].asBool());
1279 env.rpc(
"channel_authorize",
"charlie",
"nyx", chan,
"1000");
1280 BEAST_EXPECT(rs1[jss::error] ==
"badKeyType");
1284 auto const rs2 = env.rpc(
1285 "channel_authorize",
"charlie",
"secp256k1", chan,
"1000");
1286 auto const sig2 = rs2[jss::result][jss::signature].asString();
1287 BEAST_EXPECT(!sig2.empty());
1290 env.rpc(
"channel_verify", cpk, chan,
"1000", sig2);
1292 !rv[jss::result][jss::signature_verified].asBool());
1296 auto const rs3 = env.rpc(
1297 "channel_authorize",
"charlie",
"ed25519", chan,
"1000");
1298 auto const sig3 = rs3[jss::result][jss::signature].asString();
1299 BEAST_EXPECT(!sig3.empty());
1302 env.rpc(
"channel_verify", cpk, chan,
"1000", sig3);
1303 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1309 auto rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000x");
1310 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1311 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x1000");
1312 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1313 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x");
1314 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1318 args[jss::amount] =
"2000";
1319 args[jss::key_type] =
"secp256k1";
1320 args[jss::passphrase] =
"passphrase_can_be_anything";
1323 "channel_authorize",
1324 args.toStyledString())[jss::result];
1325 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1330 args[jss::channel_id] = chan1Str;
1331 args[jss::key_type] =
"secp256k1";
1332 args[jss::passphrase] =
"passphrase_can_be_anything";
1335 "channel_authorize",
1336 args.toStyledString())[jss::result];
1337 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1342 args[jss::amount] =
"2000";
1343 args[jss::channel_id] = chan1Str;
1344 args[jss::passphrase] =
"passphrase_can_be_anything";
1347 "channel_authorize",
1348 args.toStyledString())[jss::result];
1349 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1354 args[jss::amount] =
"2000";
1355 args[jss::channel_id] = chan1Str;
1356 args[jss::key_type] =
"secp256k1";
1357 args[jss::passphrase] =
"passphrase_can_be_anything";
1358 args[jss::seed] =
"seed can be anything";
1361 "channel_authorize",
1362 args.toStyledString())[jss::result];
1363 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1368 args[jss::amount] =
"2000";
1369 args[jss::channel_id] = chan1Str +
"1";
1370 args[jss::key_type] =
"secp256k1";
1371 args[jss::passphrase] =
"passphrase_can_be_anything";
1374 "channel_authorize",
1375 args.toStyledString())[jss::result];
1376 BEAST_EXPECT(rs[jss::error] ==
"channelMalformed");
1381 args[jss::amount] = 2000;
1382 args[jss::channel_id] = chan1Str;
1383 args[jss::key_type] =
"secp256k1";
1384 args[jss::passphrase] =
"passphrase_can_be_anything";
1387 "channel_authorize",
1388 args.toStyledString())[jss::result];
1389 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1394 args[jss::amount] =
"TwoThousand";
1395 args[jss::channel_id] = chan1Str;
1396 args[jss::key_type] =
"secp256k1";
1397 args[jss::passphrase] =
"passphrase_can_be_anything";
1400 "channel_authorize",
1401 args.toStyledString())[jss::result];
1402 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1410 testcase(
"Optional Fields");
1411 using namespace jtx;
1412 using namespace std::literals::chrono_literals;
1413 Env env{*
this, features};
1414 auto const alice =
Account(
"alice");
1415 auto const bob =
Account(
"bob");
1416 auto const carol =
Account(
"carol");
1417 auto const dan =
Account(
"dan");
1418 env.fund(
XRP(10000), alice, bob, carol, dan);
1419 auto const pk = alice.pk();
1420 auto const settleDelay = 3600s;
1421 auto const channelFunds =
XRP(1000);
1427 env(create(alice, bob, channelFunds, settleDelay, pk));
1429 env.rpc(
"account_channels", alice.human(), bob.human());
1430 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1432 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1433 BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember(
1434 jss::destination_tag));
1448 env.rpc(
"account_channels", alice.human(), carol.human());
1449 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1451 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1453 r[jss::result][jss::channels][0u][jss::destination_tag] ==
1461 testcase(
"malformed pk");
1462 using namespace jtx;
1463 using namespace std::literals::chrono_literals;
1464 Env env{*
this, features};
1465 auto const alice =
Account(
"alice");
1466 auto const bob =
Account(
"bob");
1467 auto USDA = alice[
"USD"];
1468 env.fund(
XRP(10000), alice, bob);
1469 auto const pk = alice.pk();
1470 auto const settleDelay = 100s;
1472 auto const chan =
channel(alice, bob, env.seq(alice));
1473 auto jv = create(alice, bob,
XRP(1000), settleDelay, pk);
1474 auto const pkHex =
strHex(pk.slice());
1475 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1477 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1479 auto badPrefix = pkHex;
1482 jv[
"PublicKey"] = badPrefix;
1485 jv[
"PublicKey"] = pkHex;
1488 auto const authAmt =
XRP(100);
1497 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1499 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1504 jv[
"PublicKey"] = badPrefix;
1508 jv.removeMember(
"PublicKey");
1512 auto const txn = R
"*(
1515 "channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
1517 "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
1519 "aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
1523 auto const r = env.rpc(
"json",
"channel_verify", txn);
1524 BEAST_EXPECT(r[
"result"][
"error"] ==
"publicMalformed");
1531 testcase(
"Metadata & Ownership");
1533 using namespace jtx;
1534 using namespace std::literals::chrono_literals;
1536 auto const alice =
Account(
"alice");
1537 auto const bob =
Account(
"bob");
1538 auto const settleDelay = 100s;
1539 auto const pk = alice.pk();
1541 auto inOwnerDir = [](
ReadView const& view,
1545 return std::find(ownerDir.begin(), ownerDir.end(), chan) !=
1549 auto ownerDirCount = [](
ReadView const& view,
1559 env.
fund(
XRP(10000), alice, bob);
1560 env(create(alice, bob,
XRP(1000), settleDelay, pk));
1562 auto const [chan, chanSle] =
1564 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1565 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1566 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1567 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1571 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1572 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1573 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1574 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1579 Env env{*
this, features};
1580 env.fund(
XRP(10000), alice, bob);
1581 env(create(alice, bob,
XRP(1000), settleDelay, pk));
1583 auto const [chan, chanSle] =
1585 BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle));
1586 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
1587 BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle));
1588 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 1);
1592 BEAST_EXPECT(!inOwnerDir(*env.current(), alice, chanSle));
1593 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 0);
1594 BEAST_EXPECT(!inOwnerDir(*env.current(), bob, chanSle));
1595 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 0);
1602 env.
fund(
XRP(10000), alice, bob);
1604 env(create(alice, bob,
XRP(1000), settleDelay, pk));
1606 auto const [chan, chanSle] =
1608 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1609 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1610 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1611 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1620 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1621 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1622 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1627 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1628 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1629 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1630 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1637 testcase(
"Account Delete");
1638 using namespace test::jtx;
1639 using namespace std::literals::chrono_literals;
1640 auto rmAccount = [
this](
1647 for (
auto minRmSeq = env.
seq(toRm) + 257;
1648 env.
current()->seq() < minRmSeq;
1662 auto const alice =
Account(
"alice");
1663 auto const bob =
Account(
"bob");
1664 auto const carol =
Account(
"carol");
1666 for (
bool const withOwnerDirFix : {
false,
true})
1668 auto const amd = withOwnerDirFix
1671 Env env{*
this, amd};
1672 env.
fund(
XRP(10000), alice, bob, carol);
1674 auto const feeDrops = env.
current()->fees().base;
1677 auto const pk = alice.pk();
1678 auto const settleDelay = 100s;
1679 auto const chan =
channel(alice, bob, env.
seq(alice));
1680 env(create(alice, bob,
XRP(1000), settleDelay, pk));
1695 BEAST_EXPECT(chanBal ==
XRP(0));
1696 BEAST_EXPECT(chanAmt ==
XRP(1000));
1698 auto preBob = env.
balance(bob);
1699 auto const delta =
XRP(50);
1700 auto reqBal = chanBal + delta;
1701 auto authAmt = reqBal +
XRP(100);
1702 assert(reqBal <= chanAmt);
1705 if (withOwnerDirFix)
1707 env(
claim(alice, chan, reqBal, authAmt));
1711 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1716 auto const preAlice = env.
balance(alice);
1721 BEAST_EXPECT(env.
balance(bob) == preBob);
1722 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1726 if (withOwnerDirFix)
1728 auto const preAlice = env.
balance(alice);
1729 env(
fund(alice, chan,
XRP(1000)));
1732 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1735 chanAmt = chanAmt +
XRP(1000);
1739 auto const preAlice = env.
balance(alice);
1742 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1752 auto const closeTime = env.
current()->info().parentCloseTime;
1753 auto const minExpiration = closeTime + settleDelay;
1754 env.
close(minExpiration);
1763 env.
fund(
XRP(10000), alice, bob, carol);
1765 auto const feeDrops = env.
current()->fees().base;
1768 auto const pk = alice.pk();
1769 auto const settleDelay = 100s;
1770 auto const chan =
channel(alice, bob, env.
seq(alice));
1771 env(create(alice, bob,
XRP(1000), settleDelay, pk));
1777 rmAccount(env, bob, carol);
1782 BEAST_EXPECT(chanBal ==
XRP(0));
1783 BEAST_EXPECT(chanAmt ==
XRP(1000));
1784 auto preBob = env.
balance(bob);
1785 auto const delta =
XRP(50);
1786 auto reqBal = chanBal + delta;
1787 auto authAmt = reqBal +
XRP(100);
1788 assert(reqBal <= chanAmt);
1792 auto const preAlice = env.
balance(alice);
1797 BEAST_EXPECT(env.
balance(bob) == preBob);
1798 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1803 auto const preAlice = env.
balance(alice);
1806 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1811 env(pay(alice, bob,
XRP(20)));
1818 reqBal = chanBal + delta;
1819 authAmt = reqBal +
XRP(100);
1820 env(
claim(alice, chan, reqBal, authAmt));
1823 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1830 reqBal = chanBal + delta;
1831 authAmt = reqBal +
XRP(100);
1834 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
1837 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
1843 auto const preAlice = env.
balance(alice);
1844 env(
fund(alice, chan,
XRP(1000)));
1846 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1849 chanAmt = chanAmt +
XRP(1000);
1858 auto const closeTime = env.
current()->info().parentCloseTime;
1859 auto const minExpiration = closeTime + settleDelay;
1860 env.
close(minExpiration);
1870 testcase(
"using tickets");
1871 using namespace jtx;
1872 using namespace std::literals::chrono_literals;
1873 Env env{*
this, features};
1874 auto const alice =
Account(
"alice");
1875 auto const bob =
Account(
"bob");
1876 auto USDA = alice[
"USD"];
1877 env.fund(
XRP(10000), alice, bob);
1883 env(ticket::create(alice, 10));
1887 env(ticket::create(bob, 10));
1890 auto const pk = alice.pk();
1891 auto const settleDelay = 100s;
1892 auto const chan =
channel(alice, bob, aliceTicketSeq);
1894 env(create(alice, bob,
XRP(1000), settleDelay, pk),
1897 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1898 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1904 auto const preAlice = env.balance(alice);
1907 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1908 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1910 auto const feeDrops = env.current()->fees().base;
1911 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
1916 BEAST_EXPECT(chanBal ==
XRP(0));
1917 BEAST_EXPECT(chanAmt ==
XRP(2000));
1921 auto const preBob = env.balance(bob);
1922 auto const delta =
XRP(500);
1923 auto const reqBal = chanBal + delta;
1924 auto const authAmt = reqBal +
XRP(100);
1925 assert(reqBal <= chanAmt);
1926 env(
claim(alice, chan, reqBal, authAmt),
1929 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1930 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1933 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1934 BEAST_EXPECT(env.balance(bob) == preBob + delta);
1939 auto preBob = env.balance(bob);
1940 auto const delta =
XRP(500);
1941 auto const reqBal = chanBal + delta;
1942 auto const authAmt = reqBal +
XRP(100);
1943 assert(reqBal <= chanAmt);
1946 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
1949 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
1950 BEAST_EXPECT(env.seq(bob) == bobSeq);
1953 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1954 auto const feeDrops = env.current()->fees().base;
1955 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
1959 preBob = env.balance(bob);
1961 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
1965 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
1966 BEAST_EXPECT(env.seq(bob) == bobSeq);
1969 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1970 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
1974 auto const preBob = env.balance(bob);
1977 assert(reqAmt <= chanAmt);
1982 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
1986 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
1987 BEAST_EXPECT(env.seq(bob) == bobSeq);
1990 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1991 BEAST_EXPECT(env.balance(bob) == preBob);
1995 env(
fund(bob, chan,
XRP(1000)),
1999 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2000 BEAST_EXPECT(env.seq(bob) == bobSeq);
2003 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2007 auto const preAlice = env.balance(alice);
2008 auto const preBob = env.balance(bob);
2009 env(
claim(bob, chan),
2013 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2014 BEAST_EXPECT(env.seq(bob) == bobSeq);
2017 auto const feeDrops = env.current()->fees().base;
2018 auto const delta = chanAmt - chanBal;
2019 assert(delta > beast::zero);
2020 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
2021 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2023 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2024 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2025 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2026 BEAST_EXPECT(env.seq(bob) == bobSeq);
2058 using namespace test::jtx;