xrpld
Loading...
Searching...
No Matches
Steps.h
1#pragma once
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/base_uint.h>
5#include <xrpl/protocol/Concepts.h>
6#include <xrpl/protocol/Quality.h>
7#include <xrpl/protocol/QualityFunction.h>
8#include <xrpl/protocol/TER.h>
9#include <xrpl/tx/paths/detail/EitherAmount.h>
10
11#include <boost/container/flat_set.hpp>
12
13#include <optional>
14
15namespace xrpl {
16class PaymentSandbox;
17class ReadView;
18class ApplyView;
19class AMMContext;
20
22enum class QualityDirection { In, Out };
24enum class OfferCrossing { No = 0, Yes = 1, Sell = 2 };
25
26inline bool
28{
29 return dir == DebtDirection::Redeems;
30}
31
32inline bool
34{
35 return dir == DebtDirection::Issues;
36}
37
65class Step
66{
67public:
68 virtual ~Step() = default;
69
84 ApplyView& afView,
85 boost::container::flat_set<uint256>& ofrsToRm,
86 EitherAmount const& out) = 0;
87
102 ApplyView& afView,
103 boost::container::flat_set<uint256>& ofrsToRm,
104 EitherAmount const& in) = 0;
105
110 [[nodiscard]] virtual std::optional<EitherAmount>
111 cachedIn() const = 0;
112
117 [[nodiscard]] virtual std::optional<EitherAmount>
118 cachedOut() const = 0;
119
124 [[nodiscard]] virtual std::optional<AccountID>
126 {
127 return std::nullopt;
128 }
129
130 // for debugging. Return the src and dst accounts for a direct step
131 // For XRP endpoints, one of src or dst will be the root account
134 {
135 return std::nullopt;
136 }
137
146 [[nodiscard]] virtual DebtDirection
147 debtDirection(ReadView const& sb, StrandDirection dir) const = 0;
148
152 [[nodiscard]] virtual std::uint32_t
154 {
155 return QUALITY_ONE;
156 }
157
171 [[nodiscard]] virtual std::pair<std::optional<Quality>, DebtDirection>
172 qualityUpperBound(ReadView const& v, DebtDirection prevStepDir) const = 0;
173
182 getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const;
183
191 [[nodiscard]] virtual std::uint32_t
193 {
194 return 0;
195 }
196
200 [[nodiscard]] virtual std::optional<Book>
202 {
203 return std::nullopt;
204 }
205
209 [[nodiscard]] virtual bool
210 isZero(EitherAmount const& out) const = 0;
211
217 [[nodiscard]] virtual bool
218 inactive() const
219 {
220 return false;
221 }
222
226 [[nodiscard]] virtual bool
227 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
228
232 [[nodiscard]] virtual bool
233 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
234
246 validFwd(PaymentSandbox& sb, ApplyView& afView, EitherAmount const& in) = 0;
247
254 friend bool
255 operator==(Step const& lhs, Step const& rhs)
256 {
257 return lhs.equal(rhs);
258 }
259
266 friend bool
267 operator!=(Step const& lhs, Step const& rhs)
268 {
269 return !(lhs == rhs);
270 }
271
274 operator<<(std::ostream& stream, Step const& step)
275 {
276 stream << step.logString();
277 return stream;
278 }
279
280private:
281 [[nodiscard]] virtual std::string
282 logString() const = 0;
283
284 [[nodiscard]] virtual bool
285 equal(Step const& rhs) const = 0;
286};
287
289Step::getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const
290{
291 auto const res = qualityUpperBound(v, prevStepDir);
292 if (res.first)
293 return {QualityFunction{*res.first, QualityFunction::CLOBLikeTag{}}, res.second};
294 return {std::nullopt, res.second};
295}
296
299
300inline std::uint32_t
301offersUsed(Strand const& strand)
302{
303 std::uint32_t r = 0;
304 for (auto const& step : strand)
305 {
306 if (step)
307 r += step->offersUsed();
308 }
309 return r;
310}
312
314inline bool
315operator==(Strand const& lhs, Strand const& rhs)
316{
317 if (lhs.size() != rhs.size())
318 return false;
319 for (size_t i = 0, e = lhs.size(); i != e; ++i)
320 {
321 if (*lhs[i] != *rhs[i])
322 return false;
323 }
324 return true;
325}
327
328/*
329 Normalize a path by inserting implied accounts and offers
330
331 @param src Account that is sending assets
332 @param dst Account that is receiving assets
333 @param deliver Asset the dst account will receive
334 (if issuer of deliver == dst, then accept any issuer)
335 @param sendMax Optional asset to send.
336 @param path Liquidity sources to use for this strand of the payment. The path
337 contains an ordered collection of the offer books to use and
338 accounts to ripple through.
339 @return error code and normalized path
340*/
341std::pair<TER, STPath>
343 AccountID const& src,
344 AccountID const& dst,
345 Asset const& deliver,
346 std::optional<Asset> const& sendMaxAsset,
347 STPath const& path);
348
375 ReadView const& sb,
376 AccountID const& src,
377 AccountID const& dst,
378 Asset const& deliver,
379 std::optional<Quality> const& limitQuality,
380 std::optional<Asset> const& sendMaxAsset,
381 STPath const& path,
382 bool ownerPaysTransferFee,
383 OfferCrossing offerCrossing,
384 AMMContext& ammContext,
385 std::optional<uint256> const& domainID,
387
416 ReadView const& sb,
417 AccountID const& src,
418 AccountID const& dst,
419 Asset const& deliver,
420 std::optional<Quality> const& limitQuality,
421 std::optional<Asset> const& sendMax,
422 STPathSet const& paths,
423 bool addDefaultPath,
424 bool ownerPaysTransferFee,
425 OfferCrossing offerCrossing,
426 AMMContext& ammContext,
427 std::optional<uint256> const& domainID,
429
431template <StepAmount TIn, StepAmount TOut, class TDerived>
432struct StepImp : public Step
433{
434private:
435 explicit StepImp() = default;
436
437public:
439 rev(PaymentSandbox& sb,
440 ApplyView& afView,
441 boost::container::flat_set<uint256>& ofrsToRm,
442 EitherAmount const& out) override
443 {
444 auto const r = static_cast<TDerived*>(this)->revImp(sb, afView, ofrsToRm, get<TOut>(out));
445 return {EitherAmount(r.first), EitherAmount(r.second)};
446 }
447
448 // Given the requested amount to consume, compute the amount produced.
449 // Return the consumed/produced
450 std::pair<EitherAmount, EitherAmount>
451 fwd(PaymentSandbox& sb,
452 ApplyView& afView,
453 boost::container::flat_set<uint256>& ofrsToRm,
454 EitherAmount const& in) override
455 {
456 auto const r = static_cast<TDerived*>(this)->fwdImp(sb, afView, ofrsToRm, get<TIn>(in));
457 return {EitherAmount(r.first), EitherAmount(r.second)};
458 }
459
460 [[nodiscard]] bool
461 isZero(EitherAmount const& out) const override
462 {
463 return get<TOut>(out) == beast::kZero;
464 }
465
466 [[nodiscard]] bool
467 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const override
468 {
469 return get<TOut>(lhs) == get<TOut>(rhs);
470 }
471
472 [[nodiscard]] bool
473 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const override
474 {
475 return get<TIn>(lhs) == get<TIn>(rhs);
476 }
477 friend TDerived;
478};
480
482// Thrown when unexpected errors occur
483class FlowException : public std::runtime_error
484{
485public:
486 TER ter;
487
488 FlowException(TER t, std::string const& msg) : std::runtime_error(msg), ter(t)
489 {
490 }
491
492 explicit FlowException(TER t) : std::runtime_error(transHuman(t)), ter(t)
493 {
494 }
495};
497
499// Check equal with tolerance
500bool
501checkNear(IOUAmount const& expected, IOUAmount const& actual);
502inline bool
503checkNear(MPTAmount const& expected, MPTAmount const& actual)
504{
505 return expected == actual;
506}
507inline bool
508checkNear(XRPAmount const& expected, XRPAmount const& actual)
509{
510 return expected == actual;
511}
513
518{
519 ReadView const& view;
524 bool const isFirst;
525 bool const isLast = false;
528 bool const isDefaultPath;
529 size_t const strandSize;
533 Step const* const prevStep = nullptr;
543 boost::container::flat_set<Asset>& seenBookOuts;
545 std::optional<uint256> domainID; // the domain the order book will use
547
550 ReadView const& view,
551 std::vector<std::unique_ptr<Step>> const& strand,
552 // A strand may not include an inner node that
553 // replicates the source or destination.
554 AccountID const& strandSrc,
555 AccountID const& strandDst,
556 Asset const& strandDeliver,
558 bool isLast,
561 bool isDefaultPath,
562 std::array<boost::container::flat_set<Asset>, 2>&
564 boost::container::flat_set<Asset>& seenBookOuts,
568};
569
571namespace test {
572// Needed for testing
573bool
575 Step const& step,
576 AccountID const& src,
577 AccountID const& dst,
578 Currency const& currency);
579
580bool
582 Step const& step,
583 AccountID const& src,
584 AccountID const& dst,
585 MPTID const& mptid);
586
587bool
588xrpEndpointStepEqual(Step const& step, AccountID const& acc);
589
590bool
591bookStepEqual(Step const& step, xrpl::Book const& book);
592} // namespace test
593
596 StrandContext const& ctx,
597 AccountID const& src,
598 AccountID const& dst,
599 Currency const& c);
600
603 StrandContext const& ctx,
604 AccountID const& src,
605 AccountID const& dst,
606 MPTID const& a);
607
609makeBookStepIi(StrandContext const& ctx, Issue const& in, Issue const& out);
610
612makeBookStepIx(StrandContext const& ctx, Issue const& in);
613
615makeBookStepXi(StrandContext const& ctx, Issue const& out);
616
618makeXrpEndpointStep(StrandContext const& ctx, AccountID const& acc);
619
621makeBookStepMm(StrandContext const& ctx, MPTIssue const& in, MPTIssue const& out);
622
624makeBookStepMx(StrandContext const& ctx, MPTIssue const& in);
625
627makeBookStepXm(StrandContext const& ctx, MPTIssue const& out);
628
630makeBookStepMi(StrandContext const& ctx, MPTIssue const& in, Issue const& out);
631
633makeBookStepIm(StrandContext const& ctx, Issue const& in, MPTIssue const& out);
634
635template <StepAmount InAmt, StepAmount OutAmt>
636bool
637isDirectXrpToXrp(Strand const& strand)
638{
640 {
641 return strand.size() == 2;
642 }
643 else
644 {
645 return false;
646 }
647}
649
650} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:38
Maintains AMM info per overall payment engine execution and individual iteration.
Definition AMMContext.h:16
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:118
Specifies an order book.
Definition Book.h:16
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:24
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:31
A step in a payment path.
Definition Steps.h:66
virtual std::optional< EitherAmount > cachedIn() const =0
Amount of currency computed coming into the Step the last time the step ran in reverse.
virtual std::pair< std::optional< Quality >, DebtDirection > qualityUpperBound(ReadView const &v, DebtDirection prevStepDir) const =0
Find an upper bound of quality for the step.
virtual std::optional< AccountID > directStepSrcAcct() const
If this step is DirectStepI (IOU->IOU direct step), return the src account.
Definition Steps.h:125
virtual std::string logString() const =0
virtual std::optional< std::pair< AccountID, AccountID > > directStepAccts() const
Definition Steps.h:133
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 std::uint32_t offersUsed() const
Return the number of offers consumed or partially consumed the last time the step ran,...
Definition Steps.h:192
friend bool operator!=(Step const &lhs, Step const &rhs)
Return true if lhs != rhs.
Definition Steps.h:267
virtual std::pair< std::optional< QualityFunction >, DebtDirection > getQualityFunc(ReadView const &v, DebtDirection prevStepDir) const
Get QualityFunction.
Definition Steps.h:289
virtual bool inactive() const
Return true if the step should be considered inactive.
Definition Steps.h:218
friend bool operator==(Step const &lhs, Step const &rhs)
Return true if lhs == rhs.
Definition Steps.h:255
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 bool equalOut(EitherAmount const &lhs, EitherAmount const &rhs) const =0
Return true if Out of lhs == Out of rhs.
virtual std::optional< Book > bookStepBook() const
If this step is a BookStep, return the book.
Definition Steps.h:201
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.
friend std::ostream & operator<<(std::ostream &stream, Step const &step)
Streaming operator for a Step.
Definition Steps.h:274
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:153
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 bool equalIn(EitherAmount const &lhs, EitherAmount const &rhs) const =0
Return true if In of lhs == In of rhs.
virtual bool equal(Step const &rhs) const =0
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 isZero(EitherAmount const &out) const =0
Check if amount is zero.
T is_same_v
bool bookStepEqual(Step const &step, xrpl::Book const &book)
bool xrpEndpointStepEqual(Step const &step, AccountID const &acc)
bool mptEndpointStepEqual(Step const &step, AccountID const &src, AccountID const &dst, MPTID const &mptid)
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:5
std::pair< TER, std::unique_ptr< Step > > makeXrpEndpointStep(StrandContext const &ctx, AccountID const &acc)
std::pair< TER, std::vector< Strand > > toStrands(ReadView const &sb, AccountID const &src, AccountID const &dst, Asset const &deliver, std::optional< Quality > const &limitQuality, std::optional< Asset > 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:574
constexpr bool operator==(BaseUInt< Bits, Tag > const &lhs, BaseUInt< Bits, Tag > const &rhs)
Definition base_uint.h:588
std::pair< TER, std::unique_ptr< Step > > makeDirectStepI(StrandContext const &ctx, AccountID const &src, AccountID const &dst, Currency const &c)
std::pair< TER, std::unique_ptr< Step > > makeBookStepIi(StrandContext const &ctx, Issue const &in, Issue const &out)
T get(Section const &section, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
std::pair< TER, Strand > toStrand(ReadView const &sb, AccountID const &src, AccountID const &dst, Asset const &deliver, std::optional< Quality > const &limitQuality, std::optional< Asset > const &sendMaxAsset, 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:170
std::pair< TER, std::unique_ptr< Step > > makeBookStepMx(StrandContext const &ctx, MPTIssue const &in)
bool issues(DebtDirection dir)
Definition Steps.h:33
std::pair< TER, std::unique_ptr< Step > > makeMptEndpointStep(StrandContext const &ctx, AccountID const &src, AccountID const &dst, MPTID const &mpt)
BaseUInt< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition UintTypes.h:36
std::string transHuman(TER code)
Definition TER.cpp:256
std::pair< TER, std::unique_ptr< Step > > makeBookStepMi(StrandContext const &ctx, MPTIssue const &in, Issue const &out)
std::pair< TER, STPath > normalizePath(AccountID const &src, AccountID const &dst, Asset const &deliver, std::optional< Asset > const &sendMaxAsset, STPath const &path)
DebtDirection
Definition Steps.h:21
std::pair< TER, std::unique_ptr< Step > > makeBookStepIx(StrandContext const &ctx, Issue const &in)
StrandDirection
Definition Steps.h:23
QualityDirection
Definition Steps.h:22
std::pair< TER, std::unique_ptr< Step > > makeBookStepXm(StrandContext const &ctx, MPTIssue const &out)
BaseUInt< 192 > MPTID
MPTID is a 192-bit value representing MPT Issuance ID, which is a concatenation of a 32-bit sequence ...
Definition UintTypes.h:44
std::pair< TER, std::unique_ptr< Step > > makeBookStepXi(StrandContext const &ctx, Issue const &out)
bool checkNear(IOUAmount const &expected, IOUAmount const &actual)
Definition PaySteps.cpp:36
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:28
std::pair< TER, std::unique_ptr< Step > > makeBookStepIm(StrandContext const &ctx, Issue const &in, MPTIssue const &out)
TERSubset< CanCvtToTER > TER
Definition TER.h:634
bool redeems(DebtDirection dir)
Definition Steps.h:27
OfferCrossing
Definition Steps.h:24
std::pair< TER, std::unique_ptr< Step > > makeBookStepMm(StrandContext const &ctx, MPTIssue const &in, MPTIssue const &out)
beast::Journal const j
Definition Steps.h:546
StrandContext(ReadView const &view, std::vector< std::unique_ptr< Step > > const &strand, AccountID const &strandSrc, AccountID const &strandDst, Asset const &strandDeliver, std::optional< Quality > const &limitQuality, bool isLast, bool ownerPaysTransferFee, OfferCrossing offerCrossing, bool isDefaultPath, std::array< boost::container::flat_set< Asset >, 2 > &seenDirectAssets, boost::container::flat_set< Asset > &seenBookOuts, AMMContext &ammContext, std::optional< uint256 > const &domainID, beast::Journal j)
StrandContext constructor.
Definition PaySteps.cpp:686
Asset const strandDeliver
Asset strand delivers.
Definition Steps.h:522
std::optional< uint256 > domainID
Definition Steps.h:545
AMMContext & ammContext
Definition Steps.h:544
std::optional< Quality > const limitQuality
Worst accepted quality.
Definition Steps.h:523
size_t const strandSize
Length of Strand.
Definition Steps.h:529
ReadView const & view
Current ReadView.
Definition Steps.h:519
bool const isFirst
true if Step is first in Strand
Definition Steps.h:524
std::array< boost::container::flat_set< Asset >, 2 > & seenDirectAssets
A strand may not include the same account node more than once in the same currency.
Definition Steps.h:539
AccountID const strandSrc
Strand source account.
Definition Steps.h:520
bool const ownerPaysTransferFee
true if owner, not sender, pays fee
Definition Steps.h:526
bool const isLast
true if Step is last in Strand
Definition Steps.h:525
bool const isDefaultPath
true if Strand is default path
Definition Steps.h:528
boost::container::flat_set< Asset > & seenBookOuts
A strand may not include an offer that output the same issue more than once.
Definition Steps.h:543
AccountID const strandDst
Strand destination account.
Definition Steps.h:521
Step const *const prevStep
The previous step in the strand.
Definition Steps.h:533
OfferCrossing const offerCrossing
Yes/Sell if offer crossing, not payment.
Definition Steps.h:527