20#include <xrpld/app/paths/Credit.h>
21#include <xrpld/app/paths/detail/AmountSpec.h>
22#include <xrpld/app/paths/detail/StepChecks.h>
23#include <xrpld/app/paths/detail/Steps.h>
24#include <xrpld/ledger/PaymentSandbox.h>
26#include <xrpl/basics/Log.h>
27#include <xrpl/protocol/Feature.h>
28#include <xrpl/protocol/IOUAmount.h>
29#include <xrpl/protocol/Quality.h>
30#include <xrpl/protocol/XRPAmount.h>
32#include <boost/container/flat_set.hpp>
38template <
class TDerived>
40 :
public StepImp<XRPAmount, XRPAmount, XRPEndpointStep<TDerived>>
106 boost::container::flat_set<uint256>& ofrsToRm,
113 boost::container::flat_set<uint256>& ofrsToRm,
135 ostr << name <<
": " <<
"\nAcc: " <<
acc_;
147 return !(lhs == rhs);
234template <
class TDerived>
243template <
class TDerived>
254template <
class TDerived>
259 boost::container::flat_set<uint256>& ofrsToRm,
262 auto const balance =
static_cast<TDerived const*
>(
this)->
xrpLiquid(sb);
267 auto& receiver = isLast_ ? acc_ :
xrpAccount();
272 cache_.emplace(result);
273 return {result, result};
276template <
class TDerived>
281 boost::container::flat_set<uint256>& ofrsToRm,
284 XRPL_ASSERT(cache_,
"ripple::XRPEndpointStep::fwdImp : cache is set");
285 auto const balance =
static_cast<TDerived const*
>(
this)->
xrpLiquid(sb);
287 auto const result = isLast_ ?
in :
std::min(balance,
in);
290 auto& receiver = isLast_ ? acc_ :
xrpAccount();
295 cache_.emplace(result);
296 return {result, result};
299template <
class TDerived>
308 JLOG(j_.
error()) <<
"Expected valid cache in validFwd";
312 XRPL_ASSERT(
in.native,
"ripple::XRPEndpointStep::validFwd : input is XRP");
314 auto const& xrpIn =
in.xrp;
315 auto const balance =
static_cast<TDerived const*
>(
this)->
xrpLiquid(sb);
317 if (!isLast_ && balance < xrpIn)
319 JLOG(j_.
warn()) <<
"XRPEndpointStep: Strand re-execute check failed."
320 <<
" Insufficient balance: " <<
to_string(balance)
325 if (xrpIn != *cache_)
327 JLOG(j_.
warn()) <<
"XRPEndpointStep: Strand re-execute check failed."
334template <
class TDerived>
340 JLOG(j_.
debug()) <<
"XRPEndpointStep: specified bad account.";
347 JLOG(j_.
warn()) <<
"XRPEndpointStep: can't send or receive XRP from "
348 "non-existent account: "
366 auto const issuesIndex = isLast_ ? 0 : 1;
370 <<
"XRPEndpointStep: loop detected: Index: " << ctx.
strandSize
389 return xs->acc() == acc;
404 auto offerCrossingStep =
405 std::make_unique<XRPEndpointOfferCrossingStep>(ctx, acc);
406 ter = offerCrossingStep->check(ctx);
407 r = std::move(offerCrossingStep);
411 auto paymentStep = std::make_unique<XRPEndpointPaymentStep>(ctx, acc);
412 ter = paymentStep->check(ctx);
413 r = std::move(paymentStep);
416 return {ter,
nullptr};
A generic endpoint for log messages.
Writeable view to a ledger, for applying a transaction.
A wrapper which makes credits unavailable to balances.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
static std::uint64_t const uRateOne
A step in a payment path.
std::int32_t const reserveReduction_
std::string logString() const override
XRPAmount xrpLiquid(ReadView &sb) const
static std::int32_t computeReserveReduction(StrandContext const &ctx, AccountID const &acc)
XRPEndpointOfferCrossingStep(StrandContext const &ctx, AccountID const &acc)
XRPAmount xrpLiquid(ReadView &sb) const
std::string logString() const override
std::optional< EitherAmount > cachedIn() const override
std::string logStringImpl(char const *name) const
TER check(StrandContext const &ctx) const
std::optional< XRPAmount > cache_
friend bool operator==(XRPEndpointStep< P > const &lhs, XRPEndpointStep< P > const &rhs)
std::pair< XRPAmount, XRPAmount > revImp(PaymentSandbox &sb, ApplyView &afView, boost::container::flat_set< uint256 > &ofrsToRm, XRPAmount const &out)
std::pair< XRPAmount, XRPAmount > fwdImp(PaymentSandbox &sb, ApplyView &afView, boost::container::flat_set< uint256 > &ofrsToRm, XRPAmount const &in)
friend bool operator!=(XRPEndpointStep const &lhs, XRPEndpointStep const &rhs)
std::pair< bool, EitherAmount > validFwd(PaymentSandbox &sb, ApplyView &afView, EitherAmount const &in) override
std::optional< std::pair< AccountID, AccountID > > directStepAccts() const override
std::optional< EitherAmount > cached() const
XRPAmount xrpLiquidImpl(ReadView &sb, std::int32_t reserveReduction) const
std::optional< EitherAmount > cachedOut() const override
XRPEndpointStep(StrandContext const &ctx, AccountID const &acc)
DebtDirection debtDirection(ReadView const &sb, StrandDirection dir) const override
AccountID const & acc() const
bool equal(Step const &rhs) const override
std::pair< std::optional< Quality >, DebtDirection > qualityUpperBound(ReadView const &v, DebtDirection prevStepDir) const override
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.
bool xrpEndpointStepEqual(Step const &step, AccountID const &acc)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
AccountID const & xrpAccount()
Compute AccountID from public key.
std::pair< TER, std::unique_ptr< Step > > make_XRPEndpointStep(StrandContext const &ctx, AccountID const &acc)
TER checkFreeze(ReadView const &view, AccountID const &src, AccountID const &dst, Currency const ¤cy)
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
Currency const & xrpCurrency()
XRP currency.
std::string to_string(base_uint< Bits, Tag > const &a)
constexpr bool operator==(base_uint< Bits, Tag > const &lhs, base_uint< Bits, Tag > const &rhs)
TER accountSend(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee)
Calls static accountSendIOU if saAmount represents Issue.
XRPAmount xrpLiquid(ReadView const &view, AccountID const &id, std::int32_t ownerCountAdj, beast::Journal j)
Context needed to build Strand Steps and for error checking.
size_t const strandSize
Length of Strand.
ReadView const & view
Current ReadView.
std::array< boost::container::flat_set< Issue >, 2 > & seenDirectIssues
A strand may not include the same account node more than once in the same currency.
OfferCrossing const offerCrossing
Yes/Sell if offer crossing, not payment.
bool const isFirst
true if Step is first in Strand
bool const isLast
true if Step is last in Strand
Issue const strandDeliver
Issue strand delivers.