20#include <xrpld/app/misc/DelegateUtils.h> 
   21#include <xrpld/app/misc/PermissionedDEXHelpers.h> 
   22#include <xrpld/app/paths/RippleCalc.h> 
   23#include <xrpld/app/tx/detail/Payment.h> 
   25#include <xrpl/basics/Log.h> 
   26#include <xrpl/ledger/CredentialHelpers.h> 
   27#include <xrpl/ledger/View.h> 
   28#include <xrpl/protocol/Feature.h> 
   29#include <xrpl/protocol/Quality.h> 
   30#include <xrpl/protocol/TxFlags.h> 
   31#include <xrpl/protocol/jss.h> 
   40            tx.isFieldPresent(sfSendMax) ? tx[sfSendMax] : tx[sfAmount];
 
   44        return maxAmount.
native() ? maxAmount.
xrp() : beast::zero;
 
 
   65            dstAmount < beast::zero);
 
 
   86    STAmount const dstAmount(tx.getFieldAmount(sfAmount));
 
 
   98    STAmount const dstAmount(tx.getFieldAmount(sfAmount));
 
  112    bool const hasPaths = tx.isFieldPresent(sfPaths);
 
  113    bool const hasMax = tx.isFieldPresent(sfSendMax);
 
  115    auto const deliverMin = tx[~sfDeliverMin];
 
  117    auto const account = tx.getAccountID(sfAccount);
 
  121    if ((mptDirect && dstAmount.
asset() != maxSourceAmount.
asset()) ||
 
  124        JLOG(j.trace()) << 
"Malformed transaction: inconsistent issues: " 
  127                        << deliverMin.value_or(
STAmount{}).getFullText();
 
  131    auto const& srcAsset = maxSourceAmount.
asset();
 
  132    auto const& dstAsset = dstAmount.
asset();
 
  134    bool const xrpDirect = srcAsset.
native() && dstAsset.native();
 
  139    auto const dstAccountID = tx.getAccountID(sfDestination);
 
  143        JLOG(j.trace()) << 
"Malformed transaction: " 
  144                        << 
"Payment destination account not specified.";
 
  147    if (hasMax && maxSourceAmount <= beast::zero)
 
  149        JLOG(j.trace()) << 
"Malformed transaction: bad max amount: " 
  153    if (dstAmount <= beast::zero)
 
  155        JLOG(j.trace()) << 
"Malformed transaction: bad dst amount: " 
  161        JLOG(j.trace()) << 
"Malformed transaction: Bad currency.";
 
  164    if (account == dstAccountID && 
equalTokens(srcAsset, dstAsset) && !hasPaths)
 
  168        JLOG(j.trace()) << 
"Malformed transaction: " 
  169                        << 
"Redundant payment from " << 
to_string(account)
 
  170                        << 
" to self without path for " << 
to_string(dstAsset);
 
  173    if (xrpDirect && hasMax)
 
  176        JLOG(j.trace()) << 
"Malformed transaction: " 
  177                        << 
"SendMax specified for XRP to XRP.";
 
  180    if ((xrpDirect || mptDirect) && hasPaths)
 
  183        JLOG(j.trace()) << 
"Malformed transaction: " 
  184                        << 
"Paths specified for XRP to XRP or MPT to MPT.";
 
  187    if (xrpDirect && partialPaymentAllowed)
 
  190        JLOG(j.trace()) << 
"Malformed transaction: " 
  191                        << 
"Partial payment specified for XRP to XRP.";
 
  194    if ((xrpDirect || mptDirect) && limitQuality)
 
  198            << 
"Malformed transaction: " 
  199            << 
"Limit quality specified for XRP to XRP or MPT to MPT.";
 
  202    if ((xrpDirect || mptDirect) && !defaultPathsAllowed)
 
  206            << 
"Malformed transaction: " 
  207            << 
"No ripple direct specified for XRP to XRP or MPT to MPT.";
 
  213        if (!partialPaymentAllowed)
 
  215            JLOG(j.trace()) << 
"Malformed transaction: Partial payment not " 
  217                            << jss::DeliverMin.c_str() << 
".";
 
  221        auto const dMin = *deliverMin;
 
  225                << 
"Malformed transaction: Invalid " << jss::DeliverMin.c_str()
 
  226                << 
" amount. " << dMin.getFullText();
 
  229        if (dMin.asset() != dstAmount.
asset())
 
  232                << 
"Malformed transaction: Dst issue differs " 
  234                << jss::DeliverMin.c_str() << 
". " << dMin.getFullText();
 
  237        if (dMin > dstAmount)
 
  240                << 
"Malformed transaction: Dst amount less than " 
  241                << jss::DeliverMin.c_str() << 
". " << dMin.getFullText();
 
 
  256    auto const delegate = tx[~sfDelegate];
 
  261    auto const sle = 
view.
read(delegateKey);
 
  273    auto const& amountAsset = dstAmount.
asset();
 
  277         tx[sfSendMax].asset() != amountAsset) ||
 
  281    if (granularPermissions.
contains(PaymentMint) && !
isXRP(amountAsset) &&
 
  282        amountAsset.getIssuer() == tx[sfAccount])
 
  285    if (granularPermissions.
contains(PaymentBurn) && !
isXRP(amountAsset) &&
 
  286        amountAsset.getIssuer() == tx[sfDestination])
 
 
  299    auto const sendMax = ctx.
