1#include <test/jtx/Account.h>
2#include <test/jtx/Env.h>
3#include <test/jtx/TestHelpers.h>
4#include <test/jtx/acctdelete.h>
5#include <test/jtx/amount.h>
6#include <test/jtx/balance.h>
7#include <test/jtx/batch.h>
8#include <test/jtx/check.h>
9#include <test/jtx/delegate.h>
10#include <test/jtx/envconfig.h>
11#include <test/jtx/fee.h>
12#include <test/jtx/flags.h>
13#include <test/jtx/mpt.h>
14#include <test/jtx/multisign.h>
15#include <test/jtx/noop.h>
16#include <test/jtx/offer.h>
17#include <test/jtx/pay.h>
18#include <test/jtx/regkey.h>
19#include <test/jtx/seq.h>
20#include <test/jtx/sig.h>
21#include <test/jtx/tags.h>
22#include <test/jtx/ter.h>
23#include <test/jtx/ticket.h>
24#include <test/jtx/trust.h>
25#include <test/jtx/txflags.h>
26#include <test/jtx/utility.h>
27#include <test/jtx/vault.h>
29#include <xrpld/app/misc/Transaction.h>
30#include <xrpld/app/misc/TxQ.h>
32#include <xrpl/basics/base_uint.h>
33#include <xrpl/basics/strHex.h>
34#include <xrpl/beast/unit_test/suite.h>
35#include <xrpl/beast/utility/Journal.h>
36#include <xrpl/config/BasicConfig.h>
37#include <xrpl/config/Constants.h>
38#include <xrpl/core/HashRouter.h>
39#include <xrpl/json/json_value.h>
40#include <xrpl/json/to_string.h>
41#include <xrpl/ledger/ApplyView.h>
42#include <xrpl/ledger/OpenView.h>
43#include <xrpl/protocol/AccountID.h>
44#include <xrpl/protocol/Batch.h>
45#include <xrpl/protocol/Feature.h>
46#include <xrpl/protocol/Indexes.h>
47#include <xrpl/protocol/Issue.h>
48#include <xrpl/protocol/KeyType.h>
49#include <xrpl/protocol/LedgerFormats.h>
50#include <xrpl/protocol/Protocol.h>
51#include <xrpl/protocol/SField.h>
52#include <xrpl/protocol/STParsedJSON.h>
53#include <xrpl/protocol/STTx.h>
54#include <xrpl/protocol/SecretKey.h>
55#include <xrpl/protocol/Serializer.h>
56#include <xrpl/protocol/SystemParameters.h>
57#include <xrpl/protocol/TER.h>
58#include <xrpl/protocol/TxFlags.h>
59#include <xrpl/protocol/TxFormats.h>
60#include <xrpl/protocol/Units.h>
61#include <xrpl/protocol/XRPAmount.h>
62#include <xrpl/protocol/jss.h>
63#include <xrpl/server/NetworkOPs.h>
64#include <xrpl/tx/apply.h>
65#include <xrpl/tx/transactors/system/Batch.h>
99 for (
auto const& txn : jrr[jss::result][jss::ledger][jss::transactions])
101 if (txn[jss::metaData][sfTransactionIndex.jsonName] == index)
111 params[jss::ledger_index] = env.
closed()->seq();
112 params[jss::transactions] =
true;
113 params[jss::expand] =
true;
121 BEAST_EXPECT(jrr[sfTransactionType.jsonName] == ledgerResult.
txType);
122 BEAST_EXPECT(jrr[jss::meta][sfTransactionResult.jsonName] == ledgerResult.
result);
123 BEAST_EXPECT(jrr[jss::meta][sfParentBatchID.jsonName] == batchID);
130 auto const transactions = jrr[jss::result][jss::ledger][jss::transactions];
135 BEAST_EXPECT(txn[jss::hash].asString() == ledgerResult.txHash);
136 BEAST_EXPECT(txn.isMember(jss::metaData));
138 BEAST_EXPECT(txn[sfTransactionType.jsonName] == ledgerResult.txType);
139 BEAST_EXPECT(meta[sfTransactionResult.jsonName] == ledgerResult.result);
140 if (ledgerResult.batchID)
145 template <
typename... Args>
152 auto const ids = batchTxn.stx->getBatchTransactionIDs();
155 for (
auto const&
id : ids)
157 TxID const batchID = batchTxn.stx->getTransactionID();
181 for (
auto const& [k, v] : extraTxQ)
192 auto const& view = *env.
current();
203 bool const withInnerSigFix = features[fixBatchInnerSigs];
205 for (
bool const withBatch : {
true,
false})
207 testcase <<
"enabled: Batch " << (withBatch ?
"enabled" :
"disabled")
208 <<
", Inner Sig Fix: " << (withInnerSigFix ?
"enabled" :
"disabled");
210 auto const amend = withBatch ? features : features - featureBatch;
214 auto const alice =
Account(
"alice");
215 auto const bob =
Account(
"bob");
216 auto const carol =
Account(
"carol");
217 env.
fund(
XRP(10000), alice, bob, carol);
222 auto const seq = env.
seq(alice);
259 auto const alice =
Account(
"alice");
260 auto const bob =
Account(
"bob");
261 auto const carol =
Account(
"carol");
262 env.
fund(
XRP(10000), alice, bob, carol);
274 auto const seq = env.
seq(alice);
282 auto const seq = env.
seq(alice);
290 auto const seq = env.
seq(alice);
293 Txflags(tfAllOrNothing | tfOnlyOne),
300 auto const seq = env.
seq(alice);
308 auto const seq = env.
seq(alice);
319 auto const seq = env.
seq(alice);
338 auto const seq = env.
seq(alice);
351 auto const seq = env.
seq(alice);
364 auto const seq = env.
seq(alice);
378 auto const seq = env.
seq(alice);
380 auto jt = env.
jt(
pay(alice, bob,
XRP(1)));
390 auto const seq = env.
seq(alice);
392 auto tx1 =
pay(alice, bob,
XRP(1));
395 tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfAccount.jsonName] = alice.human();
396 tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfSigningPubKey.jsonName] =
398 tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfTxnSignature.jsonName] =
"DEADBEEF";
409 auto const seq = env.
seq(alice);
412 tx1[jss::SigningPubKey] =
strHex(alice.pk());
424 auto const seq = env.
seq(alice);
436 auto const seq = env.
seq(alice);
449 auto const seq = env.
seq(alice);
452 tx1[jss::Fee] =
"-1";
462 auto const seq = env.
seq(alice);
465 tx1[jss::Fee] =
"1.5";
472 fail(
"Expected parse_error for fractional fee");
484 auto const seq = env.
seq(alice);
487 tx1[jss::Sequence] = seq + 1;
498 auto const seq = env.
seq(alice);
509 auto const seq = env.
seq(alice);
520 auto const seq = env.
seq(alice);
531 auto const seq = env.
seq(alice);
544 auto const seq = env.
seq(alice);
549 batch::Sig(bob, carol, alice, bob, carol, alice, bob, carol, alice, alice),
556 auto const seq = env.
seq(alice);
568 auto const seq = env.
seq(alice);
581 auto const seq = env.
seq(alice);
593 auto const seq = env.
seq(alice);
605 auto const seq = env.
seq(alice);
606 auto const bobSeq = env.
seq(bob);
614 serializeBatch(msg, tfAllOrNothing, jt.stx->getBatchTransactionIDs());
616 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfAccount.jsonName] =
618 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfSigningPubKey.jsonName] =
620 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfTxnSignature.jsonName] =
629 auto const seq = env.
seq(alice);
654 auto const alice =
Account(
"alice");
655 auto const bob =
Account(
"bob");
656 auto const carol =
Account(
"carol");
657 auto const dave =
Account(
"dave");
658 auto const elsa =
Account(
"elsa");
659 auto const frank =
Account(
"frank");
660 auto const phantom =
Account(
"phantom");
663 env.
fund(
XRP(10000), alice, bob, carol, dave, elsa, frank);
671 auto const seq = env.
seq(alice);
686 auto const seq = env.
seq(alice);
696 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
699 env(
signers(bob, 2, {{carol, 1}, {dave, 1}, {elsa, 1}}));
704 auto const seq = env.
seq(alice);
716 auto const seq = env.
seq(alice);
721 batch::Msig(bob, {carol, Account(
"dave", KeyType::Ed25519)}),
729 env(
fset(elsa, asfDisableMaster),
Sig(elsa));
730 auto const seq = env.
seq(alice);
742 auto const seq = env.
seq(alice);
754 auto const seq = env.
seq(alice);
768 auto const seq = env.seq(alice);
772 batch::Inner(
pay(alice, bob,
XRP(10)), seq + 1),
773 batch::Inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
774 batch::Msig(bob, {carol, Reg{dave, davo}}),
781 auto const seq = env.seq(alice);
784 batch::Inner(
pay(alice, bob,
XRP(10)), seq + 1),
785 batch::Inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
786 batch::Msig(bob, {carol}),
793 auto const seq = env.seq(alice);
796 batch::Inner(
pay(alice, bob,
XRP(10)), seq + 1),
797 batch::Inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
798 batch::Msig(bob, {carol, dave}),
805 auto const seq = env.seq(alice);
808 batch::Inner(
pay(alice, bob,
XRP(10)), seq + 1),
809 batch::Inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
810 batch::Msig(bob, {carol, dave}),
821 auto const ledSeq = env.current()->seq();
822 auto const seq = env.seq(alice);
825 batch::Inner(
pay(alice, phantom,
XRP(1000)), seq + 1),
826 batch::Inner(
noop(phantom), ledSeq),
827 batch::Sig(
Reg{phantom, carol}),
834 auto const ledSeq = env.current()->seq();
835 auto const seq = env.seq(alice);
838 batch::Inner(
pay(alice, bob,
XRP(1000)), seq + 1),
839 batch::Inner(
noop(bob), ledSeq),
840 batch::Sig(
Reg{bob, carol}),
848 auto const seq = env.seq(alice);
851 batch::Inner(
pay(alice, bob,
XRP(1)), seq + 1),
852 batch::Inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
853 batch::Sig(
Reg{bob, carol}),
860 auto const seq = env.seq(alice);
863 batch::Inner(
pay(alice, bob,
XRP(1)), seq + 1),
864 batch::Inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
873 env(
fset(bob, asfDisableMaster),
Sig(bob));
874 auto const seq = env.seq(alice);
877 batch::Inner(
pay(alice, bob,
XRP(1)), seq + 1),
878 batch::Inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
895 auto const alice =
Account(
"alice");
896 auto const bob =
Account(
"bob");
898 env.
fund(
XRP(10000), alice, bob);
903 auto const seq = env.
seq(alice);
905 tx1.removeMember(jss::TransactionType);
918 auto const seq = env.
seq(alice);
920 tx1.removeMember(jss::Account);
933 auto const seq = env.
seq(alice);
935 tx1.removeMember(jss::Sequence);
948 auto const seq = env.
seq(alice);
950 tx1.removeMember(jss::Fee);
963 auto const seq = env.
seq(alice);
965 tx1.removeMember(jss::SigningPubKey);
986 auto const alice =
Account(
"alice");
987 auto const bob =
Account(
"bob");
989 auto const usd = gw[
"USD"];
991 env.
fund(
XRP(10000), alice, bob, gw);
993 env.
trust(usd(1000), alice, bob);
994 env(
pay(gw, alice, usd(100)));
995 env(
pay(gw, bob, usd(100)));
1003 auto const preAliceSeq = env.
seq(alice);
1004 auto const preAlice = env.
balance(alice);
1005 auto const preAliceUSD = env.
balance(alice, usd.issue());
1006 auto const preBobSeq = env.
seq(bob);
1007 auto const preBob = env.
balance(bob);
1008 auto const preBobUSD = env.
balance(bob, usd.issue());
1014 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1024 .result =
"tesSUCCESS",
1026 .batchID = std::nullopt},
1039 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1040 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1041 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1042 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1043 BEAST_EXPECT(env.
balance(bob) == preBob);
1044 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1049 auto const preAliceSeq = env.
seq(alice);
1050 auto const preAlice = env.
balance(alice);
1051 auto const preAliceUSD = env.
balance(alice, usd.issue());
1052 auto const preBobSeq = env.
seq(bob);
1053 auto const preBob = env.
balance(bob);
1054 auto const preBobUSD = env.
balance(bob, usd.issue());
1060 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1070 .result =
"tesSUCCESS",
1072 .batchID = std::nullopt},
1085 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1086 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1087 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1088 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1089 BEAST_EXPECT(env.
balance(bob) == preBob);
1090 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1095 auto const preAliceSeq = env.
seq(alice);
1096 auto const preAlice = env.
balance(alice);
1097 auto const preAliceUSD = env.
balance(alice, usd.issue());
1098 auto const preBobSeq = env.
seq(bob);
1099 auto const preBob = env.
balance(bob);
1100 auto const preBobUSD = env.
balance(bob, usd.issue());
1106 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1116 .result =
"tesSUCCESS",
1118 .batchID = std::nullopt},
1131 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1132 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1133 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1134 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1135 BEAST_EXPECT(env.
balance(bob) == preBob);
1136 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1141 auto const preAliceSeq = env.
seq(alice);
1142 auto const preAlice = env.
balance(alice);
1143 auto const preAliceUSD = env.
balance(alice, usd.issue());
1144 auto const preBobSeq = env.
seq(bob);
1145 auto const preBob = env.
balance(bob);
1146 auto const preBobUSD = env.
balance(bob, usd.issue());
1152 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1162 .result =
"tesSUCCESS",
1164 .batchID = std::nullopt},
1177 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1178 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1179 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1180 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1181 BEAST_EXPECT(env.
balance(bob) == preBob);
1182 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1187 auto const preAliceSeq = env.
seq(alice);
1188 auto const preAlice = env.
balance(alice);
1189 auto const preAliceUSD = env.
balance(alice, usd.issue());
1190 auto const preBobSeq = env.
seq(bob);
1191 auto const preBob = env.
balance(bob);
1192 auto const preBobUSD = env.
balance(bob, usd.issue());
1198 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1208 .result =
"tesSUCCESS",
1210 .batchID = std::nullopt},
1223 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1224 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1225 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1226 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1227 BEAST_EXPECT(env.
balance(bob) == preBob);
1228 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1244 auto const alice =
Account(
"alice");
1245 auto const bob =
Account(
"bob");
1246 env.
fund(
XRP(10000), alice, bob);
1254 auto const aliceSeq = env.
seq(alice);
1255 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1266 auto const alice =
Account(
"alice");
1267 auto const bob =
Account(
"bob");
1268 auto const carol =
Account(
"carol");
1269 env.
fund(
XRP(10000), alice, bob, carol);
1275 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
1280 auto const aliceSeq = env.
seq(alice);
1281 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1293 auto const alice =
Account(
"alice");
1294 auto const bob =
Account(
"bob");
1295 auto const carol =
Account(
"carol");
1296 env.
fund(
XRP(10000), alice, bob, carol);
1302 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
1307 auto const aliceSeq = env.
seq(alice);
1308 auto const bobSeq = env.
seq(bob);
1309 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1322 auto const alice =
Account(
"alice");
1323 auto const bob =
Account(
"bob");
1324 auto const carol =
Account(
"carol");
1325 env.
fund(
XRP(10000), alice, bob, carol);
1331 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
1334 env(
signers(bob, 2, {{alice, 1}, {carol, 1}}));
1339 auto const aliceSeq = env.
seq(alice);
1340 auto const bobSeq = env.
seq(bob);
1341 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1354 auto const alice =
Account(
"alice");
1355 auto const bob =
Account(
"bob");
1356 env.
fund(
XRP(10000), alice, bob);
1364 auto const aliceSeq = env.
seq(alice);
1365 auto const bobSeq = env.
seq(bob);
1366 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1378 auto const alice =
Account(
"alice");
1379 auto const bob =
Account(
"bob");
1380 auto const gw =
Account(
"gw");
1381 auto const usd = gw[
"USD"];
1383 env.
fund(
XRP(10000), alice, bob, gw);
1385 auto const ammCreate = [&alice](
STAmount const& amount,
STAmount const& amount2) {
1387 jv[jss::Account] = alice.human();
1390 jv[jss::TradingFee] = 0;
1391 jv[jss::TransactionType] = jss::AMMCreate;
1396 auto const seq = env.
seq(alice);
1397 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
1417 auto const alice =
Account(
"alice");
1418 auto const bob =
Account(
"bob");
1419 env.
fund(
XRP(10000), alice, bob);
1423 auto const aliceSeq = env.
seq(alice);
1424 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1442 auto const alice =
Account(
"alice");
1443 auto const bob =
Account(
"bob");
1444 env.
fund(
XRP(10000), alice, bob);
1448 auto const aliceSeq = env.
seq(alice);
1450 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1464 return result.applied;
1472 auto const alice =
Account(
"alice");
1473 auto const bob =
Account(
"bob");
1474 env.
fund(
XRP(10000), alice, bob);
1477 auto const aliceSeq = env.
seq(alice);
1479 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1482 batch::Sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob),
1491 auto const alice =
Account(
"alice");
1492 auto const bob =
Account(
"bob");
1493 env.
fund(
XRP(10000), alice, bob);
1497 auto const aliceSeq = env.
seq(alice);
1499 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1502 batch::Sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob));
1507 return result.applied;
1522 auto const alice =
Account(
"alice");
1523 auto const bob =
Account(
"bob");
1524 auto const gw =
Account(
"gw");
1525 auto const usd = gw[
"USD"];
1526 env.
fund(
XRP(10000), alice, bob, gw);
1531 auto const preAlice = env.
balance(alice);
1532 auto const preBob = env.
balance(bob);
1535 auto const seq = env.
seq(alice);
1547 .result =
"tesSUCCESS",
1549 .batchID = std::nullopt},
1551 .txType =
"Payment",
1552 .result =
"tesSUCCESS",
1554 .batchID = batchID},
1556 .txType =
"Payment",
1557 .result =
"tesSUCCESS",
1559 .batchID = batchID},
1564 BEAST_EXPECT(env.
seq(alice) == seq + 3);
1567 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
1568 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
1573 auto const preAlice = env.
balance(alice);
1574 auto const preBob = env.
balance(bob);
1577 auto const seq = env.
seq(alice);
1591 .result =
"tesSUCCESS",
1593 .batchID = std::nullopt},
1598 BEAST_EXPECT(env.
seq(alice) == seq + 1);
1601 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1602 BEAST_EXPECT(env.
balance(bob) == preBob);
1607 auto const preAlice = env.
balance(alice);
1608 auto const preBob = env.
balance(bob);
1611 auto const seq = env.
seq(alice);
1624 .result =
"tesSUCCESS",
1626 .batchID = std::nullopt},
1631 BEAST_EXPECT(env.
seq(alice) == seq + 1);
1634 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1635 BEAST_EXPECT(env.
balance(bob) == preBob);
1640 auto const preAlice = env.
balance(alice);
1641 auto const preBob = env.
balance(bob);
1644 auto const seq = env.
seq(alice);
1657 .result =
"tesSUCCESS",
1659 .batchID = std::nullopt},
1664 BEAST_EXPECT(env.
seq(alice) == seq + 1);
1667 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1668 BEAST_EXPECT(env.
balance(bob) == preBob);
1682 auto const alice =
Account(
"alice");
1683 auto const bob =
Account(
"bob");
1684 auto const carol =
Account(
"carol");
1685 auto const dave =
Account(
"dave");
1686 auto const gw =
Account(
"gw");
1687 auto const usd = gw[
"USD"];
1688 env.
fund(
XRP(10000), alice, bob, carol, dave, gw);
1693 auto const preAlice = env.
balance(alice);
1694 auto const preBob = env.
balance(bob);
1697 auto const seq = env.
seq(alice);
1713 .result =
"tesSUCCESS",
1715 .batchID = std::nullopt},
1717 .txType =
"Payment",
1718 .result =
"tecUNFUNDED_PAYMENT",
1720 .batchID = batchID},
1722 .txType =
"Payment",
1723 .result =
"tecUNFUNDED_PAYMENT",
1725 .batchID = batchID},
1727 .txType =
"Payment",
1728 .result =
"tecUNFUNDED_PAYMENT",
1730 .batchID = batchID},
1735 BEAST_EXPECT(env.
seq(alice) == seq + 4);
1738 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1739 BEAST_EXPECT(env.
balance(bob) == preBob);
1744 auto const preAlice = env.
balance(alice);
1745 auto const preBob = env.
balance(bob);
1748 auto const seq = env.
seq(alice);
1762 .result =
"tesSUCCESS",
1764 .batchID = std::nullopt},
1766 .txType =
"Payment",
1767 .result =
"tecUNFUNDED_PAYMENT",
1769 .batchID = batchID},
1771 .txType =
"Payment",
1772 .result =
"tesSUCCESS",
1774 .batchID = batchID},
1779 BEAST_EXPECT(env.
seq(alice) == seq + 3);
1782 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1) - batchFee);
1783 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
1788 auto const preAlice = env.
balance(alice);
1789 auto const preBob = env.
balance(bob);
1792 auto const seq = env.
seq(alice);
1806 .result =
"tesSUCCESS",
1808 .batchID = std::nullopt},
1810 .txType =
"Payment",
1811 .result =
"tesSUCCESS",
1813 .batchID = batchID},
1818 BEAST_EXPECT(env.
seq(alice) == seq + 2);
1821 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1) - batchFee);
1822 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
1827 auto const preAlice = env.
balance(alice);
1828 auto const preBob = env.
balance(bob);
1831 auto const seq = env.
seq(alice);
1845 .result =
"tesSUCCESS",
1847 .batchID = std::nullopt},
1849 .txType =
"Payment",
1850 .result =
"tesSUCCESS",
1852 .batchID = batchID},
1857 BEAST_EXPECT(env.
seq(alice) == seq + 2);
1860 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee -
XRP(1));
1861 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
1866 auto const preAlice = env.
balance(alice);
1867 auto const preBob = env.
balance(bob);
1870 auto const seq = env.
seq(alice);
1884 .result =
"tesSUCCESS",
1886 .batchID = std::nullopt},
1888 .txType =
"Payment",
1889 .result =
"tesSUCCESS",
1891 .batchID = batchID},
1896 BEAST_EXPECT(env.
seq(alice) == seq + 2);
1899 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee -
XRP(1));
1900 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
1905 auto const preAlice = env.
balance(alice);
1906 auto const preBob = env.
balance(bob);
1907 auto const preCarol = env.
balance(carol);
1908 auto const seq = env.
seq(alice);
1916 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 1),
1918 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 2),
1920 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 3),
1929 .result =
"tesSUCCESS",
1931 .batchID = std::nullopt},
1933 .txType =
"OfferCreate",
1934 .result =
"tecKILLED",
1936 .batchID = batchID},
1938 .txType =
"OfferCreate",
1939 .result =
"tecKILLED",
1941 .batchID = batchID},
1943 .txType =
"OfferCreate",
1944 .result =
"tecKILLED",
1946 .batchID = batchID},
1948 .txType =
"Payment",
1949 .result =
"tesSUCCESS",
1951 .batchID = batchID},
1955 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(100) - batchFee);
1956 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(100));
1957 BEAST_EXPECT(env.
balance(carol) == preCarol);
1971 auto const alice =
Account(
"alice");
1972 auto const bob =
Account(
"bob");
1973 auto const carol =
Account(
"carol");
1974 auto const dave =
Account(
"dave");
1975 auto const gw =
Account(
"gw");
1976 auto const usd = gw[
"USD"];
1977 env.
fund(
XRP(10000), alice, bob, carol, dave, gw);
1982 auto const preAlice = env.
balance(alice);
1983 auto const preBob = env.
balance(bob);
1986 auto const seq = env.
seq(alice);
2001 .result =
"tesSUCCESS",
2003 .batchID = std::nullopt},
2005 .txType =
"Payment",
2006 .result =
"tecUNFUNDED_PAYMENT",
2008 .batchID = batchID},
2013 BEAST_EXPECT(env.
seq(alice) == seq + 2);
2016 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
2017 BEAST_EXPECT(env.
balance(bob) == preBob);
2022 auto const preAlice = env.
balance(alice);
2023 auto const preBob = env.
balance(bob);
2026 auto const seq = env.
seq(alice);
2040 .result =
"tesSUCCESS",
2042 .batchID = std::nullopt},
2044 .txType =
"Payment",
2045 .result =
"tesSUCCESS",
2047 .batchID = batchID},
2049 .txType =
"Payment",
2050 .result =
"tesSUCCESS",
2052 .batchID = batchID},
2054 .txType =
"Payment",
2055 .result =
"tesSUCCESS",
2057 .batchID = batchID},
2059 .txType =
"Payment",
2060 .result =
"tesSUCCESS",
2062 .batchID = batchID},
2067 BEAST_EXPECT(env.
seq(alice) == seq + 5);
2070 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(10) - batchFee);
2071 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(10));
2076 auto const preAlice = env.
balance(alice);
2077 auto const preBob = env.
balance(bob);
2080 auto const seq = env.
seq(alice);
2095 .result =
"tesSUCCESS",
2097 .batchID = std::nullopt},
2099 .txType =
"Payment",
2100 .result =
"tesSUCCESS",
2102 .batchID = batchID},
2104 .txType =
"Payment",
2105 .result =
"tesSUCCESS",
2107 .batchID = batchID},
2109 .txType =
"Payment",
2110 .result =
"tecUNFUNDED_PAYMENT",
2112 .batchID = batchID},
2117 BEAST_EXPECT(env.
seq(alice) == seq + 4);
2120 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
2121 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
2126 auto const preAlice = env.
balance(alice);
2127 auto const preBob = env.
balance(bob);
2130 auto const seq = env.
seq(alice);
2145 .result =
"tesSUCCESS",
2147 .batchID = std::nullopt},
2149 .txType =
"Payment",
2150 .result =
"tesSUCCESS",
2152 .batchID = batchID},
2154 .txType =
"Payment",
2155 .result =
"tesSUCCESS",
2157 .batchID = batchID},
2162 BEAST_EXPECT(env.
seq(alice) == seq + 3);
2165 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
2166 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
2171 auto const preAlice = env.
balance(alice);
2172 auto const preBob = env.
balance(bob);
2175 auto const seq = env.
seq(alice);
2190 .result =
"tesSUCCESS",
2192 .batchID = std::nullopt},
2194 .txType =
"Payment",
2195 .result =
"tesSUCCESS",
2197 .batchID = batchID},
2199 .txType =
"Payment",
2200 .result =
"tesSUCCESS",
2202 .batchID = batchID},
2207 BEAST_EXPECT(env.
seq(alice) == seq + 3);
2210 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
2211 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
2216 auto const preAlice = env.
balance(alice);
2217 auto const preBob = env.
balance(bob);
2218 auto const preCarol = env.
balance(carol);
2219 auto const seq = env.
seq(alice);
2228 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 3),
2235 .result =
"tesSUCCESS",
2237 .batchID = std::nullopt},
2239 .txType =
"Payment",
2240 .result =
"tesSUCCESS",
2242 .batchID = batchID},
2244 .txType =
"Payment",
2245 .result =
"tesSUCCESS",
2247 .batchID = batchID},
2249 .txType =
"OfferCreate",
2250 .result =
"tecKILLED",
2252 .batchID = batchID},
2256 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(200) - batchFee);
2257 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(100));
2258 BEAST_EXPECT(env.
balance(carol) == preCarol +
XRP(100));
2272 auto const alice =
Account(
"alice");
2273 auto const bob =
Account(
"bob");
2274 auto const carol =
Account(
"carol");
2275 auto const gw =
Account(
"gw");
2276 auto const usd = gw[
"USD"];
2277 env.
fund(
XRP(10000), alice, bob, carol, gw);
2282 auto const preAlice = env.
balance(alice);
2283 auto const preBob = env.
balance(bob);
2286 auto const seq = env.
seq(alice);
2302 .result =
"tesSUCCESS",
2304 .batchID = std::nullopt},
2306 .txType =
"Payment",
2307 .result =
"tesSUCCESS",
2309 .batchID = batchID},
2311 .txType =
"Payment",
2312 .result =
"tecUNFUNDED_PAYMENT",
2314 .batchID = batchID},
2316 .txType =
"Payment",
2317 .result =
"tecUNFUNDED_PAYMENT",
2319 .batchID = batchID},
2321 .txType =
"Payment",
2322 .result =
"tesSUCCESS",
2324 .batchID = batchID},
2329 BEAST_EXPECT(env.
seq(alice) == seq + 5);
2332 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(4) - batchFee);
2333 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(4));
2338 auto const preAlice = env.
balance(alice);
2339 auto const preBob = env.
balance(bob);
2342 auto const seq = env.
seq(alice);
2357 .result =
"tesSUCCESS",
2359 .batchID = std::nullopt},
2361 .txType =
"Payment",
2362 .result =
"tesSUCCESS",
2364 .batchID = batchID},
2366 .txType =
"Payment",
2367 .result =
"tesSUCCESS",
2369 .batchID = batchID},
2371 .txType =
"Payment",
2372 .result =
"tecUNFUNDED_PAYMENT",
2374 .batchID = batchID},
2376 .txType =
"Payment",
2377 .result =
"tesSUCCESS",
2379 .batchID = batchID},
2384 BEAST_EXPECT(env.
seq(alice) == seq + 5);
2387 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(6) - batchFee);
2388 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(6));
2393 auto const preAlice = env.
balance(alice);
2394 auto const preBob = env.
balance(bob);
2397 auto const seq = env.
seq(alice);
2412 .result =
"tesSUCCESS",
2414 .batchID = std::nullopt},
2416 .txType =
"Payment",
2417 .result =
"tesSUCCESS",
2419 .batchID = batchID},
2421 .txType =
"Payment",
2422 .result =
"tesSUCCESS",
2424 .batchID = batchID},
2426 .txType =
"Payment",
2427 .result =
"tesSUCCESS",
2429 .batchID = batchID},
2434 BEAST_EXPECT(env.
seq(alice) == seq + 4);
2437 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee -
XRP(6));
2438 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(6));
2443 auto const preAlice = env.
balance(alice);
2444 auto const preBob = env.
balance(bob);
2447 auto const seq = env.
seq(alice);
2462 .result =
"tesSUCCESS",
2464 .batchID = std::nullopt},
2466 .txType =
"Payment",
2467 .result =
"tesSUCCESS",
2469 .batchID = batchID},
2471 .txType =
"Payment",
2472 .result =
"tesSUCCESS",
2474 .batchID = batchID},
2476 .txType =
"Payment",
2477 .result =
"tesSUCCESS",
2479 .batchID = batchID},
2484 BEAST_EXPECT(env.
seq(alice) == seq + 4);
2487 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee -
XRP(6));
2488 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(6));
2493 auto const preAlice = env.
balance(alice);
2494 auto const preBob = env.
balance(bob);
2495 auto const preCarol = env.
balance(carol);
2496 auto const seq = env.
seq(alice);
2505 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 3));
2511 .result =
"tesSUCCESS",
2513 .batchID = std::nullopt},
2515 .txType =
"Payment",
2516 .result =
"tesSUCCESS",
2518 .batchID = batchID},
2520 .txType =
"Payment",
2521 .result =
"tesSUCCESS",
2523 .batchID = batchID},
2525 .txType =
"OfferCreate",
2526 .result =
"tecKILLED",
2528 .batchID = batchID},
2532 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(200) - batchFee);
2533 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(100));
2534 BEAST_EXPECT(env.
balance(carol) == preCarol +
XRP(100));
2541 bool const withInnerSigFix = features[fixBatchInnerSigs];
2545 ss <<
"inner submit rpc: batch " << (withBatch ?
"enabled" :
"disabled")
2546 <<
", inner sig fix: " << (withInnerSigFix ?
"enabled" :
"disabled") <<
": ";
2550 auto const amend = withBatch ? features : features - featureBatch;
2556 if (!BEAST_EXPECT(amend[featureBatch] == withBatch))
2559 auto const alice =
Account(
"alice");
2560 auto const bob =
Account(
"bob");
2562 env.
fund(
XRP(10000), alice, bob);
2565 auto submitAndValidate = [&](
std::string caseName,
2570 bool expectInvalidFlag =
false) {
2572 << (expectInvalidFlag ?
" - Expected to reach tx engine!" :
"");
2574 auto const expected = withBatch
2575 ? expectedEnabled.value_or(
2576 "fails local checks: Malformed: Invalid inner batch "
2578 : expectedDisabled.value_or(
"fails local checks: Empty SigningPubKey.");
2579 if (expectInvalidFlag)
2582 jrr[jss::status] ==
"success" && jrr[jss::engine_result] ==
"temINVALID_FLAG",
2590 jrr[jss::status] ==
"error" && jrr[jss::error] ==
"invalidTransaction" &&
2591 jrr[jss::error_exception] == expected,
2606 txn[sfTxnSignature] =
"DEADBEEF";
2610 submitAndValidate(
"TxnSignature set", s.
slice(), __LINE__);
2620 txn[sfSigningPubKey] =
strHex(alice.pk());
2625 "SigningPubKey set",
2629 "fails local checks: Invalid signature.");
2648 "fails local checks: Invalid Signers array size.");
2654 auto const jt = env.
jt(txn.getTxn());
2660 "Fully signed", s.
slice(), __LINE__, std::nullopt, std::nullopt, !withBatch);
2674 "No signing fields set",
2677 "fails local checks: Empty SigningPubKey.",
2678 "fails local checks: Empty SigningPubKey.",
2679 withBatch && !withInnerSigFix);
2688 STTx const amendTx(ttAMENDMENT, [seq = env.
closed()->header().seq + 1](
auto& obj) {
2689 obj.setAccountID(sfAccount, AccountID());
2690 obj.setFieldH256(sfAmendment, fixBatchInnerSigs);
2691 obj.setFieldU32(sfLedgerSequence, seq);
2692 obj.setFieldU32(sfFlags, tfInnerBatchTxn);
2699 "Pseudo-transaction",
2702 withInnerSigFix ?
"fails local checks: Empty SigningPubKey."
2703 :
"fails local checks: Cannot submit pseudo transactions.",
2704 "fails local checks: Empty SigningPubKey.");
2711 for (
bool const withBatch : {
true,
false})
2727 auto const alice =
Account(
"alice");
2728 auto const bob =
Account(
"bob");
2733 auto const preAlice = env.
balance(alice);
2734 auto const ledSeq = env.
current()->seq();
2735 auto const seq = env.
seq(alice);
2749 .result =
"tesSUCCESS",
2751 .batchID = std::nullopt},
2753 .txType =
"Payment",
2754 .result =
"tesSUCCESS",
2756 .batchID = batchID},
2758 .txType =
"AccountSet",
2759 .result =
"tesSUCCESS",
2761 .batchID = batchID},
2766 BEAST_EXPECT(env.
seq(alice) == seq + 2);
2769 BEAST_EXPECT(env.
seq(bob) == ledSeq + 1);
2772 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1000) - batchFee);
2786 auto const alice =
Account(
"alice");
2787 auto const bob =
Account(
"bob");
2788 env.
fund(
XRP(10000), alice, bob);
2791 auto const preAlice = env.
balance(alice);
2792 auto const preBob = env.
balance(bob);
2794 auto const seq = env.
seq(alice);
2798 tx1[sfDomain] =
strHex(domain);
2810 .result =
"tesSUCCESS",
2812 .batchID = std::nullopt},
2814 .txType =
"AccountSet",
2815 .result =
"tesSUCCESS",
2817 .batchID = batchID},
2819 .txType =
"Payment",
2820 .result =
"tesSUCCESS",
2822 .batchID = batchID},
2828 BEAST_EXPECT(sle->getFieldVL(sfDomain) ==
Blob(domain.
begin(), domain.
end()));
2831 BEAST_EXPECT(env.
seq(alice) == seq + 3);
2834 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1) - batchFee);
2835 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
2850 auto const alice =
Account(
"alice");
2851 auto const bob =
Account(
"bob");
2852 env.
fund(
XRP(10000), alice, bob);
2856 for (
int i = 0; i < 5; ++i)
2859 auto const preAlice = env.
balance(alice);
2860 auto const preBob = env.
balance(bob);
2862 auto const seq = env.
seq(alice);
2877 .result =
"tesSUCCESS",
2879 .batchID = std::nullopt},
2881 .txType =
"Payment",
2882 .result =
"tesSUCCESS",
2884 .batchID = batchID},
2886 .txType =
"AccountDelete",
2887 .result =
"tesSUCCESS",
2889 .batchID = batchID},
2895 BEAST_EXPECT(env.
balance(bob) == preBob + (preAlice - batchFee));
2902 auto const alice =
Account(
"alice");
2903 auto const bob =
Account(
"bob");
2904 env.
fund(
XRP(10000), alice, bob);
2908 for (
int i = 0; i < 5; ++i)
2911 auto const preAlice = env.
balance(alice);
2912 auto const preBob = env.
balance(bob);
2914 env.
trust(bob[
"USD"](1000), alice);
2917 auto const seq = env.
seq(alice);
2932 .result =
"tesSUCCESS",
2934 .batchID = std::nullopt},
2936 .txType =
"Payment",
2937 .result =
"tesSUCCESS",
2939 .batchID = batchID},
2941 .txType =
"AccountDelete",
2942 .result =
"tecHAS_OBLIGATIONS",
2944 .batchID = batchID},
2946 .txType =
"Payment",
2947 .result =
"tesSUCCESS",
2949 .batchID = batchID},
2955 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
2962 auto const alice =
Account(
"alice");
2963 auto const bob =
Account(
"bob");
2964 env.
fund(
XRP(10000), alice, bob);
2968 for (
int i = 0; i < 5; ++i)
2971 auto const preAlice = env.
balance(alice);
2972 auto const preBob = env.
balance(bob);
2974 auto const seq = env.
seq(alice);
2989 .result =
"tesSUCCESS",
2991 .batchID = std::nullopt},
2997 BEAST_EXPECT(env.
balance(bob) == preBob);
3008 [](
auto const& disabled) {
return disabled == ttLOAN_BROKER_SET; });
3014 Account const issuer{
"issuer"};
3017 Account const lender{
"lender"};
3019 Account const borrower{
"borrower"};
3029 Vault const vault{env};
3031 auto const deposit = asset(50'000);
3032 auto const debtMaximumValue = asset(25'000).value();
3033 auto const coverDepositValue = asset(1000).value();
3035 auto [tx, vaultKeylet] = vault.create({.owner = lender, .asset = asset});
3038 BEAST_EXPECT(env.
le(vaultKeylet));
3040 env(vault.deposit({.depositor = lender, .id = vaultKeylet.key, .amount = deposit}));
3047 env(
set(lender, vaultKeylet.key),
3049 kDebtMaximum(debtMaximumValue),
3053 env(coverDeposit(lender, brokerKeylet.key, coverDepositValue));
3059 using namespace loan;
3060 using namespace std::chrono_literals;
3062 auto const lenderSeq = env.
seq(lender);
3065 auto const loanKeylet =
keylet::loan(brokerKeylet.key, 1);
3070 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3073 set(lender, brokerKeylet.key, asset(1000).value()),
3075 Sig(sfCounterpartySignature, borrower),
3081 pay(lender, loanKeylet.key,
STAmount{asset, asset(500).value()}),
3088 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3091 set(lender, brokerKeylet.key, asset(1000).value()),
3098 pay(lender, loanKeylet.key,
STAmount{asset, asset(500).value()}),
3105 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3108 set(lender, brokerKeylet.key, asset(1000).value()),
3110 kCounterparty(borrower.
id()),
3116 pay(lender, loanKeylet.key,
STAmount{asset, asset(500).value()}),
3127 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3130 set(lender, brokerKeylet.key, asset(1000).value()),
3131 kCounterparty(borrower.
id()),
3143 STAmount{asset, asset(500).value()}),
3148 BEAST_EXPECT(env.
le(brokerKeylet));
3149 BEAST_EXPECT(!env.
le(loanKeylet));
3154 auto const lenderSeq = env.
seq(lender);
3159 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3162 set(lender, brokerKeylet.key, asset(1000).value()),
3163 kCounterparty(borrower.
id()),
3168 batch::Inner(manage(lender, loanKeylet.key, tfLoanImpair), lenderSeq + 2),
3172 BEAST_EXPECT(env.
le(brokerKeylet));
3173 if (
auto const sleLoan = env.
le(loanKeylet);
3174 lendingBatchEnabled ? BEAST_EXPECT(sleLoan) : !BEAST_EXPECT(!sleLoan))
3176 BEAST_EXPECT(sleLoan->isFlag(lsfLoanImpaired));
3184 testcase(
"object create w/ sequence");
3191 auto const alice =
Account(
"alice");
3192 auto const bob =
Account(
"bob");
3193 auto const gw =
Account(
"gw");
3194 auto const usd = gw[
"USD"];
3196 env.
fund(
XRP(10000), alice, bob, gw);
3199 env.
trust(usd(1000), alice, bob);
3200 env(
pay(gw, alice, usd(100)));
3201 env(
pay(gw, bob, usd(100)));
3206 auto const aliceSeq = env.
seq(alice);
3207 auto const bobSeq = env.
seq(bob);
3208 auto const preAlice = env.
balance(alice);
3209 auto const preBob = env.
balance(bob);
3210 auto const preAliceUSD = env.
balance(alice, usd.issue());
3211 auto const preBobUSD = env.
balance(bob, usd.issue());
3218 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3227 .result =
"tesSUCCESS",
3229 .batchID = std::nullopt},
3231 .txType =
"CheckCreate",
3232 .result =
"tesSUCCESS",
3234 .batchID = batchID},
3236 .txType =
"CheckCash",
3237 .result =
"tesSUCCESS",
3239 .batchID = batchID},
3244 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
3247 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
3250 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
3251 BEAST_EXPECT(env.
balance(bob) == preBob);
3254 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD + usd(10));
3255 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD - usd(10));
3260 env(
fset(alice, asfRequireDest));
3263 auto const aliceSeq = env.
seq(alice);
3264 auto const bobSeq = env.
seq(bob);
3265 auto const preAlice = env.
balance(alice);
3266 auto const preBob = env.
balance(bob);
3267 auto const preAliceUSD = env.
balance(alice, usd.issue());
3268 auto const preBobUSD = env.
balance(bob, usd.issue());
3275 batch::outer(alice, aliceSeq, batchFee, tfIndependent),
3285 .result =
"tesSUCCESS",
3287 .batchID = std::nullopt},
3289 .txType =
"CheckCreate",
3290 .result =
"tecDST_TAG_NEEDED",
3292 .batchID = batchID},
3294 .txType =
"CheckCash",
3295 .result =
"tecNO_ENTRY",
3297 .batchID = batchID},
3302 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
3305 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
3308 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
3309 BEAST_EXPECT(env.
balance(bob) == preBob);
3312 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
3313 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
3320 testcase(
"object create w/ ticket");
3327 auto const alice =
Account(
"alice");
3328 auto const bob =
Account(
"bob");
3329 auto const gw =
Account(
"gw");
3330 auto const usd = gw[
"USD"];
3332 env.
fund(
XRP(10000), alice, bob, gw);
3335 env.
trust(usd(1000), alice, bob);
3336 env(
pay(gw, alice, usd(100)));
3337 env(
pay(gw, bob, usd(100)));
3340 auto const aliceSeq = env.
seq(alice);
3341 auto const bobSeq = env.
seq(bob);
3342 auto const preAlice = env.
balance(alice);
3343 auto const preBob = env.
balance(bob);
3344 auto const preAliceUSD = env.
balance(alice, usd.issue());
3345 auto const preBobUSD = env.
balance(bob, usd.issue());
3352 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3362 .result =
"tesSUCCESS",
3364 .batchID = std::nullopt},
3366 .txType =
"TicketCreate",
3367 .result =
"tesSUCCESS",
3369 .batchID = batchID},
3371 .txType =
"CheckCreate",
3372 .result =
"tesSUCCESS",
3374 .batchID = batchID},
3376 .txType =
"CheckCash",
3377 .result =
"tesSUCCESS",
3379 .batchID = batchID},
3383 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
3384 BEAST_EXPECT(env.
seq(bob) == bobSeq + 10 + 1);
3385 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
3386 BEAST_EXPECT(env.
balance(bob) == preBob);
3387 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD + usd(10));
3388 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD - usd(10));
3394 testcase(
"object create w/ 3rd party");
3401 auto const alice =
Account(
"alice");
3402 auto const bob =
Account(
"bob");
3403 auto const carol =
Account(
"carol");
3404 auto const gw =
Account(
"gw");
3405 auto const usd = gw[
"USD"];
3407 env.
fund(
XRP(10000), alice, bob, carol, gw);
3410 env.
trust(usd(1000), alice, bob);
3411 env(
pay(gw, alice, usd(100)));
3412 env(
pay(gw, bob, usd(100)));
3415 auto const aliceSeq = env.
seq(alice);
3416 auto const bobSeq = env.
seq(bob);
3417 auto const carolSeq = env.
seq(carol);
3418 auto const preAlice = env.
balance(alice);
3419 auto const preBob = env.
balance(bob);
3420 auto const preCarol = env.
balance(carol);
3421 auto const preAliceUSD = env.
balance(alice, usd.issue());
3422 auto const preBobUSD = env.
balance(bob, usd.issue());
3429 batch::outer(carol, carolSeq, batchFee, tfAllOrNothing),
3438 .result =
"tesSUCCESS",
3440 .batchID = std::nullopt},
3442 .txType =
"CheckCreate",
3443 .result =
"tesSUCCESS",
3445 .batchID = batchID},
3447 .txType =
"CheckCash",
3448 .result =
"tesSUCCESS",
3450 .batchID = batchID},
3454 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
3455 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
3456 BEAST_EXPECT(env.
seq(carol) == carolSeq + 1);
3457 BEAST_EXPECT(env.
balance(alice) == preAlice);
3458 BEAST_EXPECT(env.
balance(bob) == preBob);
3459 BEAST_EXPECT(env.
balance(carol) == preCarol - batchFee);
3460 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD + usd(10));
3461 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD - usd(10));
3475 auto const alice =
Account(
"alice");
3476 auto const bob =
Account(
"bob");
3478 env.
fund(
XRP(10000), alice, bob);
3485 auto const aliceSeq = env.
seq(alice);
3486 auto const preAlice = env.
balance(alice);
3487 auto const preBob = env.
balance(bob);
3502 .result =
"tesSUCCESS",
3504 .batchID = std::nullopt},
3506 .txType =
"Payment",
3507 .result =
"tesSUCCESS",
3509 .batchID = batchID},
3511 .txType =
"Payment",
3512 .result =
"tesSUCCESS",
3514 .batchID = batchID},
3520 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 9);
3521 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 9);
3523 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
3524 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
3525 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
3536 auto const alice =
Account(
"alice");
3537 auto const bob =
Account(
"bob");
3539 env.
fund(
XRP(10000), alice, bob);
3546 auto const aliceSeq = env.
seq(alice);
3547 auto const preAlice = env.
balance(alice);
3548 auto const preBob = env.
balance(bob);
3554 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3562 .result =
"tesSUCCESS",
3564 .batchID = std::nullopt},
3566 .txType =
"Payment",
3567 .result =
"tesSUCCESS",
3569 .batchID = batchID},
3571 .txType =
"Payment",
3572 .result =
"tesSUCCESS",
3574 .batchID = batchID},
3580 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
3581 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
3583 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
3584 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
3585 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
3596 auto const alice =
Account(
"alice");
3597 auto const bob =
Account(
"bob");
3599 env.
fund(
XRP(10000), alice, bob);
3606 auto const aliceSeq = env.
seq(alice);
3607 auto const preAlice = env.
balance(alice);
3608 auto const preBob = env.
balance(bob);
3623 .result =
"tesSUCCESS",
3625 .batchID = std::nullopt},
3627 .txType =
"Payment",
3628 .result =
"tesSUCCESS",
3630 .batchID = batchID},
3632 .txType =
"Payment",
3633 .result =
"tesSUCCESS",
3635 .batchID = batchID},
3641 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
3642 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
3644 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
3645 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
3646 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
3658 auto const alice =
Account(
"alice");
3659 auto const bob =
Account(
"bob");
3660 auto const carol =
Account(
"carol");
3670 env.
fund(
XRP(10000), alice, bob, carol);
3673 auto const aliceSeq = env.
seq(alice);
3674 auto const carolSeq = env.
seq(carol);
3677 auto const noopTxn = env.
jt(
noop(alice),
Seq(aliceSeq + 2));
3678 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3686 batch::outer(carol, carolSeq, batchFee, tfAllOrNothing),
3696 .result =
"tesSUCCESS",
3698 .batchID = std::nullopt},
3700 .txType =
"Payment",
3701 .result =
"tesSUCCESS",
3703 .batchID = batchID},
3705 .txType =
"Payment",
3706 .result =
"tesSUCCESS",
3708 .batchID = batchID},
3718 .txType =
"AccountSet",
3719 .result =
"tesSUCCESS",
3720 .txHash = noopTxnID,
3721 .batchID = std::nullopt},
3733 env.
fund(
XRP(10000), alice, bob);
3736 auto const aliceSeq = env.
seq(alice);
3739 auto const noopTxn = env.
jt(
noop(alice),
Seq(aliceSeq + 1));
3747 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3756 .result =
"tesSUCCESS",
3758 .batchID = std::nullopt},
3760 .txType =
"Payment",
3761 .result =
"tesSUCCESS",
3763 .batchID = batchID},
3765 .txType =
"Payment",
3766 .result =
"tesSUCCESS",
3768 .batchID = batchID},
3787 env.
fund(
XRP(10000), alice, bob);
3790 auto const aliceSeq = env.
seq(alice);
3795 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3799 auto const noopTxn = env.
jt(
noop(alice),
Seq(aliceSeq + 1));
3807 .result =
"tesSUCCESS",
3809 .batchID = std::nullopt},
3811 .txType =
"Payment",
3812 .result =
"tesSUCCESS",
3814 .batchID = batchID},
3816 .txType =
"Payment",
3817 .result =
"tesSUCCESS",
3819 .batchID = batchID},
3835 env.
fund(
XRP(10000), alice, bob, carol);
3838 auto const aliceSeq = env.
seq(alice);
3839 auto const carolSeq = env.
seq(carol);
3846 batch::outer(carol, carolSeq + 1, batchFee, tfAllOrNothing),
3852 auto const noopTxn = env.
jt(
noop(carol),
Seq(carolSeq));
3853 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3860 .txType =
"AccountSet",
3861 .result =
"tesSUCCESS",
3862 .txHash = noopTxnID,
3863 .batchID = std::nullopt},
3866 .result =
"tesSUCCESS",
3868 .batchID = std::nullopt},
3870 .txType =
"Payment",
3871 .result =
"tesSUCCESS",
3873 .batchID = batchID},
3875 .txType =
"Payment",
3876 .result =
"tesSUCCESS",
3878 .batchID = batchID},
3900 auto const alice =
Account(
"alice");
3901 auto const bob =
Account(
"bob");
3909 env.
fund(
XRP(10000), alice, bob);
3916 auto const aliceSeq = env.
seq(alice);
3937 .result =
"tesSUCCESS",
3939 .batchID = std::nullopt},
3941 .txType =
"Payment",
3942 .result =
"tesSUCCESS",
3944 .batchID = batchID},
3946 .txType =
"Payment",
3947 .result =
"tesSUCCESS",
3949 .batchID = batchID},
3968 env.
fund(
XRP(10000), alice, bob);
3975 auto const aliceSeq = env.
seq(alice);
3996 .result =
"tesSUCCESS",
3998 .batchID = std::nullopt},
4000 .txType =
"Payment",
4001 .result =
"tesSUCCESS",
4003 .batchID = batchID},
4005 .txType =
"Payment",
4006 .result =
"tesSUCCESS",
4008 .batchID = batchID},
4030 auto const alice =
Account(
"alice");
4031 auto const bob =
Account(
"bob");
4041 env.
fund(
XRP(10000), alice, bob);
4048 auto const aliceSeq = env.
seq(alice);
4053 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
4071 .result =
"tesSUCCESS",
4073 .batchID = std::nullopt},
4075 .txType =
"CheckCreate",
4076 .result =
"tesSUCCESS",
4078 .batchID = batchID},
4080 .txType =
"Payment",
4081 .result =
"tesSUCCESS",
4083 .batchID = batchID},
4085 .txType =
"CheckCash",
4086 .result =
"tesSUCCESS",
4088 .batchID = std::nullopt},
4104 env.
fund(
XRP(10000), alice, bob);
4111 auto const aliceSeq = env.
seq(alice);
4112 auto const bobSeq = env.
seq(bob);
4117 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
4135 .txType =
"CheckCreate",
4136 .result =
"tesSUCCESS",
4138 .batchID = std::nullopt},
4141 .result =
"tesSUCCESS",
4143 .batchID = std::nullopt},
4145 .txType =
"CheckCash",
4146 .result =
"tesSUCCESS",
4148 .batchID = batchID},
4150 .txType =
"Payment",
4151 .result =
"tesSUCCESS",
4153 .batchID = batchID},
4167 env.
fund(
XRP(10000), alice, bob);
4174 auto const aliceSeq = env.
seq(alice);
4189 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
4197 .result =
"tesSUCCESS",
4199 .batchID = std::nullopt},
4201 .txType =
"CheckCreate",
4202 .result =
"tesSUCCESS",
4204 .batchID = batchID},
4206 .txType =
"Payment",
4207 .result =
"tesSUCCESS",
4209 .batchID = batchID},
4211 .txType =
"CheckCash",
4212 .result =
"tesSUCCESS",
4214 .batchID = std::nullopt},
4224 testcase(
"pseudo txn with tfInnerBatchTxn");
4231 auto const alice =
Account(
"alice");
4232 auto const bob =
Account(
"bob");
4233 env.
fund(
XRP(10000), alice, bob);
4236 STTx const stx =
STTx(ttAMENDMENT, [&](
auto& obj) {
4237 obj.setAccountID(sfAccount,
AccountID());
4238 obj.setFieldH256(sfAmendment,
uint256(2));
4239 obj.setFieldU32(sfLedgerSequence, env.
seq(alice));
4246 BEAST_EXPECT(reason ==
"Cannot submit pseudo transactions.");
4250 return result.applied;
4271 auto const alice =
Account(
"alice");
4272 auto const bob =
Account(
"bob");
4274 env.
fund(
XRP(10000), alice, bob);
4280 auto const aliceSeq = env.
seq(alice);
4281 auto const preAlice = env.
balance(alice);
4282 auto const preBob = env.
balance(bob);
4283 auto const bobSeq = env.
seq(bob);
4286 auto const payTxn1 = env.
jt(
pay(alice, bob,
XRP(10)),
Seq(aliceSeq));
4287 auto const payTxn1ID =
to_string(payTxn1.stx->getTransactionID());
4295 batch::outer(alice, aliceSeq + 1, batchFee, tfAllOrNothing),
4301 auto const payTxn2 = env.
jt(
pay(bob, alice,
XRP(5)),
Seq(bobSeq + 1));
4302 auto const payTxn2ID =
to_string(payTxn2.stx->getTransactionID());
4308 .txType =
"Payment",
4309 .result =
"tesSUCCESS",
4310 .txHash = payTxn1ID,
4311 .batchID = std::nullopt},
4314 .result =
"tesSUCCESS",
4316 .batchID = std::nullopt},
4318 .txType =
"Payment",
4319 .result =
"tesSUCCESS",
4321 .batchID = batchID},
4323 .txType =
"Payment",
4324 .result =
"tesSUCCESS",
4326 .batchID = batchID},
4335 .txType =
"Payment",
4336 .result =
"tesSUCCESS",
4337 .txHash = payTxn2ID,
4338 .batchID = std::nullopt},
4344 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 3);
4347 BEAST_EXPECT(env.
seq(bob) == bobSeq + 2);
4350 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(10) - batchFee - baseFee);
4351 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(10) - baseFee);
4371 auto alice =
Account(
"alice");
4373 auto carol =
Account(
"carol");
4377 env.
close(env.
now() + 5s, 10000ms);
4379 env.
close(env.
now() + 5s, 10000ms);
4390 auto const aliceSeq = env.
seq(alice);
4391 auto const bobSeq = env.
seq(bob);
4396 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
4427 auto alice =
Account(
"alice");
4429 auto carol =
Account(
"carol");
4433 env.
close(env.
now() + 5s, 10000ms);
4435 env.
close(env.
now() + 5s, 10000ms);
4442 auto const aliceSeq = env.
seq(alice);
4443 auto const bobSeq = env.
seq(bob);
4448 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
4472 auto alice =
Account(
"alice");
4474 env.
fund(
XRP(10000), alice, bob);
4482 return jt.stx->getTransactionID();
4493 return transaction->getID();
4523 auto const alice =
Account(
"alice");
4524 auto const bob =
Account(
"bob");
4525 auto const gw =
Account(
"gw");
4526 auto const usd = gw[
"USD"];
4527 env.
fund(
XRP(10000), alice, bob, gw);
4533 auto const preAlice = env.
balance(alice);
4534 auto const preBob = env.
balance(bob);
4537 auto const seq = env.
seq(alice);
4540 tx[jss::Delegate] = bob.human();
4552 .result =
"tesSUCCESS",
4554 .batchID = std::nullopt},
4556 .txType =
"Payment",
4557 .result =
"tesSUCCESS",
4559 .batchID = batchID},
4561 .txType =
"Payment",
4562 .result =
"tesSUCCESS",
4564 .batchID = batchID},
4569 BEAST_EXPECT(env.
seq(alice) == seq + 3);
4572 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
4573 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
4580 auto const alice =
Account(
"alice");
4581 auto const bob =
Account(
"bob");
4582 auto const carol =
Account(
"carol");
4583 auto const gw =
Account(
"gw");
4584 auto const usd = gw[
"USD"];
4585 env.
fund(
XRP(10000), alice, bob, carol, gw);
4591 auto const preAlice = env.
balance(alice);
4592 auto const preBob = env.
balance(bob);
4593 auto const preCarol = env.
balance(carol);
4596 auto const aliceSeq = env.
seq(alice);
4597 auto const bobSeq = env.
seq(bob);
4600 tx[jss::Delegate] = carol.human();
4604 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
4613 .result =
"tesSUCCESS",
4615 .batchID = std::nullopt},
4617 .txType =
"Payment",
4618 .result =
"tesSUCCESS",
4620 .batchID = batchID},
4622 .txType =
"Payment",
4623 .result =
"tesSUCCESS",
4625 .batchID = batchID},
4629 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
4630 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
4631 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1) - batchFee);
4632 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
4635 BEAST_EXPECT(env.
balance(carol) == preCarol);
4644 auto const alice =
Account(
"alice");
4645 auto const bob =
Account(
"bob");
4646 auto const gw =
Account(
"gw");
4647 auto const usd = gw[
"USD"];
4648 env.
fund(
XRP(10000), alice, bob, gw);
4654 auto const preAlice = env.
balance(alice);
4655 auto const preBob = env.
balance(bob);
4658 auto const seq = env.
seq(alice);
4662 tx[sfDomain.jsonName] =
strHex(domain);
4663 tx[jss::Delegate] = bob.human();
4675 .result =
"tesSUCCESS",
4677 .batchID = std::nullopt},
4679 .txType =
"AccountSet",
4680 .result =
"tesSUCCESS",
4682 .batchID = batchID},
4684 .txType =
"Payment",
4685 .result =
"tesSUCCESS",
4687 .batchID = batchID},
4692 BEAST_EXPECT(env.
seq(alice) == seq + 3);
4695 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(2) - batchFee);
4696 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(2));
4706 env.
fund(
XRP(100000), alice, bob);
4710 MPTTester mpt(env, alice, {.fund =
false});
4712 mpt.create({.flags = tfMPTCanLock});
4716 env(
delegate::set(alice, bob, {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"}));
4719 auto const seq = env.
seq(alice);
4723 jv1[sfTransactionType] = jss::MPTokenIssuanceSet;
4724 jv1[sfAccount] = alice.
human();
4725 jv1[sfDelegate] = bob.
human();
4726 jv1[sfSequence] = seq + 1;
4727 jv1[sfMPTokenIssuanceID] =
to_string(mptID);
4728 jv1[sfFlags] = tfMPTLock;
4731 jv2[sfTransactionType] = jss::MPTokenIssuanceSet;
4732 jv2[sfAccount] = alice.
human();
4733 jv2[sfDelegate] = bob.
human();
4734 jv2[sfSequence] = seq + 2;
4735 jv2[sfMPTokenIssuanceID] =
to_string(mptID);
4736 jv2[sfFlags] = tfMPTUnlock;
4749 .result =
"tesSUCCESS",
4751 .batchID = std::nullopt},
4753 .txType =
"MPTokenIssuanceSet",
4754 .result =
"tesSUCCESS",
4756 .batchID = batchID},
4758 .txType =
"MPTokenIssuanceSet",
4759 .result =
"tesSUCCESS",
4761 .batchID = batchID},
4774 env.
fund(
XRP(10000), gw, alice, bob);
4775 env(
fset(gw, asfRequireAuth));
4777 env(
trust(alice, gw[
"USD"](50)));
4780 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
4783 auto const seq = env.
seq(gw);
4786 auto jv1 =
trust(gw, gw[
"USD"](0), alice, tfSetfAuth);
4787 jv1[sfDelegate] = bob.
human();
4788 auto jv2 =
trust(gw, gw[
"USD"](0), alice, tfSetFreeze);
4789 jv2[sfDelegate] = bob.
human();
4802 .result =
"tesSUCCESS",
4804 .batchID = std::nullopt},
4806 .txType =
"TrustSet",
4807 .result =
"tesSUCCESS",
4809 .batchID = batchID},
4811 .txType =
"TrustSet",
4812 .result =
"tesSUCCESS",
4814 .batchID = batchID},
4825 env.
fund(
XRP(10000), gw, alice, bob);
4826 env(
fset(gw, asfRequireAuth));
4828 env(
trust(alice, gw[
"USD"](50)));
4831 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
4834 auto const seq = env.
seq(gw);
4837 auto jv1 =
trust(gw, gw[
"USD"](0), alice, tfSetFreeze);
4838 jv1[sfDelegate] = bob.
human();
4839 auto jv2 =
trust(gw, gw[
"USD"](0), alice, tfClearFreeze);
4840 jv2[sfDelegate] = bob.
human();
4854 .result =
"tesSUCCESS",
4856 .batchID = std::nullopt},
4858 .txType =
"TrustSet",
4859 .result =
"tesSUCCESS",
4861 .batchID = batchID},
4867 BEAST_EXPECT(env.
rpc(
"tx", txIDs[1])[jss::result][jss::error] ==
"txnNotFound");
4879 using namespace jtx;
4880 Env env(*
this, features);
4883 env.
fund(
XRP(10000), alice, bob);
4888 auto const baseFee = env.
current()->fees().base;
4889 auto const aliceSeq = env.
seq(alice);
4894 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
4897 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
4898 BEAST_EXPECT(jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
4899 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
4900 BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
4901 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
4902 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
4903 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
4908 auto const baseFee = env.
current()->fees().base;
4909 auto const aliceSeq = env.
seq(alice);
4910 env(
fset(bob, asfRequireDest));
4915 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
4918 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
4919 BEAST_EXPECT(jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
4920 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
4921 BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
4922 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
4923 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
4924 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
4929 auto const baseFee = env.
current()->fees().base;
4930 auto const aliceSeq = env.
seq(alice);
4935 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
4938 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
4939 BEAST_EXPECT(jr[jss::account_sequence_available].asUInt() == aliceSeq);
4940 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
4941 BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq);
4942 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
4943 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
4944 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
4951 using namespace jtx;
4952 Env env(*
this, features);
4956 env.
fund(
XRP(10000), alice, bob, carol);
4967 auto const seq = env.
seq(alice);
4979 auto const seq = env.
seq(alice);
5000 auto const seq = env.
seq(alice);
5007 batch::Sig(bob, carol, alice, bob, carol, alice, bob, carol, alice, alice));
5014 auto const seq = env.
seq(alice);
5021 BEAST_EXPECT(txBaseFee == batchFee);
A generic endpoint for log messages.
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
void fail(String const &reason, char const *file, int line)
Record a failure.
TestcaseT testcase
Memberspace for declaring test cases.
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Calculates the total base fee for a batch transaction.
static constexpr auto kDisabledTxTypes
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.
bool modify(modify_type const &f)
Modify the open ledger.
Writable ledger view that accumulates state and tx changes.
json::Value getJson(JsonOptions=JsonOptions::Values::None) const override
Holds the serialized result of parsing an input JSON object.
std::optional< STObject > object
The STObject if the parse was successful.
json::Value getJson(JsonOptions options) const override
Slice slice() const noexcept
virtual NetworkOPs & getOPs()=0
virtual OpenLedger & getOpenLedger()=0
virtual HashRouter & getHashRouter()=0
An immutable linear range of bytes.
Metrics getMetrics(OpenView const &view) const
Returns fee metrics in reference fee level units.
void testOpenLedger(FeatureBitset features)
void testTicketsOpenLedger(FeatureBitset features)
static json::Value getLastLedger(jtx::Env &env)
void run() override
Runs the suite.
void testBadRawTxn(FeatureBitset features)
void testObjectsOpenLedger(FeatureBitset features)
void testSequenceOpenLedger(FeatureBitset features)
void testEnable(FeatureBitset features)
void testPreflight(FeatureBitset features)
void testObjectCreate3rdParty(FeatureBitset features)
void testIndependent(FeatureBitset features)
void doTestInnerSubmitRPC(FeatureBitset features, bool withBatch)
void testBatchDelegate(FeatureBitset features)
void testBadSequence(FeatureBitset features)
void testTickets(FeatureBitset features)
void testAccountSet(FeatureBitset features)
std::pair< std::vector< std::string >, std::string > submitBatch(jtx::Env &env, TER const &result, Args &&... args)
void testPreclaim(FeatureBitset features)
void testBatchTxQueue(FeatureBitset features)
static auto openLedgerFee(jtx::Env &env, XRPAmount const &batchFee)
void testAllOrNothing(FeatureBitset features)
void testValidateRPCResponse(FeatureBitset features)
void testWithFeats(FeatureBitset features)
void testBatchCalculateBaseFee(FeatureBitset features)
void testLoan(FeatureBitset features)
void testBatchNetworkOps(FeatureBitset features)
static json::Value getTxByIndex(json::Value const &jrr, int const index)
void testObjectCreateTicket(FeatureBitset features)
void testInnerSubmitRPC(FeatureBitset features)
void validateClosedLedger(jtx::Env &env, std::vector< TestLedgerData > const &ledgerResults)
void testCalculateBaseFee(FeatureBitset features)
void testAccountActivation(FeatureBitset features)
void testUntilFailure(FeatureBitset features)
static uint256 getCheckIndex(AccountID const &account, std::uint32_t uSequence)
void validateInnerTxn(jtx::Env &env, std::string const &batchID, TestLedgerData const &ledgerResult)
void testObjectCreateSequence(FeatureBitset features)
void testOnlyOne(FeatureBitset features)
static std::unique_ptr< Config > makeSmallQueueConfig(std::map< std::string, std::string > extraTxQ={}, std::map< std::string, std::string > extraVoting={})
void testAccountDelete(FeatureBitset features)
void testPseudoTxn(FeatureBitset features)
void testBadOuterFee(FeatureBitset features)
Immutable cryptographic account descriptor.
std::string const & human() const
Returns the human readable public key.
AccountID id() const
Returns the Account ID.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
json::Value json(JsonValue &&jv, FN const &... fN)
Create JSON from parameters.
SLE::const_pointer le(Account const &account) const
Return an account root.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
void setParseFailureExpected(bool b)
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
JTx jtnofill(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
void memoize(Account const &account)
Associate AccountID with account.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
NetClock::time_point now()
Returns the current network time.
Test helper for creating, mutating, and asserting MPT and confidential MPT ledger state.
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.
Adds an inner Batch transaction to a JTx and autofills it.
Sets a nested multi-signature for a Batch transaction on a JTx.
Sets the Batch transaction signers on a JTx.
Set a ticket sequence on a JTx.
@ Array
array value (ordered list)
@ Object
object value (collection of name/value pairs).
Keylet loanBroker(AccountID const &owner, std::uint32_t seq) noexcept
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Keylet loan(uint256 const &loanBrokerID, std::uint32_t loanSeq) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
json::Value outer(jtx::Account const &account, uint32_t seq, STAmount const &fee, std::uint32_t flags)
Build an outer Batch transaction JSON object.
XRPAmount calcBatchFee(jtx::Env const &env, uint32_t const &numSigners, uint32_t const &txns=0)
Calculate the expected outer Batch transaction fee.
json::Value create(A const &account, A const &dest, STAmount const &sendMax)
Create a check.
json::Value cash(jtx::Account const &dest, uint256 const &checkId, STAmount const &amount)
Cash a check requiring that a specific amount be delivered.
json::Value set(jtx::Account const &account, jtx::Account const &authorize, std::vector< std::string > const &permissions)
Deposit preauthorize operations.
json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
json::Value regkey(Account const &account, DisabledT)
Disable the regular key.
XrpT const XRP
Converts to XRP Issue or STAmount.
json::Value noop(Account const &account)
The null transaction.
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=kBaseFeeLevel.fee(), std::uint64_t expectedMedFeeLevel=kMinEscalationFeeLevel.fee(), std::source_location const location=std::source_location::current())
FeatureBitset testableAmendments()
json::Value acctdelete(Account const &account, Account const &dest)
Delete account.
void incLgrSeqForAccDel(jtx::Env &env, jtx::Account const &acc, std::uint32_t margin=0)
std::array< Account, 1+sizeof...(Args)> noripple(Account const &account, Args const &... args)
Designate accounts as no-ripple in Env::fund.
json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
json::Value signers(Account const &account, std::uint32_t quorum, std::vector< Signer > const &v)
json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
constexpr XRPAmount
Convert XRP to drops (integral types).
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
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,...
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
constexpr FlagValue tfInnerBatchTxn
ApplyResult apply(ServiceRegistry ®istry, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
std::string strHex(FwdIt begin, FwdIt end)
constexpr TenthBips32 percentageToTenthBips(std::uint32_t percentage)
XRPAmount toDrops(FeeLevel< T > const &level, XRPAmount baseFee)
TenthBips< std::uint32_t > TenthBips32
TenthBips< std::uint16_t > TenthBips16
std::string to_string(BaseUInt< Bits, Tag > const &a)
bool passesLocalChecks(STObject const &st, std::string &)
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &message)
Generate a signature for a message.
TERSubset< CanCvtToTER > TER
void serializeBatch(Serializer &msg, std::uint32_t const &flags, std::vector< uint256 > const &txids)
std::vector< unsigned char > Blob
Storage for linear binary data.
constexpr XRPAmount kInitialXrp
Configure the native currency.
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
MPTID makeMptID(std::uint32_t sequence, AccountID const &account)
uint256 TxID
A transaction identifier.
static constexpr auto kMinLedgersToComputeSizeLimit
static constexpr auto kRetrySequencePercent
static constexpr auto kMaxLedgerCountsToStore
static constexpr auto kMinimumQueueSize
static constexpr auto kNormalConsensusIncreasePercent
static constexpr auto kLedgersInQueue
static constexpr auto kMinimumTxnInLedgerStandalone
static constexpr auto kTransactionQueue
std::optional< std::string > batchID
Execution context for applying a JSON transaction.
Set the sequence number on a JTx.