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>
27#include <xrpld/app/tx/detail/Batch.h>
29#include <xrpl/protocol/Batch.h>
30#include <xrpl/protocol/Feature.h>
31#include <xrpl/protocol/STParsedJSON.h>
32#include <xrpl/protocol/Sign.h>
33#include <xrpl/protocol/TxFlags.h>
34#include <xrpl/protocol/jss.h>
59 for (
auto const& txn : jrr[jss::result][jss::ledger][jss::transactions])
61 if (txn[jss::metaData][sfTransactionIndex.jsonName] == index)
71 params[jss::ledger_index] = env.
closed()->seq();
72 params[jss::transactions] =
true;
73 params[jss::expand] =
true;
84 BEAST_EXPECT(jrr[sfTransactionType.jsonName] == ledgerResult.
txType);
86 jrr[jss::meta][sfTransactionResult.jsonName] ==
88 BEAST_EXPECT(jrr[jss::meta][sfParentBatchID.jsonName] == batchID);
97 auto const transactions =
98 jrr[jss::result][jss::ledger][jss::transactions];
99 BEAST_EXPECT(transactions.size() == ledgerResults.
size());
103 BEAST_EXPECT(txn[jss::hash].asString() == ledgerResult.txHash);
104 BEAST_EXPECT(txn.isMember(jss::metaData));
107 txn[sfTransactionType.jsonName] == ledgerResult.txType);
109 meta[sfTransactionResult.jsonName] == ledgerResult.result);
110 if (ledgerResult.batchID)
115 template <
typename... Args>
122 auto const ids = batchTxn.stx->getBatchTransactionIDs();
124 for (
auto const&
id : ids)
126 TxID const batchID = batchTxn.stx->getTransactionID();
142 auto& section = p->section(
"transaction_queue");
143 section.set(
"ledgers_in_queue",
"2");
144 section.set(
"minimum_queue_size",
"2");
145 section.set(
"min_ledgers_to_compute_size_limit",
"3");
146 section.set(
"max_ledger_counts_to_store",
"100");
147 section.set(
"retry_sequence_percent",
"25");
148 section.set(
"normal_consensus_increase_percent",
"0");
150 for (
auto const& [k, v] : extraTxQ)
161 auto const& view = *env.
current();
163 return toDrops(metrics.openLedgerFeeLevel, batchFee) + 1;
171 using namespace test::jtx;
174 for (
bool const withBatch : {
true,
false})
176 auto const amend = withBatch ? features : features - featureBatch;
179 auto const alice =
Account(
"alice");
180 auto const bob =
Account(
"bob");
181 auto const carol =
Account(
"carol");
182 env.fund(
XRP(10000), alice, bob, carol);
187 auto const seq = env.
seq(alice);
189 auto const txResult =
203 auto const txResult =
205 env(
pay(alice, bob,
XRP(1)),
220 using namespace test::jtx;
228 auto const alice =
Account(
"alice");
229 auto const bob =
Account(
"bob");
230 auto const carol =
Account(
"carol");
231 env.fund(
XRP(10000), alice, bob, carol);
244 auto const seq = env.
seq(alice);
253 auto const seq = env.
seq(alice);
262 auto const seq = env.
seq(alice);
272 auto const seq = env.
seq(alice);
281 auto const seq = env.
seq(alice);
292 auto const seq = env.
seq(alice);
311 auto const seq = env.
seq(alice);
312 auto jt = env.jtnofill(
324 auto const seq = env.
seq(alice);
338 auto const seq = env.
seq(alice);
341 auto jt = env.jtnofill(
352 auto const seq = env.
seq(alice);
354 auto jt = env.jt(
pay(alice, bob,
XRP(1)));
364 auto const seq = env.
seq(alice);
366 auto tx1 =
pay(alice, bob,
XRP(1));
369 tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfAccount.jsonName] =
371 tx1[sfSigners.jsonName][0U][sfSigner.jsonName]
372 [sfSigningPubKey.jsonName] =
strHex(alice.pk());
373 tx1[sfSigners.jsonName][0U][sfSigner.jsonName]
374 [sfTxnSignature.jsonName] =
"DEADBEEF";
385 auto const seq = env.
seq(alice);
388 tx1[jss::SigningPubKey] =
strHex(alice.pk());
389 auto jt = env.jtnofill(
400 auto const seq = env.
seq(alice);
412 auto const seq = env.
seq(alice);
415 tx1[jss::Fee] =
to_string(env.current()->fees().base);
426 auto const seq = env.
seq(alice);
429 tx1[jss::Sequence] =
seq + 1;
440 auto const seq = env.
seq(alice);
451 auto const seq = env.
seq(alice);
462 auto const seq = env.
seq(alice);
473 auto const seq = env.
seq(alice);
486 auto const seq = env.
seq(alice);
508 auto const seq = env.
seq(alice);
520 auto const seq = env.
seq(alice);
533 auto const seq = env.
seq(alice);
545 auto const seq = env.
seq(alice);
557 auto const seq = env.
seq(alice);
558 auto const bobSeq = env.seq(bob);
560 auto jt = env.jtnofill(
569 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
570 [sfAccount.jsonName] = bob.human();
571 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
572 [sfSigningPubKey.jsonName] =
strHex(alice.pk());
573 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
574 [sfTxnSignature.jsonName] =
583 auto const seq = env.
seq(alice);
600 using namespace test::jtx;
608 auto const alice =
Account(
"alice");
609 auto const bob =
Account(
"bob");
610 auto const carol =
Account(
"carol");
611 auto const dave =
Account(
"dave");
612 auto const elsa =
Account(
"elsa");
613 auto const frank =
Account(
"frank");
614 auto const phantom =
Account(
"phantom");
615 env.memoize(phantom);
617 env.fund(
XRP(10000), alice, bob, carol, dave, elsa, frank);
625 auto const seq = env.
seq(alice);
640 auto const seq = env.
seq(alice);
650 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
653 env(
signers(bob, 2, {{carol, 1}, {dave, 1}, {elsa, 1}}));
658 auto const seq = env.
seq(alice);
670 auto const seq = env.
seq(alice);
675 batch::msig(bob, {carol, Account(
"dave", KeyType::ed25519)}),
684 auto const seq = env.
seq(alice);
696 auto const seq = env.
seq(alice);
708 auto const seq = env.
seq(alice);
722 auto const seq = env.
seq(alice);
726 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
727 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
728 batch::msig(bob, {carol, Reg{dave, davo}}),
735 auto const seq = env.seq(alice);
738 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
739 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
740 batch::msig(bob, {carol}),
747 auto const seq = env.seq(alice);
750 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
751 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
752 batch::msig(bob, {carol, dave}),
759 auto const seq = env.seq(alice);
762 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
763 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
764 batch::msig(bob, {carol, dave}),
775 auto const ledSeq = env.current()->seq();
776 auto const seq = env.seq(alice);
779 batch::inner(
pay(alice, phantom,
XRP(1000)), seq + 1),
780 batch::inner(
noop(phantom), ledSeq),
781 batch::sig(Reg{phantom, carol}),
788 auto const ledSeq = env.current()->seq();
789 auto const seq = env.seq(alice);
792 batch::inner(
pay(alice, bob,
XRP(1000)), seq + 1),
793 batch::inner(
noop(bob), ledSeq),
794 batch::sig(Reg{bob, carol}),
802 auto const seq = env.seq(alice);
805 batch::inner(
pay(alice, bob,
XRP(1)), seq + 1),
806 batch::inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
807 batch::sig(Reg{bob, carol}),
814 auto const seq = env.seq(alice);
817 batch::inner(
pay(alice, bob,
XRP(1)), seq + 1),
818 batch::inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
828 auto const seq = env.seq(alice);
831 batch::inner(
pay(alice, bob,
XRP(1)), seq + 1),
832 batch::inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
842 testcase(
"bad raw txn");
844 using namespace test::jtx;
849 auto const alice =
Account(
"alice");
850 auto const bob =
Account(
"bob");
852 env.fund(
XRP(10000), alice, bob);
856 auto const batchFee = batch::calcBatchFee(env, 1, 2);
857 auto const seq = env.
seq(alice);
859 tx1.removeMember(jss::TransactionType);
860 auto jt = env.jtnofill(
871 auto const batchFee = batch::calcBatchFee(env, 1, 2);
872 auto const seq = env.
seq(alice);
874 tx1.removeMember(jss::Account);
875 auto jt = env.jtnofill(
886 auto const batchFee = batch::calcBatchFee(env, 1, 2);
887 auto const seq = env.
seq(alice);
889 tx1.removeMember(jss::Sequence);
890 auto jt = env.jtnofill(
901 auto const batchFee = batch::calcBatchFee(env, 1, 2);
902 auto const seq = env.
seq(alice);
904 tx1.removeMember(jss::Fee);
905 auto jt = env.jtnofill(
916 auto const batchFee = batch::calcBatchFee(env, 1, 2);
917 auto const seq = env.
seq(alice);
919 tx1.removeMember(jss::SigningPubKey);
920 auto jt = env.jtnofill(
933 testcase(
"bad sequence");
935 using namespace test::jtx;
940 auto const alice =
Account(
"alice");
941 auto const bob =
Account(
"bob");
943 auto const USD = gw[
"USD"];
945 env.fund(
XRP(10000), alice, bob, gw);
947 env.trust(USD(1000), alice, bob);
948 env(pay(gw, alice, USD(100)));
949 env(pay(gw, bob, USD(100)));
957 auto const preAliceSeq = env.seq(alice);
958 auto const preAlice = env.balance(alice);
959 auto const preAliceUSD = env.balance(alice, USD.issue());
960 auto const preBobSeq = env.seq(bob);
961 auto const preBob = env.balance(bob);
962 auto const preBobUSD = env.balance(bob, USD.issue());
964 auto const batchFee = batch::calcBatchFee(env, 1, 2);
965 auto const [txIDs, batchID] = submitBatch(
978 validateClosedLedger(env, testCases);
985 validateClosedLedger(env, testCases);
989 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
990 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
991 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
992 BEAST_EXPECT(env.seq(bob) == preBobSeq);
993 BEAST_EXPECT(env.balance(bob) == preBob);
994 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
999 auto const preAliceSeq = env.seq(alice);
1000 auto const preAlice = env.balance(alice);
1001 auto const preAliceUSD = env.balance(alice, USD.issue());
1002 auto const preBobSeq = env.seq(bob);
1003 auto const preBob = env.balance(bob);
1004 auto const preBobUSD = env.balance(bob, USD.issue());
1006 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1007 auto const [txIDs, batchID] = submitBatch(
1020 validateClosedLedger(env, testCases);
1027 validateClosedLedger(env, testCases);
1031 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1032 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1033 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1034 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1035 BEAST_EXPECT(env.balance(bob) == preBob);
1036 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1041 auto const preAliceSeq = env.seq(alice);
1042 auto const preAlice = env.balance(alice);
1043 auto const preAliceUSD = env.balance(alice, USD.issue());
1044 auto const preBobSeq = env.seq(bob);
1045 auto const preBob = env.balance(bob);
1046 auto const preBobUSD = env.balance(bob, USD.issue());
1048 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1049 auto const [txIDs, batchID] = submitBatch(
1062 validateClosedLedger(env, testCases);
1069 validateClosedLedger(env, testCases);
1073 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1074 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1075 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1076 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1077 BEAST_EXPECT(env.balance(bob) == preBob);
1078 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1083 auto const preAliceSeq = env.seq(alice);
1084 auto const preAlice = env.balance(alice);
1085 auto const preAliceUSD = env.balance(alice, USD.issue());
1086 auto const preBobSeq = env.seq(bob);
1087 auto const preBob = env.balance(bob);
1088 auto const preBobUSD = env.balance(bob, USD.issue());
1090 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1091 auto const [txIDs, batchID] = submitBatch(
1104 validateClosedLedger(env, testCases);
1111 validateClosedLedger(env, testCases);
1115 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1116 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1117 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1118 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1119 BEAST_EXPECT(env.balance(bob) == preBob);
1120 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1125 auto const preAliceSeq = env.seq(alice);
1126 auto const preAlice = env.balance(alice);
1127 auto const preAliceUSD = env.balance(alice, USD.issue());
1128 auto const preBobSeq = env.seq(bob);
1129 auto const preBob = env.balance(bob);
1130 auto const preBobUSD = env.balance(bob, USD.issue());
1132 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1133 auto const [txIDs, batchID] = submitBatch(
1146 validateClosedLedger(env, testCases);
1153 validateClosedLedger(env, testCases);
1157 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1158 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1159 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1160 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1161 BEAST_EXPECT(env.balance(bob) == preBob);
1162 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1169 testcase(
"bad outer fee");
1171 using namespace test::jtx;
1178 auto const alice =
Account(
"alice");
1179 auto const bob =
Account(
"bob");
1180 env.fund(
XRP(10000), alice, bob);
1187 auto const batchFee = batch::calcBatchFee(env, 0, 1);
1188 auto const aliceSeq = env.seq(alice);
1200 auto const alice =
Account(
"alice");
1201 auto const bob =
Account(
"bob");
1202 auto const carol =
Account(
"carol");
1203 env.fund(
XRP(10000), alice, bob, carol);
1209 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
1213 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1214 auto const aliceSeq = env.seq(alice);
1227 auto const alice =
Account(
"alice");
1228 auto const bob =
Account(
"bob");
1229 auto const carol =
Account(
"carol");
1230 env.fund(
XRP(10000), alice, bob, carol);
1236 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
1240 auto const batchFee = batch::calcBatchFee(env, 2, 2);
1241 auto const aliceSeq = env.seq(alice);
1242 auto const bobSeq = env.seq(bob);
1256 auto const alice =
Account(
"alice");
1257 auto const bob =
Account(
"bob");
1258 auto const carol =
Account(
"carol");
1259 env.fund(
XRP(10000), alice, bob, carol);
1265 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
1268 env(signers(bob, 2, {{alice, 1}, {carol, 1}}));
1272 auto const batchFee = batch::calcBatchFee(env, 3, 2);
1273 auto const aliceSeq = env.seq(alice);
1274 auto const bobSeq = env.seq(bob);
1288 auto const alice =
Account(
"alice");
1289 auto const bob =
Account(
"bob");
1290 env.fund(
XRP(10000), alice, bob);
1297 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1298 auto const aliceSeq = env.seq(alice);
1299 auto const bobSeq = env.seq(bob);
1312 auto const alice =
Account(
"alice");
1313 auto const bob =
Account(
"bob");
1314 auto const gw =
Account(
"gw");
1315 auto const USD = gw[
"USD"];
1317 env.fund(
XRP(10000), alice, bob, gw);
1319 auto const ammCreate =
1322 jv[jss::Account] = alice.human();
1325 jv[jss::TradingFee] = 0;
1326 jv[jss::TransactionType] = jss::AMMCreate;
1330 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1331 auto const seq = env.
seq(alice);
1343 testcase(
"calculate base fee");
1345 using namespace test::jtx;
1352 auto const alice =
Account(
"alice");
1353 auto const bob =
Account(
"bob");
1354 env.fund(
XRP(10000), alice, bob);
1357 auto const batchFee = batch::calcBatchFee(env, 0, 9);
1358 auto const aliceSeq = env.seq(alice);
1377 auto const alice =
Account(
"alice");
1378 auto const bob =
Account(
"bob");
1379 env.fund(
XRP(10000), alice, bob);
1382 auto const batchFee = batch::calcBatchFee(env, 0, 9);
1383 auto const aliceSeq = env.seq(alice);
1384 auto jt = env.jtnofill(
1396 env.app().openLedger().modify(
1402 return result.applied;
1410 auto const alice =
Account(
"alice");
1411 auto const bob =
Account(
"bob");
1412 env.fund(
XRP(10000), alice, bob);
1415 auto const aliceSeq = env.seq(alice);
1416 auto const batchFee = batch::calcBatchFee(env, 9, 2);
1420 batch::sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob),
1429 auto const alice =
Account(
"alice");
1430 auto const bob =
Account(
"bob");
1431 env.fund(
XRP(10000), alice, bob);
1434 auto const batchFee = batch::calcBatchFee(env, 0, 9);
1435 auto const aliceSeq = env.seq(alice);
1436 auto jt = env.jtnofill(
1440 batch::sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob));
1442 env.app().openLedger().modify(
1448 return result.applied;
1456 testcase(
"all or nothing");
1458 using namespace test::jtx;
1463 auto const alice =
Account(
"alice");
1464 auto const bob =
Account(
"bob");
1465 auto const gw =
Account(
"gw");
1466 auto const USD = gw[
"USD"];
1467 env.fund(
XRP(10000), alice, bob, gw);
1472 auto const preAlice = env.balance(alice);
1473 auto const preBob = env.balance(bob);
1475 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1476 auto const seq = env.
seq(alice);
1477 auto const [txIDs, batchID] = submitBatch(
1487 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1488 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1490 validateClosedLedger(env, testCases);
1493 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
1496 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
1497 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
1502 auto const preAlice = env.balance(alice);
1503 auto const preBob = env.balance(bob);
1505 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1506 auto const seq = env.
seq(alice);
1508 auto const [txIDs, batchID] = submitBatch(
1520 validateClosedLedger(env, testCases);
1523 BEAST_EXPECT(env.seq(alice) ==
seq + 1);
1526 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1527 BEAST_EXPECT(env.balance(bob) == preBob);
1532 auto const preAlice = env.balance(alice);
1533 auto const preBob = env.balance(bob);
1535 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1536 auto const seq = env.
seq(alice);
1537 auto const [txIDs, batchID] = submitBatch(
1549 validateClosedLedger(env, testCases);
1552 BEAST_EXPECT(env.seq(alice) ==
seq + 1);
1555 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1556 BEAST_EXPECT(env.balance(bob) == preBob);
1561 auto const preAlice = env.balance(alice);
1562 auto const preBob = env.balance(bob);
1564 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1565 auto const seq = env.
seq(alice);
1566 auto const [txIDs, batchID] = submitBatch(
1578 validateClosedLedger(env, testCases);
1581 BEAST_EXPECT(env.seq(alice) ==
seq + 1);
1584 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1585 BEAST_EXPECT(env.balance(bob) == preBob);
1592 testcase(
"only one");
1594 using namespace test::jtx;
1599 auto const alice =
Account(
"alice");
1600 auto const bob =
Account(
"bob");
1601 auto const carol =
Account(
"carol");
1602 auto const dave =
Account(
"dave");
1603 auto const gw =
Account(
"gw");
1604 auto const USD = gw[
"USD"];
1605 env.fund(
XRP(10000), alice, bob, carol, dave, gw);
1610 auto const preAlice = env.balance(alice);
1611 auto const preBob = env.balance(bob);
1613 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1614 auto const seq = env.
seq(alice);
1615 auto const [txIDs, batchID] = submitBatch(
1629 {1,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[0], batchID},
1630 {2,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[1], batchID},
1631 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
1633 validateClosedLedger(env, testCases);
1636 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
1639 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1640 BEAST_EXPECT(env.balance(bob) == preBob);
1645 auto const preAlice = env.balance(alice);
1646 auto const preBob = env.balance(bob);
1648 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1649 auto const seq = env.
seq(alice);
1650 auto const [txIDs, batchID] = submitBatch(
1662 {1,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[0], batchID},
1663 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1665 validateClosedLedger(env, testCases);
1668 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
1671 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
1672 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1677 auto const preAlice = env.balance(alice);
1678 auto const preBob = env.balance(bob);
1680 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1681 auto const seq = env.
seq(alice);
1682 auto const [txIDs, batchID] = submitBatch(
1694 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1696 validateClosedLedger(env, testCases);
1699 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1702 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
1703 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1708 auto const preAlice = env.balance(alice);
1709 auto const preBob = env.balance(bob);
1711 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1712 auto const seq = env.
seq(alice);
1713 auto const [txIDs, batchID] = submitBatch(
1725 {1,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1727 validateClosedLedger(env, testCases);
1730 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1733 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(1));
1734 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1739 auto const preAlice = env.balance(alice);
1740 auto const preBob = env.balance(bob);
1742 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1743 auto const seq = env.
seq(alice);
1744 auto const [txIDs, batchID] = submitBatch(
1756 {1,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1758 validateClosedLedger(env, testCases);
1761 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1764 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(1));
1765 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1770 auto const preAlice = env.balance(alice);
1771 auto const preBob = env.balance(bob);
1772 auto const preCarol = env.balance(carol);
1773 auto const seq = env.
seq(alice);
1774 auto const batchFee = batch::calcBatchFee(env, 0, 6);
1776 auto const [txIDs, batchID] = submitBatch(
1808 {1,
"OfferCreate",
"tecKILLED", txIDs[0], batchID},
1809 {2,
"OfferCreate",
"tecKILLED", txIDs[1], batchID},
1810 {3,
"OfferCreate",
"tecKILLED", txIDs[2], batchID},
1811 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
1813 validateClosedLedger(env, testCases);
1815 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(100) - batchFee);
1816 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(100));
1817 BEAST_EXPECT(env.balance(carol) == preCarol);
1824 testcase(
"until failure");
1826 using namespace test::jtx;
1831 auto const alice =
Account(
"alice");
1832 auto const bob =
Account(
"bob");
1833 auto const carol =
Account(
"carol");
1834 auto const dave =
Account(
"dave");
1835 auto const gw =
Account(
"gw");
1836 auto const USD = gw[
"USD"];
1837 env.fund(
XRP(10000), alice, bob, carol, dave, gw);
1842 auto const preAlice = env.balance(alice);
1843 auto const preBob = env.balance(bob);
1845 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1846 auto const seq = env.
seq(alice);
1847 auto const [txIDs, batchID] = submitBatch(
1860 {1,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[0], batchID},
1862 validateClosedLedger(env, testCases);
1865 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1868 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1869 BEAST_EXPECT(env.balance(bob) == preBob);
1874 auto const preAlice = env.balance(alice);
1875 auto const preBob = env.balance(bob);
1877 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1878 auto const seq = env.
seq(alice);
1879 auto const [txIDs, batchID] = submitBatch(
1891 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1892 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1893 {3,
"Payment",
"tesSUCCESS", txIDs[2], batchID},
1894 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
1896 validateClosedLedger(env, testCases);
1899 BEAST_EXPECT(env.seq(alice) ==
seq + 5);
1902 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(10) - batchFee);
1903 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(10));
1908 auto const preAlice = env.balance(alice);
1909 auto const preBob = env.balance(bob);
1911 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1912 auto const seq = env.
seq(alice);
1913 auto const [txIDs, batchID] = submitBatch(
1926 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1927 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1928 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
1930 validateClosedLedger(env, testCases);
1933 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
1936 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
1937 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
1942 auto const preAlice = env.balance(alice);
1943 auto const preBob = env.balance(bob);
1945 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1946 auto const seq = env.
seq(alice);
1947 auto const [txIDs, batchID] = submitBatch(
1960 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1961 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1963 validateClosedLedger(env, testCases);
1966 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
1969 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
1970 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
1975 auto const preAlice = env.balance(alice);
1976 auto const preBob = env.balance(bob);
1978 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1979 auto const seq = env.
seq(alice);
1980 auto const [txIDs, batchID] = submitBatch(
1993 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1994 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1996 validateClosedLedger(env, testCases);
1999 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
2002 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2003 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2008 auto const preAlice = env.balance(alice);
2009 auto const preBob = env.balance(bob);
2010 auto const preCarol = env.balance(carol);
2011 auto const seq = env.
seq(alice);
2012 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2013 auto const [txIDs, batchID] = submitBatch(
2031 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2032 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2033 {3,
"OfferCreate",
"tecKILLED", txIDs[2], batchID},
2035 validateClosedLedger(env, testCases);
2037 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(200) - batchFee);
2038 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(100));
2039 BEAST_EXPECT(env.balance(carol) == preCarol +
XRP(100));
2046 testcase(
"independent");
2048 using namespace test::jtx;
2053 auto const alice =
Account(
"alice");
2054 auto const bob =
Account(
"bob");
2055 auto const carol =
Account(
"carol");
2056 auto const gw =
Account(
"gw");
2057 auto const USD = gw[
"USD"];
2058 env.fund(
XRP(10000), alice, bob, carol, gw);
2063 auto const preAlice = env.balance(alice);
2064 auto const preBob = env.balance(bob);
2066 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2067 auto const seq = env.
seq(alice);
2068 auto const [txIDs, batchID] = submitBatch(
2082 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2083 {2,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[1], batchID},
2084 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
2085 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2087 validateClosedLedger(env, testCases);
2090 BEAST_EXPECT(env.seq(alice) ==
seq + 5);
2093 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(4) - batchFee);
2094 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(4));
2099 auto const preAlice = env.balance(alice);
2100 auto const preBob = env.balance(bob);
2102 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2103 auto const seq = env.
seq(alice);
2104 auto const [txIDs, batchID] = submitBatch(
2117 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2118 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2119 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
2120 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2122 validateClosedLedger(env, testCases);
2125 BEAST_EXPECT(env.seq(alice) ==
seq + 5);
2128 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(6) - batchFee);
2129 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(6));
2134 auto const preAlice = env.balance(alice);
2135 auto const preBob = env.balance(bob);
2137 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2138 auto const seq = env.
seq(alice);
2139 auto const [txIDs, batchID] = submitBatch(
2152 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2153 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2154 {3,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2156 validateClosedLedger(env, testCases);
2159 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
2162 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(6));
2163 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(6));
2168 auto const preAlice = env.balance(alice);
2169 auto const preBob = env.balance(bob);
2171 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2172 auto const seq = env.
seq(alice);
2173 auto const [txIDs, batchID] = submitBatch(
2186 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2187 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2188 {3,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2190 validateClosedLedger(env, testCases);
2193 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
2196 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(6));
2197 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(6));
2202 auto const preAlice = env.balance(alice);
2203 auto const preBob = env.balance(bob);
2204 auto const preCarol = env.balance(carol);
2205 auto const seq = env.
seq(alice);
2206 auto const batchFee = batch::calcBatchFee(env, 0, 3);
2207 auto const [txIDs, batchID] = submitBatch(
2224 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2225 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2226 {3,
"OfferCreate",
"tecKILLED", txIDs[2], batchID},
2228 validateClosedLedger(env, testCases);
2230 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(200) - batchFee);
2231 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(100));
2232 BEAST_EXPECT(env.balance(carol) == preCarol +
XRP(100));
2239 testcase(
"inner submit rpc");
2241 using namespace test::jtx;
2246 auto const alice =
Account(
"alice");
2247 auto const bob =
Account(
"bob");
2249 env.fund(
XRP(10000), alice, bob);
2252 auto submitAndValidate = [&](
Slice const&
slice) {
2253 auto const jrr = env.rpc(
"submit",
strHex(
slice))[jss::result];
2255 jrr[jss::status] ==
"error" &&
2256 jrr[jss::error] ==
"invalidTransaction" &&
2257 jrr[jss::error_exception] ==
2258 "fails local checks: Malformed: Invalid inner batch "
2270 txn[sfTxnSignature] =
"DEADBEEF";
2274 submitAndValidate(s.
slice());
2284 txn[sfSigningPubKey] =
strHex(alice.pk());
2288 submitAndValidate(s.
slice());
2302 submitAndValidate(s.
slice());
2315 auto const jrr = env.rpc(
"submit",
strHex(s.
slice()))[jss::result];
2317 jrr[jss::status] ==
"success" &&
2318 jrr[jss::engine_result] ==
"temINVALID_FLAG");
2327 testcase(
"account activation");
2329 using namespace test::jtx;
2334 auto const alice =
Account(
"alice");
2335 auto const bob =
Account(
"bob");
2336 env.fund(
XRP(10000), alice);
2340 auto const preAlice = env.balance(alice);
2341 auto const ledSeq = env.current()->seq();
2342 auto const seq = env.
seq(alice);
2343 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2344 auto const [txIDs, batchID] = submitBatch(
2355 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2356 {2,
"AccountSet",
"tesSUCCESS", txIDs[1], batchID},
2358 validateClosedLedger(env, testCases);
2361 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
2364 BEAST_EXPECT(env.seq(bob) == ledSeq + 1);
2367 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - batchFee);
2368 BEAST_EXPECT(env.balance(bob) ==
XRP(1000));
2374 testcase(
"account set");
2376 using namespace test::jtx;
2381 auto const alice =
Account(
"alice");
2382 auto const bob =
Account(
"bob");
2383 env.fund(
XRP(10000), alice, bob);
2386 auto const preAlice = env.balance(alice);
2387 auto const preBob = env.balance(bob);
2389 auto const seq = env.
seq(alice);
2390 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2394 auto const [txIDs, batchID] = submitBatch(
2404 {1,
"AccountSet",
"tesSUCCESS", txIDs[0], batchID},
2405 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2407 validateClosedLedger(env, testCases);
2415 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
2418 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
2419 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
2425 testcase(
"account delete");
2427 using namespace test::jtx;
2434 auto const alice =
Account(
"alice");
2435 auto const bob =
Account(
"bob");
2436 env.fund(
XRP(10000), alice, bob);
2440 for (
int i = 0; i < 5; ++i)
2443 auto const preAlice = env.balance(alice);
2444 auto const preBob = env.balance(bob);
2446 auto const seq = env.
seq(alice);
2447 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
2448 env.current()->fees().increment;
2449 auto const [txIDs, batchID] = submitBatch(
2461 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2462 {2,
"AccountDelete",
"tesSUCCESS", txIDs[1], batchID},
2464 validateClosedLedger(env, testCases);
2468 BEAST_EXPECT(env.balance(bob) == preBob + (preAlice - batchFee));
2475 auto const alice =
Account(
"alice");
2476 auto const bob =
Account(
"bob");
2477 env.fund(
XRP(10000), alice, bob);
2481 for (
int i = 0; i < 5; ++i)
2484 auto const preAlice = env.balance(alice);
2485 auto const preBob = env.balance(bob);
2487 env.trust(bob[
"USD"](1000), alice);
2490 auto const seq = env.
seq(alice);
2491 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
2492 env.current()->fees().increment;
2493 auto const [txIDs, batchID] = submitBatch(
2505 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2506 {2,
"AccountDelete",
"tecHAS_OBLIGATIONS", txIDs[1], batchID},
2507 {3,
"Payment",
"tesSUCCESS", txIDs[2], batchID},
2509 validateClosedLedger(env, testCases);
2513 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2520 auto const alice =
Account(
"alice");
2521 auto const bob =
Account(
"bob");
2522 env.fund(
XRP(10000), alice, bob);
2526 for (
int i = 0; i < 5; ++i)
2529 auto const preAlice = env.balance(alice);
2530 auto const preBob = env.balance(bob);
2532 auto const seq = env.
seq(alice);
2533 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
2534 env.current()->fees().increment;
2535 auto const [txIDs, batchID] = submitBatch(
2548 validateClosedLedger(env, testCases);
2552 BEAST_EXPECT(env.balance(bob) == preBob);
2559 testcase(
"object create w/ sequence");
2561 using namespace test::jtx;
2566 auto const alice =
Account(
"alice");
2567 auto const bob =
Account(
"bob");
2568 auto const gw =
Account(
"gw");
2569 auto const USD = gw[
"USD"];
2571 env.fund(
XRP(10000), alice, bob, gw);
2574 env.trust(USD(1000), alice, bob);
2575 env(pay(gw, alice, USD(100)));
2576 env(pay(gw, bob, USD(100)));
2581 auto const aliceSeq = env.seq(alice);
2582 auto const bobSeq = env.seq(bob);
2583 auto const preAlice = env.balance(alice);
2584 auto const preBob = env.balance(bob);
2585 auto const preAliceUSD = env.balance(alice, USD.issue());
2586 auto const preBobUSD = env.balance(bob, USD.issue());
2588 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2589 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
2590 auto const [txIDs, batchID] = submitBatch(
2594 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
2595 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
2601 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
2602 {2,
"CheckCash",
"tesSUCCESS", txIDs[1], batchID},
2604 validateClosedLedger(env, testCases);
2607 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2610 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
2613 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
2614 BEAST_EXPECT(env.balance(bob) == preBob);
2618 env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
2619 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
2627 auto const aliceSeq = env.seq(alice);
2628 auto const bobSeq = env.seq(bob);
2629 auto const preAlice = env.balance(alice);
2630 auto const preBob = env.balance(bob);
2631 auto const preAliceUSD = env.balance(alice, USD.issue());
2632 auto const preBobUSD = env.balance(bob, USD.issue());
2634 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2635 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
2636 auto const [txIDs, batchID] = submitBatch(
2641 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
2642 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
2648 {1,
"CheckCreate",
"tecDST_TAG_NEEDED", txIDs[0], batchID},
2649 {2,
"CheckCash",
"tecNO_ENTRY", txIDs[1], batchID},
2651 validateClosedLedger(env, testCases);
2654 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2657 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
2660 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
2661 BEAST_EXPECT(env.balance(bob) == preBob);
2664 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
2665 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
2672 testcase(
"object create w/ ticket");
2674 using namespace test::jtx;
2679 auto const alice =
Account(
"alice");
2680 auto const bob =
Account(
"bob");
2681 auto const gw =
Account(
"gw");
2682 auto const USD = gw[
"USD"];
2684 env.fund(
XRP(10000), alice, bob, gw);
2687 env.trust(USD(1000), alice, bob);
2688 env(pay(gw, alice, USD(100)));
2689 env(pay(gw, bob, USD(100)));
2692 auto const aliceSeq = env.seq(alice);
2693 auto const bobSeq = env.seq(bob);
2694 auto const preAlice = env.balance(alice);
2695 auto const preBob = env.balance(bob);
2696 auto const preAliceUSD = env.balance(alice, USD.issue());
2697 auto const preBobUSD = env.balance(bob, USD.issue());
2699 auto const batchFee = batch::calcBatchFee(env, 1, 3);
2700 uint256 const chkID{getCheckIndex(bob, bobSeq + 1)};
2701 auto const [txIDs, batchID] = submitBatch(
2706 batch::inner(check::create(bob, alice, USD(10)), 0, bobSeq + 1),
2707 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
2713 {1,
"TicketCreate",
"tesSUCCESS", txIDs[0], batchID},
2714 {2,
"CheckCreate",
"tesSUCCESS", txIDs[1], batchID},
2715 {3,
"CheckCash",
"tesSUCCESS", txIDs[2], batchID},
2717 validateClosedLedger(env, testCases);
2719 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2720 BEAST_EXPECT(env.seq(bob) == bobSeq + 10 + 1);
2721 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
2722 BEAST_EXPECT(env.balance(bob) == preBob);
2723 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
2724 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
2730 testcase(
"object create w/ 3rd party");
2732 using namespace test::jtx;
2737 auto const alice =
Account(
"alice");
2738 auto const bob =
Account(
"bob");
2739 auto const carol =
Account(
"carol");
2740 auto const gw =
Account(
"gw");
2741 auto const USD = gw[
"USD"];
2743 env.fund(
XRP(10000), alice, bob, carol, gw);
2746 env.trust(USD(1000), alice, bob);
2747 env(pay(gw, alice, USD(100)));
2748 env(pay(gw, bob, USD(100)));
2751 auto const aliceSeq = env.seq(alice);
2752 auto const bobSeq = env.seq(bob);
2753 auto const carolSeq = env.seq(carol);
2754 auto const preAlice = env.balance(alice);
2755 auto const preBob = env.balance(bob);
2756 auto const preCarol = env.balance(carol);
2757 auto const preAliceUSD = env.balance(alice, USD.issue());
2758 auto const preBobUSD = env.balance(bob, USD.issue());
2760 auto const batchFee = batch::calcBatchFee(env, 2, 2);
2761 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
2762 auto const [txIDs, batchID] = submitBatch(
2766 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
2767 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq),
2773 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
2774 {2,
"CheckCash",
"tesSUCCESS", txIDs[1], batchID},
2776 validateClosedLedger(env, testCases);
2778 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
2779 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
2780 BEAST_EXPECT(env.seq(carol) == carolSeq + 1);
2781 BEAST_EXPECT(env.balance(alice) == preAlice);
2782 BEAST_EXPECT(env.balance(bob) == preBob);
2783 BEAST_EXPECT(env.balance(carol) == preCarol - batchFee);
2784 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
2785 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
2792 testcase(
"tickets outer");
2794 using namespace test::jtx;
2799 auto const alice =
Account(
"alice");
2800 auto const bob =
Account(
"bob");
2802 env.fund(
XRP(10000), alice, bob);
2806 env(ticket::create(alice, 10));
2809 auto const aliceSeq = env.seq(alice);
2810 auto const preAlice = env.balance(alice);
2811 auto const preBob = env.balance(bob);
2813 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2814 auto const [txIDs, batchID] = submitBatch(
2825 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2826 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2828 validateClosedLedger(env, testCases);
2832 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 9);
2833 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 9);
2835 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2836 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2837 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2841 testcase(
"tickets inner");
2843 using namespace test::jtx;
2848 auto const alice =
Account(
"alice");
2849 auto const bob =
Account(
"bob");
2851 env.fund(
XRP(10000), alice, bob);
2855 env(ticket::create(alice, 10));
2858 auto const aliceSeq = env.seq(alice);
2859 auto const preAlice = env.balance(alice);
2860 auto const preBob = env.balance(bob);
2862 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2863 auto const [txIDs, batchID] = submitBatch(
2873 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2874 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2876 validateClosedLedger(env, testCases);
2880 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
2881 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
2883 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
2884 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2885 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2889 testcase(
"tickets outer inner");
2891 using namespace test::jtx;
2896 auto const alice =
Account(
"alice");
2897 auto const bob =
Account(
"bob");
2899 env.fund(
XRP(10000), alice, bob);
2903 env(ticket::create(alice, 10));
2906 auto const aliceSeq = env.seq(alice);
2907 auto const preAlice = env.balance(alice);
2908 auto const preBob = env.balance(bob);
2910 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2911 auto const [txIDs, batchID] = submitBatch(
2922 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2923 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2925 validateClosedLedger(env, testCases);
2929 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
2930 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
2932 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
2933 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2934 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2941 testcase(
"sequence open ledger");
2943 using namespace test::jtx;
2946 auto const alice =
Account(
"alice");
2947 auto const bob =
Account(
"bob");
2948 auto const carol =
Account(
"carol");
2958 env.fund(
XRP(10000), alice, bob, carol);
2961 auto const aliceSeq = env.seq(alice);
2962 auto const carolSeq = env.seq(carol);
2965 auto const noopTxn = env.jt(
noop(alice),
seq(aliceSeq + 2));
2966 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
2970 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2971 auto const [txIDs, batchID] = submitBatch(
2983 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2984 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2986 validateClosedLedger(env, testCases);
2993 {0,
"AccountSet",
"tesSUCCESS", noopTxnID,
std::nullopt},
2995 validateClosedLedger(env, testCases);
3005 env.fund(
XRP(10000), alice, bob);
3008 auto const aliceSeq = env.seq(alice);
3011 auto const noopTxn = env.jt(
noop(alice),
seq(aliceSeq + 1));
3015 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3016 auto const [txIDs, batchID] = submitBatch(
3027 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3028 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3030 validateClosedLedger(env, testCases);
3037 validateClosedLedger(env, testCases);
3047 env.fund(
XRP(10000), alice, bob);
3050 auto const aliceSeq = env.seq(alice);
3051 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3052 auto const [txIDs, batchID] = submitBatch(
3059 auto const noopTxn = env.jt(
noop(alice),
seq(aliceSeq + 1));
3060 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3067 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3068 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3070 validateClosedLedger(env, testCases);
3077 validateClosedLedger(env, testCases);
3084 env.fund(
XRP(10000), alice, bob, carol);
3087 auto const aliceSeq = env.seq(alice);
3088 auto const carolSeq = env.seq(carol);
3091 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3092 auto const [txIDs, batchID] = submitBatch(
3101 auto const noopTxn = env.jt(
noop(carol),
seq(carolSeq));
3102 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3108 {0,
"AccountSet",
"tesSUCCESS", noopTxnID,
std::nullopt},
3110 {2,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3111 {3,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3113 validateClosedLedger(env, testCases);
3120 validateClosedLedger(env, testCases);
3128 testcase(
"tickets open ledger");
3130 using namespace test::jtx;
3133 auto const alice =
Account(
"alice");
3134 auto const bob =
Account(
"bob");
3142 env.fund(
XRP(10000), alice, bob);
3146 env(ticket::create(alice, 10));
3149 auto const aliceSeq = env.seq(alice);
3152 auto const noopTxn =
3154 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3158 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3159 auto const [txIDs, batchID] = submitBatch(
3171 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3172 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3174 validateClosedLedger(env, testCases);
3181 validateClosedLedger(env, testCases);
3191 env.fund(
XRP(10000), alice, bob);
3195 env(ticket::create(alice, 10));
3198 auto const aliceSeq = env.seq(alice);
3201 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3202 auto const [txIDs, batchID] = submitBatch(
3211 auto const noopTxn =
3219 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3220 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3222 validateClosedLedger(env, testCases);
3229 validateClosedLedger(env, testCases);
3237 testcase(
"objects open ledger");
3239 using namespace test::jtx;
3242 auto const alice =
Account(
"alice");
3243 auto const bob =
Account(
"bob");
3253 env.fund(
XRP(10000), alice, bob);
3257 env(ticket::create(alice, 10));
3260 auto const aliceSeq = env.seq(alice);
3263 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
3264 auto const objTxn = env.jt(check::cash(bob, chkID,
XRP(10)));
3265 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
3269 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3270 auto const [txIDs, batchID] = submitBatch(
3282 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
3283 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3284 {3,
"CheckCash",
"tesSUCCESS", objTxnID,
std::nullopt},
3286 validateClosedLedger(env, testCases);
3293 validateClosedLedger(env, testCases);
3300 env.fund(
XRP(10000), alice, bob);
3304 env(ticket::create(alice, 10));
3307 auto const aliceSeq = env.seq(alice);
3308 auto const bobSeq = env.seq(bob);
3311 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
3312 auto const objTxn = env.jt(check::create(alice, bob,
XRP(10)));
3313 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
3317 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3318 auto const [txIDs, batchID] = submitBatch(
3330 {0,
"CheckCreate",
"tesSUCCESS", objTxnID,
std::nullopt},
3332 {2,
"CheckCash",
"tesSUCCESS", txIDs[0], batchID},
3333 {3,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3335 validateClosedLedger(env, testCases);
3347 env.fund(
XRP(10000), alice, bob);
3351 env(ticket::create(alice, 10));
3354 auto const aliceSeq = env.seq(alice);
3357 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3358 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
3359 auto const [txIDs, batchID] = submitBatch(
3368 auto const objTxn = env.jt(check::cash(bob, chkID,
XRP(10)));
3369 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
3376 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
3377 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3378 {3,
"CheckCash",
"tesSUCCESS", objTxnID,
std::nullopt},
3380 validateClosedLedger(env, testCases);
3388 testcase(
"pseudo txn with tfInnerBatchTxn");
3390 using namespace test::jtx;
3395 auto const alice =
Account(
"alice");
3396 auto const bob =
Account(
"bob");
3397 env.fund(
XRP(10000), alice, bob);
3400 STTx const stx =
STTx(ttAMENDMENT, [&](
auto& obj) {
3401 obj.setAccountID(sfAccount,
AccountID());
3402 obj.setFieldH256(sfAmendment,
uint256(2));
3403 obj.setFieldU32(sfLedgerSequence, env.seq(alice));
3410 BEAST_EXPECT(reason ==
"Cannot submit pseudo transactions.");
3414 return result.applied;
3421 testcase(
"batch open ledger");
3429 using namespace test::jtx;
3433 XRPAmount const baseFee = env.current()->fees().base;
3435 auto const alice =
Account(
"alice");
3436 auto const bob =
Account(
"bob");
3438 env.fund(
XRP(10000), alice, bob);
3444 auto const aliceSeq = env.seq(alice);
3445 auto const preAlice = env.balance(alice);
3446 auto const preBob = env.balance(bob);
3447 auto const bobSeq = env.seq(bob);
3450 auto const payTxn1 = env.jt(pay(alice, bob,
XRP(10)),
seq(aliceSeq));
3451 auto const payTxn1ID =
to_string(payTxn1.stx->getTransactionID());
3455 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3456 auto const [txIDs, batchID] = submitBatch(
3465 auto const payTxn2 = env.jt(pay(bob, alice,
XRP(5)),
seq(bobSeq + 1));
3466 auto const payTxn2ID =
to_string(payTxn2.stx->getTransactionID());
3473 {2,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3474 {3,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3476 validateClosedLedger(env, testCases);
3484 validateClosedLedger(env, testCases);
3488 BEAST_EXPECT(env.seq(alice) == aliceSeq + 3);
3491 BEAST_EXPECT(env.seq(bob) == bobSeq + 2);
3495 env.balance(alice) == preAlice -
XRP(10) - batchFee - baseFee);
3496 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(10) - baseFee);
3502 testcase(
"batch tx queue");
3504 using namespace test::jtx;
3511 makeSmallQueueConfig(
3512 {{
"minimum_txn_in_ledger_standalone",
"2"}}),
3516 auto alice =
Account(
"alice");
3518 auto carol =
Account(
"carol");
3522 env.close(env.now() + 5s, 10000ms);
3524 env.close(env.now() + 5s, 10000ms);
3535 auto const aliceSeq = env.seq(alice);
3536 auto const bobSeq = env.seq(bob);
3537 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3555 openLedgerFee(env, batchFee),
3571 makeSmallQueueConfig(
3572 {{
"minimum_txn_in_ledger_standalone",
"2"}}),
3576 auto alice =
Account(
"alice");
3578 auto carol =
Account(
"carol");
3582 env.close(env.now() + 5s, 10000ms);
3584 env.close(env.now() + 5s, 10000ms);
3591 auto const aliceSeq = env.seq(alice);
3592 auto const bobSeq = env.seq(bob);
3593 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3614 testcase(
"batch network ops");
3616 using namespace test::jtx;
3626 auto alice =
Account(
"alice");
3628 env.
fund(
XRP(10000), alice, bob);
3636 return jt.stx->getTransactionID();
3648 return transaction->getID();
3673 testcase(
"batch delegate");
3675 using namespace test::jtx;
3682 auto const alice =
Account(
"alice");
3683 auto const bob =
Account(
"bob");
3684 auto const gw =
Account(
"gw");
3685 auto const USD = gw[
"USD"];
3686 env.fund(
XRP(10000), alice, bob, gw);
3689 env(delegate::set(alice, bob, {
"Payment"}));
3692 auto const preAlice = env.balance(alice);
3693 auto const preBob = env.balance(bob);
3695 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3696 auto const seq = env.
seq(alice);
3699 tx[jss::Delegate] = bob.human();
3700 auto const [txIDs, batchID] = submitBatch(
3710 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3711 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3713 validateClosedLedger(env, testCases);
3716 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
3719 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
3720 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
3727 auto const alice =
Account(
"alice");
3728 auto const bob =
Account(
"bob");
3729 auto const carol =
Account(
"carol");
3730 auto const gw =
Account(
"gw");
3731 auto const USD = gw[
"USD"];
3732 env.fund(
XRP(10000), alice, bob, carol, gw);
3735 env(delegate::set(bob, carol, {
"Payment"}));
3738 auto const preAlice = env.balance(alice);
3739 auto const preBob = env.balance(bob);
3740 auto const preCarol = env.balance(carol);
3742 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3743 auto const aliceSeq = env.seq(alice);
3744 auto const bobSeq = env.seq(bob);
3747 tx[jss::Delegate] = carol.human();
3748 auto const [txIDs, batchID] = submitBatch(
3759 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3760 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3762 validateClosedLedger(env, testCases);
3764 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
3765 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
3766 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
3767 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
3770 BEAST_EXPECT(env.balance(carol) == preCarol);
3779 auto const alice =
Account(
"alice");
3780 auto const bob =
Account(
"bob");
3781 auto const gw =
Account(
"gw");
3782 auto const USD = gw[
"USD"];
3783 env.fund(
XRP(10000), alice, bob, gw);
3786 env(delegate::set(alice, bob, {
"AccountDomainSet"}));
3789 auto const preAlice = env.balance(alice);
3790 auto const preBob = env.balance(bob);
3792 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3793 auto const seq = env.
seq(alice);
3798 tx[jss::Delegate] = bob.human();
3799 auto const [txIDs, batchID] = submitBatch(
3809 {1,
"AccountSet",
"tesSUCCESS", txIDs[0], batchID},
3810 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3812 validateClosedLedger(env, testCases);
3815 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
3818 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(2) - batchFee);
3819 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(2));
3829 env.fund(
XRP(100000), alice, bob);
3832 auto const mptID =
makeMptID(env.seq(alice), alice);
3833 MPTTester mpt(env, alice, {.fund =
false});
3840 alice, bob, {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"}));
3843 auto const seq = env.
seq(alice);
3844 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3847 jv1[sfTransactionType] = jss::MPTokenIssuanceSet;
3848 jv1[sfAccount] = alice.human();
3849 jv1[sfDelegate] = bob.human();
3850 jv1[sfSequence] =
seq + 1;
3851 jv1[sfMPTokenIssuanceID] =
to_string(mptID);
3855 jv2[sfTransactionType] = jss::MPTokenIssuanceSet;
3856 jv2[sfAccount] = alice.human();
3857 jv2[sfDelegate] = bob.human();
3858 jv2[sfSequence] =
seq + 2;
3859 jv2[sfMPTokenIssuanceID] =
to_string(mptID);
3862 auto const [txIDs, batchID] = submitBatch(
3872 {1,
"MPTokenIssuanceSet",
"tesSUCCESS", txIDs[0], batchID},
3873 {2,
"MPTokenIssuanceSet",
"tesSUCCESS", txIDs[1], batchID},
3875 validateClosedLedger(env, testCases);
3886 env.fund(
XRP(10000), gw, alice, bob);
3889 env(trust(alice, gw[
"USD"](50)));
3893 gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
3896 auto const seq = env.
seq(gw);
3897 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3899 auto jv1 = trust(gw, gw[
"USD"](0), alice,
tfSetfAuth);
3900 jv1[sfDelegate] = bob.human();
3901 auto jv2 = trust(gw, gw[
"USD"](0), alice,
tfSetFreeze);
3902 jv2[sfDelegate] = bob.human();
3904 auto const [txIDs, batchID] = submitBatch(
3914 {1,
"TrustSet",
"tesSUCCESS", txIDs[0], batchID},
3915 {2,
"TrustSet",
"tesSUCCESS", txIDs[1], batchID},
3917 validateClosedLedger(env, testCases);
3926 env.fund(
XRP(10000), gw, alice, bob);
3929 env(trust(alice, gw[
"USD"](50)));
3933 gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
3936 auto const seq = env.
seq(gw);
3937 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3939 auto jv1 = trust(gw, gw[
"USD"](0), alice,
tfSetFreeze);
3940 jv1[sfDelegate] = bob.human();
3942 jv2[sfDelegate] = bob.human();
3944 auto const [txIDs, batchID] = submitBatch(
3955 {1,
"TrustSet",
"tesSUCCESS", txIDs[0], batchID},
3956 {2,
"TrustSet",
"tecNO_DELEGATE_PERMISSION", txIDs[1], batchID},
3958 validateClosedLedger(env, testCases);
3968 testcase(
"Validate RPC response");
3970 using namespace jtx;
3974 env.
fund(
XRP(10000), alice, bob);
3979 auto const baseFee = env.
current()->fees().base;
3980 auto const aliceSeq = env.
seq(alice);
3981 auto jtx = env.
jt(pay(alice, bob,
XRP(1)));
3985 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
3988 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
3990 jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
3991 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
3993 jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
3994 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
3995 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
3996 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
4001 auto const baseFee = env.
current()->fees().base;
4002 auto const aliceSeq = env.
seq(alice);
4004 auto jtx = env.
jt(pay(alice, bob,
XRP(1)),
seq(aliceSeq));
4008 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
4011 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
4013 jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
4014 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
4016 jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
4017 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
4018 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
4019 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
4024 auto const baseFee = env.
current()->fees().base;
4025 auto const aliceSeq = env.
seq(alice);
4026 auto jtx = env.
jt(pay(alice, bob,
XRP(1)),
seq(aliceSeq + 1));
4030 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
4033 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
4035 jr[jss::account_sequence_available].asUInt() == aliceSeq);
4036 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
4037 BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq);
4038 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
4039 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
4040 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
4047 using namespace jtx;
4052 env.
fund(
XRP(10000), alice, bob, carol);
4063 auto const seq = env.
seq(alice);
4064 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
4070 XRPAmount const txBaseFee = getBaseFee(jtx);
4076 auto const seq = env.
seq(alice);
4077 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
4091 XRPAmount const txBaseFee = getBaseFee(jtx);
4097 auto const seq = env.
seq(alice);
4098 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
4115 XRPAmount const txBaseFee = getBaseFee(jtx);
4121 auto const seq = env.
seq(alice);
4122 XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2);
4127 XRPAmount const txBaseFee = getBaseFee(jtx);
4128 BEAST_EXPECT(txBaseFee == batchFee);
4135 testEnable(features);
4136 testPreflight(features);
4137 testPreclaim(features);
4138 testBadRawTxn(features);
4139 testBadSequence(features);
4140 testBadOuterFee(features);
4141 testCalculateBaseFee(features);
4142 testAllOrNothing(features);
4143 testOnlyOne(features);
4144 testUntilFailure(features);
4145 testIndependent(features);
4146 testInnerSubmitRPC(features);
4147 testAccountActivation(features);
4148 testAccountSet(features);
4149 testAccountDelete(features);
4150 testObjectCreateSequence(features);
4151 testObjectCreateTicket(features);
4152 testObjectCreate3rdParty(features);
4153 testTickets(features);
4154 testSequenceOpenLedger(features);
4155 testTicketsOpenLedger(features);
4156 testObjectsOpenLedger(features);
4157 testPseudoTxn(features);
4158 testOpenLedger(features);
4159 testBatchTxQueue(features);
4160 testBatchNetworkOps(features);
4161 testBatchDelegate(features);
4162 testValidateRPCResponse(features);
4163 testBatchCalculateBaseFee(features);
4170 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.