21#include <test/jtx/TestHelpers.h>
22#include <test/jtx/utility.h>
24#include <xrpld/app/misc/HashRouter.h>
25#include <xrpld/app/misc/NetworkOPs.h>
26#include <xrpld/app/misc/Transaction.h>
27#include <xrpld/app/tx/apply.h>
28#include <xrpld/app/tx/detail/Batch.h>
30#include <xrpl/protocol/Batch.h>
31#include <xrpl/protocol/Feature.h>
32#include <xrpl/protocol/STParsedJSON.h>
33#include <xrpl/protocol/Sign.h>
34#include <xrpl/protocol/TxFlags.h>
35#include <xrpl/protocol/jss.h>
60 for (
auto const& txn : jrr[jss::result][jss::ledger][jss::transactions])
62 if (txn[jss::metaData][sfTransactionIndex.jsonName] == index)
72 params[jss::ledger_index] = env.
closed()->seq();
73 params[jss::transactions] =
true;
74 params[jss::expand] =
true;
85 BEAST_EXPECT(jrr[sfTransactionType.jsonName] == ledgerResult.
txType);
87 jrr[jss::meta][sfTransactionResult.jsonName] ==
89 BEAST_EXPECT(jrr[jss::meta][sfParentBatchID.jsonName] == batchID);
98 auto const transactions =
99 jrr[jss::result][jss::ledger][jss::transactions];
100 BEAST_EXPECT(transactions.size() == ledgerResults.
size());
104 BEAST_EXPECT(txn[jss::hash].asString() == ledgerResult.txHash);
105 BEAST_EXPECT(txn.isMember(jss::metaData));
108 txn[sfTransactionType.jsonName] == ledgerResult.txType);
110 meta[sfTransactionResult.jsonName] == ledgerResult.result);
111 if (ledgerResult.batchID)
116 template <
typename... Args>
123 auto const ids = batchTxn.stx->getBatchTransactionIDs();
125 for (
auto const&
id : ids)
127 TxID const batchID = batchTxn.stx->getTransactionID();
143 auto& section = p->section(
"transaction_queue");
144 section.set(
"ledgers_in_queue",
"2");
145 section.set(
"minimum_queue_size",
"2");
146 section.set(
"min_ledgers_to_compute_size_limit",
"3");
147 section.set(
"max_ledger_counts_to_store",
"100");
148 section.set(
"retry_sequence_percent",
"25");
149 section.set(
"normal_consensus_increase_percent",
"0");
151 for (
auto const& [k, v] : extraTxQ)
162 auto const& view = *env.
current();
164 return toDrops(metrics.openLedgerFeeLevel, batchFee) + 1;
172 using namespace test::jtx;
175 for (
bool const withBatch : {
true,
false})
177 auto const amend = withBatch ? features : features - featureBatch;
180 auto const alice =
Account(
"alice");
181 auto const bob =
Account(
"bob");
182 auto const carol =
Account(
"carol");
183 env.fund(
XRP(10000), alice, bob, carol);
188 auto const seq = env.
seq(alice);
190 auto const txResult =
204 auto const txResult =
206 env(
pay(alice, bob,
XRP(1)),
221 using namespace test::jtx;
229 auto const alice =
Account(
"alice");
230 auto const bob =
Account(
"bob");
231 auto const carol =
Account(
"carol");
232 env.fund(
XRP(10000), alice, bob, carol);
245 auto const seq = env.
seq(alice);
254 auto const seq = env.
seq(alice);
263 auto const seq = env.
seq(alice);
273 auto const seq = env.
seq(alice);
282 auto const seq = env.
seq(alice);
293 auto const seq = env.
seq(alice);
312 auto const seq = env.
seq(alice);
313 auto jt = env.jtnofill(
325 auto const seq = env.
seq(alice);
339 auto const seq = env.
seq(alice);
342 auto jt = env.jtnofill(
353 auto const seq = env.
seq(alice);
355 auto jt = env.jt(
pay(alice, bob,
XRP(1)));
365 auto const seq = env.
seq(alice);
367 auto tx1 =
pay(alice, bob,
XRP(1));
370 tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfAccount.jsonName] =
372 tx1[sfSigners.jsonName][0U][sfSigner.jsonName]
373 [sfSigningPubKey.jsonName] =
strHex(alice.pk());
374 tx1[sfSigners.jsonName][0U][sfSigner.jsonName]
375 [sfTxnSignature.jsonName] =
"DEADBEEF";
386 auto const seq = env.
seq(alice);
389 tx1[jss::SigningPubKey] =
strHex(alice.pk());
390 auto jt = env.jtnofill(
401 auto const seq = env.
seq(alice);
413 auto const seq = env.
seq(alice);
416 tx1[jss::Fee] =
to_string(env.current()->fees().base);
427 auto const seq = env.
seq(alice);
430 tx1[jss::Sequence] =
seq + 1;
441 auto const seq = env.
seq(alice);
452 auto const seq = env.
seq(alice);
463 auto const seq = env.
seq(alice);
474 auto const seq = env.
seq(alice);
487 auto const seq = env.
seq(alice);
509 auto const seq = env.
seq(alice);
521 auto const seq = env.
seq(alice);
534 auto const seq = env.
seq(alice);
546 auto const seq = env.
seq(alice);
558 auto const seq = env.
seq(alice);
559 auto const bobSeq = env.seq(bob);
561 auto jt = env.jtnofill(
570 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
571 [sfAccount.jsonName] = bob.human();
572 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
573 [sfSigningPubKey.jsonName] =
strHex(alice.pk());
574 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName]
575 [sfTxnSignature.jsonName] =
584 auto const seq = env.
seq(alice);
601 using namespace test::jtx;
609 auto const alice =
Account(
"alice");
610 auto const bob =
Account(
"bob");
611 auto const carol =
Account(
"carol");
612 auto const dave =
Account(
"dave");
613 auto const elsa =
Account(
"elsa");
614 auto const frank =
Account(
"frank");
615 auto const phantom =
Account(
"phantom");
616 env.memoize(phantom);
618 env.fund(
XRP(10000), alice, bob, carol, dave, elsa, frank);
626 auto const seq = env.
seq(alice);
641 auto const seq = env.
seq(alice);
651 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
654 env(
signers(bob, 2, {{carol, 1}, {dave, 1}, {elsa, 1}}));
659 auto const seq = env.
seq(alice);
671 auto const seq = env.
seq(alice);
676 batch::msig(bob, {carol, Account(
"dave", KeyType::ed25519)}),
685 auto const seq = env.
seq(alice);
697 auto const seq = env.
seq(alice);
709 auto const seq = env.
seq(alice);
723 auto const seq = env.
seq(alice);
727 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
728 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
729 batch::msig(bob, {carol, Reg{dave, davo}}),
736 auto const seq = env.seq(alice);
739 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
740 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
741 batch::msig(bob, {carol}),
748 auto const seq = env.seq(alice);
751 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
752 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
753 batch::msig(bob, {carol, dave}),
760 auto const seq = env.seq(alice);
763 batch::inner(
pay(alice, bob,
XRP(10)), seq + 1),
764 batch::inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
765 batch::msig(bob, {carol, dave}),
776 auto const ledSeq = env.current()->seq();
777 auto const seq = env.seq(alice);
780 batch::inner(
pay(alice, phantom,
XRP(1000)), seq + 1),
781 batch::inner(
noop(phantom), ledSeq),
782 batch::sig(Reg{phantom, carol}),
789 auto const ledSeq = env.current()->seq();
790 auto const seq = env.seq(alice);
793 batch::inner(
pay(alice, bob,
XRP(1000)), seq + 1),
794 batch::inner(
noop(bob), ledSeq),
795 batch::sig(Reg{bob, carol}),
803 auto const seq = env.seq(alice);
806 batch::inner(
pay(alice, bob,
XRP(1)), seq + 1),
807 batch::inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
808 batch::sig(Reg{bob, carol}),
815 auto const seq = env.seq(alice);
818 batch::inner(
pay(alice, bob,
XRP(1)), seq + 1),
819 batch::inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
829 auto const seq = env.seq(alice);
832 batch::inner(
pay(alice, bob,
XRP(1)), seq + 1),
833 batch::inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
843 testcase(
"bad raw txn");
845 using namespace test::jtx;
850 auto const alice =
Account(
"alice");
851 auto const bob =
Account(
"bob");
853 env.fund(
XRP(10000), alice, bob);
857 auto const batchFee = batch::calcBatchFee(env, 1, 2);
858 auto const seq = env.
seq(alice);
860 tx1.removeMember(jss::TransactionType);
861 auto jt = env.jtnofill(
872 auto const batchFee = batch::calcBatchFee(env, 1, 2);
873 auto const seq = env.
seq(alice);
875 tx1.removeMember(jss::Account);
876 auto jt = env.jtnofill(
887 auto const batchFee = batch::calcBatchFee(env, 1, 2);
888 auto const seq = env.
seq(alice);
890 tx1.removeMember(jss::Sequence);
891 auto jt = env.jtnofill(
902 auto const batchFee = batch::calcBatchFee(env, 1, 2);
903 auto const seq = env.
seq(alice);
905 tx1.removeMember(jss::Fee);
906 auto jt = env.jtnofill(
917 auto const batchFee = batch::calcBatchFee(env, 1, 2);
918 auto const seq = env.
seq(alice);
920 tx1.removeMember(jss::SigningPubKey);
921 auto jt = env.jtnofill(
934 testcase(
"bad sequence");
936 using namespace test::jtx;
941 auto const alice =
Account(
"alice");
942 auto const bob =
Account(
"bob");
944 auto const USD = gw[
"USD"];
946 env.fund(
XRP(10000), alice, bob, gw);
948 env.trust(USD(1000), alice, bob);
949 env(pay(gw, alice, USD(100)));
950 env(pay(gw, bob, USD(100)));
958 auto const preAliceSeq = env.seq(alice);
959 auto const preAlice = env.balance(alice);
960 auto const preAliceUSD = env.balance(alice, USD.issue());
961 auto const preBobSeq = env.seq(bob);
962 auto const preBob = env.balance(bob);
963 auto const preBobUSD = env.balance(bob, USD.issue());
965 auto const batchFee = batch::calcBatchFee(env, 1, 2);
966 auto const [txIDs, batchID] = submitBatch(
979 validateClosedLedger(env, testCases);
986 validateClosedLedger(env, testCases);
990 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
991 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
992 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
993 BEAST_EXPECT(env.seq(bob) == preBobSeq);
994 BEAST_EXPECT(env.balance(bob) == preBob);
995 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1000 auto const preAliceSeq = env.seq(alice);
1001 auto const preAlice = env.balance(alice);
1002 auto const preAliceUSD = env.balance(alice, USD.issue());
1003 auto const preBobSeq = env.seq(bob);
1004 auto const preBob = env.balance(bob);
1005 auto const preBobUSD = env.balance(bob, USD.issue());
1007 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1008 auto const [txIDs, batchID] = submitBatch(
1021 validateClosedLedger(env, testCases);
1028 validateClosedLedger(env, testCases);
1032 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1033 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1034 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1035 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1036 BEAST_EXPECT(env.balance(bob) == preBob);
1037 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1042 auto const preAliceSeq = env.seq(alice);
1043 auto const preAlice = env.balance(alice);
1044 auto const preAliceUSD = env.balance(alice, USD.issue());
1045 auto const preBobSeq = env.seq(bob);
1046 auto const preBob = env.balance(bob);
1047 auto const preBobUSD = env.balance(bob, USD.issue());
1049 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1050 auto const [txIDs, batchID] = submitBatch(
1063 validateClosedLedger(env, testCases);
1070 validateClosedLedger(env, testCases);
1074 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1075 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1076 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1077 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1078 BEAST_EXPECT(env.balance(bob) == preBob);
1079 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1084 auto const preAliceSeq = env.seq(alice);
1085 auto const preAlice = env.balance(alice);
1086 auto const preAliceUSD = env.balance(alice, USD.issue());
1087 auto const preBobSeq = env.seq(bob);
1088 auto const preBob = env.balance(bob);
1089 auto const preBobUSD = env.balance(bob, USD.issue());
1091 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1092 auto const [txIDs, batchID] = submitBatch(
1105 validateClosedLedger(env, testCases);
1112 validateClosedLedger(env, testCases);
1116 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1117 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1118 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1119 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1120 BEAST_EXPECT(env.balance(bob) == preBob);
1121 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1126 auto const preAliceSeq = env.seq(alice);
1127 auto const preAlice = env.balance(alice);
1128 auto const preAliceUSD = env.balance(alice, USD.issue());
1129 auto const preBobSeq = env.seq(bob);
1130 auto const preBob = env.balance(bob);
1131 auto const preBobUSD = env.balance(bob, USD.issue());
1133 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1134 auto const [txIDs, batchID] = submitBatch(
1147 validateClosedLedger(env, testCases);
1154 validateClosedLedger(env, testCases);
1158 BEAST_EXPECT(env.seq(alice) == preAliceSeq + 1);
1159 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1160 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
1161 BEAST_EXPECT(env.seq(bob) == preBobSeq);
1162 BEAST_EXPECT(env.balance(bob) == preBob);
1163 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
1170 testcase(
"bad outer fee");
1172 using namespace test::jtx;
1179 auto const alice =
Account(
"alice");
1180 auto const bob =
Account(
"bob");
1181 env.fund(
XRP(10000), alice, bob);
1188 auto const batchFee = batch::calcBatchFee(env, 0, 1);
1189 auto const aliceSeq = env.seq(alice);
1201 auto const alice =
Account(
"alice");
1202 auto const bob =
Account(
"bob");
1203 auto const carol =
Account(
"carol");
1204 env.fund(
XRP(10000), alice, bob, carol);
1210 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
1214 auto const batchFee = batch::calcBatchFee(env, 1, 2);
1215 auto const aliceSeq = env.seq(alice);
1228 auto const alice =
Account(
"alice");
1229 auto const bob =
Account(
"bob");
1230 auto const carol =
Account(
"carol");
1231 env.fund(
XRP(10000), alice, bob, carol);
1237 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
1241 auto const batchFee = batch::calcBatchFee(env, 2, 2);
1242 auto const aliceSeq = env.seq(alice);
1243 auto const bobSeq = env.seq(bob);
1257 auto const alice =
Account(
"alice");
1258 auto const bob =
Account(
"bob");
1259 auto const carol =
Account(
"carol");
1260 env.fund(
XRP(10000), alice, bob, carol);
1266 env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
1269 env(signers(bob, 2, {{alice, 1}, {carol, 1}}));
1273 auto const batchFee = batch::calcBatchFee(env, 3, 2);
1274 auto const aliceSeq = env.seq(alice);
1275 auto const bobSeq = env.seq(bob);
1289 auto const alice =
Account(
"alice");
1290 auto const bob =
Account(
"bob");
1291 env.fund(
XRP(10000), alice, bob);
1298 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1299 auto const aliceSeq = env.seq(alice);
1300 auto const bobSeq = env.seq(bob);
1313 auto const alice =
Account(
"alice");
1314 auto const bob =
Account(
"bob");
1315 auto const gw =
Account(
"gw");
1316 auto const USD = gw[
"USD"];
1318 env.fund(
XRP(10000), alice, bob, gw);
1320 auto const ammCreate =
1323 jv[jss::Account] = alice.human();
1326 jv[jss::TradingFee] = 0;
1327 jv[jss::TransactionType] = jss::AMMCreate;
1331 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1332 auto const seq = env.
seq(alice);
1344 testcase(
"calculate base fee");
1346 using namespace test::jtx;
1353 auto const alice =
Account(
"alice");
1354 auto const bob =
Account(
"bob");
1355 env.fund(
XRP(10000), alice, bob);
1358 auto const batchFee = batch::calcBatchFee(env, 0, 9);
1359 auto const aliceSeq = env.seq(alice);
1378 auto const alice =
Account(
"alice");
1379 auto const bob =
Account(
"bob");
1380 env.fund(
XRP(10000), alice, bob);
1383 auto const batchFee = batch::calcBatchFee(env, 0, 9);
1384 auto const aliceSeq = env.seq(alice);
1385 auto jt = env.jtnofill(
1397 env.app().openLedger().modify(
1403 return result.applied;
1411 auto const alice =
Account(
"alice");
1412 auto const bob =
Account(
"bob");
1413 env.fund(
XRP(10000), alice, bob);
1416 auto const aliceSeq = env.seq(alice);
1417 auto const batchFee = batch::calcBatchFee(env, 9, 2);
1421 batch::sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob),
1430 auto const alice =
Account(
"alice");
1431 auto const bob =
Account(
"bob");
1432 env.fund(
XRP(10000), alice, bob);
1435 auto const batchFee = batch::calcBatchFee(env, 0, 9);
1436 auto const aliceSeq = env.seq(alice);
1437 auto jt = env.jtnofill(
1441 batch::sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob));
1443 env.app().openLedger().modify(
1449 return result.applied;
1457 testcase(
"all or nothing");
1459 using namespace test::jtx;
1464 auto const alice =
Account(
"alice");
1465 auto const bob =
Account(
"bob");
1466 auto const gw =
Account(
"gw");
1467 auto const USD = gw[
"USD"];
1468 env.fund(
XRP(10000), alice, bob, gw);
1473 auto const preAlice = env.balance(alice);
1474 auto const preBob = env.balance(bob);
1476 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1477 auto const seq = env.
seq(alice);
1478 auto const [txIDs, batchID] = submitBatch(
1488 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1489 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1491 validateClosedLedger(env, testCases);
1494 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
1497 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
1498 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
1503 auto const preAlice = env.balance(alice);
1504 auto const preBob = env.balance(bob);
1506 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1507 auto const seq = env.
seq(alice);
1509 auto const [txIDs, batchID] = submitBatch(
1521 validateClosedLedger(env, testCases);
1524 BEAST_EXPECT(env.seq(alice) ==
seq + 1);
1527 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1528 BEAST_EXPECT(env.balance(bob) == preBob);
1533 auto const preAlice = env.balance(alice);
1534 auto const preBob = env.balance(bob);
1536 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1537 auto const seq = env.
seq(alice);
1538 auto const [txIDs, batchID] = submitBatch(
1550 validateClosedLedger(env, testCases);
1553 BEAST_EXPECT(env.seq(alice) ==
seq + 1);
1556 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1557 BEAST_EXPECT(env.balance(bob) == preBob);
1562 auto const preAlice = env.balance(alice);
1563 auto const preBob = env.balance(bob);
1565 auto const batchFee = batch::calcBatchFee(env, 0, 2);
1566 auto const seq = env.
seq(alice);
1567 auto const [txIDs, batchID] = submitBatch(
1579 validateClosedLedger(env, testCases);
1582 BEAST_EXPECT(env.seq(alice) ==
seq + 1);
1585 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1586 BEAST_EXPECT(env.balance(bob) == preBob);
1593 testcase(
"only one");
1595 using namespace test::jtx;
1600 auto const alice =
Account(
"alice");
1601 auto const bob =
Account(
"bob");
1602 auto const carol =
Account(
"carol");
1603 auto const dave =
Account(
"dave");
1604 auto const gw =
Account(
"gw");
1605 auto const USD = gw[
"USD"];
1606 env.fund(
XRP(10000), alice, bob, carol, dave, gw);
1611 auto const preAlice = env.balance(alice);
1612 auto const preBob = env.balance(bob);
1614 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1615 auto const seq = env.
seq(alice);
1616 auto const [txIDs, batchID] = submitBatch(
1630 {1,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[0], batchID},
1631 {2,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[1], batchID},
1632 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
1634 validateClosedLedger(env, testCases);
1637 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
1640 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1641 BEAST_EXPECT(env.balance(bob) == preBob);
1646 auto const preAlice = env.balance(alice);
1647 auto const preBob = env.balance(bob);
1649 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1650 auto const seq = env.
seq(alice);
1651 auto const [txIDs, batchID] = submitBatch(
1663 {1,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[0], batchID},
1664 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1666 validateClosedLedger(env, testCases);
1669 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
1672 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
1673 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1678 auto const preAlice = env.balance(alice);
1679 auto const preBob = env.balance(bob);
1681 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1682 auto const seq = env.
seq(alice);
1683 auto const [txIDs, batchID] = submitBatch(
1695 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1697 validateClosedLedger(env, testCases);
1700 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1703 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
1704 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1709 auto const preAlice = env.balance(alice);
1710 auto const preBob = env.balance(bob);
1712 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1713 auto const seq = env.
seq(alice);
1714 auto const [txIDs, batchID] = submitBatch(
1726 {1,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1728 validateClosedLedger(env, testCases);
1731 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1734 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(1));
1735 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1740 auto const preAlice = env.balance(alice);
1741 auto const preBob = env.balance(bob);
1743 auto const batchFee = batch::calcBatchFee(env, 0, 3);
1744 auto const seq = env.
seq(alice);
1745 auto const [txIDs, batchID] = submitBatch(
1757 {1,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1759 validateClosedLedger(env, testCases);
1762 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1765 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(1));
1766 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
1771 auto const preAlice = env.balance(alice);
1772 auto const preBob = env.balance(bob);
1773 auto const preCarol = env.balance(carol);
1774 auto const seq = env.
seq(alice);
1775 auto const batchFee = batch::calcBatchFee(env, 0, 6);
1777 auto const [txIDs, batchID] = submitBatch(
1809 {1,
"OfferCreate",
"tecKILLED", txIDs[0], batchID},
1810 {2,
"OfferCreate",
"tecKILLED", txIDs[1], batchID},
1811 {3,
"OfferCreate",
"tecKILLED", txIDs[2], batchID},
1812 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
1814 validateClosedLedger(env, testCases);
1816 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(100) - batchFee);
1817 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(100));
1818 BEAST_EXPECT(env.balance(carol) == preCarol);
1825 testcase(
"until failure");
1827 using namespace test::jtx;
1832 auto const alice =
Account(
"alice");
1833 auto const bob =
Account(
"bob");
1834 auto const carol =
Account(
"carol");
1835 auto const dave =
Account(
"dave");
1836 auto const gw =
Account(
"gw");
1837 auto const USD = gw[
"USD"];
1838 env.fund(
XRP(10000), alice, bob, carol, dave, gw);
1843 auto const preAlice = env.balance(alice);
1844 auto const preBob = env.balance(bob);
1846 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1847 auto const seq = env.
seq(alice);
1848 auto const [txIDs, batchID] = submitBatch(
1861 {1,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[0], batchID},
1863 validateClosedLedger(env, testCases);
1866 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
1869 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
1870 BEAST_EXPECT(env.balance(bob) == preBob);
1875 auto const preAlice = env.balance(alice);
1876 auto const preBob = env.balance(bob);
1878 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1879 auto const seq = env.
seq(alice);
1880 auto const [txIDs, batchID] = submitBatch(
1892 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1893 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1894 {3,
"Payment",
"tesSUCCESS", txIDs[2], batchID},
1895 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
1897 validateClosedLedger(env, testCases);
1900 BEAST_EXPECT(env.seq(alice) ==
seq + 5);
1903 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(10) - batchFee);
1904 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(10));
1909 auto const preAlice = env.balance(alice);
1910 auto const preBob = env.balance(bob);
1912 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1913 auto const seq = env.
seq(alice);
1914 auto const [txIDs, batchID] = submitBatch(
1927 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1928 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1929 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
1931 validateClosedLedger(env, testCases);
1934 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
1937 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
1938 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
1943 auto const preAlice = env.balance(alice);
1944 auto const preBob = env.balance(bob);
1946 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1947 auto const seq = env.
seq(alice);
1948 auto const [txIDs, batchID] = submitBatch(
1961 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1962 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1964 validateClosedLedger(env, testCases);
1967 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
1970 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
1971 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
1976 auto const preAlice = env.balance(alice);
1977 auto const preBob = env.balance(bob);
1979 auto const batchFee = batch::calcBatchFee(env, 0, 4);
1980 auto const seq = env.
seq(alice);
1981 auto const [txIDs, batchID] = submitBatch(
1994 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
1995 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
1997 validateClosedLedger(env, testCases);
2000 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
2003 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2004 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2009 auto const preAlice = env.balance(alice);
2010 auto const preBob = env.balance(bob);
2011 auto const preCarol = env.balance(carol);
2012 auto const seq = env.
seq(alice);
2013 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2014 auto const [txIDs, batchID] = submitBatch(
2032 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2033 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2034 {3,
"OfferCreate",
"tecKILLED", txIDs[2], batchID},
2036 validateClosedLedger(env, testCases);
2038 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(200) - batchFee);
2039 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(100));
2040 BEAST_EXPECT(env.balance(carol) == preCarol +
XRP(100));
2047 testcase(
"independent");
2049 using namespace test::jtx;
2054 auto const alice =
Account(
"alice");
2055 auto const bob =
Account(
"bob");
2056 auto const carol =
Account(
"carol");
2057 auto const gw =
Account(
"gw");
2058 auto const USD = gw[
"USD"];
2059 env.fund(
XRP(10000), alice, bob, carol, gw);
2064 auto const preAlice = env.balance(alice);
2065 auto const preBob = env.balance(bob);
2067 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2068 auto const seq = env.
seq(alice);
2069 auto const [txIDs, batchID] = submitBatch(
2083 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2084 {2,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[1], batchID},
2085 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
2086 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2088 validateClosedLedger(env, testCases);
2091 BEAST_EXPECT(env.seq(alice) ==
seq + 5);
2094 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(4) - batchFee);
2095 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(4));
2100 auto const preAlice = env.balance(alice);
2101 auto const preBob = env.balance(bob);
2103 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2104 auto const seq = env.
seq(alice);
2105 auto const [txIDs, batchID] = submitBatch(
2118 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2119 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2120 {3,
"Payment",
"tecUNFUNDED_PAYMENT", txIDs[2], batchID},
2121 {4,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2123 validateClosedLedger(env, testCases);
2126 BEAST_EXPECT(env.seq(alice) ==
seq + 5);
2129 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(6) - batchFee);
2130 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(6));
2135 auto const preAlice = env.balance(alice);
2136 auto const preBob = env.balance(bob);
2138 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2139 auto const seq = env.
seq(alice);
2140 auto const [txIDs, batchID] = submitBatch(
2153 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2154 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2155 {3,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2157 validateClosedLedger(env, testCases);
2160 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
2163 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(6));
2164 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(6));
2169 auto const preAlice = env.balance(alice);
2170 auto const preBob = env.balance(bob);
2172 auto const batchFee = batch::calcBatchFee(env, 0, 4);
2173 auto const seq = env.
seq(alice);
2174 auto const [txIDs, batchID] = submitBatch(
2187 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2188 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2189 {3,
"Payment",
"tesSUCCESS", txIDs[3], batchID},
2191 validateClosedLedger(env, testCases);
2194 BEAST_EXPECT(env.seq(alice) ==
seq + 4);
2197 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee -
XRP(6));
2198 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(6));
2203 auto const preAlice = env.balance(alice);
2204 auto const preBob = env.balance(bob);
2205 auto const preCarol = env.balance(carol);
2206 auto const seq = env.
seq(alice);
2207 auto const batchFee = batch::calcBatchFee(env, 0, 3);
2208 auto const [txIDs, batchID] = submitBatch(
2225 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2226 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2227 {3,
"OfferCreate",
"tecKILLED", txIDs[2], batchID},
2229 validateClosedLedger(env, testCases);
2231 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(200) - batchFee);
2232 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(100));
2233 BEAST_EXPECT(env.balance(carol) == preCarol +
XRP(100));
2240 testcase(
"inner submit rpc");
2242 using namespace test::jtx;
2247 auto const alice =
Account(
"alice");
2248 auto const bob =
Account(
"bob");
2250 env.fund(
XRP(10000), alice, bob);
2253 auto submitAndValidate = [&](
Slice const&
slice) {
2254 auto const jrr = env.rpc(
"submit",
strHex(
slice))[jss::result];
2256 jrr[jss::status] ==
"error" &&
2257 jrr[jss::error] ==
"invalidTransaction" &&
2258 jrr[jss::error_exception] ==
2259 "fails local checks: Malformed: Invalid inner batch "
2271 txn[sfTxnSignature] =
"DEADBEEF";
2275 submitAndValidate(s.
slice());
2285 txn[sfSigningPubKey] =
strHex(alice.pk());
2289 submitAndValidate(s.
slice());
2303 submitAndValidate(s.
slice());
2316 auto const jrr = env.rpc(
"submit",
strHex(s.
slice()))[jss::result];
2318 jrr[jss::status] ==
"success" &&
2319 jrr[jss::engine_result] ==
"temINVALID_FLAG");
2328 testcase(
"account activation");
2330 using namespace test::jtx;
2335 auto const alice =
Account(
"alice");
2336 auto const bob =
Account(
"bob");
2337 env.fund(
XRP(10000), alice);
2341 auto const preAlice = env.balance(alice);
2342 auto const ledSeq = env.current()->seq();
2343 auto const seq = env.
seq(alice);
2344 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2345 auto const [txIDs, batchID] = submitBatch(
2356 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2357 {2,
"AccountSet",
"tesSUCCESS", txIDs[1], batchID},
2359 validateClosedLedger(env, testCases);
2362 BEAST_EXPECT(env.seq(alice) ==
seq + 2);
2365 BEAST_EXPECT(env.seq(bob) == ledSeq + 1);
2368 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - batchFee);
2369 BEAST_EXPECT(env.balance(bob) ==
XRP(1000));
2375 testcase(
"account set");
2377 using namespace test::jtx;
2382 auto const alice =
Account(
"alice");
2383 auto const bob =
Account(
"bob");
2384 env.fund(
XRP(10000), alice, bob);
2387 auto const preAlice = env.balance(alice);
2388 auto const preBob = env.balance(bob);
2390 auto const seq = env.
seq(alice);
2391 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2395 auto const [txIDs, batchID] = submitBatch(
2405 {1,
"AccountSet",
"tesSUCCESS", txIDs[0], batchID},
2406 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2408 validateClosedLedger(env, testCases);
2416 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
2419 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
2420 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
2426 testcase(
"account delete");
2428 using namespace test::jtx;
2435 auto const alice =
Account(
"alice");
2436 auto const bob =
Account(
"bob");
2437 env.fund(
XRP(10000), alice, bob);
2441 for (
int i = 0; i < 5; ++i)
2444 auto const preAlice = env.balance(alice);
2445 auto const preBob = env.balance(bob);
2447 auto const seq = env.
seq(alice);
2448 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
2449 env.current()->fees().increment;
2450 auto const [txIDs, batchID] = submitBatch(
2462 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2463 {2,
"AccountDelete",
"tesSUCCESS", txIDs[1], batchID},
2465 validateClosedLedger(env, testCases);
2469 BEAST_EXPECT(env.balance(bob) == preBob + (preAlice - batchFee));
2476 auto const alice =
Account(
"alice");
2477 auto const bob =
Account(
"bob");
2478 env.fund(
XRP(10000), alice, bob);
2482 for (
int i = 0; i < 5; ++i)
2485 auto const preAlice = env.balance(alice);
2486 auto const preBob = env.balance(bob);
2488 env.trust(bob[
"USD"](1000), alice);
2491 auto const seq = env.
seq(alice);
2492 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
2493 env.current()->fees().increment;
2494 auto const [txIDs, batchID] = submitBatch(
2506 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2507 {2,
"AccountDelete",
"tecHAS_OBLIGATIONS", txIDs[1], batchID},
2508 {3,
"Payment",
"tesSUCCESS", txIDs[2], batchID},
2510 validateClosedLedger(env, testCases);
2514 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2521 auto const alice =
Account(
"alice");
2522 auto const bob =
Account(
"bob");
2523 env.fund(
XRP(10000), alice, bob);
2527 for (
int i = 0; i < 5; ++i)
2530 auto const preAlice = env.balance(alice);
2531 auto const preBob = env.balance(bob);
2533 auto const seq = env.
seq(alice);
2534 auto const batchFee = batch::calcBatchFee(env, 0, 2) +
2535 env.current()->fees().increment;
2536 auto const [txIDs, batchID] = submitBatch(
2549 validateClosedLedger(env, testCases);
2553 BEAST_EXPECT(env.balance(bob) == preBob);
2560 testcase(
"object create w/ sequence");
2562 using namespace test::jtx;
2567 auto const alice =
Account(
"alice");
2568 auto const bob =
Account(
"bob");
2569 auto const gw =
Account(
"gw");
2570 auto const USD = gw[
"USD"];
2572 env.fund(
XRP(10000), alice, bob, gw);
2575 env.trust(USD(1000), alice, bob);
2576 env(pay(gw, alice, USD(100)));
2577 env(pay(gw, bob, USD(100)));
2582 auto const aliceSeq = env.seq(alice);
2583 auto const bobSeq = env.seq(bob);
2584 auto const preAlice = env.balance(alice);
2585 auto const preBob = env.balance(bob);
2586 auto const preAliceUSD = env.balance(alice, USD.issue());
2587 auto const preBobUSD = env.balance(bob, USD.issue());
2589 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2590 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
2591 auto const [txIDs, batchID] = submitBatch(
2595 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
2596 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
2602 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
2603 {2,
"CheckCash",
"tesSUCCESS", txIDs[1], batchID},
2605 validateClosedLedger(env, testCases);
2608 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2611 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
2614 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
2615 BEAST_EXPECT(env.balance(bob) == preBob);
2619 env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
2620 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
2628 auto const aliceSeq = env.seq(alice);
2629 auto const bobSeq = env.seq(bob);
2630 auto const preAlice = env.balance(alice);
2631 auto const preBob = env.balance(bob);
2632 auto const preAliceUSD = env.balance(alice, USD.issue());
2633 auto const preBobUSD = env.balance(bob, USD.issue());
2635 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2636 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
2637 auto const [txIDs, batchID] = submitBatch(
2642 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
2643 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
2649 {1,
"CheckCreate",
"tecDST_TAG_NEEDED", txIDs[0], batchID},
2650 {2,
"CheckCash",
"tecNO_ENTRY", txIDs[1], batchID},
2652 validateClosedLedger(env, testCases);
2655 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2658 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
2661 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
2662 BEAST_EXPECT(env.balance(bob) == preBob);
2665 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD);
2666 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD);
2673 testcase(
"object create w/ ticket");
2675 using namespace test::jtx;
2680 auto const alice =
Account(
"alice");
2681 auto const bob =
Account(
"bob");
2682 auto const gw =
Account(
"gw");
2683 auto const USD = gw[
"USD"];
2685 env.fund(
XRP(10000), alice, bob, gw);
2688 env.trust(USD(1000), alice, bob);
2689 env(pay(gw, alice, USD(100)));
2690 env(pay(gw, bob, USD(100)));
2693 auto const aliceSeq = env.seq(alice);
2694 auto const bobSeq = env.seq(bob);
2695 auto const preAlice = env.balance(alice);
2696 auto const preBob = env.balance(bob);
2697 auto const preAliceUSD = env.balance(alice, USD.issue());
2698 auto const preBobUSD = env.balance(bob, USD.issue());
2700 auto const batchFee = batch::calcBatchFee(env, 1, 3);
2701 uint256 const chkID{getCheckIndex(bob, bobSeq + 1)};
2702 auto const [txIDs, batchID] = submitBatch(
2707 batch::inner(check::create(bob, alice, USD(10)), 0, bobSeq + 1),
2708 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq + 1),
2714 {1,
"TicketCreate",
"tesSUCCESS", txIDs[0], batchID},
2715 {2,
"CheckCreate",
"tesSUCCESS", txIDs[1], batchID},
2716 {3,
"CheckCash",
"tesSUCCESS", txIDs[2], batchID},
2718 validateClosedLedger(env, testCases);
2720 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2721 BEAST_EXPECT(env.seq(bob) == bobSeq + 10 + 1);
2722 BEAST_EXPECT(env.balance(alice) == preAlice - batchFee);
2723 BEAST_EXPECT(env.balance(bob) == preBob);
2724 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
2725 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
2731 testcase(
"object create w/ 3rd party");
2733 using namespace test::jtx;
2738 auto const alice =
Account(
"alice");
2739 auto const bob =
Account(
"bob");
2740 auto const carol =
Account(
"carol");
2741 auto const gw =
Account(
"gw");
2742 auto const USD = gw[
"USD"];
2744 env.fund(
XRP(10000), alice, bob, carol, gw);
2747 env.trust(USD(1000), alice, bob);
2748 env(pay(gw, alice, USD(100)));
2749 env(pay(gw, bob, USD(100)));
2752 auto const aliceSeq = env.seq(alice);
2753 auto const bobSeq = env.seq(bob);
2754 auto const carolSeq = env.seq(carol);
2755 auto const preAlice = env.balance(alice);
2756 auto const preBob = env.balance(bob);
2757 auto const preCarol = env.balance(carol);
2758 auto const preAliceUSD = env.balance(alice, USD.issue());
2759 auto const preBobUSD = env.balance(bob, USD.issue());
2761 auto const batchFee = batch::calcBatchFee(env, 2, 2);
2762 uint256 const chkID{getCheckIndex(bob, env.seq(bob))};
2763 auto const [txIDs, batchID] = submitBatch(
2767 batch::inner(check::create(bob, alice, USD(10)), bobSeq),
2768 batch::inner(check::cash(alice, chkID, USD(10)), aliceSeq),
2774 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
2775 {2,
"CheckCash",
"tesSUCCESS", txIDs[1], batchID},
2777 validateClosedLedger(env, testCases);
2779 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
2780 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
2781 BEAST_EXPECT(env.seq(carol) == carolSeq + 1);
2782 BEAST_EXPECT(env.balance(alice) == preAlice);
2783 BEAST_EXPECT(env.balance(bob) == preBob);
2784 BEAST_EXPECT(env.balance(carol) == preCarol - batchFee);
2785 BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD + USD(10));
2786 BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10));
2793 testcase(
"tickets outer");
2795 using namespace test::jtx;
2800 auto const alice =
Account(
"alice");
2801 auto const bob =
Account(
"bob");
2803 env.fund(
XRP(10000), alice, bob);
2807 env(ticket::create(alice, 10));
2810 auto const aliceSeq = env.seq(alice);
2811 auto const preAlice = env.balance(alice);
2812 auto const preBob = env.balance(bob);
2814 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2815 auto const [txIDs, batchID] = submitBatch(
2826 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2827 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2829 validateClosedLedger(env, testCases);
2833 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 9);
2834 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 9);
2836 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
2837 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2838 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2842 testcase(
"tickets inner");
2844 using namespace test::jtx;
2849 auto const alice =
Account(
"alice");
2850 auto const bob =
Account(
"bob");
2852 env.fund(
XRP(10000), alice, bob);
2856 env(ticket::create(alice, 10));
2859 auto const aliceSeq = env.seq(alice);
2860 auto const preAlice = env.balance(alice);
2861 auto const preBob = env.balance(bob);
2863 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2864 auto const [txIDs, batchID] = submitBatch(
2874 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2875 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2877 validateClosedLedger(env, testCases);
2881 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
2882 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
2884 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
2885 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2886 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2890 testcase(
"tickets outer inner");
2892 using namespace test::jtx;
2897 auto const alice =
Account(
"alice");
2898 auto const bob =
Account(
"bob");
2900 env.fund(
XRP(10000), alice, bob);
2904 env(ticket::create(alice, 10));
2907 auto const aliceSeq = env.seq(alice);
2908 auto const preAlice = env.balance(alice);
2909 auto const preBob = env.balance(bob);
2911 auto const batchFee = batch::calcBatchFee(env, 0, 2);
2912 auto const [txIDs, batchID] = submitBatch(
2923 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2924 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2926 validateClosedLedger(env, testCases);
2930 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
2931 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
2933 BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
2934 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
2935 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
2942 testcase(
"sequence open ledger");
2944 using namespace test::jtx;
2947 auto const alice =
Account(
"alice");
2948 auto const bob =
Account(
"bob");
2949 auto const carol =
Account(
"carol");
2959 env.fund(
XRP(10000), alice, bob, carol);
2962 auto const aliceSeq = env.seq(alice);
2963 auto const carolSeq = env.seq(carol);
2966 auto const noopTxn = env.jt(
noop(alice),
seq(aliceSeq + 2));
2967 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
2971 auto const batchFee = batch::calcBatchFee(env, 1, 2);
2972 auto const [txIDs, batchID] = submitBatch(
2984 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
2985 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
2987 validateClosedLedger(env, testCases);
2994 {0,
"AccountSet",
"tesSUCCESS", noopTxnID,
std::nullopt},
2996 validateClosedLedger(env, testCases);
3006 env.fund(
XRP(10000), alice, bob);
3009 auto const aliceSeq = env.seq(alice);
3012 auto const noopTxn = env.jt(
noop(alice),
seq(aliceSeq + 1));
3016 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3017 auto const [txIDs, batchID] = submitBatch(
3028 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3029 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3031 validateClosedLedger(env, testCases);
3038 validateClosedLedger(env, testCases);
3048 env.fund(
XRP(10000), alice, bob);
3051 auto const aliceSeq = env.seq(alice);
3052 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3053 auto const [txIDs, batchID] = submitBatch(
3060 auto const noopTxn = env.jt(
noop(alice),
seq(aliceSeq + 1));
3061 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3068 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3069 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3071 validateClosedLedger(env, testCases);
3078 validateClosedLedger(env, testCases);
3085 env.fund(
XRP(10000), alice, bob, carol);
3088 auto const aliceSeq = env.seq(alice);
3089 auto const carolSeq = env.seq(carol);
3092 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3093 auto const [txIDs, batchID] = submitBatch(
3102 auto const noopTxn = env.jt(
noop(carol),
seq(carolSeq));
3103 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3109 {0,
"AccountSet",
"tesSUCCESS", noopTxnID,
std::nullopt},
3111 {2,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3112 {3,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3114 validateClosedLedger(env, testCases);
3121 validateClosedLedger(env, testCases);
3129 testcase(
"tickets open ledger");
3131 using namespace test::jtx;
3134 auto const alice =
Account(
"alice");
3135 auto const bob =
Account(
"bob");
3143 env.fund(
XRP(10000), alice, bob);
3147 env(ticket::create(alice, 10));
3150 auto const aliceSeq = env.seq(alice);
3153 auto const noopTxn =
3155 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3159 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3160 auto const [txIDs, batchID] = submitBatch(
3172 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3173 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3175 validateClosedLedger(env, testCases);
3182 validateClosedLedger(env, testCases);
3192 env.fund(
XRP(10000), alice, bob);
3196 env(ticket::create(alice, 10));
3199 auto const aliceSeq = env.seq(alice);
3202 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3203 auto const [txIDs, batchID] = submitBatch(
3212 auto const noopTxn =
3220 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3221 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3223 validateClosedLedger(env, testCases);
3230 validateClosedLedger(env, testCases);
3238 testcase(
"objects open ledger");
3240 using namespace test::jtx;
3243 auto const alice =
Account(
"alice");
3244 auto const bob =
Account(
"bob");
3254 env.fund(
XRP(10000), alice, bob);
3258 env(ticket::create(alice, 10));
3261 auto const aliceSeq = env.seq(alice);
3264 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
3265 auto const objTxn = env.jt(check::cash(bob, chkID,
XRP(10)));
3266 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
3270 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3271 auto const [txIDs, batchID] = submitBatch(
3283 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
3284 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3285 {3,
"CheckCash",
"tesSUCCESS", objTxnID,
std::nullopt},
3287 validateClosedLedger(env, testCases);
3294 validateClosedLedger(env, testCases);
3301 env.fund(
XRP(10000), alice, bob);
3305 env(ticket::create(alice, 10));
3308 auto const aliceSeq = env.seq(alice);
3309 auto const bobSeq = env.seq(bob);
3312 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
3313 auto const objTxn = env.jt(check::create(alice, bob,
XRP(10)));
3314 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
3318 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3319 auto const [txIDs, batchID] = submitBatch(
3331 {0,
"CheckCreate",
"tesSUCCESS", objTxnID,
std::nullopt},
3333 {2,
"CheckCash",
"tesSUCCESS", txIDs[0], batchID},
3334 {3,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3336 validateClosedLedger(env, testCases);
3348 env.fund(
XRP(10000), alice, bob);
3352 env(ticket::create(alice, 10));
3355 auto const aliceSeq = env.seq(alice);
3358 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3359 uint256 const chkID{getCheckIndex(alice, aliceSeq)};
3360 auto const [txIDs, batchID] = submitBatch(
3369 auto const objTxn = env.jt(check::cash(bob, chkID,
XRP(10)));
3370 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
3377 {1,
"CheckCreate",
"tesSUCCESS", txIDs[0], batchID},
3378 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3379 {3,
"CheckCash",
"tesSUCCESS", objTxnID,
std::nullopt},
3381 validateClosedLedger(env, testCases);
3389 testcase(
"pseudo txn with tfInnerBatchTxn");
3391 using namespace test::jtx;
3396 auto const alice =
Account(
"alice");
3397 auto const bob =
Account(
"bob");
3398 env.fund(
XRP(10000), alice, bob);
3401 STTx const stx =
STTx(ttAMENDMENT, [&](
auto& obj) {
3402 obj.setAccountID(sfAccount,
AccountID());
3403 obj.setFieldH256(sfAmendment,
uint256(2));
3404 obj.setFieldU32(sfLedgerSequence, env.seq(alice));
3411 BEAST_EXPECT(reason ==
"Cannot submit pseudo transactions.");
3415 return result.applied;
3422 testcase(
"batch open ledger");
3430 using namespace test::jtx;
3434 XRPAmount const baseFee = env.current()->fees().base;
3436 auto const alice =
Account(
"alice");
3437 auto const bob =
Account(
"bob");
3439 env.fund(
XRP(10000), alice, bob);
3445 auto const aliceSeq = env.seq(alice);
3446 auto const preAlice = env.balance(alice);
3447 auto const preBob = env.balance(bob);
3448 auto const bobSeq = env.seq(bob);
3451 auto const payTxn1 = env.jt(pay(alice, bob,
XRP(10)),
seq(aliceSeq));
3452 auto const payTxn1ID =
to_string(payTxn1.stx->getTransactionID());
3456 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3457 auto const [txIDs, batchID] = submitBatch(
3466 auto const payTxn2 = env.jt(pay(bob, alice,
XRP(5)),
seq(bobSeq + 1));
3467 auto const payTxn2ID =
to_string(payTxn2.stx->getTransactionID());
3474 {2,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3475 {3,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3477 validateClosedLedger(env, testCases);
3485 validateClosedLedger(env, testCases);
3489 BEAST_EXPECT(env.seq(alice) == aliceSeq + 3);
3492 BEAST_EXPECT(env.seq(bob) == bobSeq + 2);
3496 env.balance(alice) == preAlice -
XRP(10) - batchFee - baseFee);
3497 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(10) - baseFee);
3503 testcase(
"batch tx queue");
3505 using namespace test::jtx;
3512 makeSmallQueueConfig(
3513 {{
"minimum_txn_in_ledger_standalone",
"2"}}),
3517 auto alice =
Account(
"alice");
3519 auto carol =
Account(
"carol");
3523 env.close(env.now() + 5s, 10000ms);
3525 env.close(env.now() + 5s, 10000ms);
3536 auto const aliceSeq = env.seq(alice);
3537 auto const bobSeq = env.seq(bob);
3538 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3556 openLedgerFee(env, batchFee),
3572 makeSmallQueueConfig(
3573 {{
"minimum_txn_in_ledger_standalone",
"2"}}),
3577 auto alice =
Account(
"alice");
3579 auto carol =
Account(
"carol");
3583 env.close(env.now() + 5s, 10000ms);
3585 env.close(env.now() + 5s, 10000ms);
3592 auto const aliceSeq = env.seq(alice);
3593 auto const bobSeq = env.seq(bob);
3594 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3615 testcase(
"batch network ops");
3617 using namespace test::jtx;
3627 auto alice =
Account(
"alice");
3629 env.
fund(
XRP(10000), alice, bob);
3637 return jt.stx->getTransactionID();
3649 return transaction->getID();
3674 testcase(
"batch delegate");
3676 using namespace test::jtx;
3683 auto const alice =
Account(
"alice");
3684 auto const bob =
Account(
"bob");
3685 auto const gw =
Account(
"gw");
3686 auto const USD = gw[
"USD"];
3687 env.fund(
XRP(10000), alice, bob, gw);
3690 env(delegate::set(alice, bob, {
"Payment"}));
3693 auto const preAlice = env.balance(alice);
3694 auto const preBob = env.balance(bob);
3696 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3697 auto const seq = env.
seq(alice);
3700 tx[jss::Delegate] = bob.human();
3701 auto const [txIDs, batchID] = submitBatch(
3711 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3712 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3714 validateClosedLedger(env, testCases);
3717 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
3720 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(3) - batchFee);
3721 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(3));
3728 auto const alice =
Account(
"alice");
3729 auto const bob =
Account(
"bob");
3730 auto const carol =
Account(
"carol");
3731 auto const gw =
Account(
"gw");
3732 auto const USD = gw[
"USD"];
3733 env.fund(
XRP(10000), alice, bob, carol, gw);
3736 env(delegate::set(bob, carol, {
"Payment"}));
3739 auto const preAlice = env.balance(alice);
3740 auto const preBob = env.balance(bob);
3741 auto const preCarol = env.balance(carol);
3743 auto const batchFee = batch::calcBatchFee(env, 1, 2);
3744 auto const aliceSeq = env.seq(alice);
3745 auto const bobSeq = env.seq(bob);
3748 tx[jss::Delegate] = carol.human();
3749 auto const [txIDs, batchID] = submitBatch(
3760 {1,
"Payment",
"tesSUCCESS", txIDs[0], batchID},
3761 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3763 validateClosedLedger(env, testCases);
3765 BEAST_EXPECT(env.seq(alice) == aliceSeq + 2);
3766 BEAST_EXPECT(env.seq(bob) == bobSeq + 1);
3767 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1) - batchFee);
3768 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(1));
3771 BEAST_EXPECT(env.balance(carol) == preCarol);
3780 auto const alice =
Account(
"alice");
3781 auto const bob =
Account(
"bob");
3782 auto const gw =
Account(
"gw");
3783 auto const USD = gw[
"USD"];
3784 env.fund(
XRP(10000), alice, bob, gw);
3787 env(delegate::set(alice, bob, {
"AccountDomainSet"}));
3790 auto const preAlice = env.balance(alice);
3791 auto const preBob = env.balance(bob);
3793 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3794 auto const seq = env.
seq(alice);
3799 tx[jss::Delegate] = bob.human();
3800 auto const [txIDs, batchID] = submitBatch(
3810 {1,
"AccountSet",
"tesSUCCESS", txIDs[0], batchID},
3811 {2,
"Payment",
"tesSUCCESS", txIDs[1], batchID},
3813 validateClosedLedger(env, testCases);
3816 BEAST_EXPECT(env.seq(alice) ==
seq + 3);
3819 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(2) - batchFee);
3820 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(2));
3830 env.fund(
XRP(100000), alice, bob);
3833 auto const mptID =
makeMptID(env.seq(alice), alice);
3834 MPTTester mpt(env, alice, {.fund =
false});
3841 alice, bob, {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"}));
3844 auto const seq = env.
seq(alice);
3845 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3848 jv1[sfTransactionType] = jss::MPTokenIssuanceSet;
3849 jv1[sfAccount] = alice.human();
3850 jv1[sfDelegate] = bob.human();
3851 jv1[sfSequence] =
seq + 1;
3852 jv1[sfMPTokenIssuanceID] =
to_string(mptID);
3856 jv2[sfTransactionType] = jss::MPTokenIssuanceSet;
3857 jv2[sfAccount] = alice.human();
3858 jv2[sfDelegate] = bob.human();
3859 jv2[sfSequence] =
seq + 2;
3860 jv2[sfMPTokenIssuanceID] =
to_string(mptID);
3863 auto const [txIDs, batchID] = submitBatch(
3873 {1,
"MPTokenIssuanceSet",
"tesSUCCESS", txIDs[0], batchID},
3874 {2,
"MPTokenIssuanceSet",
"tesSUCCESS", txIDs[1], batchID},
3876 validateClosedLedger(env, testCases);
3887 env.fund(
XRP(10000), gw, alice, bob);
3890 env(trust(alice, gw[
"USD"](50)));
3894 gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
3897 auto const seq = env.
seq(gw);
3898 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3900 auto jv1 = trust(gw, gw[
"USD"](0), alice,
tfSetfAuth);
3901 jv1[sfDelegate] = bob.human();
3902 auto jv2 = trust(gw, gw[
"USD"](0), alice,
tfSetFreeze);
3903 jv2[sfDelegate] = bob.human();
3905 auto const [txIDs, batchID] = submitBatch(
3915 {1,
"TrustSet",
"tesSUCCESS", txIDs[0], batchID},
3916 {2,
"TrustSet",
"tesSUCCESS", txIDs[1], batchID},
3918 validateClosedLedger(env, testCases);
3927 env.fund(
XRP(10000), gw, alice, bob);
3930 env(trust(alice, gw[
"USD"](50)));
3934 gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
3937 auto const seq = env.
seq(gw);
3938 auto const batchFee = batch::calcBatchFee(env, 0, 2);
3940 auto jv1 = trust(gw, gw[
"USD"](0), alice,
tfSetFreeze);
3941 jv1[sfDelegate] = bob.human();
3943 jv2[sfDelegate] = bob.human();
3945 auto const [txIDs, batchID] = submitBatch(
3956 {1,
"TrustSet",
"tesSUCCESS", txIDs[0], 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.