2#include <test/jtx/Account.h>
3#include <test/jtx/Env.h>
4#include <test/jtx/Env_ss.h>
5#include <test/jtx/JTx.h>
6#include <test/jtx/amount.h>
7#include <test/jtx/balance.h>
8#include <test/jtx/envconfig.h>
9#include <test/jtx/fee.h>
10#include <test/jtx/flags.h>
11#include <test/jtx/memo.h>
12#include <test/jtx/multisign.h>
13#include <test/jtx/noop.h>
14#include <test/jtx/offer.h>
15#include <test/jtx/owners.h>
16#include <test/jtx/paths.h>
17#include <test/jtx/pay.h>
18#include <test/jtx/prop.h>
19#include <test/jtx/rate.h>
20#include <test/jtx/regkey.h>
21#include <test/jtx/require.h>
22#include <test/jtx/rpc.h>
23#include <test/jtx/sendmax.h>
24#include <test/jtx/seq.h>
25#include <test/jtx/sig.h>
26#include <test/jtx/tags.h>
27#include <test/jtx/ter.h>
28#include <test/jtx/ticket.h>
29#include <test/jtx/trust.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/hash/uhash.h>
36#include <xrpl/beast/unit_test/suite.h>
37#include <xrpl/beast/utility/Journal.h>
38#include <xrpl/config/Constants.h>
39#include <xrpl/json/json_value.h>
40#include <xrpl/protocol/AccountID.h>
41#include <xrpl/protocol/ErrorCodes.h>
42#include <xrpl/protocol/Feature.h>
43#include <xrpl/protocol/KeyType.h>
44#include <xrpl/protocol/SField.h>
45#include <xrpl/protocol/STAmount.h>
46#include <xrpl/protocol/Serializer.h>
47#include <xrpl/protocol/TER.h>
48#include <xrpl/protocol/TxFlags.h>
49#include <xrpl/protocol/TxFormats.h>
50#include <xrpl/protocol/jss.h>
51#include <xrpl/server/NetworkOPs.h>
53#include <boost/lexical_cast.hpp>
76 return boost::lexical_cast<std::string>(t);
96 auto const usd = gw[
"USD"];
121 fail(
"missing exception");
131 fail(
"missing exception");
147 BEAST_EXPECT(
toString(
XRP(-.005)) ==
"-5000 drops");
152 BEAST_EXPECT(
XRP(1) ==
drops(1000000));
157 auto const usd = gw[
"USD"];
158 BEAST_EXPECT(
toString(usd(0)) ==
"0/USD(gw)");
159 BEAST_EXPECT(
toString(usd(10)) ==
"10/USD(gw)");
160 BEAST_EXPECT(
toString(usd(-10)) ==
"-10/USD(gw)");
161 BEAST_EXPECT(usd(0) ==
STAmount(usd, 0));
162 BEAST_EXPECT(usd(1) ==
STAmount(usd, 1));
163 BEAST_EXPECT(usd(-1) ==
STAmount(usd, -1));
166 BEAST_EXPECT(!
get(usd(10)).isAny);
167 BEAST_EXPECT(
get(
kAny(usd(10))).isAny);
175 auto const n =
XRP(10000);
177 auto const usd = gw[
"USD"];
178 auto const alice =
Account(
"alice");
191 env.
fund(n,
"alice");
192 env.
fund(n,
"bob",
"carol");
202 env.
fund(n,
"zachary");
209 env.
fund(n,
"alice",
"bob", gw);
217 BEAST_EXPECT(env.
balance(alice) == 0);
218 BEAST_EXPECT(env.
balance(alice, usd) != 0);
219 BEAST_EXPECT(env.
balance(alice, usd) == usd(0));
220 env.
fund(n, alice, gw);
222 BEAST_EXPECT(env.
balance(alice) == n);
223 BEAST_EXPECT(env.
balance(gw) == n);
224 env.
trust(usd(1000), alice);
225 env(
pay(gw, alice, usd(10)));
227 BEAST_EXPECT(
toString(env.
balance(gw, alice[
"USD"])) ==
"-10/USD(alice)");
234 BEAST_EXPECT(env.
seq(
"alice") == 3);
235 BEAST_EXPECT(env.
seq(gw) == 3);
241 env.
fund(n,
"alice");
261 auto const usd = gw[
"USD"];
264 env.
fund(
XRP(10000),
"alice", gw);
267 env.
trust(usd(100),
"alice");
273 env(
fset(
"alice", asfRequireDest),
Require(
Flags(
"alice", asfRequireDest)));
287 env.
fund(
XRP(10000), alice, bob);
304 env(
fset(alice, asfDisableMaster),
Sig(alice));
309 env(
fclear(alice, asfDisableMaster),
Sig(bob));
319 auto const gw =
Account(
"gateway");
320 auto const usd = gw[
"USD"];
322 env.
fund(
XRP(10000),
"alice",
"bob",
"carol", gw);
337 env.
trust(usd(100),
"alice",
"bob",
"carol");
341 env(
pay(gw,
"carol", usd(50)));
353 env(
regkey(
"alice",
"eric"));
355 env(
noop(
"alice"),
Sig(
"alice"));
356 env(
noop(
"alice"),
Sig(
"eric"));
361 env(
fset(
"alice", asfDisableMaster),
Sig(
"alice"));
366 env(
noop(
"alice"),
Sig(
"eric"));
370 env(
fclear(
"alice", asfDisableMaster));
385 auto const gw =
Account(
"gateway");
386 auto const usd = gw[
"USD"];
388 auto const alice =
Account{
"alice"};
393 auto const openTxCount = env.
current()->txCount();
394 BEAST_EXPECT(localTxCnt == 2 && queueTxCount == 0 && openTxCount == 2);
396 auto applyTxn = [&env](
auto&&... txnArgs) {
397 auto jt = env.
jt(txnArgs...);
404 args[jss::fail_hard] =
true;
409 auto jr = applyTxn(
noop(alice),
Fee(1));
411 BEAST_EXPECT(jr[jss::result][jss::engine_result] ==
"telINSUF_FEE_P");
414 BEAST_EXPECT(env.
current()->txCount() == openTxCount);
416 jr = applyTxn(
noop(alice),
Sig(
"bob"));
418 BEAST_EXPECT(jr[jss::result][jss::engine_result] ==
"tefBAD_AUTH");
421 BEAST_EXPECT(env.
current()->txCount() == openTxCount);
423 jr = applyTxn(
noop(alice),
Seq(20));
425 BEAST_EXPECT(jr[jss::result][jss::engine_result] ==
"terPRE_SEQ");
428 BEAST_EXPECT(env.
current()->txCount() == openTxCount);
430 jr = applyTxn(
offer(alice,
XRP(1000), usd(1000)));
432 BEAST_EXPECT(jr[jss::result][jss::engine_result] ==
"tecUNFUNDED_OFFER");
435 BEAST_EXPECT(env.
current()->txCount() == openTxCount);
439 BEAST_EXPECT(jr[jss::result][jss::engine_result] ==
"temBAD_FEE");
442 BEAST_EXPECT(env.
current()->txCount() == openTxCount);
444 jr = applyTxn(
noop(alice));
446 BEAST_EXPECT(jr[jss::result][jss::engine_result] ==
"tesSUCCESS");
448 BEAST_EXPECT(env.
current()->txCount() == openTxCount + 1);
460 env(
signers(
"alice", 1, {{
"bob", 1}, {
"carol", 2}}));
463 auto const baseFee = env.
current()->fees().base;
465 env(
noop(
"alice"),
Msig(
"carol"),
Fee(2 * baseFee));
466 env(
noop(
"alice"),
Msig(
"bob",
"carol"),
Fee(3 * baseFee));
468 Msig(
"bob",
"carol",
"dilbert"),
504 BEAST_EXPECT(!jt1.
get<
int>());
506 BEAST_EXPECT(jt1.
get<
int>());
507 BEAST_EXPECT(*jt1.
get<
int>() == 7);
508 BEAST_EXPECT(!jt1.
get<
UDT>());
513 BEAST_EXPECT(jt1.
get<
int>());
514 BEAST_EXPECT(*jt1.
get<
int>() == 17);
515 BEAST_EXPECT(!jt1.
get<
UDT>());
519 *jt1.
get<
int>() = 42;
520 BEAST_EXPECT(jt1.
get<
int>());
521 BEAST_EXPECT(*jt1.
get<
int>() == 42);
522 BEAST_EXPECT(!jt1.
get<
UDT>());
525 auto const& jt2 = jt1;
526 BEAST_EXPECT(jt2.get<
int>());
527 BEAST_EXPECT(*jt2.get<
int>() == 42);
528 BEAST_EXPECT(!jt2.get<
UDT>());
536 env.
fund(
XRP(100000),
"alice");
537 auto jt1 = env.
jt(
noop(
"alice"));
544 BEAST_EXPECT(*jt3.get<
std::string>() ==
"Hello, world!");
545 BEAST_EXPECT(jt3.get<
bool>());
546 BEAST_EXPECT(!*jt3.get<
bool>());
558 BEAST_EXPECT(jt1.
get<
int>());
559 BEAST_EXPECT(*jt1.
get<
int>() == 7);
560 BEAST_EXPECT(!jt1.
get<
UDT>());
562 BEAST_EXPECT(jt2.
get<
int>());
563 BEAST_EXPECT(*jt2.
get<
int>() == 7);
564 BEAST_EXPECT(!jt2.
get<
UDT>());
567 BEAST_EXPECT(jt3.
get<
int>());
568 BEAST_EXPECT(*jt3.
get<
int>() == 7);
569 BEAST_EXPECT(!jt3.
get<
UDT>());
581 BEAST_EXPECT(jt1.
get<
int>());
582 BEAST_EXPECT(*jt1.
get<
int>() == 7);
583 BEAST_EXPECT(!jt1.
get<
UDT>());
584 JTx jt2(std::move(jt1));
585 BEAST_EXPECT(!jt1.
get<
int>());
586 BEAST_EXPECT(!jt1.
get<
UDT>());
587 BEAST_EXPECT(jt2.
get<
int>());
588 BEAST_EXPECT(*jt2.
get<
int>() == 7);
589 BEAST_EXPECT(!jt2.
get<
UDT>());
590 jt1 = std::move(jt2);
591 BEAST_EXPECT(!jt2.
get<
int>());
592 BEAST_EXPECT(!jt2.
get<
UDT>());
593 BEAST_EXPECT(jt1.
get<
int>());
594 BEAST_EXPECT(*jt1.
get<
int>() == 7);
595 BEAST_EXPECT(!jt1.
get<
UDT>());
607 env(
noop(
"alice"),
Memo(
"data",
"format",
"type"));
608 env(
noop(
"alice"),
Memo(
"data1",
"format1",
"type1"),
Memo(
"data2",
"format2",
"type2"));
617 Memo(
"data",
"format",
"type")(env, jt);
619 auto const& memo = jt.
jv[
"Memos"][0u][
"Memo"];
630 auto seq = env.
current()->seq();
631 BEAST_EXPECT(seq == env.
closed()->seq() + 1);
633 BEAST_EXPECT(env.
closed()->seq() == seq);
634 BEAST_EXPECT(env.
current()->seq() == seq + 1);
636 BEAST_EXPECT(env.
closed()->seq() == seq + 1);
637 BEAST_EXPECT(env.
current()->seq() == seq + 2);
647 env.
fund(
XRP(100000),
"alice",
"bob");
649 env(
pay(
"alice",
"bob",
XRP(100)));
662 auto const usd = gw[
"USD"];
663 env.
fund(
XRP(10000),
"alice",
"bob");
666 pay(
"alice",
"bob", usd(10)),
683 auto const baseFee = env.
current()->fees().base;
690 JTx const jt = env.
jt(jsonNoOp);
701 auto const baseFee = env.
current()->fees().base;
703 auto const alice =
Account(
"alice");
711 if (BEAST_EXPECT(tx))
713 BEAST_EXPECT(tx->getAccountID(sfAccount) == alice.id());
714 BEAST_EXPECT(tx->getTxnType() == ttACCOUNT_SET);
724 if (BEAST_EXPECT(tx))
726 BEAST_EXPECT(tx->getAccountID(sfAccount) == alice.id());
727 BEAST_EXPECT(tx->getTxnType() == ttACCOUNT_SET);
734 params[jss::fee_mult_max] = 1;
735 params[jss::fee_div_max] = 2;
737 auto const expectedErrorString =
"Fee of " +
std::to_string(baseFee.drops()) +
738 " exceeds the requested tx limit of " +
std::to_string(baseFee.drops() / 2);
758 auto const n = supported.size();
759 for (
size_t i = 0; i < n; ++i)
768 if (!neverSupportedFeat)
770 log <<
"No unsupported features found - skipping test." <<
std::endl;
775 auto hasFeature = [](
Env& env,
uint256 const& f) {
784 supported, [&](
uint256 const& f) { this->BEAST_EXPECT(hasFeature(env, f)); });
792 bool const has = (f == featureDynamicMPT || f == featureTokenEscrow);
793 this->BEAST_EXPECT(has == hasFeature(env, f));
797 auto const missingSomeFeatures =
799 BEAST_EXPECT(missingSomeFeatures.count() == (supported.count() - 2));
802 Env env{*
this, missingSomeFeatures};
805 bool const hasnot = (f == featureDynamicMPT || f == featureTokenEscrow);
806 this->BEAST_EXPECT(hasnot != hasFeature(env, f));
816 *
this,
FeatureBitset{featureDynamicMPT, featureTokenEscrow, *neverSupportedFeat}};
821 BEAST_EXPECT(hasFeature(env, *neverSupportedFeat));
824 bool const has = (f == featureDynamicMPT || f == featureTokenEscrow);
825 this->BEAST_EXPECT(has == hasFeature(env, f));
838 BEAST_EXPECT(hasFeature(env, *neverSupportedFeat));
840 bool const hasnot = (f == featureDynamicMPT || f == featureTokenEscrow);
841 this->BEAST_EXPECT(hasnot != hasFeature(env, f));
854 BEAST_EXPECT(hasFeature(env, *neverSupportedFeat));
856 supported, [&](
uint256 const& f) { this->BEAST_EXPECT(hasFeature(env, f)); });
bool except(F &&f, String const &reason)
void pass()
Record a successful test condition.
void fail(String const &reason, char const *file, int line)
Record a failure.
LogOs< char > log
Logging output stream.
TestcaseT testcase
Memberspace for declaring test cases.
std::string toStyledString() const
virtual Config & config()=0
std::unordered_set< uint256, beast::Uhash<> > features
FeatureBitset & set(uint256 const &f, bool value=true)
virtual std::size_t getLocalTxCount()=0
Slice slice() const noexcept
virtual NetworkOPs & getOPs()=0
Metrics getMetrics(OpenView const &view) const
Returns fee metrics in reference fee level units.
void run() override
Runs the suite.
static void testAccount()
static std::string toString(T const &t)
void testExceptionalShutdown()
Immutable cryptographic account descriptor.
A transaction testing environment wrapper.
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.
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.
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.
std::shared_ptr< STTx const > tx() const
Return the tx data for the last JTx.
void memoize(Account const &account)
Associate AccountID with account.
void require(Args const &... args)
Check a set of requirements.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Set a multisignature on a JTx.
Match clear account flags.
Match the number of items in the account's owner directory.
Set Paths, SendMax on a JTx.
Check a set of conditions.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Sets the SendMax 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.
T is_trivially_constructible_v
@ Object
object value (collection of name/value pairs).
json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
static DisabledT const kDisabled
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.
OwnerCount< ltRIPPLE_STATE > lines
Match the number of trust lines in the account's owner directory.
json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
FeatureBitset testableAmendments()
std::array< Account, 1+sizeof...(Args)> noripple(Account const &account, Args const &... args)
Designate accounts as no-ripple in Env::fund.
AnyT const kAny
Returns an amount representing "any issuer".
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.
static AutofillT const kAutofill
json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
json::Value signers(Account const &account, std::uint32_t quorum, std::vector< Signer > const &v)
OwnerCount< ltTICKET > tickets
Match the number of tickets on the account.
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)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
T get(Section const §ion, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
std::string strHex(FwdIt begin, FwdIt end)
void foreachFeature(FeatureBitset bs, F &&f)
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
uint256 bitsetIndexToFeature(size_t i)
static constexpr auto kPortRpc
std::size_t txCount
Number of transactions in the queue.
Amount specifier with an option for any issuer.
Execution context for applying a JSON transaction.
Prop * get()
Return a property if it exists.
void set(std::unique_ptr< BasicProp > p)
Set a property If the property already exists, it is replaced.
Represents an XRP, IOU, or MPT quantity This customizes the string conversion and supports XRP conver...
Set the sequence number on a JTx.