20#include <xrpld/app/ledger/Ledger.h>
21#include <xrpld/app/paths/Flow.h>
22#include <xrpld/app/tx/detail/CashCheck.h>
24#include <xrpl/basics/Log.h>
25#include <xrpl/basics/scope.h>
26#include <xrpl/protocol/Feature.h>
27#include <xrpl/protocol/Indexes.h>
28#include <xrpl/protocol/TER.h>
29#include <xrpl/protocol/TxFlags.h>
39 auto const optAmount = ctx.
tx[~sfAmount];
40 auto const optDeliverMin = ctx.
tx[~sfDeliverMin];
42 if (
static_cast<bool>(optAmount) ==
static_cast<bool>(optDeliverMin))
45 <<
"Malformed transaction: "
46 "does not specify exactly one of Amount and DeliverMin.";
51 STAmount const value{optAmount ? *optAmount : *optDeliverMin};
54 JLOG(ctx.
j.
warn()) <<
"Malformed transaction: bad amount: "
55 << value.getFullText();
61 JLOG(ctx.
j.
warn()) <<
"Malformed transaction: Bad currency.";
74 JLOG(ctx.
j.
warn()) <<
"Check does not exist.";
79 AccountID const dstId = sleCheck->at(sfDestination);
80 if (ctx.
tx[sfAccount] != dstId)
82 JLOG(ctx.
j.
warn()) <<
"Cashing a check with wrong Destination.";
85 AccountID const srcId = sleCheck->at(sfAccount);
91 JLOG(ctx.
j.
error()) <<
"Malformed transaction: Cashing check to self.";
98 if (!sleSrc || !sleDst)
102 <<
"Malformed transaction: source or destination not in ledger";
107 !sleCheck->isFieldPresent(sfDestinationTag))
112 <<
"Malformed transaction: DestinationTag required in check.";
119 JLOG(ctx.
j.
warn()) <<
"Cashing a check that has already expired.";
127 auto const optAmount = tx[~sfAmount];
128 return optAmount ? *optAmount : tx[sfDeliverMin];
131 STAmount const sendMax = sleCheck->at(sfSendMax);
132 Currency const currency{value.getCurrency()};
135 JLOG(ctx.
j.
warn()) <<
"Check cash does not match check currency.";
138 AccountID const issuerId{value.getIssuer()};
141 JLOG(ctx.
j.
warn()) <<
"Check cash does not match check issuer.";
146 JLOG(ctx.
j.
warn()) <<
"Check cashed for more than check sendMax.";
155 sleCheck->at(sfAccount),
167 if (value > availableFunds)
170 <<
"Check cashed for more than owner's balance.";
176 if (!value.native() && (value.getIssuer() != dstId))
178 auto const sleTrustLine =
185 <<
"Cannot cash check for IOU without trustline.";
193 <<
"Can't receive IOUs from non-existent issuer: "
210 bool const canonical_gt(dstId > issuerId);
212 bool const is_authorized(
213 sleTrustLine->at(sfFlags) &
219 <<
"Can't receive IOUs from issuer without auth.";
232 JLOG(ctx.
j.
warn()) <<
"Cashing a check to a frozen trustline.";
251 JLOG(
j_.
fatal()) <<
"Precheck did not verify check's existence.";
256 AccountID const srcId{sleCheck->getAccountID(sfAccount)};
262 <<
"Precheck did not verify source or destination's existence.";
278 auto const optDeliverMin =
ctx_.
tx[~sfDeliverMin];
282 STAmount const sendMax = sleCheck->at(sfSendMax);
303 if (srcLiquid < xrpDeliver)
307 JLOG(
j_.
trace()) <<
"Cash Check: Insufficient XRP: "
308 << srcLiquid.getFullText() <<
" < "
309 << xrpDeliver.getFullText();
335 optDeliverMin->issue(),
341 Issue const& trustLineIssue = flowDeliver.issue();
342 AccountID const issuer = flowDeliver.getIssuer();
345 bool const destLow = issuer >
account_;
347 bool const checkCashMakesTrustLine =
350 if (checkCashMakesTrustLine && !psb.
exists(trustLineKey))
362 if (
std::uint32_t const ownerCount = {sleDst->at(sfOwnerCount)};
365 JLOG(
j_.
trace()) <<
"Trust line does not exist. "
366 "Insufficent reserve to create line.";
371 Currency const currency = flowDeliver.getCurrency();
372 STAmount initialBalance(flowDeliver.issue());
409 auto const sleTrustLine = psb.
peek(trustLineKey);
413 SF_AMOUNT const& tweakedLimit = destLow ? sfLowLimit : sfHighLimit;
414 STAmount const savedLimit = sleTrustLine->at(tweakedLimit);
418 [&psb, &trustLineKey, &tweakedLimit, &savedLimit]() {
419 if (
auto const sleTrustLine = psb.
peek(trustLineKey))
420 sleTrustLine->at(tweakedLimit) = savedLimit;
423 if (checkCashMakesTrustLine)
429 sleTrustLine->at(tweakedLimit) = bigAmount;
433 auto const result =
flow(
440 static_cast<bool>(optDeliverMin),
444 sleCheck->getFieldAmount(sfSendMax),
451 return result.result();
457 if (result.actualAmountOut < *optDeliverMin)
460 <<
"flow did not produce DeliverMin.";
463 if (!checkCashMakesTrustLine)
470 if (checkCashMakesTrustLine)
482 sleCheck->at(sfDestinationNode),
487 JLOG(
j_.
fatal()) <<
"Unable to delete check from destination.";
495 sleCheck->at(sfOwnerNode),
500 JLOG(
j_.
fatal()) <<
"Unable to delete check from owner.";
Stream trace() const
Severity stream access functions.
virtual beast::Journal journal(std::string const &name)=0
beast::Journal const journal
void deliver(STAmount const &amount)
Sets the DeliveredAmount field in the metadata.
bool dirRemove(Keylet const &directory, std::uint64_t page, uint256 const &key, bool keepRoot)
Remove an entry from a directory.
static TER preclaim(PreclaimContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
A currency issued by an account.
A wrapper which makes credits unavailable to balances.
void apply(RawView &to)
Apply changes to base view.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
virtual Fees const & fees() const =0
Returns the fees for 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.
void setIssuer(AccountID const &uIssuer)
static int const cMaxOffset
Currency const & getCurrency() const
static std::uint64_t const cMaxValue
AccountID const & getIssuer() const
bool native() const noexcept
STAmount const & getFieldAmount(SField const &field) const
Fees const & fees() const override
Returns the fees for the base ledger.
void erase(std::shared_ptr< SLE > const &sle) override
Remove a peeked SLE.
void update(std::shared_ptr< SLE > const &sle) override
Indicate changes to a peeked SLE.
bool exists(Keylet const &k) const override
Determine if a state item exists.
Rules const & rules() const override
Returns the tx processing rules.
std::shared_ptr< SLE > peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
AccountID const & noAccount()
A placeholder for empty accounts.
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
bool isLegalNet(STAmount const &value)
void adjustOwnerCount(ApplyView &view, std::shared_ptr< SLE > const &sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
TER transferXRP(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &amount, beast::Journal j)
StrandResult< TInAmt, TOutAmt > flow(PaymentSandbox const &baseView, Strand const &strand, std::optional< TInAmt > const &maxIn, TOutAmt const &out, beast::Journal j)
Request out amount from a strand.
bool isFrozen(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer)
bool hasExpired(ReadView const &view, std::optional< std::uint32_t > const &exp)
Determines whether the given expiration time has passed.
@ tecNO_LINE_INSUF_RESERVE
bool isTesSuccess(TER x) noexcept
std::string to_string(base_uint< Bits, Tag > const &a)
TER trustCreate(ApplyView &view, bool const bSrcHigh, AccountID const &uSrcAccountID, AccountID const &uDstAccountID, uint256 const &uIndex, SLE::ref sleAccount, bool const bAuth, bool const bNoRipple, bool const bFreeze, bool bDeepFreeze, STAmount const &saBalance, STAmount const &saLimit, std::uint32_t uSrcQualityIn, std::uint32_t uSrcQualityOut, beast::Journal j)
Create a trust line.
TERSubset< CanCvtToNotTEC > NotTEC
XRPAmount xrpLiquid(ReadView const &view, AccountID const &id, std::int32_t ownerCountAdj, beast::Journal j)
A pair of SHAMap key and LedgerEntryType.
State information when determining if a tx is likely to claim a fee.
State information when preflighting a tx.
A field with a type known at compile time.