1#include <xrpl/tx/Transactor.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/Slice.h>
5#include <xrpl/basics/base_uint.h>
6#include <xrpl/basics/contract.h>
7#include <xrpl/beast/utility/Zero.h>
8#include <xrpl/beast/utility/instrumentation.h>
9#include <xrpl/core/NetworkIDService.h>
10#include <xrpl/core/ServiceRegistry.h>
11#include <xrpl/json/to_string.h>
12#include <xrpl/ledger/ApplyView.h>
13#include <xrpl/ledger/ReadView.h>
14#include <xrpl/ledger/helpers/AccountRootHelpers.h>
15#include <xrpl/ledger/helpers/CredentialHelpers.h>
16#include <xrpl/ledger/helpers/DelegateHelpers.h>
17#include <xrpl/ledger/helpers/NFTokenHelpers.h>
18#include <xrpl/ledger/helpers/OfferHelpers.h>
19#include <xrpl/ledger/helpers/RippleStateHelpers.h>
20#include <xrpl/ledger/helpers/SponsorHelpers.h>
21#include <xrpl/protocol/AccountID.h>
22#include <xrpl/protocol/Feature.h>
23#include <xrpl/protocol/Indexes.h>
24#include <xrpl/protocol/LedgerFormats.h>
25#include <xrpl/protocol/Permissions.h>
26#include <xrpl/protocol/Protocol.h>
27#include <xrpl/protocol/PublicKey.h>
28#include <xrpl/protocol/Rules.h>
29#include <xrpl/protocol/SField.h>
30#include <xrpl/protocol/STAmount.h>
31#include <xrpl/protocol/STLedgerEntry.h>
32#include <xrpl/protocol/STTx.h>
33#include <xrpl/protocol/Serializer.h>
34#include <xrpl/protocol/SystemParameters.h>
35#include <xrpl/protocol/TER.h>
36#include <xrpl/protocol/TxFlags.h>
37#include <xrpl/protocol/TxMeta.h>
38#include <xrpl/protocol/XRPAmount.h>
39#include <xrpl/server/LoadFeeTrack.h>
40#include <xrpl/tx/ApplyContext.h>
41#include <xrpl/tx/SignerEntries.h>
42#include <xrpl/tx/apply.h>
43#include <xrpl/tx/applySteps.h>
67 JLOG(ctx.
j.
warn()) <<
"Pseudo transactions cannot contain the "
68 "tfInnerBatchTxn flag.";
74 uint32_t
const nodeNID = ctx.
registry.get().getNetworkIDService().getNetworkID();
91 if (*txNID != nodeNID)
100 JLOG(ctx.
j.
warn()) <<
"applyTransaction: transaction id may not be zero";
107 <<
": invalid flags.";
124 if (
auto const spk = sigObject.
getFieldVL(sfSigningPubKey);
127 JLOG(j.
debug()) <<
"preflightCheckSigningKey: invalid signing key";
139 if (signature && !signature->empty())
152 for (
auto const& signer : sigObject.
getFieldArray(sfSigners))
154 if (signer.isFieldPresent(sfTxnSignature) && !signer[sfTxnSignature].empty())
162 Slice const signingPubKey = sigObject[sfSigningPubKey];
163 if (!signingPubKey.
empty())
182 if ((hasSponsor || hasSponsorFlags || hasSponsorSig) && !ctx.
rules.
enabled(featureSponsor))
185 if (hasSponsor != hasSponsorFlags)
187 JLOG(ctx.
j.
debug()) <<
"preflight1: sponsor and sponsor flags mismatch";
190 if (hasSponsorSig && (!hasSponsor || !hasSponsorFlags))
192 JLOG(ctx.
j.
debug()) <<
"preflight1: sponsor signature without sponsor definition";
198 auto const sponsorFlags = ctx.
tx.
getFieldU32(sfSponsorFlags);
201 JLOG(ctx.
j.
debug()) <<
"preflight1: invalid sponsor flags";
212 <<
"preflight1: spfSponsorReserve not allowed for this transaction type";
220 JLOG(ctx.
j.
debug()) <<
"preflight1: Sponsor account cannot be the same as the account";
235 if (!ctx.
rules.
enabled(featurePermissionDelegationV1_1))
238 if (ctx.
tx[sfDelegate] == ctx.
tx[sfAccount])
248 !perm.hasGranularPermissions(txType))
252 if (
auto const ret =
preflight0(ctx, flagMask))
258 JLOG(ctx.
j.
warn()) <<
"preflight1: bad account id";
264 if (!fee.native() || fee.negative() || !
isLegalAmount(fee.xrp()))
266 JLOG(ctx.
j.
debug()) <<
"preflight1: invalid fee";
330 JLOG(ctx.
j.
debug()) <<
"preflight2: bad signature. " << sigValid.second;
365 return !slice->empty() && slice->length() <= maxLength;
386 auto const delegate = tx[~sfDelegate];
401 if (heldGranularPermissions.
empty())
432 auto const sponsorshipSle =
439 if (
isFeeSponsored(tx) && sponsorshipSle->isFlag(lsfSponsorshipRequireSignForFee))
442 if (
isReserveSponsored(tx) && sponsorshipSle->isFlag(lsfSponsorshipRequireSignForReserve))
468 if (sponsorObj.isFieldPresent(sfSigners))
469 sponsorSignerCount += sponsorObj.getFieldArray(sfSigners).size();
472 return baseFee + ((signerCount + sponsorSignerCount) * baseFee);
499 view.fees().increment >
view.fees().base * 100,
500 "xrpl::Transactor::calculateOwnerReserveFee : Owner reserve is "
502 return view.fees().increment;
518 if (!ctx.
tx[sfFee].native())
521 auto const feePaid = ctx.
tx[sfFee].xrp();
528 JLOG(ctx.
j.
trace()) <<
"Batch: Fee must be zero.";
540 if (feePaid < feeDue)
542 JLOG(ctx.
j.
trace()) <<
"Insufficient fee paid: " <<
to_string(feePaid) <<
"/"
552 auto const payerSle = ctx.
view.
read(feePayer.keylet);
569 if (payerSle->getType() != ltSPONSORSHIP)
572 if (payerSle->isFieldPresent(feePayer.balanceField))
573 maxSpendable = payerSle->getFieldAmount(feePayer.balanceField).xrp();
575 if (payerSle->isFieldPresent(sfMaxFee))
577 auto const cap = payerSle->getFieldAmount(sfMaxFee).xrp();
578 maxSpendable =
std::min(maxSpendable, cap);
583 if (payerSle->getType() != ltACCOUNT_ROOT)
589 maxSpendable = payerSle->getFieldAmount(sfBalance).xrp() - sponsorReserve;
593 maxSpendable = payerSle->getFieldAmount(feePayer.balanceField).xrp();
604 if (maxSpendable < feePaid)
606 JLOG(ctx.
j.
trace()) <<
"Insufficient balance:" <<
" balance=" <<
to_string(maxSpendable)
624 auto const feePaid =
ctx_.tx[sfFee].xrp();
627 auto const sle =
view().
peek(feePayer.keylet);
629 JLOG(
j_.trace()) <<
"Fee payer: " +
to_string(feePayer.id);
638 if (sle->isFieldPresent(feePayer.balanceField))
640 balance = sle->getFieldAmount(feePayer.balanceField).xrp();
642 else if (feePayer.balanceField != sfFeeAmount)
656 spendable = balance > sponsorReserve ? balance - sponsorReserve :
beast::kZero;
660 auto const cap = sle->getFieldAmount(sfMaxFee).xrp();
661 spendable =
std::min(spendable, cap);
669 if (feePaid > spendable &&
679 auto const feeAmountAfter = balance - feePaid;
681 if (feeAmountAfter ==
beast::kZero && feePayer.balanceField == sfFeeAmount)
684 sle->makeFieldAbsent(feePayer.balanceField);
688 sle->setFieldAmount(feePayer.balanceField, feeAmountAfter);
706 JLOG(j.
trace()) <<
"applyTransaction: delay: source account does not exist "
714 if (tSeqProx.
isSeq())
718 JLOG(j.
trace()) <<
"applyTransaction: has both a TicketSequence "
719 "and a non-zero Sequence number";
722 if (tSeqProx != aSeq)
726 JLOG(j.
trace()) <<
"applyTransaction: has future sequence number "
727 <<
"a_seq=" << aSeq <<
" t_seq=" << tSeqProx;
731 JLOG(j.
trace()) <<
"applyTransaction: has past sequence number "
732 <<
"a_seq=" << aSeq <<
" t_seq=" << tSeqProx;
745 JLOG(j.
trace()) <<
"applyTransaction: has future ticket id "
746 <<
"a_seq=" << aSeq <<
" t_seq=" << tSeqProx;
753 JLOG(j.
trace()) <<
"applyTransaction: ticket already used or never created "
754 <<
"a_seq=" << aSeq <<
" t_seq=" << tSeqProx;
771 JLOG(ctx.
j.
trace()) <<
"applyTransaction: delay: source account does not exist "
777 (sle->getFieldH256(sfAccountTxnID) != ctx.
tx.
getFieldH256(sfAccountTxnID)))
793 XRPL_ASSERT(sleAccount,
"xrpl::Transactor::consumeSeqProxy : non-null account");
795 if (seqProxy.
isSeq())
800 sleAccount->setFieldU32(sfSequence, seqProxy.
value() + 1);
821 JLOG(j.
fatal()) <<
"Ticket disappeared from ledger.";
830 JLOG(j.
fatal()) <<
"Unable to delete Ticket from owner.";
841 JLOG(j.
fatal()) <<
"Could not find Ticket owner account root.";
846 if (
auto ticketCount = (*sleAccount)[~sfTicketCount])
848 if (*ticketCount == 1)
850 sleAccount->makeFieldAbsent(sfTicketCount);
854 ticketCount = *ticketCount - 1;
860 JLOG(j.
fatal()) <<
"TicketCount field missing from account root.";
869 view.erase(sleTicket);
893 "xrpl::Transactor::apply : non-null SLE or zero account");
907 if (sle->isFieldPresent(sfAccountTxnID))
908 sle->setFieldH256(sfAccountTxnID,
ctx_.tx.getTransactionID());
924 bool permitUncreatedAccount)
929 if ((
view.rules().enabled(featureLendingProtocol) ||
930 view.rules().enabled(featureBatchV1_1) ||
view.rules().enabled(fixCleanup3_3_0)) &&
940 auto const pkSigner = sigObject.
getFieldVL(sfSigningPubKey);
942 if (parentBatchId &&
view.rules().enabled(featureBatchV1_1))
945 if (sigObject.
isFieldPresent(sfTxnSignature) || !pkSigner.empty() ||
968 auto const sponsorID = sigObject.
getAccountID(sfSponsor);
969 auto const sponsorSignature = sigObject.
getFieldObject(sfSponsorSignature);
970 if (
auto const ret =
checkSign(
view, flags, std::nullopt, sponsorID, sponsorSignature, j);
983 XRPL_ASSERT(!pkSigner.empty(),
"xrpl::Transactor::checkSign : non-empty signer");
987 JLOG(j.
trace()) <<
"checkSign: signing public key type is unknown";
999 if (!permitUncreatedAccount)
1001 if (idAccount != idSigner)
1025 bool const isMasterDisabled = sleAccount->isFlag(lsfDisableMaster);
1028 if ((*sleAccount)[~sfRegularKey] == idSigner)
1034 if (!isMasterDisabled && idAccount == idSigner)
1040 if (isMasterDisabled && idAccount == idSigner)
1060 if (!sleAccountSigners)
1062 JLOG(j.
trace()) <<
"applyTransaction: Invalid: Not a multi-signing account.";
1069 sleAccountSigners->isFieldPresent(sfSignerListID),
1070 "xrpl::Transactor::checkMultiSign : has signer list ID");
1072 sleAccountSigners->getFieldU32(sfSignerListID) == 0,
1073 "xrpl::Transactor::checkMultiSign : signer list ID is 0");
1076 if (!accountSigners)
1077 return accountSigners.error();
1089 auto iter = accountSigners->begin();
1090 for (
auto const& txSigner : txSigners)
1092 AccountID const txSignerAcctID = txSigner.getAccountID(sfAccount);
1095 while (iter->account < txSignerAcctID)
1097 if (++iter == accountSigners->end())
1099 JLOG(j.
trace()) <<
"applyTransaction: Invalid SigningAccount.Account.";
1103 if (iter->account != txSignerAcctID)
1106 JLOG(j.
trace()) <<
"applyTransaction: Invalid SigningAccount.Account.";
1113 auto const spk = txSigner.getFieldVL(sfSigningPubKey);
1119 JLOG(j.
trace()) <<
"checkMultiSign: signing public key type is unknown";
1125 "xrpl::Transactor::checkMultiSign : non-empty signer or "
1127 AccountID const signingAcctIDFromPubKey =
1157 if (signingAcctIDFromPubKey == txSignerAcctID)
1160 if (sleTxSignerRoot)
1163 std::uint32_t const signerAccountFlags = sleTxSignerRoot->getFieldU32(sfFlags);
1165 if ((signerAccountFlags & lsfDisableMaster) != 0u)
1167 JLOG(j.
trace()) <<
"applyTransaction: Signer:Account lsfDisableMaster.";
1176 if (!sleTxSignerRoot)
1178 JLOG(j.
trace()) <<
"applyTransaction: Non-phantom signer "
1179 "lacks account root.";
1183 if (!sleTxSignerRoot->isFieldPresent(sfRegularKey))
1185 JLOG(j.
trace()) <<
"applyTransaction: Account lacks RegularKey.";
1188 if (signingAcctIDFromPubKey != sleTxSignerRoot->getAccountID(sfRegularKey))
1190 JLOG(j.
trace()) <<
"applyTransaction: Account doesn't match RegularKey.";
1195 weightSum += iter->weight;
1199 if (weightSum < sleAccountSigners->getFieldU32(sfSignerQuorum))
1201 JLOG(j.
trace()) <<
"applyTransaction: Signers failed to meet quorum.";
1216 for (
auto const& index : offers)
1236 for (
auto const& index : offers)
1250 for (
auto const& index : creds)
1257 <<
"removeExpiredCredentials: failed to delete expired credential. Err: "
1272 JLOG(viewJ.
error()) <<
"removeDeletedTrustLines: deleted trustlines exceed max "
1273 << trustLines.
size();
1277 for (
auto const& index : trustLines)
1279 if (
auto const sleState = view.
peek({ltRIPPLE_STATE, index});
1282 JLOG(viewJ.
error()) <<
"removeDeletedTrustLines: failed to delete AMM trustline";
1306 auto const payerSle =
view().
peek(feePayer.keylet);
1312 if (payerSle->isFieldPresent(feePayer.balanceField))
1314 balance = payerSle->getFieldAmount(feePayer.balanceField).xrp();
1316 else if (feePayer.balanceField != sfFeeAmount)
1323 auto const cap = payerSle->getFieldAmount(sfMaxFee).xrp();
1335 spendable = balance > sponsorReserve ? balance - sponsorReserve :
beast::kZero;
1341 "xrpl::Transactor::reset : valid balance");
1346 if (fee > spendable)
1355 auto const feeAmountAfter = balance - fee;
1356 if (feeAmountAfter ==
beast::kZero && feePayer.balanceField == sfFeeAmount)
1359 payerSle->makeFieldAbsent(feePayer.balanceField);
1363 payerSle->setFieldAmount(feePayer.balanceField, feeAmountAfter);
1367 XRPL_ASSERT(
isTesSuccess(ter),
"xrpl::Transactor::reset : result is tesSUCCESS");
1372 if (payerSle != txnAcct)
1389 if (
view.exists(sponsorshipKeylet))
1394 .keylet = sponsorshipKeylet,
1395 .balanceField = sfFeeAmount,
1402 "xrpl::getFeePayer has sponsor signature without a sponsorship object");
1408 .balanceField = sfBalance,
1414 auto const payerType =
1418 .id = payerID, .keylet = payerAccountKeylet, .balanceField = sfBalance, .type = payerType};
1426 JLOG(
j_.debug()) <<
"Transaction trapped: " << txHash;
1432 JLOG(
j_.trace()) <<
"reapplying because of " <<
transToken(result);
1439 auto typesForResult = [](
TER const ter) {
1447 types.
insert(ltRIPPLE_STATE);
1451 types.
insert(ltNFTOKEN_OFFER);
1452 types.
insert(ltCREDENTIAL);
1460 auto const typesToCollect = typesForResult(result);
1463 if (!typesToCollect.empty())
1466 [&typesToCollect, &deletedObjects](
1472 "xrpl::Transactor::processPersistentChanges : non-null "
1474 if (before &&
after)
1476 auto const type = before->getType();
1477 if (typesToCollect.contains(type))
1481 if (type == ltOFFER &&
1482 before->getFieldAmount(sfTakerPays) !=
1483 after->getFieldAmount(sfTakerPays))
1486 deletedObjects[type].push_back(index);
1495 auto const resetResult =
reset(fee);
1497 result = resetResult.first;
1499 fee = resetResult.second;
1504 auto const typesToApply = typesForResult(result);
1505 if (
isTecClaim(result) && !typesToApply.empty())
1507 auto const viewJ =
ctx_.registry.get().getJournal(
"View");
1508 for (
auto const& [type, ids] : deletedObjects)
1510 if (ids.empty() || !typesToApply.contains(type))
1518 case ltNFTOKEN_OFFER:
1521 case ltRIPPLE_STATE:
1530 "xrpl::Transactor::processPersistentChanges() : "
1555 JLOG(
ctx_.journal.fatal()) <<
1556 "Transaction has failed one or more transaction invariants, tx: " <<
1563 JLOG(
ctx_.journal.fatal()) <<
1564 "Exception while checking transaction invariants: " <<
1588 return ctx_.checkInvariants(result, fee);
1595 JLOG(
j_.trace()) <<
"apply: " <<
ctx_.tx.getTransactionID();
1614 JLOG(
j_.fatal()) <<
"Transaction serdes mismatch";
1617 UNREACHABLE(
"xrpl::Transactor::operator() : transaction serdes mismatch");
1623 if (
auto const& trap =
ctx_.registry.get().getTrapTxID();
1624 trap && *trap ==
ctx_.tx.getTransactionID())
1629 auto result =
ctx_.preclaimResult;
1635 XRPL_ASSERT(result !=
temUNKNOWN,
"xrpl::Transactor::operator() : result is not temUNKNOWN");
1637 if (
auto stream =
j_.trace())
1638 stream <<
"preclaim result: " <<
transToken(result);
1641 auto fee =
ctx_.tx.getFieldAmount(sfFee).xrp();
1668 auto const resetResult =
reset(fee);
1670 result = resetResult.first;
1672 fee = resetResult.second;
1679 result =
ctx_.checkInvariants(result, fee);
1705 ctx_.destroyXRP(fee);
1708 metadata =
ctx_.apply(result);
1716 JLOG(
j_.trace()) << (applied ?
"applied " :
"not applied ") <<
transToken(result);
1718 return {result, applied, metadata};
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
State information when applying a tx.
Writeable view to a ledger, for applying a transaction.
virtual SLE::pointer peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual void update(SLE::ref sle)=0
Indicate changes to a peeked SLE.
RAII class to set and restore the current transaction rules.
static uint32_t txToPermissionType(TxType type)
static Permission const & getInstance()
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
virtual bool txExists(key_type const &key) const =0
Returns true if a tx exists in the tx map.
virtual bool open() const =0
Returns true if this reflects an open ledger.
LedgerIndex seq() const
Returns the sequence number of the base ledger.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
virtual std::string getFullText() const
std::shared_ptr< STLedgerEntry > pointer
std::shared_ptr< STLedgerEntry const > const & const_ref
std::shared_ptr< STLedgerEntry const > const_pointer
Blob getFieldVL(SField const &field) const
bool isEquivalent(STBase const &t) const override
std::uint32_t getFieldU32(SField const &field) const
STArray const & getFieldArray(SField const &field) const
bool isFlag(std::uint32_t) const
bool isFieldPresent(SField const &field) const
uint256 getFieldH256(SField const &field) const
STBase const & peekAtField(SField const &field) const
STObject getFieldObject(SField const &field) const
AccountID getAccountID(SField const &field) const
STAmount const & getFieldAmount(SField const &field) const
std::uint32_t getFlags() const
SeqProxy getSeqProxy() const
TxType getTxnType() const
json::Value getJson(JsonOptions options) const override
AccountID getInitiator() const
The account responsible for the authorization: the delegate when sfDelegate is present,...
uint256 getTransactionID() const
A type that represents either a sequence value or a ticket value.
static constexpr SeqProxy rawSequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
constexpr bool isTicket() const
constexpr std::uint32_t value() const
constexpr bool isSeq() const
Slice slice() const noexcept
Service registry for dependency injection.
virtual LoadFeeTrack & getFeeTrack()=0
static std::expected< std::vector< SignerEntry >, NotTEC > deserialize(STObject const &obj, beast::Journal journal, std::string_view annotation)
An immutable linear range of bytes.
bool empty() const noexcept
Return true if the byte range is empty.
static NotTEC preflight1(PreflightContext const &ctx, std::uint32_t flagMask)
Performs early sanity checks on the account and fee fields.
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
TER consumeSeqProxy(SLE::pointer const &sleAccount)
static NotTEC checkPermission(ReadView const &view, STTx const &tx, std::unordered_set< GranularPermissionType > &heldGranularPermissions)
void trapTransaction(uint256) const
static TER checkFee(PreclaimContext const &ctx, XRPAmount baseFee)
static XRPAmount minimumFee(ServiceRegistry ®istry, XRPAmount baseFee, Fees const &fees, ApplyFlags flags)
Compute the minimum fee required to process a transaction with a given baseFee based on the current s...
static NotTEC checkSign(PreclaimContext const &ctx)
static NotTEC checkSponsor(ReadView const &view, STTx const &tx)
static XRPAmount calculateOwnerReserveFee(ReadView const &view, STTx const &tx)
ApplyResult operator()()
Process the transaction.
static NotTEC preflightSigValidated(PreflightContext const &ctx)
static NotTEC checkSeqProxy(ReadView const &view, STTx const &tx, beast::Journal j)
static FeePayer getFeePayer(ReadView const &view, STTx const &tx)
static NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
static NotTEC checkSingleSign(ReadView const &view, AccountID const &idSigner, AccountID const &idAccount, SLE::const_pointer sleAccount, beast::Journal const j)
TER checkTransactionInvariants(TER result, XRPAmount fee)
Check transaction-specific invariants only.
Transactor(Transactor const &)=delete
static NotTEC preflightUniversal(PreflightContext const &ctx)
Universal validations.
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
TER checkInvariants(TER result, XRPAmount fee)
Check all invariants for the current transaction.
AccountID const accountID_
static NotTEC checkPriorTxAndLastLedger(PreclaimContext const &ctx)
static NotTEC checkMultiSign(ReadView const &view, ApplyFlags flags, AccountID const &id, STObject const &sigObject, beast::Journal const j)
static bool validDataLength(std::optional< Slice > const &slice, std::size_t maxLength)
virtual void preCompute()
virtual void visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after)=0
Inspect a single ledger entry modified by this transaction.
std::pair< TER, XRPAmount > reset(XRPAmount fee)
Reset the context, discarding any changes made and adjust the fee.
virtual bool finalizeInvariants(STTx const &tx, TER result, XRPAmount fee, ReadView const &view, beast::Journal const &j)=0
Check transaction-specific post-conditions after all entries have been visited.
static TER ticketDelete(ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)
std::tuple< TER, XRPAmount, bool > processPersistentChanges(TER result, XRPAmount fee)
TER deleteSLE(ApplyView &view, SLE::ref sleCredential, beast::Journal j)
std::optional< NotTEC > preflightCheckSimulateKeys(ApplyFlags flags, STObject const &sigObject, beast::Journal j)
Checks the special signing key state needed for simulation.
NotTEC preflightCheckSigningKey(STObject const &sigObject, beast::Journal j)
Checks the validity of the transactor signing key.
Keylet computation functions.
Keylet nftokenOffer(AccountID const &owner, SeqProxy const &seq)
An offer from an account to buy or sell an NFT.
Keylet offer(AccountID const &id, SeqProxy const &seq) noexcept
An offer from an account.
Keylet signerList(AccountID const &account) noexcept
A SignerList.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet ticket(AccountID const &id, SeqProxy const &ticketSeq)
A ticket belonging to an account.
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet sponsorship(AccountID const &sponsor, AccountID const &sponsee) noexcept
A Sponsorship.
Keylet credential(AccountID const &subject, AccountID const &issuer, Slice const &credType) noexcept
bool deleteTokenOffer(ApplyView &view, SLE::ref offer)
Deletes the given token offer.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
@ telNETWORK_ID_MAKES_TX_NON_CANONICAL
@ terNO_DELEGATE_PERMISSION
static void removeExpiredNFTokenOffers(ApplyView &view, std::vector< uint256 > const &offers, beast::Journal viewJ)
constexpr FlagValue tfInnerBatchTxn
void decreaseOwnerCountForObject(ApplyView &view, SLE::ref accountSle, SLE::ref objectSle, std::uint32_t count, beast::Journal j)
Decrease owner-count fields for an existing ledger object.
bool isLegalAmount(XRPAmount const &amount)
Returns true if the amount does not exceed the initial XRP in existence.
std::unordered_set< GranularPermissionType > getGranularPermission(SLE::const_ref delegate, TxType const &type)
Load the granular permissions granted to the delegate account for the specified transaction type.
@ SigBad
Signature is bad.
TER deleteAMMTrustLine(ApplyView &view, SLE::pointer sleState, std::optional< AccountID > const &ammAccountID, beast::Journal j)
Delete trustline to AMM.
static void removeExpiredCredentials(ApplyView &view, std::vector< uint256 > const &creds, beast::Journal viewJ)
bool isTecClaimHardFail(TER ter, ApplyFlags flags)
Return true if the transaction can claim a fee (tec), and the ApplyFlags do not allow soft failures.
std::pair< Validity, std::string > checkValidity(HashRouter &router, STTx const &tx, Rules const &rules)
Checks transaction signature and local checks.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
static void removeUnfundedOffers(ApplyView &view, std::vector< uint256 > const &offers, beast::Journal viewJ)
constexpr std::uint16_t kMaxDeletableAmmTrustLines
The maximum number of trustlines to delete as part of AMM account deletion cleanup.
std::string transToken(TER code)
NotTEC checkTxPermission(SLE::const_ref delegate, STTx const &tx)
Check if the delegate account has permission to execute the transaction.
TER offerDelete(ApplyView &view, SLE::ref sle, beast::Journal j)
Delete an offer.
bool isReserveSponsored(STTx const &tx)
Whether the transaction's reserve is sponsored (sfSponsor present + spfSponsorReserve set).
std::string to_string(BaseUInt< Bits, Tag > const &a)
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
constexpr std::size_t kExpiredOfferRemoveLimit
The maximum number of expired offers to delete at once.
Slice makeSlice(std::array< T, N > const &a)
void open(soci::session &s, BasicConfig const &config, std::string const &dbName)
Open a soci session.
bool isReserveSponsorAllowed(TxType txType)
Whether the given transaction type may use reserve sponsorship (v1).
std::string toShortString(BaseUInt< Bits, Tag > const &a)
TERSubset< CanCvtToNotTEC > NotTEC
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
bool isFeeSponsored(STTx const &tx)
Whether the transaction's fee is sponsored (sfSponsor present + spfSponsorFee set).
static NotTEC preflight1Sponsor(PreflightContext const &ctx)
AccountID calcAccountID(PublicKey const &pk)
static void removeDeletedTrustLines(ApplyView &view, std::vector< uint256 > const &trustLines, beast::Journal viewJ)
bool hasInvalidAmount(STBase const &field, beast::Journal j)
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
constexpr FlagValue spfSponsorFlagMask
XRPAmount scaleFeeLoad(XRPAmount fee, LoadFeeTrack const &feeTrack, Fees const &fees, bool bUnlimited)
bool isTesSuccess(TER x) noexcept
TERSubset< CanCvtToTER > TER
NotTEC preflight0(PreflightContext const &ctx, std::uint32_t flagMask)
Performs early sanity checks on the txid and flags.
bool isTecClaim(TER x) noexcept
bool isPseudoAccount(SLE::const_pointer sleAcct, std::set< SField const * > const &pseudoFieldFilter={})
Returns true if and only if sleAcct is a pseudo-account or specific pseudo-accounts in pseudoFieldFil...
constexpr std::size_t kUnfundedOfferRemoveLimit
The maximum number of unfunded offers to delete at once.
constexpr std::size_t kOversizeMetaDataCap
The maximum number of metadata entries allowed in one transaction.
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
constexpr FlagValue tfUniversalMask
XRPAmount accountReserve(ReadView const &view, SLE::const_ref sle, beast::Journal j, Adjustment adj={})
Returns the account reserve, in drops.
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Reflects the fee settings for a particular ledger.
State information when determining if a tx is likely to claim a fee.
std::reference_wrapper< ServiceRegistry > registry
std::optional< uint256 const > const parentBatchId
State information when preflighting a tx.
std::optional< uint256 const > parentBatchId
std::reference_wrapper< ServiceRegistry > registry