1#include <test/jtx/Account.h>
2#include <test/jtx/Env.h>
3#include <test/jtx/SignerUtils.h>
4#include <test/jtx/TestHelpers.h>
5#include <test/jtx/acctdelete.h>
6#include <test/jtx/amount.h>
7#include <test/jtx/balance.h>
8#include <test/jtx/batch.h>
9#include <test/jtx/check.h>
10#include <test/jtx/delegate.h>
11#include <test/jtx/envconfig.h>
12#include <test/jtx/fee.h>
13#include <test/jtx/flags.h>
14#include <test/jtx/mpt.h>
15#include <test/jtx/multisign.h>
16#include <test/jtx/noop.h>
17#include <test/jtx/offer.h>
18#include <test/jtx/pay.h>
19#include <test/jtx/regkey.h>
20#include <test/jtx/seq.h>
21#include <test/jtx/sig.h>
22#include <test/jtx/tags.h>
23#include <test/jtx/ter.h>
24#include <test/jtx/ticket.h>
25#include <test/jtx/trust.h>
26#include <test/jtx/txflags.h>
27#include <test/jtx/utility.h>
28#include <test/jtx/vault.h>
30#include <xrpld/app/misc/Transaction.h>
31#include <xrpld/app/misc/TxQ.h>
33#include <xrpl/basics/base_uint.h>
34#include <xrpl/basics/strHex.h>
35#include <xrpl/beast/unit_test/suite.h>
36#include <xrpl/beast/utility/Journal.h>
37#include <xrpl/config/BasicConfig.h>
38#include <xrpl/config/Constants.h>
39#include <xrpl/core/HashRouter.h>
40#include <xrpl/json/json_value.h>
41#include <xrpl/json/to_string.h>
42#include <xrpl/ledger/ApplyView.h>
43#include <xrpl/ledger/OpenView.h>
44#include <xrpl/protocol/AccountID.h>
45#include <xrpl/protocol/Batch.h>
46#include <xrpl/protocol/Feature.h>
47#include <xrpl/protocol/Indexes.h>
48#include <xrpl/protocol/Issue.h>
49#include <xrpl/protocol/KeyType.h>
50#include <xrpl/protocol/LedgerFormats.h>
51#include <xrpl/protocol/MPTIssue.h>
52#include <xrpl/protocol/Protocol.h>
53#include <xrpl/protocol/SField.h>
54#include <xrpl/protocol/STParsedJSON.h>
55#include <xrpl/protocol/STTx.h>
56#include <xrpl/protocol/SecretKey.h>
57#include <xrpl/protocol/SeqProxy.h>
58#include <xrpl/protocol/Serializer.h>
59#include <xrpl/protocol/Sign.h>
60#include <xrpl/protocol/TER.h>
61#include <xrpl/protocol/TxFlags.h>
62#include <xrpl/protocol/TxFormats.h>
63#include <xrpl/protocol/Units.h>
64#include <xrpl/protocol/XRPAmount.h>
65#include <xrpl/protocol/jss.h>
66#include <xrpl/server/NetworkOPs.h>
67#include <xrpl/tx/Transactor.h>
68#include <xrpl/tx/apply.h>
69#include <xrpl/tx/transactors/payment/Payment.h>
70#include <xrpl/tx/transactors/system/Batch.h>
105 for (
auto const& txn : jrr[jss::result][jss::ledger][jss::transactions])
107 if (txn[jss::metaData][sfTransactionIndex.jsonName] == index)
117 params[jss::ledger_index] = env.
closed()->seq();
118 params[jss::transactions] =
true;
119 params[jss::expand] =
true;
127 BEAST_EXPECT(jrr[sfTransactionType.jsonName] == ledgerResult.
txType);
128 BEAST_EXPECT(jrr[jss::meta][sfTransactionResult.jsonName] == ledgerResult.
result);
129 BEAST_EXPECT(jrr[jss::meta][sfParentBatchID.jsonName] == batchID);
136 auto const transactions = jrr[jss::result][jss::ledger][jss::transactions];
141 BEAST_EXPECT(txn[jss::hash].asString() == ledgerResult.txHash);
142 BEAST_EXPECT(txn.isMember(jss::metaData));
144 BEAST_EXPECT(txn[sfTransactionType.jsonName] == ledgerResult.txType);
145 BEAST_EXPECT(meta[sfTransactionResult.jsonName] == ledgerResult.result);
146 if (ledgerResult.batchID)
151 template <
typename... Args>
158 auto const ids = batchTxn.stx->getBatchTransactionIDs();
161 for (
auto const&
id : ids)
163 TxID const batchID = batchTxn.stx->getTransactionID();
187 for (
auto const& [k, v] : extraTxQ)
198 auto const& view = *env.
current();
209 for (
bool const withBatch : {
true,
false})
211 testcase <<
"enabled: Batch " << (withBatch ?
"enabled" :
"disabled");
213 auto const amend = withBatch ? features : features - featureBatchV1_1;
215 Env env{*
this, amend};
217 auto const alice =
Account(
"alice");
218 auto const bob =
Account(
"bob");
219 auto const carol =
Account(
"carol");
220 env.
fund(
XRP(10000), alice, bob, carol);
225 auto const seq = env.
seq(alice);
258 Env env{*
this, features};
260 auto const alice =
Account(
"alice");
261 auto const bob =
Account(
"bob");
262 auto const carol =
Account(
"carol");
263 env.
fund(
XRP(10000), alice, bob, carol);
275 auto const seq = env.
seq(alice);
283 auto const seq = env.
seq(alice);
291 auto const seq = env.
seq(alice);
294 Txflags(tfAllOrNothing | tfOnlyOne),
301 auto const seq = env.
seq(alice);
309 auto const seq = env.
seq(alice);
320 auto const seq = env.
seq(alice);
339 auto const seq = env.
seq(alice);
352 auto const seq = env.
seq(alice);
365 auto const seq = env.
seq(alice);
379 auto const seq = env.
seq(alice);
381 auto jt = env.
jt(
pay(alice, bob,
XRP(1)));
391 auto const seq = env.
seq(alice);
393 auto tx1 =
pay(alice, bob,
XRP(1));
396 tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfAccount.jsonName] = alice.human();
397 tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfSigningPubKey.jsonName] =
399 tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfTxnSignature.jsonName] =
"DEADBEEF";
410 auto const seq = env.
seq(alice);
413 tx1[jss::SigningPubKey] =
strHex(alice.pk());
425 auto const seq = env.
seq(alice);
446 Env disabledEnv{*
this, features - featureBatchV1_1};
447 disabledEnv.
fund(
XRP(10000), alice, bob);
453 disabledEnv.
current()->rules(),
472 auto const seq = env.
seq(alice);
485 auto const seq = env.
seq(alice);
488 tx1[jss::Fee] =
"-1";
498 auto const seq = env.
seq(alice);
501 tx1[jss::Fee] =
"1.5";
508 fail(
"Expected parse_error for fractional fee");
519 auto const seq = env.
seq(alice);
522 tx1[jss::Sequence] = seq + 1;
533 auto const seq = env.
seq(alice);
544 auto const seq = env.
seq(alice);
555 auto const seq = env.
seq(alice);
566 auto const seq = env.
seq(alice);
579 auto const seq = env.
seq(alice);
591 auto const seq = env.
seq(alice);
603 auto const seq = env.
seq(alice);
616 auto const seq = env.
seq(alice);
628 auto const seq = env.
seq(alice);
640 auto const seq = env.
seq(alice);
641 auto const bobSeq = env.
seq(bob);
651 jt.stx->getAccountID(sfAccount),
652 jt.stx->getSeqProxy().value(),
654 jt.stx->getBatchTransactionIDs());
657 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfAccount.jsonName] =
659 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfSigningPubKey.jsonName] =
661 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfTxnSignature.jsonName] =
670 auto const seq = env.
seq(alice);
693 Env env{*
this, features};
695 auto const alice =
Account(
"alice");
696 auto const bob =
Account(
"bob");
697 auto const carol =
Account(
"carol");
698 auto const dave =
Account(
"dave");
699 auto const elsa =
Account(
"elsa");
700 auto const frank =
Account(
"frank");
701 auto const phantom =
Account(
"phantom");
704 env.
fund(
XRP(10000), alice, bob, carol, dave, elsa, frank);
712 auto const seq = env.
seq(alice);
727 auto const seq = env.
seq(alice);
737 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
740 env(
signers(bob, 2, {{carol, 1}, {dave, 1}, {elsa, 1}}));
745 auto const seq = env.
seq(alice);
757 auto const seq = env.
seq(alice);
762 batch::Msig(bob, {carol, Account(
"dave", KeyType::Ed25519)}),
770 env(
fset(elsa, asfDisableMaster),
Sig(elsa));
771 auto const seq = env.
seq(alice);
783 auto const seq = env.
seq(alice);
795 auto const seq = env.
seq(alice);
809 auto const seq = env.seq(alice);
813 batch::Inner(
pay(alice, bob,
XRP(10)), seq + 1),
814 batch::Inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
815 batch::Msig(bob, {carol, Reg{dave, davo}}),
822 auto const seq = env.seq(alice);
825 batch::Inner(
pay(alice, bob,
XRP(10)), seq + 1),
826 batch::Inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
827 batch::Msig(bob, {carol}),
834 auto const seq = env.seq(alice);
837 batch::Inner(
pay(alice, bob,
XRP(10)), seq + 1),
838 batch::Inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
839 batch::Msig(bob, {carol, dave}),
846 auto const seq = env.seq(alice);
849 batch::Inner(
pay(alice, bob,
XRP(10)), seq + 1),
850 batch::Inner(
pay(bob, alice,
XRP(5)), env.seq(bob)),
851 batch::Msig(bob, {carol, dave}),
862 auto const ledSeq = env.current()->seq();
863 auto const seq = env.seq(alice);
866 batch::Inner(
pay(alice, phantom,
XRP(1000)), seq + 1),
867 batch::Inner(
noop(phantom), ledSeq),
868 batch::Sig(
Reg{phantom, carol}),
875 auto const ledSeq = env.current()->seq();
876 auto const seq = env.seq(alice);
879 batch::Inner(
pay(alice, bob,
XRP(1000)), seq + 1),
880 batch::Inner(
noop(bob), ledSeq),
881 batch::Sig(
Reg{bob, carol}),
889 auto const seq = env.seq(alice);
892 batch::Inner(
pay(alice, bob,
XRP(1)), seq + 1),
893 batch::Inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
894 batch::Sig(
Reg{bob, carol}),
901 auto const seq = env.seq(alice);
904 batch::Inner(
pay(alice, bob,
XRP(1)), seq + 1),
905 batch::Inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
914 env(
fset(bob, asfDisableMaster),
Sig(bob));
915 auto const seq = env.seq(alice);
918 batch::Inner(
pay(alice, bob,
XRP(1)), seq + 1),
919 batch::Inner(
pay(bob, alice,
XRP(2)), env.seq(bob)),
934 Env env{*
this, features};
936 auto const alice =
Account(
"alice");
937 auto const bob =
Account(
"bob");
939 env.
fund(
XRP(10000), alice, bob);
947 auto const seq = env.
seq(alice);
949 tx1.removeMember(field);
958 return jt.
stx ==
nullptr;
967 BEAST_EXPECT(batchCtorFails(jss::TransactionType));
969 BEAST_EXPECT(batchCtorFails(jss::Account));
971 BEAST_EXPECT(batchCtorFails(jss::Sequence));
973 BEAST_EXPECT(batchCtorFails(jss::Fee));
975 BEAST_EXPECT(batchCtorFails(jss::SigningPubKey));
980 STAmount const mptAmt{issue, UINT64_C(100)};
983 auto const seq = env.
seq(alice);
986 tx1[jss::TransactionType] = jss::OfferCreate;
987 tx1[jss::Account] = alice.human();
1001 auto const seq = env.
seq(alice);
1003 auto tx1 =
pay(alice, bob,
XRP(10));
1004 auto& ma = tx1[
"Memos"];
1005 auto& mi = ma[ma.size()];
1006 auto& m = mi[
"Memo"];
1010 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
1026 Env env{*
this, features};
1028 auto const alice =
Account(
"alice");
1029 auto const bob =
Account(
"bob");
1030 auto const gw =
Account(
"gw");
1031 auto const usd = gw[
"USD"];
1033 env.
fund(
XRP(10000), alice, bob, gw);
1035 env.
trust(usd(1000), alice, bob);
1036 env(
pay(gw, alice, usd(100)));
1037 env(
pay(gw, bob, usd(100)));
1045 auto const preAliceSeq = env.
seq(alice);
1046 auto const preAlice = env.
balance(alice);
1047 auto const preAliceUSD = env.
balance(alice, usd.issue());
1048 auto const preBobSeq = env.
seq(bob);
1049 auto const preBob = env.
balance(bob);
1050 auto const preBobUSD = env.
balance(bob, usd.issue());
1056 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1066 .result =
"tesSUCCESS",
1068 .batchID = std::nullopt},
1081 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1082 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1083 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1084 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1085 BEAST_EXPECT(env.
balance(bob) == preBob);
1086 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1091 auto const preAliceSeq = env.
seq(alice);
1092 auto const preAlice = env.
balance(alice);
1093 auto const preAliceUSD = env.
balance(alice, usd.issue());
1094 auto const preBobSeq = env.
seq(bob);
1095 auto const preBob = env.
balance(bob);
1096 auto const preBobUSD = env.
balance(bob, usd.issue());
1102 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1112 .result =
"tesSUCCESS",
1114 .batchID = std::nullopt},
1127 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1128 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1129 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1130 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1131 BEAST_EXPECT(env.
balance(bob) == preBob);
1132 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1137 auto const preAliceSeq = env.
seq(alice);
1138 auto const preAlice = env.
balance(alice);
1139 auto const preAliceUSD = env.
balance(alice, usd.issue());
1140 auto const preBobSeq = env.
seq(bob);
1141 auto const preBob = env.
balance(bob);
1142 auto const preBobUSD = env.
balance(bob, usd.issue());
1148 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1158 .result =
"tesSUCCESS",
1160 .batchID = std::nullopt},
1173 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1174 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1175 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1176 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1177 BEAST_EXPECT(env.
balance(bob) == preBob);
1178 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1183 auto const preAliceSeq = env.
seq(alice);
1184 auto const preAlice = env.
balance(alice);
1185 auto const preAliceUSD = env.
balance(alice, usd.issue());
1186 auto const preBobSeq = env.
seq(bob);
1187 auto const preBob = env.
balance(bob);
1188 auto const preBobUSD = env.
balance(bob, usd.issue());
1194 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1204 .result =
"tesSUCCESS",
1206 .batchID = std::nullopt},
1219 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1220 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1221 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1222 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1223 BEAST_EXPECT(env.
balance(bob) == preBob);
1224 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1229 auto const preAliceSeq = env.
seq(alice);
1230 auto const preAlice = env.
balance(alice);
1231 auto const preAliceUSD = env.
balance(alice, usd.issue());
1232 auto const preBobSeq = env.
seq(bob);
1233 auto const preBob = env.
balance(bob);
1234 auto const preBobUSD = env.
balance(bob, usd.issue());
1240 batch::outer(alice, preAliceSeq, batchFee, tfAllOrNothing),
1250 .result =
"tesSUCCESS",
1252 .batchID = std::nullopt},
1265 BEAST_EXPECT(env.
seq(alice) == preAliceSeq + 1);
1266 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1267 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
1268 BEAST_EXPECT(env.
seq(bob) == preBobSeq);
1269 BEAST_EXPECT(env.
balance(bob) == preBob);
1270 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
1284 Env env{*
this, features};
1286 auto const alice =
Account(
"alice");
1287 auto const bob =
Account(
"bob");
1288 env.
fund(
XRP(10000), alice, bob);
1296 auto const aliceSeq = env.
seq(alice);
1297 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1306 Env env{*
this, features};
1308 auto const alice =
Account(
"alice");
1309 auto const bob =
Account(
"bob");
1310 auto const carol =
Account(
"carol");
1311 env.
fund(
XRP(10000), alice, bob, carol);
1317 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
1322 auto const aliceSeq = env.
seq(alice);
1323 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1333 Env env{*
this, features};
1335 auto const alice =
Account(
"alice");
1336 auto const bob =
Account(
"bob");
1337 auto const carol =
Account(
"carol");
1338 env.
fund(
XRP(10000), alice, bob, carol);
1344 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
1349 auto const aliceSeq = env.
seq(alice);
1350 auto const bobSeq = env.
seq(bob);
1351 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1362 Env env{*
this, features};
1364 auto const alice =
Account(
"alice");
1365 auto const bob =
Account(
"bob");
1366 auto const carol =
Account(
"carol");
1367 env.
fund(
XRP(10000), alice, bob, carol);
1373 env(
signers(alice, 2, {{bob, 1}, {carol, 1}}));
1376 env(
signers(bob, 2, {{alice, 1}, {carol, 1}}));
1381 auto const aliceSeq = env.
seq(alice);
1382 auto const bobSeq = env.
seq(bob);
1383 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1394 Env env{*
this, features};
1396 auto const alice =
Account(
"alice");
1397 auto const bob =
Account(
"bob");
1398 env.
fund(
XRP(10000), alice, bob);
1406 auto const aliceSeq = env.
seq(alice);
1407 auto const bobSeq = env.
seq(bob);
1408 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1418 Env env{*
this, features};
1420 auto const alice =
Account(
"alice");
1421 auto const bob =
Account(
"bob");
1422 auto const gw =
Account(
"gw");
1423 auto const usd = gw[
"USD"];
1425 env.
fund(
XRP(10000), alice, bob, gw);
1427 auto const ammCreate = [&alice](
STAmount const& amount,
STAmount const& amount2) {
1429 jv[jss::Account] = alice.human();
1432 jv[jss::TradingFee] = 0;
1433 jv[jss::TransactionType] = jss::AMMCreate;
1438 auto const seq = env.
seq(alice);
1439 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
1457 Env env{*
this, features};
1459 auto const alice =
Account(
"alice");
1460 auto const bob =
Account(
"bob");
1461 env.
fund(
XRP(10000), alice, bob);
1465 auto const aliceSeq = env.
seq(alice);
1466 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1484 Env env{*
this, features};
1486 auto const alice =
Account(
"alice");
1487 auto const bob =
Account(
"bob");
1488 env.
fund(
XRP(10000), alice, bob);
1492 auto const aliceSeq = env.
seq(alice);
1494 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1505 BEAST_EXPECT(jt.stx ==
nullptr);
1513 Env env{*
this, features};
1515 auto const alice =
Account(
"alice");
1516 auto const bob =
Account(
"bob");
1517 env.
fund(
XRP(10000), alice, bob);
1520 auto const aliceSeq = env.
seq(alice);
1526 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1542 BEAST_EXPECT(threw);
1554 Env env{*
this, features};
1556 auto const alice =
Account(
"alice");
1557 auto const bob =
Account(
"bob");
1558 env.
fund(
XRP(10000), alice, bob);
1564 auto const aliceSeq = env.
seq(alice);
1566 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1577 Env env{*
this, features};
1579 auto const alice =
Account(
"alice");
1580 auto const bob =
Account(
"bob");
1581 env.
fund(
XRP(10000), alice, bob);
1585 auto const aliceSeq = env.
seq(alice);
1587 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
1595 return result.applied;
1601 auto const [
valid, reason] =
1604 BEAST_EXPECT(reason ==
"BatchSigners array exceeds max entries.");
1616 Env env{*
this, features};
1618 auto const alice =
Account(
"alice");
1619 auto const bob =
Account(
"bob");
1620 auto const gw =
Account(
"gw");
1621 auto const usd = gw[
"USD"];
1622 env.
fund(
XRP(10000), alice, bob, gw);
1627 auto const preAlice = env.
balance(alice);
1628 auto const preBob = env.
balance(bob);
1631 auto const seq = env.
seq(alice);
1643 .result =
"tesSUCCESS",
1645 .batchID = std::nullopt},
1647 .txType =
"Payment",
1648 .result =
"tesSUCCESS",
1650 .batchID = batchID},
1652 .txType =
"Payment",
1653 .result =
"tesSUCCESS",
1655 .batchID = batchID},
1660 BEAST_EXPECT(env.
seq(alice) == seq + 3);
1663 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
1664 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
1669 auto const preAlice = env.
balance(alice);
1670 auto const preBob = env.
balance(bob);
1673 auto const seq = env.
seq(alice);
1687 .result =
"tesSUCCESS",
1689 .batchID = std::nullopt},
1694 BEAST_EXPECT(env.
seq(alice) == seq + 1);
1697 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1698 BEAST_EXPECT(env.
balance(bob) == preBob);
1703 auto const preAlice = env.
balance(alice);
1704 auto const preBob = env.
balance(bob);
1707 auto const seq = env.
seq(alice);
1720 .result =
"tesSUCCESS",
1722 .batchID = std::nullopt},
1727 BEAST_EXPECT(env.
seq(alice) == seq + 1);
1730 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1731 BEAST_EXPECT(env.
balance(bob) == preBob);
1736 auto const preAlice = env.
balance(alice);
1737 auto const preBob = env.
balance(bob);
1740 auto const seq = env.
seq(alice);
1753 .result =
"tesSUCCESS",
1755 .batchID = std::nullopt},
1760 BEAST_EXPECT(env.
seq(alice) == seq + 1);
1763 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1764 BEAST_EXPECT(env.
balance(bob) == preBob);
1776 Env env{*
this, features};
1778 auto const alice =
Account(
"alice");
1779 auto const bob =
Account(
"bob");
1780 auto const carol =
Account(
"carol");
1781 auto const dave =
Account(
"dave");
1782 auto const gw =
Account(
"gw");
1783 auto const usd = gw[
"USD"];
1784 env.
fund(
XRP(10000), alice, bob, carol, dave, gw);
1789 auto const preAlice = env.
balance(alice);
1790 auto const preBob = env.
balance(bob);
1793 auto const seq = env.
seq(alice);
1809 .result =
"tesSUCCESS",
1811 .batchID = std::nullopt},
1813 .txType =
"Payment",
1814 .result =
"tecUNFUNDED_PAYMENT",
1816 .batchID = batchID},
1818 .txType =
"Payment",
1819 .result =
"tecUNFUNDED_PAYMENT",
1821 .batchID = batchID},
1823 .txType =
"Payment",
1824 .result =
"tecUNFUNDED_PAYMENT",
1826 .batchID = batchID},
1831 BEAST_EXPECT(env.
seq(alice) == seq + 4);
1834 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
1835 BEAST_EXPECT(env.
balance(bob) == preBob);
1840 auto const preAlice = env.
balance(alice);
1841 auto const preBob = env.
balance(bob);
1844 auto const seq = env.
seq(alice);
1858 .result =
"tesSUCCESS",
1860 .batchID = std::nullopt},
1862 .txType =
"Payment",
1863 .result =
"tecUNFUNDED_PAYMENT",
1865 .batchID = batchID},
1867 .txType =
"Payment",
1868 .result =
"tesSUCCESS",
1870 .batchID = batchID},
1875 BEAST_EXPECT(env.
seq(alice) == seq + 3);
1878 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1) - batchFee);
1879 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
1884 auto const preAlice = env.
balance(alice);
1885 auto const preBob = env.
balance(bob);
1888 auto const seq = env.
seq(alice);
1902 .result =
"tesSUCCESS",
1904 .batchID = std::nullopt},
1906 .txType =
"Payment",
1907 .result =
"tesSUCCESS",
1909 .batchID = batchID},
1914 BEAST_EXPECT(env.
seq(alice) == seq + 2);
1917 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1) - batchFee);
1918 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
1923 auto const preAlice = env.
balance(alice);
1924 auto const preBob = env.
balance(bob);
1927 auto const seq = env.
seq(alice);
1941 .result =
"tesSUCCESS",
1943 .batchID = std::nullopt},
1945 .txType =
"Payment",
1946 .result =
"tesSUCCESS",
1948 .batchID = batchID},
1953 BEAST_EXPECT(env.
seq(alice) == seq + 2);
1956 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee -
XRP(1));
1957 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
1962 auto const preAlice = env.
balance(alice);
1963 auto const preBob = env.
balance(bob);
1966 auto const seq = env.
seq(alice);
1980 .result =
"tesSUCCESS",
1982 .batchID = std::nullopt},
1984 .txType =
"Payment",
1985 .result =
"tesSUCCESS",
1987 .batchID = batchID},
1992 BEAST_EXPECT(env.
seq(alice) == seq + 2);
1995 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee -
XRP(1));
1996 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
2001 auto const preAlice = env.
balance(alice);
2002 auto const preBob = env.
balance(bob);
2003 auto const preCarol = env.
balance(carol);
2004 auto const seq = env.
seq(alice);
2012 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 1),
2014 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 2),
2016 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 3),
2025 .result =
"tesSUCCESS",
2027 .batchID = std::nullopt},
2029 .txType =
"OfferCreate",
2030 .result =
"tecKILLED",
2032 .batchID = batchID},
2034 .txType =
"OfferCreate",
2035 .result =
"tecKILLED",
2037 .batchID = batchID},
2039 .txType =
"OfferCreate",
2040 .result =
"tecKILLED",
2042 .batchID = batchID},
2044 .txType =
"Payment",
2045 .result =
"tesSUCCESS",
2047 .batchID = batchID},
2051 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(100) - batchFee);
2052 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(100));
2053 BEAST_EXPECT(env.
balance(carol) == preCarol);
2065 Env env{*
this, features};
2067 auto const alice =
Account(
"alice");
2068 auto const bob =
Account(
"bob");
2069 auto const carol =
Account(
"carol");
2070 auto const dave =
Account(
"dave");
2071 auto const gw =
Account(
"gw");
2072 auto const usd = gw[
"USD"];
2073 env.
fund(
XRP(10000), alice, bob, carol, dave, gw);
2078 auto const preAlice = env.
balance(alice);
2079 auto const preBob = env.
balance(bob);
2082 auto const seq = env.
seq(alice);
2097 .result =
"tesSUCCESS",
2099 .batchID = std::nullopt},
2101 .txType =
"Payment",
2102 .result =
"tecUNFUNDED_PAYMENT",
2104 .batchID = batchID},
2109 BEAST_EXPECT(env.
seq(alice) == seq + 2);
2112 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
2113 BEAST_EXPECT(env.
balance(bob) == preBob);
2118 auto const preAlice = env.
balance(alice);
2119 auto const preBob = env.
balance(bob);
2122 auto const seq = env.
seq(alice);
2136 .result =
"tesSUCCESS",
2138 .batchID = std::nullopt},
2140 .txType =
"Payment",
2141 .result =
"tesSUCCESS",
2143 .batchID = batchID},
2145 .txType =
"Payment",
2146 .result =
"tesSUCCESS",
2148 .batchID = batchID},
2150 .txType =
"Payment",
2151 .result =
"tesSUCCESS",
2153 .batchID = batchID},
2155 .txType =
"Payment",
2156 .result =
"tesSUCCESS",
2158 .batchID = batchID},
2163 BEAST_EXPECT(env.
seq(alice) == seq + 5);
2166 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(10) - batchFee);
2167 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(10));
2172 auto const preAlice = env.
balance(alice);
2173 auto const preBob = env.
balance(bob);
2176 auto const seq = env.
seq(alice);
2191 .result =
"tesSUCCESS",
2193 .batchID = std::nullopt},
2195 .txType =
"Payment",
2196 .result =
"tesSUCCESS",
2198 .batchID = batchID},
2200 .txType =
"Payment",
2201 .result =
"tesSUCCESS",
2203 .batchID = batchID},
2205 .txType =
"Payment",
2206 .result =
"tecUNFUNDED_PAYMENT",
2208 .batchID = batchID},
2213 BEAST_EXPECT(env.
seq(alice) == seq + 4);
2216 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
2217 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
2222 auto const preAlice = env.
balance(alice);
2223 auto const preBob = env.
balance(bob);
2226 auto const seq = env.
seq(alice);
2241 .result =
"tesSUCCESS",
2243 .batchID = std::nullopt},
2245 .txType =
"Payment",
2246 .result =
"tesSUCCESS",
2248 .batchID = batchID},
2250 .txType =
"Payment",
2251 .result =
"tesSUCCESS",
2253 .batchID = batchID},
2258 BEAST_EXPECT(env.
seq(alice) == seq + 3);
2261 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
2262 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
2267 auto const preAlice = env.
balance(alice);
2268 auto const preBob = env.
balance(bob);
2271 auto const seq = env.
seq(alice);
2286 .result =
"tesSUCCESS",
2288 .batchID = std::nullopt},
2290 .txType =
"Payment",
2291 .result =
"tesSUCCESS",
2293 .batchID = batchID},
2295 .txType =
"Payment",
2296 .result =
"tesSUCCESS",
2298 .batchID = batchID},
2303 BEAST_EXPECT(env.
seq(alice) == seq + 3);
2306 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
2307 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
2312 auto const preAlice = env.
balance(alice);
2313 auto const preBob = env.
balance(bob);
2314 auto const preCarol = env.
balance(carol);
2315 auto const seq = env.
seq(alice);
2324 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 3),
2331 .result =
"tesSUCCESS",
2333 .batchID = std::nullopt},
2335 .txType =
"Payment",
2336 .result =
"tesSUCCESS",
2338 .batchID = batchID},
2340 .txType =
"Payment",
2341 .result =
"tesSUCCESS",
2343 .batchID = batchID},
2345 .txType =
"OfferCreate",
2346 .result =
"tecKILLED",
2348 .batchID = batchID},
2352 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(200) - batchFee);
2353 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(100));
2354 BEAST_EXPECT(env.
balance(carol) == preCarol +
XRP(100));
2366 Env env{*
this, features};
2368 auto const alice =
Account(
"alice");
2369 auto const bob =
Account(
"bob");
2370 auto const carol =
Account(
"carol");
2371 auto const gw =
Account(
"gw");
2372 auto const usd = gw[
"USD"];
2373 env.
fund(
XRP(10000), alice, bob, carol, gw);
2378 auto const preAlice = env.
balance(alice);
2379 auto const preBob = env.
balance(bob);
2382 auto const seq = env.
seq(alice);
2398 .result =
"tesSUCCESS",
2400 .batchID = std::nullopt},
2402 .txType =
"Payment",
2403 .result =
"tesSUCCESS",
2405 .batchID = batchID},
2407 .txType =
"Payment",
2408 .result =
"tecUNFUNDED_PAYMENT",
2410 .batchID = batchID},
2412 .txType =
"Payment",
2413 .result =
"tecUNFUNDED_PAYMENT",
2415 .batchID = batchID},
2417 .txType =
"Payment",
2418 .result =
"tesSUCCESS",
2420 .batchID = batchID},
2425 BEAST_EXPECT(env.
seq(alice) == seq + 5);
2428 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(4) - batchFee);
2429 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(4));
2434 auto const preAlice = env.
balance(alice);
2435 auto const preBob = env.
balance(bob);
2438 auto const seq = env.
seq(alice);
2453 .result =
"tesSUCCESS",
2455 .batchID = std::nullopt},
2457 .txType =
"Payment",
2458 .result =
"tesSUCCESS",
2460 .batchID = batchID},
2462 .txType =
"Payment",
2463 .result =
"tesSUCCESS",
2465 .batchID = batchID},
2467 .txType =
"Payment",
2468 .result =
"tecUNFUNDED_PAYMENT",
2470 .batchID = batchID},
2472 .txType =
"Payment",
2473 .result =
"tesSUCCESS",
2475 .batchID = batchID},
2480 BEAST_EXPECT(env.
seq(alice) == seq + 5);
2483 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(6) - batchFee);
2484 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(6));
2489 auto const preAlice = env.
balance(alice);
2490 auto const preBob = env.
balance(bob);
2493 auto const seq = env.
seq(alice);
2508 .result =
"tesSUCCESS",
2510 .batchID = std::nullopt},
2512 .txType =
"Payment",
2513 .result =
"tesSUCCESS",
2515 .batchID = batchID},
2517 .txType =
"Payment",
2518 .result =
"tesSUCCESS",
2520 .batchID = batchID},
2522 .txType =
"Payment",
2523 .result =
"tesSUCCESS",
2525 .batchID = batchID},
2530 BEAST_EXPECT(env.
seq(alice) == seq + 4);
2533 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee -
XRP(6));
2534 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(6));
2539 auto const preAlice = env.
balance(alice);
2540 auto const preBob = env.
balance(bob);
2543 auto const seq = env.
seq(alice);
2558 .result =
"tesSUCCESS",
2560 .batchID = std::nullopt},
2562 .txType =
"Payment",
2563 .result =
"tesSUCCESS",
2565 .batchID = batchID},
2567 .txType =
"Payment",
2568 .result =
"tesSUCCESS",
2570 .batchID = batchID},
2572 .txType =
"Payment",
2573 .result =
"tesSUCCESS",
2575 .batchID = batchID},
2580 BEAST_EXPECT(env.
seq(alice) == seq + 4);
2583 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee -
XRP(6));
2584 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(6));
2589 auto const preAlice = env.
balance(alice);
2590 auto const preBob = env.
balance(bob);
2591 auto const preCarol = env.
balance(carol);
2592 auto const seq = env.
seq(alice);
2601 offer(alice, alice[
"USD"](100),
XRP(100), tfImmediateOrCancel), seq + 3));
2607 .result =
"tesSUCCESS",
2609 .batchID = std::nullopt},
2611 .txType =
"Payment",
2612 .result =
"tesSUCCESS",
2614 .batchID = batchID},
2616 .txType =
"Payment",
2617 .result =
"tesSUCCESS",
2619 .batchID = batchID},
2621 .txType =
"OfferCreate",
2622 .result =
"tecKILLED",
2624 .batchID = batchID},
2628 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(200) - batchFee);
2629 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(100));
2630 BEAST_EXPECT(env.
balance(carol) == preCarol +
XRP(100));
2638 std::string(
"inner submit rpc: batch ") + (withBatch ?
"enabled" :
"disabled") +
": ";
2640 auto const amend = withBatch ? features : features - featureBatchV1_1;
2645 Env env{*
this, amend};
2646 if (!BEAST_EXPECT(amend[featureBatchV1_1] == withBatch))
2649 auto const alice =
Account(
"alice");
2650 auto const bob =
Account(
"bob");
2652 env.
fund(
XRP(10000), alice, bob);
2662 jrr[jss::status] ==
"error" && jrr[jss::error] ==
"invalidTransaction" &&
2663 jrr[jss::error_exception] ==
2664 "fails local checks: Batch inner transactions are never "
2665 "considered validly signed.",
2679 txn[sfTxnSignature] =
"DEADBEEF";
2683 submitAndValidate(
"TxnSignature set", s.
slice(), __LINE__);
2693 txn[sfSigningPubKey] =
strHex(alice.pk());
2697 submitAndValidate(
"SigningPubKey set", s.
slice(), __LINE__);
2711 submitAndValidate(
"Signers set", s.
slice(), __LINE__);
2717 auto const jt = env.
jt(txn.getTxn());
2722 submitAndValidate(
"Fully signed", s.
slice(), __LINE__);
2735 submitAndValidate(
"No signing fields set", s.
slice(), __LINE__);
2744 STTx const amendTx(ttAMENDMENT, [seq = env.
closed()->header().seq + 1](
auto& obj) {
2745 obj.setAccountID(sfAccount, AccountID());
2746 obj.setFieldH256(sfAmendment, featureBatchV1_1);
2747 obj.setFieldU32(sfLedgerSequence, seq);
2748 obj.setFieldU32(sfFlags, tfInnerBatchTxn);
2754 submitAndValidate(
"Pseudo-transaction", s.
slice(), __LINE__);
2761 for (
bool const withBatch : {
true,
false})
2775 Env env{*
this, features};
2777 auto const alice =
Account(
"alice");
2778 auto const bob =
Account(
"bob");
2783 auto const preAlice = env.
balance(alice);
2784 auto const ledSeq = env.
current()->seq();
2785 auto const seq = env.
seq(alice);
2799 .result =
"tesSUCCESS",
2801 .batchID = std::nullopt},
2803 .txType =
"Payment",
2804 .result =
"tesSUCCESS",
2806 .batchID = batchID},
2808 .txType =
"AccountSet",
2809 .result =
"tesSUCCESS",
2811 .batchID = batchID},
2816 BEAST_EXPECT(env.
seq(alice) == seq + 2);
2819 BEAST_EXPECT(env.
seq(bob) == ledSeq + 1);
2822 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1000) - batchFee);
2833 Env env{*
this, features};
2835 auto const alice =
Account(
"alice");
2836 auto const gw =
Account(
"gw");
2837 auto const carol =
Account(
"carol");
2838 auto const usd = gw[
"USD"];
2839 env.
fund(
XRP(10000), alice, gw);
2843 env(
trust(alice, usd(100000)));
2844 env(
pay(gw, alice, usd(10000)));
2845 env(
offer(gw, usd(2000),
XRP(2000)));
2848 auto const seq = env.
seq(alice);
2851 auto pp =
pay(alice, carol,
XRP(1000));
2853 pp[jss::Flags] = tfPartialPayment;
2862 BEAST_EXPECT(!env.
le(carol));
2879 Env env{*
this, features};
2881 auto const alice =
Account(
"alice");
2884 auto const unfunded =
Account(
"aaa");
2885 auto const carol =
Account(
"carol");
2886 env.
fund(
XRP(10000), alice, carol);
2890 BEAST_EXPECT(unfunded.id() < carol.id());
2892 auto const seq = env.
seq(alice);
2893 auto const ledSeq = env.
current()->seq();
2904 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
2921 Env env{*
this, features};
2923 auto const alice =
Account(
"alice");
2924 auto const bob =
Account(
"bob");
2925 env.
fund(
XRP(10000), alice, bob);
2928 auto const preAlice = env.
balance(alice);
2929 auto const preBob = env.
balance(bob);
2931 auto const seq = env.
seq(alice);
2935 tx1[sfDomain] =
strHex(domain);
2947 .result =
"tesSUCCESS",
2949 .batchID = std::nullopt},
2951 .txType =
"AccountSet",
2952 .result =
"tesSUCCESS",
2954 .batchID = batchID},
2956 .txType =
"Payment",
2957 .result =
"tesSUCCESS",
2959 .batchID = batchID},
2965 BEAST_EXPECT(sle->getFieldVL(sfDomain) ==
Blob(domain.
begin(), domain.
end()));
2968 BEAST_EXPECT(env.
seq(alice) == seq + 3);
2971 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1) - batchFee);
2972 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
2985 Env env{*
this, features};
2987 auto const alice =
Account(
"alice");
2988 auto const bob =
Account(
"bob");
2989 env.
fund(
XRP(10000), alice, bob);
2993 for (
int i = 0; i < 5; ++i)
2996 auto const preAlice = env.
balance(alice);
2997 auto const preBob = env.
balance(bob);
2999 auto const seq = env.
seq(alice);
3014 .result =
"tesSUCCESS",
3016 .batchID = std::nullopt},
3018 .txType =
"Payment",
3019 .result =
"tesSUCCESS",
3021 .batchID = batchID},
3023 .txType =
"AccountDelete",
3024 .result =
"tesSUCCESS",
3026 .batchID = batchID},
3032 BEAST_EXPECT(env.
balance(bob) == preBob + (preAlice - batchFee));
3037 Env env{*
this, features};
3039 auto const alice =
Account(
"alice");
3040 auto const bob =
Account(
"bob");
3041 env.
fund(
XRP(10000), alice, bob);
3045 for (
int i = 0; i < 5; ++i)
3048 auto const preAlice = env.
balance(alice);
3049 auto const preBob = env.
balance(bob);
3051 env.
trust(bob[
"USD"](1000), alice);
3054 auto const seq = env.
seq(alice);
3069 .result =
"tesSUCCESS",
3071 .batchID = std::nullopt},
3073 .txType =
"Payment",
3074 .result =
"tesSUCCESS",
3076 .batchID = batchID},
3078 .txType =
"AccountDelete",
3079 .result =
"tecHAS_OBLIGATIONS",
3081 .batchID = batchID},
3083 .txType =
"Payment",
3084 .result =
"tesSUCCESS",
3086 .batchID = batchID},
3092 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
3097 Env env{*
this, features};
3099 auto const alice =
Account(
"alice");
3100 auto const bob =
Account(
"bob");
3101 env.
fund(
XRP(10000), alice, bob);
3105 for (
int i = 0; i < 5; ++i)
3108 auto const preAlice = env.
balance(alice);
3109 auto const preBob = env.
balance(bob);
3111 auto const seq = env.
seq(alice);
3126 .result =
"tesSUCCESS",
3128 .batchID = std::nullopt},
3134 BEAST_EXPECT(env.
balance(bob) == preBob);
3145 [](
auto const& disabled) {
return disabled == ttLOAN_BROKER_SET; });
3149 Env env{*
this, features};
3151 Account const issuer{
"issuer"};
3154 Account const lender{
"lender"};
3156 Account const borrower{
"borrower"};
3166 Vault const vault{env};
3168 auto const deposit = asset(50'000);
3169 auto const debtMaximumValue = asset(25'000).value();
3170 auto const coverDepositValue = asset(1000).value();
3172 auto [tx, vaultKeylet] = vault.create({.owner = lender, .asset = asset});
3175 BEAST_EXPECT(env.
le(vaultKeylet));
3177 env(vault.deposit({.depositor = lender, .id = vaultKeylet.key, .amount = deposit}));
3180 auto const brokerKeylet =
3185 env(
set(lender, vaultKeylet.key),
3187 kDebtMaximum(debtMaximumValue),
3191 env(coverDeposit(lender, brokerKeylet.key, coverDepositValue));
3197 using namespace loan;
3198 using namespace std::chrono_literals;
3200 auto const lenderSeq = env.
seq(lender);
3208 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3211 set(lender, brokerKeylet.key, asset(1000).value()),
3213 Sig(sfCounterpartySignature, borrower),
3219 pay(lender, loanKeylet.key,
STAmount{asset, asset(500).value()}),
3226 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3229 set(lender, brokerKeylet.key, asset(1000).value()),
3236 pay(lender, loanKeylet.key,
STAmount{asset, asset(500).value()}),
3243 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3246 set(lender, brokerKeylet.key, asset(1000).value()),
3248 kCounterparty(borrower.
id()),
3254 pay(lender, loanKeylet.key,
STAmount{asset, asset(500).value()}),
3265 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3268 set(lender, brokerKeylet.key, asset(1000).value()),
3269 kCounterparty(borrower.
id()),
3281 STAmount{asset, asset(500).value()}),
3286 BEAST_EXPECT(env.
le(brokerKeylet));
3287 BEAST_EXPECT(!env.
le(loanKeylet));
3292 auto const lenderSeq = env.
seq(lender);
3297 batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing),
3300 set(lender, brokerKeylet.key, asset(1000).value()),
3301 kCounterparty(borrower.
id()),
3306 batch::Inner(manage(lender, loanKeylet.key, tfLoanImpair), lenderSeq + 2),
3310 BEAST_EXPECT(env.
le(brokerKeylet));
3311 if (
auto const sleLoan = env.
le(loanKeylet);
3312 lendingBatchEnabled ? BEAST_EXPECT(sleLoan) : !BEAST_EXPECT(!sleLoan))
3314 BEAST_EXPECT(sleLoan->isFlag(lsfLoanImpaired));
3322 testcase(
"object create w/ sequence");
3327 Env env{*
this, features};
3329 auto const alice =
Account(
"alice");
3330 auto const bob =
Account(
"bob");
3331 auto const gw =
Account(
"gw");
3332 auto const usd = gw[
"USD"];
3334 env.
fund(
XRP(10000), alice, bob, gw);
3337 env.
trust(usd(1000), alice, bob);
3338 env(
pay(gw, alice, usd(100)));
3339 env(
pay(gw, bob, usd(100)));
3344 auto const aliceSeq = env.
seq(alice);
3345 auto const bobSeq = env.
seq(bob);
3346 auto const preAlice = env.
balance(alice);
3347 auto const preBob = env.
balance(bob);
3348 auto const preAliceUSD = env.
balance(alice, usd.issue());
3349 auto const preBobUSD = env.
balance(bob, usd.issue());
3356 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3365 .result =
"tesSUCCESS",
3367 .batchID = std::nullopt},
3369 .txType =
"CheckCreate",
3370 .result =
"tesSUCCESS",
3372 .batchID = batchID},
3374 .txType =
"CheckCash",
3375 .result =
"tesSUCCESS",
3377 .batchID = batchID},
3382 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
3385 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
3388 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
3389 BEAST_EXPECT(env.
balance(bob) == preBob);
3392 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD + usd(10));
3393 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD - usd(10));
3398 env(
fset(alice, asfRequireDest));
3401 auto const aliceSeq = env.
seq(alice);
3402 auto const bobSeq = env.
seq(bob);
3403 auto const preAlice = env.
balance(alice);
3404 auto const preBob = env.
balance(bob);
3405 auto const preAliceUSD = env.
balance(alice, usd.issue());
3406 auto const preBobUSD = env.
balance(bob, usd.issue());
3413 batch::outer(alice, aliceSeq, batchFee, tfIndependent),
3423 .result =
"tesSUCCESS",
3425 .batchID = std::nullopt},
3427 .txType =
"CheckCreate",
3428 .result =
"tecDST_TAG_NEEDED",
3430 .batchID = batchID},
3432 .txType =
"CheckCash",
3433 .result =
"tecNO_ENTRY",
3435 .batchID = batchID},
3440 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
3443 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
3446 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
3447 BEAST_EXPECT(env.
balance(bob) == preBob);
3450 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD);
3451 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD);
3458 testcase(
"object create w/ ticket");
3463 Env env{*
this, features};
3465 auto const alice =
Account(
"alice");
3466 auto const bob =
Account(
"bob");
3467 auto const gw =
Account(
"gw");
3468 auto const usd = gw[
"USD"];
3470 env.
fund(
XRP(10000), alice, bob, gw);
3473 env.
trust(usd(1000), alice, bob);
3474 env(
pay(gw, alice, usd(100)));
3475 env(
pay(gw, bob, usd(100)));
3478 auto const aliceSeq = env.
seq(alice);
3479 auto const bobSeq = env.
seq(bob);
3480 auto const preAlice = env.
balance(alice);
3481 auto const preBob = env.
balance(bob);
3482 auto const preAliceUSD = env.
balance(alice, usd.issue());
3483 auto const preBobUSD = env.
balance(bob, usd.issue());
3490 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3500 .result =
"tesSUCCESS",
3502 .batchID = std::nullopt},
3504 .txType =
"TicketCreate",
3505 .result =
"tesSUCCESS",
3507 .batchID = batchID},
3509 .txType =
"CheckCreate",
3510 .result =
"tesSUCCESS",
3512 .batchID = batchID},
3514 .txType =
"CheckCash",
3515 .result =
"tesSUCCESS",
3517 .batchID = batchID},
3521 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
3522 BEAST_EXPECT(env.
seq(bob) == bobSeq + 10 + 1);
3523 BEAST_EXPECT(env.
balance(alice) == preAlice - batchFee);
3524 BEAST_EXPECT(env.
balance(bob) == preBob);
3525 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD + usd(10));
3526 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD - usd(10));
3532 testcase(
"object create w/ 3rd party");
3537 Env env{*
this, features};
3539 auto const alice =
Account(
"alice");
3540 auto const bob =
Account(
"bob");
3541 auto const carol =
Account(
"carol");
3542 auto const gw =
Account(
"gw");
3543 auto const usd = gw[
"USD"];
3545 env.
fund(
XRP(10000), alice, bob, carol, gw);
3548 env.
trust(usd(1000), alice, bob);
3549 env(
pay(gw, alice, usd(100)));
3550 env(
pay(gw, bob, usd(100)));
3553 auto const aliceSeq = env.
seq(alice);
3554 auto const bobSeq = env.
seq(bob);
3555 auto const carolSeq = env.
seq(carol);
3556 auto const preAlice = env.
balance(alice);
3557 auto const preBob = env.
balance(bob);
3558 auto const preCarol = env.
balance(carol);
3559 auto const preAliceUSD = env.
balance(alice, usd.issue());
3560 auto const preBobUSD = env.
balance(bob, usd.issue());
3567 batch::outer(carol, carolSeq, batchFee, tfAllOrNothing),
3576 .result =
"tesSUCCESS",
3578 .batchID = std::nullopt},
3580 .txType =
"CheckCreate",
3581 .result =
"tesSUCCESS",
3583 .batchID = batchID},
3585 .txType =
"CheckCash",
3586 .result =
"tesSUCCESS",
3588 .batchID = batchID},
3592 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
3593 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
3594 BEAST_EXPECT(env.
seq(carol) == carolSeq + 1);
3595 BEAST_EXPECT(env.
balance(alice) == preAlice);
3596 BEAST_EXPECT(env.
balance(bob) == preBob);
3597 BEAST_EXPECT(env.
balance(carol) == preCarol - batchFee);
3598 BEAST_EXPECT(env.
balance(alice, usd.issue()) == preAliceUSD + usd(10));
3599 BEAST_EXPECT(env.
balance(bob, usd.issue()) == preBobUSD - usd(10));
3611 Env env{*
this, features};
3613 auto const alice =
Account(
"alice");
3614 auto const bob =
Account(
"bob");
3616 env.
fund(
XRP(10000), alice, bob);
3623 auto const aliceSeq = env.
seq(alice);
3624 auto const preAlice = env.
balance(alice);
3625 auto const preBob = env.
balance(bob);
3640 .result =
"tesSUCCESS",
3642 .batchID = std::nullopt},
3644 .txType =
"Payment",
3645 .result =
"tesSUCCESS",
3647 .batchID = batchID},
3649 .txType =
"Payment",
3650 .result =
"tesSUCCESS",
3652 .batchID = batchID},
3658 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 9);
3659 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 9);
3661 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
3662 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
3663 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
3672 Env env{*
this, features};
3674 auto const alice =
Account(
"alice");
3675 auto const bob =
Account(
"bob");
3677 env.
fund(
XRP(10000), alice, bob);
3684 auto const aliceSeq = env.
seq(alice);
3685 auto const preAlice = env.
balance(alice);
3686 auto const preBob = env.
balance(bob);
3692 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3700 .result =
"tesSUCCESS",
3702 .batchID = std::nullopt},
3704 .txType =
"Payment",
3705 .result =
"tesSUCCESS",
3707 .batchID = batchID},
3709 .txType =
"Payment",
3710 .result =
"tesSUCCESS",
3712 .batchID = batchID},
3718 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
3719 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
3721 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
3722 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
3723 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
3732 Env env{*
this, features};
3734 auto const alice =
Account(
"alice");
3735 auto const bob =
Account(
"bob");
3737 env.
fund(
XRP(10000), alice, bob);
3744 auto const aliceSeq = env.
seq(alice);
3745 auto const preAlice = env.
balance(alice);
3746 auto const preBob = env.
balance(bob);
3761 .result =
"tesSUCCESS",
3763 .batchID = std::nullopt},
3765 .txType =
"Payment",
3766 .result =
"tesSUCCESS",
3768 .batchID = batchID},
3770 .txType =
"Payment",
3771 .result =
"tesSUCCESS",
3773 .batchID = batchID},
3779 BEAST_EXPECT(sle->getFieldU32(sfOwnerCount) == 8);
3780 BEAST_EXPECT(sle->getFieldU32(sfTicketCount) == 8);
3782 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 1);
3783 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
3784 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
3796 auto const alice =
Account(
"alice");
3797 auto const bob =
Account(
"bob");
3798 auto const carol =
Account(
"carol");
3807 Env env{*
this, features};
3808 env.
fund(
XRP(10000), alice, bob, carol);
3811 auto const aliceSeq = env.
seq(alice);
3812 auto const carolSeq = env.
seq(carol);
3815 auto const noopTxn = env.
jt(
noop(alice),
Seq(aliceSeq + 2));
3816 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3824 batch::outer(carol, carolSeq, batchFee, tfAllOrNothing),
3834 .result =
"tesSUCCESS",
3836 .batchID = std::nullopt},
3838 .txType =
"Payment",
3839 .result =
"tesSUCCESS",
3841 .batchID = batchID},
3843 .txType =
"Payment",
3844 .result =
"tesSUCCESS",
3846 .batchID = batchID},
3856 .txType =
"AccountSet",
3857 .result =
"tesSUCCESS",
3858 .txHash = noopTxnID,
3859 .batchID = std::nullopt},
3870 Env env{*
this, features};
3871 env.
fund(
XRP(10000), alice, bob);
3874 auto const aliceSeq = env.
seq(alice);
3877 auto const noopTxn = env.
jt(
noop(alice),
Seq(aliceSeq + 1));
3885 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3894 .result =
"tesSUCCESS",
3896 .batchID = std::nullopt},
3898 .txType =
"Payment",
3899 .result =
"tesSUCCESS",
3901 .batchID = batchID},
3903 .txType =
"Payment",
3904 .result =
"tesSUCCESS",
3906 .batchID = batchID},
3924 Env env{*
this, features};
3925 env.
fund(
XRP(10000), alice, bob);
3928 auto const aliceSeq = env.
seq(alice);
3933 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
3937 auto const noopTxn = env.
jt(
noop(alice),
Seq(aliceSeq + 1));
3945 .result =
"tesSUCCESS",
3947 .batchID = std::nullopt},
3949 .txType =
"Payment",
3950 .result =
"tesSUCCESS",
3952 .batchID = batchID},
3954 .txType =
"Payment",
3955 .result =
"tesSUCCESS",
3957 .batchID = batchID},
3972 Env env{*
this, features};
3973 env.
fund(
XRP(10000), alice, bob, carol);
3976 auto const aliceSeq = env.
seq(alice);
3977 auto const carolSeq = env.
seq(carol);
3984 batch::outer(carol, carolSeq + 1, batchFee, tfAllOrNothing),
3990 auto const noopTxn = env.
jt(
noop(carol),
Seq(carolSeq));
3991 auto const noopTxnID =
to_string(noopTxn.stx->getTransactionID());
3998 .txType =
"AccountSet",
3999 .result =
"tesSUCCESS",
4000 .txHash = noopTxnID,
4001 .batchID = std::nullopt},
4004 .result =
"tesSUCCESS",
4006 .batchID = std::nullopt},
4008 .txType =
"Payment",
4009 .result =
"tesSUCCESS",
4011 .batchID = batchID},
4013 .txType =
"Payment",
4014 .result =
"tesSUCCESS",
4016 .batchID = batchID},
4038 auto const alice =
Account(
"alice");
4039 auto const bob =
Account(
"bob");
4046 Env env{*
this, features};
4047 env.
fund(
XRP(10000), alice, bob);
4054 auto const aliceSeq = env.
seq(alice);
4075 .result =
"tesSUCCESS",
4077 .batchID = std::nullopt},
4079 .txType =
"Payment",
4080 .result =
"tesSUCCESS",
4082 .batchID = batchID},
4084 .txType =
"Payment",
4085 .result =
"tesSUCCESS",
4087 .batchID = batchID},
4105 Env env{*
this, features};
4106 env.
fund(
XRP(10000), alice, bob);
4113 auto const aliceSeq = env.
seq(alice);
4134 .result =
"tesSUCCESS",
4136 .batchID = std::nullopt},
4138 .txType =
"Payment",
4139 .result =
"tesSUCCESS",
4141 .batchID = batchID},
4143 .txType =
"Payment",
4144 .result =
"tesSUCCESS",
4146 .batchID = batchID},
4168 auto const alice =
Account(
"alice");
4169 auto const bob =
Account(
"bob");
4178 Env env{*
this, features};
4179 env.
fund(
XRP(10000), alice, bob);
4186 auto const aliceSeq = env.
seq(alice);
4191 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
4209 .result =
"tesSUCCESS",
4211 .batchID = std::nullopt},
4213 .txType =
"CheckCreate",
4214 .result =
"tesSUCCESS",
4216 .batchID = batchID},
4218 .txType =
"Payment",
4219 .result =
"tesSUCCESS",
4221 .batchID = batchID},
4223 .txType =
"CheckCash",
4224 .result =
"tesSUCCESS",
4226 .batchID = std::nullopt},
4241 Env env{*
this, features};
4242 env.
fund(
XRP(10000), alice, bob);
4249 auto const aliceSeq = env.
seq(alice);
4250 auto const bobSeq = env.
seq(bob);
4255 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
4273 .txType =
"CheckCreate",
4274 .result =
"tesSUCCESS",
4276 .batchID = std::nullopt},
4279 .result =
"tesSUCCESS",
4281 .batchID = std::nullopt},
4283 .txType =
"CheckCash",
4284 .result =
"tesSUCCESS",
4286 .batchID = batchID},
4288 .txType =
"Payment",
4289 .result =
"tesSUCCESS",
4291 .batchID = batchID},
4304 Env env{*
this, features};
4305 env.
fund(
XRP(10000), alice, bob);
4312 auto const aliceSeq = env.
seq(alice);
4327 auto const objTxnID =
to_string(objTxn.stx->getTransactionID());
4335 .result =
"tesSUCCESS",
4337 .batchID = std::nullopt},
4339 .txType =
"CheckCreate",
4340 .result =
"tesSUCCESS",
4342 .batchID = batchID},
4344 .txType =
"Payment",
4345 .result =
"tesSUCCESS",
4347 .batchID = batchID},
4349 .txType =
"CheckCash",
4350 .result =
"tesSUCCESS",
4352 .batchID = std::nullopt},
4362 testcase(
"pseudo txn with tfInnerBatchTxn");
4367 Env env{*
this, features};
4369 auto const alice =
Account(
"alice");
4370 auto const bob =
Account(
"bob");
4371 env.
fund(
XRP(10000), alice, bob);
4374 STTx const stx =
STTx(ttAMENDMENT, [&](
auto& obj) {
4375 obj.setAccountID(sfAccount,
AccountID());
4376 obj.setFieldH256(sfAmendment,
uint256(2));
4377 obj.setFieldU32(sfLedgerSequence, env.
seq(alice));
4384 BEAST_EXPECT(reason ==
"Cannot submit pseudo transactions.");
4388 return result.applied;
4406 Env env{*
this, features};
4409 auto const alice =
Account(
"alice");
4410 auto const bob =
Account(
"bob");
4412 env.
fund(
XRP(10000), alice, bob);
4418 auto const aliceSeq = env.
seq(alice);
4419 auto const preAlice = env.
balance(alice);
4420 auto const preBob = env.
balance(bob);
4421 auto const bobSeq = env.
seq(bob);
4424 auto const payTxn1 = env.
jt(
pay(alice, bob,
XRP(10)),
Seq(aliceSeq));
4425 auto const payTxn1ID =
to_string(payTxn1.stx->getTransactionID());
4433 batch::outer(alice, aliceSeq + 1, batchFee, tfAllOrNothing),
4439 auto const payTxn2 = env.
jt(
pay(bob, alice,
XRP(5)),
Seq(bobSeq + 1));
4440 auto const payTxn2ID =
to_string(payTxn2.stx->getTransactionID());
4446 .txType =
"Payment",
4447 .result =
"tesSUCCESS",
4448 .txHash = payTxn1ID,
4449 .batchID = std::nullopt},
4452 .result =
"tesSUCCESS",
4454 .batchID = std::nullopt},
4456 .txType =
"Payment",
4457 .result =
"tesSUCCESS",
4459 .batchID = batchID},
4461 .txType =
"Payment",
4462 .result =
"tesSUCCESS",
4464 .batchID = batchID},
4473 .txType =
"Payment",
4474 .result =
"tesSUCCESS",
4475 .txHash = payTxn2ID,
4476 .batchID = std::nullopt},
4482 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 3);
4485 BEAST_EXPECT(env.
seq(bob) == bobSeq + 2);
4488 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(10) - batchFee - baseFee);
4489 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(10) - baseFee);
4512 auto alice =
Account(
"alice");
4514 auto carol =
Account(
"carol");
4518 env.
close(env.
now() + 5s, 10000ms);
4520 env.
close(env.
now() + 5s, 10000ms);
4531 auto const aliceSeq = env.
seq(alice);
4532 auto const bobSeq = env.
seq(bob);
4537 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
4563 auto alice =
Account(
"alice");
4565 auto carol =
Account(
"carol");
4569 env.
close(env.
now() + 5s, 10000ms);
4571 env.
close(env.
now() + 5s, 10000ms);
4578 auto const aliceSeq = env.
seq(alice);
4579 auto const bobSeq = env.
seq(bob);
4584 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
4608 auto alice =
Account(
"alice");
4612 env.
close(env.
now() + 5s, 10000ms);
4620 auto const aliceSeq = env.
seq(alice);
4629 auto const bobSeq = env.
seq(bob);
4631 env(
batch::outer(alice, aliceSeq + 2, batchFee, tfAllOrNothing),
4652 auto alice =
Account(
"alice");
4654 env.
fund(
XRP(10000), alice, bob);
4662 return jt.stx->getTransactionID();
4673 return transaction->getID();
4694 testcase(
"batch delegate consent");
4711 Env env{*
this, features};
4713 auto const alice =
Account(
"alice");
4714 auto const bob =
Account(
"bob");
4715 auto const mallory =
Account(
"mallory");
4716 env.
fund(
XRP(10000), alice, bob, mallory);
4722 auto const preMallory = env.
balance(mallory);
4725 auto const seq = env.
seq(alice);
4728 inner[jss::Delegate] = bob.human();
4731 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
4738 BEAST_EXPECT(env.
balance(mallory) == preMallory);
4752 Env env{*
this, features};
4754 auto const alice =
Account(
"alice");
4755 auto const bob =
Account(
"bob");
4756 auto const mallory =
Account(
"mallory");
4757 env.
fund(
XRP(10000), alice, bob, mallory);
4760 auto const preMallory = env.
balance(mallory);
4763 auto const seq = env.
seq(alice);
4766 inner[jss::Delegate] = bob.human();
4768 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
4774 BEAST_EXPECT(env.
balance(mallory) == preMallory);
4780 Env env{*
this, features};
4782 auto const alice =
Account(
"alice");
4783 auto const bob =
Account(
"bob");
4784 auto const mallory =
Account(
"mallory");
4785 env.
fund(
XRP(10000), alice, bob, mallory);
4788 auto const preMallory = env.
balance(mallory);
4791 auto const seq = env.
seq(alice);
4794 inner[jss::Delegate] = bob.human();
4796 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
4803 BEAST_EXPECT(env.
balance(mallory) == preMallory +
XRP(1000));
4809 Env env{*
this, features};
4811 auto const alice =
Account(
"alice");
4812 auto const bob =
Account(
"bob");
4813 auto const carol =
Account(
"carol");
4814 env.
fund(
XRP(10000), alice, bob, carol);
4820 auto const preAlice = env.
balance(alice);
4823 auto const aliceSeq = env.
seq(alice);
4824 auto const bobSeq = env.
seq(bob);
4827 inner[jss::Delegate] = carol.human();
4830 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
4836 BEAST_EXPECT(env.
balance(alice) == preAlice);
4842 Env env{*
this, features};
4844 auto const alice =
Account(
"alice");
4845 auto const bob =
Account(
"bob");
4846 auto const carol =
Account(
"carol");
4847 auto const mallory =
Account(
"mallory");
4848 env.
fund(
XRP(10000), alice, bob, carol, mallory);
4854 auto const preMallory = env.
balance(mallory);
4857 auto const seq = env.
seq(alice);
4860 inner[jss::Delegate] = bob.human();
4863 env(
batch::outer(alice, seq, batchFee, tfAllOrNothing),
4870 BEAST_EXPECT(env.
balance(mallory) == preMallory);
4876 Env env{*
this, features};
4878 auto const alice =
Account(
"alice");
4879 auto const bob =
Account(
"bob");
4880 env.
fund(
XRP(10000), alice, bob);
4887 auto const preBob = env.
balance(bob);
4890 auto const aliceSeq = env.
seq(alice);
4891 auto const bobSeq = env.
seq(bob);
4894 inner[jss::Delegate] = alice.human();
4896 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
4903 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
4911 Env env{*
this, features};
4913 auto const alice =
Account(
"alice");
4914 auto const bob =
Account(
"bob");
4915 auto const carol =
Account(
"carol");
4916 env.
fund(
XRP(10000), alice, bob, carol);
4922 auto const preAlice = env.
balance(alice);
4925 auto const aliceSeq = env.
seq(alice);
4926 auto const bobSeq = env.
seq(bob);
4929 inner[jss::Delegate] = carol.human();
4932 env(
batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
4939 BEAST_EXPECT(env.
balance(alice) == preAlice);
4947 Env env{*
this, features};
4949 auto const alice =
Account(
"alice");
4950 auto const bob =
Account(
"bob");
4951 auto const mallory =
Account(
"mallory");
4952 env.
fund(
XRP(10000), alice, bob, mallory);
4958 auto const preMallory = env.
balance(mallory);
4961 auto const seq = env.
seq(bob);
4964 inner2[jss::Delegate] = alice.human();
4980 .result =
"tesSUCCESS",
4982 .batchID = std::nullopt},
4984 .txType =
"Payment",
4985 .result =
"tesSUCCESS",
4987 .batchID = batchID},
4989 .txType =
"Payment",
4990 .result =
"tesSUCCESS",
4992 .batchID = batchID},
4997 BEAST_EXPECT(env.
balance(mallory) == preMallory +
XRP(1000));
5007 Env env{*
this, features};
5009 auto const alice =
Account(
"alice");
5010 auto const bob =
Account(
"bob");
5011 auto const mallory =
Account(
"mallory");
5012 env.
fund(
XRP(10000), alice, bob, mallory);
5018 auto const preMallory = env.
balance(mallory);
5021 auto const seq = env.
seq(bob);
5026 inner2[jss::Delegate] = alice.human();
5043 .result =
"tesSUCCESS",
5045 .batchID = std::nullopt},
5047 .txType =
"DelegateSet",
5048 .result =
"tesSUCCESS",
5050 .batchID = batchID},
5056 BEAST_EXPECT(env.
balance(mallory) == preMallory);
5057 BEAST_EXPECT(env.
rpc(
"tx", txIDs[1])[jss::result][jss::error] ==
"txnNotFound");
5071 Env env{*
this, features};
5073 auto const alice =
Account(
"alice");
5074 auto const bob =
Account(
"bob");
5075 auto const gw =
Account(
"gw");
5076 auto const usd = gw[
"USD"];
5077 env.
fund(
XRP(10000), alice, bob, gw);
5083 auto const preAlice = env.
balance(alice);
5084 auto const preBob = env.
balance(bob);
5087 auto const seq = env.
seq(alice);
5090 tx[jss::Delegate] = bob.human();
5105 .result =
"tesSUCCESS",
5107 .batchID = std::nullopt},
5109 .txType =
"Payment",
5110 .result =
"tesSUCCESS",
5112 .batchID = batchID},
5114 .txType =
"Payment",
5115 .result =
"tesSUCCESS",
5117 .batchID = batchID},
5122 BEAST_EXPECT(env.
seq(alice) == seq + 3);
5125 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(3) - batchFee);
5126 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(3));
5131 Env env{*
this, features};
5133 auto const alice =
Account(
"alice");
5134 auto const bob =
Account(
"bob");
5135 auto const carol =
Account(
"carol");
5136 auto const gw =
Account(
"gw");
5137 auto const usd = gw[
"USD"];
5138 env.
fund(
XRP(10000), alice, bob, carol, gw);
5144 auto const preAlice = env.
balance(alice);
5145 auto const preBob = env.
balance(bob);
5146 auto const preCarol = env.
balance(carol);
5149 auto const aliceSeq = env.
seq(alice);
5150 auto const bobSeq = env.
seq(bob);
5153 tx[jss::Delegate] = carol.human();
5159 batch::outer(alice, aliceSeq, batchFee, tfAllOrNothing),
5168 .result =
"tesSUCCESS",
5170 .batchID = std::nullopt},
5172 .txType =
"Payment",
5173 .result =
"tesSUCCESS",
5175 .batchID = batchID},
5177 .txType =
"Payment",
5178 .result =
"tesSUCCESS",
5180 .batchID = batchID},
5184 BEAST_EXPECT(env.
seq(alice) == aliceSeq + 2);
5185 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
5186 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1) - batchFee);
5187 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(1));
5190 BEAST_EXPECT(env.
balance(carol) == preCarol);
5197 Env env{*
this, features};
5199 auto const alice =
Account(
"alice");
5200 auto const bob =
Account(
"bob");
5201 auto const gw =
Account(
"gw");
5202 auto const usd = gw[
"USD"];
5203 env.
fund(
XRP(10000), alice, bob, gw);
5209 auto const preAlice = env.
balance(alice);
5210 auto const preBob = env.
balance(bob);
5213 auto const seq = env.
seq(alice);
5217 tx[sfDomain.jsonName] =
strHex(domain);
5218 tx[jss::Delegate] = bob.human();
5233 .result =
"tesSUCCESS",
5235 .batchID = std::nullopt},
5237 .txType =
"AccountSet",
5238 .result =
"tesSUCCESS",
5240 .batchID = batchID},
5242 .txType =
"Payment",
5243 .result =
"tesSUCCESS",
5245 .batchID = batchID},
5250 BEAST_EXPECT(env.
seq(alice) == seq + 3);
5253 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(2) - batchFee);
5254 BEAST_EXPECT(env.
balance(bob) == preBob +
XRP(2));
5261 Env env{*
this, features};
5264 env.
fund(
XRP(100000), alice, bob);
5268 MPTTester mpt(env, alice, {.fund =
false});
5270 mpt.create({.flags = tfMPTCanLock});
5274 env(
delegate::set(alice, bob, {
"MPTokenIssuanceLock",
"MPTokenIssuanceUnlock"}));
5277 auto const seq = env.
seq(alice);
5281 jv1[sfTransactionType] = jss::MPTokenIssuanceSet;
5282 jv1[sfAccount] = alice.
human();
5283 jv1[sfDelegate] = bob.
human();
5284 jv1[sfSequence] = seq + 1;
5285 jv1[sfMPTokenIssuanceID] =
to_string(mptID);
5286 jv1[sfFlags] = tfMPTLock;
5289 jv2[sfTransactionType] = jss::MPTokenIssuanceSet;
5290 jv2[sfAccount] = alice.
human();
5291 jv2[sfDelegate] = bob.
human();
5292 jv2[sfSequence] = seq + 2;
5293 jv2[sfMPTokenIssuanceID] =
to_string(mptID);
5294 jv2[sfFlags] = tfMPTUnlock;
5310 .result =
"tesSUCCESS",
5312 .batchID = std::nullopt},
5314 .txType =
"MPTokenIssuanceSet",
5315 .result =
"tesSUCCESS",
5317 .batchID = batchID},
5319 .txType =
"MPTokenIssuanceSet",
5320 .result =
"tesSUCCESS",
5322 .batchID = batchID},
5331 Env env{*
this, features};
5335 env.
fund(
XRP(10000), gw, alice, bob);
5336 env(
fset(gw, asfRequireAuth));
5338 env(
trust(alice, gw[
"USD"](50)));
5341 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
5344 auto const seq = env.
seq(gw);
5347 auto jv1 =
trust(gw, gw[
"USD"](0), alice, tfSetfAuth);
5348 jv1[sfDelegate] = bob.
human();
5349 auto jv2 =
trust(gw, gw[
"USD"](0), alice, tfSetFreeze);
5350 jv2[sfDelegate] = bob.
human();
5366 .result =
"tesSUCCESS",
5368 .batchID = std::nullopt},
5370 .txType =
"TrustSet",
5371 .result =
"tesSUCCESS",
5373 .batchID = batchID},
5375 .txType =
"TrustSet",
5376 .result =
"tesSUCCESS",
5378 .batchID = batchID},
5385 Env env{*
this, features};
5389 env.
fund(
XRP(10000), gw, alice, bob);
5390 env(
fset(gw, asfRequireAuth));
5392 env(
trust(alice, gw[
"USD"](50)));
5395 env(
delegate::set(gw, bob, {
"TrustlineAuthorize",
"TrustlineFreeze"}));
5398 auto const seq = env.
seq(gw);
5401 auto jv1 =
trust(gw, gw[
"USD"](0), alice, tfSetFreeze);
5402 jv1[sfDelegate] = bob.
human();
5403 auto jv2 =
trust(gw, gw[
"USD"](0), alice, tfClearFreeze);
5404 jv2[sfDelegate] = bob.
human();
5421 .result =
"tesSUCCESS",
5423 .batchID = std::nullopt},
5425 .txType =
"TrustSet",
5426 .result =
"tesSUCCESS",
5428 .batchID = batchID},
5434 BEAST_EXPECT(env.
rpc(
"tx", txIDs[1])[jss::result][jss::error] ==
"txnNotFound");
5446 using namespace jtx;
5447 Env env(*
this, features);
5450 env.
fund(
XRP(10000), alice, bob);
5455 auto const baseFee = env.
current()->fees().base;
5456 auto const aliceSeq = env.
seq(alice);
5461 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
5464 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
5465 BEAST_EXPECT(jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
5466 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
5467 BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
5468 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
5469 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
5470 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
5475 auto const baseFee = env.
current()->fees().base;
5476 auto const aliceSeq = env.
seq(alice);
5477 env(
fset(bob, asfRequireDest));
5482 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
5485 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
5486 BEAST_EXPECT(jr[jss::account_sequence_available].asUInt() == aliceSeq + 1);
5487 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
5488 BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq + 1);
5489 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
5490 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
5491 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
5496 auto const baseFee = env.
current()->fees().base;
5497 auto const aliceSeq = env.
seq(alice);
5502 auto const jr = env.
rpc(
"submit",
strHex(s.
slice()))[jss::result];
5505 BEAST_EXPECT(jr.isMember(jss::account_sequence_available));
5506 BEAST_EXPECT(jr[jss::account_sequence_available].asUInt() == aliceSeq);
5507 BEAST_EXPECT(jr.isMember(jss::account_sequence_next));
5508 BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq);
5509 BEAST_EXPECT(jr.isMember(jss::open_ledger_cost));
5510 BEAST_EXPECT(jr[jss::open_ledger_cost] ==
to_string(baseFee));
5511 BEAST_EXPECT(jr.isMember(jss::validated_ledger_index));
5518 using namespace jtx;
5519 Env env(*
this, features);
5523 env.
fund(
XRP(10000), alice, bob, carol);
5535 auto const seq = env.
seq(alice);
5541 BEAST_EXPECT(
jtx.stx ==
nullptr);
5547 auto const seq = env.
seq(alice);
5562 BEAST_EXPECT(
jtx.stx ==
nullptr);
5567 auto const seq = env.
seq(alice);
5577 BEAST_EXPECT(txBaseFee == env.
current()->fees().base);
5582 auto const seq = env.
seq(alice);
5589 BEAST_EXPECT(txBaseFee == batchFee);
5596 testcase(
"standalone tx with tfInnerBatchTxn rejected");
5605 Env env{*
this, features};
5607 auto const alice =
Account(
"alice");
5608 auto const bob =
Account(
"bob");
5609 env.
fund(
XRP(10000), alice, bob);
5623 STTx const stx =
STTx(ttPAYMENT, [&](
auto& obj) {
5624 obj.setAccountID(sfAccount, alice.id());
5625 obj.setAccountID(sfDestination, bob.id());
5626 obj.setFieldAmount(sfAmount,
XRP(1));
5627 obj.setFieldAmount(sfFee,
XRP(0));
5628 obj.setFieldU32(sfSequence, env.
seq(alice));
5634 BEAST_EXPECT(!result.applied);
5650 Env env{*
this, features};
5652 auto const alice =
Account(
"alice");
5653 auto const bob =
Account(
"bob");
5654 auto const carol =
Account(
"carol");
5655 auto const eve =
Account(
"eve");
5656 env.
fund(
XRP(10000), alice, bob, carol, eve);
5659 auto const preCarol = env.
balance(carol);
5660 auto const bobSeq = env.
seq(bob);
5661 auto const carolSeq = env.
seq(carol);
5663 auto const aliceSeq = env.
seq(alice);
5671 auto const capturedSigners = jt1.
jv[sfBatchSigners.jsonName];
5675 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
5676 BEAST_EXPECT(env.
seq(carol) == carolSeq);
5684 jt2.
jv[sfBatchSigners.jsonName] = capturedSigners;
5688 BEAST_EXPECT(env.
seq(carol) == carolSeq);
5689 BEAST_EXPECT(env.
balance(carol) == preCarol);
5695 Env env{*
this, features};
5697 auto const alice =
Account(
"alice");
5698 auto const bob =
Account(
"bob");
5699 auto const carol =
Account(
"carol");
5700 env.
fund(
XRP(10000), alice, bob, carol);
5703 auto const preCarol = env.
balance(carol);
5704 auto const bobSeq = env.
seq(bob);
5705 auto const carolSeq = env.
seq(carol);
5707 auto const aliceSeq1 = env.
seq(alice);
5715 auto const capturedSigners = jt1.
jv[sfBatchSigners.jsonName];
5719 BEAST_EXPECT(env.
seq(bob) == bobSeq + 1);
5720 BEAST_EXPECT(env.
seq(carol) == carolSeq);
5728 jt2.
jv[sfBatchSigners.jsonName] = capturedSigners;
5732 BEAST_EXPECT(env.
balance(carol) == preCarol);
5733 BEAST_EXPECT(env.
seq(carol) == carolSeq);
5739 Env env{*
this, features};
5741 auto const alice =
Account(
"alice");
5742 auto const bob =
Account(
"bob");
5743 auto const carol =
Account(
"carol");
5744 auto const dave =
Account(
"dave");
5745 auto const elsa =
Account(
"elsa");
5746 env.
fund(
XRP(10000), alice, bob, carol, dave, elsa);
5749 env(
signers(bob, 2, {{dave, 1}, {elsa, 1}}));
5751 env(
signers(carol, 2, {{dave, 1}, {elsa, 1}}));
5754 auto const seq = env.
seq(alice);
5763 auto const bobSignerEntry = jt1.
jv[sfBatchSigners.jsonName][0u];
5768 auto const seq2 = env.
seq(alice);
5776 carolSigner[sfBatchSigner.jsonName][jss::Account] = carol.human();
5777 carolSigner[sfBatchSigner.jsonName][jss::SigningPubKey] =
"";
5778 carolSigner[sfBatchSigner.jsonName][sfSigners.jsonName] =
5779 bobSignerEntry[sfBatchSigner.jsonName][sfSigners.jsonName];
5781 jt2.jv[sfBatchSigners.jsonName][0u] = carolSigner;
5790 testcase(
"unsorted batch signers");
5794 Env env{*
this, features};
5796 auto const alice =
Account(
"alice");
5797 auto const bob =
Account(
"bob");
5798 auto const carol =
Account(
"carol");
5799 env.
fund(
XRP(10000), alice, bob, carol);
5802 auto const seq = env.
seq(alice);
5803 auto const bobSeq = env.
seq(bob);
5804 auto const carolSeq = env.
seq(carol);
5813 auto const s0 = jt.
jv[sfBatchSigners.jsonName][0u];
5814 auto const s1 = jt.jv[sfBatchSigners.jsonName][1u];
5815 jt.jv[sfBatchSigners.jsonName][0u] = s1;
5816 jt.jv[sfBatchSigners.jsonName][1u] = s0;
5825 testcase(
"batch signature caching");
5835 auto buildValidBatch = [](
Env& env) {
5836 auto const alice =
Account(
"alice");
5837 auto const bob =
Account(
"bob");
5838 auto const seq = env.seq(alice);
5849 Env env{*
this, features};
5853 auto jt = buildValidBatch(env);
5854 auto const txid = jt.stx->getTransactionID();
5865 Env env{*
this, features};
5869 auto jt = buildValidBatch(env);
5870 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfTxnSignature.jsonName] =
5877 Env env{*
this, features};
5881 auto jt = buildValidBatch(env);
5882 jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfTxnSignature.jsonName] =
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.
Lightweight wrapper to tag static string.
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
static constexpr auto kDisabledTxTypes
HashRouterFlags getFlags(uint256 const &key)
bool setFlags(uint256 const &key, HashRouterFlags flags)
Set the flags on a hash.
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
uint256 getTransactionID() const
static constexpr SeqProxy rawSequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
Slice slice() const noexcept
virtual NetworkOPs & getOPs()=0
virtual OpenLedger & getOpenLedger()=0
virtual HashRouter & getHashRouter()=0
An immutable linear range of bytes.
static NotTEC invokePreflight(PreflightContext const &ctx)
Metrics getMetrics(OpenView const &view) const
Returns fee metrics in reference fee level units.
void testOpenLedger(FeatureBitset features)
void testBatchDelegateConsent(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 testStandaloneInnerBatchFlag(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 testCheckAllSignatures(FeatureBitset features)
void testValidateRPCResponse(FeatureBitset features)
void testWithFeats(FeatureBitset features)
void testBatchCalculateBaseFee(FeatureBitset features)
void testLoan(FeatureBitset features)
void testOuterBinding(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 testUnsortedBatchSigners(FeatureBitset features)
void testPseudoTxn(FeatureBitset features)
void testBadOuterFee(FeatureBitset features)
void testBatchSigCache(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)
ParseFailureGuard getParseFailureGuard(bool b)
Gets an RAII guard to set and restore the parse failure flag.
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.
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.
beast::Journal const journal
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).
TER valid(STTx const &tx, ReadView const &view, AccountID const &src, beast::Journal j)
Keylet loan(uint256 const &loanBrokerID, SeqProxy const &loanSeq) noexcept
Keylet check(AccountID const &id, SeqProxy const &seq) noexcept
A Check.
Keylet loanBroker(AccountID const &owner, SeqProxy const &seq) 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
constexpr std::size_t kMaxBatchSigners
The maximum number of batch signers.
@ SigBad
Signature is bad.
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)
std::pair< Validity, std::string > checkValidity(HashRouter &router, STTx const &tx, Rules const &rules)
Checks transaction signature and local checks.
constexpr TenthBips32 percentageToTenthBips(std::uint32_t percentage)
constexpr std::size_t kMaxBatchTxCount
The maximum number of transactions that can be in a batch.
constexpr HashRouterFlags kSfSiggood
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(STTx const &tx, std::string &)
void finishMultiSigningData(AccountID const &signingID, Serializer &s)
MPTID makeMptID(std::uint32_t const sequence, AccountID const &account)
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
std::vector< unsigned char > Blob
Storage for linear binary data.
void serializeBatch(Serializer &msg, AccountID const &outerAccount, std::uint32_t outerSeqValue, std::uint32_t const &flags, std::vector< uint256 > const &txids)
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
uint256 TxID
A transaction identifier.
constexpr bool any(HashRouterFlags flags)
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
State information when preflighting a tx.
static constexpr auto kTransactionQueue
std::optional< std::string > batchID
Execution context for applying a JSON transaction.
std::shared_ptr< STTx const > stx
Set the sequence number on a JTx.