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>
55 return {k.key, view.
read(k)};
95 static boost::optional<std::int64_t>
113 boost::optional<NetClock::time_point>
const& cancelAfter = boost::none,
114 boost::optional<std::uint32_t>
const& dstTag = boost::none)
118 jv[jss::TransactionType] = jss::PaymentChannelCreate;
120 jv[jss::Account] = account.human();
121 jv[jss::Destination] = to.
human();
123 jv[
"SettleDelay"] = settleDelay.
count();
126 jv[
"CancelAfter"] = cancelAfter->time_since_epoch().count();
128 jv[
"DestinationTag"] = *dstTag;
137 boost::optional<NetClock::time_point>
const&
expiration = boost::none)
141 jv[jss::TransactionType] = jss::PaymentChannelFund;
143 jv[jss::Account] = account.human();
147 jv[
"Expiration"] =
expiration->time_since_epoch().count();
155 boost::optional<STAmount>
const&
balance = boost::none,
156 boost::optional<STAmount>
const& amount = boost::none,
157 boost::optional<Slice>
const& signature = boost::none,
158 boost::optional<PublicKey>
const& pk = boost::none)
162 jv[jss::TransactionType] = jss::PaymentChannelClaim;
164 jv[jss::Account] = account.human();
171 jv[
"Signature"] =
strHex(*signature);
173 jv[
"PublicKey"] =
strHex(pk->slice());
182 using namespace std::literals::chrono_literals;
184 auto const alice =
Account(
"alice");
185 auto const bob =
Account(
"bob");
186 auto USDA = alice[
"USD"];
187 env.
fund(
XRP(10000), alice, bob);
188 auto const pk = alice.pk();
189 auto const settleDelay = 100s;
190 auto const chan =
channel(alice, bob, env.
seq(alice));
191 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
196 auto const preAlice = env.
balance(alice);
197 env(
fund(alice, chan,
XRP(1000)));
198 auto const feeDrops = env.
current()->fees().base;
199 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
204 BEAST_EXPECT(chanBal ==
XRP(0));
205 BEAST_EXPECT(chanAmt ==
XRP(2000));
209 env(
create(alice, bob, USDA(1000), settleDelay, pk),
212 env(
create(alice, bob,
XRP(-1000), settleDelay, pk),
218 env(
create(alice,
"noAccount",
XRP(1000), settleDelay, pk),
221 env(
create(alice, alice,
XRP(1000), settleDelay, pk),
227 channel(alice,
"noAccount", env.
seq(alice) - 1),
235 auto const iou = USDA(100).value();
236 auto const negXRP =
XRP(-100).value();
237 auto const posXRP =
XRP(100).value();
247 auto const delta =
XRP(500);
248 auto const reqBal = chanBal + delta;
249 auto const authAmt = reqBal +
XRP(-100);
250 assert(reqBal <= chanAmt);
255 auto const preBob = env.
balance(bob);
256 auto const delta =
XRP(500);
257 auto const reqBal = chanBal + delta;
258 auto const authAmt = reqBal +
XRP(100);
259 assert(reqBal <= chanAmt);
260 env(
claim(alice, chan, reqBal, authAmt));
263 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
268 auto preBob = env.
balance(bob);
269 auto const delta =
XRP(500);
270 auto const reqBal = chanBal + delta;
271 auto const authAmt = reqBal +
XRP(100);
272 assert(reqBal <= chanAmt);
275 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
278 auto const feeDrops = env.
current()->fees().base;
279 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
284 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
288 BEAST_EXPECT(env.
balance(bob) == preBob - feeDrops);
292 auto const preBob = env.
balance(bob);
295 assert(reqAmt <= chanAmt);
298 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
302 BEAST_EXPECT(env.
balance(bob) == preBob);
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);
370 auto const chan =
channel(alice, bob, env.
seq(alice));
371 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
373 env.
close(cancelAfter);
378 auto preAlice = env.
balance(alice);
379 auto preBob = env.
balance(bob);
380 auto const delta =
XRP(500);
381 auto const reqBal = chanBal + delta;
382 auto const authAmt = reqBal +
XRP(100);
383 assert(reqBal <= chanAmt);
386 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
387 auto const feeDrops = env.
current()->fees().base;
389 BEAST_EXPECT(env.
balance(bob) == preBob - feeDrops);
390 BEAST_EXPECT(env.
balance(alice) == preAlice + channelFunds);
396 env.
fund(
XRP(10000), alice, bob, carol);
397 auto const pk = alice.pk();
398 auto const settleDelay = 100s;
400 env.
current()->info().parentCloseTime + 3600s;
401 auto const channelFunds =
XRP(1000);
402 auto const chan =
channel(alice, bob, env.
seq(alice));
403 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
408 env.
close(cancelAfter);
410 auto const preAlice = env.
balance(alice);
413 BEAST_EXPECT(env.
balance(alice) == preAlice + channelFunds);
420 testcase(
"expiration");
422 using namespace std::literals::chrono_literals;
424 auto const alice =
Account(
"alice");
425 auto const bob =
Account(
"bob");
426 auto const carol =
Account(
"carol");
427 env.
fund(
XRP(10000), alice, bob, carol);
428 auto const pk = alice.pk();
429 auto const settleDelay = 3600s;
430 auto const closeTime = env.
current()->info().parentCloseTime;
431 auto const minExpiration = closeTime + settleDelay;
433 auto const channelFunds =
XRP(1000);
434 auto const chan =
channel(alice, bob, env.
seq(alice));
435 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
440 auto counts = [](
auto const& t) {
441 return t.time_since_epoch().count();
450 counts(minExpiration) + 100);
456 counts(minExpiration) + 50);
463 counts(minExpiration) + 50);
467 counts(minExpiration) + 50);
476 env.
close(minExpiration);
486 testcase(
"settle delay");
488 using namespace std::literals::chrono_literals;
490 auto const alice =
Account(
"alice");
491 auto const bob =
Account(
"bob");
492 env.
fund(
XRP(10000), alice, bob);
493 auto const pk = alice.pk();
494 auto const settleDelay = 3600s;
496 env.
current()->info().parentCloseTime + settleDelay;
497 auto const channelFunds =
XRP(1000);
498 auto const chan =
channel(alice, bob, env.
seq(alice));
499 env(
create(alice, bob, channelFunds, settleDelay, pk));
504 env.
close(settleTimepoint - settleDelay / 2);
509 auto preBob = env.
balance(bob);
510 auto const delta =
XRP(500);
511 auto const reqBal = chanBal + delta;
512 auto const authAmt = reqBal +
XRP(100);
513 assert(reqBal <= chanAmt);
516 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
519 auto const feeDrops = env.
current()->fees().base;
520 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
522 env.
close(settleTimepoint);
527 auto const preAlice = env.
balance(alice);
528 auto preBob = env.
balance(bob);
529 auto const delta =
XRP(500);
530 auto const reqBal = chanBal + delta;
531 auto const authAmt = reqBal +
XRP(100);
532 assert(reqBal <= chanAmt);
535 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
537 auto const feeDrops = env.
current()->fees().base;
538 BEAST_EXPECT(env.
balance(alice) == preAlice + chanAmt - chanBal);
539 BEAST_EXPECT(env.
balance(bob) == preBob - feeDrops);
546 testcase(
"close dry");
548 using namespace std::literals::chrono_literals;
550 auto const alice =
Account(
"alice");
551 auto const bob =
Account(
"bob");
552 env.
fund(
XRP(10000), alice, bob);
553 auto const pk = alice.pk();
554 auto const settleDelay = 3600s;
555 auto const channelFunds =
XRP(1000);
556 auto const chan =
channel(alice, bob, env.
seq(alice));
557 env(
create(alice, bob, channelFunds, settleDelay, pk));
564 auto const preBob = env.
balance(bob);
565 env(
claim(alice, chan, channelFunds.value(), channelFunds.value()));
567 BEAST_EXPECT(env.
balance(bob) == preBob + channelFunds);
569 auto const preAlice = env.
balance(alice);
573 auto const feeDrops = env.
current()->fees().base;
574 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
581 testcase(
"default amount");
583 using namespace std::literals::chrono_literals;
585 auto const alice =
Account(
"alice");
586 auto const bob =
Account(
"bob");
587 env.
fund(
XRP(10000), alice, bob);
588 auto const pk = alice.pk();
589 auto const settleDelay = 3600s;
590 auto const channelFunds =
XRP(1000);
591 auto const chan =
channel(alice, bob, env.
seq(alice));
592 env(
create(alice, bob, channelFunds, settleDelay, pk));
600 auto const preBob = env.
balance(bob);
602 auto const delta =
XRP(500);
603 auto const reqBal = chanBal + delta;
604 assert(reqBal <= chanAmt);
607 env(
claim(bob, chan, reqBal, boost::none,
Slice(
sig), alice.pk()));
609 auto const feeDrops = env.
current()->fees().base;
610 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
617 auto const preBob = env.
balance(bob);
619 auto const delta =
XRP(500);
620 auto const reqBal = chanBal + delta;
621 assert(reqBal <= chanAmt);
624 env(
claim(bob, chan, reqBal, boost::none,
Slice(
sig), alice.pk()));
626 auto const feeDrops = env.
current()->fees().base;
627 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
636 testcase(
"Disallow XRP");
638 using namespace std::literals::chrono_literals;
640 auto const alice =
Account(
"alice");
641 auto const bob =
Account(
"bob");
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);
658 auto const chan =
channel(alice, bob, env.
seq(alice));
659 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
667 env.
fund(
XRP(10000), alice, bob);
668 auto const chan =
channel(alice, bob, env.
seq(alice));
669 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
673 auto const reqBal =
XRP(500).value();
681 env.
fund(
XRP(10000), alice, bob);
682 auto const chan =
channel(alice, bob, env.
seq(alice));
683 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
687 auto const reqBal =
XRP(500).value();
688 env(
claim(alice, chan, reqBal, reqBal));
698 using namespace std::literals::chrono_literals;
701 auto const alice =
Account(
"alice");
702 auto const bob =
Account(
"bob");
703 env.
fund(
XRP(10000), alice, bob);
705 auto const pk = alice.pk();
706 auto const settleDelay = 3600s;
707 auto const channelFunds =
XRP(1000);
709 auto const chan =
channel(alice, bob, env.
seq(alice));
710 env(
create(alice, bob, channelFunds, settleDelay, pk),
715 auto const chan =
channel(alice, bob, env.
seq(alice));
717 alice, bob, channelFunds, settleDelay, pk, boost::none, 1));
725 testcase(
"Deposit Authorization");
727 using namespace std::literals::chrono_literals;
729 auto const alice =
Account(
"alice");
730 auto const bob =
Account(
"bob");
731 auto const carol =
Account(
"carol");
732 auto USDA = alice[
"USD"];
735 env.
fund(
XRP(10000), alice, bob, carol);
740 auto const pk = alice.pk();
741 auto const settleDelay = 100s;
742 auto const chan =
channel(alice, bob, env.
seq(alice));
743 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
751 env(
fund(alice, chan,
XRP(1000)));
755 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
760 auto const baseFee = env.
current()->fees().base;
761 auto const preBob = env.
balance(bob);
763 auto const delta =
XRP(500).value();
771 BEAST_EXPECT(env.
balance(bob) == preBob);
783 BEAST_EXPECT(env.
balance(bob) == preBob + delta - baseFee);
787 auto const delta =
XRP(600).value();
798 env(deposit::auth(bob, carol));
812 env(deposit::auth(bob, alice));
819 env.
balance(bob) == preBob + delta - (3 * baseFee));
824 auto const delta =
XRP(800).value();
826 env(deposit::unauth(bob, alice));
838 env(
claim(alice, chan, delta, delta));
841 env.
balance(bob) == preBob +
XRP(800) - (5 * baseFee));
850 testcase(
"Multiple channels to the same account");
852 using namespace std::literals::chrono_literals;
854 auto const alice =
Account(
"alice");
855 auto const bob =
Account(
"bob");
856 env.
fund(
XRP(10000), alice, bob);
857 auto const pk = alice.pk();
858 auto const settleDelay = 3600s;
859 auto const channelFunds =
XRP(1000);
860 auto const chan1 =
channel(alice, bob, env.
seq(alice));
861 env(
create(alice, bob, channelFunds, settleDelay, pk));
863 auto const chan2 =
channel(alice, bob, env.
seq(alice));
864 env(
create(alice, bob, channelFunds, settleDelay, pk));
866 BEAST_EXPECT(chan1 != chan2);
872 testcase(
"AccountChannels RPC");
875 using namespace std::literals::chrono_literals;
877 auto const alice =
Account(
"alice");
878 auto const bob =
Account(
"bob");
880 env.
fund(
XRP(10000), alice, bob, charlie);
881 auto const pk = alice.pk();
882 auto const settleDelay = 3600s;
883 auto const channelFunds =
XRP(1000);
885 env(
create(alice, bob, channelFunds, settleDelay, pk));
889 env.
rpc(
"account_channels", alice.human(), bob.human());
890 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
892 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
893 BEAST_EXPECT(r[jss::result][jss::validated]);
896 auto const r = env.
rpc(
"account_channels", alice.human());
897 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
899 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
900 BEAST_EXPECT(r[jss::result][jss::validated]);
904 env.
rpc(
"account_channels", bob.human(), alice.human());
905 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
906 BEAST_EXPECT(r[jss::result][jss::validated]);
909 env(
create(alice, bob, channelFunds, settleDelay, pk));
913 env.
rpc(
"account_channels", alice.human(), bob.human());
914 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
915 BEAST_EXPECT(r[jss::result][jss::validated]);
916 BEAST_EXPECT(chan1Str != chan2Str);
917 for (
auto const& c : {chan1Str, chan2Str})
919 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
920 r[jss::result][jss::channels][1u][jss::channel_id] == c);
927 testcase(
"Account channels RPC markers");
929 using namespace test::jtx;
930 using namespace std::literals;
932 auto const alice =
Account(
"alice");
937 for (
int i = 0; i < n; ++i)
946 for (
auto const& a : bobs)
954 auto const settleDelay = 3600s;
955 auto const channelFunds =
XRP(1);
956 for (
auto const& b : bobs)
958 env(
create(alice, b, channelFunds, settleDelay, alice.pk()));
964 boost::optional<int> limit = boost::none,
966 boost::optional<test::jtx::Account>
const& dst =
969 jvc[jss::account] = src.human();
971 jvc[jss::destination_account] = dst->human();
973 jvc[jss::limit] = *limit;
975 jvc[jss::marker] = marker;
978 "json",
"account_channels",
to_string(jvc))[jss::result];
983 auto const r = testLimit(env, alice);
984 BEAST_EXPECT(r.isMember(jss::channels));
985 BEAST_EXPECT(r[jss::channels].size() == bobs.size());
990 for (
auto const& a : bobs)
995 for (
int limit = 1; limit < bobs.size() + 1; ++limit)
997 auto leftToFind = bobsB58;
998 auto const numFull = bobs.
size() / limit;
999 auto const numNonFull = bobs.size() % limit ? 1 : 0;
1003 auto const testIt = [&](
bool expectMarker,
int expectedBatchSize) {
1004 auto const r = testLimit(env, alice, limit, marker);
1005 BEAST_EXPECT(!expectMarker || r.isMember(jss::marker));
1006 if (r.isMember(jss::marker))
1007 marker = r[jss::marker];
1008 BEAST_EXPECT(r[jss::channels].size() == expectedBatchSize);
1009 auto const c = r[jss::channels];
1010 auto const s = r[jss::channels].size();
1011 for (
int j = 0; j < s; ++j)
1014 c[j][jss::destination_account].asString();
1015 BEAST_EXPECT(leftToFind.count(dstAcc));
1016 leftToFind.erase(dstAcc);
1020 for (
int i = 0; i < numFull; ++i)
1022 bool const expectMarker = (numNonFull != 0 || i < numFull - 1);
1023 testIt(expectMarker, limit);
1028 testIt(
false, bobs.size() % limit);
1030 BEAST_EXPECT(leftToFind.empty());
1035 auto const r = testLimit(env, alice, 0);
1036 BEAST_EXPECT(r.isMember(jss::marker));
1037 BEAST_EXPECT(r[jss::channels].size() == 0);
1046 testcase(
"Account channels RPC owner only");
1048 using namespace test::jtx;
1049 using namespace std::literals;
1051 auto const alice =
Account(
"alice");
1052 auto const bob =
Account(
"bob");
1054 env.
fund(
XRP(10000), alice, bob);
1059 auto const settleDelay = 3600s;
1060 auto const channelFunds =
XRP(1000);
1061 env(
create(alice, bob, channelFunds, settleDelay, alice.pk()));
1062 env(
create(bob, alice, channelFunds, settleDelay, bob.pk()));
1064 auto const r = [&] {
1066 jvc[jss::account] = alice.human();
1069 "json",
"account_channels",
to_string(jvc))[jss::result];
1071 BEAST_EXPECT(r.isMember(jss::channels));
1072 BEAST_EXPECT(r[jss::channels].size() == 1);
1074 r[jss::channels][0u][jss::destination_account].asString() ==
1081 testcase(
"PayChan Auth/Verify RPC");
1082 using namespace jtx;
1083 using namespace std::literals::chrono_literals;
1085 auto const alice =
Account(
"alice");
1086 auto const bob =
Account(
"bob");
1088 env.
fund(
XRP(10000), alice, bob, charlie);
1089 auto const pk = alice.pk();
1090 auto const settleDelay = 3600s;
1091 auto const channelFunds =
XRP(1000);
1093 env(
create(alice, bob, channelFunds, settleDelay, pk));
1098 env.
rpc(
"account_channels", alice.human(), bob.human());
1099 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1101 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1102 BEAST_EXPECT(r[jss::result][jss::validated]);
1104 r[jss::result][jss::channels][0u][jss::public_key].asString();
1107 auto const r = env.
rpc(
"account_channels", alice.human());
1108 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1110 r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1111 BEAST_EXPECT(r[jss::result][jss::validated]);
1113 r[jss::result][jss::channels][0u][jss::public_key].asString();
1117 env.
rpc(
"account_channels", bob.human(), alice.human());
1118 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1119 BEAST_EXPECT(r[jss::result][jss::validated]);
1122 env(
create(alice, bob, channelFunds, settleDelay, pk));
1126 env.
rpc(
"account_channels", alice.human(), bob.human());
1127 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1128 BEAST_EXPECT(r[jss::result][jss::validated]);
1129 BEAST_EXPECT(chan1Str != chan2Str);
1130 for (
auto const& c : {chan1Str, chan2Str})
1132 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1133 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1139 for (
int i = 0; i < slice.size(); ++i)
1141 s +=
"0123456789ABCDEF"[((slice[i] & 0xf0) >> 4)];
1142 s +=
"0123456789ABCDEF"[((slice[i] & 0x0f) >> 0)];
1150 env.
rpc(
"channel_authorize",
"alice", chan1Str,
"1000");
1151 auto const sig = rs[jss::result][jss::signature].asString();
1152 BEAST_EXPECT(!
sig.empty());
1154 auto const rv = env.
rpc(
1155 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1156 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1163 env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1164 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1170 env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1000x",
sig);
1171 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1172 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 ",
sig);
1173 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1174 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"x1000",
sig);
1175 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1176 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"x",
sig);
1177 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1178 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
" ",
sig);
1179 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1181 "channel_verify", pkAsHex, chan1Str,
"1000 1000",
sig);
1182 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1183 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1,000",
sig);
1184 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1185 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
" 1000",
sig);
1186 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1187 rv = env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"",
sig);
1188 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1193 auto chan1StrBad = chan1Str;
1194 chan1StrBad.pop_back();
1196 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1197 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1198 rv = env.
rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1199 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1201 chan1StrBad = chan1Str;
1202 chan1StrBad.push_back(
'0');
1204 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1205 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1206 rv = env.
rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1207 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1209 chan1StrBad = chan1Str;
1210 chan1StrBad.back() =
'x';
1212 "channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1213 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1214 rv = env.
rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1215 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1219 auto illFormedPk = chan1PkStr.
substr(0, chan1PkStr.
size() - 1);
1220 auto const rv = env.
rpc(
1221 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1223 !rv[jss::result][jss::signature_verified].asBool());
1228 auto illFormedPk = pkAsHex.substr(0, chan1PkStr.
size() - 1);
1229 auto const rv = env.
rpc(
1230 "channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1232 !rv[jss::result][jss::signature_verified].asBool());
1238 env.
rpc(
"channel_authorize",
"alice", chan2Str,
"1000");
1239 auto const sig = rs[jss::result][jss::signature].asString();
1240 BEAST_EXPECT(!
sig.empty());
1242 auto const rv = env.
rpc(
1243 "channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1245 !rv[jss::result][jss::signature_verified].asBool());
1251 env.
rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1253 !rv[jss::result][jss::signature_verified].asBool());
1261 charlie, alice, channelFunds, settleDelay, charlie.pk()));
1267 env.
rpc(
"account_channels", charlie.human(), alice.human());
1268 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1270 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1271 BEAST_EXPECT(r[jss::result][jss::validated]);
1272 cpk = r[jss::result][jss::channels][0u][jss::public_key]
1278 env.
rpc(
"channel_authorize",
"charlie", chan,
"1000");
1279 auto const sig = rs[jss::result][jss::signature].asString();
1280 BEAST_EXPECT(!
sig.empty());
1283 env.
rpc(
"channel_verify", cpk, chan,
"1000",
sig);
1285 !rv[jss::result][jss::signature_verified].asBool());
1290 env.
rpc(
"channel_authorize",
"charlie",
"nyx", chan,
"1000");
1291 BEAST_EXPECT(rs1[jss::error] ==
"badKeyType");
1295 auto const rs2 = env.
rpc(
1296 "channel_authorize",
"charlie",
"secp256k1", chan,
"1000");
1297 auto const sig2 = rs2[jss::result][jss::signature].
asString();
1298 BEAST_EXPECT(!sig2.empty());
1301 env.
rpc(
"channel_verify", cpk, chan,
"1000", sig2);
1303 !rv[jss::result][jss::signature_verified].asBool());
1307 auto const rs3 = env.
rpc(
1308 "channel_authorize",
"charlie",
"ed25519", chan,
"1000");
1309 auto const sig3 = rs3[jss::result][jss::signature].
asString();
1310 BEAST_EXPECT(!sig3.empty());
1313 env.
rpc(
"channel_verify", cpk, chan,
"1000", sig3);
1314 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1320 auto rs = env.
rpc(
"channel_authorize",
"alice", chan1Str,
"1000x");
1321 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1322 rs = env.
rpc(
"channel_authorize",
"alice", chan1Str,
"x1000");
1323 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1324 rs = env.
rpc(
"channel_authorize",
"alice", chan1Str,
"x");
1325 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1329 args[jss::amount] =
"2000";
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::channel_id] = chan1Str;
1342 args[jss::key_type] =
"secp256k1";
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::passphrase] =
"passphrase_can_be_anything";
1358 "channel_authorize",
1359 args.toStyledString())[jss::result];
1360 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1365 args[jss::amount] =
"2000";
1366 args[jss::channel_id] = chan1Str;
1367 args[jss::key_type] =
"secp256k1";
1368 args[jss::passphrase] =
"passphrase_can_be_anything";
1369 args[jss::seed] =
"seed can be anything";
1372 "channel_authorize",
1373 args.toStyledString())[jss::result];
1374 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1379 args[jss::amount] =
"2000";
1380 args[jss::channel_id] = chan1Str +
"1";
1381 args[jss::key_type] =
"secp256k1";
1382 args[jss::passphrase] =
"passphrase_can_be_anything";
1385 "channel_authorize",
1386 args.toStyledString())[jss::result];
1387 BEAST_EXPECT(rs[jss::error] ==
"channelMalformed");
1392 args[jss::amount] = 2000;
1393 args[jss::channel_id] = chan1Str;
1394 args[jss::key_type] =
"secp256k1";
1395 args[jss::passphrase] =
"passphrase_can_be_anything";
1398 "channel_authorize",
1399 args.toStyledString())[jss::result];
1400 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1405 args[jss::amount] =
"TwoThousand";
1406 args[jss::channel_id] = chan1Str;
1407 args[jss::key_type] =
"secp256k1";
1408 args[jss::passphrase] =
"passphrase_can_be_anything";
1411 "channel_authorize",
1412 args.toStyledString())[jss::result];
1413 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1421 testcase(
"Optional Fields");
1422 using namespace jtx;
1423 using namespace std::literals::chrono_literals;
1425 auto const alice =
Account(
"alice");
1426 auto const bob =
Account(
"bob");
1427 auto const carol =
Account(
"carol");
1428 auto const dan =
Account(
"dan");
1429 env.
fund(
XRP(10000), alice, bob, carol, dan);
1430 auto const pk = alice.pk();
1431 auto const settleDelay = 3600s;
1432 auto const channelFunds =
XRP(1000);
1434 boost::optional<NetClock::time_point> cancelAfter;
1438 env(
create(alice, bob, channelFunds, settleDelay, pk));
1440 env.
rpc(
"account_channels", alice.human(), bob.human());
1441 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1443 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1444 BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember(
1445 jss::destination_tag));
1459 env.
rpc(
"account_channels", alice.human(), carol.human());
1460 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1462 r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1464 r[jss::result][jss::channels][0u][jss::destination_tag] ==
1472 testcase(
"malformed pk");
1473 using namespace jtx;
1474 using namespace std::literals::chrono_literals;
1476 auto const alice =
Account(
"alice");
1477 auto const bob =
Account(
"bob");
1478 auto USDA = alice[
"USD"];
1479 env.
fund(
XRP(10000), alice, bob);
1480 auto const pk = alice.pk();
1481 auto const settleDelay = 100s;
1483 auto const chan =
channel(alice, bob, env.
seq(alice));
1484 auto jv =
create(alice, bob,
XRP(1000), settleDelay, pk);
1485 auto const pkHex =
strHex(pk.slice());
1486 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1488 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1490 auto badPrefix = pkHex;
1493 jv[
"PublicKey"] = badPrefix;
1496 jv[
"PublicKey"] = pkHex;
1499 auto const authAmt =
XRP(100);
1508 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1510 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1515 jv[
"PublicKey"] = badPrefix;
1519 jv.removeMember(
"PublicKey");
1523 auto const txn = R
"*(
1526 "channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
1528 "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
1530 "aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
1534 auto const r = env.
rpc(
"json",
"channel_verify", txn);
1535 BEAST_EXPECT(r[
"result"][
"error"] ==
"publicMalformed");
1542 testcase(
"Metadata & Ownership");
1544 using namespace jtx;
1545 using namespace std::literals::chrono_literals;
1547 auto const alice =
Account(
"alice");
1548 auto const bob =
Account(
"bob");
1549 auto const settleDelay = 100s;
1550 auto const pk = alice.pk();
1552 auto inOwnerDir = [](
ReadView const& view,
1556 return std::find(ownerDir.begin(), ownerDir.end(), chan) !=
1560 auto ownerDirCount = [](
ReadView const& view,
1571 env.
fund(
XRP(10000), alice, bob);
1572 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1574 auto const [chan, chanSle] =
1576 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1577 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1578 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1579 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1583 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1584 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1585 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1586 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1592 env.
fund(
XRP(10000), alice, bob);
1593 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1595 auto const [chan, chanSle] =
1597 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1598 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1599 BEAST_EXPECT(inOwnerDir(*env.
current(), bob, chanSle));
1600 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 1);
1604 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1605 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1606 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1607 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1615 env.
fund(
XRP(10000), alice, bob);
1617 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1619 auto const [chan, chanSle] =
1621 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1622 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1623 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1624 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1633 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1634 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1635 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1640 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1641 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1642 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1643 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1650 testcase(
"Account Delete");
1651 using namespace test::jtx;
1652 using namespace std::literals::chrono_literals;
1653 auto rmAccount = [
this](
1660 for (
auto minRmSeq = env.
seq(toRm) + 257;
1661 env.
current()->seq() < minRmSeq;
1675 auto const alice =
Account(
"alice");
1676 auto const bob =
Account(
"bob");
1677 auto const carol =
Account(
"carol");
1679 for (
bool const withOwnerDirFix : {
false,
true})
1681 auto const amd = withOwnerDirFix
1684 Env env{*
this, amd};
1685 env.
fund(
XRP(10000), alice, bob, carol);
1687 auto const feeDrops = env.
current()->fees().base;
1690 auto const pk = alice.pk();
1691 auto const settleDelay = 100s;
1692 auto const chan =
channel(alice, bob, env.
seq(alice));
1693 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1708 BEAST_EXPECT(chanBal ==
XRP(0));
1709 BEAST_EXPECT(chanAmt ==
XRP(1000));
1711 auto preBob = env.
balance(bob);
1712 auto const delta =
XRP(50);
1713 auto reqBal = chanBal + delta;
1714 auto authAmt = reqBal +
XRP(100);
1715 assert(reqBal <= chanAmt);
1718 if (withOwnerDirFix)
1720 env(
claim(alice, chan, reqBal, authAmt));
1724 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1729 auto const preAlice = env.
balance(alice);
1734 BEAST_EXPECT(env.
balance(bob) == preBob);
1735 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1739 if (withOwnerDirFix)
1741 auto const preAlice = env.
balance(alice);
1742 env(
fund(alice, chan,
XRP(1000)));
1745 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1748 chanAmt = chanAmt +
XRP(1000);
1752 auto const preAlice = env.
balance(alice);
1755 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1765 auto const closeTime = env.
current()->info().parentCloseTime;
1766 auto const minExpiration = closeTime + settleDelay;
1767 env.
close(minExpiration);
1777 env.
fund(
XRP(10000), alice, bob, carol);
1779 auto const feeDrops = env.
current()->fees().base;
1782 auto const pk = alice.pk();
1783 auto const settleDelay = 100s;
1784 auto const chan =
channel(alice, bob, env.
seq(alice));
1785 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1791 rmAccount(env, bob, carol);
1796 BEAST_EXPECT(chanBal ==
XRP(0));
1797 BEAST_EXPECT(chanAmt ==
XRP(1000));
1798 auto preBob = env.
balance(bob);
1799 auto const delta =
XRP(50);
1800 auto reqBal = chanBal + delta;
1801 auto authAmt = reqBal +
XRP(100);
1802 assert(reqBal <= chanAmt);
1806 auto const preAlice = env.
balance(alice);
1811 BEAST_EXPECT(env.
balance(bob) == preBob);
1812 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1817 auto const preAlice = env.
balance(alice);
1820 BEAST_EXPECT(env.
balance(alice) == preAlice - feeDrops);
1825 env(
pay(alice, bob,
XRP(20)));
1832 reqBal = chanBal + delta;
1833 authAmt = reqBal +
XRP(100);
1834 env(
claim(alice, chan, reqBal, authAmt));
1837 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1844 reqBal = chanBal + delta;
1845 authAmt = reqBal +
XRP(100);
1848 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
1851 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
1857 auto const preAlice = env.
balance(alice);
1858 env(
fund(alice, chan,
XRP(1000)));
1860 env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1863 chanAmt = chanAmt +
XRP(1000);
1872 auto const closeTime = env.
current()->info().parentCloseTime;
1873 auto const minExpiration = closeTime + settleDelay;
1874 env.
close(minExpiration);
1884 testcase(
"using tickets");
1885 using namespace jtx;
1886 using namespace std::literals::chrono_literals;
1888 auto const alice =
Account(
"alice");
1889 auto const bob =
Account(
"bob");
1890 auto USDA = alice[
"USD"];
1891 env.
fund(
XRP(10000), alice, bob);
1897 env(ticket::create(alice, 10));
1901 env(ticket::create(bob, 10));
1904 auto const pk = alice.pk();
1905 auto const settleDelay = 100s;
1906 auto const chan =
channel(alice, bob, aliceTicketSeq);
1908 env(
create(alice, bob,
XRP(1000), settleDelay, pk),
1912 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
1918 auto const preAlice = env.
balance(alice);
1922 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
1924 auto const feeDrops = env.
current()->fees().base;
1925 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1930 BEAST_EXPECT(chanBal ==
XRP(0));
1931 BEAST_EXPECT(chanAmt ==
XRP(2000));
1935 auto const preBob = env.
balance(bob);
1936 auto const delta =
XRP(500);
1937 auto const reqBal = chanBal + delta;
1938 auto const authAmt = reqBal +
XRP(100);
1939 assert(reqBal <= chanAmt);
1940 env(
claim(alice, chan, reqBal, authAmt),
1944 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
1948 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1953 auto preBob = env.
balance(bob);
1954 auto const delta =
XRP(500);
1955 auto const reqBal = chanBal + delta;
1956 auto const authAmt = reqBal +
XRP(100);
1957 assert(reqBal <= chanAmt);
1960 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
1964 BEAST_EXPECT(env.
seq(bob) == bobSeq);
1968 auto const feeDrops = env.
current()->fees().base;
1969 BEAST_EXPECT(env.
balance(bob) == preBob + delta - feeDrops);
1975 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
1980 BEAST_EXPECT(env.
seq(bob) == bobSeq);
1984 BEAST_EXPECT(env.
balance(bob) == preBob - feeDrops);
1988 auto const preBob = env.
balance(bob);
1991 assert(reqAmt <= chanAmt);
1996 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
2001 BEAST_EXPECT(env.
seq(bob) == bobSeq);
2005 BEAST_EXPECT(env.
balance(bob) == preBob);
2009 env(
fund(bob, chan,
XRP(1000)),
2014 BEAST_EXPECT(env.
seq(bob) == bobSeq);
2021 auto const preAlice = env.
balance(alice);
2022 auto const preBob = env.
balance(bob);
2023 env(
claim(bob, chan),
2028 BEAST_EXPECT(env.
seq(bob) == bobSeq);
2031 auto const feeDrops = env.
current()->fees().base;
2032 auto const delta = chanAmt - chanBal;
2033 assert(delta > beast::zero);
2034 BEAST_EXPECT(env.
balance(alice) == preAlice + delta);
2035 BEAST_EXPECT(env.
balance(bob) == preBob - feeDrops);
2038 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
2040 BEAST_EXPECT(env.
seq(bob) == bobSeq);