tx[~sfSendMax];
 
  301    AccountID const dstAccountID(ctx.
tx[sfDestination]);
 
  305    auto const sleDst = ctx.
view.
read(k);
 
  313                << 
"Delay transaction: Destination account does not exist.";
 
  319        else if (ctx.
view.
open() && partialPaymentAllowed)
 
  323            JLOG(ctx.
j.
trace()) << 
"Delay transaction: Partial payment not " 
  324                                   "allowed to create account.";
 
  335                << 
"Delay transaction: Destination account does not exist. " 
  336                << 
"Insufficent payment to create account.";
 
  354            << 
"Malformed transaction: DestinationTag required.";
 
  360    if ((hasPaths || sendMax || !dstAmount.
native()) && ctx.
view.
open())
 
  366                return path.size() > MaxPathLength;
 
  381                ctx.
view, ctx.
tx[sfAccount], ctx.
tx[sfDomainID]))
 
  385                ctx.
view, ctx.
tx[sfDestination], ctx.
tx[sfDomainID]))
 
 
  395    auto const deliverMin = 
ctx_.
tx[~sfDeliverMin];
 
  403    auto const sendMax = 
ctx_.
tx[~sfSendMax];
 
  411    JLOG(
j_.
trace()) << 
"maxSourceAmount=" << maxSourceAmount.getFullText()
 
  426        sleDst->setAccountID(sfAccount, dstAccountID);
 
  427        sleDst->setFieldU32(sfSequence, seqno);
 
  441    bool const reqDepositAuth =
 
  447        (hasPaths || sendMax || !dstAmount.
native()) && !mptDirect;
 
  451    if (!depositPreauth && 
ripple && reqDepositAuth)
 
  459        if (depositPreauth && depositAuth)
 
  486            JLOG(
j_.
debug()) << 
"Entering RippleCalc in payment: " 
  514        auto terResult = rc.
result();
 
  552        auto const& issuer = mptIssue.
getIssuer();
 
  555        Rate rate{QUALITY_ONE};
 
  557        if (
account_ != issuer && dstAccountID != issuer)
 
  579        if (partialPaymentAllowed && requiredMaxSourceAmount > maxSourceAmount)
 
  581            requiredMaxSourceAmount = maxSourceAmount;
 
  583            amountDeliver = 
divide(maxSourceAmount, rate);
 
  586        if (requiredMaxSourceAmount > maxSourceAmount ||
 
  587            (deliverMin && amountDeliver < *deliverMin))
 
  600            if (
view().rules().enabled(fixMPTDeliveredAmount) &&
 
  601                amountDeliver != dstAmount)
 
  610    XRPL_ASSERT(dstAmount.
native(), 
"ripple::Payment::doApply : amount is XRP");
 
  620    auto const ownerCount = sleSrc->getFieldU32(sfOwnerCount);
 
  634        JLOG(
j_.
trace()) << 
"Delay transaction: Insufficient funds: " 
  676        if (dstAmount > dstReserve ||
 
  677            sleDst->getFieldAmount(sfBalance) > dstReserve)
 
  693    sleDst->setFieldAmount(
 
  694        sfBalance, sleDst->getFieldAmount(sfBalance) + dstAmount);
 
 
Stream trace() const
Severity stream access functions.
 
beast::Journal const journal
 
void deliver(STAmount const &amount)
Sets the DeliveredAmount field in the metadata.
 
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
 
virtual void insert(std::shared_ptr< SLE > const &sle)=0
Insert a new state SLE.
 
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
 
A currency issued by an account.
 
AccountID const & getIssuer() const
 
A wrapper which makes credits unavailable to balances.
 
void apply(RawView &to)
Apply changes to base view.
 
static NotTEC checkPermission(ReadView const &view, STTx const &tx)
 
static std::size_t const MaxPathSize
 
