1#include <xrpld/app/ledger/Ledger.h> 
    2#include <xrpld/app/paths/Flow.h> 
    3#include <xrpld/app/tx/detail/CashCheck.h> 
    5#include <xrpl/basics/Log.h> 
    6#include <xrpl/basics/scope.h> 
    7#include <xrpl/protocol/Feature.h> 
    8#include <xrpl/protocol/Indexes.h> 
    9#include <xrpl/protocol/TER.h> 
   10#include <xrpl/protocol/TxFlags.h> 
   20    auto const optAmount = ctx.
tx[~sfAmount];
 
   21    auto const optDeliverMin = ctx.
tx[~sfDeliverMin];
 
   23    if (
static_cast<bool>(optAmount) == 
static_cast<bool>(optDeliverMin))
 
   26            << 
"Malformed transaction: " 
   27               "does not specify exactly one of Amount and DeliverMin.";
 
   32    STAmount const value{optAmount ? *optAmount : *optDeliverMin};
 
   35        JLOG(ctx.
j.
warn()) << 
"Malformed transaction: bad amount: " 
   36                           << value.getFullText();
 
   42        JLOG(ctx.
j.
warn()) << 
"Malformed transaction: Bad currency.";
 
 
   55        JLOG(ctx.
j.
warn()) << 
"Check does not exist.";
 
   60    AccountID const dstId = sleCheck->at(sfDestination);
 
   61    if (ctx.
tx[sfAccount] != dstId)
 
   63        JLOG(ctx.
j.
warn()) << 
"Cashing a check with wrong Destination.";
 
   66    AccountID const srcId = sleCheck->at(sfAccount);
 
   72        JLOG(ctx.
j.
error()) << 
"Malformed transaction: Cashing check to self.";
 
   79        if (!sleSrc || !sleDst)
 
   83                << 
"Malformed transaction: source or destination not in ledger";
 
   88            !sleCheck->isFieldPresent(sfDestinationTag))
 
   93                << 
"Malformed transaction: DestinationTag required in check.";
 
  100        JLOG(ctx.
j.
warn()) << 
"Cashing a check that has already expired.";
 
  108            auto const optAmount = tx[~sfAmount];
 
  109            return optAmount ? *optAmount : tx[sfDeliverMin];
 
  112        STAmount const sendMax = sleCheck->at(sfSendMax);
 
  113        Currency const currency{value.getCurrency()};
 
  116            JLOG(ctx.
j.
warn()) << 
"Check cash does not match check currency.";
 
  119        AccountID const issuerId{value.getIssuer()};
 
  122            JLOG(ctx.
j.
warn()) << 
"Check cash does not match check issuer.";
 
  127            JLOG(ctx.
j.
warn()) << 
"Check cashed for more than check sendMax.";
 
  136                sleCheck->at(sfAccount),
 
  148            if (value > availableFunds)
 
  151                    << 
"Check cashed for more than owner's balance.";
 
  157        if (!value.native() && (value.getIssuer() != dstId))
 
  159            auto const sleTrustLine =
 
  166                    << 
"Cannot cash check for IOU without trustline.";
 
  174                    << 
"Can't receive IOUs from non-existent issuer: " 
  191                bool const canonical_gt(dstId > issuerId);
 
  193                bool const is_authorized(
 
  194                    sleTrustLine->at(sfFlags) &
 
  200                        << 
"Can't receive IOUs from issuer without auth.";
 
  213                JLOG(ctx.
j.
warn()) << 
"Cashing a check to a frozen trustline.";
 
 
  232        JLOG(
j_.
fatal()) << 
"Precheck did not verify check's existence.";
 
  237    AccountID const srcId{sleCheck->getAccountID(sfAccount)};
 
  243            << 
"Precheck did not verify source or destination's existence.";
 
  259    auto const optDeliverMin = 
ctx_.
tx[~sfDeliverMin];
 
  263        STAmount const sendMax = sleCheck->at(sfSendMax);
 
  284            if (srcLiquid < xrpDeliver)
 
  288                JLOG(
j_.
trace()) << 
"Cash Check: Insufficient XRP: " 
  289                                 << srcLiquid.getFullText() << 
" < " 
  290                                 << xrpDeliver.getFullText();
 
  316                                    optDeliverMin->issue(),
 
  322            Issue const& trustLineIssue = flowDeliver.issue();
 
  323            AccountID const issuer = flowDeliver.getIssuer();
 
  326            bool const destLow = issuer > 
account_;
 
  328            bool const checkCashMakesTrustLine =
 
  331            if (checkCashMakesTrustLine && !psb.
exists(trustLineKey))
 
  343                if (
std::uint32_t const ownerCount = {sleDst->at(sfOwnerCount)};
 
  346                    JLOG(
j_.
trace()) << 
"Trust line does not exist. " 
  347                                        "Insufficent reserve to create line.";
 
  352                Currency const currency = flowDeliver.getCurrency();
 
  353                STAmount initialBalance(flowDeliver.issue());
 
  390            auto const sleTrustLine = psb.
peek(trustLineKey);
 
  394            SF_AMOUNT const& tweakedLimit = destLow ? sfLowLimit : sfHighLimit;
 
  395            STAmount const savedLimit = sleTrustLine->at(tweakedLimit);
 
  399                [&psb, &trustLineKey, &tweakedLimit, &savedLimit]() {
 
  400                    if (
auto const sleTrustLine = psb.
peek(trustLineKey))
 
  401                        sleTrustLine->at(tweakedLimit) = savedLimit;
 
  404            if (checkCashMakesTrustLine)
 
  410                sleTrustLine->at(tweakedLimit) = bigAmount;
 
  414            auto const result = 
flow(
 
  421                static_cast<bool>(optDeliverMin),  
 
  425                sleCheck->getFieldAmount(sfSendMax),
 
  432                return result.result();
 
  438                if (result.actualAmountOut < *optDeliverMin)
 
  441                        << 
"flow did not produce DeliverMin.";
 
  444                if (!checkCashMakesTrustLine)
 
  451            if (checkCashMakesTrustLine)
 
  463            sleCheck->at(sfDestinationNode),
 
  468        JLOG(
j_.
fatal()) << 
"Unable to delete check from destination.";
 
  476            sleCheck->at(sfOwnerNode),
 
  481        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.