18 #include <ripple/core/ConfigSections.h>
19 #include <ripple/protocol/Feature.h>
20 #include <ripple/protocol/jss.h>
66 testcase(
"No Reserve");
69 Env env{*
this, features};
78 auto const fee = env.current()->fees().base;
79 auto const smallSignersReserve = reserve1 ?
XRP(250) :
XRP(350);
80 env.fund(smallSignersReserve -
drops(1), alice);
82 env.require(
owners(alice, 0));
89 env.require(
owners(alice, 0));
96 env.require(
owners(alice, reserve1 ? 1 : 3));
101 auto const addReserveBigSigners = reserve1 ?
XRP(0) :
XRP(350);
102 env(
pay(env.master, alice, addReserveBigSigners +
fee -
drops(1)));
118 env.require(
owners(alice, reserve1 ? 1 : 3));
125 env.require(
owners(alice, reserve1 ? 1 : 10));
130 env.require(
owners(alice, 0));
136 testcase(
"SignerListSet");
139 Env env{*
this, features};
141 env.fund(
XRP(1000), alice);
211 env.require(
owners(alice, 0));
217 testcase(
"Phantom Signers");
220 Env env{*
this, features};
222 env.fund(
XRP(1000), alice);
226 env(signers(alice, 1, {{
bogie, 1}, {
demon, 1}}));
231 auto const baseFee = env.current()->fees().base;
235 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
238 aliceSeq = env.seq(alice);
241 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
243 aliceSeq = env.seq(alice);
246 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
249 aliceSeq = env.seq(alice);
252 BEAST_EXPECT(env.seq(alice) == aliceSeq);
255 aliceSeq = env.seq(alice);
261 BEAST_EXPECT(env.seq(alice) == aliceSeq);
264 env(signers(alice, 2, {{
bogie, 1}, {
demon, 1}}));
265 aliceSeq = env.seq(alice);
268 BEAST_EXPECT(env.seq(alice) == aliceSeq);
271 aliceSeq = env.seq(alice);
274 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
283 Env env{*
this, features};
285 env.fund(
XRP(1000), alice);
304 auto const baseFee = env.current()->fees().base;
309 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
312 aliceSeq = env.seq(alice);
315 fee((2 * baseFee) - 1),
319 BEAST_EXPECT(env.seq(alice) == aliceSeq);
322 aliceSeq = env.seq(alice);
328 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
331 aliceSeq = env.seq(alice);
334 fee((9 * baseFee) - 1),
338 BEAST_EXPECT(env.seq(alice) == aliceSeq);
344 testcase(
"Misordered Signers");
347 Env env{*
this, features};
349 env.fund(
XRP(1000), alice);
354 env(signers(alice, 1, {{
bogie, 1}, {
demon, 1}}));
359 std::reverse(phantoms.signers.begin(), phantoms.signers.end());
363 BEAST_EXPECT(env.seq(alice) == aliceSeq);
369 testcase(
"Master Signers");
372 Env env{*
this, features};
376 env.fund(
XRP(1000), alice, becky, cheri);
387 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
390 env(signers(alice, 4, {{becky, 3}, {cheri, 4}}),
sig(alice));
395 auto const baseFee = env.current()->fees().base;
396 aliceSeq = env.seq(alice);
399 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
402 aliceSeq = env.seq(alice);
405 BEAST_EXPECT(env.seq(alice) == aliceSeq);
415 aliceSeq = env.seq(alice);
416 env(
noop(alice),
msig(becky, cheri),
fee(3 * baseFee));
418 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
424 testcase(
"Regular Signers");
427 Env env{*
this, features};
431 env.fund(
XRP(1000), alice, becky, cheri);
435 env(signers(alice, 1, {{becky, 1}, {cheri, 1}}),
sig(alice));
451 auto const baseFee = env.current()->fees().base;
455 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
458 aliceSeq = env.seq(alice);
464 BEAST_EXPECT(env.seq(alice) == aliceSeq);
467 aliceSeq = env.seq(alice);
470 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
472 aliceSeq = env.seq(alice);
475 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
478 aliceSeq = env.seq(alice);
483 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
489 testcase(
"Regular Signers Using submit_multisigned");
495 cfg->loadFromString(
"[" SECTION_SIGNING_SUPPORT
"]\ntrue");
502 env.
fund(
XRP(1000), alice, becky, cheri);
506 env(signers(alice, 2, {{becky, 1}, {cheri, 1}}),
sig(alice));
519 auto const baseFee = env.
current()->fees().base;
525 jv[jss::tx_json][jss::Account] = alice.human();
526 jv[jss::tx_json][jss::TransactionType] = jss::AccountSet;
527 jv[jss::tx_json][jss::Fee] = (8 * baseFee).jsonClipped();
528 jv[jss::tx_json][jss::Sequence] = env.
seq(alice);
529 jv[jss::tx_json][jss::SigningPubKey] =
"";
533 jv[jss::account] = cheri.human();
534 jv[jss::key_type] =
"ed25519";
535 jv[jss::passphrase] = cher.name();
538 jv[jss::account] = becky.human();
539 jv[jss::secret] = beck.name();
545 aliceSeq = env.
seq(alice);
549 env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
550 BEAST_EXPECT(jrr[jss::status] ==
"success");
555 jv_two[jss::tx_json] = jrr[jss::tx_json];
557 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_two))[jss::result];
558 BEAST_EXPECT(jrr[jss::status] ==
"success");
561 jv_submit[jss::tx_json] = jrr[jss::tx_json];
564 "submit_multisigned",
566 BEAST_EXPECT(jrr[jss::status] ==
"success");
568 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
573 aliceSeq = env.
seq(alice);
575 jv_one[jss::tx_json][jss::SigningPubKey] =
576 strHex(alice.pk().slice());
579 env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
580 BEAST_EXPECT(jrr[jss::status] ==
"error");
581 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
583 jrr[jss::error_message] ==
584 "When multi-signing 'tx_json.SigningPubKey' must be empty.");
589 aliceSeq = env.
seq(alice);
591 jv_one[jss::tx_json][jss::Fee] = -1;
594 env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
595 BEAST_EXPECT(jrr[jss::status] ==
"success");
600 jv_two[jss::tx_json] = jrr[jss::tx_json];
602 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_two))[jss::result];
603 BEAST_EXPECT(jrr[jss::status] ==
"success");
606 jv_submit[jss::tx_json] = jrr[jss::tx_json];
609 "submit_multisigned",
611 BEAST_EXPECT(jrr[jss::status] ==
"error");
612 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
614 jrr[jss::error_message] ==
615 "Invalid Fee field. Fees must be greater than zero.");
620 aliceSeq = env.
seq(alice);
622 jv_one[jss::tx_json][jss::Fee] =
623 alice[
"USD"](10).value().getFullText();
626 env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
627 BEAST_EXPECT(jrr[jss::status] ==
"success");
632 jv_two[jss::tx_json] = jrr[jss::tx_json];
634 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_two))[jss::result];
635 BEAST_EXPECT(jrr[jss::status] ==
"success");
638 jv_submit[jss::tx_json] = jrr[jss::tx_json];
641 "submit_multisigned",
643 BEAST_EXPECT(jrr[jss::status] ==
"error");
644 BEAST_EXPECT(jrr[jss::error] ==
"internal");
645 BEAST_EXPECT(jrr[jss::error_message] ==
"Internal error.");
650 aliceSeq = env.
seq(alice);
652 jv[jss::account] = cheri.human();
653 jv[jss::secret] = cheri.name();
654 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv))[jss::result];
655 BEAST_EXPECT(jrr[jss::status] ==
"error");
656 BEAST_EXPECT(jrr[jss::error] ==
"masterDisabled");
658 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
664 aliceSeq = env.
seq(alice);
668 env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
669 BEAST_EXPECT(jrr[jss::status] ==
"success");
674 jv_two[jss::tx_json] = jrr[jss::tx_json];
675 jv_two[jss::account] = becky.human();
676 jv_two[jss::key_type] =
"ed25519";
677 jv_two[jss::passphrase] = becky.name();
678 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_two))[jss::result];
679 BEAST_EXPECT(jrr[jss::status] ==
"success");
682 jv_submit[jss::tx_json] = jrr[jss::tx_json];
685 "submit_multisigned",
687 BEAST_EXPECT(jrr[jss::status] ==
"success");
689 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
695 jv[jss::tx_json][jss::Account] =
"DEADBEEF";
697 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv))[jss::result];
698 BEAST_EXPECT(jrr[jss::status] ==
"error");
699 BEAST_EXPECT(jrr[jss::error] ==
"srcActMalformed");
702 jv[jss::tx_json][jss::Account] = jimmy.human();
703 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv))[jss::result];
704 BEAST_EXPECT(jrr[jss::status] ==
"error");
705 BEAST_EXPECT(jrr[jss::error] ==
"srcActNotFound");
709 aliceSeq = env.
seq(alice);
715 "json",
"submit_multisigned",
to_string(jv))[jss::result];
716 BEAST_EXPECT(jrr[jss::status] ==
"error");
717 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
719 jrr[jss::error_message] ==
720 "tx_json.Signers array may not be empty.");
722 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
729 testcase(
"Heterogenious Signers");
732 Env env{*
this, features};
737 env.fund(
XRP(1000), alice, becky, cheri, daria);
758 env(signers(alice, 1, {{becky, 1}, {cheri, 1}, {daria, 1}, {
jinni, 1}}),
764 auto const baseFee = env.current()->fees().base;
768 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
770 aliceSeq = env.seq(alice);
773 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
775 aliceSeq = env.seq(alice);
778 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
780 aliceSeq = env.seq(alice);
783 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
785 aliceSeq = env.seq(alice);
788 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
791 aliceSeq = env.seq(alice);
796 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
810 aliceSeq = env.seq(alice);
815 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
818 aliceSeq = env.seq(alice);
823 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
841 aliceSeq = env.seq(alice);
854 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
857 aliceSeq = env.seq(alice);
863 BEAST_EXPECT(env.seq(alice) == aliceSeq);
868 env.require(
owners(alice, 0));
876 testcase(
"Key Disable");
879 Env env{*
this, features};
881 env.fund(
XRP(1000), alice);
915 env(signers(alice, 1, {{
bogie, 1}}),
sig(alie));
921 auto const baseFee = env.current()->fees().base;
934 env(signers(alice, 1, {{
bogie, 1}}),
sig(alice));
957 testcase(
"Regular Key");
960 Env env{*
this, features};
962 env.fund(
XRP(1000), alice);
978 env.fund(
XRP(1000), becky);
980 env(signers(becky, 1, {{alice, 1}}),
sig(becky));
992 testcase(
"Transaction Types");
995 Env env{*
this, features};
1000 auto const USD = gw[
"USD"];
1001 env.fund(
XRP(1000), alice, becky, zelda, gw);
1006 env(
regkey(alice, alie));
1010 env(signers(alice, 2, {{becky, 1}, {
bogie, 1}}),
sig(alie));
1013 env.require(
owners(alice, signerListOwners + 0));
1016 auto const baseFee = env.current()->fees().base;
1018 env(
pay(alice, env.master,
XRP(1)),
1022 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1025 aliceSeq = env.seq(alice);
1028 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1031 aliceSeq = env.seq(alice);
1035 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1038 env(
trust(
"alice", USD(100)),
1043 env.require(
owners(alice, signerListOwners + 1));
1046 env(
pay(gw, alice, USD(50)));
1048 env.require(
balance(alice, USD(50)));
1049 env.require(
balance(gw, alice[
"USD"](-50)));
1052 env(offer(alice,
XRP(50), USD(50)),
1056 env.require(
owners(alice, signerListOwners + 2));
1060 aliceSeq = env.seq(alice);
1066 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1067 env.require(
owners(alice, signerListOwners + 1));
1071 env(signers(alice, 3, {{becky, 1}, {
bogie, 1}, {
demon, 1}}),
1081 testcase(
"Bad Signature Text");
1084 using namespace jtx;
1086 Env env{*
this, features};
1089 auto submitSTTx = [&env](
STTx const& stx) {
1091 jvResult[jss::tx_blob] =
strHex(stx.getSerializer().slice());
1092 return env.rpc(
"json",
"submit",
to_string(jvResult));
1096 env.fund(
XRP(1000), alice);
1097 env(signers(alice, 1, {{
bogie, 1}, {
demon, 1}}),
sig(alice));
1099 auto const baseFee = env.current()->fees().base;
1105 auto const info = submitSTTx(local);
1107 info[jss::result][jss::error_exception] ==
1108 "fails local checks: Empty SigningPubKey.");
1119 auto const info = submitSTTx(local);
1121 info[jss::result][jss::error_exception] ==
1122 "fails local checks: Invalid signature.");
1132 auto const info = submitSTTx(local);
1134 info[jss::result][jss::error_exception] ==
1135 "fails local checks: Invalid signature.");
1142 auto const info = submitSTTx(local);
1144 info[jss::result][jss::error_exception] ==
1145 "fails local checks: Cannot both single- and multi-sign.");
1151 local.
sign(alice.pk(), alice.sk());
1153 auto const info = submitSTTx(local);
1155 info[jss::result][jss::error_exception] ==
1156 "fails local checks: Cannot both single- and multi-sign.");
1168 auto const info = submitSTTx(local);
1170 info[jss::result][jss::error_exception].asString().find(
1171 "Invalid signature on account r") != std::string::npos);
1178 auto const info = submitSTTx(local);
1180 info[jss::result][jss::error_exception] ==
1181 "fails local checks: Invalid Signers array size.");
1235 auto const info = submitSTTx(local);
1237 info[jss::result][jss::error_exception] ==
1238 "fails local checks: Invalid Signers array size.");
1244 auto const info = submitSTTx(local);
1246 info[jss::result][jss::error_exception] ==
1247 "fails local checks: Invalid multisigner.");
1253 auto const info = submitSTTx(local);
1255 info[jss::result][jss::error_exception] ==
1256 "fails local checks: Duplicate Signers not allowed.");
1266 auto const info = submitSTTx(local);
1268 info[jss::result][jss::error_exception] ==
1269 "fails local checks: Unsorted Signers array.");
1276 testcase(
"No Multisigners");
1278 using namespace jtx;
1279 Env env{*
this, features};
1282 env.fund(
XRP(1000), alice, becky);
1285 auto const baseFee = env.current()->fees().base;
1295 testcase(
"Multisigning multisigner");
1302 using namespace jtx;
1303 Env env{*
this, features};
1306 env.fund(
XRP(1000), alice, becky);
1310 env(signers(alice, 1, {{becky, 1}}));
1314 env(signers(becky, 1, {{
bogie, 1}, {
demon, 1}}));
1319 auto const baseFee = env.current()->fees().base;
1372 testcase(
"sign_for Hash");
1378 using namespace jtx;
1384 cfg->loadFromString(
"[" SECTION_SIGNING_SUPPORT
"]\ntrue");
1391 env(signers(alice, 2, {{
bogie, 1}, {
ghost, 1}}));
1396 auto const baseFee = env.
current()->fees().base;
1400 jvSig1[jss::tx_json][jss::Account] = alice.human();
1401 jvSig1[jss::tx_json][jss::Amount] = 10000000;
1402 jvSig1[jss::tx_json][jss::Destination] = env.
master.
human();
1403 jvSig1[jss::tx_json][jss::Fee] = (3 * baseFee).jsonClipped();
1404 jvSig1[jss::tx_json][jss::Sequence] = env.
seq(alice);
1405 jvSig1[jss::tx_json][jss::TransactionType] = jss::Payment;
1408 BEAST_EXPECT(jvSig2[jss::result][jss::status].asString() ==
"success");
1412 jvSig2[jss::result][jss::tx_json][jss::hash].
asString();
1415 jvSig2[jss::result][jss::account] =
ghost.
human();
1416 jvSig2[jss::result][jss::secret] =
ghost.
name();
1418 env.
rpc(
"json",
"sign_for",
to_string(jvSig2[jss::result]));
1420 jvSubmit[jss::result][jss::status].asString() ==
"success");
1424 jvSubmit[jss::result][jss::tx_json][jss::hash].
asString();
1425 BEAST_EXPECT(hash1 != hash2);
1429 "json",
"submit_multisigned",
to_string(jvSubmit[jss::result]));
1431 jvResult[jss::result][jss::status].asString() ==
"success");
1433 jvResult[jss::result][jss::engine_result].asString() ==
1439 hash2 == jvResult[jss::result][jss::tx_json][jss::hash].asString());
1445 BEAST_EXPECT(jvTx[jss::result][jss::status].asString() ==
"success");
1446 BEAST_EXPECT(jvTx[jss::result][jss::validated].asString() ==
"true");
1455 testcase(
"Amendment Transition");
1461 using namespace jtx;
1468 env.fund(
XRP(1000), alice, becky, cheri, daria);
1472 env(signers(alice, 1, {{
bogie, 1}}));
1486 env.require(
owners(alice, 3));
1487 env.require(
owners(becky, 10));
1494 env(signers(cheri, 1, {{
bogie, 1}}));
1508 env.require(
owners(alice, 3));
1509 env.require(
owners(becky, 10));
1510 env.require(
owners(cheri, 1));
1511 env.require(
owners(daria, 1));
1529 env.require(
owners(alice, 1));
1530 env.require(
owners(becky, 0));
1531 env.require(
owners(cheri, 1));
1532 env.require(
owners(daria, 1));
1541 env.require(
owners(alice, 0));
1542 env.require(
owners(becky, 0));
1543 env.require(
owners(cheri, 0));
1544 env.require(
owners(daria, 0));
1550 testcase(
"Signers With Tickets");
1552 using namespace jtx;
1553 Env env{*
this, features};
1555 env.fund(
XRP(2000), alice);
1560 env(ticket::create(alice, 20));
1565 env(signers(alice, 1, {{
bogie, 1}, {
demon, 1}}),
1568 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1569 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1572 auto const baseFee = env.current()->fees().base;
1578 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1579 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1584 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1585 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1594 testcase(
"Signers With Tags");
1596 using namespace jtx;
1597 Env env{*
this, features};
1599 env.fund(
XRP(1000), alice);
1601 uint8_t tag1[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1602 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1603 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1604 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
1607 "hello world some ascii 32b long";
1613 env(signers(alice, 1, {{
bogie, 1, bogie_tag}, {
demon, 1, demon_tag}}));
1618 auto const baseFee = env.current()->fees().base;
1622 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1625 aliceSeq = env.seq(alice);
1628 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1630 aliceSeq = env.seq(alice);
1633 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1636 aliceSeq = env.seq(alice);
1639 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1642 aliceSeq = env.seq(alice);
1648 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1651 env(signers(alice, 2, {{
bogie, 1}, {
demon, 1}}));
1652 aliceSeq = env.seq(alice);
1655 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1658 aliceSeq = env.seq(alice);
1661 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1690 using namespace jtx;