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/jss.h>
25 #include <ripple/protocol/PayChan.h>
26 #include <ripple/protocol/TxFlags.h>
61 return {k.key, view.
read(k)};
104 boost::optional<std::int64_t>
122 boost::optional<NetClock::time_point>
const& cancelAfter = boost::none,
123 boost::optional<std::uint32_t>
const& dstTag = boost::none)
127 jv[jss::TransactionType] = jss::PaymentChannelCreate;
129 jv[jss::Account] = account.human ();
130 jv[jss::Destination] = to.
human ();
132 jv[
"SettleDelay"] = settleDelay.
count ();
135 jv[
"CancelAfter"] = cancelAfter->time_since_epoch ().count ();
137 jv[
"DestinationTag"] = *dstTag;
146 boost::optional<NetClock::time_point>
const&
expiration = boost::none)
150 jv[jss::TransactionType] = jss::PaymentChannelFund;
152 jv[jss::Account] = account.human ();
156 jv[
"Expiration"] =
expiration->time_since_epoch ().count ();
164 boost::optional<STAmount>
const&
balance = boost::none,
165 boost::optional<STAmount>
const& amount = boost::none,
166 boost::optional<Slice>
const& signature = boost::none,
167 boost::optional<PublicKey>
const& pk = boost::none)
171 jv[jss::TransactionType] = jss::PaymentChannelClaim;
173 jv[jss::Account] = account.human ();
180 jv[
"Signature"] =
strHex (*signature);
182 jv[
"PublicKey"] =
strHex (pk->slice ());
191 using namespace std::literals::chrono_literals;
193 auto const alice =
Account (
"alice");
194 auto const bob =
Account (
"bob");
195 auto USDA = alice[
"USD"];
196 env.
fund (
XRP (10000), alice, bob);
197 auto const pk = alice.pk ();
198 auto const settleDelay = 100s;
199 env (
create (alice, bob,
XRP (1000), settleDelay, pk));
205 auto const preAlice = env.
balance (alice);
206 env (
fund (alice, chan,
XRP (1000)));
207 auto const feeDrops = env.
current ()->fees ().base;
208 BEAST_EXPECT (env.
balance (alice) == preAlice -
XRP (1000) - feeDrops);
213 BEAST_EXPECT (chanBal ==
XRP (0));
214 BEAST_EXPECT (chanAmt ==
XRP (2000));
218 env (
create (alice, bob, USDA (1000), settleDelay, pk),
220 env (
fund (alice, chan, USDA (1000)),
222 env (
create (alice, bob,
XRP (-1000), settleDelay, pk),
224 env (
fund (alice, chan,
XRP (-1000)),
229 env (
create (alice,
"noAccount",
XRP (1000), settleDelay, pk),
232 env (
create (alice, alice,
XRP (1000), settleDelay, pk),
238 env (
create (alice, bob,
XRP (10000), settleDelay, pk),
243 auto const iou = USDA (100).value ();
244 auto const negXRP =
XRP (-100).value ();
245 auto const posXRP =
XRP (100).value ();
255 auto const delta =
XRP (500);
256 auto const reqBal = chanBal + delta;
257 auto const authAmt = reqBal +
XRP (-100);
258 assert (reqBal <= chanAmt);
263 auto const preBob = env.
balance (bob);
264 auto const delta =
XRP (500);
265 auto const reqBal = chanBal + delta;
266 auto const authAmt = reqBal +
XRP (100);
267 assert (reqBal <= chanAmt);
268 env (
claim (alice, chan, reqBal, authAmt));
271 BEAST_EXPECT (env.
balance (bob) == preBob + delta);
276 auto preBob = env.
balance (bob);
277 auto const delta =
XRP (500);
278 auto const reqBal = chanBal + delta;
279 auto const authAmt = reqBal +
XRP (100);
280 assert (reqBal <= chanAmt);
283 env (
claim (bob, chan, reqBal, authAmt,
Slice (
sig), alice.pk ()));
286 auto const feeDrops = env.
current ()->fees ().base;
287 BEAST_EXPECT (env.
balance (bob) == preBob + delta - feeDrops);
292 env (
claim (bob, chan, reqBal, authAmt,
Slice (
sig), alice.pk ()),
296 BEAST_EXPECT (env.
balance (bob) == preBob - feeDrops);
300 auto const preBob = env.
balance (bob);
303 assert (reqAmt <= chanAmt);
306 env (
claim (bob, chan, reqAmt, authAmt,
Slice (
sig), alice.pk ()),
310 BEAST_EXPECT (env.
balance (bob) == preBob);
322 env (
claim (bob, chan,
XRP (1500).value (),
XRP (1500).value (),
332 env (
claim (bob, chan,
XRP (1500).value (),
XRP (1500).value (),
340 auto const preAlice = env.
balance (alice);
341 auto const preBob = env.
balance (bob);
344 auto const feeDrops = env.
current ()->fees ().base;
345 auto const delta = chanAmt - chanBal;
346 assert (delta > beast::zero);
347 BEAST_EXPECT (env.
balance (alice) == preAlice + delta);
348 BEAST_EXPECT (env.
balance (bob) == preBob - feeDrops);
355 testcase (
"cancel after");
357 using namespace std::literals::chrono_literals;
358 auto const alice =
Account (
"alice");
359 auto const bob =
Account (
"bob");
360 auto const carol =
Account (
"carol");
364 env.
fund (
XRP (10000), alice, bob);
365 auto const pk = alice.pk ();
366 auto const settleDelay = 100s;
368 env.
current ()->info ().parentCloseTime + 3600s;
369 auto const channelFunds =
XRP (1000);
371 alice, bob, channelFunds, settleDelay, pk, cancelAfter));
379 env.
close (cancelAfter);
384 auto preAlice = env.
balance (alice);
385 auto preBob = env.
balance (bob);
386 auto const delta =
XRP (500);
387 auto const reqBal = chanBal + delta;
388 auto const authAmt = reqBal +
XRP (100);
389 assert (reqBal <= chanAmt);
393 bob, chan, reqBal, authAmt,
Slice (
sig), alice.pk ()));
394 auto const feeDrops = env.
current ()->fees ().base;
396 BEAST_EXPECT (env.
balance (bob) == preBob - feeDrops);
397 BEAST_EXPECT (env.
balance (alice) == preAlice + channelFunds);
403 env.
fund (
XRP (10000), alice, bob, carol);
404 auto const pk = alice.pk ();
405 auto const settleDelay = 100s;
407 env.
current ()->info ().parentCloseTime + 3600s;
408 auto const channelFunds =
XRP (1000);
410 alice, bob, channelFunds, settleDelay, pk, cancelAfter));
417 env.
close (cancelAfter);
419 auto const preAlice = env.
balance (alice);
422 BEAST_EXPECT (env.
balance (alice) == preAlice + channelFunds);
429 testcase (
"expiration");
431 using namespace std::literals::chrono_literals;
433 auto const alice =
Account (
"alice");
434 auto const bob =
Account (
"bob");
435 auto const carol =
Account (
"carol");
436 env.
fund (
XRP (10000), alice, bob, carol);
437 auto const pk = alice.pk ();
438 auto const settleDelay = 3600s;
439 auto const closeTime = env.
current ()->info ().parentCloseTime;
440 auto const minExpiration = closeTime + settleDelay;
442 auto const channelFunds =
XRP (1000);
443 env (
create (alice, bob, channelFunds, settleDelay, pk, cancelAfter));
450 auto const& t) {
return t.time_since_epoch ().count (); };
452 counts (minExpiration));
457 counts (minExpiration) + 100);
462 counts (minExpiration) + 50);
464 env (
fund (alice, chan,
XRP (1),
468 counts (minExpiration) + 50);
471 counts (minExpiration) + 50);
475 env (
fund (alice, chan,
XRP (1),
480 env.
close (minExpiration);
490 testcase (
"settle delay");
492 using namespace std::literals::chrono_literals;
494 auto const alice =
Account (
"alice");
495 auto const bob =
Account (
"bob");
496 env.
fund (
XRP (10000), alice, bob);
497 auto const pk = alice.pk ();
498 auto const settleDelay = 3600s;
500 env.
current ()->info ().parentCloseTime + settleDelay;
501 auto const channelFunds =
XRP (1000);
502 env (
create (alice, bob, channelFunds, settleDelay, pk));
508 env.
close (settleTimepoint-settleDelay/2);
513 auto preBob = env.
balance (bob);
514 auto const delta =
XRP (500);
515 auto const reqBal = chanBal + delta;
516 auto const authAmt = reqBal +
XRP (100);
517 assert (reqBal <= chanAmt);
520 env (
claim (bob, chan, reqBal, authAmt,
Slice (
sig), alice.pk ()));
523 auto const feeDrops = env.
current ()->fees ().base;
524 BEAST_EXPECT (env.
balance (bob) == preBob + delta - feeDrops);
526 env.
close (settleTimepoint);
531 auto const preAlice = env.
balance (alice);
532 auto preBob = env.
balance (bob);
533 auto const delta =
XRP (500);
534 auto const reqBal = chanBal + delta;
535 auto const authAmt = reqBal +
XRP (100);
536 assert (reqBal <= chanAmt);
539 env (
claim (bob, chan, reqBal, authAmt,
Slice (
sig), alice.pk ()));
541 auto const feeDrops = env.
current ()->fees ().base;
542 BEAST_EXPECT (env.
balance (alice) == preAlice + chanAmt - chanBal);
543 BEAST_EXPECT (env.
balance (bob) == preBob - feeDrops);
550 testcase (
"close dry");
552 using namespace std::literals::chrono_literals;
554 auto const alice =
Account (
"alice");
555 auto const bob =
Account (
"bob");
556 env.
fund (
XRP (10000), alice, bob);
557 auto const pk = alice.pk ();
558 auto const settleDelay = 3600s;
559 auto const channelFunds =
XRP (1000);
560 env (
create (alice, bob, channelFunds, settleDelay, pk));
568 auto const preBob = env.
balance (bob);
570 alice, chan, channelFunds.value (), channelFunds.value ()));
572 BEAST_EXPECT (env.
balance (bob) == preBob + channelFunds);
574 auto const preAlice = env.
balance (alice);
578 auto const feeDrops = env.
current ()->fees ().base;
579 BEAST_EXPECT (env.
balance (alice) == preAlice - feeDrops);
586 testcase (
"default amount");
588 using namespace std::literals::chrono_literals;
590 auto const alice =
Account (
"alice");
591 auto const bob =
Account (
"bob");
592 env.
fund (
XRP (10000), alice, bob);
593 auto const pk = alice.pk ();
594 auto const settleDelay = 3600s;
595 auto const channelFunds =
XRP (1000);
596 env (
create (alice, bob, channelFunds, settleDelay, pk));
605 auto const preBob = env.
balance (bob);
607 auto const delta =
XRP (500);
608 auto const reqBal = chanBal + delta;
609 assert (reqBal <= chanAmt);
613 bob, chan, reqBal, boost::none,
Slice (
sig), alice.pk ()));
615 auto const feeDrops = env.
current ()->fees ().base;
616 BEAST_EXPECT (env.
balance (bob) == preBob + delta - feeDrops);
623 auto const preBob = env.
balance (bob);
625 auto const delta =
XRP (500);
626 auto const reqBal = chanBal + delta;
627 assert (reqBal <= chanAmt);
631 bob, chan, reqBal, boost::none,
Slice (
sig), alice.pk ()));
633 auto const feeDrops = env.
current ()->fees ().base;
634 BEAST_EXPECT (env.
balance (bob) == preBob + delta - feeDrops);
643 testcase (
"Disallow XRP");
645 using namespace std::literals::chrono_literals;
647 auto const alice =
Account (
"alice");
648 auto const bob =
Account (
"bob");
652 env.
fund (
XRP (10000), alice, bob);
654 env (
create (alice, bob,
XRP (1000), 3600s, alice.pk()),
663 env.
fund (
XRP (10000), alice, bob);
665 env (
create (alice, bob,
XRP (1000), 3600s, alice.pk()));
674 env.
fund (
XRP (10000), alice, bob);
675 env (
create (alice, bob,
XRP (1000), 3600s, alice.pk()));
680 auto const reqBal =
XRP (500).value();
688 env.
fund (
XRP (10000), alice, bob);
689 env (
create (alice, bob,
XRP (1000), 3600s, alice.pk()));
694 auto const reqBal =
XRP (500).value();
695 env (
claim (alice, chan, reqBal, reqBal));
703 testcase (
"Dst Tag");
705 using namespace std::literals::chrono_literals;
708 auto const alice =
Account (
"alice");
709 auto const bob =
Account (
"bob");
710 env.
fund (
XRP (10000), alice, bob);
712 auto const pk = alice.pk ();
713 auto const settleDelay = 3600s;
714 auto const channelFunds =
XRP (1000);
715 env (
create (alice, bob, channelFunds, settleDelay, pk),
720 create (alice, bob, channelFunds, settleDelay, pk, boost::none, 1));
728 testcase (
"Deposit Authorization");
730 using namespace std::literals::chrono_literals;
732 auto const alice =
Account (
"alice");
733 auto const bob =
Account (
"bob");
734 auto const carol =
Account (
"carol");
735 auto USDA = alice[
"USD"];
738 env.
fund (
XRP (10000), alice, bob, carol);
743 auto const pk = alice.pk ();
744 auto const settleDelay = 100s;
745 env (
create (alice, bob,
XRP (1000), settleDelay, pk));
754 env (
fund (alice, chan,
XRP (1000)));
758 env (
claim (alice, chan,
763 auto const baseFee = env.
current()->fees().base;
764 auto const preBob = env.
balance (bob);
766 auto const delta =
XRP (500).value();
771 env (
claim (alice, chan,
774 BEAST_EXPECT (env.
balance (bob) == preBob);
786 BEAST_EXPECT (env.
balance (bob) == preBob + delta - baseFee);
790 auto const delta =
XRP (600).value();
795 env (
claim (carol, chan,
801 env(deposit::auth (bob, carol));
804 env (
claim (carol, chan,
809 env (
claim (alice, chan, delta, delta,
815 env(deposit::auth (bob, alice));
822 env.
balance (bob) == preBob + delta - (3 * baseFee));
827 auto const delta =
XRP (800).value();
829 env(deposit::unauth (bob, alice));
841 env (
claim (alice, chan, delta, delta));
844 env.
balance (bob) == preBob +
XRP (800) - (5 * baseFee));
853 testcase (
"Multiple channels to the same account");
855 using namespace std::literals::chrono_literals;
857 auto const alice =
Account (
"alice");
858 auto const bob =
Account (
"bob");
859 env.
fund (
XRP (10000), alice, bob);
860 auto const pk = alice.pk ();
861 auto const settleDelay = 3600s;
862 auto const channelFunds =
XRP (1000);
863 env (
create (alice, bob, channelFunds, settleDelay, pk));
866 env (
create (alice, bob, channelFunds, settleDelay, pk));
869 BEAST_EXPECT (chan1 != chan2);
875 testcase(
"AccountChannels RPC");
878 using namespace std::literals::chrono_literals;
880 auto const alice =
Account(
"alice");
881 auto const bob =
Account(
"bob");
883 env.
fund(
XRP(10000), alice, bob, charlie);
884 auto const pk = alice.pk();
885 auto const settleDelay = 3600s;
886 auto const channelFunds =
XRP(1000);
887 env(
create(alice, bob, channelFunds, settleDelay, pk));
892 env.
rpc(
"account_channels", alice.human(), bob.human());
893 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
895 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
896 BEAST_EXPECT(r[jss::result][jss::validated]);
899 auto const r = env.
rpc(
"account_channels", alice.human());
900 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
902 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
903 BEAST_EXPECT(r[jss::result][jss::validated]);
907 env.
rpc(
"account_channels", bob.human(), alice.human());
908 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
909 BEAST_EXPECT(r[jss::result][jss::validated]);
911 env(
create(alice, bob, channelFunds, settleDelay, pk));
916 env.
rpc(
"account_channels", alice.human(), bob.human());
917 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
918 BEAST_EXPECT(r[jss::result][jss::validated]);
919 BEAST_EXPECT(chan1Str != chan2Str);
920 for (
auto const& c : {chan1Str, chan2Str})
922 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
923 r[jss::result][jss::channels][1u][jss::channel_id] == c);
930 testcase(
"Account channels RPC markers");
932 using namespace test::jtx;
933 using namespace std::literals;
935 auto const alice =
Account(
"alice");
940 for (
int i = 0; i < n; ++i)
949 for (
auto const& a : bobs)
957 auto const settleDelay = 3600s;
958 auto const channelFunds =
XRP(1);
959 for (
auto const& b : bobs)
961 env(
create(alice, b, channelFunds, settleDelay, alice.pk()));
967 boost::optional<int> limit = boost::none,
969 boost::optional<test::jtx::Account>
const& dst =
972 jvc[jss::account] = src.human();
974 jvc[jss::destination_account] = dst->human();
976 jvc[jss::limit] = *limit;
978 jvc[jss::marker] = marker;
981 "json",
"account_channels",
to_string(jvc))[jss::result];
986 auto const r = testLimit(env, alice);
987 BEAST_EXPECT(r.isMember(jss::channels));
988 BEAST_EXPECT(r[jss::channels].size() == bobs.size());
993 for (
auto const& a : bobs)
998 for (
int limit = 1; limit < bobs.size() + 1; ++limit)
1000 auto leftToFind = bobsB58;
1001 auto const numFull = bobs.
size() / limit;
1002 auto const numNonFull = bobs.size() % limit ? 1 : 0;
1006 auto const testIt = [&](
bool expectMarker,
int expectedBatchSize) {
1007 auto const r = testLimit(env, alice, limit, marker);
1008 BEAST_EXPECT(!expectMarker || r.isMember(jss::marker));
1009 if (r.isMember(jss::marker))
1010 marker = r[jss::marker];
1011 BEAST_EXPECT(r[jss::channels].size() == expectedBatchSize);
1012 auto const c = r[jss::channels];
1013 auto const s = r[jss::channels].size();
1014 for (
int j = 0; j < s; ++j)
1017 c[j][jss::destination_account].asString();
1018 BEAST_EXPECT(leftToFind.count(dstAcc));
1019 leftToFind.erase(dstAcc);
1023 for (
int i = 0; i < numFull; ++i)
1025 bool const expectMarker = (numNonFull != 0 || i < numFull - 1);
1026 testIt(expectMarker, limit);
1031 testIt(
false, bobs.size() % limit);
1033 BEAST_EXPECT(leftToFind.empty());
1038 auto const r = testLimit(env, alice, 0);
1039 BEAST_EXPECT(r.isMember(jss::marker));
1040 BEAST_EXPECT(r[jss::channels].size() == 0);
1048 testcase(
"Account channels RPC owner only");
1050 using namespace test::jtx;
1051 using namespace std::literals;
1054 auto const alice =
Account(
"alice");
1055 auto const bob =
Account(
"bob");
1057 env.
fund(
XRP(10000), alice, bob);
1062 auto const settleDelay = 3600s;
1063 auto const channelFunds =
XRP (1000);
1064 env(
create(alice, bob, channelFunds, settleDelay, alice.pk()));
1065 env(
create(bob, alice, channelFunds, settleDelay, bob.pk()));
1069 jvc[jss::account] = alice.human();
1072 "json",
"account_channels",
to_string(jvc))[jss::result];
1074 BEAST_EXPECT(r.isMember(jss::channels));
1075 BEAST_EXPECT(r[jss::channels].size() == 1);
1076 BEAST_EXPECT(r[jss::channels][0u][jss::destination_account].asString() == bob.human());
1082 testcase (
"PayChan Auth/Verify RPC");
1083 using namespace jtx;
1084 using namespace std::literals::chrono_literals;
1086 auto const alice =
Account (
"alice");
1087 auto const bob =
Account (
"bob");
1089 env.
fund (
XRP (10000), alice, bob, charlie);
1090 auto const pk = alice.pk ();
1091 auto const settleDelay = 3600s;
1092 auto const channelFunds =
XRP (1000);
1093 env (
create (alice, bob, channelFunds, settleDelay, pk));
1099 env.
rpc (
"account_channels", alice.human (), bob.human ());
1100 BEAST_EXPECT (r[jss::result][jss::channels].size () == 1);
1101 BEAST_EXPECT (r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1102 BEAST_EXPECT (r[jss::result][jss::validated]);
1103 chan1PkStr = r[jss::result][jss::channels][0u][jss::public_key].asString();
1107 env.
rpc (
"account_channels", alice.human ());
1108 BEAST_EXPECT (r[jss::result][jss::channels].size () == 1);
1109 BEAST_EXPECT (r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1110 BEAST_EXPECT (r[jss::result][jss::validated]);
1111 chan1PkStr = r[jss::result][jss::channels][0u][jss::public_key].asString();
1115 env.
rpc (
"account_channels", bob.human (), alice.human ());
1116 BEAST_EXPECT (r[jss::result][jss::channels].size () == 0);
1117 BEAST_EXPECT (r[jss::result][jss::validated]);
1119 env (
create (alice, bob, channelFunds, settleDelay, pk));
1124 env.
rpc (
"account_channels", alice.human (), bob.human ());
1125 BEAST_EXPECT (r[jss::result][jss::channels].size () == 2);
1126 BEAST_EXPECT (r[jss::result][jss::validated]);
1127 BEAST_EXPECT (chan1Str != chan2Str);
1128 for (
auto const& c : {chan1Str, chan2Str})
1129 BEAST_EXPECT (r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1130 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1136 for (
int i = 0; i < slice.size(); ++i)
1138 s +=
"0123456789ABCDEF"[((slice[i] & 0xf0) >> 4)];
1139 s +=
"0123456789ABCDEF"[((slice[i] & 0x0f) >> 0)];
1147 env.
rpc (
"channel_authorize",
"alice", chan1Str,
"1000");
1148 auto const sig = rs[jss::result][jss::signature].asString ();
1149 BEAST_EXPECT (!
sig.empty ());
1151 auto const rv = env.
rpc(
1152 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1153 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1159 auto const rv = env.
rpc (
1160 "channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1161 BEAST_EXPECT (rv[jss::result][jss::signature_verified].asBool ());
1167 env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1000x",
sig);
1168 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1169 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 ",
sig);
1170 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1171 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"x1000",
sig);
1172 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1173 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"x",
sig);
1174 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1175 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
" ",
sig);
1176 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1177 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 1000",
sig);
1178 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1179 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1,000",
sig);
1180 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1181 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
" 1000",
sig);
1182 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1183 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"",
sig);
1184 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1189 auto chan1StrBad = chan1Str;
1190 chan1StrBad.pop_back();
1191 auto rv = env.
rpc(
"channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1192 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1193 rv = env.
rpc (
"channel_authorize",
"alice", chan1StrBad,
"1000");
1194 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1196 chan1StrBad = chan1Str;
1197 chan1StrBad.push_back(
'0');
1198 rv = env.
rpc(
"channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1199 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1200 rv = env.
rpc (
"channel_authorize",
"alice", chan1StrBad,
"1000");
1201 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1203 chan1StrBad = chan1Str;
1204 chan1StrBad.back() =
'x';
1205 rv = env.
rpc(
"channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1206 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1207 rv = env.
rpc (
"channel_authorize",
"alice", chan1StrBad,
"1000");
1208 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1212 auto illFormedPk = chan1PkStr.
substr(0, chan1PkStr.
size() - 1);
1213 auto const rv = env.
rpc(
1214 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1215 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1220 auto illFormedPk = pkAsHex.substr(0, chan1PkStr.
size() - 1);
1221 auto const rv = env.
rpc(
1222 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1223 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1229 env.
rpc (
"channel_authorize",
"alice", chan2Str,
"1000");
1230 auto const sig = rs[jss::result][jss::signature].asString ();
1231 BEAST_EXPECT (!
sig.empty ());
1233 auto const rv = env.
rpc(
1234 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1236 !rv[jss::result][jss::signature_verified].asBool());
1241 auto const rv = env.
rpc(
1242 "channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1244 !rv[jss::result][jss::signature_verified].asBool());
1249 env (
create (charlie, alice, channelFunds, settleDelay, charlie.pk()));
1257 env.
rpc (
"account_channels", charlie.human (), alice.human ());
1258 BEAST_EXPECT (r[jss::result][jss::channels].size () == 1);
1259 BEAST_EXPECT (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].asString();
1266 env.
rpc (
"channel_authorize",
"charlie", chan,
"1000");
1267 auto const sig = rs[jss::result][jss::signature].asString ();
1268 BEAST_EXPECT (!
sig.empty ());
1270 auto const rv = env.
rpc(
1271 "channel_verify", cpk, chan,
"1000",
sig);
1272 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1277 env.
rpc (
"channel_authorize",
"charlie",
"nyx", chan,
"1000");
1278 BEAST_EXPECT(rs1[jss::error] ==
"badKeyType");
1283 env.
rpc (
"channel_authorize",
"charlie",
"secp256k1", chan,
"1000");
1284 auto const sig2 = rs2[jss::result][jss::signature].
asString ();
1285 BEAST_EXPECT (!sig2.empty ());
1287 auto const rv = env.
rpc(
1288 "channel_verify", cpk, chan,
"1000", sig2);
1289 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1294 env.
rpc (
"channel_authorize",
"charlie",
"ed25519", chan,
"1000");
1295 auto const sig3 = rs3[jss::result][jss::signature].
asString ();
1296 BEAST_EXPECT (!sig3.empty ());
1298 auto const rv = env.
rpc(
1299 "channel_verify", cpk, chan,
"1000", sig3);
1300 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1306 auto rs = env.
rpc(
"channel_authorize",
"alice", chan1Str,
"1000x");
1307 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1308 rs = env.
rpc(
"channel_authorize",
"alice", chan1Str,
"x1000");
1309 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1310 rs = env.
rpc(
"channel_authorize",
"alice", chan1Str,
"x");
1311 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1315 args[jss::amount] =
"2000";
1316 args[jss::key_type] =
"secp256k1";
1317 args[jss::passphrase] =
"passphrase_can_be_anything";
1318 rs = env.
rpc (
"json",
1319 "channel_authorize", args.toStyledString())[jss::result];
1320 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1325 args[jss::channel_id] = chan1Str;
1326 args[jss::key_type] =
"secp256k1";
1327 args[jss::passphrase] =
"passphrase_can_be_anything";
1328 rs = env.
rpc (
"json",
1329 "channel_authorize", args.toStyledString())[jss::result];
1330 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1335 args[jss::amount] =
"2000";
1336 args[jss::channel_id] = chan1Str;
1337 args[jss::passphrase] =
"passphrase_can_be_anything";
1338 rs = env.
rpc (
"json",
1339 "channel_authorize", args.toStyledString())[jss::result];
1340 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1345 args[jss::amount] =
"2000";
1346 args[jss::channel_id] = chan1Str;
1347 args[jss::key_type] =
"secp256k1";
1348 args[jss::passphrase] =
"passphrase_can_be_anything";
1349 args[jss::seed] =
"seed can be anything";
1350 rs = env.
rpc (
"json",
1351 "channel_authorize", args.toStyledString())[jss::result];
1352 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1357 args[jss::amount] =
"2000";
1358 args[jss::channel_id] = chan1Str +
"1";
1359 args[jss::key_type] =
"secp256k1";
1360 args[jss::passphrase] =
"passphrase_can_be_anything";
1361 rs = env.
rpc (
"json",
1362 "channel_authorize", args.toStyledString())[jss::result];
1363 BEAST_EXPECT(rs[jss::error] ==
"channelMalformed");
1368 args[jss::amount] = 2000;
1369 args[jss::channel_id] = chan1Str;
1370 args[jss::key_type] =
"secp256k1";
1371 args[jss::passphrase] =
"passphrase_can_be_anything";
1372 rs = env.
rpc (
"json",
1373 "channel_authorize", args.toStyledString())[jss::result];
1374 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1379 args[jss::amount] =
"TwoThousand";
1380 args[jss::channel_id] = chan1Str;
1381 args[jss::key_type] =
"secp256k1";
1382 args[jss::passphrase] =
"passphrase_can_be_anything";
1383 rs = env.
rpc (
"json",
1384 "channel_authorize", args.toStyledString())[jss::result];
1385 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1393 testcase (
"Optional Fields");
1394 using namespace jtx;
1395 using namespace std::literals::chrono_literals;
1397 auto const alice =
Account (
"alice");
1398 auto const bob =
Account (
"bob");
1399 auto const carol =
Account (
"carol");
1400 auto const dan =
Account (
"dan");
1401 env.
fund (
XRP (10000), alice, bob, carol, dan);
1402 auto const pk = alice.pk ();
1403 auto const settleDelay = 3600s;
1404 auto const channelFunds =
XRP (1000);
1406 boost::optional<NetClock::time_point> cancelAfter;
1409 env (
create (alice, bob, channelFunds, settleDelay, pk));
1412 env.
rpc (
"account_channels", alice.human (), bob.human ());
1413 BEAST_EXPECT (r[jss::result][jss::channels].size () == 1);
1414 BEAST_EXPECT (r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1415 BEAST_EXPECT (!r[jss::result][jss::channels][0u].isMember(jss::destination_tag));
1420 alice, carol, channelFunds, settleDelay, pk, cancelAfter, dstTag));
1423 env.
rpc (
"account_channels", alice.human (), carol.human ());
1424 BEAST_EXPECT (r[jss::result][jss::channels].size () == 1);
1425 BEAST_EXPECT (r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1426 BEAST_EXPECT (r[jss::result][jss::channels][0u][jss::destination_tag] == dstTag);
1433 testcase (
"malformed pk");
1434 using namespace jtx;
1435 using namespace std::literals::chrono_literals;
1437 auto const alice =
Account (
"alice");
1438 auto const bob =
Account (
"bob");
1439 auto USDA = alice[
"USD"];
1440 env.
fund (
XRP (10000), alice, bob);
1441 auto const pk = alice.pk ();
1442 auto const settleDelay = 100s;
1444 auto jv =
create (alice, bob,
XRP (1000), settleDelay, pk);
1445 auto const pkHex =
strHex (pk.slice ());
1446 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size()-2);
1448 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size()-2);
1450 auto badPrefix = pkHex;
1453 jv[
"PublicKey"] = badPrefix;
1456 jv[
"PublicKey"] = pkHex;
1460 auto const authAmt =
XRP (100);
1462 jv =
claim(bob, chan, authAmt.value(), authAmt.value(),
Slice(
sig), alice.pk());
1463 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size()-2);
1465 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size()-2);
1470 jv[
"PublicKey"] = badPrefix;
1474 jv.removeMember(
"PublicKey");
1478 auto const txn = R
"*(
1481 "channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
1483 "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
1485 "aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
1489 auto const r = env.
rpc(
"json",
"channel_verify", txn);
1490 BEAST_EXPECT(r[
"result"][
"error"] ==
"publicMalformed");
1497 testcase(
"Metadata & Ownership");
1499 using namespace jtx;
1500 using namespace std::literals::chrono_literals;
1502 auto const alice =
Account(
"alice");
1503 auto const bob =
Account(
"bob");
1504 auto const settleDelay = 100s;
1505 auto const pk = alice.pk();
1507 auto inOwnerDir = [](
ReadView const& view,
1511 return std::find(ownerDir.begin(), ownerDir.end(), chan) != ownerDir.end();
1514 auto ownerDirCount = [](
ReadView const& view,
1526 env.
fund (
XRP (10000), alice, bob);
1527 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1530 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1531 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1532 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1533 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1537 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1538 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1539 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1540 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1546 env.
fund (
XRP (10000), alice, bob);
1547 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1550 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1551 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1552 BEAST_EXPECT(inOwnerDir(*env.
current(), bob, chanSle));
1553 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 1);
1557 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1558 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1559 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1560 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1568 env.
fund (
XRP (10000), alice, bob);
1570 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1573 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1574 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1575 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1576 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1585 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1586 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1587 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
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 testcase(
"Account Delete");
1603 using namespace test::jtx;
1604 using namespace std::literals::chrono_literals;
1605 auto rmAccount = [
this](
1612 for (
auto minRmSeq = env.
seq(toRm) + 257;
1613 env.
current()->seq() < minRmSeq;
1626 auto const alice =
Account(
"alice");
1627 auto const bob =
Account(
"bob");
1628 auto const carol =
Account(
"carol");
1630 for (
bool const withOwnerDirFix : {
false,
true})
1632 auto const amd = withOwnerDirFix
1635 Env env{*
this, amd};
1636 env.
fund(
XRP(10000), alice, bob, carol);
1638 auto const feeDrops = env.
current()->fees().base;
1641 auto const pk = alice.pk();
1642 auto const settleDelay = 100s;
1643 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1659 BEAST_EXPECT(chanBal ==
XRP(0));
1660 BEAST_EXPECT(chanAmt ==
XRP(1000));
1662 auto preBob = env.
balance(bob);
1663 auto const delta =
XRP(50);
1664 auto reqBal = chanBal + delta;
1665 auto authAmt = reqBal +
XRP(100);
1666 assert(reqBal <= chanAmt);
1669 if (withOwnerDirFix)
1671 env(
claim(alice, chan, reqBal, authAmt));
1675 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1680 auto const preAlice = env.
balance(alice);
1685 BEAST_EXPECT(env.
balance(bob) == preBob);
1686 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1690 if (withOwnerDirFix)
1692 auto const preAlice = env.
balance(alice);
1693 env(
fund(alice, chan,
XRP(1000)));
1696 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1699 chanAmt = chanAmt +
XRP(1000);
1703 auto const preAlice = env.
balance(alice);
1706 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1716 auto const closeTime = env.
current()->info().parentCloseTime;
1717 auto const minExpiration = closeTime + settleDelay;
1718 env.
close(minExpiration);
1728 env.
fund(
XRP(10000), alice, bob, carol);
1730 auto const feeDrops = env.
current()->fees().base;
1733 auto const pk = alice.pk();
1734 auto const settleDelay = 100s;
1735 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1742 rmAccount(env, bob, carol);
1747 BEAST_EXPECT(chanBal ==
XRP(0));
1748 BEAST_EXPECT(chanAmt ==
XRP(1000));
1749 auto preBob = env.
balance(bob);
1750 auto const delta =
XRP(50);
1751 auto reqBal = chanBal + delta;
1752 auto authAmt = reqBal +
XRP(100);
1753 assert(reqBal <= chanAmt);
1757 auto const preAlice = env.
balance(alice);
1762 BEAST_EXPECT(env.
balance(bob) == preBob);
1763 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1768 auto const preAlice = env.
balance(alice);
1771 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1776 env(
pay(alice, bob,
XRP(20)));
1783 reqBal = chanBal + delta;
1784 authAmt = reqBal +
XRP(100);
1785 env(
claim(alice, chan, reqBal, authAmt));
1788 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1795 reqBal = chanBal + delta;
1796 authAmt = reqBal +
XRP(100);
1799 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
1802 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
1808 auto const preAlice = env.
balance(alice);
1809 env(
fund(alice, chan,
XRP(1000)));
1811 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1814 chanAmt = chanAmt +
XRP(1000);
1823 auto const closeTime = env.
current()->info().parentCloseTime;
1824 auto const minExpiration = closeTime + settleDelay;
1825 env.
close(minExpiration);