1#include <xrpl/tx/invariants/NFTInvariant.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/beast/utility/instrumentation.h>
5#include <xrpl/protocol/Indexes.h>
6#include <xrpl/protocol/TxFormats.h>
7#include <xrpl/protocol/nftPageMask.h>
8#include <xrpl/tx/invariants/InvariantCheckPrivilege.h>
9#include <xrpl/tx/transactors/nft/NFTokenUtils.h>
20 static constexpr uint256 const accountBits = ~pageBits;
22 if ((before && before->getType() != ltNFTOKEN_PAGE) ||
27 uint256 const account = sle->key() & accountBits;
28 uint256 const hiLimit = sle->key() & pageBits;
36 if (account != (*prev & accountBits))
39 if (hiLimit <= (*prev & pageBits))
43 if (
auto const next = (*sle)[~sfNextPageMin])
45 if (account != (*next & accountBits))
48 if (hiLimit >= (*next & pageBits))
53 auto const& nftokens = sle->getFieldArray(sfNFTokens);
56 if (
std::size_t const nftokenCount = nftokens.size();
62 uint256 const loLimit = prev ? *prev & pageBits :
uint256(beast::zero);
66 for (
auto const& obj : nftokens)
68 uint256 const tokenID = obj[sfNFTokenID];
75 if (
uint256 const tokenPageBits = tokenID & pageBits;
76 tokenPageBits < loLimit || tokenPageBits >= hiLimit)
79 if (
auto uri = obj[~sfURI]; uri && uri->empty())
93 before->isFieldPresent(sfPreviousPageMin))
102 if (!isDelete && before &&
after)
110 before->isFieldPresent(sfNextPageMin) && !
after->isFieldPresent(sfNextPageMin))
127 JLOG(j.
fatal()) <<
"Invariant failed: NFT page is improperly linked.";
133 JLOG(j.
fatal()) <<
"Invariant failed: NFT found in incorrect page.";
139 JLOG(j.
fatal()) <<
"Invariant failed: NFTs on page are not sorted.";
145 JLOG(j.
fatal()) <<
"Invariant failed: NFT contains empty URI.";
151 JLOG(j.
fatal()) <<
"Invariant failed: NFT page has invalid size.";
159 JLOG(j.
fatal()) <<
"Invariant failed: Last NFT page deleted with "
160 "non-empty directory.";
165 JLOG(j.
fatal()) <<
"Invariant failed: Lost NextMinPage link.";
180 if (before && before->getType() == ltACCOUNT_ROOT)
186 if (
after &&
after->getType() == ltACCOUNT_ROOT)
205 JLOG(j.
fatal()) <<
"Invariant failed: the number of minted tokens "
206 "changed without a mint transaction!";
212 JLOG(j.
fatal()) <<
"Invariant failed: the number of burned tokens "
213 "changed without a burn transaction!";
224 JLOG(j.
fatal()) <<
"Invariant failed: successful minting didn't increase "
225 "the number of minted tokens.";
231 JLOG(j.
fatal()) <<
"Invariant failed: failed minting changed the "
232 "number of minted tokens.";
238 JLOG(j.
fatal()) <<
"Invariant failed: minting changed the number of "
250 JLOG(j.
fatal()) <<
"Invariant failed: successful burning didn't increase "
251 "the number of burned tokens.";
258 JLOG(j.
fatal()) <<
"Invariant failed: failed burning changed the "
259 "number of burned tokens.";
265 JLOG(j.
fatal()) <<
"Invariant failed: burning changed the number of "
A generic endpoint for log messages.
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
std::uint32_t beforeMintedTotal
std::uint32_t afterBurnedTotal
std::uint32_t afterMintedTotal
std::uint32_t beforeBurnedTotal
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &) const
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
TxType getTxnType() const
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &) const
uint256 constexpr pageMask(std::string_view("0000000000000000000000000000000000000000ffffffffffffffffffffffff"))
bool compareTokens(uint256 const &a, uint256 const &b)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::size_t constexpr dirMaxTokensPerPage
The maximum number of items in an NFT page.
bool hasPrivilege(STTx const &tx, Privilege priv)
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
bool isTesSuccess(TER x) noexcept