2#include <test/jtx/Account.h>
3#include <test/jtx/Env.h>
4#include <test/jtx/TestHelpers.h>
5#include <test/jtx/amount.h>
6#include <test/jtx/credentials.h>
7#include <test/jtx/directory.h>
8#include <test/jtx/multisign.h>
9#include <test/jtx/noop.h>
10#include <test/jtx/offer.h>
11#include <test/jtx/owners.h>
12#include <test/jtx/pay.h>
13#include <test/jtx/tags.h>
14#include <test/jtx/ter.h>
15#include <test/jtx/trust.h>
17#include <xrpl/basics/base_uint.h>
18#include <xrpl/basics/random.h>
19#include <xrpl/beast/unit_test/suite.h>
20#include <xrpl/core/ServiceRegistry.h>
21#include <xrpl/json/json_value.h>
22#include <xrpl/json/to_string.h>
23#include <xrpl/ledger/ApplyView.h>
24#include <xrpl/ledger/BookDirs.h>
25#include <xrpl/ledger/Sandbox.h>
26#include <xrpl/ledger/helpers/DirectoryHelpers.h>
27#include <xrpl/protocol/Book.h>
28#include <xrpl/protocol/Feature.h>
29#include <xrpl/protocol/Indexes.h>
30#include <xrpl/protocol/Issue.h>
31#include <xrpl/protocol/LedgerFormats.h>
32#include <xrpl/protocol/Protocol.h>
33#include <xrpl/protocol/SField.h>
34#include <xrpl/protocol/TER.h>
35#include <xrpl/protocol/jss.h>
56 BEAST_EXPECT(i < 17577);
60 for (
int j = 0; j != 3; ++j)
82 p->setFieldU64(sfIndexNext, 0);
86 p->setFieldU64(sfIndexNext, i + 1);
91 p->setFieldU64(sfIndexPrevious, n - 1);
95 p->setFieldU64(sfIndexPrevious, i - 1);
108 auto usd = gw[
"USD"];
112 testcase(
"Directory Ordering (with 'SortedDirectories' amendment)");
115 env.
fund(
XRP(10000000), alice, gw);
126 auto const view = env.
closed();
135 auto const& v = p->getFieldV256(sfIndexes);
143 for (
auto const& e : v)
147 BEAST_EXPECT(c->getFieldU32(sfSequence) >= minSeq);
148 BEAST_EXPECT(c->getFieldU32(sfSequence) < maxSeq);
151 page = p->getFieldU64(sfIndexNext);
160 for (
auto const&
offer : book)
163 BEAST_EXPECT(
offer->getFieldAmount(sfTakerPays) == usd(count));
164 BEAST_EXPECT(
offer->getFieldAmount(sfTakerGets) ==
XRP(count));
174 auto const alice =
Account(
"alice");
175 auto const bob =
Account(
"bob");
176 auto const charlie =
Account(
"charlie");
181 env.
fund(
XRP(1000000), alice, charlie, gw);
188 env(
signers(alice, 1, {{bob, 1}}));
210 auto cl = currencies;
212 for (
auto const& c : cl)
214 env(
trust(alice, c(50)));
222 for (
auto const& c : cl)
224 env(
trust(alice, c(0)));
234 auto cl = currencies;
238 for (
auto const& c : currencies)
240 env(
trust(charlie, c(50)));
242 env(
pay(gw, charlie, c(50)));
255 for (
auto const& c : cl)
257 env(
offer(charlie,
XRP(50), c(50)));
266 for (
auto const& c : cl)
268 env(
pay(alice, charlie, c(50)));
279 testcase(
"RIPD-1353 Empty Offer Directories");
284 auto const gw =
Account{
"gateway"};
285 auto const alice =
Account{
"alice"};
286 auto const usd = gw[
"USD"];
288 env.
fund(
XRP(10000), alice, gw);
290 env.
trust(usd(1000), alice);
291 env(
pay(gw, alice, usd(1000)));
293 auto const firstOfferSeq = env.
seq(alice);
296 for (
int i = 0; i < 3; ++i)
304 for (
auto page : {0, 2, 1})
327 env.
trust(usd(0), alice);
328 env(
pay(alice, gw, alice[
"USD"](1000)));
342 auto const gw =
Account{
"gateway"};
343 auto const alice =
Account{
"alice"};
344 auto const usd = gw[
"USD"];
349 constexpr uint256 kBase(
"fb71c9aa3310141da4b01d6c744a98286af2d72ab5448d5adc0910ca0c910880");
351 constexpr uint256 kItem(
"bad0f021aa3b2f6754a8fe82a5779730aa0bbbab82f17201ef24900efc2c7312");
365 p->setFieldV256(sfIndexes, v);
389 p1->setFieldV256(sfIndexes, v1);
397 p2->setFieldV256(sfIndexes, v2);
410 BEAST_EXPECT(p1->getFieldU64(sfIndexNext) == 0);
411 BEAST_EXPECT(p1->getFieldU64(sfIndexPrevious) == 0);
415 BEAST_EXPECT(p0->getFieldU64(sfIndexNext) == 1);
416 BEAST_EXPECT(p0->getFieldU64(sfIndexPrevious) == 1);
426 auto const gw =
Account{
"gateway"};
427 auto const alice =
Account{
"alice"};
428 auto const usd = gw[
"USD"];
430 auto ledgerData = [
this](
Env& env) {
432 params[jss::type] = jss::directory;
433 params[jss::ledger_index] =
"validated";
434 auto const result = env.rpc(
"json",
"ledger_data",
to_string(params))[jss::result];
435 BEAST_EXPECT(!result.isMember(jss::marker));
441 env.
fund(
XRP(10000), alice, gw);
443 env.
trust(usd(1000), alice);
444 env(
pay(gw, alice, usd(1000)));
448 auto const jrr = ledgerData(env);
449 auto const& jstate = jrr[jss::state];
453 BEAST_EXPECT(
directory[
"LedgerEntryType"] == jss::DirectoryNode);
456 BEAST_EXPECT(!
directory.isMember(
"PreviousTxnID"));
457 BEAST_EXPECT(!
directory.isMember(
"PreviousTxnLgrSeq"));
468 auto const txID =
to_string(env.
tx()->getTransactionID());
469 auto const ledgerSeq = env.
current()->header().seq;
476 auto const jrr = ledgerData(env);
477 auto const& jstate = jrr[jss::state];
481 BEAST_EXPECT(
directory[
"LedgerEntryType"] == jss::DirectoryNode);
486 BEAST_EXPECT(!
directory.isMember(
"PreviousTxnID"));
487 BEAST_EXPECT(!
directory.isMember(
"PreviousTxnLgrSeq"));
496 directory[
"PreviousTxnID"].asString() == txID);
498 directory.isMember(
"PreviousTxnLgrSeq") &&
499 directory[
"PreviousTxnLgrSeq"].asUInt() == ledgerSeq);
511 auto const testCase = [&,
this](
FeatureBitset features,
auto setup) {
514 Env env(*
this, features);
518 auto const [lastPage, full] = setup(env);
521 for (
int i = 0; i < 63; ++i)
534 auto sle = view.peek({ltCREDENTIAL, key});
535 if (!BEAST_EXPECT(sle))
538 BEAST_EXPECT(page == lastPage);
539 sle->setFieldU64(sfIssuerNode, page);
554 for (
int i = 0; i < 64; ++i)
562 BEAST_EXPECT(sle ==
nullptr);
571 testcase(
"directory full without fixDirectoryLimit");
577 testcase(
"directory not full with fixDirectoryLimit");
582 [
this](Env&) -> std::tuple<std::uint64_t, bool> {
583 testcase(
"directory full with fixDirectoryLimit");
TestcaseT testcase
Memberspace for declaring test cases.
Writeable view to a ledger, for applying a transaction.
bool dirRemove(Keylet const &directory, std::uint64_t page, uint256 const &key, bool keepRoot)
Remove an entry from a directory.
virtual void update(SLE::ref sle)=0
Indicate changes to a peeked SLE.
void pushBack(uint256 const &v)
Discardable, editable view to a ledger.
void insert(SLE::ref sle) override
Insert a new state SLE.
std::optional< key_type > succ(key_type const &key, std::optional< key_type > const &last=std::nullopt) const override
Return the key of the next state item.
SLE::pointer peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
void update(SLE::ref sle) override
Indicate changes to a peeked SLE.
Immutable cryptographic account descriptor.
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.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
void enableFeature(uint256 const feature)
std::uint32_t seq(Account const &account) const
Returns the next sequence number on 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.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
json::Value deleteCred(jtx::Account const &acc, jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
json::Value create(jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
auto bumpLastPage(Env &env, std::uint64_t newLastPage, Keylet directory, std::function< bool(ApplyView &, uint256, std::uint64_t)> adjust) -> std::expected< void, Error >
Move the position of the last page in the user's directory on open ledger to newLastPage.
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
json::Value offerCancel(Account const &account, std::uint32_t offerSeq)
Cancel an offer.
XrpT const XRP
Converts to XRP Issue or STAmount.
json::Value noop(Account const &account)
The null transaction.
FeatureBitset testableAmendments()
json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
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)
bool checkArraySize(json::Value const &val, unsigned int size)
BEAST_DEFINE_TESTSUITE_PRIO(AccountDelete, app, xrpl, 2)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
bool dirIsEmpty(ReadView const &view, Keylet const &k)
Returns true if the directory is empty.
constexpr std::size_t kDirNodeMaxEntries
The maximum number of entries per directory page.
BaseUInt< 256, detail::DirectoryTag > Directory
Directory is an index into the directory of offer books.
constexpr std::uint64_t kDirNodeMaxPages
The maximum number of pages allowed in a directory.
std::string to_string(BaseUInt< Bits, Tag > const &a)
uint256 getQualityNext(uint256 const &uBase)
uint256 getBookBase(Book const &book)
beast::xor_shift_engine & defaultPrng()
Return the default random engine.
void testDirectoryOrdering()
void run() override
Runs the suite.
std::string currcode(std::size_t i)
static void makePages(Sandbox &sb, uint256 const &base, std::uint64_t n)