3#include <xrpld/core/ConfigSections.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/jss.h>
54 Env env{*
this, features};
59 auto const fee = env.current()->fees().base;
60 env.fund(
XRP(250) -
drops(1), alice);
62 env.require(
owners(alice, 0));
69 env.require(
owners(alice, 0));
76 env.require(
owners(alice, 1));
97 env.require(
owners(alice, 1));
104 env.require(
owners(alice, 1));
109 env.require(
owners(alice, 0));
118 Env env{*
this, features};
120 env.fund(
XRP(1000), alice);
172 {
bogie, 1}, {
demon, 1}, {
ghost, 1}, {
haunt, 1}, {
jinni, 1}, {
phase, 1},
173 {
shade, 1}, {
spook, 1}, {spare, 1}, {
acc10, 1}, {
acc11, 1}, {
acc12, 1},
174 {
acc13, 1}, {
acc14, 1}, {
acc15, 1}, {
acc16, 1}, {
acc17, 1}, {
acc18, 1},
175 {
acc19, 1}, {
acc20, 1}, {
acc21, 1}, {
acc22, 1}, {
acc23, 1}, {
acc24, 1},
176 {
acc25, 1}, {
acc26, 1}, {
acc27, 1}, {
acc28, 1}, {
acc29, 1}, {
acc30, 1},
181 env.require(
owners(alice, 0));
190 Env env{*
this, features};
192 env.fund(
XRP(1000), alice);
198 env.require(
owners(alice, 1));
201 auto const baseFee = env.current()->fees().base;
205 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
208 aliceSeq = env.seq(alice);
211 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
213 aliceSeq = env.seq(alice);
216 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
219 aliceSeq = env.seq(alice);
223 rpc(
"invalidTransaction",
"fails local checks: Duplicate Signers not allowed."));
225 BEAST_EXPECT(env.seq(alice) == aliceSeq);
228 aliceSeq = env.seq(alice);
231 BEAST_EXPECT(env.seq(alice) == aliceSeq);
235 aliceSeq = env.seq(alice);
238 BEAST_EXPECT(env.seq(alice) == aliceSeq);
241 aliceSeq = env.seq(alice);
244 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
253 Env env{*
this, features};
255 env.fund(
XRP(1000), alice);
271 env.require(
owners(alice, 1));
274 auto const baseFee = env.current()->fees().base;
279 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
282 aliceSeq = env.seq(alice);
286 BEAST_EXPECT(env.seq(alice) == aliceSeq);
289 aliceSeq = env.seq(alice);
295 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
298 aliceSeq = env.seq(alice);
301 fee((9 * baseFee) - 1),
305 BEAST_EXPECT(env.seq(alice) == aliceSeq);
314 Env env{*
this, features};
316 env.fund(
XRP(1000), alice);
323 env.require(
owners(alice, 1));
326 std::reverse(phantoms.signers.begin(), phantoms.signers.end());
330 rpc(
"invalidTransaction",
"fails local checks: Unsorted Signers array."));
332 BEAST_EXPECT(env.seq(alice) == aliceSeq);
341 Env env{*
this, features};
345 env.fund(
XRP(1000), alice, becky, cheri);
356 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
359 env(
signers(alice, 4, {{becky, 3}, {cheri, 4}}),
sig(alice));
361 env.require(
owners(alice, 1));
364 auto const baseFee = env.current()->fees().base;
365 aliceSeq = env.seq(alice);
368 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
371 aliceSeq = env.seq(alice);
374 BEAST_EXPECT(env.seq(alice) == aliceSeq);
384 aliceSeq = env.seq(alice);
385 env(
noop(alice),
msig(becky, cheri),
fee(3 * baseFee));
387 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
396 Env env{*
this, features};
400 env.fund(
XRP(1000), alice, becky, cheri);
404 env(
signers(alice, 1, {{becky, 1}, {cheri, 1}}),
sig(alice));
416 env(
fset(cheri, asfDisableMaster),
sig(cheri));
420 auto const baseFee = env.current()->fees().base;
424 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
427 aliceSeq = env.seq(alice);
430 BEAST_EXPECT(env.seq(alice) == aliceSeq);
433 aliceSeq = env.seq(alice);
436 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
438 aliceSeq = env.seq(alice);
441 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
444 aliceSeq = env.seq(alice);
447 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
453 testcase(
"Regular Signers Using submit_multisigned");
459 cfg->loadFromString(
"[" SECTION_SIGNING_SUPPORT
"]\ntrue");
466 env.
fund(
XRP(1000), alice, becky, cheri);
470 env(
signers(alice, 2, {{becky, 1}, {cheri, 1}}),
sig(alice));
480 env(
fset(cheri, asfDisableMaster),
sig(cheri));
483 auto const baseFee = env.
current()->fees().base;
489 jv[jss::tx_json][jss::Account] = alice.human();
490 jv[jss::tx_json][jss::TransactionType] = jss::AccountSet;
491 jv[jss::tx_json][jss::Fee] = (8 * baseFee).jsonClipped();
492 jv[jss::tx_json][jss::Sequence] = env.
seq(alice);
493 jv[jss::tx_json][jss::SigningPubKey] =
"";
497 jv[jss::account] = cheri.human();
498 jv[jss::key_type] =
"ed25519";
499 jv[jss::passphrase] = cher.name();
502 jv[jss::account] = becky.human();
503 jv[jss::secret] = beck.name();
509 aliceSeq = env.
seq(alice);
512 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
513 BEAST_EXPECT(jrr[jss::status] ==
"success");
518 jv_two[jss::tx_json] = jrr[jss::tx_json];
520 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_two))[jss::result];
521 BEAST_EXPECT(jrr[jss::status] ==
"success");
524 jv_submit[jss::tx_json] = jrr[jss::tx_json];
525 jrr = env.
rpc(
"json",
"submit_multisigned",
to_string(jv_submit))[jss::result];
526 BEAST_EXPECT(jrr[jss::status] ==
"success");
528 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
533 aliceSeq = env.
seq(alice);
535 jv_one[jss::tx_json][jss::SigningPubKey] =
strHex(alice.pk().slice());
537 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
538 BEAST_EXPECT(jrr[jss::status] ==
"error");
539 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
541 jrr[jss::error_message] ==
542 "When multi-signing 'tx_json.SigningPubKey' must be empty.");
547 aliceSeq = env.
seq(alice);
549 jv_one[jss::tx_json][jss::Fee] = -1;
551 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
552 BEAST_EXPECT(jrr[jss::status] ==
"success");
557 jv_two[jss::tx_json] = jrr[jss::tx_json];
559 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_two))[jss::result];
560 BEAST_EXPECT(jrr[jss::status] ==
"success");
563 jv_submit[jss::tx_json] = jrr[jss::tx_json];
564 jrr = env.
rpc(
"json",
"submit_multisigned",
to_string(jv_submit))[jss::result];
565 BEAST_EXPECT(jrr[jss::status] ==
"error");
566 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
568 jrr[jss::error_message] ==
"Invalid Fee field. Fees must be greater than zero.");
573 aliceSeq = env.
seq(alice);
575 jv_one[jss::tx_json][jss::Fee] = alice[
"USD"](10).value().getFullText();
577 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
578 BEAST_EXPECT(jrr[jss::status] ==
"success");
583 jv_two[jss::tx_json] = jrr[jss::tx_json];
585 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_two))[jss::result];
586 BEAST_EXPECT(jrr[jss::status] ==
"success");
589 jv_submit[jss::tx_json] = jrr[jss::tx_json];
590 jrr = env.
rpc(
"json",
"submit_multisigned",
to_string(jv_submit))[jss::result];
591 BEAST_EXPECT(jrr[jss::status] ==
"error");
592 BEAST_EXPECT(jrr[jss::error] ==
"internal");
593 BEAST_EXPECT(jrr[jss::error_message] ==
"Internal error.");
598 aliceSeq = env.
seq(alice);
600 jv[jss::account] = cheri.human();
601 jv[jss::secret] = cheri.name();
602 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv))[jss::result];
603 BEAST_EXPECT(jrr[jss::status] ==
"error");
604 BEAST_EXPECT(jrr[jss::error] ==
"masterDisabled");
606 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
612 aliceSeq = env.
seq(alice);
615 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_one))[jss::result];
616 BEAST_EXPECT(jrr[jss::status] ==
"success");
621 jv_two[jss::tx_json] = jrr[jss::tx_json];
622 jv_two[jss::account] = becky.human();
623 jv_two[jss::key_type] =
"ed25519";
624 jv_two[jss::passphrase] = becky.name();
625 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv_two))[jss::result];
626 BEAST_EXPECT(jrr[jss::status] ==
"success");
629 jv_submit[jss::tx_json] = jrr[jss::tx_json];
630 jrr = env.
rpc(
"json",
"submit_multisigned",
to_string(jv_submit))[jss::result];
631 BEAST_EXPECT(jrr[jss::status] ==
"success");
633 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
639 jv[jss::tx_json][jss::Account] =
"DEADBEEF";
641 auto jrr = env.
rpc(
"json",
"sign_for",
to_string(jv))[jss::result];
642 BEAST_EXPECT(jrr[jss::status] ==
"error");
643 BEAST_EXPECT(jrr[jss::error] ==
"srcActMalformed");
646 jv[jss::tx_json][jss::Account] = jimmy.human();
647 jrr = env.
rpc(
"json",
"sign_for",
to_string(jv))[jss::result];
648 BEAST_EXPECT(jrr[jss::status] ==
"error");
649 BEAST_EXPECT(jrr[jss::error] ==
"srcActNotFound");
653 aliceSeq = env.
seq(alice);
657 auto jrr = env.
rpc(
"json",
"submit_multisigned",
to_string(jv))[jss::result];
658 BEAST_EXPECT(jrr[jss::status] ==
"error");
659 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
660 BEAST_EXPECT(jrr[jss::error_message] ==
"tx_json.Signers array may not be empty.");
662 BEAST_EXPECT(env.
seq(alice) == aliceSeq);
672 Env env{*
this, features};
677 env.fund(
XRP(1000), alice, becky, cheri, daria);
683 env(
fset(alice, asfDisableMaster),
sig(alice));
694 env(
fset(daria, asfDisableMaster),
sig(daria));
698 env(
signers(alice, 1, {{becky, 1}, {cheri, 1}, {daria, 1}, {
jinni, 1}}),
sig(alie));
700 env.require(
owners(alice, 1));
703 auto const baseFee = env.current()->fees().base;
707 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
709 aliceSeq = env.seq(alice);
712 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
714 aliceSeq = env.seq(alice);
717 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
719 aliceSeq = env.seq(alice);
722 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
724 aliceSeq = env.seq(alice);
727 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
730 aliceSeq = env.seq(alice);
733 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
739 {{becky, 0xFFFF}, {cheri, 0xFFFF}, {daria, 0xFFFF}, {
jinni, 0xFFFF}}),
742 env.require(
owners(alice, 1));
744 aliceSeq = env.seq(alice);
747 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
750 aliceSeq = env.seq(alice);
753 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
769 env.require(
owners(alice, 1));
771 aliceSeq = env.seq(alice);
776 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
779 aliceSeq = env.seq(alice);
785 BEAST_EXPECT(env.seq(alice) == aliceSeq);
790 env.require(
owners(alice, 0));
801 Env env{*
this, features};
803 env.fund(
XRP(1000), alice);
830 env(
fset(alice, asfDisableMaster),
sig(alice));
842 auto const baseFee = env.current()->fees().base;
855 env(
fset(alice, asfDisableMaster),
sig(alice));
864 env(
fclear(alice, asfDisableMaster),
sig(alie));
878 Env env{*
this, features};
880 env.fund(
XRP(1000), alice);
897 env.fund(
XRP(1000), becky);
900 env(
signers(becky, 1, {{alice, 1}}),
sig(becky));
915 Env env{*
this, features};
920 auto const USD = gw[
"USD"];
921 env.fund(
XRP(1000), alice, becky, zelda, gw);
927 env(
fset(alice, asfDisableMaster),
sig(alice));
932 env.require(
owners(alice, 1));
935 auto const baseFee = env.current()->fees().base;
939 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
942 aliceSeq = env.seq(alice);
945 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
948 aliceSeq = env.seq(alice);
952 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
955 env(
trust(
"alice", USD(100)),
960 env.require(
owners(alice, 2));
963 env(
pay(gw, alice, USD(50)));
965 env.require(
balance(alice, USD(50)));
966 env.require(
balance(gw, alice[
"USD"](-50)));
971 env.require(
owners(alice, 3));
975 aliceSeq = env.seq(alice);
978 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
979 env.require(
owners(alice, 2));
987 env.require(
owners(alice, 2));
998 Env env{*
this, features};
1001 auto submitSTTx = [&env](
STTx const& stx) {
1003 jvResult[jss::tx_blob] =
strHex(stx.getSerializer().slice());
1004 return env.rpc(
"json",
"submit",
to_string(jvResult));
1008 env.fund(
XRP(1000), alice);
1012 auto const baseFee = env.current()->fees().base;
1015 JTx const tx = env.jt(
noop(alice),
sig(alice));
1018 auto const info = submitSTTx(local);
1020 info[jss::result][jss::error_exception] ==
1021 "fails local checks: Empty SigningPubKey.");
1025 JTx const tx = env.jt(
noop(alice),
sig(alice));
1028 auto badSig = local.
getFieldVL(sfTxnSignature);
1032 auto const info = submitSTTx(local);
1034 info[jss::result][jss::error_exception] ==
1035 "fails local checks: Invalid signature.");
1039 JTx const tx = env.jt(
noop(alice),
sig(alice));
1045 auto const info = submitSTTx(local);
1047 info[jss::result][jss::error_exception] ==
1048 "fails local checks: Invalid signature.");
1054 local[sfSigningPubKey] = alice.pk();
1055 auto const info = submitSTTx(local);
1057 info[jss::result][jss::error_exception] ==
1058 "fails local checks: Cannot both single- and multi-sign.");
1064 local.
sign(alice.pk(), alice.sk());
1066 auto const info = submitSTTx(local);
1068 info[jss::result][jss::error_exception] ==
1069 "fails local checks: Cannot both single- and multi-sign.");
1077 auto badSig =
signer.getFieldVL(sfTxnSignature);
1079 signer.setFieldVL(sfTxnSignature, badSig);
1081 auto const info = submitSTTx(local);
1083 info[jss::result][jss::error_exception].asString().find(
1084 "Invalid signature on account r") != std::string::npos);
1091 auto const info = submitSTTx(local);
1093 info[jss::result][jss::error_exception] ==
1094 "fails local checks: Invalid Signers array size.");
1097 JTx const tx = env.jt(
1136 auto const info = submitSTTx(local);
1138 info[jss::result][jss::error_exception] ==
1139 "fails local checks: Invalid Signers array size.");
1143 JTx const tx = env.jt(
noop(alice),
fee(2 * baseFee),
msig(alice));
1145 auto const info = submitSTTx(local);
1147 info[jss::result][jss::error_exception] ==
1148 "fails local checks: Invalid multisigner.");
1154 auto const info = submitSTTx(local);
1156 info[jss::result][jss::error_exception] ==
1157 "fails local checks: Duplicate Signers not allowed.");
1167 auto const info = submitSTTx(local);
1169 info[jss::result][jss::error_exception] ==
1170 "fails local checks: Unsorted Signers array.");
1179 using namespace jtx;
1180 Env env{*
this, features};
1183 env.fund(
XRP(1000), alice, becky);
1186 auto const baseFee = env.current()->fees().base;
1193 testcase(
"Multisigning multisigner");
1200 using namespace jtx;
1201 Env env{*
this, features};
1204 env.fund(
XRP(1000), alice, becky);
1208 env(
signers(alice, 1, {{becky, 1}}));
1217 auto const baseFee = env.current()->fees().base;
1222 env(
fset(becky, asfDisableMaster));
1264 using namespace jtx;
1270 cfg->loadFromString(
"[" SECTION_SIGNING_SUPPORT
"]\ntrue");
1282 auto const baseFee = env.
current()->fees().base;
1286 jvSig1[jss::tx_json][jss::Account] = alice.human();
1287 jvSig1[jss::tx_json][jss::Amount] = 10000000;
1288 jvSig1[jss::tx_json][jss::Destination] = env.
master.
human();
1289 jvSig1[jss::tx_json][jss::Fee] = (3 * baseFee).jsonClipped();
1290 jvSig1[jss::tx_json][jss::Sequence] = env.
seq(alice);
1291 jvSig1[jss::tx_json][jss::TransactionType] = jss::Payment;
1294 BEAST_EXPECT(jvSig2[jss::result][jss::status].asString() ==
"success");
1300 jvSig2[jss::result][jss::account] =
ghost.
human();
1301 jvSig2[jss::result][jss::secret] =
ghost.
name();
1303 BEAST_EXPECT(jvSubmit[jss::result][jss::status].asString() ==
"success");
1307 BEAST_EXPECT(hash1 != hash2);
1311 env.
rpc(
"json",
"submit_multisigned",
to_string(jvSubmit[jss::result]));
1312 BEAST_EXPECT(jvResult[jss::result][jss::status].asString() ==
"success");
1313 BEAST_EXPECT(jvResult[jss::result][jss::engine_result].asString() ==
"tesSUCCESS");
1317 BEAST_EXPECT(hash2 == jvResult[jss::result][jss::tx_json][jss::hash].asString());
1323 BEAST_EXPECT(jvTx[jss::result][jss::status].asString() ==
"success");
1324 BEAST_EXPECT(jvTx[jss::result][jss::validated].asString() ==
"true");
1326 jvTx[jss::result][jss::meta][sfTransactionResult.jsonName].
asString() ==
"tesSUCCESS");
1334 using namespace jtx;
1335 Env env{*
this, features};
1337 env.fund(
XRP(2000), alice);
1349 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1350 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1353 auto const baseFee = env.current()->fees().base;
1356 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1357 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1362 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1363 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1371 using namespace jtx;
1372 Env env{*
this, features};
1374 env.fund(
XRP(1000), alice);
1376 uint8_t tag1[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03,
1377 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
1378 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
1380 uint8_t tag2[] =
"hello world some ascii 32b long";
1388 env.require(
owners(alice, 1));
1391 auto const baseFee = env.current()->fees().base;
1395 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1398 aliceSeq = env.seq(alice);
1401 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1403 aliceSeq = env.seq(alice);
1406 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1409 aliceSeq = env.seq(alice);
1413 rpc(
"invalidTransaction",
"fails local checks: Duplicate Signers not allowed."));
1415 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1418 aliceSeq = env.seq(alice);
1421 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1425 aliceSeq = env.seq(alice);
1428 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1431 aliceSeq = env.seq(alice);
1434 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
1440 using namespace test::jtx;
1442 Env env{*
this, features};
1445 env.fund(
XRP(1000), alice);
1448 bool const enabled = features[fixInvalidTxFlags];
1462 using namespace jtx;
1463 Env env{*
this, features};
1465 env.fund(
XRP(1000), alice);
1475 BEAST_EXPECT(sle->getFieldArray(sfSignerEntries).size() == 2);
1476 if (features[fixIncludeKeyletFields])
1478 BEAST_EXPECT((*sle)[sfOwner] == alice.id());
1482 BEAST_EXPECT(!sle->isFieldPresent(sfOwner));
1512 using namespace jtx;
1525BEAST_DEFINE_TESTSUITE(MultiSign, app,
xrpl);
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 setFieldVL(SField const &field, Blob const &)
void setFieldU32(SField const &field, std::uint32_t)
STArray & peekFieldArray(SField const &field)
void sign(PublicKey const &publicKey, SecretKey const &secretKey, std::optional< std::reference_wrapper< SField const > > signatureTarget={})
static base_uint fromVoid(void const *data)
void testMultisigningMultisigner(FeatureBitset features)
void testRegKey(FeatureBitset features)
void testAll(FeatureBitset features)
void testPhantomSigners(FeatureBitset features)
void testBadSignatureText(FeatureBitset features)
void testSignForHash(FeatureBitset features)
void testTxTypes(FeatureBitset features)
void testRegularSigners(FeatureBitset features)
void testKeyDisable(FeatureBitset features)
void testMisorderedSigners(FeatureBitset features)
void testSignersWithTags(FeatureBitset features)
void testSignerListSet(FeatureBitset features)
void testSignerListSetFlags(FeatureBitset features)
void testRegularSignersUsingSubmitMulti(FeatureBitset features)
void testSignerListObject(FeatureBitset features)
void testHeterogeneousSigners(FeatureBitset features)
void testMasterSigners(FeatureBitset features)
void testFee(FeatureBitset features)
void run() override
Runs the suite.
void testNoMultiSigners(FeatureBitset features)
void testNoReserve(FeatureBitset features)
void testSignersWithTickets(FeatureBitset features)
Immutable cryptographic account descriptor.
std::string const & human() const
Returns the human readable public key.
std::string const & name() const
Return the name.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
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.
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Json::Value signers(Account const &account, std::uint32_t quorum, std::vector< signer > const &v)
XRP_t const XRP
Converts to XRP Issue or STAmount.
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Json::Value offer_cancel(Account const &account, std::uint32_t offerSeq)
Cancel an offer.
FeatureBitset testable_amendments()
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Json::Value regkey(Account const &account, disabled_t)
Disable the regular key.
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
owner_count< ltTICKET > tickets
Match the number of tickets on the account.
owner_count< ltRIPPLE_STATE > lines
Match the number of trust lines in the account's owner directory.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
static disabled_t const disabled
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::string to_string(base_uint< Bits, Tag > const &a)
std::string strHex(FwdIt begin, FwdIt end)
TERSubset< CanCvtToTER > TER
std::vector< unsigned char > Blob
Storage for linear binary data.
@ tecINSUFFICIENT_RESERVE
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.