static bool checkExtraFeatures(PreflightContext const &ctx)
 
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
 
static TER preclaim(PreclaimContext const &ctx)
 
static NotTEC preflight(PreflightContext const &ctx)
 
static TxConsequences makeTxConsequences(PreflightContext const &ctx)
 
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
 
virtual bool open() const =0
Returns true if this reflects an open ledger.
 
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
 
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.
 
constexpr bool holds() const noexcept
 
int exponent() const noexcept
 
Asset const & asset() const
 
constexpr TIss const & get() const
 
std::uint64_t mantissa() const noexcept
 
std::string getFullText() const override
 
bool native() const noexcept
 
STPathSet const & getFieldPathSet(SField const &field) const
 
AccountID getAccountID(SField const &field) const
 
STAmount const & getFieldAmount(SField const &field) const
 
bool isFieldPresent(SField const &field) const
 
std::uint32_t getFlags() const
 
std::vector< STPath >::const_iterator end() const
 
std::vector< STPath >::const_iterator begin() const
 
std::vector< STPath >::size_type size() const
 
uint256 getTransactionID() const
 
Class describing the consequences to the account of applying a transaction if the transaction consume...
 
static Output rippleCalculate(PaymentSandbox &view, STAmount const &saMaxAmountReq, STAmount const &saDstAmountReq, AccountID const &uDstAccountID, AccountID const &uSrcAccountID, STPathSet const &spsPaths, std::optional< uint256 > const &domainID, Logs &l, Input const *const pInputs=nullptr)
 
NotTEC checkFields(STTx const &tx, beast::Journal j)
 
TER valid(STTx const &tx, ReadView const &view, AccountID const &src, beast::Journal j)
 
Keylet delegate(AccountID const &account, AccountID const &authorizedAccount) noexcept
A keylet for Delegate object.
 
Keylet account(AccountID const &id) noexcept
AccountID root.
 
bool accountInDomain(ReadView const &view, AccountID const &account, Domain const &domainID)
 
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
 
STAmount divide(STAmount const &amount, Rate const &rate)
 
NotTEC checkTxPermission(std::shared_ptr< SLE const > const &delegate, STTx const &tx)
Check if the delegate account has permission to execute the transaction.
 
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
 
constexpr bool equalTokens(Asset const &lhs, Asset const &rhs)
 
bool isXRP(AccountID const &c)
 
bool isLegalNet(STAmount const &value)
 
constexpr std::uint32_t tfMPTPaymentMask
 
STAmount getMaxSourceAmount(AccountID const &account, STAmount const &dstAmount, std::optional< STAmount > const &sendMax)
 
STAmount multiply(STAmount const &amount, Rate const &rate)
 
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No)
Calls static accountSendIOU if saAmount represents Issue.
 
TER verifyDepositPreauth(STTx const &tx, ApplyView &view, AccountID const &src, AccountID const &dst, std::shared_ptr< SLE > const &sleDst, beast::Journal j)
 
TER requireAuth(ReadView const &view, Issue const &issue, AccountID const &account, AuthType authType=AuthType::Legacy)
Check if the account lacks required authorization.
 
constexpr std::uint32_t tfPartialPayment
 
void loadGranularPermission(std::shared_ptr< SLE const > const &delegate, TxType const &type, std::unordered_set< GranularPermissionType > &granularPermissions)
Load the granular permissions granted to the delegate account for the specified transaction type.
 
TER canTransfer(ReadView const &view, MPTIssue const &mptIssue, AccountID const &from, AccountID const &to)
Check if the destination account is allowed to receive MPT.
 
Rate transferRate(ReadView const &view, AccountID const &issuer)
Returns IOU issuer transfer fee as Rate.
 
bool isTerRetry(TER x) noexcept
 
constexpr std::uint32_t tfNoRippleDirect
 
bool isTesSuccess(TER x) noexcept
 
constexpr std::uint32_t tfPaymentMask
 
constexpr std::uint32_t tfLimitQuality
 
std::string to_string(base_uint< Bits, Tag > const &a)
 
bool isAnyFrozen(ReadView const &view, std::initializer_list< AccountID > const &accounts, MPTIssue const &mptIssue, int depth=0)
 
@ terNO_DELEGATE_PERMISSION
 
bool isPseudoAccount(std::shared_ptr< SLE const > sleAcct)
 
@ temBAD_SEND_XRP_PARTIAL
 
@ temBAD_SEND_XRP_NO_DIRECT
 
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
 
State information when determining if a tx is likely to claim a fee.
 
State information when preflighting a tx.
 
Represents a transfer rate.
 
void setResult(TER const value)