20 #include <ripple/app/paths/RippleCalc.h>
21 #include <ripple/app/tx/impl/Payment.h>
22 #include <ripple/basics/Log.h>
23 #include <ripple/core/Config.h>
24 #include <ripple/protocol/Feature.h>
25 #include <ripple/protocol/TxFlags.h>
26 #include <ripple/protocol/jss.h>
27 #include <ripple/protocol/st.h>
39 return sendMax.native() ? sendMax.xrp() : beast::zero;
44 return saDstAmount.
native() ? saDstAmount.xrp() : beast::zero;
61 JLOG(j.trace()) <<
"Malformed transaction: "
62 <<
"Invalid flags set.";
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;
86 saDstAmount < beast::zero);
88 auto const& uSrcCurrency = maxSourceAmount.
getCurrency();
89 auto const& uDstCurrency = saDstAmount.
getCurrency();
92 bool const bXRPDirect = uSrcCurrency.
isZero() && uDstCurrency.isZero();
101 JLOG(j.trace()) <<
"Malformed transaction: "
102 <<
"Payment destination account not specified.";
105 if (bMax && maxSourceAmount <= beast::zero)
107 JLOG(j.trace()) <<
"Malformed transaction: "
108 <<
"bad max amount: " << maxSourceAmount.
getFullText();
111 if (saDstAmount <= beast::zero)
113 JLOG(j.trace()) <<
"Malformed transaction: "
114 <<
"bad dst amount: " << saDstAmount.
getFullText();
119 JLOG(j.trace()) <<
"Malformed transaction: "
123 if (account == uDstAccountID && uSrcCurrency == uDstCurrency && !bPaths)
127 JLOG(j.trace()) <<
"Malformed transaction: "
128 <<
"Redundant payment from " <<
to_string(account)
129 <<
" to self without path for "
133 if (bXRPDirect && bMax)
136 JLOG(j.trace()) <<
"Malformed transaction: "
137 <<
"SendMax specified for XRP to XRP.";
140 if (bXRPDirect && bPaths)
143 JLOG(j.trace()) <<
"Malformed transaction: "
144 <<
"Paths specified for XRP to XRP.";
147 if (bXRPDirect && partialPaymentAllowed)
150 JLOG(j.trace()) <<
"Malformed transaction: "
151 <<
"Partial payment specified for XRP to XRP.";
154 if (bXRPDirect && limitQuality)
157 JLOG(j.trace()) <<
"Malformed transaction: "
158 <<
"Limit quality specified for XRP to XRP.";
161 if (bXRPDirect && !defaultPathsAllowed)
164 JLOG(j.trace()) <<
"Malformed transaction: "
165 <<
"No ripple direct specified for XRP to XRP.";
172 if (!partialPaymentAllowed)
174 JLOG(j.trace()) <<
"Malformed transaction: Partial payment not "
176 << jss::DeliverMin.c_str() <<
".";
180 auto const dMin = *deliverMin;
184 <<
"Malformed transaction: Invalid " << jss::DeliverMin.c_str()
185 <<
" amount. " << dMin.getFullText();
188 if (dMin.issue() != saDstAmount.
issue())
191 <<
"Malformed transaction: Dst issue differs "
193 << jss::DeliverMin.c_str() <<
". " << dMin.getFullText();
196 if (dMin > saDstAmount)
199 <<
"Malformed transaction: Dst amount less than "
200 << jss::DeliverMin.c_str() <<
". " << dMin.getFullText();
221 auto const sleDst = ctx.
view.
read(k);
226 if (!saDstAmount.
native())
229 <<
"Delay transaction: Destination account does not exist.";
235 else if (ctx.
view.
open() && partialPaymentAllowed)
239 JLOG(ctx.
j.
trace()) <<
"Delay transaction: Partial payment not "
240 "allowed to create account.";
251 <<
"Delay transaction: Destination account does not exist. "
252 <<
"Insufficent payment to create account.";
270 <<
"Malformed transaction: DestinationTag required.";
275 if (paths || sendMax || !saDstAmount.
native())
286 for (
auto const& path : spsPaths)
319 maxSourceAmount = *sendMax;
320 else if (saDstAmount.
native())
321 maxSourceAmount = saDstAmount;
327 saDstAmount < beast::zero);
343 sleDst = std::make_shared<SLE>(k);
344 sleDst->setAccountID(
sfAccount, uDstAccountID);
358 bool const reqDepositAuth = sleDst->getFlags() &
lsfDepositAuth &&
363 bool const bRipple = paths || sendMax || !saDstAmount.
native();
367 if (!depositPreauth && bRipple && reqDepositAuth)
375 if (depositPreauth && reqDepositAuth)
401 JLOG(
j_.
debug()) <<
"Entering RippleCalc in payment: "
428 auto terResult = rc.
result();
439 assert(saDstAmount.
native());
449 auto const uOwnerCount = sleSrc->getFieldU32(
sfOwnerCount);
463 JLOG(
j_.
trace()) <<
"Delay transaction: Insufficient funds: "
500 if (saDstAmount > dstReserve ||
501 sleDst->getFieldAmount(
sfBalance) > dstReserve)
509 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.
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
Keylet account(AccountID const &id) noexcept
AccountID root.
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)
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
virtual bool open() const =0
Returns true if this reflects an open ledger.
STAmount const & getFieldAmount(SField const &field) const