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>
47 return {k.key, view.
read(k)};
87 using namespace std::literals::chrono_literals;
88 Env env{*
this, features};
89 auto const alice =
Account(
"alice");
90 auto const bob =
Account(
"bob");
91 auto USDA = alice[
"USD"];
92 env.fund(
XRP(10000), alice, bob);
93 auto const pk = alice.pk();
94 auto const settleDelay = 100s;
95 auto const chan =
channel(alice, bob, env.seq(alice));
96 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
101 auto const preAlice = env.balance(alice);
102 env(
fund(alice, chan,
XRP(1000)));
103 auto const feeDrops = env.current()->fees().base;
104 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
109 BEAST_EXPECT(chanBal ==
XRP(0));
110 BEAST_EXPECT(chanAmt ==
XRP(2000));
114 env(
create(alice, bob, USDA(1000), settleDelay, pk),
117 env(
create(alice, bob,
XRP(-1000), settleDelay, pk),
123 env(
create(alice,
"noAccount",
XRP(1000), settleDelay, pk),
126 env(
create(alice, alice,
XRP(1000), settleDelay, pk),
132 channel(alice,
"noAccount", env.seq(alice) - 1),
140 auto const iou = USDA(100).value();
141 auto const negXRP =
XRP(-100).value();
142 auto const posXRP =
XRP(100).value();
152 auto const delta =
XRP(500);
153 auto const reqBal = chanBal + delta;
154 auto const authAmt = reqBal +
XRP(-100);
155 assert(reqBal <= chanAmt);
160 auto const preBob = env.balance(bob);
161 auto const delta =
XRP(500);
162 auto const reqBal = chanBal + delta;
163 auto const authAmt = reqBal +
XRP(100);
164 assert(reqBal <= chanAmt);
165 env(
claim(alice, chan, reqBal, authAmt));
167 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
168 BEAST_EXPECT(env.balance(bob) == preBob + delta);
173 auto preBob = env.balance(bob);
174 auto const delta =
XRP(500);
175 auto const reqBal = chanBal + delta;
176 auto const authAmt = reqBal +
XRP(100);
177 assert(reqBal <= chanAmt);
180 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
182 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
183 auto const feeDrops = env.current()->fees().base;
184 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
188 preBob = env.balance(bob);
189 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
192 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
193 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
197 auto const preBob = env.balance(bob);
200 assert(reqAmt <= chanAmt);
203 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
206 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
207 BEAST_EXPECT(env.balance(bob) == preBob);
213 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
227 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
241 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
245 auto const preAlice = env.balance(alice);
246 auto const preBob = env.balance(bob);
249 auto const feeDrops = env.current()->fees().base;
250 auto const delta = chanAmt - chanBal;
251 assert(delta > beast::zero);
252 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
253 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
260 testcase(
"Disallow Incoming Flag");
267 env.fund(
XRP(10000), alice);
270 auto const sle = env.le(alice);
271 uint32_t
flags = sle->getFlags();
275 using namespace std::literals::chrono_literals;
277 auto const alice =
Account(
"alice");
278 auto const bob =
Account(
"bob");
279 auto const cho =
Account(
"cho");
280 env.fund(
XRP(10000), alice, bob, cho);
281 auto const pk = alice.pk();
282 auto const settleDelay = 100s;
290 auto const chan =
channel(alice, bob, env.seq(alice));
291 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
302 auto const chan =
channel(bob, alice, env.seq(bob));
303 env(
create(bob, alice,
XRP(1000), settleDelay, pk),
314 auto const chan =
channel(alice, bob, env.seq(alice));
315 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
322 auto const chan =
channel(cho, alice, env.seq(cho));
323 env(
create(cho, alice,
XRP(1000), settleDelay, pk),
334 auto const chan =
channel(cho, alice, env.seq(cho));
335 env(
create(cho, alice,
XRP(1000), settleDelay, pk),
344 testcase(
"cancel after");
346 using namespace std::literals::chrono_literals;
347 auto const alice =
Account(
"alice");
348 auto const bob =
Account(
"bob");
349 auto const carol =
Account(
"carol");
352 Env env{*
this, features};
353 env.fund(
XRP(10000), alice, bob);
354 auto const pk = alice.pk();
355 auto const settleDelay = 100s;
357 env.current()->info().parentCloseTime + 3600s;
358 auto const channelFunds =
XRP(1000);
359 auto const chan =
channel(alice, bob, env.seq(alice));
360 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
362 env.close(cancelAfter);
367 auto preAlice = env.balance(alice);
368 auto preBob = env.balance(bob);
369 auto const delta =
XRP(500);
370 auto const reqBal = chanBal + delta;
371 auto const authAmt = reqBal +
XRP(100);
372 assert(reqBal <= chanAmt);
375 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
376 auto const feeDrops = env.current()->fees().base;
378 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
379 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
384 Env env{*
this, features};
385 env.fund(
XRP(10000), alice, bob, carol);
386 auto const pk = alice.pk();
387 auto const settleDelay = 100s;
389 env.current()->info().parentCloseTime + 3600s;
390 auto const channelFunds =
XRP(1000);
391 auto const chan =
channel(alice, bob, env.seq(alice));
392 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
397 env.close(cancelAfter);
399 auto const preAlice = env.balance(alice);
402 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
409 testcase(
"expiration");
411 using namespace std::literals::chrono_literals;
412 Env env{*
this, features};
413 auto const alice =
Account(
"alice");
414 auto const bob =
Account(
"bob");
415 auto const carol =
Account(
"carol");
416 env.fund(
XRP(10000), alice, bob, carol);
417 auto const pk = alice.pk();
418 auto const settleDelay = 3600s;
419 auto const closeTime = env.current()->info().parentCloseTime;
420 auto const minExpiration = closeTime + settleDelay;
422 auto const channelFunds =
XRP(1000);
423 auto const chan =
channel(alice, bob, env.seq(alice));
424 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
429 auto counts = [](
auto const& t) {
430 return t.time_since_epoch().count();
439 counts(minExpiration) + 100);
445 counts(minExpiration) + 50);
452 counts(minExpiration) + 50);
456 counts(minExpiration) + 50);
465 env.close(minExpiration);
475 testcase(
"settle delay");
477 using namespace std::literals::chrono_literals;
478 Env env{*
this, features};
479 auto const alice =
Account(
"alice");
480 auto const bob =
Account(
"bob");
481 env.fund(
XRP(10000), alice, bob);
482 auto const pk = alice.pk();
483 auto const settleDelay = 3600s;
485 env.current()->info().parentCloseTime + settleDelay;
486 auto const channelFunds =
XRP(1000);
487 auto const chan =
channel(alice, bob, env.seq(alice));
488 env(
create(alice, bob, channelFunds, settleDelay, pk));
493 env.close(settleTimepoint - settleDelay / 2);
498 auto preBob = env.balance(bob);
499 auto const delta =
XRP(500);
500 auto const reqBal = chanBal + delta;
501 auto const authAmt = reqBal +
XRP(100);
502 assert(reqBal <= chanAmt);
505 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
507 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
508 auto const feeDrops = env.current()->fees().base;
509 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
511 env.close(settleTimepoint);
516 auto const preAlice = env.balance(alice);
517 auto preBob = env.balance(bob);
518 auto const delta =
XRP(500);
519 auto const reqBal = chanBal + delta;
520 auto const authAmt = reqBal +
XRP(100);
521 assert(reqBal <= chanAmt);
524 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
526 auto const feeDrops = env.current()->fees().base;
527 BEAST_EXPECT(env.balance(alice) == preAlice + chanAmt - chanBal);
528 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
535 testcase(
"close dry");
537 using namespace std::literals::chrono_literals;
538 Env env{*
this, features};
539 auto const alice =
Account(
"alice");
540 auto const bob =
Account(
"bob");
541 env.fund(
XRP(10000), alice, bob);
542 auto const pk = alice.pk();
543 auto const settleDelay = 3600s;
544 auto const channelFunds =
XRP(1000);
545 auto const chan =
channel(alice, bob, env.seq(alice));
546 env(
create(alice, bob, channelFunds, settleDelay, pk));
553 auto const preBob = env.balance(bob);
554 env(
claim(alice, chan, channelFunds.value(), channelFunds.value()));
555 BEAST_EXPECT(
channelBalance(*env.current(), chan) == channelFunds);
556 BEAST_EXPECT(env.balance(bob) == preBob + channelFunds);
558 auto const preAlice = env.balance(alice);
562 auto const feeDrops = env.current()->fees().base;
563 BEAST_EXPECT(env.balance(alice) == preAlice - feeDrops);
570 testcase(
"default amount");
572 using namespace std::literals::chrono_literals;
573 Env env{*
this, features};
574 auto const alice =
Account(
"alice");
575 auto const bob =
Account(
"bob");
576 env.fund(
XRP(10000), alice, bob);
577 auto const pk = alice.pk();
578 auto const settleDelay = 3600s;
579 auto const channelFunds =
XRP(1000);
580 auto const chan =
channel(alice, bob, env.seq(alice));
581 env(
create(alice, bob, channelFunds, settleDelay, pk));
589 auto const preBob = env.balance(bob);
591 auto const delta =
XRP(500);
592 auto const reqBal = chanBal + delta;
593 assert(reqBal <= chanAmt);
596 env(
claim(bob, chan, reqBal, std::nullopt,
Slice(
sig), alice.pk()));
598 auto const feeDrops = env.current()->fees().base;
599 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
606 auto const preBob = env.balance(bob);
608 auto const delta =
XRP(500);
609 auto const reqBal = chanBal + delta;
610 assert(reqBal <= chanAmt);
613 env(
claim(bob, chan, reqBal, std::nullopt,
Slice(
sig), alice.pk()));
615 auto const feeDrops = env.current()->fees().base;
616 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
625 testcase(
"Disallow XRP");
627 using namespace std::literals::chrono_literals;
629 auto const alice =
Account(
"alice");
630 auto const bob =
Account(
"bob");
634 env.
fund(
XRP(10000), alice, bob);
636 auto const chan =
channel(alice, bob, env.
seq(alice));
637 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()),
644 Env env{*
this, features};
645 env.fund(
XRP(10000), alice, bob);
647 auto const chan =
channel(alice, bob, env.seq(alice));
648 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
656 env.
fund(
XRP(10000), alice, bob);
657 auto const chan =
channel(alice, bob, env.
seq(alice));
658 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
662 auto const reqBal =
XRP(500).value();
669 Env env{*
this, features};
670 env.fund(
XRP(10000), alice, bob);
671 auto const chan =
channel(alice, bob, env.seq(alice));
672 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
676 auto const reqBal =
XRP(500).value();
677 env(
claim(alice, chan, reqBal, reqBal));
687 using namespace std::literals::chrono_literals;
689 Env env{*
this, features};
690 auto const alice =
Account(
"alice");
691 auto const bob =
Account(
"bob");
692 env.fund(
XRP(10000), alice, bob);
694 auto const pk = alice.pk();
695 auto const settleDelay = 3600s;
696 auto const channelFunds =
XRP(1000);
698 auto const chan =
channel(alice, bob, env.seq(alice));
699 env(
create(alice, bob, channelFunds, settleDelay, pk),
704 auto const chan =
channel(alice, bob, env.seq(alice));
706 alice, bob, channelFunds, settleDelay, pk, std::nullopt, 1));
714 testcase(
"Deposit Authorization");
716 using namespace std::literals::chrono_literals;
718 auto const alice =
Account(
"alice");
719 auto const bob =
Account(
"bob");
720 auto const carol =
Account(
"carol");
721 auto USDA = alice[
"USD"];
723 Env env{*
this, features};
724 env.fund(
XRP(10000), alice, bob, carol);
729 auto const pk = alice.pk();
730 auto const settleDelay = 100s;
731 auto const chan =
channel(alice, bob, env.seq(alice));
732 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
740 env(
fund(alice, chan,
XRP(1000)));
744 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
749 auto const baseFee = env.current()->fees().base;
750 auto const preBob = env.balance(bob);
752 auto const delta =
XRP(500).value();
760 BEAST_EXPECT(env.balance(bob) == preBob);
772 BEAST_EXPECT(env.balance(bob) == preBob + delta - baseFee);
776 auto const delta =
XRP(600).value();
787 env(deposit::auth(bob, carol));
801 env(deposit::auth(bob, alice));
808 env.balance(bob) == preBob + delta - (3 * baseFee));
813 auto const delta =
XRP(800).value();
815 env(deposit::unauth(bob, alice));
827 env(
claim(alice, chan, delta, delta));
830 env.balance(bob) == preBob +
XRP(800) - (5 * baseFee));
839 testcase(
"Multiple channels to the same account");
841 using namespace std::literals::chrono_literals;
842 Env env{*
this, features};
843 auto const alice =
Account(
"alice");
844 auto const bob =
Account(
"bob");
845 env.fund(
XRP(10000), alice, bob);
846 auto const pk = alice.pk();
847 auto const settleDelay = 3600s;
848 auto const channelFunds =
XRP(1000);
849 auto const chan1 =
channel(alice, bob, env.seq(alice));
850 env(
create(alice, bob, channelFunds, settleDelay, pk));
852 auto const chan2 =
channel(alice, bob, env.seq(alice));
853 env(
create(alice, bob, channelFunds, settleDelay, pk));
855 BEAST_EXPECT(chan1 != chan2);
861 testcase(
"AccountChannels RPC");
864 using namespace std::literals::chrono_literals;
865 Env env{*
this, features};
866 auto const alice =
Account(
"alice");
867 auto const bob =
Account(
"bob");
869 env.fund(
XRP(10000), alice, bob, charlie);
870 auto const pk = alice.pk();
871 auto const settleDelay = 3600s;
872 auto const channelFunds =
XRP(1000);
874 env(
create(alice, bob, channelFunds, settleDelay, pk));
878 env.rpc(
"account_channels", alice.human(), bob.human());
879 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
881 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
882 BEAST_EXPECT(r[jss::result][jss::validated]);
885 auto const r = env.rpc(
"account_channels", alice.human());
886 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
888 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
889 BEAST_EXPECT(r[jss::result][jss::validated]);
893 env.rpc(
"account_channels", bob.human(), alice.human());
894 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
895 BEAST_EXPECT(r[jss::result][jss::validated]);
898 env(
create(alice, bob, channelFunds, settleDelay, pk));
902 env.rpc(
"account_channels", alice.human(), bob.human());
903 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
904 BEAST_EXPECT(r[jss::result][jss::validated]);
905 BEAST_EXPECT(chan1Str != chan2Str);
906 for (
auto const& c : {chan1Str, chan2Str})
908 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
909 r[jss::result][jss::channels][1u][jss::channel_id] == c);
916 testcase(
"Account channels RPC markers");
918 using namespace test::jtx;
919 using namespace std::literals;
921 auto const alice =
Account(
"alice");
926 for (
int i = 0; i < n; ++i)
933 Env env{*
this, features};
934 env.fund(
XRP(10000), alice);
935 for (
auto const& a : bobs)
937 env.fund(
XRP(10000), a);
943 auto const settleDelay = 3600s;
944 auto const channelFunds =
XRP(1);
945 for (
auto const& b : bobs)
947 env(
create(alice, b, channelFunds, settleDelay, alice.pk()));
958 jvc[jss::account] = src.human();
960 jvc[jss::destination_account] = dst->human();
962 jvc[jss::limit] = *limit;
964 jvc[jss::marker] = marker;
967 "json",
"account_channels",
to_string(jvc))[jss::result];
972 auto const r = testLimit(env, alice);
973 BEAST_EXPECT(r.isMember(jss::channels));
974 BEAST_EXPECT(r[jss::channels].size() == bobs.size());
979 for (
auto const& a : bobs)
984 for (
int limit = 1; limit < bobs.size() + 1; ++limit)
986 auto leftToFind = bobsB58;
987 auto const numFull = bobs.
size() / limit;
988 auto const numNonFull = bobs.size() % limit ? 1 : 0;
992 auto const testIt = [&](
bool expectMarker,
int expectedBatchSize) {
993 auto const r = testLimit(env, alice, limit, marker);
994 BEAST_EXPECT(!expectMarker || r.isMember(jss::marker));
995 if (r.isMember(jss::marker))
996 marker = r[jss::marker];
997 BEAST_EXPECT(r[jss::channels].size() == expectedBatchSize);
998 auto const c = r[jss::channels];
999 auto const s = r[jss::channels].size();
1000 for (
int j = 0; j < s; ++j)
1003 c[j][jss::destination_account].asString();
1004 BEAST_EXPECT(leftToFind.count(dstAcc));
1005 leftToFind.erase(dstAcc);
1009 for (
int i = 0; i < numFull; ++i)
1011 bool const expectMarker = (numNonFull != 0 || i < numFull - 1);
1012 testIt(expectMarker, limit);
1017 testIt(
false, bobs.size() % limit);
1019 BEAST_EXPECT(leftToFind.empty());
1024 auto const r = testLimit(env, alice, 0);
1025 BEAST_EXPECT(r.isMember(jss::error_message));
1034 testcase(
"Account channels RPC owner only");
1036 using namespace test::jtx;
1037 using namespace std::literals;
1039 auto const alice =
Account(
"alice");
1040 auto const bob =
Account(
"bob");
1041 Env env{*
this, features};
1042 env.fund(
XRP(10000), alice, bob);
1047 auto const settleDelay = 3600s;
1048 auto const channelFunds =
XRP(1000);
1049 env(
create(alice, bob, channelFunds, settleDelay, alice.pk()));
1050 env(
create(bob, alice, channelFunds, settleDelay, bob.pk()));
1052 auto const r = [&] {
1054 jvc[jss::account] = alice.human();
1057 "json",
"account_channels",
to_string(jvc))[jss::result];
1059 BEAST_EXPECT(r.isMember(jss::channels));
1060 BEAST_EXPECT(r[jss::channels].size() == 1);
1062 r[jss::channels][0u][jss::destination_account].asString() ==
1069 testcase(
"PayChan Auth/Verify RPC");
1070 using namespace jtx;
1071 using namespace std::literals::chrono_literals;
1072 Env env{*
this, features};
1073 auto const alice =
Account(
"alice");
1074 auto const bob =
Account(
"bob");
1076 env.fund(
XRP(10000), alice, bob, charlie);
1077 auto const pk = alice.pk();
1078 auto const settleDelay = 3600s;
1079 auto const channelFunds =
XRP(1000);
1081 env(
create(alice, bob, channelFunds, settleDelay, pk));
1086 env.rpc(
"account_channels", alice.human(), bob.human());
1087 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1089 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1090 BEAST_EXPECT(r[jss::result][jss::validated]);
1092 r[jss::result][jss::channels][0u][jss::public_key].asString();
1095 auto const r = env.rpc(
"account_channels", alice.human());
1096 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1098 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1099 BEAST_EXPECT(r[jss::result][jss::validated]);
1101 r[jss::result][jss::channels][0u][jss::public_key].asString();
1105 env.rpc(
"account_channels", bob.human(), alice.human());
1106 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1107 BEAST_EXPECT(r[jss::result][jss::validated]);
1110 env(
create(alice, bob, channelFunds, settleDelay, pk));
1114 env.rpc(
"account_channels", alice.human(), bob.human());
1115 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1116 BEAST_EXPECT(r[jss::result][jss::validated]);
1117 BEAST_EXPECT(chan1Str != chan2Str);
1118 for (
auto const& c : {chan1Str, chan2Str})
1120 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1121 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1127 for (
int i = 0; i < slice.size(); ++i)
1129 s +=
"0123456789ABCDEF"[((slice[i] & 0xf0) >> 4)];
1130 s +=
"0123456789ABCDEF"[((slice[i] & 0x0f) >> 0)];
1138 env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000");
1139 auto const sig = rs[jss::result][jss::signature].asString();
1140 BEAST_EXPECT(!
sig.empty());
1142 auto const rv = env.rpc(
1143 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1144 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1151 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1152 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1158 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000x",
sig);
1159 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1160 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 ",
sig);
1161 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1162 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x1000",
sig);
1163 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1164 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x",
sig);
1165 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1166 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" ",
sig);
1167 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1169 "channel_verify", pkAsHex, chan1Str,
"1000 1000",
sig);
1170 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1171 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1,000",
sig);
1172 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1173 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" 1000",
sig);
1174 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1175 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"",
sig);
1176 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1181 auto chan1StrBad = chan1Str;
1182 chan1StrBad.pop_back();
1184 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1185 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1186 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1187 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1189 chan1StrBad = chan1Str;
1190 chan1StrBad.push_back(
'0');
1192 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1193 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1194 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1195 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1197 chan1StrBad = chan1Str;
1198 chan1StrBad.back() =
'x';
1200 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1201 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1202 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1203 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1207 auto illFormedPk = chan1PkStr.
substr(0, chan1PkStr.
size() - 1);
1208 auto const rv = env.rpc(
1209 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1211 !rv[jss::result][jss::signature_verified].asBool());
1216 auto illFormedPk = pkAsHex.substr(0, chan1PkStr.
size() - 1);
1217 auto const rv = env.rpc(
1218 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1220 !rv[jss::result][jss::signature_verified].asBool());
1226 env.rpc(
"channel_authorize",
"alice", chan2Str,
"1000");
1227 auto const sig = rs[jss::result][jss::signature].asString();
1228 BEAST_EXPECT(!
sig.empty());
1230 auto const rv = env.rpc(
1231 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1233 !rv[jss::result][jss::signature_verified].asBool());
1239 env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1241 !rv[jss::result][jss::signature_verified].asBool());
1249 charlie, alice, channelFunds, settleDelay, charlie.pk()));
1255 env.rpc(
"account_channels", charlie.human(), alice.human());
1256 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1258 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1259 BEAST_EXPECT(r[jss::result][jss::validated]);
1260 cpk = r[jss::result][jss::channels][0u][jss::public_key]
1266 env.rpc(
"channel_authorize",
"charlie", chan,
"1000");
1267 auto const sig = rs[jss::result][jss::signature].asString();
1268 BEAST_EXPECT(!
sig.empty());
1271 env.rpc(
"channel_verify", cpk, chan,
"1000",
sig);
1273 !rv[jss::result][jss::signature_verified].asBool());
1278 env.rpc(
"channel_authorize",
"charlie",
"nyx", chan,
"1000");
1279 BEAST_EXPECT(rs1[jss::error] ==
"badKeyType");
1283 auto const rs2 = env.rpc(
1284 "channel_authorize",
"charlie",
"secp256k1", chan,
"1000");
1285 auto const sig2 = rs2[jss::result][jss::signature].asString();
1286 BEAST_EXPECT(!sig2.empty());
1289 env.rpc(
"channel_verify", cpk, chan,
"1000", sig2);
1291 !rv[jss::result][jss::signature_verified].asBool());
1295 auto const rs3 = env.rpc(
1296 "channel_authorize",
"charlie",
"ed25519", chan,
"1000");
1297 auto const sig3 = rs3[jss::result][jss::signature].asString();
1298 BEAST_EXPECT(!sig3.empty());
1301 env.rpc(
"channel_verify", cpk, chan,
"1000", sig3);
1302 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1308 auto rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000x");
1309 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1310 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x1000");
1311 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1312 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x");
1313 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1317 args[jss::amount] =
"2000";
1318 args[jss::key_type] =
"secp256k1";
1319 args[jss::passphrase] =
"passphrase_can_be_anything";
1322 "channel_authorize",
1323 args.toStyledString())[jss::result];
1324 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1329 args[jss::channel_id] = chan1Str;
1330 args[jss::key_type] =
"secp256k1";
1331 args[jss::passphrase] =
"passphrase_can_be_anything";
1334 "channel_authorize",
1335 args.toStyledString())[jss::result];
1336 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1341 args[jss::amount] =
"2000";
1342 args[jss::channel_id] = chan1Str;
1343 args[jss::passphrase] =
"passphrase_can_be_anything";
1346 "channel_authorize",
1347 args.toStyledString())[jss::result];
1348 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1353 args[jss::amount] =
"2000";
1354 args[jss::channel_id] = chan1Str;
1355 args[jss::key_type] =
"secp256k1";
1356 args[jss::passphrase] =
"passphrase_can_be_anything";
1357 args[jss::seed] =
"seed can be anything";
1360 "channel_authorize",
1361 args.toStyledString())[jss::result];
1362 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1367 args[jss::amount] =
"2000";
1368 args[jss::channel_id] = chan1Str +
"1";
1369 args[jss::key_type] =
"secp256k1";
1370 args[jss::passphrase] =
"passphrase_can_be_anything";
1373 "channel_authorize",
1374 args.toStyledString())[jss::result];
1375 BEAST_EXPECT(rs[jss::error] ==
"channelMalformed");
1380 args[jss::amount] = 2000;
1381 args[jss::channel_id] = chan1Str;
1382 args[jss::key_type] =
"secp256k1";
1383 args[jss::passphrase] =
"passphrase_can_be_anything";
1386 "channel_authorize",
1387 args.toStyledString())[jss::result];
1388 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1393 args[jss::amount] =
"TwoThousand";
1394 args[jss::channel_id] = chan1Str;
1395 args[jss::key_type] =
"secp256k1";
1396 args[jss::passphrase] =
"passphrase_can_be_anything";
1399 "channel_authorize",
1400 args.toStyledString())[jss::result];
1401 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1409 testcase(
"Optional Fields");
1410 using namespace jtx;
1411 using namespace std::literals::chrono_literals;
1412 Env env{*
this, features};
1413 auto const alice =
Account(
"alice");
1414 auto const bob =
Account(
"bob");
1415 auto const carol =
Account(
"carol");
1416 auto const dan =
Account(
"dan");
1417 env.fund(
XRP(10000), alice, bob, carol, dan);
1418 auto const pk = alice.pk();
1419 auto const settleDelay = 3600s;
1420 auto const channelFunds =
XRP(1000);
1426 env(
create(alice, bob, channelFunds, settleDelay, pk));
1428 env.rpc(
"account_channels", alice.human(), bob.human());
1429 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1431 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1432 BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember(
1433 jss::destination_tag));
1447 env.rpc(
"account_channels", alice.human(), carol.human());
1448 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1450 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1452 r[jss::result][jss::channels][0u][jss::destination_tag] ==
1460 testcase(
"malformed pk");
1461 using namespace jtx;
1462 using namespace std::literals::chrono_literals;
1463 Env env{*
this, features};
1464 auto const alice =
Account(
"alice");
1465 auto const bob =
Account(
"bob");
1466 auto USDA = alice[
"USD"];
1467 env.fund(
XRP(10000), alice, bob);
1468 auto const pk = alice.pk();
1469 auto const settleDelay = 100s;
1471 auto const chan =
channel(alice, bob, env.seq(alice));
1472 auto jv =
create(alice, bob,
XRP(1000), settleDelay, pk);
1473 auto const pkHex =
strHex(pk.slice());
1474 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1476 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1478 auto badPrefix = pkHex;
1481 jv[
"PublicKey"] = badPrefix;
1484 jv[
"PublicKey"] = pkHex;
1487 auto const authAmt =
XRP(100);
1496 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1498 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1503 jv[
"PublicKey"] = badPrefix;
1507 jv.removeMember(
"PublicKey");
1511 auto const txn = R
"*(
1514 "channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
1516 "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
1518 "aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
1522 auto const r = env.rpc(
"json",
"channel_verify", txn);
1523 BEAST_EXPECT(r[
"result"][
"error"] ==
"publicMalformed");
1530 testcase(
"Metadata & Ownership");
1532 using namespace jtx;
1533 using namespace std::literals::chrono_literals;
1535 auto const alice =
Account(
"alice");
1536 auto const bob =
Account(
"bob");
1537 auto const settleDelay = 100s;
1538 auto const pk = alice.pk();
1540 auto inOwnerDir = [](
ReadView const& view,
1544 return std::find(ownerDir.begin(), ownerDir.end(), chan) !=
1548 auto ownerDirCount = [](
ReadView const& view,
1558 env.
fund(
XRP(10000), alice, bob);
1559 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1561 auto const [chan, chanSle] =
1563 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1564 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1565 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1566 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1570 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1571 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1572 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1573 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1578 Env env{*
this, features};
1579 env.fund(
XRP(10000), alice, bob);
1580 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1582 auto const [chan, chanSle] =
1584 BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle));
1585 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
1586 BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle));
1587 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 1);
1591 BEAST_EXPECT(!inOwnerDir(*env.current(), alice, chanSle));
1592 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 0);
1593 BEAST_EXPECT(!inOwnerDir(*env.current(), bob, chanSle));
1594 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 0);
1601 env.
fund(
XRP(10000), alice, bob);
1603 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1605 auto const [chan, chanSle] =
1607 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1608 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1609 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1610 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1619 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1620 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1621 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1626 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1627 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1628 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1629 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1636 testcase(
"Account Delete");
1637 using namespace test::jtx;
1638 using namespace std::literals::chrono_literals;
1639 auto rmAccount = [
this](
1646 for (
auto minRmSeq = env.
seq(toRm) + 257;
1647 env.
current()->seq() < minRmSeq;
1661 auto const alice =
Account(
"alice");
1662 auto const bob =
Account(
"bob");
1663 auto const carol =
Account(
"carol");
1665 for (
bool const withOwnerDirFix : {
false,
true})
1667 auto const amd = withOwnerDirFix
1670 Env env{*
this, amd};
1671 env.
fund(
XRP(10000), alice, bob, carol);
1673 auto const feeDrops = env.
current()->fees().base;
1676 auto const pk = alice.pk();
1677 auto const settleDelay = 100s;
1678 auto const chan =
channel(alice, bob, env.
seq(alice));
1679 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1694 BEAST_EXPECT(chanBal ==
XRP(0));
1695 BEAST_EXPECT(chanAmt ==
XRP(1000));
1697 auto preBob = env.
balance(bob);
1698 auto const delta =
XRP(50);
1699 auto reqBal = chanBal + delta;
1700 auto authAmt = reqBal +
XRP(100);
1701 assert(reqBal <= chanAmt);
1704 if (withOwnerDirFix)
1706 env(
claim(alice, chan, reqBal, authAmt));
1710 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1715 auto const preAlice = env.
balance(alice);
1720 BEAST_EXPECT(env.
balance(bob) == preBob);
1721 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1725 if (withOwnerDirFix)
1727 auto const preAlice = env.
balance(alice);
1728 env(
fund(alice, chan,
XRP(1000)));
1731 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1734 chanAmt = chanAmt +
XRP(1000);
1738 auto const preAlice = env.
balance(alice);
1741 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1751 auto const closeTime = env.
current()->info().parentCloseTime;
1752 auto const minExpiration = closeTime + settleDelay;
1753 env.
close(minExpiration);
1762 env.
fund(
XRP(10000), alice, bob, carol);
1764 auto const feeDrops = env.
current()->fees().base;
1767 auto const pk = alice.pk();
1768 auto const settleDelay = 100s;
1769 auto const chan =
channel(alice, bob, env.
seq(alice));
1770 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1776 rmAccount(env, bob, carol);
1781 BEAST_EXPECT(chanBal ==
XRP(0));
1782 BEAST_EXPECT(chanAmt ==
XRP(1000));
1783 auto preBob = env.
balance(bob);
1784 auto const delta =
XRP(50);
1785 auto reqBal = chanBal + delta;
1786 auto authAmt = reqBal +
XRP(100);
1787 assert(reqBal <= chanAmt);
1791 auto const preAlice = env.
balance(alice);
1796 BEAST_EXPECT(env.
balance(bob) == preBob);
1797 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1802 auto const preAlice = env.
balance(alice);
1805 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1810 env(pay(alice, bob,
XRP(20)));
1817 reqBal = chanBal + delta;
1818 authAmt = reqBal +
XRP(100);
1819 env(
claim(alice, chan, reqBal, authAmt));
1822 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1829 reqBal = chanBal + delta;
1830 authAmt = reqBal +
XRP(100);
1833 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
1836 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
1842 auto const preAlice = env.
balance(alice);
1843 env(
fund(alice, chan,
XRP(1000)));
1845 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1848 chanAmt = chanAmt +
XRP(1000);
1857 auto const closeTime = env.
current()->info().parentCloseTime;
1858 auto const minExpiration = closeTime + settleDelay;
1859 env.
close(minExpiration);
1869 testcase(
"using tickets");
1870 using namespace jtx;
1871 using namespace std::literals::chrono_literals;
1872 Env env{*
this, features};
1873 auto const alice =
Account(
"alice");
1874 auto const bob =
Account(
"bob");
1875 auto USDA = alice[
"USD"];
1876 env.fund(
XRP(10000), alice, bob);
1882 env(ticket::create(alice, 10));
1886 env(ticket::create(bob, 10));
1889 auto const pk = alice.pk();
1890 auto const settleDelay = 100s;
1891 auto const chan =
channel(alice, bob, aliceTicketSeq);
1893 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
1896 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1897 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1903 auto const preAlice = env.balance(alice);
1906 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1907 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1909 auto const feeDrops = env.current()->fees().base;
1910 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
1915 BEAST_EXPECT(chanBal ==
XRP(0));
1916 BEAST_EXPECT(chanAmt ==
XRP(2000));
1920 auto const preBob = env.balance(bob);
1921 auto const delta =
XRP(500);
1922 auto const reqBal = chanBal + delta;
1923 auto const authAmt = reqBal +
XRP(100);
1924 assert(reqBal <= chanAmt);
1925 env(
claim(alice, chan, reqBal, authAmt),
1928 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1929 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1932 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1933 BEAST_EXPECT(env.balance(bob) == preBob + delta);
1938 auto preBob = env.balance(bob);
1939 auto const delta =
XRP(500);
1940 auto const reqBal = chanBal + delta;
1941 auto const authAmt = reqBal +
XRP(100);
1942 assert(reqBal <= chanAmt);
1945 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
1948 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
1949 BEAST_EXPECT(env.seq(bob) == bobSeq);
1952 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1953 auto const feeDrops = env.current()->fees().base;
1954 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
1958 preBob = env.balance(bob);
1960 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
1964 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
1965 BEAST_EXPECT(env.seq(bob) == bobSeq);
1968 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1969 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
1973 auto const preBob = env.balance(bob);
1976 assert(reqAmt <= chanAmt);
1981 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
1985 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
1986 BEAST_EXPECT(env.seq(bob) == bobSeq);
1989 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1990 BEAST_EXPECT(env.balance(bob) == preBob);
1994 env(
fund(bob, chan,
XRP(1000)),
1998 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
1999 BEAST_EXPECT(env.seq(bob) == bobSeq);
2002 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
2006 auto const preAlice = env.balance(alice);
2007 auto const preBob = env.balance(bob);
2008 env(
claim(bob, chan),
2012 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2013 BEAST_EXPECT(env.seq(bob) == bobSeq);
2016 auto const feeDrops = env.current()->fees().base;
2017 auto const delta = chanAmt - chanBal;
2018 assert(delta > beast::zero);
2019 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
2020 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
2022 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
2023 BEAST_EXPECT(env.seq(alice) == aliceSeq);
2024 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
2025 BEAST_EXPECT(env.seq(bob) == bobSeq);
2057 using namespace test::jtx;