20 #include <ripple/app/tx/impl/Payment.h>
21 #include <ripple/app/paths/RippleCalc.h>
22 #include <ripple/basics/Log.h>
23 #include <ripple/core/Config.h>
24 #include <ripple/protocol/Feature.h>
25 #include <ripple/protocol/jss.h>
26 #include <ripple/protocol/st.h>
27 #include <ripple/protocol/TxFlags.h>
39 return sendMax.native() ? sendMax.xrp() : beast::zero;
44 return saDstAmount.
native() ? saDstAmount.xrp() : beast::zero;
61 JLOG(j.trace()) <<
"Malformed transaction: " <<
69 bool const bPaths = tx.isFieldPresent (
sfPaths);
70 bool const bMax = tx.isFieldPresent (
sfSendMax);
75 auto const account = tx.getAccountID(
sfAccount);
78 maxSourceAmount = tx.getFieldAmount (
sfSendMax);
79 else if (saDstAmount.
native ())
80 maxSourceAmount = saDstAmount;
85 saDstAmount < beast::zero);
87 auto const& uSrcCurrency = maxSourceAmount.
getCurrency ();
88 auto const& uDstCurrency = saDstAmount.
getCurrency ();
91 bool const bXRPDirect = uSrcCurrency.
isZero () && uDstCurrency.isZero ();
100 JLOG(j.trace()) <<
"Malformed transaction: " <<
101 "Payment destination account not specified.";
104 if (bMax && maxSourceAmount <= beast::zero)
106 JLOG(j.trace()) <<
"Malformed transaction: " <<
107 "bad max amount: " << maxSourceAmount.
getFullText ();
110 if (saDstAmount <= beast::zero)
112 JLOG(j.trace()) <<
"Malformed transaction: "<<
118 JLOG(j.trace()) <<
"Malformed transaction: " <<
122 if (account == uDstAccountID && uSrcCurrency == uDstCurrency && !bPaths)
126 JLOG(j.trace()) <<
"Malformed transaction: " <<
127 "Redundant payment from " <<
to_string (account) <<
128 " to self without path for " <<
to_string (uDstCurrency);
131 if (bXRPDirect && bMax)
134 JLOG(j.trace()) <<
"Malformed transaction: " <<
135 "SendMax specified for XRP to XRP.";
138 if (bXRPDirect && bPaths)
141 JLOG(j.trace()) <<
"Malformed transaction: " <<
142 "Paths specified for XRP to XRP.";
145 if (bXRPDirect && partialPaymentAllowed)
148 JLOG(j.trace()) <<
"Malformed transaction: " <<
149 "Partial payment specified for XRP to XRP.";
152 if (bXRPDirect && limitQuality)
155 JLOG(j.trace()) <<
"Malformed transaction: " <<
156 "Limit quality specified for XRP to XRP.";
159 if (bXRPDirect && !defaultPathsAllowed)
162 JLOG(j.trace()) <<
"Malformed transaction: " <<
163 "No ripple direct specified for XRP to XRP.";
170 if (! partialPaymentAllowed)
172 JLOG(j.trace()) <<
"Malformed transaction: Partial payment not "
173 "specified for " << jss::DeliverMin.c_str() <<
".";
177 auto const dMin = *deliverMin;
180 JLOG(j.trace()) <<
"Malformed transaction: Invalid " <<
181 jss::DeliverMin.c_str() <<
" amount. " <<
185 if (dMin.issue() != saDstAmount.
issue())
187 JLOG(j.trace()) <<
"Malformed transaction: Dst issue differs "
188 "from " << jss::DeliverMin.c_str() <<
". " <<
192 if (dMin > saDstAmount)
194 JLOG(j.trace()) <<
"Malformed transaction: Dst amount less than " <<
195 jss::DeliverMin.c_str() <<
". " <<
217 auto const sleDst = ctx.
view.
read(k);
222 if (!saDstAmount.
native())
225 "Delay transaction: Destination account does not exist.";
232 && partialPaymentAllowed)
237 "Delay transaction: Partial payment not allowed to create account.";
249 "Delay transaction: Destination account does not exist. " <<
250 "Insufficent payment to create account.";
266 JLOG(ctx.
j.
trace()) <<
"Malformed transaction: DestinationTag required.";
271 if (paths || sendMax || !saDstAmount.
native())
282 for (
auto const& path : spsPaths)
316 maxSourceAmount = *sendMax;
317 else if (saDstAmount.
native ())
318 maxSourceAmount = saDstAmount;
323 saDstAmount < beast::zero);
326 "maxSourceAmount=" << maxSourceAmount.
getFullText () <<
340 sleDst = std::make_shared<SLE>(k);
341 sleDst->setAccountID(
sfAccount, uDstAccountID);
355 bool const reqDepositAuth = sleDst->getFlags() &
lsfDepositAuth &&
360 bool const bRipple = paths || sendMax || !saDstAmount.
native ();
364 if (!depositPreauth && bRipple && reqDepositAuth)
372 if (depositPreauth && reqDepositAuth)
380 if (!
view().exists (
399 <<
"Entering RippleCalc in payment: "
428 auto terResult = rc.
result ();
439 assert (saDstAmount.
native ());
449 auto const uOwnerCount = sleSrc->getFieldU32 (
sfOwnerCount);
464 JLOG(
j_.
trace()) <<
"Delay transaction: Insufficient funds: " <<
496 if (!
view().exists (
502 if (saDstAmount > dstReserve ||
503 sleDst->getFieldAmount (
sfBalance) > dstReserve)
511 sleDst->setFieldAmount(
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
const std::uint32_t tfNoRippleDirect
const std::uint32_t tfPartialPayment
Stream trace() const
Severity stream access functions.
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
A wrapper which makes credits unavailable to balances.
std::uint64_t mantissa() const noexcept
const uint256 featureDepositPreauth
const SF_U32 sfSequence(access, STI_UINT32, 4, "Sequence")
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
const std::uint32_t tfPaymentMask
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
const uint256 featureDepositAuth
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
bool isLegalNet(STAmount const &value)
std::string to_string(ListDisposition disposition)
const SF_Amount sfAmount(access, STI_AMOUNT, 1, "Amount")
static NotTEC preflight(PreflightContext const &ctx)
const SF_U32 sfOwnerCount(access, STI_UINT32, 13, "OwnerCount")
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
static const depositPreauth_t depositPreauth
const uint256 featureDeletableAccounts
const SF_U32 sfDestinationTag(access, STI_UINT32, 14, "DestinationTag")
std::string getFullText() const override
int exponent() const noexcept
@ temBAD_SEND_XRP_PARTIAL
static const account_t account
const SF_Amount sfSendMax(access, STI_AMOUNT, 9, "SendMax")
AccountID getAccountID(SField const &field) const
static const std::size_t MaxPathLength
std::uint32_t getFlags() const
void deliver(STAmount const &amount)
Sets the DeliveredAmount field in the metadata.
@ temBAD_SEND_XRP_NO_DIRECT
bool enabled(uint256 const &id) const
Returns true if a feature is enabled.
static XRPAmount calculateMaxSpend(STTx const &tx)
const SF_Amount sfFee(access, STI_AMOUNT, 8, "Fee")
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
Currency const & getCurrency() const
uint256 getTransactionID() const
State information when determining if a tx is likely to claim a fee.
bool native() const noexcept
virtual void insert(std::shared_ptr< SLE > const &sle)=0
Insert a new state SLE.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
static const std::size_t MaxPathSize
const SF_Amount sfBalance(access, STI_AMOUNT, 2, "Balance")
const SF_Amount sfDeliverMin(access, STI_AMOUNT, 10, "DeliverMin")
void apply(RawView &to)
Apply changes to base view.
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
LedgerIndex seq() const
Returns the sequence number of the base ledger.
virtual Rules const & rules() const =0
Returns the tx processing rules.
Issue const & issue() const
bool isFieldPresent(SField const &field) const
const std::uint32_t tfLimitQuality
static Output rippleCalculate(PaymentSandbox &view, STAmount const &saMaxAmountReq, STAmount const &saDstAmountReq, AccountID const &uDstAccountID, AccountID const &uSrcAccountID, STPathSet const &spsPaths, Logs &l, Input const *const pInputs=nullptr)
const SField sfPaths(access, STI_PATHSET, 1, "Paths")
std::vector< STPath >::size_type size() const
const SF_Account sfDestination(access, STI_ACCOUNT, 3, "Destination")
void setResult(TER const value)
State information when preflighting a tx.
STPathSet const & getFieldPathSet(SField const &field) const
static TER preclaim(PreclaimContext const &ctx)
virtual bool open() const =0
Returns true if this reflects an open ledger.
STAmount const & getFieldAmount(SField const &field) const