21#include <test/jtx/TestHelpers.h>
22#include <test/jtx/utility.h>
24#include <xrpld/app/misc/HashRouter.h>
25#include <xrpld/app/misc/Transaction.h>
26#include <xrpld/app/tx/apply.h>
28#include <xrpl/protocol/Batch.h>
29#include <xrpl/protocol/Feature.h>
30#include <xrpl/protocol/STParsedJSON.h>
31#include <xrpl/protocol/Sign.h>
32#include <xrpl/protocol/TxFlags.h>
33#include <xrpl/protocol/jss.h>
58 for (
auto const& txn : jrr[jss::result][jss::ledger][jss::transactions])
60 if (txn[jss::metaData][sfTransactionIndex.jsonName] == index)
70 params[jss::ledger_index] = env.
closed()->seq();
71 params[jss::transactions] =
true;
72 params[jss::expand] =
true;
83 BEAST_EXPECT(jrr[sfTransactionType.jsonName] == ledgerResult.
txType);
85 jrr[jss::meta][sfTransactionResult.jsonName] ==
87 BEAST_EXPECT(jrr[jss::meta][sfParentBatchID.jsonName] == batchID);
96 auto const transactions =
97 jrr[jss::result][jss::ledger][jss::transactions];
98 BEAST_EXPECT(transactions.size() == ledgerResults.
size());
102 BEAST_EXPECT(txn[jss::hash].asString() == ledgerResult.txHash);
103 BEAST_EXPECT(txn.isMember(jss::metaData));
106 txn[sfTransactionType.jsonName] == ledgerResult.txType);
108 meta[sfTransactionResult.jsonName] == ledgerResult.result);
109 if (ledgerResult.batchID)
114 template <
typename... Args>
118 auto batchTxn = env.
jt(std::forward<Args>(args)...);
121 auto const ids = batchTxn.stx->getBatchTransactionIDs();
123 for (
auto const&
id : ids)
125 TxID const batchID = batchTxn.stx->getTransactionID();
141 auto& section = p->section(
"transaction_queue");
142 section.set(
"ledgers_in_queue",
"2");
143 section.set(
"minimum_queue_size",
"2");
144 section.set(
"min_ledgers_to_compute_size_limit",
"3");
145 section.set(
"max_ledger_counts_to_store",
"100");
146 section.set(
"retry_sequence_percent",
"25");
147 section.set(
"normal_consensus_increase_percent",
"0");
149 for (
auto const& [k, v] : extraTxQ)
160 auto const& view = *env.
current();
162 return toDrops(metrics.openLedgerFeeLevel, batchFee) + 1;
170 using namespace test::jtx;
173 for (
bool const withBatch : {
true,
false})
175 auto const amend = withBatch ? features : features - featureBatch;
178 auto const alice =
Account(
"alice");
179 auto const bob =
Account(
"bob");
180 auto const carol =
Account(
"carol");
181 env.fund(
XRP(10000), alice, bob, carol);
186 auto const seq = env.
seq(alice);
188 auto const txResult =
202 auto const txResult =
204 env(
pay(alice, bob,
XRP(1)),
219 using namespace test::jtx;
227 auto const alice =
Account(
"alice");
228 auto const bob =
Account(
"bob");
229 auto const carol =
Account(
"carol");
230 env.fund(
XRP(10000), alice, bob, carol);
243 auto const seq = env.
seq(alice);
252 auto const seq = env.
seq(alice);
261 auto const seq = env.
seq(alice);
271 auto const seq = env.
seq(alice);
280 auto const seq = env.
seq(alice);
291 auto const seq = env.
seq(alice);
310 auto const seq = env.
seq(alice);
311 auto jt = env.jtnofill(
322 auto const seq = env.
seq(alice);
336 auto const seq = env.
seq(alice);
339 auto jt = env.jtnofill(
350 auto const seq = env.
seq(alice);
352 auto jt = env.jt(
pay(alice, bob,
XRP(1)));
362 auto const seq = env.
seq(alice);
364 auto tx1 =
pay(alice, bob,
XRP(1));
367 tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfAccount.jsonName] =
369 tx1[sfSigners.jsonName][0U][sfSigner.jsonName]
370 [sfSigningPubKey.jsonName] =
strHex(alice.pk());
371 tx1[sfSigners.jsonName][0U][sfSigner.jsonName]
372 [sfTxnSignature.jsonName] =
"DEADBEEF";
383 auto const seq = env.
seq(alice);
386 tx1[jss::SigningPubKey] =
strHex(alice.pk());
387 auto jt = env.jtnofill(
398 auto const seq = env.
seq(alice);
410 auto const seq = env.
seq(alice);
413 tx1[jss::Fee] =
to_string(env.current()->fees().base);
424 auto const seq = env.
seq(alice);
427 tx1[jss::Sequence] =
seq + 1;
438 auto const seq = env.
seq(alice);
449 auto const seq = env.
seq(alice);
460 auto const seq = env.
seq(alice);
471 auto const seq = env.
seq(alice);
484 auto const seq = env.
seq(alice);
506 auto const seq = env.
seq(alice);
518 auto const seq = env.
seq(alice);
531 auto const seq = env.
seq(alice);
543 auto const seq = env.
seq(alice);
555 auto const seq = env.
seq(alice);
556 auto const bobSeq = env.seq(bob);
558 auto jt = env.jtnofill(
567 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
568 [sfAccount.jsonName] = bob.human();
569 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
570 [sfSigningPubKey.jsonName] =
strHex(alice.pk());
571 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
572 [sfTxnSignature.jsonName] =
581 auto const seq = env.
seq(alice);
598 using namespace test::jtx;
606 auto const alice =
Account(
"alice");
607 auto const bob =
Account(
"bob");
608 auto const carol =
Account(
"carol");
609 auto const dave =
Account(
"dave");
610 auto const elsa =
Account(
"elsa");
611 auto const frank =
Account(
"frank");
612 auto const phantom =
Account(
"phantom");
613 env.memoize(phantom);
615 env.fund(
XRP(10000), alice, bob, carol, dave, elsa, frank);
623 auto const seq = env.
seq(alice);
638 auto const seq = env.
seq(alice);
648 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
651 env(
signers(bob, 2, {{carol, 1}, {dave, 1}, {elsa, 1}}));
656 auto const seq = env.
seq(alice);
668 auto const seq = env.
seq(alice);
673 batch::msig(bob, {carol, Account(
"dave", KeyType::ed25519)}),
682 auto const seq = env.
seq(alice);
694 auto const seq = env.
seq(alice);
706 auto const seq = env.
seq(alice);
720 auto const seq = env.
seq(alice);
724 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
725 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
726 batch::msig(bob, {carol, Reg{dave, davo}}),
733 auto const seq = env.seq(alice);
736 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
737 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
738 batch::msig(bob, {carol}),
745 auto const seq = env.seq(alice);
748 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
749 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
750 batch::msig(bob, {carol, dave}),
757 auto const seq = env.seq(alice);
760 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
761 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
762 batch::msig(bob, {carol, dave}),
773 auto const ledSeq = env.current()->seq();
774 auto const seq = env.seq(alice);
777 batch::inner(
pay(alice, phantom,
XRP(1000)), seq + 1),
778 batch::inner(
noop(phantom), ledSeq),
779 batch::sig(Reg{phantom, carol}),
786 auto const ledSeq = env.current()->seq();
787 auto const seq = env.seq(alice);
790 batch::inner(
pay(alice, bob,
XRP(1000)), seq + 1),
791 batch::inner(
noop(bob), ledSeq),
792 batch::sig(Reg{bob, carol}),
800 auto const seq = env.seq(alice);
803 batch::inner(
pay(alice, bob,
XRP(1)), seq + 1),
804 batch::inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
805 batch::sig(Reg{bob, carol}),
812 auto const seq = env.seq(alice);
815 batch::inner(
pay(alice, bob,
XRP(1)), seq + 1),
816 batch::inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
826 auto const seq = env.seq(alice);
829 batch::inner(
pay(alice, bob,
XRP(1)), seq + 1),
830 batch::inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
840 testcase(
"bad raw txn");
842 using namespace test::jtx;
847 auto const alice =
Account(
"alice");
848 auto const bob =
Account(
"bob");
850 env.fund(
XRP(10000), alice, bob);
854 auto const batchFee = batch::calcBatchFee(env, 1, 2);
855 auto const seq = env.
seq(alice);
857 tx1.removeMember(jss::TransactionType);
858 auto jt = env.jtnofill(
869 auto const batchFee = batch::calcBatchFee(env, 1, 2);
870 auto const seq = env.
seq(alice);
872 tx1.removeMember(jss::Account);
873 auto jt = env.jtnofill(
884 auto const batchFee = batch::calcBatchFee(env, 1, 2);
885 auto const seq = env.
seq(alice);
887 tx1.removeMember(jss::Sequence);
888 auto jt = env.jtnofill(
899 auto const batchFee = batch::calcBatchFee(env, 1, 2);
900 auto const seq = env.
seq(alice);
902 tx1.removeMember(jss::Fee);
903 auto jt = env.jtnofill(
914 auto const batchFee = batch::calcBatchFee(env, 1, 2);
915 auto const seq = env.
seq(alice);
917 tx1.removeMember(jss::SigningPubKey);
918 auto jt = env.jtnofill(
931 testcase(
"bad sequence");
933 using namespace test::jtx;
938 auto const alice =
Account(
"alice");
939 auto const bob =
Account(
"bob");
941 auto const USD = gw[
"USD"];
943 env.fund(
XRP(10000), alice, bob, gw);
945 env.trust(USD(1000), alice, bob);
946 env(pay(gw, alice, USD(100)));
947 env(pay(gw, bob, USD(100)));
955 auto const preAliceSeq = env.seq(alice);
956 auto const preAlice = env.balance(alice);
957 auto const preAliceUSD = env.balance(alice, USD.issue());
958 auto const preBobSeq = env.seq(bob);
959 auto const preBob = env.balance(bob);
960 auto const preBobUSD = env.balance(bob, USD.issue());
962 auto const batchFee = batch::calcBatchFee(env, 1, 2);
963 auto const [txIDs, batchID] = submitBatch(
974 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
976 validateClosedLedger(env, testCases);
983 validateClosedLedger(env, testCases);
987 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
988 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
989 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
990 BEAST_EXPECT(env.seq(bob) == preBobSeq);
991 BEAST_EXPECT(env.balance(bob) == preBob);
992 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
997 auto const preAliceSeq = env.seq(alice);
998 auto const preAlice = env.balance(alice);
999 auto const preAliceUSD = env.balance(alice, USD.issue());
1000 auto const preBobSeq = env.seq(bob);
1001 auto const preBob = env.balance(bob);
1002 auto const preBobUSD = env.balance(bob, USD.issue());
1004 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1005 auto const [txIDs, batchID] = submitBatch(
1016 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1018 validateClosedLedger(env, testCases);
1025 validateClosedLedger(env, testCases);
1029 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1030 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1031 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1032 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1033 BEAST_EXPECT(env.balance(bob) == preBob);
1034 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1039 auto const preAliceSeq = env.seq(alice);
1040 auto const preAlice = env.balance(alice);
1041 auto const preAliceUSD = env.balance(alice, USD.issue());
1042 auto const preBobSeq = env.seq(bob);
1043 auto const preBob = env.balance(bob);
1044 auto const preBobUSD = env.balance(bob, USD.issue());
1046 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1047 auto const [txIDs, batchID] = submitBatch(
1058 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1060 validateClosedLedger(env, testCases);
1067 validateClosedLedger(env, testCases);
1071 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1072 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1073 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1074 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1075 BEAST_EXPECT(env.balance(bob) == preBob);
1076 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1081 auto const preAliceSeq = env.seq(alice);
1082 auto const preAlice = env.balance(alice);
1083 auto const preAliceUSD = env.balance(alice, USD.issue());
1084 auto const preBobSeq = env.seq(bob);
1085 auto const preBob = env.balance(bob);
1086 auto const preBobUSD = env.balance(bob, USD.issue());
1088 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1089 auto const [txIDs, batchID] = submitBatch(
1100 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1102 validateClosedLedger(env, testCases);
1109 validateClosedLedger(env, testCases);
1113 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1114 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1115 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1116 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1117 BEAST_EXPECT(env.balance(bob) == preBob);
1118 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1123 auto const preAliceSeq = env.seq(alice);
1124 auto const preAlice = env.balance(alice);
1125 auto const preAliceUSD = env.balance(alice, USD.issue());
1126 auto const preBobSeq = env.seq(bob);
1127 auto const preBob = env.balance(bob);
1128 auto const preBobUSD = env.balance(bob, USD.issue());
1130 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1131 auto const [txIDs, batchID] = submitBatch(
1142 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1144 validateClosedLedger(env, testCases);
1151 validateClosedLedger(env, testCases);
1155 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1156 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1157 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1158 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1159 BEAST_EXPECT(env.balance(bob) == preBob);
1160 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1167 testcase(
"bad outer fee");
1169 using namespace test::jtx;
1176 auto const alice =
Account(
"alice");
1177 auto const bob =
Account(
"bob");
1178 env.fund(
XRP(10000), alice, bob);
1185 auto const batchFee = batch::calcBatchFee(env, 0, 1);
1186 auto const aliceSeq = env.seq(alice);
1198 auto const alice =
Account(
"alice");
1199 auto const bob =
Account(
"bob");
1200 auto const carol =
Account(
"carol");
1201 env.fund(
XRP(10000), alice, bob, carol);
1207 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
1211 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1212 auto const aliceSeq = env.seq(alice);
1225 auto const alice =
Account(
"alice");
1226 auto const bob =
Account(
"bob");
1227 auto const carol =
Account(
"carol");
1228 env.fund(
XRP(10000), alice, bob, carol);
1234 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
1238 auto const batchFee = batch::calcBatchFee(env, 2, 2);
1239 auto const aliceSeq = env.seq(alice);
1240 auto const bobSeq = env.seq(bob);
1254 auto const alice =
Account(
"alice");
1255 auto const bob =
Account(
"bob");
1256 auto const carol =
Account(
"carol");
1257 env.fund(
XRP(10000), alice, bob, carol);
1263 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
1266 env(signers(bob, 2, {{alice, 1}, {carol, 1}}));
1270 auto const batchFee = batch::calcBatchFee(env, 3, 2);
1271 auto const aliceSeq = env.seq(alice);
1272 auto const bobSeq = env.seq(bob);
1286 auto const alice =
Account(
"alice");
1287 auto const bob =
Account(
"bob");
1288 env.fund(
XRP(10000), alice, bob);
1295 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1296 auto const aliceSeq = env.seq(alice);
1297 auto const bobSeq = env.seq(bob);
1310 auto const alice =
Account(
"alice");
1311 auto const bob =
Account(
"bob");
1312 auto const gw =
Account(
"gw");
1313 auto const USD = gw[
"USD"];
1315 env.fund(
XRP(10000), alice, bob, gw);
1317 auto const ammCreate =
1320 jv[jss::Account] = alice.human();
1323 jv[jss::TradingFee] = 0;
1324 jv[jss::TransactionType] = jss::AMMCreate;
1328 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1329 auto const seq = env.
seq(alice);
1341 testcase(
"calculate base fee");
1343 using namespace test::jtx;
1350 auto const alice =
Account(
"alice");
1351 auto const bob =
Account(
"bob");
1352 env.fund(
XRP(10000), alice, bob);
1355 auto const batchFee = batch::calcBatchFee(env, 0, 9);
1356 auto const aliceSeq = env.seq(alice);
1375 auto const alice =
Account(
"alice");
1376 auto const bob =
Account(
"bob");
1377 env.fund(
XRP(10000), alice, bob);
1380 auto const batchFee = batch::calcBatchFee(env, 0, 9);
1381 auto const aliceSeq = env.seq(alice);
1382 auto jt = env.jtnofill(
1394 env.app().openLedger().modify(
1400 return result.applied;
1408 auto const alice =
Account(
"alice");
1409 auto const bob =
Account(
"bob");
1410 env.fund(
XRP(10000), alice, bob);
1413 auto const aliceSeq = env.seq(alice);
1414 auto const batchFee = batch::calcBatchFee(env, 9, 2);
1418 batch::sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob),
1427 auto const alice =
Account(
"alice");
1428 auto const bob =
Account(
"bob");
1429 env.fund(
XRP(10000), alice, bob);
1432 auto const batchFee = batch::calcBatchFee(env, 0, 9);
1433 auto const aliceSeq = env.seq(alice);
1434 auto jt = env.jtnofill(
1438 batch::sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob));
1440 env.app().openLedger().modify(
1446 return result.applied;
1454 testcase(
"all or nothing");
1456 using namespace test::jtx;
1461 auto const alice =
Account(
"alice");
1462 auto const bob =
Account(
"bob");
1463 auto const gw =
Account(
"gw");
1464 auto const USD = gw[
"USD"];
1465 env.fund(
XRP(10000), alice, bob, gw);
1470 auto const preAlice = env.balance(alice);
1471 auto const preBob = env.balance(bob);
1473 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1474 auto const seq = env.
seq(alice);
1475 auto const [txIDs, batchID] = submitBatch(
1484 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1485 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1486 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1488 validateClosedLedger(env, testCases);
1491 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
1494 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
1495 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
1500 auto const preAlice = env.balance(alice);
1501 auto const preBob = env.balance(bob);
1503 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1504 auto const seq = env.
seq(alice);
1506 auto const [txIDs, batchID] = submitBatch(
1516 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1518 validateClosedLedger(env, testCases);
1521 BEAST_EXPECT(env.seq(alice) ==
seq + 1);
1524 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1525 BEAST_EXPECT(env.balance(bob) == preBob);
1530 auto const preAlice = env.balance(alice);
1531 auto const preBob = env.balance(bob);
1533 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1534 auto const seq = env.
seq(alice);
1535 auto const [txIDs, batchID] = submitBatch(
1545 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1547 validateClosedLedger(env, testCases);
1550 BEAST_EXPECT(env.seq(alice) ==
seq + 1);
1553 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1554 BEAST_EXPECT(env.balance(bob) == preBob);
1559 auto const preAlice = env.balance(alice);
1560 auto const preBob = env.balance(bob);
1562 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1563 auto const seq = env.
seq(alice);
1564 auto const [txIDs, batchID] = submitBatch(
1574 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1576 validateClosedLedger(env, testCases);
1579 BEAST_EXPECT(env.seq(alice) ==
seq + 1);
1582 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1583 BEAST_EXPECT(env.balance(bob) == preBob);
1590 testcase(
"only one");
1592 using namespace test::jtx;
1597 auto const alice =
Account(
"alice");
1598 auto const bob =
Account(
"bob");
1599 auto const carol =
Account(
"carol");
1600 auto const dave =
Account(
"dave");
1601 auto const gw =
Account(
"gw");
1602 auto const USD = gw[
"USD"];
1603 env.fund(
XRP(10000), alice, bob, carol, dave, gw);
1608 auto const preAlice = env.balance(alice);
1609 auto const preBob = env.balance(bob);
1611 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1612 auto const seq = env.
seq(alice);
1613 auto const [txIDs, batchID] = submitBatch(
1626 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1627 {1,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[0], batchID},
1628 {2,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[1], batchID},
1629 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
1631 validateClosedLedger(env, testCases);
1634 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
1637 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1638 BEAST_EXPECT(env.balance(bob) == preBob);
1643 auto const preAlice = env.balance(alice);
1644 auto const preBob = env.balance(bob);
1646 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1647 auto const seq = env.
seq(alice);
1648 auto const [txIDs, batchID] = submitBatch(
1659 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1660 {1,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[0], batchID},
1661 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1663 validateClosedLedger(env, testCases);
1666 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
1669 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
1670 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1675 auto const preAlice = env.balance(alice);
1676 auto const preBob = env.balance(bob);
1678 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1679 auto const seq = env.
seq(alice);
1680 auto const [txIDs, batchID] = submitBatch(
1691 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1692 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1694 validateClosedLedger(env, testCases);
1697 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1700 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
1701 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1706 auto const preAlice = env.balance(alice);
1707 auto const preBob = env.balance(bob);
1709 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1710 auto const seq = env.
seq(alice);
1711 auto const [txIDs, batchID] = submitBatch(
1722 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1723 {1,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1725 validateClosedLedger(env, testCases);
1728 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1731 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(1));
1732 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1737 auto const preAlice = env.balance(alice);
1738 auto const preBob = env.balance(bob);
1740 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1741 auto const seq = env.
seq(alice);
1742 auto const [txIDs, batchID] = submitBatch(
1753 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1754 {1,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1756 validateClosedLedger(env, testCases);
1759 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1762 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(1));
1763 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1768 auto const preAlice = env.balance(alice);
1769 auto const preBob = env.balance(bob);
1770 auto const preCarol = env.balance(carol);
1771 auto const seq = env.
seq(alice);
1772 auto const batchFee = batch::calcBatchFee(env, 0, 6);
1774 auto const [txIDs, batchID] = submitBatch(
1805 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1806 {1,
"OfferCreate",
"tecKILLED", txIDs[0], batchID},
1807 {2,
"OfferCreate",
"tecKILLED", txIDs[1], batchID},
1808 {3,
"OfferCreate",
"tecKILLED", txIDs[2], batchID},
1809 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
1811 validateClosedLedger(env, testCases);
1813 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(100) - batchFee);
1814 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(100));
1815 BEAST_EXPECT(env.balance(carol) == preCarol);
1822 testcase(
"until failure");
1824 using namespace test::jtx;
1829 auto const alice =
Account(
"alice");
1830 auto const bob =
Account(
"bob");
1831 auto const carol =
Account(
"carol");
1832 auto const dave =
Account(
"dave");
1833 auto const gw =
Account(
"gw");
1834 auto const USD = gw[
"USD"];
1835 env.fund(
XRP(10000), alice, bob, carol, dave, gw);
1840 auto const preAlice = env.balance(alice);
1841 auto const preBob = env.balance(bob);
1843 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1844 auto const seq = env.
seq(alice);
1845 auto const [txIDs, batchID] = submitBatch(
1857 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1858 {1,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[0], batchID},
1860 validateClosedLedger(env, testCases);
1863 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1866 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1867 BEAST_EXPECT(env.balance(bob) == preBob);
1872 auto const preAlice = env.balance(alice);
1873 auto const preBob = env.balance(bob);
1875 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1876 auto const seq = env.
seq(alice);
1877 auto const [txIDs, batchID] = submitBatch(
1888 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1889 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1890 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1891 {3,
"Payment",
"tesSUCCESS", txIDs[2], batchID},
1892 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
1894 validateClosedLedger(env, testCases);
1897 BEAST_EXPECT(env.seq(alice) ==
seq + 5);
1900 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(10) - batchFee);
1901 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(10));
1906 auto const preAlice = env.balance(alice);
1907 auto const preBob = env.balance(bob);
1909 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1910 auto const seq = env.
seq(alice);
1911 auto const [txIDs, batchID] = submitBatch(
1923 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1924 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1925 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1926 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
1928 validateClosedLedger(env, testCases);
1931 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
1934 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
1935 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
1940 auto const preAlice = env.balance(alice);
1941 auto const preBob = env.balance(bob);
1943 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1944 auto const seq = env.
seq(alice);
1945 auto const [txIDs, batchID] = submitBatch(
1957 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1958 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1959 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1961 validateClosedLedger(env, testCases);
1964 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
1967 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
1968 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
1973 auto const preAlice = env.balance(alice);
1974 auto const preBob = env.balance(bob);
1976 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1977 auto const seq = env.
seq(alice);
1978 auto const [txIDs, batchID] = submitBatch(
1990 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
1991 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1992 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1994 validateClosedLedger(env, testCases);
1997 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
2000 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2001 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2006 auto const preAlice = env.balance(alice);
2007 auto const preBob = env.balance(bob);
2008 auto const preCarol = env.balance(carol);
2009 auto const seq = env.
seq(alice);
2010 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2011 auto const [txIDs, batchID] = submitBatch(
2028 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2029 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2030 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2031 {3,
"OfferCreate",
"tecKILLED", txIDs[2], batchID},
2033 validateClosedLedger(env, testCases);
2035 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(200) - batchFee);
2036 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(100));
2037 BEAST_EXPECT(env.balance(carol) == preCarol +
XRP(100));
2044 testcase(
"independent");
2046 using namespace test::jtx;
2051 auto const alice =
Account(
"alice");
2052 auto const bob =
Account(
"bob");
2053 auto const carol =
Account(
"carol");
2054 auto const gw =
Account(
"gw");
2055 auto const USD = gw[
"USD"];
2056 env.fund(
XRP(10000), alice, bob, carol, gw);
2061 auto const preAlice = env.balance(alice);
2062 auto const preBob = env.balance(bob);
2064 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2065 auto const seq = env.
seq(alice);
2066 auto const [txIDs, batchID] = submitBatch(
2079 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2080 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2081 {2,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[1], batchID},
2082 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
2083 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2085 validateClosedLedger(env, testCases);
2088 BEAST_EXPECT(env.seq(alice) ==
seq + 5);
2091 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(4) - batchFee);
2092 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(4));
2097 auto const preAlice = env.balance(alice);
2098 auto const preBob = env.balance(bob);
2100 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2101 auto const seq = env.
seq(alice);
2102 auto const [txIDs, batchID] = submitBatch(
2114 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2115 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2116 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2117 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
2118 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2120 validateClosedLedger(env, testCases);
2123 BEAST_EXPECT(env.seq(alice) ==
seq + 5);
2126 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(6) - batchFee);
2127 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(6));
2132 auto const preAlice = env.balance(alice);
2133 auto const preBob = env.balance(bob);
2135 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2136 auto const seq = env.
seq(alice);
2137 auto const [txIDs, batchID] = submitBatch(
2149 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2150 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2151 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2152 {3,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2154 validateClosedLedger(env, testCases);
2157 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
2160 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(6));
2161 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(6));
2166 auto const preAlice = env.balance(alice);
2167 auto const preBob = env.balance(bob);
2169 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2170 auto const seq = env.
seq(alice);
2171 auto const [txIDs, batchID] = submitBatch(
2183 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2184 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2185 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2186 {3,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2188 validateClosedLedger(env, testCases);
2191 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
2194 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(6));
2195 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(6));
2200 auto const preAlice = env.balance(alice);
2201 auto const preBob = env.balance(bob);
2202 auto const preCarol = env.balance(carol);
2203 auto const seq = env.
seq(alice);
2204 auto const batchFee = batch::calcBatchFee(env, 0, 3);
2205 auto const [txIDs, batchID] = submitBatch(
2221 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2222 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2223 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2224 {3,
"OfferCreate",
"tecKILLED", txIDs[2], batchID},
2226 validateClosedLedger(env, testCases);
2228 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(200) - batchFee);
2229 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(100));
2230 BEAST_EXPECT(env.balance(carol) == preCarol +
XRP(100));
2237 testcase(
"inner submit rpc");
2239 using namespace test::jtx;
2244 auto const alice =
Account(
"alice");
2245 auto const bob =
Account(
"bob");
2247 env.fund(
XRP(10000), alice, bob);
2250 auto submitAndValidate = [&](
Slice const&
slice) {
2251 auto const jrr = env.rpc(
"submit",
strHex(
slice))[jss::result];
2253 jrr[jss::status] ==
"error" &&
2254 jrr[jss::error] ==
"invalidTransaction" &&
2255 jrr[jss::error_exception] ==
2256 "fails local checks: Malformed: Invalid inner batch "
2268 txn[sfTxnSignature] =
"DEADBEEF";
2272 submitAndValidate(s.
slice());
2282 txn[sfSigningPubKey] =
strHex(alice.pk());
2286 submitAndValidate(s.
slice());
2300 submitAndValidate(s.
slice());
2313 auto const jrr = env.rpc(
"submit",
strHex(s.
slice()))[jss::result];
2315 jrr[jss::status] ==
"success" &&
2316 jrr[jss::engine_result] ==
"temINVALID_FLAG");
2325 testcase(
"account activation");
2327 using namespace test::jtx;
2332 auto const alice =
Account(
"alice");
2333 auto const bob =
Account(
"bob");
2334 env.fund(
XRP(10000), alice);
2338 auto const preAlice = env.balance(alice);
2339 auto const ledSeq = env.current()->seq();
2340 auto const seq = env.
seq(alice);
2341 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2342 auto const [txIDs, batchID] = submitBatch(
2352 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2353 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2354 {2,
"AccountSet",
"tesSUCCESS", txIDs[1], batchID},
2356 validateClosedLedger(env, testCases);
2359 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
2362 BEAST_EXPECT(env.seq(bob) == ledSeq + 1);
2365 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - batchFee);
2366 BEAST_EXPECT(env.balance(bob) ==
XRP(1000));
2372 testcase(
"account set");
2374 using namespace test::jtx;
2379 auto const alice =
Account(
"alice");
2380 auto const bob =
Account(
"bob");
2381 env.fund(
XRP(10000), alice, bob);
2384 auto const preAlice = env.balance(alice);
2385 auto const preBob = env.balance(bob);
2387 auto const seq = env.
seq(alice);
2388 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2392 auto const [txIDs, batchID] = submitBatch(
2401 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2402 {1,
"AccountSet",
"tesSUCCESS", txIDs[0], batchID},
2403 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2405 validateClosedLedger(env, testCases);
2413 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
2416 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
2417 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
2423 testcase(
"account delete");
2425 using namespace test::jtx;
2432 auto const alice =
Account(
"alice");
2433 auto const bob =
Account(
"bob");
2434 env.fund(
XRP(10000), alice, bob);
2438 for (
int i = 0; i < 5; ++i)
2441 auto const preAlice = env.balance(alice);
2442 auto const preBob = env.balance(bob);
2444 auto const seq = env.
seq(alice);
2445 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
2446 env.current()->fees().increment;
2447 auto const [txIDs, batchID] = submitBatch(
2458 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2459 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2460 {2,
"AccountDelete",
"tesSUCCESS", txIDs[1], batchID},
2462 validateClosedLedger(env, testCases);
2466 BEAST_EXPECT(env.balance(bob) == preBob + (preAlice - batchFee));
2473 auto const alice =
Account(
"alice");
2474 auto const bob =
Account(
"bob");
2475 env.fund(
XRP(10000), alice, bob);
2479 for (
int i = 0; i < 5; ++i)
2482 auto const preAlice = env.balance(alice);
2483 auto const preBob = env.balance(bob);
2485 env.trust(bob[
"USD"](1000), alice);
2488 auto const seq = env.
seq(alice);
2489 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
2490 env.current()->fees().increment;
2491 auto const [txIDs, batchID] = submitBatch(
2502 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2503 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2504 {2,
"AccountDelete",
"tecHAS_OBLIGATIONS", txIDs[1], batchID},
2505 {3,
"Payment",
"tesSUCCESS", txIDs[2], batchID},
2507 validateClosedLedger(env, testCases);
2511 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2518 auto const alice =
Account(
"alice");
2519 auto const bob =
Account(
"bob");
2520 env.fund(
XRP(10000), alice, bob);
2524 for (
int i = 0; i < 5; ++i)
2527 auto const preAlice = env.balance(alice);
2528 auto const preBob = env.balance(bob);
2530 auto const seq = env.
seq(alice);
2531 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
2532 env.current()->fees().increment;
2533 auto const [txIDs, batchID] = submitBatch(
2544 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2546 validateClosedLedger(env, testCases);
2550 BEAST_EXPECT(env.balance(bob) == preBob);
2557 testcase(
"object create w/ sequence");
2559 using namespace test::jtx;
2564 auto const alice =
Account(
"alice");
2565 auto const bob =
Account(
"bob");
2566 auto const gw =
Account(
"gw");
2567 auto const USD = gw[
"USD"];
2569 env.fund(
XRP(10000), alice, bob, gw);
2572 env.trust(USD(1000), alice, bob);
2573 env(pay(gw, alice, USD(100)));
2574 env(pay(gw, bob, USD(100)));
2579 auto const aliceSeq = env.seq(alice);
2580 auto const bobSeq = env.seq(bob);
2581 auto const preAlice = env.balance(alice);
2582 auto const preBob = env.balance(bob);
2583 auto const preAliceUSD = env.balance(alice, USD.issue());
2584 auto const preBobUSD = env.balance(bob, USD.issue());
2586 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2587 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
2588 auto const [txIDs, batchID] = submitBatch(
2592 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
2593 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
2598 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2599 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
2600 {2,
"CheckCash",
"tesSUCCESS", txIDs[1], batchID},
2602 validateClosedLedger(env, testCases);
2605 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2608 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
2611 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
2612 BEAST_EXPECT(env.balance(bob) == preBob);
2616 env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
2617 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
2625 auto const aliceSeq = env.seq(alice);
2626 auto const bobSeq = env.seq(bob);
2627 auto const preAlice = env.balance(alice);
2628 auto const preBob = env.balance(bob);
2629 auto const preAliceUSD = env.balance(alice, USD.issue());
2630 auto const preBobUSD = env.balance(bob, USD.issue());
2632 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2633 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
2634 auto const [txIDs, batchID] = submitBatch(
2639 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
2640 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
2645 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2646 {1,
"CheckCreate",
"tecDST_TAG_NEEDED", txIDs[0], batchID},
2647 {2,
"CheckCash",
"tecNO_ENTRY", txIDs[1], batchID},
2649 validateClosedLedger(env, testCases);
2652 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2655 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
2658 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
2659 BEAST_EXPECT(env.balance(bob) == preBob);
2662 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
2663 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
2670 testcase(
"object create w/ ticket");
2672 using namespace test::jtx;
2677 auto const alice =
Account(
"alice");
2678 auto const bob =
Account(
"bob");
2679 auto const gw =
Account(
"gw");
2680 auto const USD = gw[
"USD"];
2682 env.fund(
XRP(10000), alice, bob, gw);
2685 env.trust(USD(1000), alice, bob);
2686 env(pay(gw, alice, USD(100)));
2687 env(pay(gw, bob, USD(100)));
2690 auto const aliceSeq = env.seq(alice);
2691 auto const bobSeq = env.seq(bob);
2692 auto const preAlice = env.balance(alice);
2693 auto const preBob = env.balance(bob);
2694 auto const preAliceUSD = env.balance(alice, USD.issue());
2695 auto const preBobUSD = env.balance(bob, USD.issue());
2697 auto const batchFee = batch::calcBatchFee(env, 1, 3);
2698 uint256 const chkID{getCheckIndex(bob, bobSeq + 1)};
2699 auto const [txIDs, batchID] = submitBatch(
2704 batch::inner(check::create(bob, alice, USD(10)), 0, bobSeq + 1),
2705 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
2710 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2711 {1,
"TicketCreate",
"tesSUCCESS", txIDs[0], batchID},
2712 {2,
"CheckCreate",
"tesSUCCESS", txIDs[1], batchID},
2713 {3,
"CheckCash",
"tesSUCCESS", txIDs[2], batchID},
2715 validateClosedLedger(env, testCases);
2717 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2718 BEAST_EXPECT(env.seq(bob) == bobSeq + 10 + 1);
2719 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
2720 BEAST_EXPECT(env.balance(bob) == preBob);
2721 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
2722 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
2728 testcase(
"object create w/ 3rd party");
2730 using namespace test::jtx;
2735 auto const alice =
Account(
"alice");
2736 auto const bob =
Account(
"bob");
2737 auto const carol =
Account(
"carol");
2738 auto const gw =
Account(
"gw");
2739 auto const USD = gw[
"USD"];
2741 env.fund(
XRP(10000), alice, bob, carol, gw);
2744 env.trust(USD(1000), alice, bob);
2745 env(pay(gw, alice, USD(100)));
2746 env(pay(gw, bob, USD(100)));
2749 auto const aliceSeq = env.seq(alice);
2750 auto const bobSeq = env.seq(bob);
2751 auto const carolSeq = env.seq(carol);
2752 auto const preAlice = env.balance(alice);
2753 auto const preBob = env.balance(bob);
2754 auto const preCarol = env.balance(carol);
2755 auto const preAliceUSD = env.balance(alice, USD.issue());
2756 auto const preBobUSD = env.balance(bob, USD.issue());
2758 auto const batchFee = batch::calcBatchFee(env, 2, 2);
2759 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
2760 auto const [txIDs, batchID] = submitBatch(
2764 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
2765 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq),
2770 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2771 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
2772 {2,
"CheckCash",
"tesSUCCESS", txIDs[1], batchID},
2774 validateClosedLedger(env, testCases);
2776 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
2777 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
2778 BEAST_EXPECT(env.seq(carol) == carolSeq + 1);
2779 BEAST_EXPECT(env.balance(alice) == preAlice);
2780 BEAST_EXPECT(env.balance(bob) == preBob);
2781 BEAST_EXPECT(env.balance(carol) == preCarol - batchFee);
2782 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
2783 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
2790 testcase(
"tickets outer");
2792 using namespace test::jtx;
2797 auto const alice =
Account(
"alice");
2798 auto const bob =
Account(
"bob");
2800 env.fund(
XRP(10000), alice, bob);
2804 env(ticket::create(alice, 10));
2807 auto const aliceSeq = env.seq(alice);
2808 auto const preAlice = env.balance(alice);
2809 auto const preBob = env.balance(bob);
2811 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2812 auto const [txIDs, batchID] = submitBatch(
2822 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2823 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2824 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2826 validateClosedLedger(env, testCases);
2830 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 9);
2831 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 9);
2833 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2834 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2835 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2839 testcase(
"tickets inner");
2841 using namespace test::jtx;
2846 auto const alice =
Account(
"alice");
2847 auto const bob =
Account(
"bob");
2849 env.fund(
XRP(10000), alice, bob);
2853 env(ticket::create(alice, 10));
2856 auto const aliceSeq = env.seq(alice);
2857 auto const preAlice = env.balance(alice);
2858 auto const preBob = env.balance(bob);
2860 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2861 auto const [txIDs, batchID] = submitBatch(
2870 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2871 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2872 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2874 validateClosedLedger(env, testCases);
2878 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
2879 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
2881 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
2882 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2883 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2887 testcase(
"tickets outer inner");
2889 using namespace test::jtx;
2894 auto const alice =
Account(
"alice");
2895 auto const bob =
Account(
"bob");
2897 env.fund(
XRP(10000), alice, bob);
2901 env(ticket::create(alice, 10));
2904 auto const aliceSeq = env.seq(alice);
2905 auto const preAlice = env.balance(alice);
2906 auto const preBob = env.balance(bob);
2908 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2909 auto const [txIDs, batchID] = submitBatch(
2919 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2920 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2921 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2923 validateClosedLedger(env, testCases);
2927 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
2928 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
2930 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
2931 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2932 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2939 testcase(
"sequence open ledger");
2941 using namespace test::jtx;
2944 auto const alice =
Account(
"alice");
2945 auto const bob =
Account(
"bob");
2946 auto const carol =
Account(
"carol");
2956 env.fund(
XRP(10000), alice, bob, carol);
2959 auto const aliceSeq = env.seq(alice);
2960 auto const carolSeq = env.seq(carol);
2963 auto const noopTxn = env.jt(
noop(alice),
seq(aliceSeq + 2));
2964 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
2968 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2969 auto const [txIDs, batchID] = submitBatch(
2980 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
2981 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2982 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2984 validateClosedLedger(env, testCases);
2991 {0,
"AccountSet",
"tesSUCCESS", noopTxnID, std::nullopt},
2993 validateClosedLedger(env, testCases);
3003 env.fund(
XRP(10000), alice, bob);
3006 auto const aliceSeq = env.seq(alice);
3009 auto const noopTxn = env.jt(
noop(alice),
seq(aliceSeq + 1));
3013 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3014 auto const [txIDs, batchID] = submitBatch(
3024 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
3025 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3026 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3028 validateClosedLedger(env, testCases);
3035 validateClosedLedger(env, testCases);
3045 env.fund(
XRP(10000), alice, bob);
3048 auto const aliceSeq = env.seq(alice);
3049 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3050 auto const [txIDs, batchID] = submitBatch(
3057 auto const noopTxn = env.jt(
noop(alice),
seq(aliceSeq + 1));
3058 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3064 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
3065 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3066 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3068 validateClosedLedger(env, testCases);
3075 validateClosedLedger(env, testCases);
3082 env.fund(
XRP(10000), alice, bob, carol);
3085 auto const aliceSeq = env.seq(alice);
3086 auto const carolSeq = env.seq(carol);
3089 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3090 auto const [txIDs, batchID] = submitBatch(
3099 auto const noopTxn = env.jt(
noop(carol),
seq(carolSeq));
3100 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3106 {0,
"AccountSet",
"tesSUCCESS", noopTxnID, std::nullopt},
3107 {1,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
3108 {2,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3109 {3,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3111 validateClosedLedger(env, testCases);
3118 validateClosedLedger(env, testCases);
3126 testcase(
"tickets open ledger");
3128 using namespace test::jtx;
3131 auto const alice =
Account(
"alice");
3132 auto const bob =
Account(
"bob");
3140 env.fund(
XRP(10000), alice, bob);
3144 env(ticket::create(alice, 10));
3147 auto const aliceSeq = env.seq(alice);
3150 auto const noopTxn =
3152 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3156 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3157 auto const [txIDs, batchID] = submitBatch(
3168 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
3169 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3170 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3172 validateClosedLedger(env, testCases);
3179 validateClosedLedger(env, testCases);
3189 env.fund(
XRP(10000), alice, bob);
3193 env(ticket::create(alice, 10));
3196 auto const aliceSeq = env.seq(alice);
3199 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3200 auto const [txIDs, batchID] = submitBatch(
3209 auto const noopTxn =
3216 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
3217 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3218 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3220 validateClosedLedger(env, testCases);
3227 validateClosedLedger(env, testCases);
3235 testcase(
"objects open ledger");
3237 using namespace test::jtx;
3240 auto const alice =
Account(
"alice");
3241 auto const bob =
Account(
"bob");
3251 env.fund(
XRP(10000), alice, bob);
3255 env(ticket::create(alice, 10));
3258 auto const aliceSeq = env.seq(alice);
3261 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
3262 auto const objTxn = env.jt(check::cash(bob, chkID,
XRP(10)));
3263 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
3267 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3268 auto const [txIDs, batchID] = submitBatch(
3279 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
3280 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
3281 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3282 {3,
"CheckCash",
"tesSUCCESS", objTxnID, std::nullopt},
3284 validateClosedLedger(env, testCases);
3291 validateClosedLedger(env, testCases);
3298 env.fund(
XRP(10000), alice, bob);
3302 env(ticket::create(alice, 10));
3305 auto const aliceSeq = env.seq(alice);
3306 auto const bobSeq = env.seq(bob);
3309 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
3310 auto const objTxn = env.jt(check::create(alice, bob,
XRP(10)));
3311 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
3315 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3316 auto const [txIDs, batchID] = submitBatch(
3328 {0,
"CheckCreate",
"tesSUCCESS", objTxnID, std::nullopt},
3329 {1,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
3330 {2,
"CheckCash",
"tesSUCCESS", txIDs[0], batchID},
3331 {3,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3333 validateClosedLedger(env, testCases);
3345 env.fund(
XRP(10000), alice, bob);
3349 env(ticket::create(alice, 10));
3352 auto const aliceSeq = env.seq(alice);
3355 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3356 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
3357 auto const [txIDs, batchID] = submitBatch(
3366 auto const objTxn = env.jt(check::cash(bob, chkID,
XRP(10)));
3367 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
3373 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
3374 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
3375 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3376 {3,
"CheckCash",
"tesSUCCESS", objTxnID, std::nullopt},
3378 validateClosedLedger(env, testCases);
3386 testcase(
"pseudo txn with tfInnerBatchTxn");
3388 using namespace test::jtx;
3393 auto const alice =
Account(
"alice");
3394 auto const bob =
Account(
"bob");
3395 env.fund(
XRP(10000), alice, bob);
3398 STTx const stx =
STTx(ttAMENDMENT, [&](
auto& obj) {
3399 obj.setAccountID(sfAccount,
AccountID());
3400 obj.setFieldH256(sfAmendment,
uint256(2));
3401 obj.setFieldU32(sfLedgerSequence, env.seq(alice));
3408 BEAST_EXPECT(reason ==
"Cannot submit pseudo transactions.");
3412 return result.applied;
3419 testcase(
"batch open ledger");
3427 using namespace test::jtx;
3431 XRPAmount const baseFee = env.current()->fees().base;
3433 auto const alice =
Account(
"alice");
3434 auto const bob =
Account(
"bob");
3436 env.fund(
XRP(10000), alice, bob);
3442 auto const aliceSeq = env.seq(alice);
3443 auto const preAlice = env.balance(alice);
3444 auto const preBob = env.balance(bob);
3445 auto const bobSeq = env.seq(bob);
3448 auto const payTxn1 = env.jt(pay(alice, bob,
XRP(10)),
seq(aliceSeq));
3449 auto const payTxn1ID =
to_string(payTxn1.stx->getTransactionID());
3453 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3454 auto const [txIDs, batchID] = submitBatch(
3463 auto const payTxn2 = env.jt(pay(bob, alice,
XRP(5)),
seq(bobSeq + 1));
3464 auto const payTxn2ID =
to_string(payTxn2.stx->getTransactionID());
3469 {0,
"Payment",
"tesSUCCESS", payTxn1ID, std::nullopt},
3470 {1,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
3471 {2,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3472 {3,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3474 validateClosedLedger(env, testCases);
3480 {0,
"Payment",
"tesSUCCESS", payTxn2ID, std::nullopt},
3482 validateClosedLedger(env, testCases);
3486 BEAST_EXPECT(env.seq(alice) == aliceSeq + 3);
3489 BEAST_EXPECT(env.seq(bob) == bobSeq + 2);
3493 env.balance(alice) == preAlice -
XRP(10) - batchFee - baseFee);
3494 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(10) - baseFee);
3500 testcase(
"batch tx queue");
3502 using namespace test::jtx;
3509 makeSmallQueueConfig(
3510 {{
"minimum_txn_in_ledger_standalone",
"2"}}),
3514 auto alice =
Account(
"alice");
3516 auto carol =
Account(
"carol");
3520 env.close(env.now() + 5s, 10000ms);
3522 env.close(env.now() + 5s, 10000ms);
3533 auto const aliceSeq = env.seq(alice);
3534 auto const bobSeq = env.seq(bob);
3535 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3553 openLedgerFee(env, batchFee),
3569 makeSmallQueueConfig(
3570 {{
"minimum_txn_in_ledger_standalone",
"2"}}),
3574 auto alice =
Account(
"alice");
3576 auto carol =
Account(
"carol");
3580 env.close(env.now() + 5s, 10000ms);
3582 env.close(env.now() + 5s, 10000ms);
3589 auto const aliceSeq = env.seq(alice);
3590 auto const bobSeq = env.seq(bob);
3591 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3612 testcase(
"batch network ops");
3614 using namespace test::jtx;
3624 auto alice =
Account(
"alice");
3626 env.
fund(
XRP(10000), alice, bob);
3634 return jt.stx->getTransactionID();
3643 std::make_shared<Transaction>(jt.stx, reason, env.
app());
3646 return transaction->getID();
3667 testcase(
"batch delegate");
3669 using namespace test::jtx;
3676 auto const alice =
Account(
"alice");
3677 auto const bob =
Account(
"bob");
3678 auto const gw =
Account(
"gw");
3679 auto const USD = gw[
"USD"];
3680 env.fund(
XRP(10000), alice, bob, gw);
3683 env(delegate::set(alice, bob, {
"Payment"}));
3686 auto const preAlice = env.balance(alice);
3687 auto const preBob = env.balance(bob);
3689 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3690 auto const seq = env.
seq(alice);
3693 tx[jss::Delegate] = bob.human();
3694 auto const [txIDs, batchID] = submitBatch(
3703 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
3704 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3705 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3707 validateClosedLedger(env, testCases);
3710 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
3713 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
3714 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
3721 auto const alice =
Account(
"alice");
3722 auto const bob =
Account(
"bob");
3723 auto const carol =
Account(
"carol");
3724 auto const gw =
Account(
"gw");
3725 auto const USD = gw[
"USD"];
3726 env.fund(
XRP(10000), alice, bob, carol, gw);
3729 env(delegate::set(bob, carol, {
"Payment"}));
3732 auto const preAlice = env.balance(alice);
3733 auto const preBob = env.balance(bob);
3734 auto const preCarol = env.balance(carol);
3736 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3737 auto const aliceSeq = env.seq(alice);
3738 auto const bobSeq = env.seq(bob);
3741 tx[jss::Delegate] = carol.human();
3742 auto const [txIDs, batchID] = submitBatch(
3752 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
3753 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3754 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3756 validateClosedLedger(env, testCases);
3758 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
3759 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
3760 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
3761 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
3764 BEAST_EXPECT(env.balance(carol) == preCarol);
3771 auto const alice =
Account(
"alice");
3772 auto const bob =
Account(
"bob");
3773 auto const gw =
Account(
"gw");
3774 auto const USD = gw[
"USD"];
3775 env.fund(
XRP(10000), alice, bob, gw);
3778 env(delegate::set(alice, bob, {
"AccountDomainSet"}));
3781 auto const preAlice = env.balance(alice);
3782 auto const preBob = env.balance(bob);
3784 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3785 auto const seq = env.
seq(alice);
3790 tx[jss::Delegate] = bob.human();
3791 auto const [txIDs, batchID] = submitBatch(
3800 {0,
"Batch",
"tesSUCCESS", batchID, std::nullopt},
3801 {1,
"AccountSet",
"tesSUCCESS", txIDs[0], batchID},
3802 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3804 validateClosedLedger(env, testCases);
3807 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
3810 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(2) - batchFee);
3811 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(2));
3818 testEnable(features);
3819 testPreflight(features);
3820 testPreclaim(features);
3821 testBadRawTxn(features);
3822 testBadSequence(features);
3823 testBadOuterFee(features);
3824 testCalculateBaseFee(features);
3825 testAllOrNothing(features);
3826 testOnlyOne(features);
3827 testUntilFailure(features);
3828 testIndependent(features);
3829 testInnerSubmitRPC(features);
3830 testAccountActivation(features);
3831 testAccountSet(features);
3832 testAccountDelete(features);
3833 testObjectCreateSequence(features);
3834 testObjectCreateTicket(features);
3835 testObjectCreate3rdParty(features);
3836 testTickets(features);
3837 testSequenceOpenLedger(features);
3838 testTicketsOpenLedger(features);
3839 testObjectsOpenLedger(features);
3840 testPseudoTxn(features);
3841 testOpenLedger(features);
3842 testBatchTxQueue(features);
3843 testBatchNetworkOps(features);
3844 testBatchDelegate(features);
3851 using namespace test::jtx;
A generic endpoint for log messages.
testcase_t testcase
Memberspace for declaring test cases.
virtual NetworkOPs & getOPs()=0
virtual HashRouter & getHashRouter()=0
int getFlags(uint256 const &key)
virtual void submitTransaction(std::shared_ptr< STTx const > const &)=0
virtual void processTransaction(std::shared_ptr< Transaction > &transaction, bool bUnlimited, bool bLocal, FailHard failType)=0
Process transactions as they arrive from the network or which are submitted by clients.
Writable ledger view that accumulates state and tx changes.
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Holds the serialized result of parsing an input JSON object.
std::optional< STObject > object
The STObject if the parse was successful.
Slice slice() const noexcept
An immutable linear range of bytes.
Metrics getMetrics(OpenView const &view) const
Returns fee metrics in reference fee level units.
void testBatchNetworkOps(FeatureBitset features)
void validateInnerTxn(jtx::Env &env, std::string const &batchID, TestLedgerData const &ledgerResult)
void testAccountSet(FeatureBitset features)
void testTickets(FeatureBitset features)
void run() override
Runs the suite.
void testAllOrNothing(FeatureBitset features)
void testObjectCreate3rdParty(FeatureBitset features)
void testAccountActivation(FeatureBitset features)
Json::Value getLastLedger(jtx::Env &env)
void testObjectCreateTicket(FeatureBitset features)
void testBadRawTxn(FeatureBitset features)
void testPreclaim(FeatureBitset features)
std::pair< std::vector< std::string >, std::string > submitBatch(jtx::Env &env, TER const &result, Args &&... args)
void testBatchTxQueue(FeatureBitset features)
void testBadSequence(FeatureBitset features)
static uint256 getCheckIndex(AccountID const &account, std::uint32_t uSequence)
Json::Value getTxByIndex(Json::Value const &jrr, int const index)
void validateClosedLedger(jtx::Env &env, std::vector< TestLedgerData > const &ledgerResults)
void testObjectCreateSequence(FeatureBitset features)
void testBatchDelegate(FeatureBitset features)
void testOpenLedger(FeatureBitset features)
auto openLedgerFee(jtx::Env &env, XRPAmount const &batchFee)
void testPreflight(FeatureBitset features)
void testUntilFailure(FeatureBitset features)
void testWithFeats(FeatureBitset features)
void testSequenceOpenLedger(FeatureBitset features)
void testTicketsOpenLedger(FeatureBitset features)
void testIndependent(FeatureBitset features)
static std::unique_ptr< Config > makeSmallQueueConfig(std::map< std::string, std::string > extraTxQ={}, std::map< std::string, std::string > extraVoting={})
void testOnlyOne(FeatureBitset features)
void testPseudoTxn(FeatureBitset features)
void testInnerSubmitRPC(FeatureBitset features)
void testEnable(FeatureBitset features)
void testBadOuterFee(FeatureBitset features)
void testObjectsOpenLedger(FeatureBitset features)
void testCalculateBaseFee(FeatureBitset features)
void testAccountDelete(FeatureBitset features)
Immutable cryptographic account descriptor.
A transaction testing environment.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
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.
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
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)
Adds a new Batch Txn on a JTx and autofills.
Set a batch nested multi-signature on a JTx.
Set a batch signature on a JTx.
Set a multisignature on a JTx.
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)
@ objectValue
object value (collection of name/value pairs).
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Json::Value outer(jtx::Account const &account, uint32_t seq, STAmount const &fee, std::uint32_t flags)
Batch.
XRPAmount calcBatchFee(jtx::Env const &env, uint32_t const &numSigners, uint32_t const &txns=0)
Calculate Batch Fee.
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)
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
std::array< Account, 1+sizeof...(Args)> noripple(Account const &account, Args const &... args)
Designate accounts as no-ripple in Env::fund.
void checkMetrics(Suite &test, jtx::Env &env, std::size_t expectedCount, std::optional< std::size_t > expectedMaxCount, std::size_t expectedInLedger, std::size_t expectedPerLedger, std::uint64_t expectedMinFeeLevel=baseFeeLevel.fee(), std::uint64_t expectedMedFeeLevel=minEscalationFeeLevel.fee(), source_location const location=source_location::current())
void incLgrSeqForAccDel(jtx::Env &env, jtx::Account const &acc, std::uint32_t margin=0)
Json::Value acctdelete(Account const &account, Account const &dest)
Delete account.
XRP_t const XRP
Converts to XRP Issue or STAmount.
FeatureBitset supported_amendments()
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
constexpr std::uint32_t tfAllOrNothing
constexpr std::uint32_t tfOnlyOne
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
constexpr std::uint32_t asfRequireDest
constexpr std::uint32_t tfIndependent
void serializeBatch(Serializer &msg, std::uint32_t const &flags, std::vector< uint256 > const &txids)
constexpr std::uint32_t tfImmediateOrCancel
constexpr std::uint32_t asfDisableMaster
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &message)
Generate a signature for a message.
constexpr std::uint32_t tfUntilFailure
std::string strHex(FwdIt begin, FwdIt end)
constexpr std::uint32_t tfSetfAuth
constexpr std::uint32_t tfDisallowXRP
ApplyResult apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
bool passesLocalChecks(STObject const &st, std::string &)
std::string to_string(base_uint< Bits, Tag > const &a)
constexpr std::uint32_t asfAllowTrustLineClawback
XRPAmount toDrops(FeeLevel< T > const &level, XRPAmount baseFee)
constexpr std::uint32_t tfInnerBatchTxn
std::optional< std::string > batchID
Set the sequence number on a JTx.