2#include <test/jtx/TestHelpers.h>
3#include <test/jtx/utility.h>
5#include <xrpld/app/misc/HashRouter.h>
6#include <xrpld/app/misc/NetworkOPs.h>
7#include <xrpld/app/misc/Transaction.h>
8#include <xrpld/app/tx/apply.h>
9#include <xrpld/app/tx/detail/Batch.h>
11#include <xrpl/protocol/Batch.h>
12#include <xrpl/protocol/Feature.h>
13#include <xrpl/protocol/STParsedJSON.h>
14#include <xrpl/protocol/Sign.h>
15#include <xrpl/protocol/TxFlags.h>
16#include <xrpl/protocol/jss.h>
41 for (
auto const& txn : jrr[jss::result][jss::ledger][jss::transactions])
43 if (txn[jss::metaData][sfTransactionIndex.jsonName] == index)
53 params[jss::ledger_index] = env.
closed()->seq();
54 params[jss::transactions] =
true;
55 params[jss::expand] =
true;
66 BEAST_EXPECT(jrr[sfTransactionType.jsonName] == ledgerResult.
txType);
68 jrr[jss::meta][sfTransactionResult.jsonName] ==
70 BEAST_EXPECT(jrr[jss::meta][sfParentBatchID.jsonName] == batchID);
79 auto const transactions =
80 jrr[jss::result][jss::ledger][jss::transactions];
81 BEAST_EXPECT(transactions.size() == ledgerResults.
size());
85 BEAST_EXPECT(txn[jss::hash].asString() == ledgerResult.txHash);
86 BEAST_EXPECT(txn.isMember(jss::metaData));
89 txn[sfTransactionType.jsonName] == ledgerResult.txType);
91 meta[sfTransactionResult.jsonName] == ledgerResult.result);
92 if (ledgerResult.batchID)
97 template <
typename... Args>
104 auto const ids = batchTxn.stx->getBatchTransactionIDs();
106 for (
auto const&
id : ids)
108 TxID const batchID = batchTxn.stx->getTransactionID();
124 auto& section = p->section(
"transaction_queue");
125 section.set(
"ledgers_in_queue",
"2");
126 section.set(
"minimum_queue_size",
"2");
127 section.set(
"min_ledgers_to_compute_size_limit",
"3");
128 section.set(
"max_ledger_counts_to_store",
"100");
129 section.set(
"retry_sequence_percent",
"25");
130 section.set(
"normal_consensus_increase_percent",
"0");
132 for (
auto const& [k, v] : extraTxQ)
143 auto const& view = *env.
current();
145 return toDrops(metrics.openLedgerFeeLevel, batchFee) + 1;
153 using namespace test::jtx;
156 for (
bool const withBatch : {
true,
false})
158 auto const amend = withBatch ? features : features - featureBatch;
161 auto const alice =
Account(
"alice");
162 auto const bob =
Account(
"bob");
163 auto const carol =
Account(
"carol");
164 env.fund(
XRP(10000), alice, bob, carol);
169 auto const seq = env.
seq(alice);
171 auto const txResult =
185 auto const txResult =
187 env(
pay(alice, bob,
XRP(1)),
202 using namespace test::jtx;
210 auto const alice =
Account(
"alice");
211 auto const bob =
Account(
"bob");
212 auto const carol =
Account(
"carol");
213 env.fund(
XRP(10000), alice, bob, carol);
226 auto const seq = env.
seq(alice);
235 auto const seq = env.
seq(alice);
244 auto const seq = env.
seq(alice);
254 auto const seq = env.
seq(alice);
263 auto const seq = env.
seq(alice);
274 auto const seq = env.
seq(alice);
293 auto const seq = env.
seq(alice);
294 auto jt = env.jtnofill(
306 auto const seq = env.
seq(alice);
320 auto const seq = env.
seq(alice);
323 auto jt = env.jtnofill(
334 auto const seq = env.
seq(alice);
336 auto jt = env.jt(
pay(alice, bob,
XRP(1)));
346 auto const seq = env.
seq(alice);
348 auto tx1 =
pay(alice, bob,
XRP(1));
351 tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfAccount.jsonName] =
353 tx1[sfSigners.jsonName][0U][sfSigner.jsonName]
354 [sfSigningPubKey.jsonName] =
strHex(alice.pk());
355 tx1[sfSigners.jsonName][0U][sfSigner.jsonName]
356 [sfTxnSignature.jsonName] =
"DEADBEEF";
367 auto const seq = env.
seq(alice);
370 tx1[jss::SigningPubKey] =
strHex(alice.pk());
371 auto jt = env.jtnofill(
382 auto const seq = env.
seq(alice);
394 auto const seq = env.
seq(alice);
397 tx1[jss::Fee] =
to_string(env.current()->fees().base);
408 auto const seq = env.
seq(alice);
411 tx1[jss::Sequence] =
seq + 1;
422 auto const seq = env.
seq(alice);
433 auto const seq = env.
seq(alice);
444 auto const seq = env.
seq(alice);
455 auto const seq = env.
seq(alice);
468 auto const seq = env.
seq(alice);
490 auto const seq = env.
seq(alice);
502 auto const seq = env.
seq(alice);
515 auto const seq = env.
seq(alice);
527 auto const seq = env.
seq(alice);
539 auto const seq = env.
seq(alice);
540 auto const bobSeq = env.seq(bob);
542 auto jt = env.jtnofill(
551 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
552 [sfAccount.jsonName] = bob.human();
553 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
554 [sfSigningPubKey.jsonName] =
strHex(alice.pk());
555 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
556 [sfTxnSignature.jsonName] =
565 auto const seq = env.
seq(alice);
582 using namespace test::jtx;
590 auto const alice =
Account(
"alice");
591 auto const bob =
Account(
"bob");
592 auto const carol =
Account(
"carol");
593 auto const dave =
Account(
"dave");
594 auto const elsa =
Account(
"elsa");
595 auto const frank =
Account(
"frank");
596 auto const phantom =
Account(
"phantom");
597 env.memoize(phantom);
599 env.fund(
XRP(10000), alice, bob, carol, dave, elsa, frank);
607 auto const seq = env.
seq(alice);
622 auto const seq = env.
seq(alice);
632 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
635 env(
signers(bob, 2, {{carol, 1}, {dave, 1}, {elsa, 1}}));
640 auto const seq = env.
seq(alice);
652 auto const seq = env.
seq(alice);
657 batch::msig(bob, {carol, Account(
"dave", KeyType::ed25519)}),
666 auto const seq = env.
seq(alice);
678 auto const seq = env.
seq(alice);
690 auto const seq = env.
seq(alice);
704 auto const seq = env.
seq(alice);
708 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
709 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
710 batch::msig(bob, {carol, Reg{dave, davo}}),
717 auto const seq = env.seq(alice);
720 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
721 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
722 batch::msig(bob, {carol}),
729 auto const seq = env.seq(alice);
732 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
733 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
734 batch::msig(bob, {carol, dave}),
741 auto const seq = env.seq(alice);
744 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
745 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
746 batch::msig(bob, {carol, dave}),
757 auto const ledSeq = env.current()->seq();
758 auto const seq = env.seq(alice);
761 batch::inner(
pay(alice, phantom,
XRP(1000)), seq + 1),
762 batch::inner(
noop(phantom), ledSeq),
763 batch::sig(Reg{phantom, carol}),
770 auto const ledSeq = env.current()->seq();
771 auto const seq = env.seq(alice);
774 batch::inner(
pay(alice, bob,
XRP(1000)), seq + 1),
775 batch::inner(
noop(bob), ledSeq),
776 batch::sig(Reg{bob, carol}),
784 auto const seq = env.seq(alice);
787 batch::inner(
pay(alice, bob,
XRP(1)), seq + 1),
788 batch::inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
789 batch::sig(Reg{bob, carol}),
796 auto const seq = env.seq(alice);
799 batch::inner(
pay(alice, bob,
XRP(1)), seq + 1),
800 batch::inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
810 auto const seq = env.seq(alice);
813 batch::inner(
pay(alice, bob,
XRP(1)), seq + 1),
814 batch::inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
824 testcase(
"bad raw txn");
826 using namespace test::jtx;
831 auto const alice =
Account(
"alice");
832 auto const bob =
Account(
"bob");
834 env.fund(
XRP(10000), alice, bob);
838 auto const batchFee = batch::calcBatchFee(env, 1, 2);
839 auto const seq = env.
seq(alice);
841 tx1.removeMember(jss::TransactionType);
842 auto jt = env.jtnofill(
853 auto const batchFee = batch::calcBatchFee(env, 1, 2);
854 auto const seq = env.
seq(alice);
856 tx1.removeMember(jss::Account);
857 auto jt = env.jtnofill(
868 auto const batchFee = batch::calcBatchFee(env, 1, 2);
869 auto const seq = env.
seq(alice);
871 tx1.removeMember(jss::Sequence);
872 auto jt = env.jtnofill(
883 auto const batchFee = batch::calcBatchFee(env, 1, 2);
884 auto const seq = env.
seq(alice);
886 tx1.removeMember(jss::Fee);
887 auto jt = env.jtnofill(
898 auto const batchFee = batch::calcBatchFee(env, 1, 2);
899 auto const seq = env.
seq(alice);
901 tx1.removeMember(jss::SigningPubKey);
902 auto jt = env.jtnofill(
915 testcase(
"bad sequence");
917 using namespace test::jtx;
922 auto const alice =
Account(
"alice");
923 auto const bob =
Account(
"bob");
925 auto const USD = gw[
"USD"];
927 env.fund(
XRP(10000), alice, bob, gw);
929 env.trust(USD(1000), alice, bob);
930 env(pay(gw, alice, USD(100)));
931 env(pay(gw, bob, USD(100)));
939 auto const preAliceSeq = env.seq(alice);
940 auto const preAlice = env.balance(alice);
941 auto const preAliceUSD = env.balance(alice, USD.issue());
942 auto const preBobSeq = env.seq(bob);
943 auto const preBob = env.balance(bob);
944 auto const preBobUSD = env.balance(bob, USD.issue());
946 auto const batchFee = batch::calcBatchFee(env, 1, 2);
947 auto const [txIDs, batchID] = submitBatch(
960 validateClosedLedger(env, testCases);
967 validateClosedLedger(env, testCases);
971 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
972 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
973 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
974 BEAST_EXPECT(env.seq(bob) == preBobSeq);
975 BEAST_EXPECT(env.balance(bob) == preBob);
976 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
981 auto const preAliceSeq = env.seq(alice);
982 auto const preAlice = env.balance(alice);
983 auto const preAliceUSD = env.balance(alice, USD.issue());
984 auto const preBobSeq = env.seq(bob);
985 auto const preBob = env.balance(bob);
986 auto const preBobUSD = env.balance(bob, USD.issue());
988 auto const batchFee = batch::calcBatchFee(env, 1, 2);
989 auto const [txIDs, batchID] = submitBatch(
1002 validateClosedLedger(env, testCases);
1009 validateClosedLedger(env, testCases);
1013 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1014 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1015 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1016 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1017 BEAST_EXPECT(env.balance(bob) == preBob);
1018 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1023 auto const preAliceSeq = env.seq(alice);
1024 auto const preAlice = env.balance(alice);
1025 auto const preAliceUSD = env.balance(alice, USD.issue());
1026 auto const preBobSeq = env.seq(bob);
1027 auto const preBob = env.balance(bob);
1028 auto const preBobUSD = env.balance(bob, USD.issue());
1030 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1031 auto const [txIDs, batchID] = submitBatch(
1044 validateClosedLedger(env, testCases);
1051 validateClosedLedger(env, testCases);
1055 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1056 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1057 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1058 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1059 BEAST_EXPECT(env.balance(bob) == preBob);
1060 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1065 auto const preAliceSeq = env.seq(alice);
1066 auto const preAlice = env.balance(alice);
1067 auto const preAliceUSD = env.balance(alice, USD.issue());
1068 auto const preBobSeq = env.seq(bob);
1069 auto const preBob = env.balance(bob);
1070 auto const preBobUSD = env.balance(bob, USD.issue());
1072 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1073 auto const [txIDs, batchID] = submitBatch(
1086 validateClosedLedger(env, testCases);
1093 validateClosedLedger(env, testCases);
1097 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1098 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1099 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1100 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1101 BEAST_EXPECT(env.balance(bob) == preBob);
1102 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1107 auto const preAliceSeq = env.seq(alice);
1108 auto const preAlice = env.balance(alice);
1109 auto const preAliceUSD = env.balance(alice, USD.issue());
1110 auto const preBobSeq = env.seq(bob);
1111 auto const preBob = env.balance(bob);
1112 auto const preBobUSD = env.balance(bob, USD.issue());
1114 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1115 auto const [txIDs, batchID] = submitBatch(
1128 validateClosedLedger(env, testCases);
1135 validateClosedLedger(env, testCases);
1139 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1140 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1141 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1142 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1143 BEAST_EXPECT(env.balance(bob) == preBob);
1144 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1151 testcase(
"bad outer fee");
1153 using namespace test::jtx;
1160 auto const alice =
Account(
"alice");
1161 auto const bob =
Account(
"bob");
1162 env.fund(
XRP(10000), alice, bob);
1169 auto const batchFee = batch::calcBatchFee(env, 0, 1);
1170 auto const aliceSeq = env.seq(alice);
1182 auto const alice =
Account(
"alice");
1183 auto const bob =
Account(
"bob");
1184 auto const carol =
Account(
"carol");
1185 env.fund(
XRP(10000), alice, bob, carol);
1191 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
1195 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1196 auto const aliceSeq = env.seq(alice);
1209 auto const alice =
Account(
"alice");
1210 auto const bob =
Account(
"bob");
1211 auto const carol =
Account(
"carol");
1212 env.fund(
XRP(10000), alice, bob, carol);
1218 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
1222 auto const batchFee = batch::calcBatchFee(env, 2, 2);
1223 auto const aliceSeq = env.seq(alice);
1224 auto const bobSeq = env.seq(bob);
1238 auto const alice =
Account(
"alice");
1239 auto const bob =
Account(
"bob");
1240 auto const carol =
Account(
"carol");
1241 env.fund(
XRP(10000), alice, bob, carol);
1247 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
1250 env(signers(bob, 2, {{alice, 1}, {carol, 1}}));
1254 auto const batchFee = batch::calcBatchFee(env, 3, 2);
1255 auto const aliceSeq = env.seq(alice);
1256 auto const bobSeq = env.seq(bob);
1270 auto const alice =
Account(
"alice");
1271 auto const bob =
Account(
"bob");
1272 env.fund(
XRP(10000), alice, bob);
1279 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1280 auto const aliceSeq = env.seq(alice);
1281 auto const bobSeq = env.seq(bob);
1294 auto const alice =
Account(
"alice");
1295 auto const bob =
Account(
"bob");
1296 auto const gw =
Account(
"gw");
1297 auto const USD = gw[
"USD"];
1299 env.fund(
XRP(10000), alice, bob, gw);
1301 auto const ammCreate =
1304 jv[jss::Account] = alice.human();
1307 jv[jss::TradingFee] = 0;
1308 jv[jss::TransactionType] = jss::AMMCreate;
1312 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1313 auto const seq = env.
seq(alice);
1325 testcase(
"calculate base fee");
1327 using namespace test::jtx;
1334 auto const alice =
Account(
"alice");
1335 auto const bob =
Account(
"bob");
1336 env.fund(
XRP(10000), alice, bob);
1339 auto const batchFee = batch::calcBatchFee(env, 0, 9);
1340 auto const aliceSeq = env.seq(alice);
1359 auto const alice =
Account(
"alice");
1360 auto const bob =
Account(
"bob");
1361 env.fund(
XRP(10000), alice, bob);
1364 auto const batchFee = batch::calcBatchFee(env, 0, 9);
1365 auto const aliceSeq = env.seq(alice);
1366 auto jt = env.jtnofill(
1378 env.app().openLedger().modify(
1384 return result.applied;
1392 auto const alice =
Account(
"alice");
1393 auto const bob =
Account(
"bob");
1394 env.fund(
XRP(10000), alice, bob);
1397 auto const aliceSeq = env.seq(alice);
1398 auto const batchFee = batch::calcBatchFee(env, 9, 2);
1402 batch::sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob),
1411 auto const alice =
Account(
"alice");
1412 auto const bob =
Account(
"bob");
1413 env.fund(
XRP(10000), alice, bob);
1416 auto const batchFee = batch::calcBatchFee(env, 0, 9);
1417 auto const aliceSeq = env.seq(alice);
1418 auto jt = env.jtnofill(
1422 batch::sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob));
1424 env.app().openLedger().modify(
1430 return result.applied;
1438 testcase(
"all or nothing");
1440 using namespace test::jtx;
1445 auto const alice =
Account(
"alice");
1446 auto const bob =
Account(
"bob");
1447 auto const gw =
Account(
"gw");
1448 auto const USD = gw[
"USD"];
1449 env.fund(
XRP(10000), alice, bob, gw);
1454 auto const preAlice = env.balance(alice);
1455 auto const preBob = env.balance(bob);
1457 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1458 auto const seq = env.
seq(alice);
1459 auto const [txIDs, batchID] = submitBatch(
1469 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1470 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1472 validateClosedLedger(env, testCases);
1475 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
1478 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
1479 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
1484 auto const preAlice = env.balance(alice);
1485 auto const preBob = env.balance(bob);
1487 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1488 auto const seq = env.
seq(alice);
1490 auto const [txIDs, batchID] = submitBatch(
1502 validateClosedLedger(env, testCases);
1505 BEAST_EXPECT(env.seq(alice) ==
seq + 1);
1508 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1509 BEAST_EXPECT(env.balance(bob) == preBob);
1514 auto const preAlice = env.balance(alice);
1515 auto const preBob = env.balance(bob);
1517 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1518 auto const seq = env.
seq(alice);
1519 auto const [txIDs, batchID] = submitBatch(
1531 validateClosedLedger(env, testCases);
1534 BEAST_EXPECT(env.seq(alice) ==
seq + 1);
1537 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1538 BEAST_EXPECT(env.balance(bob) == preBob);
1543 auto const preAlice = env.balance(alice);
1544 auto const preBob = env.balance(bob);
1546 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1547 auto const seq = env.
seq(alice);
1548 auto const [txIDs, batchID] = submitBatch(
1560 validateClosedLedger(env, testCases);
1563 BEAST_EXPECT(env.seq(alice) ==
seq + 1);
1566 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1567 BEAST_EXPECT(env.balance(bob) == preBob);
1574 testcase(
"only one");
1576 using namespace test::jtx;
1581 auto const alice =
Account(
"alice");
1582 auto const bob =
Account(
"bob");
1583 auto const carol =
Account(
"carol");
1584 auto const dave =
Account(
"dave");
1585 auto const gw =
Account(
"gw");
1586 auto const USD = gw[
"USD"];
1587 env.fund(
XRP(10000), alice, bob, carol, dave, gw);
1592 auto const preAlice = env.balance(alice);
1593 auto const preBob = env.balance(bob);
1595 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1596 auto const seq = env.
seq(alice);
1597 auto const [txIDs, batchID] = submitBatch(
1611 {1,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[0], batchID},
1612 {2,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[1], batchID},
1613 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
1615 validateClosedLedger(env, testCases);
1618 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
1621 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1622 BEAST_EXPECT(env.balance(bob) == preBob);
1627 auto const preAlice = env.balance(alice);
1628 auto const preBob = env.balance(bob);
1630 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1631 auto const seq = env.
seq(alice);
1632 auto const [txIDs, batchID] = submitBatch(
1644 {1,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[0], batchID},
1645 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1647 validateClosedLedger(env, testCases);
1650 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
1653 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
1654 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1659 auto const preAlice = env.balance(alice);
1660 auto const preBob = env.balance(bob);
1662 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1663 auto const seq = env.
seq(alice);
1664 auto const [txIDs, batchID] = submitBatch(
1676 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1678 validateClosedLedger(env, testCases);
1681 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1684 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
1685 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1690 auto const preAlice = env.balance(alice);
1691 auto const preBob = env.balance(bob);
1693 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1694 auto const seq = env.
seq(alice);
1695 auto const [txIDs, batchID] = submitBatch(
1707 {1,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1709 validateClosedLedger(env, testCases);
1712 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1715 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(1));
1716 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1721 auto const preAlice = env.balance(alice);
1722 auto const preBob = env.balance(bob);
1724 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1725 auto const seq = env.
seq(alice);
1726 auto const [txIDs, batchID] = submitBatch(
1738 {1,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1740 validateClosedLedger(env, testCases);
1743 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1746 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(1));
1747 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1752 auto const preAlice = env.balance(alice);
1753 auto const preBob = env.balance(bob);
1754 auto const preCarol = env.balance(carol);
1755 auto const seq = env.
seq(alice);
1756 auto const batchFee = batch::calcBatchFee(env, 0, 6);
1758 auto const [txIDs, batchID] = submitBatch(
1790 {1,
"OfferCreate",
"tecKILLED", txIDs[0], batchID},
1791 {2,
"OfferCreate",
"tecKILLED", txIDs[1], batchID},
1792 {3,
"OfferCreate",
"tecKILLED", txIDs[2], batchID},
1793 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
1795 validateClosedLedger(env, testCases);
1797 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(100) - batchFee);
1798 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(100));
1799 BEAST_EXPECT(env.balance(carol) == preCarol);
1806 testcase(
"until failure");
1808 using namespace test::jtx;
1813 auto const alice =
Account(
"alice");
1814 auto const bob =
Account(
"bob");
1815 auto const carol =
Account(
"carol");
1816 auto const dave =
Account(
"dave");
1817 auto const gw =
Account(
"gw");
1818 auto const USD = gw[
"USD"];
1819 env.fund(
XRP(10000), alice, bob, carol, dave, gw);
1824 auto const preAlice = env.balance(alice);
1825 auto const preBob = env.balance(bob);
1827 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1828 auto const seq = env.
seq(alice);
1829 auto const [txIDs, batchID] = submitBatch(
1842 {1,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[0], batchID},
1844 validateClosedLedger(env, testCases);
1847 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1850 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1851 BEAST_EXPECT(env.balance(bob) == preBob);
1856 auto const preAlice = env.balance(alice);
1857 auto const preBob = env.balance(bob);
1859 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1860 auto const seq = env.
seq(alice);
1861 auto const [txIDs, batchID] = submitBatch(
1873 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1874 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1875 {3,
"Payment",
"tesSUCCESS", txIDs[2], batchID},
1876 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
1878 validateClosedLedger(env, testCases);
1881 BEAST_EXPECT(env.seq(alice) ==
seq + 5);
1884 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(10) - batchFee);
1885 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(10));
1890 auto const preAlice = env.balance(alice);
1891 auto const preBob = env.balance(bob);
1893 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1894 auto const seq = env.
seq(alice);
1895 auto const [txIDs, batchID] = submitBatch(
1908 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1909 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1910 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
1912 validateClosedLedger(env, testCases);
1915 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
1918 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
1919 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
1924 auto const preAlice = env.balance(alice);
1925 auto const preBob = env.balance(bob);
1927 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1928 auto const seq = env.
seq(alice);
1929 auto const [txIDs, batchID] = submitBatch(
1942 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1943 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1945 validateClosedLedger(env, testCases);
1948 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
1951 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
1952 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
1957 auto const preAlice = env.balance(alice);
1958 auto const preBob = env.balance(bob);
1960 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1961 auto const seq = env.
seq(alice);
1962 auto const [txIDs, batchID] = submitBatch(
1975 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1976 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1978 validateClosedLedger(env, testCases);
1981 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
1984 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
1985 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
1990 auto const preAlice = env.balance(alice);
1991 auto const preBob = env.balance(bob);
1992 auto const preCarol = env.balance(carol);
1993 auto const seq = env.
seq(alice);
1994 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1995 auto const [txIDs, batchID] = submitBatch(
2013 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2014 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2015 {3,
"OfferCreate",
"tecKILLED", txIDs[2], batchID},
2017 validateClosedLedger(env, testCases);
2019 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(200) - batchFee);
2020 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(100));
2021 BEAST_EXPECT(env.balance(carol) == preCarol +
XRP(100));
2028 testcase(
"independent");
2030 using namespace test::jtx;
2035 auto const alice =
Account(
"alice");
2036 auto const bob =
Account(
"bob");
2037 auto const carol =
Account(
"carol");
2038 auto const gw =
Account(
"gw");
2039 auto const USD = gw[
"USD"];
2040 env.fund(
XRP(10000), alice, bob, carol, gw);
2045 auto const preAlice = env.balance(alice);
2046 auto const preBob = env.balance(bob);
2048 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2049 auto const seq = env.
seq(alice);
2050 auto const [txIDs, batchID] = submitBatch(
2064 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2065 {2,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[1], batchID},
2066 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
2067 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2069 validateClosedLedger(env, testCases);
2072 BEAST_EXPECT(env.seq(alice) ==
seq + 5);
2075 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(4) - batchFee);
2076 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(4));
2081 auto const preAlice = env.balance(alice);
2082 auto const preBob = env.balance(bob);
2084 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2085 auto const seq = env.
seq(alice);
2086 auto const [txIDs, batchID] = submitBatch(
2099 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2100 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2101 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
2102 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2104 validateClosedLedger(env, testCases);
2107 BEAST_EXPECT(env.seq(alice) ==
seq + 5);
2110 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(6) - batchFee);
2111 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(6));
2116 auto const preAlice = env.balance(alice);
2117 auto const preBob = env.balance(bob);
2119 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2120 auto const seq = env.
seq(alice);
2121 auto const [txIDs, batchID] = submitBatch(
2134 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2135 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2136 {3,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2138 validateClosedLedger(env, testCases);
2141 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
2144 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(6));
2145 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(6));
2150 auto const preAlice = env.balance(alice);
2151 auto const preBob = env.balance(bob);
2153 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2154 auto const seq = env.
seq(alice);
2155 auto const [txIDs, batchID] = submitBatch(
2168 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2169 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2170 {3,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2172 validateClosedLedger(env, testCases);
2175 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
2178 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(6));
2179 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(6));
2184 auto const preAlice = env.balance(alice);
2185 auto const preBob = env.balance(bob);
2186 auto const preCarol = env.balance(carol);
2187 auto const seq = env.
seq(alice);
2188 auto const batchFee = batch::calcBatchFee(env, 0, 3);
2189 auto const [txIDs, batchID] = submitBatch(
2206 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2207 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2208 {3,
"OfferCreate",
"tecKILLED", txIDs[2], batchID},
2210 validateClosedLedger(env, testCases);
2212 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(200) - batchFee);
2213 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(100));
2214 BEAST_EXPECT(env.balance(carol) == preCarol +
XRP(100));
2221 testcase(
"inner submit rpc");
2223 using namespace test::jtx;
2228 auto const alice =
Account(
"alice");
2229 auto const bob =
Account(
"bob");
2231 env.fund(
XRP(10000), alice, bob);
2234 auto submitAndValidate = [&](
Slice const&
slice) {
2235 auto const jrr = env.rpc(
"submit",
strHex(
slice))[jss::result];
2237 jrr[jss::status] ==
"error" &&
2238 jrr[jss::error] ==
"invalidTransaction" &&
2239 jrr[jss::error_exception] ==
2240 "fails local checks: Malformed: Invalid inner batch "
2252 txn[sfTxnSignature] =
"DEADBEEF";
2256 submitAndValidate(s.
slice());
2266 txn[sfSigningPubKey] =
strHex(alice.pk());
2270 submitAndValidate(s.
slice());
2284 submitAndValidate(s.
slice());
2297 auto const jrr = env.rpc(
"submit",
strHex(s.
slice()))[jss::result];
2299 jrr[jss::status] ==
"success" &&
2300 jrr[jss::engine_result] ==
"temINVALID_FLAG");
2309 testcase(
"account activation");
2311 using namespace test::jtx;
2316 auto const alice =
Account(
"alice");
2317 auto const bob =
Account(
"bob");
2318 env.fund(
XRP(10000), alice);
2322 auto const preAlice = env.balance(alice);
2323 auto const ledSeq = env.current()->seq();
2324 auto const seq = env.
seq(alice);
2325 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2326 auto const [txIDs, batchID] = submitBatch(
2337 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2338 {2,
"AccountSet",
"tesSUCCESS", txIDs[1], batchID},
2340 validateClosedLedger(env, testCases);
2343 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
2346 BEAST_EXPECT(env.seq(bob) == ledSeq + 1);
2349 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - batchFee);
2350 BEAST_EXPECT(env.balance(bob) ==
XRP(1000));
2356 testcase(
"account set");
2358 using namespace test::jtx;
2363 auto const alice =
Account(
"alice");
2364 auto const bob =
Account(
"bob");
2365 env.fund(
XRP(10000), alice, bob);
2368 auto const preAlice = env.balance(alice);
2369 auto const preBob = env.balance(bob);
2371 auto const seq = env.
seq(alice);
2372 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2376 auto const [txIDs, batchID] = submitBatch(
2386 {1,
"AccountSet",
"tesSUCCESS", txIDs[0], batchID},
2387 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2389 validateClosedLedger(env, testCases);
2397 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
2400 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
2401 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
2407 testcase(
"account delete");
2409 using namespace test::jtx;
2416 auto const alice =
Account(
"alice");
2417 auto const bob =
Account(
"bob");
2418 env.fund(
XRP(10000), alice, bob);
2422 for (
int i = 0; i < 5; ++i)
2425 auto const preAlice = env.balance(alice);
2426 auto const preBob = env.balance(bob);
2428 auto const seq = env.
seq(alice);
2429 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
2430 env.current()->fees().increment;
2431 auto const [txIDs, batchID] = submitBatch(
2443 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2444 {2,
"AccountDelete",
"tesSUCCESS", txIDs[1], batchID},
2446 validateClosedLedger(env, testCases);
2450 BEAST_EXPECT(env.balance(bob) == preBob + (preAlice - batchFee));
2457 auto const alice =
Account(
"alice");
2458 auto const bob =
Account(
"bob");
2459 env.fund(
XRP(10000), alice, bob);
2463 for (
int i = 0; i < 5; ++i)
2466 auto const preAlice = env.balance(alice);
2467 auto const preBob = env.balance(bob);
2469 env.trust(bob[
"USD"](1000), alice);
2472 auto const seq = env.
seq(alice);
2473 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
2474 env.current()->fees().increment;
2475 auto const [txIDs, batchID] = submitBatch(
2487 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2488 {2,
"AccountDelete",
"tecHAS_OBLIGATIONS", txIDs[1], batchID},
2489 {3,
"Payment",
"tesSUCCESS", txIDs[2], batchID},
2491 validateClosedLedger(env, testCases);
2495 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2502 auto const alice =
Account(
"alice");
2503 auto const bob =
Account(
"bob");
2504 env.fund(
XRP(10000), alice, bob);
2508 for (
int i = 0; i < 5; ++i)
2511 auto const preAlice = env.balance(alice);
2512 auto const preBob = env.balance(bob);
2514 auto const seq = env.
seq(alice);
2515 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
2516 env.current()->fees().increment;
2517 auto const [txIDs, batchID] = submitBatch(
2530 validateClosedLedger(env, testCases);
2534 BEAST_EXPECT(env.balance(bob) == preBob);
2541 testcase(
"object create w/ sequence");
2543 using namespace test::jtx;
2548 auto const alice =
Account(
"alice");
2549 auto const bob =
Account(
"bob");
2550 auto const gw =
Account(
"gw");
2551 auto const USD = gw[
"USD"];
2553 env.fund(
XRP(10000), alice, bob, gw);
2556 env.trust(USD(1000), alice, bob);
2557 env(pay(gw, alice, USD(100)));
2558 env(pay(gw, bob, USD(100)));
2563 auto const aliceSeq = env.seq(alice);
2564 auto const bobSeq = env.seq(bob);
2565 auto const preAlice = env.balance(alice);
2566 auto const preBob = env.balance(bob);
2567 auto const preAliceUSD = env.balance(alice, USD.issue());
2568 auto const preBobUSD = env.balance(bob, USD.issue());
2570 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2571 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
2572 auto const [txIDs, batchID] = submitBatch(
2576 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
2577 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
2583 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
2584 {2,
"CheckCash",
"tesSUCCESS", txIDs[1], batchID},
2586 validateClosedLedger(env, testCases);
2589 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2592 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
2595 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
2596 BEAST_EXPECT(env.balance(bob) == preBob);
2600 env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
2601 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
2609 auto const aliceSeq = env.seq(alice);
2610 auto const bobSeq = env.seq(bob);
2611 auto const preAlice = env.balance(alice);
2612 auto const preBob = env.balance(bob);
2613 auto const preAliceUSD = env.balance(alice, USD.issue());
2614 auto const preBobUSD = env.balance(bob, USD.issue());
2616 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2617 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
2618 auto const [txIDs, batchID] = submitBatch(
2623 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
2624 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
2630 {1,
"CheckCreate",
"tecDST_TAG_NEEDED", txIDs[0], batchID},
2631 {2,
"CheckCash",
"tecNO_ENTRY", txIDs[1], batchID},
2633 validateClosedLedger(env, testCases);
2636 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2639 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
2642 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
2643 BEAST_EXPECT(env.balance(bob) == preBob);
2646 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
2647 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
2654 testcase(
"object create w/ ticket");
2656 using namespace test::jtx;
2661 auto const alice =
Account(
"alice");
2662 auto const bob =
Account(
"bob");
2663 auto const gw =
Account(
"gw");
2664 auto const USD = gw[
"USD"];
2666 env.fund(
XRP(10000), alice, bob, gw);
2669 env.trust(USD(1000), alice, bob);
2670 env(pay(gw, alice, USD(100)));
2671 env(pay(gw, bob, USD(100)));
2674 auto const aliceSeq = env.seq(alice);
2675 auto const bobSeq = env.seq(bob);
2676 auto const preAlice = env.balance(alice);
2677 auto const preBob = env.balance(bob);
2678 auto const preAliceUSD = env.balance(alice, USD.issue());
2679 auto const preBobUSD = env.balance(bob, USD.issue());
2681 auto const batchFee = batch::calcBatchFee(env, 1, 3);
2682 uint256 const chkID{getCheckIndex(bob, bobSeq + 1)};
2683 auto const [txIDs, batchID] = submitBatch(
2688 batch::inner(check::create(bob, alice, USD(10)), 0, bobSeq + 1),
2689 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
2695 {1,
"TicketCreate",
"tesSUCCESS", txIDs[0], batchID},
2696 {2,
"CheckCreate",
"tesSUCCESS", txIDs[1], batchID},
2697 {3,
"CheckCash",
"tesSUCCESS", txIDs[2], batchID},
2699 validateClosedLedger(env, testCases);
2701 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2702 BEAST_EXPECT(env.seq(bob) == bobSeq + 10 + 1);
2703 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
2704 BEAST_EXPECT(env.balance(bob) == preBob);
2705 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
2706 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
2712 testcase(
"object create w/ 3rd party");
2714 using namespace test::jtx;
2719 auto const alice =
Account(
"alice");
2720 auto const bob =
Account(
"bob");
2721 auto const carol =
Account(
"carol");
2722 auto const gw =
Account(
"gw");
2723 auto const USD = gw[
"USD"];
2725 env.fund(
XRP(10000), alice, bob, carol, gw);
2728 env.trust(USD(1000), alice, bob);
2729 env(pay(gw, alice, USD(100)));
2730 env(pay(gw, bob, USD(100)));
2733 auto const aliceSeq = env.seq(alice);
2734 auto const bobSeq = env.seq(bob);
2735 auto const carolSeq = env.seq(carol);
2736 auto const preAlice = env.balance(alice);
2737 auto const preBob = env.balance(bob);
2738 auto const preCarol = env.balance(carol);
2739 auto const preAliceUSD = env.balance(alice, USD.issue());
2740 auto const preBobUSD = env.balance(bob, USD.issue());
2742 auto const batchFee = batch::calcBatchFee(env, 2, 2);
2743 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
2744 auto const [txIDs, batchID] = submitBatch(
2748 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
2749 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq),
2755 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
2756 {2,
"CheckCash",
"tesSUCCESS", txIDs[1], batchID},
2758 validateClosedLedger(env, testCases);
2760 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
2761 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
2762 BEAST_EXPECT(env.seq(carol) == carolSeq + 1);
2763 BEAST_EXPECT(env.balance(alice) == preAlice);
2764 BEAST_EXPECT(env.balance(bob) == preBob);
2765 BEAST_EXPECT(env.balance(carol) == preCarol - batchFee);
2766 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
2767 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
2774 testcase(
"tickets outer");
2776 using namespace test::jtx;
2781 auto const alice =
Account(
"alice");
2782 auto const bob =
Account(
"bob");
2784 env.fund(
XRP(10000), alice, bob);
2788 env(ticket::create(alice, 10));
2791 auto const aliceSeq = env.seq(alice);
2792 auto const preAlice = env.balance(alice);
2793 auto const preBob = env.balance(bob);
2795 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2796 auto const [txIDs, batchID] = submitBatch(
2807 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2808 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2810 validateClosedLedger(env, testCases);
2814 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 9);
2815 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 9);
2817 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2818 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2819 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2823 testcase(
"tickets inner");
2825 using namespace test::jtx;
2830 auto const alice =
Account(
"alice");
2831 auto const bob =
Account(
"bob");
2833 env.fund(
XRP(10000), alice, bob);
2837 env(ticket::create(alice, 10));
2840 auto const aliceSeq = env.seq(alice);
2841 auto const preAlice = env.balance(alice);
2842 auto const preBob = env.balance(bob);
2844 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2845 auto const [txIDs, batchID] = submitBatch(
2855 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2856 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2858 validateClosedLedger(env, testCases);
2862 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
2863 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
2865 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
2866 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2867 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2871 testcase(
"tickets outer inner");
2873 using namespace test::jtx;
2878 auto const alice =
Account(
"alice");
2879 auto const bob =
Account(
"bob");
2881 env.fund(
XRP(10000), alice, bob);
2885 env(ticket::create(alice, 10));
2888 auto const aliceSeq = env.seq(alice);
2889 auto const preAlice = env.balance(alice);
2890 auto const preBob = env.balance(bob);
2892 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2893 auto const [txIDs, batchID] = submitBatch(
2904 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2905 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2907 validateClosedLedger(env, testCases);
2911 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
2912 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
2914 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
2915 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2916 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2923 testcase(
"sequence open ledger");
2925 using namespace test::jtx;
2928 auto const alice =
Account(
"alice");
2929 auto const bob =
Account(
"bob");
2930 auto const carol =
Account(
"carol");
2940 env.fund(
XRP(10000), alice, bob, carol);
2943 auto const aliceSeq = env.seq(alice);
2944 auto const carolSeq = env.seq(carol);
2947 auto const noopTxn = env.jt(
noop(alice),
seq(aliceSeq + 2));
2948 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
2952 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2953 auto const [txIDs, batchID] = submitBatch(
2965 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2966 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2968 validateClosedLedger(env, testCases);
2975 {0,
"AccountSet",
"tesSUCCESS", noopTxnID,
std::nullopt},
2977 validateClosedLedger(env, testCases);
2987 env.fund(
XRP(10000), alice, bob);
2990 auto const aliceSeq = env.seq(alice);
2993 auto const noopTxn = env.jt(
noop(alice),
seq(aliceSeq + 1));
2997 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2998 auto const [txIDs, batchID] = submitBatch(
3009 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3010 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3012 validateClosedLedger(env, testCases);
3019 validateClosedLedger(env, testCases);
3029 env.fund(
XRP(10000), alice, bob);
3032 auto const aliceSeq = env.seq(alice);
3033 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3034 auto const [txIDs, batchID] = submitBatch(
3041 auto const noopTxn = env.jt(
noop(alice),
seq(aliceSeq + 1));
3042 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3049 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3050 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3052 validateClosedLedger(env, testCases);
3059 validateClosedLedger(env, testCases);
3066 env.fund(
XRP(10000), alice, bob, carol);
3069 auto const aliceSeq = env.seq(alice);
3070 auto const carolSeq = env.seq(carol);
3073 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3074 auto const [txIDs, batchID] = submitBatch(
3083 auto const noopTxn = env.jt(
noop(carol),
seq(carolSeq));
3084 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3090 {0,
"AccountSet",
"tesSUCCESS", noopTxnID,
std::nullopt},
3092 {2,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3093 {3,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3095 validateClosedLedger(env, testCases);
3102 validateClosedLedger(env, testCases);
3110 testcase(
"tickets open ledger");
3112 using namespace test::jtx;
3115 auto const alice =
Account(
"alice");
3116 auto const bob =
Account(
"bob");
3124 env.fund(
XRP(10000), alice, bob);
3128 env(ticket::create(alice, 10));
3131 auto const aliceSeq = env.seq(alice);
3134 auto const noopTxn =
3136 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3140 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3141 auto const [txIDs, batchID] = submitBatch(
3153 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3154 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3156 validateClosedLedger(env, testCases);
3163 validateClosedLedger(env, testCases);
3173 env.fund(
XRP(10000), alice, bob);
3177 env(ticket::create(alice, 10));
3180 auto const aliceSeq = env.seq(alice);
3183 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3184 auto const [txIDs, batchID] = submitBatch(
3193 auto const noopTxn =
3201 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3202 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3204 validateClosedLedger(env, testCases);
3211 validateClosedLedger(env, testCases);
3219 testcase(
"objects open ledger");
3221 using namespace test::jtx;
3224 auto const alice =
Account(
"alice");
3225 auto const bob =
Account(
"bob");
3235 env.fund(
XRP(10000), alice, bob);
3239 env(ticket::create(alice, 10));
3242 auto const aliceSeq = env.seq(alice);
3245 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
3246 auto const objTxn = env.jt(check::cash(bob, chkID,
XRP(10)));
3247 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
3251 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3252 auto const [txIDs, batchID] = submitBatch(
3264 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
3265 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3266 {3,
"CheckCash",
"tesSUCCESS", objTxnID,
std::nullopt},
3268 validateClosedLedger(env, testCases);
3275 validateClosedLedger(env, testCases);
3282 env.fund(
XRP(10000), alice, bob);
3286 env(ticket::create(alice, 10));
3289 auto const aliceSeq = env.seq(alice);
3290 auto const bobSeq = env.seq(bob);
3293 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
3294 auto const objTxn = env.jt(check::create(alice, bob,
XRP(10)));
3295 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
3299 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3300 auto const [txIDs, batchID] = submitBatch(
3312 {0,
"CheckCreate",
"tesSUCCESS", objTxnID,
std::nullopt},
3314 {2,
"CheckCash",
"tesSUCCESS", txIDs[0], batchID},
3315 {3,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3317 validateClosedLedger(env, testCases);
3329 env.fund(
XRP(10000), alice, bob);
3333 env(ticket::create(alice, 10));
3336 auto const aliceSeq = env.seq(alice);
3339 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3340 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
3341 auto const [txIDs, batchID] = submitBatch(
3350 auto const objTxn = env.jt(check::cash(bob, chkID,
XRP(10)));
3351 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
3358 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
3359 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3360 {3,
"CheckCash",
"tesSUCCESS", objTxnID,
std::nullopt},
3362 validateClosedLedger(env, testCases);
3370 testcase(
"pseudo txn with tfInnerBatchTxn");
3372 using namespace test::jtx;
3377 auto const alice =
Account(
"alice");
3378 auto const bob =
Account(
"bob");
3379 env.fund(
XRP(10000), alice, bob);
3382 STTx const stx =
STTx(ttAMENDMENT, [&](
auto& obj) {
3383 obj.setAccountID(sfAccount,
AccountID());
3384 obj.setFieldH256(sfAmendment,
uint256(2));
3385 obj.setFieldU32(sfLedgerSequence, env.seq(alice));
3392 BEAST_EXPECT(reason ==
"Cannot submit pseudo transactions.");
3396 return result.applied;
3403 testcase(
"batch open ledger");
3411 using namespace test::jtx;
3415 XRPAmount const baseFee = env.current()->fees().base;
3417 auto const alice =
Account(
"alice");
3418 auto const bob =
Account(
"bob");
3420 env.fund(
XRP(10000), alice, bob);
3426 auto const aliceSeq = env.seq(alice);
3427 auto const preAlice = env.balance(alice);
3428 auto const preBob = env.balance(bob);
3429 auto const bobSeq = env.seq(bob);
3432 auto const payTxn1 = env.jt(pay(alice, bob,
XRP(10)),
seq(aliceSeq));
3433 auto const payTxn1ID =
to_string(payTxn1.stx->getTransactionID());
3437 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3438 auto const [txIDs, batchID] = submitBatch(
3447 auto const payTxn2 = env.jt(pay(bob, alice,
XRP(5)),
seq(bobSeq + 1));
3448 auto const payTxn2ID =
to_string(payTxn2.stx->getTransactionID());
3455 {2,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3456 {3,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3458 validateClosedLedger(env, testCases);
3466 validateClosedLedger(env, testCases);
3470 BEAST_EXPECT(env.seq(alice) == aliceSeq + 3);
3473 BEAST_EXPECT(env.seq(bob) == bobSeq + 2);
3477 env.balance(alice) == preAlice -
XRP(10) - batchFee - baseFee);
3478 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(10) - baseFee);
3484 testcase(
"batch tx queue");
3486 using namespace test::jtx;
3493 makeSmallQueueConfig(
3494 {{
"minimum_txn_in_ledger_standalone",
"2"}}),
3498 auto alice =
Account(
"alice");
3500 auto carol =
Account(
"carol");
3504 env.close(env.now() + 5s, 10000ms);
3506 env.close(env.now() + 5s, 10000ms);
3517 auto const aliceSeq = env.seq(alice);
3518 auto const bobSeq = env.seq(bob);
3519 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3537 openLedgerFee(env, batchFee),
3553 makeSmallQueueConfig(
3554 {{
"minimum_txn_in_ledger_standalone",
"2"}}),
3558 auto alice =
Account(
"alice");
3560 auto carol =
Account(
"carol");
3564 env.close(env.now() + 5s, 10000ms);
3566 env.close(env.now() + 5s, 10000ms);
3573 auto const aliceSeq = env.seq(alice);
3574 auto const bobSeq = env.seq(bob);
3575 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3596 testcase(
"batch network ops");
3598 using namespace test::jtx;
3608 auto alice =
Account(
"alice");
3610 env.
fund(
XRP(10000), alice, bob);
3618 return jt.stx->getTransactionID();
3630 return transaction->getID();
3655 testcase(
"batch delegate");
3657 using namespace test::jtx;
3664 auto const alice =
Account(
"alice");
3665 auto const bob =
Account(
"bob");
3666 auto const gw =
Account(
"gw");
3667 auto const USD = gw[
"USD"];
3668 env.fund(
XRP(10000), alice, bob, gw);
3671 env(delegate::set(alice, bob, {
"Payment"}));
3674 auto const preAlice = env.balance(alice);
3675 auto const preBob = env.balance(bob);
3677 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3678 auto const seq = env.
seq(alice);
3681 tx[jss::Delegate] = bob.human();
3682 auto const [txIDs, batchID] = submitBatch(
3692 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3693 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3695 validateClosedLedger(env, testCases);
3698 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
3701 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
3702 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
3709 auto const alice =
Account(
"alice");
3710 auto const bob =
Account(
"bob");
3711 auto const carol =
Account(
"carol");
3712 auto const gw =
Account(
"gw");
3713 auto const USD = gw[
"USD"];
3714 env.fund(
XRP(10000), alice, bob, carol, gw);
3717 env(delegate::set(bob, carol, {
"Payment"}));
3720 auto const preAlice = env.balance(alice);
3721 auto const preBob = env.balance(bob);
3722 auto const preCarol = env.balance(carol);
3724 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3725 auto const aliceSeq = env.seq(alice);
3726 auto const bobSeq = env.seq(bob);
3729 tx[jss::Delegate] = carol.human();
3730 auto const [txIDs, batchID] = submitBatch(
3741 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3742 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3744 validateClosedLedger(env, testCases);
3746 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
3747 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
3748 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
3749 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
3752 BEAST_EXPECT(env.balance(carol) == preCarol);
3761 auto const alice =
Account(
"alice");
3762 auto const bob =
Account(
"bob");
3763 auto const gw =
Account(
"gw");
3764 auto const USD = gw[
"USD"];
3765 env.fund(
XRP(10000), alice, bob, gw);
3768 env(delegate::set(alice, bob, {
"AccountDomainSet"}));
3771 auto const preAlice = env.balance(alice);
3772 auto const preBob = env.balance(bob);
3774 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3775 auto const seq = env.
seq(alice);
3780 tx[jss::Delegate] = bob.human();
3781 auto const [txIDs, batchID] = submitBatch(
3791 {1,
"AccountSet",
"tesSUCCESS", txIDs[0], batchID},
3792 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3794 validateClosedLedger(env, testCases);
3797 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
3800 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(2) - batchFee);
3801 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(2));
3811 env.fund(
XRP(100000), alice, bob);
3814 auto const mptID =
makeMptID(env.seq(alice), alice);
3815 MPTTester mpt(env, alice, {.fund =
false});
3822 alice, bob, {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"}));
3825 auto const seq = env.
seq(alice);
3826 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3829 jv1[sfTransactionType] = jss::MPTokenIssuanceSet;
3830 jv1[sfAccount] = alice.human();
3831 jv1[sfDelegate] = bob.human();
3832 jv1[sfSequence] =
seq + 1;
3833 jv1[sfMPTokenIssuanceID] =
to_string(mptID);
3837 jv2[sfTransactionType] = jss::MPTokenIssuanceSet;
3838 jv2[sfAccount] = alice.human();
3839 jv2[sfDelegate] = bob.human();
3840 jv2[sfSequence] =
seq + 2;
3841 jv2[sfMPTokenIssuanceID] =
to_string(mptID);
3844 auto const [txIDs, batchID] = submitBatch(
3854 {1,
"MPTokenIssuanceSet",
"tesSUCCESS", txIDs[0], batchID},
3855 {2,
"MPTokenIssuanceSet",
"tesSUCCESS", txIDs[1], batchID},
3857 validateClosedLedger(env, testCases);
3868 env.fund(
XRP(10000), gw, alice, bob);
3871 env(trust(alice, gw[
"USD"](50)));
3875 gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
3878 auto const seq = env.
seq(gw);
3879 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3881 auto jv1 = trust(gw, gw[
"USD"](0), alice,
tfSetfAuth);
3882 jv1[sfDelegate] = bob.human();
3883 auto jv2 = trust(gw, gw[
"USD"](0), alice,
tfSetFreeze);
3884 jv2[sfDelegate] = bob.human();
3886 auto const [txIDs, batchID] = submitBatch(
3896 {1,
"TrustSet",
"tesSUCCESS", txIDs[0], batchID},
3897 {2,
"TrustSet",
"tesSUCCESS", txIDs[1], batchID},
3899 validateClosedLedger(env, testCases);
3908 env.fund(
XRP(10000), gw, alice, bob);
3911 env(trust(alice, gw[
"USD"](50)));
3915 gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
3918 auto const seq = env.
seq(gw);
3919 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3921 auto jv1 = trust(gw, gw[
"USD"](0), alice,
tfSetFreeze);
3922 jv1[sfDelegate] = bob.human();
3924 jv2[sfDelegate] = bob.human();
3926 auto const [txIDs, batchID] = submitBatch(
3937 {1,
"TrustSet",
"tesSUCCESS", txIDs[0], batchID},
3939 validateClosedLedger(env, testCases);
3949 testcase(
"Validate RPC response");
3951 using namespace jtx;
3955 env.
fund(
XRP(10000), alice, bob);
3960 auto const baseFee = env.
current()->fees().base;
3961 auto const aliceSeq = env.
seq(alice);
3962 auto jtx = env.
jt(pay(alice, bob,
XRP(1)));
3966 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
3969 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
3971 jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
3972 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
3974 jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
3975 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
3976 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
3977 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
3982 auto const baseFee = env.
current()->fees().base;
3983 auto const aliceSeq = env.
seq(alice);
3985 auto jtx = env.
jt(pay(alice, bob,
XRP(1)),
seq(aliceSeq));
3989 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
3992 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
3994 jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
3995 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
3997 jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
3998 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
3999 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
4000 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
4005 auto const baseFee = env.
current()->fees().base;
4006 auto const aliceSeq = env.
seq(alice);
4007 auto jtx = env.
jt(pay(alice, bob,
XRP(1)),
seq(aliceSeq + 1));
4011 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
4014 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
4016 jr[jss::account_sequence_available].asUInt() == aliceSeq);
4017 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
4018 BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq);
4019 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
4020 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
4021 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
4028 using namespace jtx;
4033 env.
fund(
XRP(10000), alice, bob, carol);
4044 auto const seq = env.
seq(alice);
4045 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
4051 XRPAmount const txBaseFee = getBaseFee(jtx);
4057 auto const seq = env.
seq(alice);
4058 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
4072 XRPAmount const txBaseFee = getBaseFee(jtx);
4078 auto const seq = env.
seq(alice);
4079 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
4096 XRPAmount const txBaseFee = getBaseFee(jtx);
4102 auto const seq = env.
seq(alice);
4103 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
4108 XRPAmount const txBaseFee = getBaseFee(jtx);
4109 BEAST_EXPECT(txBaseFee == batchFee);
4116 testEnable(features);
4117 testPreflight(features);
4118 testPreclaim(features);
4119 testBadRawTxn(features);
4120 testBadSequence(features);
4121 testBadOuterFee(features);
4122 testCalculateBaseFee(features);
4123 testAllOrNothing(features);
4124 testOnlyOne(features);
4125 testUntilFailure(features);
4126 testIndependent(features);
4127 testInnerSubmitRPC(features);
4128 testAccountActivation(features);
4129 testAccountSet(features);
4130 testAccountDelete(features);
4131 testObjectCreateSequence(features);
4132 testObjectCreateTicket(features);
4133 testObjectCreate3rdParty(features);
4134 testTickets(features);
4135 testSequenceOpenLedger(features);
4136 testTicketsOpenLedger(features);
4137 testObjectsOpenLedger(features);
4138 testPseudoTxn(features);
4139 testOpenLedger(features);
4140 testBatchTxQueue(features);
4141 testBatchNetworkOps(features);
4142 testBatchDelegate(features);
4143 testValidateRPCResponse(features);
4144 testBatchCalculateBaseFee(features);
4151 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
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Calculates the total base fee for a batch transaction.
HashRouterFlags 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 testBatchCalculateBaseFee(FeatureBitset features)
void testObjectCreate3rdParty(FeatureBitset features)
void testAccountActivation(FeatureBitset features)
Json::Value getLastLedger(jtx::Env &env)
void testValidateRPCResponse(FeatureBitset features)
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::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.
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)
void create(MPTCreate const &arg=MPTCreate{})
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
FeatureBitset testable_amendments()
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.
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 const tfMPTUnlock
bool set(T &target, std::string const &name, Section const §ion)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
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 tfClearFreeze
constexpr std::uint32_t const tfMPTLock
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 asfRequireAuth
MPTID makeMptID(std::uint32_t sequence, AccountID const &account)
constexpr std::uint32_t tfSetFreeze
constexpr std::uint32_t const tfMPTCanLock
constexpr std::uint32_t tfInnerBatchTxn
std::optional< std::string > batchID
Execution context for applying a JSON transaction.
Set the sequence number on a JTx.