rippled
Loading...
Searching...
No Matches
Steps.h
1#ifndef XRPL_APP_PATHS_IMPL_PAYSTEPS_H_INCLUDED
2#define XRPL_APP_PATHS_IMPL_PAYSTEPS_H_INCLUDED
3
4#include <xrpld/app/paths/detail/AmountSpec.h>
5
6#include <xrpl/basics/Log.h>
7#include <xrpl/basics/base_uint.h>
8#include <xrpl/protocol/Quality.h>
9#include <xrpl/protocol/QualityFunction.h>
10#include <xrpl/protocol/STLedgerEntry.h>
11#include <xrpl/protocol/TER.h>
12
13#include <boost/container/flat_set.hpp>
14
15#include <optional>
16
17namespace ripple {
18class PaymentSandbox;
19class ReadView;
20class ApplyView;
21class AMMContext;
22
24enum class QualityDirection { in, out };
26enum OfferCrossing { no = 0, yes = 1, sell = 2 };
27
28inline bool
30{
31 return dir == DebtDirection::redeems;
32}
33
34inline bool
36{
37 return dir == DebtDirection::issues;
38}
39
66class Step
67{
68public:
69 virtual ~Step() = default;
70
85 ApplyView& afView,
86 boost::container::flat_set<uint256>& ofrsToRm,
87 EitherAmount const& out) = 0;
88
103 ApplyView& afView,
104 boost::container::flat_set<uint256>& ofrsToRm,
105 EitherAmount const& in) = 0;
106
112 cachedIn() const = 0;
113
119 cachedOut() const = 0;
120
127 {
128 return std::nullopt;
129 }
130
131 // for debugging. Return the src and dst accounts for a direct step
132 // For XRP endpoints, one of src or dst will be the root account
135 {
136 return std::nullopt;
137 }
138
147 virtual DebtDirection
148 debtDirection(ReadView const& sb, StrandDirection dir) const = 0;
149
153 virtual std::uint32_t
155 {
156 return QUALITY_ONE;
157 }
158
159 // clang-format off
174 // clang-format on
176 qualityUpperBound(ReadView const& v, DebtDirection prevStepDir) const = 0;
177
186 getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const;
187
195 virtual std::uint32_t
197 {
198 return 0;
199 }
200
204 virtual std::optional<Book>
206 {
207 return std::nullopt;
208 }
209
213 virtual bool
214 isZero(EitherAmount const& out) const = 0;
215
221 virtual bool
222 inactive() const
223 {
224 return false;
225 }
226
230 virtual bool
231 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
232
236 virtual bool
237 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
238
251
258 friend bool
259 operator==(Step const& lhs, Step const& rhs)
260 {
261 return lhs.equal(rhs);
262 }
263
270 friend bool
271 operator!=(Step const& lhs, Step const& rhs)
272 {
273 return !(lhs == rhs);
274 }
275
278 operator<<(std::ostream& stream, Step const& step)
279 {
280 stream << step.logString();
281 return stream;
282 }
283
284private:
285 virtual std::string
286 logString() const = 0;
287
288 virtual bool
289 equal(Step const& rhs) const = 0;
290};
291
293Step::getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const
294{
295 if (auto const res = qualityUpperBound(v, prevStepDir); res.first)
296 return {
298 res.second};
299 else
300 return {std::nullopt, res.second};
301}
302
305
306inline std::uint32_t
307offersUsed(Strand const& strand)
308{
309 std::uint32_t r = 0;
310 for (auto const& step : strand)
311 {
312 if (step)
313 r += step->offersUsed();
314 }
315 return r;
316}
318
320inline bool
321operator==(Strand const& lhs, Strand const& rhs)
322{
323 if (lhs.size() != rhs.size())
324 return false;
325 for (size_t i = 0, e = lhs.size(); i != e; ++i)
326 if (*lhs[i] != *rhs[i])
327 return false;
328 return true;
329}
331
332/*
333 Normalize a path by inserting implied accounts and offers
334
335 @param src Account that is sending assets
336 @param dst Account that is receiving assets
337 @param deliver Asset the dst account will receive
338 (if issuer of deliver == dst, then accept any issuer)
339 @param sendMax Optional asset to send.
340 @param path Liquidity sources to use for this strand of the payment. The path
341 contains an ordered collection of the offer books to use and
342 accounts to ripple through.
343 @return error code and normalized path
344*/
347 AccountID const& src,
348 AccountID const& dst,
349 Issue const& deliver,
350 std::optional<Issue> const& sendMaxIssue,
351 STPath const& path);
352
379 ReadView const& sb,
380 AccountID const& src,
381 AccountID const& dst,
382 Issue const& deliver,
383 std::optional<Quality> const& limitQuality,
384 std::optional<Issue> const& sendMaxIssue,
385 STPath const& path,
386 bool ownerPaysTransferFee,
387 OfferCrossing offerCrossing,
388 AMMContext& ammContext,
389 std::optional<uint256> const& domainID,
391
420 ReadView const& sb,
421 AccountID const& src,
422 AccountID const& dst,
423 Issue const& deliver,
424 std::optional<Quality> const& limitQuality,
425 std::optional<Issue> const& sendMax,
426 STPathSet const& paths,
427 bool addDefaultPath,
428 bool ownerPaysTransferFee,
429 OfferCrossing offerCrossing,
430 AMMContext& ammContext,
431 std::optional<uint256> const& domainID,
433
435template <class TIn, class TOut, class TDerived>
436struct StepImp : public Step
437{
438 explicit StepImp() = default;
439
441 rev(PaymentSandbox& sb,
442 ApplyView& afView,
443 boost::container::flat_set<uint256>& ofrsToRm,
444 EitherAmount const& out) override
445 {
446 auto const r = static_cast<TDerived*>(this)->revImp(
447 sb, afView, ofrsToRm, get<TOut>(out));
448 return {EitherAmount(r.first), EitherAmount(r.second)};
449 }
450
451 // Given the requested amount to consume, compute the amount produced.
452 // Return the consumed/produced
454 fwd(PaymentSandbox& sb,
455 ApplyView& afView,
456 boost::container::flat_set<uint256>& ofrsToRm,
457 EitherAmount const& in) override
458 {
459 auto const r = static_cast<TDerived*>(this)->fwdImp(
460 sb, afView, ofrsToRm, get<TIn>(in));
461 return {EitherAmount(r.first), EitherAmount(r.second)};
462 }
463
464 bool
465 isZero(EitherAmount const& out) const override
466 {
467 return get<TOut>(out) == beast::zero;
468 }
469
470 bool
471 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const override
472 {
473 return get<TOut>(lhs) == get<TOut>(rhs);
474 }
475
476 bool
477 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const override
478 {
479 return get<TIn>(lhs) == get<TIn>(rhs);
480 }
481};
483
485// Thrown when unexpected errors occur
486class FlowException : public std::runtime_error
487{
488public:
489 TER ter;
490
491 FlowException(TER t, std::string const& msg)
492 : std::runtime_error(msg), ter(t)
493 {
494 }
495
496 explicit FlowException(TER t) : std::runtime_error(transHuman(t)), ter(t)
497 {
498 }
499};
501
503// Check equal with tolerance
504bool
505checkNear(IOUAmount const& expected, IOUAmount const& actual);
506bool
507checkNear(XRPAmount const& expected, XRPAmount const& actual);
509
514{
515 ReadView const& view;
520 bool const isFirst;
521 bool const isLast = false;
523 OfferCrossing const
525 bool const isDefaultPath;
526 size_t const strandSize;
530 Step const* const prevStep = nullptr;
540 boost::container::flat_set<Issue>& seenBookOuts;
542 std::optional<uint256> domainID; // the domain the order book will use
544
547 ReadView const& view_,
548 std::vector<std::unique_ptr<Step>> const& strand_,
549 // A strand may not include an inner node that
550 // replicates the source or destination.
551 AccountID const& strandSrc_,
552 AccountID const& strandDst_,
553 Issue const& strandDeliver_,
554 std::optional<Quality> const& limitQuality_,
555 bool isLast_,
556 bool ownerPaysTransferFee_,
557 OfferCrossing offerCrossing_,
558 bool isDefaultPath_,
559 std::array<boost::container::flat_set<Issue>, 2>&
560 seenDirectIssues_,
561 boost::container::flat_set<Issue>&
562 seenBookOuts_,
563 AMMContext& ammContext_,
565 beast::Journal j_);
566};
567
569namespace test {
570// Needed for testing
571bool
573 Step const& step,
574 AccountID const& src,
575 AccountID const& dst,
576 Currency const& currency);
577
578bool
579xrpEndpointStepEqual(Step const& step, AccountID const& acc);
580
581bool
582bookStepEqual(Step const& step, ripple::Book const& book);
583} // namespace test
584
587 StrandContext const& ctx,
588 AccountID const& src,
589 AccountID const& dst,
590 Currency const& c);
591
593make_BookStepII(StrandContext const& ctx, Issue const& in, Issue const& out);
594
596make_BookStepIX(StrandContext const& ctx, Issue const& in);
597
599make_BookStepXI(StrandContext const& ctx, Issue const& out);
600
602make_XRPEndpointStep(StrandContext const& ctx, AccountID const& acc);
603
604template <class InAmt, class OutAmt>
605bool
606isDirectXrpToXrp(Strand const& strand);
608
609} // namespace ripple
610
611#endif
A generic endpoint for log messages.
Definition Journal.h:41
Maintains AMM info per overall payment engine execution and individual iteration.
Definition AMMContext.h:17
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:124
Specifies an order book.
Definition Book.h:17
A currency issued by an account.
Definition Issue.h:14
A wrapper which makes credits unavailable to balances.
Average quality of a path as a function of out: q(out) = m * out + b, where m = -1 / poolGets,...
A view into a ledger.
Definition ReadView.h:32
A step in a payment path.
Definition Steps.h:67
virtual std::uint32_t lineQualityIn(ReadView const &) const
If this step is a DirectStepI, return the quality in of the dst account.
Definition Steps.h:154
virtual DebtDirection debtDirection(ReadView const &sb, StrandDirection dir) const =0
If this step is a DirectStepI and the src redeems to the dst, return true, otherwise return false.
virtual bool equal(Step const &rhs) const =0
virtual std::optional< EitherAmount > cachedIn() const =0
Amount of currency computed coming into the Step the last time the step ran in reverse.
virtual ~Step()=default
virtual std::optional< EitherAmount > cachedOut() const =0
Amount of currency computed coming out of the Step the last time the step ran in reverse.
virtual bool equalOut(EitherAmount const &lhs, EitherAmount const &rhs) const =0
Return true if Out of lhs == Out of rhs.
virtual std::pair< EitherAmount, EitherAmount > fwd(PaymentSandbox &sb, ApplyView &afView, boost::container::flat_set< uint256 > &ofrsToRm, EitherAmount const &in)=0
Find the amount we get out of the step given the input subject to liquidity limits.
virtual std::pair< std::optional< Quality >, DebtDirection > qualityUpperBound(ReadView const &v, DebtDirection prevStepDir) const =0
Find an upper bound of quality for the step.
friend bool operator!=(Step const &lhs, Step const &rhs)
Return true if lhs != rhs.
Definition Steps.h:271
virtual std::pair< EitherAmount, EitherAmount > rev(PaymentSandbox &sb, ApplyView &afView, boost::container::flat_set< uint256 > &ofrsToRm, EitherAmount const &out)=0
Find the amount we need to put into the step to get the requested out subject to liquidity limits.
virtual bool isZero(EitherAmount const &out) const =0
Check if amount is zero.
virtual bool inactive() const
Return true if the step should be considered inactive.
Definition Steps.h:222
virtual std::uint32_t offersUsed() const
Return the number of offers consumed or partially consumed the last time the step ran,...
Definition Steps.h:196
virtual std::pair< bool, EitherAmount > validFwd(PaymentSandbox &sb, ApplyView &afView, EitherAmount const &in)=0
Check that the step can correctly execute in the forward direction.
virtual std::optional< Book > bookStepBook() const
If this step is a BookStep, return the book.
Definition Steps.h:205
virtual std::optional< std::pair< AccountID, AccountID > > directStepAccts() const
Definition Steps.h:134
friend bool operator==(Step const &lhs, Step const &rhs)
Return true if lhs == rhs.
Definition Steps.h:259
friend std::ostream & operator<<(std::ostream &stream, Step const &step)
Streaming operator for a Step.
Definition Steps.h:278
virtual bool equalIn(EitherAmount const &lhs, EitherAmount const &rhs) const =0
Return true if In of lhs == In of rhs.
virtual std::string logString() const =0
virtual std::pair< std::optional< QualityFunction >, DebtDirection > getQualityFunc(ReadView const &v, DebtDirection prevStepDir) const
Get QualityFunction.
Definition Steps.h:293
virtual std::optional< AccountID > directStepSrcAcct() const
If this step is DirectStepI (IOU->IOU direct step), return the src account.
Definition Steps.h:126
T is_same_v
bool xrpEndpointStepEqual(Step const &step, AccountID const &acc)
bool bookStepEqual(Step const &step, ripple::Book const &book)
bool directStepEqual(Step const &step, AccountID const &src, AccountID const &dst, Currency const &currency)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:29
std::string transHuman(TER code)
Definition TER.cpp:254
std::pair< TER, std::unique_ptr< Step > > make_XRPEndpointStep(StrandContext const &ctx, AccountID const &acc)
StrandDirection
Definition Steps.h:25
OfferCrossing
Definition Steps.h:26
@ no
Definition Steps.h:26
@ yes
Definition Steps.h:26
@ sell
Definition Steps.h:26
QualityDirection
Definition Steps.h:24
std::pair< TER, std::unique_ptr< Step > > make_BookStepXI(StrandContext const &ctx, Issue const &out)
base_uint< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition UintTypes.h:37
DebtDirection
Definition Steps.h:23
std::pair< TER, std::unique_ptr< Step > > make_BookStepIX(StrandContext const &ctx, Issue const &in)
bool checkNear(IOUAmount const &expected, IOUAmount const &actual)
Definition PaySteps.cpp:15
std::pair< TER, std::unique_ptr< Step > > make_BookStepII(StrandContext const &ctx, Issue const &in, Issue const &out)
std::pair< TER, STPath > normalizePath(AccountID const &src, AccountID const &dst, Issue const &deliver, std::optional< Issue > const &sendMaxIssue, STPath const &path)
std::pair< TER, std::unique_ptr< Step > > make_DirectStepI(StrandContext const &ctx, AccountID const &src, AccountID const &dst, Currency const &c)
bool isDirectXrpToXrp(Strand const &strand)
Definition PaySteps.cpp:611
std::pair< TER, std::vector< Strand > > toStrands(ReadView const &view, AccountID const &src, AccountID const &dst, Issue const &deliver, std::optional< Quality > const &limitQuality, std::optional< Issue > const &sendMax, STPathSet const &paths, bool addDefaultPath, bool ownerPaysTransferFee, OfferCrossing offerCrossing, AMMContext &ammContext, std::optional< uint256 > const &domainID, beast::Journal j)
Create a Strand for each specified path (including the default path, if indicated)
Definition PaySteps.cpp:456
constexpr bool operator==(base_uint< Bits, Tag > const &lhs, base_uint< Bits, Tag > const &rhs)
Definition base_uint.h:566
TERSubset< CanCvtToTER > TER
Definition TER.h:630
std::pair< TER, Strand > toStrand(ReadView const &view, AccountID const &src, AccountID const &dst, Issue const &deliver, std::optional< Quality > const &limitQuality, std::optional< Issue > const &sendMaxIssue, STPath const &path, bool ownerPaysTransferFee, OfferCrossing offerCrossing, AMMContext &ammContext, std::optional< uint256 > const &domainID, beast::Journal j)
Create a Strand for the specified path.
Definition PaySteps.cpp:117
STL namespace.
Context needed to build Strand Steps and for error checking.
Definition Steps.h:514
bool const isDefaultPath
true if Strand is default path
Definition Steps.h:525
size_t const strandSize
Length of Strand.
Definition Steps.h:526
beast::Journal const j
Definition Steps.h:543
boost::container::flat_set< Issue > & seenBookOuts
A strand may not include an offer that output the same issue more than once.
Definition Steps.h:540
AccountID const strandSrc
Strand source account.
Definition Steps.h:516
ReadView const & view
Current ReadView.
Definition Steps.h:515
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.
Definition Steps.h:536
Step const *const prevStep
The previous step in the strand.
Definition Steps.h:530
bool const ownerPaysTransferFee
true if owner, not sender, pays fee
Definition Steps.h:522
AccountID const strandDst
Strand destination account.
Definition Steps.h:517
std::optional< uint256 > domainID
Definition Steps.h:542
OfferCrossing const offerCrossing
Yes/Sell if offer crossing, not payment.
Definition Steps.h:524
bool const isFirst
true if Step is first in Strand
Definition Steps.h:520
bool const isLast
true if Step is last in Strand
Definition Steps.h:521
std::optional< Quality > const limitQuality
Worst accepted quality.
Definition Steps.h:519
Issue const strandDeliver
Issue strand delivers.
Definition Steps.h:518
AMMContext & ammContext
Definition Steps.h:541