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>
25#include <xrpl/basics/Log.h>
26#include <xrpl/protocol/Feature.h>
27#include <xrpl/protocol/IOUAmount.h>
28#include <xrpl/protocol/Quality.h>
29#include <xrpl/protocol/XRPAmount.h>
31#include <boost/container/flat_set.hpp>
37template <
class TDerived>
39 :
public StepImp<XRPAmount, XRPAmount, XRPEndpointStep<TDerived>>
105 boost::container::flat_set<uint256>& ofrsToRm,
112 boost::container::flat_set<uint256>& ofrsToRm,
134 ostr << name <<
": " <<
"\nAcc: " <<
acc_;
146 return !(lhs == rhs);
233template <
class TDerived>
242template <
class TDerived>
253template <
class TDerived>
258 boost::container::flat_set<uint256>& ofrsToRm,
261 auto const balance =
static_cast<TDerived const*
>(
this)->
xrpLiquid(sb);
266 auto& receiver = isLast_ ? acc_ :
xrpAccount();
271 cache_.emplace(result);
272 return {result, result};
275template <
class TDerived>
280 boost::container::flat_set<uint256>& ofrsToRm,
283 XRPL_ASSERT(cache_,
"ripple::XRPEndpointStep::fwdImp : cache is set");
284 auto const balance =
static_cast<TDerived const*
>(
this)->
xrpLiquid(sb);
286 auto const result = isLast_ ?
in :
std::min(balance,
in);
289 auto& receiver = isLast_ ? acc_ :
xrpAccount();
294 cache_.emplace(result);
295 return {result, result};
298template <
class TDerived>
307 JLOG(j_.
error()) <<
"Expected valid cache in validFwd";
311 XRPL_ASSERT(
in.native,
"ripple::XRPEndpointStep::validFwd : input is XRP");
313 auto const& xrpIn =
in.xrp;
314 auto const balance =
static_cast<TDerived const*
>(
this)->
xrpLiquid(sb);
316 if (!isLast_ && balance < xrpIn)
318 JLOG(j_.
warn()) <<
"XRPEndpointStep: Strand re-execute check failed."
319 <<
" Insufficient balance: " <<
to_string(balance)
324 if (xrpIn != *cache_)
326 JLOG(j_.
warn()) <<
"XRPEndpointStep: Strand re-execute check failed."
333template <
class TDerived>
339 JLOG(j_.
debug()) <<
"XRPEndpointStep: specified bad account.";
346 JLOG(j_.
warn()) <<
"XRPEndpointStep: can't send or receive XRP from "
347 "non-existent account: "
365 auto const issuesIndex = isLast_ ? 0 : 1;
369 <<
"XRPEndpointStep: loop detected: Index: " << ctx.
strandSize
388 return xs->acc() == acc;
403 auto offerCrossingStep =
404 std::make_unique<XRPEndpointOfferCrossingStep>(ctx, acc);
405 ter = offerCrossingStep->check(ctx);
406 r = std::move(offerCrossingStep);
410 auto paymentStep = std::make_unique<XRPEndpointPaymentStep>(ctx, acc);
411 ter = paymentStep->check(ctx);
412 r = std::move(paymentStep);
415 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.