20#include <xrpld/app/misc/AMMHelpers.h>
21#include <xrpld/app/misc/AMMUtils.h>
22#include <xrpld/app/tx/detail/InvariantCheck.h>
23#include <xrpld/app/tx/detail/NFTokenUtils.h>
24#include <xrpld/app/tx/detail/PermissionedDomainSet.h>
26#include <xrpl/basics/Log.h>
27#include <xrpl/ledger/CredentialHelpers.h>
28#include <xrpl/ledger/ReadView.h>
29#include <xrpl/ledger/View.h>
30#include <xrpl/protocol/Feature.h>
31#include <xrpl/protocol/STArray.h>
32#include <xrpl/protocol/STNumber.h>
33#include <xrpl/protocol/SystemParameters.h>
34#include <xrpl/protocol/TxFormats.h>
35#include <xrpl/protocol/Units.h>
36#include <xrpl/protocol/nftPageMask.h>
85 return safe_cast<Privilege>(
90#pragma push_macro("TRANSACTION")
93#define TRANSACTION(tag, value, name, delegatable, amendment, privileges, ...) \
95 return (privileges) & priv; \
103#include <xrpl/protocol/detail/transactions.macro>
111#pragma pop_macro("TRANSACTION")
133 JLOG(j.
fatal()) <<
"Invariant failed: fee paid was negative: "
142 JLOG(j.
fatal()) <<
"Invariant failed: fee paid exceeds system limit: "
151 JLOG(j.
fatal()) <<
"Invariant failed: fee paid is " << fee.
drops()
152 <<
" exceeds fee specified in transaction.";
176 switch (before->getType())
179 drops_ -= (*before)[sfBalance].xrp().drops();
183 ((*before)[sfAmount] - (*before)[sfBalance]).xrp().drops();
186 if (
isXRP((*before)[sfAmount]))
187 drops_ -= (*before)[sfAmount].xrp().drops();
196 switch (
after->getType())
199 drops_ += (*after)[sfBalance].xrp().drops();
203 drops_ += ((*after)[sfAmount] - (*after)[sfBalance])
209 drops_ += (*after)[sfAmount].xrp().drops();
229 JLOG(j.
fatal()) <<
"Invariant failed: XRP net change was positive: "
237 JLOG(j.
fatal()) <<
"Invariant failed: XRP net change of " <<
drops_
238 <<
" doesn't match fee " << fee.
drops();
253 auto isBad = [](
STAmount const& balance) {
254 if (!balance.native())
257 auto const drops = balance.xrp();
271 if (before && before->getType() == ltACCOUNT_ROOT)
272 bad_ |= isBad((*before)[sfBalance]);
274 if (
after &&
after->getType() == ltACCOUNT_ROOT)
288 JLOG(j.
fatal()) <<
"Invariant failed: incorrect account XRP balance";
305 if (pays < beast::zero)
308 if (gets < beast::zero)
312 return pays.
native() && gets.native();
315 if (before && before->getType() == ltOFFER)
316 bad_ |= isBad((*before)[sfTakerPays], (*before)[sfTakerGets]);
319 bad_ |= isBad((*
after)[sfTakerPays], (*after)[sfTakerGets]);
332 JLOG(j.
fatal()) <<
"Invariant failed: offer with a bad amount";
347 auto isBad = [](
STAmount const& amount) {
360 if (amount.holds<
Issue>())
362 if (amount <= beast::zero)
372 if (amount <= beast::zero)
382 if (before && before->getType() == ltESCROW)
383 bad_ |= isBad((*before)[sfAmount]);
393 if (
after &&
after->getType() == ltMPTOKEN_ISSUANCE)
395 auto const outstanding = (*after)[sfOutstandingAmount];
396 checkAmount(outstanding);
397 if (
auto const locked = (*
after)[~sfLockedAmount])
399 checkAmount(*locked);
400 bad_ = outstanding < *locked;
406 auto const mptAmount = (*after)[sfMPTAmount];
407 checkAmount(mptAmount);
408 if (
auto const locked = (*
after)[~sfLockedAmount])
410 checkAmount(*locked);
425 JLOG(j.
fatal()) <<
"Invariant failed: escrow specifies invalid amount";
440 if (isDelete && before && before->getType() == ltACCOUNT_ROOT)
462 JLOG(j.
fatal()) <<
"Invariant failed: account deletion "
463 "succeeded without deleting an account";
465 JLOG(j.
fatal()) <<
"Invariant failed: account deletion "
466 "succeeded but deleted multiple accounts!";
480 JLOG(j.
fatal()) <<
"Invariant failed: an account root was deleted";
492 if (isDelete && before && before->getType() == ltACCOUNT_ROOT)
508 [[maybe_unused]]
bool const enforce =
512 auto const objectExists = [&view, enforce, &j](
auto const& keylet) {
514 if (
auto const sle = view.
read(keylet))
517 auto const typeName = [&sle]() {
522 return item->getName();
527 <<
"Invariant failed: account deletion left behind a "
528 << typeName <<
" object";
533 "ripple::AccountRootsDeletedClean::finalize::objectExists : "
534 "account deletion left no objects behind");
542 auto const accountID = accountSLE->getAccountID(sfAccount);
546 if (objectExists(
std::invoke(keyletfunc, accountID)) && enforce)
561 if (key && objectExists(
Keylet{ltNFTOKEN_PAGE, *key}) && enforce)
569 if (accountSLE->isFieldPresent(*field))
571 auto const key = accountSLE->getFieldH256(*field);
589 if (before &&
after && before->getType() !=
after->getType())
594#pragma push_macro("LEDGER_ENTRY")
597#define LEDGER_ENTRY(tag, ...) case tag:
599 switch (
after->getType())
601#include <xrpl/protocol/detail/ledger_entries.macro>
610#pragma pop_macro("LEDGER_ENTRY")
627 JLOG(j.
fatal()) <<
"Invariant failed: ledger entry type mismatch";
632 JLOG(j.
fatal()) <<
"Invariant failed: invalid ledger entry type added";
646 if (
after &&
after->getType() == ltRIPPLE_STATE)
668 JLOG(j.
fatal()) <<
"Invariant failed: an XRP trust line was created";
680 if (
after &&
after->getType() == ltRIPPLE_STATE)
690 (lowDeepFreeze && !lowFreeze) || (highDeepFreeze && !highFreeze);
705 JLOG(j.
fatal()) <<
"Invariant failed: a trust line with deep freeze flag "
706 "without normal freeze was created";
734 if (balanceChange.signum() == 0)
766 [[maybe_unused]]
bool const enforce =
771 auto const issuerSle =
findIssuer(issue.account, view);
780 "ripple::TransfersNotFrozen::finalize : enforce "
805 after,
"ripple::TransfersNotFrozen::isValidEntry : valid after.");
811 if (
after->getType() == ltACCOUNT_ROOT)
823 return after->getType() == ltRIPPLE_STATE &&
824 (!before || before->getType() == ltRIPPLE_STATE);
833 auto const getBalance = [](
auto const& line,
auto const& other,
bool zero) {
835 line ? line->at(sfBalance) : other->at(sfBalance).zeroed();
836 return zero ? amt.
zeroed() : amt;
844 auto const balanceBefore = getBalance(before,
after,
false);
851 auto const balanceAfter = getBalance(
after, before, isDelete);
853 return balanceAfter - balanceBefore;
861 "ripple::TransfersNotFrozen::recordBalance : valid trustline "
865 changes.senders.emplace_back(std::move(change));
867 changes.receivers.emplace_back(std::move(change));
875 auto const balanceChangeSign = balanceChange.
signum();
876 auto const currency =
after->at(sfBalance).getCurrency();
880 {currency,
after->at(sfHighLimit).getIssuer()},
881 {
after, balanceChangeSign});
885 {currency,
after->at(sfLowLimit).getIssuer()},
886 {
after, -balanceChangeSign});
928 for (
auto const& change : actors)
930 bool const high = change.line->at(sfLowLimit).getIssuer() ==
931 issuer->at(sfAccount);
934 change, high, tx, j, enforce, globalFreeze))
954 bool const deepFreeze =
956 bool const frozen = globalFreeze || deepFreeze || freeze;
968 JLOG(j.
debug()) <<
"Invariant check allowing funds to be moved "
970 <<
" a frozen trustline for AMMClawback "
975 JLOG(j.
fatal()) <<
"Invariant failed: Attempting to move frozen funds for "
980 "ripple::TransfersNotFrozen::validateFrozenState : enforce "
999 if (!before &&
after->getType() == ltACCOUNT_ROOT)
1021 JLOG(j.
fatal()) <<
"Invariant failed: multiple accounts "
1022 "created in a single transaction";
1029 bool const pseudoAccount =
1034 JLOG(j.
fatal()) <<
"Invariant failed: pseudo-account created by a "
1035 "wrong transaction type";
1048 JLOG(j.
fatal()) <<
"Invariant failed: account created with "
1049 "wrong starting sequence number";
1060 <<
"Invariant failed: pseudo-account created with "
1069 JLOG(j.
fatal()) <<
"Invariant failed: account root created illegally";
1082 static constexpr uint256 const accountBits = ~pageBits;
1084 if ((before && before->getType() != ltNFTOKEN_PAGE) ||
1085 (
after &&
after->getType() != ltNFTOKEN_PAGE))
1089 uint256 const account = sle->key() & accountBits;
1090 uint256 const hiLimit = sle->key() & pageBits;
1098 if (account != (*prev & accountBits))
1101 if (hiLimit <= (*prev & pageBits))
1105 if (
auto const next = (*sle)[~sfNextPageMin])
1107 if (account != (*next & accountBits))
1110 if (hiLimit >= (*next & pageBits))
1115 auto const& nftokens = sle->getFieldArray(sfNFTokens);
1118 if (
std::size_t const nftokenCount = nftokens.size();
1119 (!isDelete && nftokenCount == 0) ||
1126 prev ? *prev & pageBits :
uint256(beast::zero);
1130 for (
auto const& obj : nftokens)
1132 uint256 const tokenID = obj[sfNFTokenID];
1139 if (
uint256 const tokenPageBits = tokenID & pageBits;
1140 tokenPageBits < loLimit || tokenPageBits >= hiLimit)
1143 if (
auto uri = obj[~sfURI]; uri && uri->empty())
1157 before->isFieldPresent(sfPreviousPageMin))
1166 if (!isDelete && before &&
after)
1174 before->isFieldPresent(sfNextPageMin) &&
1175 !
after->isFieldPresent(sfNextPageMin))
1192 JLOG(j.
fatal()) <<
"Invariant failed: NFT page is improperly linked.";
1198 JLOG(j.
fatal()) <<
"Invariant failed: NFT found in incorrect page.";
1204 JLOG(j.
fatal()) <<
"Invariant failed: NFTs on page are not sorted.";
1210 JLOG(j.
fatal()) <<
"Invariant failed: NFT contains empty URI.";
1216 JLOG(j.
fatal()) <<
"Invariant failed: NFT page has invalid size.";
1224 JLOG(j.
fatal()) <<
"Invariant failed: Last NFT page deleted with "
1225 "non-empty directory.";
1230 JLOG(j.
fatal()) <<
"Invariant failed: Lost NextMinPage link.";
1245 if (before && before->getType() == ltACCOUNT_ROOT)
1251 if (
after &&
after->getType() == ltACCOUNT_ROOT)
1270 JLOG(j.
fatal()) <<
"Invariant failed: the number of minted tokens "
1271 "changed without a mint transaction!";
1277 JLOG(j.
fatal()) <<
"Invariant failed: the number of burned tokens "
1278 "changed without a burn transaction!";
1290 <<
"Invariant failed: successful minting didn't increase "
1291 "the number of minted tokens.";
1297 JLOG(j.
fatal()) <<
"Invariant failed: failed minting changed the "
1298 "number of minted tokens.";
1305 <<
"Invariant failed: minting changed the number of "
1318 <<
"Invariant failed: successful burning didn't increase "
1319 "the number of burned tokens.";
1326 JLOG(j.
fatal()) <<
"Invariant failed: failed burning changed the "
1327 "number of burned tokens.";
1334 <<
"Invariant failed: burning changed the number of "
1351 if (before && before->getType() == ltRIPPLE_STATE)
1354 if (before && before->getType() == ltMPTOKEN)
1374 <<
"Invariant failed: more than one trustline changed.";
1381 <<
"Invariant failed: more than one mptokens changed.";
1393 if (holderBalance.
signum() < 0)
1396 <<
"Invariant failed: trustline balance is negative";
1405 JLOG(j.
fatal()) <<
"Invariant failed: some trustlines were changed "
1406 "despite failure of the transaction.";
1412 JLOG(j.
fatal()) <<
"Invariant failed: some mptokens were changed "
1413 "despite failure of the transaction.";
1429 if (
after &&
after->getType() == ltMPTOKEN_ISSUANCE)
1460 JLOG(j.
fatal()) <<
"Invariant failed: transaction "
1461 "succeeded without creating a MPT issuance";
1465 JLOG(j.
fatal()) <<
"Invariant failed: transaction "
1466 "succeeded while removing MPT issuances";
1470 JLOG(j.
fatal()) <<
"Invariant failed: transaction "
1471 "succeeded but created multiple issuances";
1481 JLOG(j.
fatal()) <<
"Invariant failed: MPT issuance deletion "
1482 "succeeded without removing a MPT issuance";
1486 JLOG(j.
fatal()) <<
"Invariant failed: MPT issuance deletion "
1487 "succeeded while creating MPT issuances";
1491 JLOG(j.
fatal()) <<
"Invariant failed: MPT issuance deletion "
1492 "succeeded but deleted multiple issuances";
1501 bool const enforceEscrowFinish = (tx.
getTxnType() == ttESCROW_FINISH) &&
1508 enforceEscrowFinish)
1514 JLOG(j.
fatal()) <<
"Invariant failed: MPT authorize "
1515 "succeeded but created MPT issuances";
1520 JLOG(j.
fatal()) <<
"Invariant failed: MPT authorize "
1521 "succeeded but deleted issuances";
1525 submittedByIssuer &&
1529 <<
"Invariant failed: MPT authorize submitted by issuer "
1530 "succeeded but created/deleted mptokens";
1540 <<
"Invariant failed: MPT authorize submitted by holder "
1541 "succeeded but created/deleted bad number of mptokens";
1553 !enforceEscrowFinish,
1554 "ripple::ValidMPTIssuance::finalize",
1555 "not escrow finish tx");
1567 JLOG(j.
fatal()) <<
"Invariant failed: a MPT issuance was created";
1571 JLOG(j.
fatal()) <<
"Invariant failed: a MPT issuance was deleted";
1575 JLOG(j.
fatal()) <<
"Invariant failed: a MPToken was created";
1579 JLOG(j.
fatal()) <<
"Invariant failed: a MPToken was deleted";
1594 if (before && before->getType() != ltPERMISSIONED_DOMAIN)
1596 if (
after &&
after->getType() != ltPERMISSIONED_DOMAIN)
1601 auto const& credentials = sle->getFieldArray(sfAcceptedCredentials);
1612 for (
auto const& cred : sorted)
1614 auto const& credTx = credentials[i++];
1615 sleStatus.
isSorted_ = (cred.first == credTx[sfIssuer]) &&
1616 (cred.second == credTx[sfCredentialType]);
1650 JLOG(j.
fatal()) <<
"Invariant failed: permissioned domain with "
1658 JLOG(j.
fatal()) <<
"Invariant failed: permissioned domain bad "
1667 <<
"Invariant failed: permissioned domain credentials "
1675 <<
"Invariant failed: permissioned domain credentials "
1699 if (
after &&
after->getType() == ltACCOUNT_ROOT)
1701 bool const isPseudo = [&]() {
1708 if (
after->at(sfSequence) == 0)
1729 return after->isFieldPresent(*sf);
1734 error <<
"pseudo-account has " << numFields
1735 <<
" pseudo-account fields set";
1739 if (before && before->at(sfSequence) !=
after->at(sfSequence))
1748 if (
after->isFieldPresent(sfRegularKey))
1764 bool const enforce = view.
rules().
enabled(featureSingleAssetVault);
1769 "ripple::ValidPseudoAccounts::finalize : no bad "
1770 "changes or enforce invariant");
1773 for (
auto const& error :
errors_)
1775 JLOG(j.
fatal()) <<
"Invariant failed: " << error;
1793 if (
after->isFieldPresent(sfDomainID))
1799 if (
after->isFieldPresent(sfDomainID))
1807 (!
after->isFieldPresent(sfDomainID) ||
1808 !
after->isFieldPresent(sfAdditionalBooks) ||
1809 after->getFieldArray(sfAdditionalBooks).size() > 1))
1823 if ((txType != ttPAYMENT && txType != ttOFFER_CREATE) ||
1831 JLOG(j.
fatal()) <<
"Invariant failed: hybrid offer is malformed";
1842 JLOG(j.
fatal()) <<
"Invariant failed: domain doesn't exist";
1852 JLOG(j.
fatal()) <<
"Invariant failed: transaction"
1853 " consumed wrong domains";
1860 JLOG(j.
fatal()) <<
"Invariant failed: domain transaction"
1861 " affected regular offers";
1879 auto const type =
after->getType();
1889 (type == ltACCOUNT_ROOT &&
after->isFieldPresent(sfAMMID)))
1898 if (before->getType() == ltAMM)
1912 bool const positive = amount > beast::zero && amount2 > beast::zero &&
1913 lptAMMBalance > beast::zero;
1916 (amount == beast::zero && amount2 == beast::zero &&
1917 lptAMMBalance == beast::zero);
1928 JLOG(j.
error()) <<
"AMMVote invariant failed: "
1947 JLOG(j.
error()) <<
"AMMBid invariant failed: pool changed";
1980 <<
"AMMCreate invariant failed: AMM object is not created";
1990 tx[sfAmount].get<Issue>(),
1991 tx[sfAmount2].get<Issue>(),
2002 JLOG(j.
error()) <<
"AMMCreate invariant failed: " << amount <<
" "
2019 ?
"AMM object is not deleted on tesSUCCESS"
2020 :
"AMM object is changed on tecINCOMPLETE";
2021 JLOG(j.
error()) <<
"AMMDelete invariant failed: " << msg;
2036 JLOG(j.
error()) <<
"AMM swap invariant failed: AMM object changed";
2055 tx[sfAsset].get<Issue>(),
2056 tx[sfAsset2].get<Issue>(),
2063 auto const poolProductMean =
root2(amount * amount2);
2064 bool const nonNegativeBalances =
2068 auto weakInvariantCheck = [&]() {
2073 if (!nonNegativeBalances ||
2074 (!strongInvariantCheck && !weakInvariantCheck()))
2079 <<
" " << poolProductMean <<
" "
2101 JLOG(j.
error()) <<
"AMMDeposit invariant failed: AMM object is deleted";
2153 case ttAMM_CLAWBACK:
2154 case ttAMM_WITHDRAW:
2163 case ttOFFER_CREATE:
A generic endpoint for log messages.
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 &)
std::vector< std::shared_ptr< SLE const > > accountsDeleted_
std::uint32_t accountsDeleted_
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 &)
A currency issued by an account.
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 &)
std::uint32_t afterMintedTotal
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
std::uint32_t afterBurnedTotal
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
std::uint32_t beforeBurnedTotal
std::uint32_t beforeMintedTotal
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 &)
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
bool deepFreezeWithoutFreeze_
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 &)
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 &)
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
virtual std::optional< key_type > succ(key_type const &key, std::optional< key_type > const &last=std::nullopt) const =0
Return the key of the next state item.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
LedgerIndex seq() const
Returns the sequence number of the base ledger.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Currency const & getCurrency() const
int signum() const noexcept
AccountID const & getIssuer() const
bool native() const noexcept
STAmount zeroed() const
Returns a zero value with the same issuer and currency.
AccountID getAccountID(SField const &field) const
STAmount const & getFieldAmount(SField const &field) const
uint256 getHash(HashPrefix prefix) const
bool isFieldPresent(SField const &field) const
uint256 getFieldH256(SField const &field) const
TxType getTxnType() const
uint256 getTransactionID() 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 &)
std::map< AccountID, std::shared_ptr< SLE const > const > possibleIssuers_
bool isValidEntry(std::shared_ptr< SLE const > const &before, std::shared_ptr< SLE const > const &after)
void recordBalance(Issue const &issue, BalanceChange change)
std::shared_ptr< SLE const > findIssuer(AccountID const &issuerID, ReadView const &view)
bool validateIssuerChanges(std::shared_ptr< SLE const > const &issuer, IssuerChanges const &changes, STTx const &tx, beast::Journal const &j, bool enforce)
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
STAmount calculateBalanceChange(std::shared_ptr< SLE const > const &before, std::shared_ptr< SLE const > const &after, bool isDelete)
void recordBalanceChanges(std::shared_ptr< SLE const > const &after, STAmount const &balanceChange)
bool validateFrozenState(BalanceChange const &change, bool high, STTx const &tx, beast::Journal const &j, bool enforce, bool globalFreeze)
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 &)
bool finalizeWithdraw(STTx const &, ReadView const &, bool enforce, beast::Journal const &) const
bool finalizeDEX(bool enforce, beast::Journal const &) const
std::optional< STAmount > lptAMMBalanceAfter_
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
bool finalizeBid(bool enforce, beast::Journal const &) const
std::optional< AccountID > ammAccount_
bool finalizeDelete(bool enforce, TER res, beast::Journal const &) const
bool finalizeCreate(STTx const &, ReadView const &, bool enforce, beast::Journal const &) const
bool finalizeVote(bool enforce, beast::Journal const &) const
bool finalizeDeposit(STTx const &, ReadView const &, bool enforce, beast::Journal const &) const
bool generalInvariant(STTx const &, ReadView const &, ZeroAllowed zeroAllowed, beast::Journal const &) const
std::optional< STAmount > lptAMMBalanceBefore_
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
std::uint32_t trustlinesChanged
std::uint32_t mptokensChanged
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
std::uint32_t mptIssuancesCreated_
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
std::uint32_t mptokensCreated_
std::uint32_t mptIssuancesDeleted_
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
std::uint32_t mptokensDeleted_
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 &)
std::uint32_t accountsCreated_
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
std::uint32_t accountSeq_
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 &)
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
hash_set< uint256 > domains_
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
std::optional< SleStatus > sleStatus_[2]
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::vector< std::string > errors_
void visitEntry(bool, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
constexpr value_type drops() const
Returns the number of drops.
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
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 &)
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
T emplace_back(T... args)
std::set< std::pair< AccountID, Slice > > makeSorted(STArray const &credentials)
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Keylet nftpage_min(AccountID const &owner)
NFT page keylets.
Keylet nftpage_max(AccountID const &owner)
A keylet for the owner's last possible NFT page.
bool compareTokens(uint256 const &a, uint256 const &b)
uint256 constexpr pageMask(std::string_view("0000000000000000000000000000000000000000ffffffffffffffffffffffff"))
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
bool isXRP(AccountID const &c)
constexpr base_uint< Bits, Tag > operator|(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
static bool validBalances(STAmount const &amount, STAmount const &amount2, STAmount const &lptAMMBalance, ValidAMM::ZeroAllowed zeroAllowed)
std::size_t constexpr maxPermissionedDomainCredentialsArraySize
The maximum number of credentials can be passed in array for permissioned domain.
bool hasPrivilege(STTx const &tx, Privilege priv)
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safe_cast(Src s) noexcept
std::uint64_t constexpr maxMPTokenAmount
The maximum amount of MPTokenIssuance.
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
std::size_t constexpr dirMaxTokensPerPage
The maximum number of items in an NFT page.
std::array< keyletDesc< AccountID const & >, 6 > const directAccountKeylets
std::pair< STAmount, STAmount > ammPoolHolds(ReadView const &view, AccountID const &ammAccountID, Issue const &issue1, Issue const &issue2, FreezeHandling freezeHandling, beast::Journal const j)
Get AMM pool balances.
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
STAmount ammLPTokens(STAmount const &asset1, STAmount const &asset2, Issue const &lptIssue)
Calculate LP Tokens given AMM pool reserves.
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
@ transactionID
transaction plus signature to give transaction ID
std::vector< SField const * > const & getPseudoAccountFields()
bool withinRelativeDistance(Quality const &calcQuality, Quality const &reqQuality, Number const &dist)
Check if the relative distance between the qualities is within the requested distance.
bool isPseudoAccount(std::shared_ptr< SLE const > sleAcct)
A pair of SHAMap key and LedgerEntryType.
int const balanceChangeSign
std::shared_ptr< SLE const > const line
std::vector< BalanceChange > receivers
std::vector< BalanceChange > senders
std::size_t credentialsSize_