20 #include <ripple/app/tx/impl/InvariantCheck.h>
22 #include <ripple/app/tx/impl/details/NFTokenUtils.h>
23 #include <ripple/basics/FeeUnits.h>
24 #include <ripple/basics/Log.h>
25 #include <ripple/ledger/ReadView.h>
26 #include <ripple/protocol/Feature.h>
27 #include <ripple/protocol/STArray.h>
28 #include <ripple/protocol/SystemParameters.h>
29 #include <ripple/protocol/nftPageMask.h>
53 JLOG(j.
fatal()) <<
"Invariant failed: fee paid was negative: "
62 JLOG(j.
fatal()) <<
"Invariant failed: fee paid exceeds system limit: "
71 JLOG(j.
fatal()) <<
"Invariant failed: fee paid is " << fee.
drops()
72 <<
" exceeds fee specified in transaction.";
96 switch (before->getType())
115 switch (
after->getType())
148 JLOG(j.
fatal()) <<
"Invariant failed: XRP net change was positive: "
156 JLOG(j.
fatal()) <<
"Invariant failed: XRP net change of " <<
drops_
157 <<
" doesn't match fee " << fee.
drops();
172 auto isBad = [](
STAmount const& balance) {
173 if (!balance.native())
176 auto const drops = balance.xrp();
207 JLOG(j.
fatal()) <<
"Invariant failed: incorrect account XRP balance";
224 if (pays < beast::zero)
227 if (gets < beast::zero)
231 return pays.
native() && gets.native();
234 if (before && before->getType() ==
ltOFFER)
251 JLOG(j.
fatal()) <<
"Invariant failed: offer with a bad amount";
266 auto isBad = [](
STAmount const& amount) {
267 if (!amount.native())
279 if (before && before->getType() ==
ltESCROW)
296 JLOG(j.
fatal()) <<
"Invariant failed: escrow specifies invalid amount";
329 JLOG(j.
fatal()) <<
"Invariant failed: account deletion "
330 "succeeded without deleting an account";
332 JLOG(j.
fatal()) <<
"Invariant failed: account deletion "
333 "succeeded but deleted multiple accounts!";
340 JLOG(j.
fatal()) <<
"Invariant failed: an account root was deleted";
352 if (before &&
after && before->getType() !=
after->getType())
357 switch (
after->getType())
396 JLOG(j.
fatal()) <<
"Invariant failed: ledger entry type mismatch";
401 JLOG(j.
fatal()) <<
"Invariant failed: invalid ledger entry type added";
437 JLOG(j.
fatal()) <<
"Invariant failed: an XRP trust line was created";
469 JLOG(j.
fatal()) <<
"Invariant failed: multiple accounts "
470 "created in a single transaction";
482 JLOG(j.
fatal()) <<
"Invariant failed: account created with "
483 "wrong starting sequence number";
489 JLOG(j.
fatal()) <<
"Invariant failed: account root created "
490 "by a non-Payment or by an unsuccessful transaction";
503 static constexpr
uint256 const accountBits = ~pageBits;
506 uint256 const account = sle->key() & accountBits;
507 uint256 const hiLimit = sle->key() & pageBits;
515 if (account != (*prev & accountBits))
518 if (hiLimit <= (*prev & pageBits))
524 if (account != (*next & accountBits))
527 if (hiLimit >= (*next & pageBits))
532 auto const& nftokens = sle->getFieldArray(
sfNFTokens);
535 if (
std::size_t const nftokenCount = nftokens.size();
536 (!isDelete && nftokenCount == 0) ||
543 prev ? *prev & pageBits :
uint256(beast::zero);
547 for (
auto const& obj : nftokens)
556 if (
uint256 const tokenPageBits = tokenID & pageBits;
557 tokenPageBits < loLimit || tokenPageBits >= hiLimit)
560 if (
auto uri = obj[~
sfURI]; uri && uri->empty())
583 JLOG(j.
fatal()) <<
"Invariant failed: NFT page is improperly linked.";
589 JLOG(j.
fatal()) <<
"Invariant failed: NFT found in incorrect page.";
595 JLOG(j.
fatal()) <<
"Invariant failed: NFTs on page are not sorted.";
601 JLOG(j.
fatal()) <<
"Invariant failed: NFT contains empty URI.";
607 JLOG(j.
fatal()) <<
"Invariant failed: NFT page has invalid size.";
647 JLOG(j.
fatal()) <<
"Invariant failed: the number of minted tokens "
648 "changed without a mint transaction!";
654 JLOG(j.
fatal()) <<
"Invariant failed: the number of burned tokens "
655 "changed without a burn transaction!";
667 <<
"Invariant failed: successful minting didn't increase "
668 "the number of minted tokens.";
674 JLOG(j.
fatal()) <<
"Invariant failed: failed minting changed the "
675 "number of minted tokens.";
682 <<
"Invariant failed: minting changed the number of "
695 <<
"Invariant failed: successful burning didn't increase "
696 "the number of burned tokens.";
703 JLOG(j.
fatal()) <<
"Invariant failed: failed burning changed the "
704 "number of burned tokens.";
711 <<
"Invariant failed: burning changed the number of "
TxType getTxnType() const
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
@ ttACCOUNT_DELETE
This transaction type deletes an existing account.
@ ltTICKET
A ledger object which describes a ticket.
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
const SF_UINT256 sfNFTokenID
@ ltLEDGER_HASHES
A ledger object that contains a list of ledger hashes.
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
constexpr value_type drops() const
Returns the number of drops.
const SF_UINT32 sfSequence
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
@ ltSIGNER_LIST
A ledger object which contains a signer list for an account.
const SF_UINT32 sfMintedNFTokens
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
constexpr std::size_t dirMaxTokensPerPage
The maximum number of items in an NFT page.
TxType
Transaction type identifiers.
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
std::uint32_t beforeMintedTotal
@ ltCHECK
A ledger object which describes a check.
@ ltFEE_SETTINGS
The ledger object which lists the network's fee settings.
std::uint32_t afterMintedTotal
bool compareTokens(uint256 const &a, uint256 const &b)
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
std::uint32_t accountSeq_
@ ltDIR_NODE
A ledger object which contains a list of object identifiers.
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
constexpr uint256 pageMask(std::string_view("0000000000000000000000000000000000000000ffffffffffffffffffffffff"))
const uint256 featureDeletableAccounts
@ ttPAYMENT
This transaction type executes a payment.
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
const SF_AMOUNT sfTakerPays
@ ltAMENDMENTS
The ledger object which lists details about amendments on the network.
const SF_AMOUNT sfLowLimit
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
@ ltOFFER
A ledger object which describes an offer on the DEX.
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
std::uint32_t afterBurnedTotal
@ ltESCROW
A ledger object describing a single escrow.
@ ltNFTOKEN_OFFER
A ledger object which identifies an offer to buy or sell an NFT.
@ ttNFTOKEN_MINT
This transaction mints a new NFT.
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
@ ltDEPOSIT_PREAUTH
A ledger object which describes a deposit preauthorization.
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
const SF_AMOUNT sfTakerGets
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
A generic endpoint for log messages.
const SF_AMOUNT sfHighLimit
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
std::uint32_t beforeBurnedTotal
bool native() const noexcept
@ ltNFTOKEN_PAGE
A ledger object which contains a list of NFTs.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
@ ltNEGATIVE_UNL
The ledger object which tracks the current negative UNL state.
LedgerIndex seq() const
Returns the sequence number of the base ledger.
std::uint32_t accountsCreated_
virtual Rules const & rules() const =0
Returns the tx processing rules.
@ ltACCOUNT_ROOT
A ledger object which describes an account.
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
const SF_AMOUNT sfBalance
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
const SF_UINT256 sfNextPageMin
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
const SF_UINT256 sfPreviousPageMin
@ ttNFTOKEN_BURN
This transaction burns (i.e.
static bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
std::uint32_t accountsDeleted_
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
@ ltRIPPLE_STATE
A ledger object which describes a bidirectional trust line.
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
const SF_UINT32 sfBurnedNFTokens
STAmount const & getFieldAmount(SField const &field) const
@ ltPAYCHAN
A ledger object describing a single unidirectional XRP payment channel.