3#include <xrpld/app/misc/NetworkOPs.h>
4#include <xrpld/app/misc/TxQ.h>
6#include <xrpl/beast/hash/uhash.h>
7#include <xrpl/beast/unit_test.h>
8#include <xrpl/protocol/Feature.h>
9#include <xrpl/protocol/TxFlags.h>
10#include <xrpl/protocol/jss.h>
12#include <boost/lexical_cast.hpp>
27 return boost::lexical_cast<std::string>(t);
47 auto const USD = gw[
"USD"];
72 fail(
"missing exception");
82 fail(
"missing exception");
103 BEAST_EXPECT(
XRP(1) ==
drops(1000000));
108 auto const USD = gw[
"USD"];
109 BEAST_EXPECT(
to_string(USD(0)) ==
"0/USD(gw)");
110 BEAST_EXPECT(
to_string(USD(10)) ==
"10/USD(gw)");
111 BEAST_EXPECT(
to_string(USD(-10)) ==
"-10/USD(gw)");
112 BEAST_EXPECT(USD(0) ==
STAmount(USD, 0));
113 BEAST_EXPECT(USD(1) ==
STAmount(USD, 1));
114 BEAST_EXPECT(USD(-1) ==
STAmount(USD, -1));
117 BEAST_EXPECT(!
get(USD(10)).is_any);
118 BEAST_EXPECT(
get(
any(USD(10))).is_any);
126 auto const n =
XRP(10000);
128 auto const USD = gw[
"USD"];
129 auto const alice =
Account(
"alice");
142 env.
fund(n,
"alice");
143 env.
fund(n,
"bob",
"carol");
153 env.
fund(n,
"zachary");
160 env.
fund(n,
"alice",
"bob", gw);
168 BEAST_EXPECT(env.
balance(alice) == 0);
169 BEAST_EXPECT(env.
balance(alice, USD) != 0);
170 BEAST_EXPECT(env.
balance(alice, USD) == USD(0));
171 env.
fund(n, alice, gw);
173 BEAST_EXPECT(env.
balance(alice) == n);
174 BEAST_EXPECT(env.
balance(gw) == n);
175 env.
trust(USD(1000), alice);
176 env(
pay(gw, alice, USD(10)));
185 BEAST_EXPECT(env.
seq(
"alice") == 3);
186 BEAST_EXPECT(env.
seq(gw) == 3);
192 env.
fund(n,
"alice");
212 auto const USD = gw[
"USD"];
215 env.
fund(
XRP(10000),
"alice", gw);
218 env.
trust(USD(100),
"alice");
238 env.fund(
XRP(10000), alice, bob);
270 auto const gw =
Account(
"gateway");
271 auto const USD = gw[
"USD"];
273 env.
fund(
XRP(10000),
"alice",
"bob",
"carol", gw);
288 env.
trust(USD(100),
"alice",
"bob",
"carol");
292 env(
pay(gw,
"carol", USD(50)));
304 env(
regkey(
"alice",
"eric"));
306 env(
noop(
"alice"),
sig(
"alice"));
307 env(
noop(
"alice"),
sig(
"eric"));
317 env(
noop(
"alice"),
sig(
"eric"));
336 auto const gw =
Account(
"gateway");
337 auto const USD = gw[
"USD"];
339 auto const alice =
Account{
"alice"};
344 auto const openTxCount = env.
current()->txCount();
345 BEAST_EXPECT(localTxCnt == 2 && queueTxCount == 0 && openTxCount == 2);
347 auto applyTxn = [&env](
auto&&... txnArgs) {
348 auto jt = env.
jt(txnArgs...);
355 args[jss::fail_hard] =
true;
357 return env.
rpc(
"json",
"submit", args.toStyledString());
360 auto jr = applyTxn(
noop(alice),
fee(1));
362 BEAST_EXPECT(jr[jss::result][jss::engine_result] ==
"telINSUF_FEE_P");
365 BEAST_EXPECT(env.
current()->txCount() == openTxCount);
367 jr = applyTxn(
noop(alice),
sig(
"bob"));
369 BEAST_EXPECT(jr[jss::result][jss::engine_result] ==
"tefBAD_AUTH");
372 BEAST_EXPECT(env.
current()->txCount() == openTxCount);
374 jr = applyTxn(
noop(alice),
seq(20));
376 BEAST_EXPECT(jr[jss::result][jss::engine_result] ==
"terPRE_SEQ");
379 BEAST_EXPECT(env.
current()->txCount() == openTxCount);
381 jr = applyTxn(
offer(alice,
XRP(1000), USD(1000)));
383 BEAST_EXPECT(jr[jss::result][jss::engine_result] ==
"tecUNFUNDED_OFFER");
386 BEAST_EXPECT(env.
current()->txCount() == openTxCount);
390 BEAST_EXPECT(jr[jss::result][jss::engine_result] ==
"temBAD_FEE");
393 BEAST_EXPECT(env.
current()->txCount() == openTxCount);
395 jr = applyTxn(
noop(alice));
397 BEAST_EXPECT(jr[jss::result][jss::engine_result] ==
"tesSUCCESS");
399 BEAST_EXPECT(env.
current()->txCount() == openTxCount + 1);
411 env(
signers(
"alice", 1, {{
"bob", 1}, {
"carol", 2}}));
414 auto const baseFee = env.
current()->fees().base;
416 env(
noop(
"alice"),
msig(
"carol"),
fee(2 * baseFee));
417 env(
noop(
"alice"),
msig(
"bob",
"carol"),
fee(3 * baseFee));
452 BEAST_EXPECT(!jt1.
get<
int>());
454 BEAST_EXPECT(jt1.
get<
int>());
455 BEAST_EXPECT(*jt1.
get<
int>() == 7);
456 BEAST_EXPECT(!jt1.
get<
UDT>());
461 BEAST_EXPECT(jt1.
get<
int>());
462 BEAST_EXPECT(*jt1.
get<
int>() == 17);
463 BEAST_EXPECT(!jt1.
get<
UDT>());
467 *jt1.
get<
int>() = 42;
468 BEAST_EXPECT(jt1.
get<
int>());
469 BEAST_EXPECT(*jt1.
get<
int>() == 42);
470 BEAST_EXPECT(!jt1.
get<
UDT>());
473 auto const& jt2 = jt1;
474 BEAST_EXPECT(jt2.get<
int>());
475 BEAST_EXPECT(*jt2.get<
int>() == 42);
476 BEAST_EXPECT(!jt2.get<
UDT>());
484 env.
fund(
XRP(100000),
"alice");
485 auto jt1 = env.
jt(
noop(
"alice"));
492 BEAST_EXPECT(*jt3.get<
std::string>() ==
"Hello, world!");
493 BEAST_EXPECT(jt3.get<
bool>());
494 BEAST_EXPECT(!*jt3.get<
bool>());
506 BEAST_EXPECT(jt1.
get<
int>());
507 BEAST_EXPECT(*jt1.
get<
int>() == 7);
508 BEAST_EXPECT(!jt1.
get<
UDT>());
510 BEAST_EXPECT(jt2.
get<
int>());
511 BEAST_EXPECT(*jt2.
get<
int>() == 7);
512 BEAST_EXPECT(!jt2.
get<
UDT>());
515 BEAST_EXPECT(jt3.
get<
int>());
516 BEAST_EXPECT(*jt3.
get<
int>() == 7);
517 BEAST_EXPECT(!jt3.
get<
UDT>());
529 BEAST_EXPECT(jt1.
get<
int>());
530 BEAST_EXPECT(*jt1.
get<
int>() == 7);
531 BEAST_EXPECT(!jt1.
get<
UDT>());
532 JTx jt2(std::move(jt1));
533 BEAST_EXPECT(!jt1.
get<
int>());
534 BEAST_EXPECT(!jt1.
get<
UDT>());
535 BEAST_EXPECT(jt2.
get<
int>());
536 BEAST_EXPECT(*jt2.
get<
int>() == 7);
537 BEAST_EXPECT(!jt2.
get<
UDT>());
538 jt1 = std::move(jt2);
539 BEAST_EXPECT(!jt2.
get<
int>());
540 BEAST_EXPECT(!jt2.
get<
UDT>());
541 BEAST_EXPECT(jt1.
get<
int>());
542 BEAST_EXPECT(*jt1.
get<
int>() == 7);
543 BEAST_EXPECT(!jt1.
get<
UDT>());
555 env(
noop(
"alice"),
memo(
"data",
"format",
"type"));
556 env(
noop(
"alice"),
memo(
"data1",
"format1",
"type1"),
memo(
"data2",
"format2",
"type2"));
565 memo(
"data",
"format",
"type")(env, jt);
567 auto const&
memo = jt.
jv[
"Memos"][0u][
"Memo"];
579 BEAST_EXPECT(
seq == env.
closed()->seq() + 1);
581 BEAST_EXPECT(env.
closed()->seq() ==
seq);
582 BEAST_EXPECT(env.
current()->seq() ==
seq + 1);
584 BEAST_EXPECT(env.
closed()->seq() ==
seq + 1);
585 BEAST_EXPECT(env.
current()->seq() ==
seq + 2);
595 env.
fund(
XRP(100000),
"alice",
"bob");
597 env(
pay(
"alice",
"bob",
XRP(100)));
610 auto const USD = gw[
"USD"];
611 env.
fund(
XRP(10000),
"alice",
"bob");
614 pay(
"alice",
"bob", USD(10)),
631 auto const baseFee = env.
current()->fees().base;
637 JTx jt = env.
jt(jsonNoop);
648 auto const baseFee = env.
current()->fees().base;
650 auto const alice =
Account(
"alice");
658 if (BEAST_EXPECT(tx))
660 BEAST_EXPECT(tx->getAccountID(sfAccount) == alice.id());
661 BEAST_EXPECT(tx->getTxnType() == ttACCOUNT_SET);
671 if (BEAST_EXPECT(tx))
673 BEAST_EXPECT(tx->getAccountID(sfAccount) == alice.id());
674 BEAST_EXPECT(tx->getTxnType() == ttACCOUNT_SET);
681 params[jss::fee_mult_max] = 1;
682 params[jss::fee_div_max] = 2;
684 auto const expectedErrorString =
"Fee of " +
std::to_string(baseFee.drops()) +
685 " exceeds the requested tx limit of " +
std::to_string(baseFee.drops() / 2);
705 auto const n = supported.size();
706 for (
size_t i = 0; i < n; ++i)
713 if (!neverSupportedFeat)
715 log <<
"No unsupported features found - skipping test." <<
std::endl;
720 auto hasFeature = [](
Env& env,
uint256 const& f) {
736 bool const has = (f == featureDynamicMPT || f == featureTokenEscrow);
737 this->BEAST_EXPECT(has == hasFeature(env, f));
741 auto const missingSomeFeatures =
testable_amendments() - featureDynamicMPT - featureTokenEscrow;
742 BEAST_EXPECT(missingSomeFeatures.count() == (supported.count() - 2));
745 Env env{*
this, missingSomeFeatures};
748 bool hasnot = (f == featureDynamicMPT || f == featureTokenEscrow);
749 this->BEAST_EXPECT(hasnot != hasFeature(env, f));
758 Env env{*
this,
FeatureBitset{featureDynamicMPT, featureTokenEscrow, *neverSupportedFeat}};
763 BEAST_EXPECT(hasFeature(env, *neverSupportedFeat));
766 bool has = (f == featureDynamicMPT || f == featureTokenEscrow);
767 this->BEAST_EXPECT(has == hasFeature(env, f));
780 BEAST_EXPECT(hasFeature(env, *neverSupportedFeat));
782 bool hasnot = (f == featureDynamicMPT || f == featureTokenEscrow);
783 this->BEAST_EXPECT(hasnot != hasFeature(env, f));
796 BEAST_EXPECT(hasFeature(env, *neverSupportedFeat));
808 (*cfg).deprecatedClearSection(
"port_rpc");
log_os< char > log
Logging output stream.
void pass()
Record a successful test condition.
testcase_t testcase
Memberspace for declaring test cases.
bool except(F &&f, String const &reason)
void fail(String const &reason, char const *file, int line)
Record a failure.
virtual Config & config()=0
virtual NetworkOPs & getOPs()=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
Metrics getMetrics(OpenView const &view) const
Returns fee metrics in reference fee level units.
static std::string to_string(T const &t)
void run() override
Runs the suite.
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.
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.
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.
Json::Value json(JsonValue &&jv, FN const &... fN)
Create JSON from parameters.
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
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.
@ objectValue
object value (collection of name/value pairs).
Json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
any_t const any
Returns an amount representing "any issuer".
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 rate(Account const &account, double multiplier)
Set a transfer rate.
XRP_t const XRP
Converts to XRP Issue or STAmount.
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
static autofill_t const autofill
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
FeatureBitset testable_amendments()
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Json::Value regkey(Account const &account, disabled_t)
Disable the regular key.
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
owner_count< ltTICKET > tickets
Match the number of tickets on the account.
owner_count< ltRIPPLE_STATE > lines
Match the number of trust lines in the account's owner directory.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
static disabled_t const disabled
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr std::uint32_t asfRequireDest
constexpr std::uint32_t asfDisableMaster
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)
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
void foreachFeature(FeatureBitset bs, F &&f)
constexpr std::uint32_t asfDefaultRipple
uint256 bitsetIndexToFeature(size_t i)
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< basic_prop > p)
Set a property If the property already exists, it is replaced.
Represents an XRP or IOU quantity This customizes the string conversion and supports XRP conversions ...
Set the sequence number on a JTx.