3#include <xrpld/core/ConfigSections.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/jss.h>
54 Env env{*
this, features};
59 bool const reserve1{features[featureMultiSignReserve]};
63 auto const fee = env.current()->fees().base;
64 auto const smallSignersReserve = reserve1 ?
XRP(250) :
XRP(350);
65 env.fund(smallSignersReserve -
drops(1), alice);
67 env.require(
owners(alice, 0));
74 env.require(
owners(alice, 0));
81 env.require(
owners(alice, reserve1 ? 1 : 3));
86 auto const addReserveBigSigners = reserve1 ?
XRP(0) :
XRP(350);
87 env(
pay(env.master, alice, addReserveBigSigners +
fee -
drops(1)));
103 env.require(
owners(alice, reserve1 ? 1 : 3));
110 env.require(
owners(alice, reserve1 ? 1 : 10));
115 env.require(
owners(alice, 0));
124 Env env{*
this, features};
126 env.fund(
XRP(1000), alice);
179 features[featureExpandedSignerList]
197 env.require(
owners(alice, 0));
206 Env env{*
this, features};
208 env.fund(
XRP(1000), alice);
214 env.require(
owners(alice, features[featureMultiSignReserve] ? 1 : 4));
217 auto const baseFee = env.current()->fees().base;
221 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
224 aliceSeq = env.seq(alice);
227 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
229 aliceSeq = env.seq(alice);
232 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
235 aliceSeq = env.seq(alice);
239 rpc(
"invalidTransaction",
240 "fails local checks: Duplicate Signers not allowed."));
242 BEAST_EXPECT(env.seq(alice) == aliceSeq);
245 aliceSeq = env.seq(alice);
251 BEAST_EXPECT(env.seq(alice) == aliceSeq);
255 aliceSeq = env.seq(alice);
258 BEAST_EXPECT(env.seq(alice) == aliceSeq);
261 aliceSeq = env.seq(alice);
264 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
273 Env env{*
this, features};
275 env.fund(
XRP(1000), alice);
291 env.require(
owners(alice, features[featureMultiSignReserve] ? 1 : 10));
294 auto const baseFee = env.current()->fees().base;
299 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
302 aliceSeq = env.seq(alice);
305 fee((2 * baseFee) - 1),
309 BEAST_EXPECT(env.seq(alice) == aliceSeq);
312 aliceSeq = env.seq(alice);
318 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
321 aliceSeq = env.seq(alice);
324 fee((9 * baseFee) - 1),
328 BEAST_EXPECT(env.seq(alice) == aliceSeq);
337 Env env{*
this, features};
339 env.fund(
XRP(1000), alice);
346 env.require(
owners(alice, features[featureMultiSignReserve] ? 1 : 4));
349 std::reverse(phantoms.signers.begin(), phantoms.signers.end());
353 rpc(
"invalidTransaction",
354 "fails local checks: Unsorted Signers array."));
356 BEAST_EXPECT(env.seq(alice) == aliceSeq);
365 Env env{*
this, features};
369 env.fund(
XRP(1000), alice, becky, cheri);
380 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
383 env(
signers(alice, 4, {{becky, 3}, {cheri, 4}}),
sig(alice));
385 env.require(
owners(alice, features[featureMultiSignReserve] ? 1 : 4));
388 auto const baseFee = env.current()->fees().base;
389 aliceSeq = env.seq(alice);
392 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
395 aliceSeq = env.seq(alice);
398 BEAST_EXPECT(env.seq(alice) == aliceSeq);
408 aliceSeq = env.seq(alice);
409 env(
noop(alice),
msig(becky, cheri),
fee(3 * baseFee));
411 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
420 Env env{*
this, features};
424 env.fund(
XRP(1000), alice, becky, cheri);
428 env(
signers(alice, 1, {{becky, 1}, {cheri, 1}}),
sig(alice));
444 auto const baseFee = env.current()->fees().base;
448 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
451 aliceSeq = env.seq(alice);
457 BEAST_EXPECT(env.seq(alice) == aliceSeq);
460 aliceSeq = env.seq(alice);
463 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
465 aliceSeq = env.seq(alice);
468 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
471 aliceSeq = env.seq(alice);
476 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
482 testcase(
"Regular Signers Using submit_multisigned");
488 cfg->loadFromString(
"[" SECTION_SIGNING_SUPPORT
"]\ntrue");
495 env.
fund(
XRP(1000), alice, becky, cheri);
499 env(
signers(alice, 2, {{becky, 1}, {cheri, 1}}),
sig(alice));
512 auto const baseFee = env.
current()->fees().base;
518 jv[jss::tx_json][jss::Account] = alice.human();
519 jv[jss::tx_json][jss::TransactionType] = jss::AccountSet;
520 jv[jss::tx_json][jss::Fee] = (8 * baseFee).jsonClipped();
521 jv[jss::tx_json][jss::Sequence] = env.
seq(alice);
522 jv[jss::tx_json][jss::SigningPubKey] =
"";
526 jv[jss::account] = cheri.human();
527 jv[jss::key_type] =
"ed25519";
528 jv[jss::passphrase] = cher.name();
531 jv[jss::account] = becky.human();
532 jv[jss::secret] = beck.name();
538 aliceSeq = env.
seq(alice);
542 env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
543 BEAST_EXPECT(jrr[jss::status] ==
"success");
548 jv_two[jss::tx_json] = jrr[jss::tx_json];
550 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_two))[jss::result];
551 BEAST_EXPECT(jrr[jss::status] ==
"success");
554 jv_submit[jss::tx_json] = jrr[jss::tx_json];
557 "submit_multisigned",
559 BEAST_EXPECT(jrr[jss::status] ==
"success");
561 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
566 aliceSeq = env.
seq(alice);
568 jv_one[jss::tx_json][jss::SigningPubKey] =
569 strHex(alice.pk().slice());
572 env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
573 BEAST_EXPECT(jrr[jss::status] ==
"error");
574 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
576 jrr[jss::error_message] ==
577 "When multi-signing 'tx_json.SigningPubKey' must be empty.");
582 aliceSeq = env.
seq(alice);
584 jv_one[jss::tx_json][jss::Fee] = -1;
587 env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
588 BEAST_EXPECT(jrr[jss::status] ==
"success");
593 jv_two[jss::tx_json] = jrr[jss::tx_json];
595 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_two))[jss::result];
596 BEAST_EXPECT(jrr[jss::status] ==
"success");
599 jv_submit[jss::tx_json] = jrr[jss::tx_json];
602 "submit_multisigned",
604 BEAST_EXPECT(jrr[jss::status] ==
"error");
605 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
607 jrr[jss::error_message] ==
608 "Invalid Fee field. Fees must be greater than zero.");
613 aliceSeq = env.
seq(alice);
615 jv_one[jss::tx_json][jss::Fee] =
616 alice[
"USD"](10).value().getFullText();
619 env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
620 BEAST_EXPECT(jrr[jss::status] ==
"success");
625 jv_two[jss::tx_json] = jrr[jss::tx_json];
627 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_two))[jss::result];
628 BEAST_EXPECT(jrr[jss::status] ==
"success");
631 jv_submit[jss::tx_json] = jrr[jss::tx_json];
634 "submit_multisigned",
636 BEAST_EXPECT(jrr[jss::status] ==
"error");
637 BEAST_EXPECT(jrr[jss::error] ==
"internal");
638 BEAST_EXPECT(jrr[jss::error_message] ==
"Internal error.");
643 aliceSeq = env.
seq(alice);
645 jv[jss::account] = cheri.human();
646 jv[jss::secret] = cheri.name();
647 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv))[jss::result];
648 BEAST_EXPECT(jrr[jss::status] ==
"error");
649 BEAST_EXPECT(jrr[jss::error] ==
"masterDisabled");
651 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
657 aliceSeq = env.
seq(alice);
661 env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
662 BEAST_EXPECT(jrr[jss::status] ==
"success");
667 jv_two[jss::tx_json] = jrr[jss::tx_json];
668 jv_two[jss::account] = becky.human();
669 jv_two[jss::key_type] =
"ed25519";
670 jv_two[jss::passphrase] = becky.name();
671 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_two))[jss::result];
672 BEAST_EXPECT(jrr[jss::status] ==
"success");
675 jv_submit[jss::tx_json] = jrr[jss::tx_json];
678 "submit_multisigned",
680 BEAST_EXPECT(jrr[jss::status] ==
"success");
682 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
688 jv[jss::tx_json][jss::Account] =
"DEADBEEF";
690 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv))[jss::result];
691 BEAST_EXPECT(jrr[jss::status] ==
"error");
692 BEAST_EXPECT(jrr[jss::error] ==
"srcActMalformed");
695 jv[jss::tx_json][jss::Account] = jimmy.human();
696 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv))[jss::result];
697 BEAST_EXPECT(jrr[jss::status] ==
"error");
698 BEAST_EXPECT(jrr[jss::error] ==
"srcActNotFound");
702 aliceSeq = env.
seq(alice);
704 jv[jss::tx_json][sfSigners.fieldName] =
708 "json",
"submit_multisigned",
to_string(jv))[jss::result];
709 BEAST_EXPECT(jrr[jss::status] ==
"error");
710 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
712 jrr[jss::error_message] ==
713 "tx_json.Signers array may not be empty.");
715 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
725 Env env{*
this, features};
730 env.fund(
XRP(1000), alice, becky, cheri, daria);
751 env(
signers(alice, 1, {{becky, 1}, {cheri, 1}, {daria, 1}, {
jinni, 1}}),
754 env.require(
owners(alice, features[featureMultiSignReserve] ? 1 : 6));
757 auto const baseFee = env.current()->fees().base;
761 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
763 aliceSeq = env.seq(alice);
766 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
768 aliceSeq = env.seq(alice);
771 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
773 aliceSeq = env.seq(alice);
776 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
778 aliceSeq = env.seq(alice);
781 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
784 aliceSeq = env.seq(alice);
789 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
801 env.require(
owners(alice, features[featureMultiSignReserve] ? 1 : 6));
803 aliceSeq = env.seq(alice);
808 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
811 aliceSeq = env.seq(alice);
816 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
832 env.require(
owners(alice, features[featureMultiSignReserve] ? 1 : 10));
834 aliceSeq = env.seq(alice);
847 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
850 aliceSeq = env.seq(alice);
856 BEAST_EXPECT(env.seq(alice) == aliceSeq);
861 env.require(
owners(alice, 0));
872 Env env{*
this, features};
874 env.fund(
XRP(1000), alice);
915 auto const baseFee = env.current()->fees().base;
954 Env env{*
this, features};
956 env.fund(
XRP(1000), alice);
973 env.fund(
XRP(1000), becky);
976 env(
signers(becky, 1, {{alice, 1}}),
sig(becky));
991 Env env{*
this, features};
996 auto const USD = gw[
"USD"];
997 env.fund(
XRP(1000), alice, becky, zelda, gw);
1002 env(
regkey(alice, alie));
1008 int const signerListOwners{features[featureMultiSignReserve] ? 1 : 4};
1009 env.require(
owners(alice, signerListOwners + 0));
1012 auto const baseFee = env.current()->fees().base;
1014 env(
pay(alice, env.master,
XRP(1)),
1018 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1021 aliceSeq = env.seq(alice);
1024 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1027 aliceSeq = env.seq(alice);
1031 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1034 env(
trust(
"alice", USD(100)),
1039 env.require(
owners(alice, signerListOwners + 1));
1042 env(
pay(gw, alice, USD(50)));
1044 env.require(
balance(alice, USD(50)));
1045 env.require(
balance(gw, alice[
"USD"](-50)));
1048 env(
offer(alice,
XRP(50), USD(50)),
1052 env.require(
owners(alice, signerListOwners + 2));
1056 aliceSeq = env.seq(alice);
1062 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1063 env.require(
owners(alice, signerListOwners + 1));
1071 env.require(
owners(alice, features[featureMultiSignReserve] ? 2 : 6));
1080 using namespace jtx;
1082 Env env{*
this, features};
1085 auto submitSTTx = [&env](
STTx const& stx) {
1087 jvResult[jss::tx_blob] =
strHex(stx.getSerializer().slice());
1088 return env.rpc(
"json",
"submit",
to_string(jvResult));
1092 env.fund(
XRP(1000), alice);
1096 auto const baseFee = env.current()->fees().base;
1102 auto const info = submitSTTx(local);
1104 info[jss::result][jss::error_exception] ==
1105 "fails local checks: Empty SigningPubKey.");
1112 auto badSig = local.
getFieldVL(sfTxnSignature);
1116 auto const info = submitSTTx(local);
1118 info[jss::result][jss::error_exception] ==
1119 "fails local checks: Invalid signature.");
1129 auto const info = submitSTTx(local);
1131 info[jss::result][jss::error_exception] ==
1132 "fails local checks: Invalid signature.");
1138 local[sfSigningPubKey] = alice.pk();
1139 auto const info = submitSTTx(local);
1141 info[jss::result][jss::error_exception] ==
1142 "fails local checks: Cannot both single- and multi-sign.");
1148 local.
sign(alice.pk(), alice.sk());
1150 auto const info = submitSTTx(local);
1152 info[jss::result][jss::error_exception] ==
1153 "fails local checks: Cannot both single- and multi-sign.");
1161 auto badSig =
signer.getFieldVL(sfTxnSignature);
1163 signer.setFieldVL(sfTxnSignature, badSig);
1165 auto const info = submitSTTx(local);
1167 info[jss::result][jss::error_exception].asString().find(
1168 "Invalid signature on account r") != std::string::npos);
1175 auto const info = submitSTTx(local);
1177 info[jss::result][jss::error_exception] ==
1178 "fails local checks: Invalid Signers array size.");
1187 features[featureExpandedSignerList] ?
msig(
1232 auto const info = submitSTTx(local);
1234 info[jss::result][jss::error_exception] ==
1235 "fails local checks: Invalid Signers array size.");
1241 auto const info = submitSTTx(local);
1243 info[jss::result][jss::error_exception] ==
1244 "fails local checks: Invalid multisigner.");
1250 auto const info = submitSTTx(local);
1252 info[jss::result][jss::error_exception] ==
1253 "fails local checks: Duplicate Signers not allowed.");
1263 auto const info = submitSTTx(local);
1265 info[jss::result][jss::error_exception] ==
1266 "fails local checks: Unsorted Signers array.");
1275 using namespace jtx;
1276 Env env{*
this, features};
1279 env.fund(
XRP(1000), alice, becky);
1282 auto const baseFee = env.current()->fees().base;
1292 testcase(
"Multisigning multisigner");
1299 using namespace jtx;
1300 Env env{*
this, features};
1303 env.fund(
XRP(1000), alice, becky);
1307 env(
signers(alice, 1, {{becky, 1}}));
1316 auto const baseFee = env.current()->fees().base;
1375 using namespace jtx;
1381 cfg->loadFromString(
"[" SECTION_SIGNING_SUPPORT
"]\ntrue");
1393 auto const baseFee = env.
current()->fees().base;
1397 jvSig1[jss::tx_json][jss::Account] = alice.human();
1398 jvSig1[jss::tx_json][jss::Amount] = 10000000;
1399 jvSig1[jss::tx_json][jss::Destination] = env.
master.
human();
1400 jvSig1[jss::tx_json][jss::Fee] = (3 * baseFee).jsonClipped();
1401 jvSig1[jss::tx_json][jss::Sequence] = env.
seq(alice);
1402 jvSig1[jss::tx_json][jss::TransactionType] = jss::Payment;
1405 BEAST_EXPECT(jvSig2[jss::result][jss::status].asString() ==
"success");
1409 jvSig2[jss::result][jss::tx_json][jss::hash].
asString();
1412 jvSig2[jss::result][jss::account] =
ghost.
human();
1413 jvSig2[jss::result][jss::secret] =
ghost.
name();
1415 env.
rpc(
"json",
"sign_for",
to_string(jvSig2[jss::result]));
1417 jvSubmit[jss::result][jss::status].asString() ==
"success");
1421 jvSubmit[jss::result][jss::tx_json][jss::hash].
asString();
1422 BEAST_EXPECT(hash1 != hash2);
1426 "json",
"submit_multisigned",
to_string(jvSubmit[jss::result]));
1428 jvResult[jss::result][jss::status].asString() ==
"success");
1430 jvResult[jss::result][jss::engine_result].asString() ==
1436 hash2 == jvResult[jss::result][jss::tx_json][jss::hash].asString());
1442 BEAST_EXPECT(jvTx[jss::result][jss::status].asString() ==
"success");
1443 BEAST_EXPECT(jvTx[jss::result][jss::validated].asString() ==
"true");
1445 jvTx[jss::result][jss::meta][sfTransactionResult.jsonName]
1458 using namespace jtx;
1465 env.fund(
XRP(1000), alice, becky, cheri, daria);
1483 env.require(
owners(alice, 3));
1484 env.require(
owners(becky, 10));
1487 env.enableFeature(featureMultiSignReserve);
1505 env.require(
owners(alice, 3));
1506 env.require(
owners(becky, 10));
1507 env.require(
owners(cheri, 1));
1508 env.require(
owners(daria, 1));
1526 env.require(
owners(alice, 1));
1527 env.require(
owners(becky, 0));
1528 env.require(
owners(cheri, 1));
1529 env.require(
owners(daria, 1));
1538 env.require(
owners(alice, 0));
1539 env.require(
owners(becky, 0));
1540 env.require(
owners(cheri, 0));
1541 env.require(
owners(daria, 0));
1549 using namespace jtx;
1550 Env env{*
this, features};
1552 env.fund(
XRP(2000), alice);
1565 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1566 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1569 auto const baseFee = env.current()->fees().base;
1575 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1576 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1581 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1582 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1588 if (!features[featureExpandedSignerList])
1593 using namespace jtx;
1594 Env env{*
this, features};
1596 env.fund(
XRP(1000), alice);
1598 uint8_t tag1[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1599 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1600 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1601 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
1604 "hello world some ascii 32b long";
1612 env.require(
owners(alice, features[featureMultiSignReserve] ? 1 : 4));
1615 auto const baseFee = env.current()->fees().base;
1619 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1622 aliceSeq = env.seq(alice);
1625 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1627 aliceSeq = env.seq(alice);
1630 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1633 aliceSeq = env.seq(alice);
1637 rpc(
"invalidTransaction",
1638 "fails local checks: Duplicate Signers not allowed."));
1640 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1643 aliceSeq = env.seq(alice);
1649 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1653 aliceSeq = env.seq(alice);
1656 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1659 aliceSeq = env.seq(alice);
1662 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1668 using namespace test::jtx;
1670 Env env{*
this, features};
1673 env.fund(
XRP(1000), alice);
1676 bool const enabled = features[fixInvalidTxFlags];
1679 (enabled ?
"enabled" :
"disabled"));
1694 using namespace jtx;
1695 Env env{*
this, features};
1697 env.fund(
XRP(1000), alice);
1707 BEAST_EXPECT(sle->getFieldArray(sfSignerEntries).size() == 2);
1708 if (features[fixIncludeKeyletFields])
1710 BEAST_EXPECT((*sle)[sfOwner] == alice.id());
1714 BEAST_EXPECT(!sle->isFieldPresent(sfOwner));
1744 using namespace jtx;
1751 testAll(
all - featureMultiSignReserve - featureExpandedSignerList);
1765BEAST_DEFINE_TESTSUITE(MultiSign, app,
ripple);
const_iterator begin() const
const_iterator end() const
std::string asString() const
Returns the unquoted string value.
testcase_t testcase
Memberspace for declaring test cases.
Blob getFieldVL(SField const &field) const
std::uint32_t getFieldU32(SField const &field) const
void setFieldU32(SField const &field, std::uint32_t)
STArray & peekFieldArray(SField const &field)
void setFieldVL(SField const &field, Blob const &)
void sign(PublicKey const &publicKey, SecretKey const &secretKey, std::optional< std::reference_wrapper< SField const > > signatureTarget={})
static base_uint fromVoid(void const *data)
void testSignersWithTickets(FeatureBitset features)
void testSignersWithTags(FeatureBitset features)
void testAmendmentTransition()
void testSignForHash(FeatureBitset features)
void run() override
Runs the suite.
void testPhantomSigners(FeatureBitset features)
void testHeterogeneousSigners(FeatureBitset features)
void testMisorderedSigners(FeatureBitset features)
void testSignerListObject(FeatureBitset features)
void testAll(FeatureBitset features)
void testMasterSigners(FeatureBitset features)
void testKeyDisable(FeatureBitset features)
void testRegularSignersUsingSubmitMulti(FeatureBitset features)
void testBadSignatureText(FeatureBitset features)
void testSignerListSetFlags(FeatureBitset features)
void testFee(FeatureBitset features)
void testMultisigningMultisigner(FeatureBitset features)
void testSignerListSet(FeatureBitset features)
void testNoMultiSigners(FeatureBitset features)
void testNoReserve(FeatureBitset features)
void testRegularSigners(FeatureBitset features)
void testRegKey(FeatureBitset features)
void testTxTypes(FeatureBitset features)
Immutable cryptographic account descriptor.
std::string const & name() const
Return the name.
std::string const & human() const
Returns the human readable public key.
A transaction testing environment.
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Set a multisignature on a JTx.
Match the number of items in the account's owner directory.
Check a set of conditions.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Set the regular signature on a JTx.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Set a ticket sequence on a JTx.
@ arrayValue
array value (ordered list)
Keylet signers(AccountID const &account) noexcept
A SignerList.
Json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
owner_count< ltRIPPLE_STATE > lines
Match the number of trust lines in the account's owner directory.
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Json::Value regkey(Account const &account, disabled_t)
Disable the regular key.
Json::Value signers(Account const &account, std::uint32_t quorum, std::vector< signer > const &v)
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
FeatureBitset testable_amendments()
static disabled_t const disabled
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
owner_count< ltTICKET > tickets
Match the number of tickets on the account.
XRP_t const XRP
Converts to XRP Issue or STAmount.
Json::Value offer_cancel(Account const &account, std::uint32_t offerSeq)
Cancel an offer.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr std::uint32_t tfPassive
constexpr std::uint32_t asfDisableMaster
std::string strHex(FwdIt begin, FwdIt end)
@ tecINSUFFICIENT_RESERVE
std::vector< unsigned char > Blob
Storage for linear binary data.
std::string to_string(base_uint< Bits, Tag > const &a)
TERSubset< CanCvtToTER > TER
Execution context for applying a JSON transaction.
std::shared_ptr< STTx const > stx
Set the sequence number on a JTx.
A signer in a SignerList.