rippled
Loading...
Searching...
No Matches
Steps.h
1#pragma once
2
3#include <xrpld/app/paths/detail/AmountSpec.h>
4
5#include <xrpl/basics/Log.h>
6#include <xrpl/basics/base_uint.h>
7#include <xrpl/protocol/Quality.h>
8#include <xrpl/protocol/QualityFunction.h>
9#include <xrpl/protocol/STLedgerEntry.h>
10#include <xrpl/protocol/TER.h>
11
12#include <boost/container/flat_set.hpp>
13
14#include <optional>
15
16namespace xrpl {
17class PaymentSandbox;
18class ReadView;
19class ApplyView;
20class AMMContext;
21
23enum class QualityDirection { in, out };
25enum OfferCrossing { no = 0, yes = 1, sell = 2 };
26
27inline bool
29{
30 return dir == DebtDirection::redeems;
31}
32
33inline bool
35{
36 return dir == DebtDirection::issues;
37}
38
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
111 cachedIn() const = 0;
112
118 cachedOut() const = 0;
119
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 virtual DebtDirection
147 debtDirection(ReadView const& sb, StrandDirection dir) const = 0;
148
152 virtual std::uint32_t
154 {
155 return QUALITY_ONE;
156 }
157
158 // clang-format off
173 // clang-format on
175 qualityUpperBound(ReadView const& v, DebtDirection prevStepDir) const = 0;
176
185 getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const;
186
194 virtual std::uint32_t
196 {
197 return 0;
198 }
199
203 virtual std::optional<Book>
205 {
206 return std::nullopt;
207 }
208
212 virtual bool
213 isZero(EitherAmount const& out) const = 0;
214
220 virtual bool
221 inactive() const
222 {
223 return false;
224 }
225
229 virtual bool
230 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
231
235 virtual bool
236 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
237
250
257 friend bool
258 operator==(Step const& lhs, Step const& rhs)
259 {
260 return lhs.equal(rhs);
261 }
262
269 friend bool
270 operator!=(Step const& lhs, Step const& rhs)
271 {
272 return !(lhs == rhs);
273 }
274
277 operator<<(std::ostream& stream, Step const& step)
278 {
279 stream << step.logString();
280 return stream;
281 }
282
283private:
284 virtual std::string
285 logString() const = 0;
286
287 virtual bool
288 equal(Step const& rhs) const = 0;
289};
290
292Step::getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const
293{
294 if (auto const res = qualityUpperBound(v, prevStepDir); res.first)
295 return {QualityFunction{*res.first, QualityFunction::CLOBLikeTag{}}, res.second};
296 else
297 return {std::nullopt, res.second};
298}
299
302
303inline std::uint32_t
304offersUsed(Strand const& strand)
305{
306 std::uint32_t r = 0;
307 for (auto const& step : strand)
308 {
309 if (step)
310 r += step->offersUsed();
311 }
312 return r;
313}
315
317inline bool
318operator==(Strand const& lhs, Strand const& rhs)
319{
320 if (lhs.size() != rhs.size())
321 return false;
322 for (size_t i = 0, e = lhs.size(); i != e; ++i)
323 if (*lhs[i] != *rhs[i])
324 return false;
325 return true;
326}
328
329/*
330 Normalize a path by inserting implied accounts and offers
331
332 @param src Account that is sending assets
333 @param dst Account that is receiving assets
334 @param deliver Asset the dst account will receive
335 (if issuer of deliver == dst, then accept any issuer)
336 @param sendMax Optional asset to send.
337 @param path Liquidity sources to use for this strand of the payment. The path
338 contains an ordered collection of the offer books to use and
339 accounts to ripple through.
340 @return error code and normalized path
341*/
344 AccountID const& src,
345 AccountID const& dst,
346 Issue const& deliver,
347 std::optional<Issue> const& sendMaxIssue,
348 STPath const& path);
349
376 ReadView const& sb,
377 AccountID const& src,
378 AccountID const& dst,
379 Issue const& deliver,
380 std::optional<Quality> const& limitQuality,
381 std::optional<Issue> const& sendMaxIssue,
382 STPath const& path,
383 bool ownerPaysTransferFee,
384 OfferCrossing offerCrossing,
385 AMMContext& ammContext,
386 std::optional<uint256> const& domainID,
388
417 ReadView const& sb,
418 AccountID const& src,
419 AccountID const& dst,
420 Issue const& deliver,
421 std::optional<Quality> const& limitQuality,
422 std::optional<Issue> const& sendMax,
423 STPathSet const& paths,
424 bool addDefaultPath,
425 bool ownerPaysTransferFee,
426 OfferCrossing offerCrossing,
427 AMMContext& ammContext,
428 std::optional<uint256> const& domainID,
430
432template <class TIn, class TOut, class TDerived>
433struct StepImp : public Step
434{
435 explicit StepImp() = default;
436
438 rev(PaymentSandbox& sb,
439 ApplyView& afView,
440 boost::container::flat_set<uint256>& ofrsToRm,
441 EitherAmount const& out) override
442 {
443 auto const r = static_cast<TDerived*>(this)->revImp(sb, afView, ofrsToRm, get<TOut>(out));
444 return {EitherAmount(r.first), EitherAmount(r.second)};
445 }
446
447 // Given the requested amount to consume, compute the amount produced.
448 // Return the consumed/produced
450 fwd(PaymentSandbox& sb,
451 ApplyView& afView,
452 boost::container::flat_set<uint256>& ofrsToRm,
453 EitherAmount const& in) override
454 {
455 auto const r = static_cast<TDerived*>(this)->fwdImp(sb, afView, ofrsToRm, get<TIn>(in));
456 return {EitherAmount(r.first), EitherAmount(r.second)};
457 }
458
459 bool
460 isZero(EitherAmount const& out) const override
461 {
462 return get<TOut>(out) == beast::zero;
463 }
464
465 bool
466 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const override
467 {
468 return get<TOut>(lhs) == get<TOut>(rhs);
469 }
470
471 bool
472 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const override
473 {
474 return get<TIn>(lhs) == get<TIn>(rhs);
475 }
476};
478
480// Thrown when unexpected errors occur
481class FlowException : public std::runtime_error
482{
483public:
484 TER ter;
485
486 FlowException(TER t, std::string const& msg) : std::runtime_error(msg), ter(t)
487 {
488 }
489
490 explicit FlowException(TER t) : std::runtime_error(transHuman(t)), ter(t)
491 {
492 }
493};
495
497// Check equal with tolerance
498bool
499checkNear(IOUAmount const& expected, IOUAmount const& actual);
500bool
501checkNear(XRPAmount const& expected, XRPAmount const& actual);
503
508{
509 ReadView const& view;
514 bool const isFirst;
515 bool const isLast = false;
518 bool const isDefaultPath;
519 size_t const strandSize;
523 Step const* const prevStep = nullptr;
533 boost::container::flat_set<Issue>& seenBookOuts;
535 std::optional<uint256> domainID; // the domain the order book will use
537
540 ReadView const& view_,
541 std::vector<std::unique_ptr<Step>> const& strand_,
542 // A strand may not include an inner node that
543 // replicates the source or destination.
544 AccountID const& strandSrc_,
545 AccountID const& strandDst_,
546 Issue const& strandDeliver_,
547 std::optional<Quality> const& limitQuality_,
548 bool isLast_,
549 bool ownerPaysTransferFee_,
550 OfferCrossing offerCrossing_,
551 bool isDefaultPath_,
552 std::array<boost::container::flat_set<Issue>, 2>& seenDirectIssues_,
553 boost::container::flat_set<Issue>& seenBookOuts_,
554 AMMContext& ammContext_,
556 beast::Journal j_);
557};
558
560namespace test {
561// Needed for testing
562bool
563directStepEqual(Step const& step, AccountID const& src, AccountID const& dst, Currency const& currency);
564
565bool
566xrpEndpointStepEqual(Step const& step, AccountID const& acc);
567
568bool
569bookStepEqual(Step const& step, xrpl::Book const& book);
570} // namespace test
571
573make_DirectStepI(StrandContext const& ctx, AccountID const& src, AccountID const& dst, Currency const& c);
574
576make_BookStepII(StrandContext const& ctx, Issue const& in, Issue const& out);
577
579make_BookStepIX(StrandContext const& ctx, Issue const& in);
580
582make_BookStepXI(StrandContext const& ctx, Issue const& out);
583
585make_XRPEndpointStep(StrandContext const& ctx, AccountID const& acc);
586
587template <class InAmt, class OutAmt>
588bool
589isDirectXrpToXrp(Strand const& strand);
591
592} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:40
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:114
Specifies an order book.
Definition Book.h:16
A currency issued by an account.
Definition Issue.h:13
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:195
friend bool operator!=(Step const &lhs, Step const &rhs)
Return true if lhs != rhs.
Definition Steps.h:270
virtual std::pair< std::optional< QualityFunction >, DebtDirection > getQualityFunc(ReadView const &v, DebtDirection prevStepDir) const
Get QualityFunction.
Definition Steps.h:292
virtual bool inactive() const
Return true if the step should be considered inactive.
Definition Steps.h:221
friend bool operator==(Step const &lhs, Step const &rhs)
Return true if lhs == rhs.
Definition Steps.h:258
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:204
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:277
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
STL namespace.
bool bookStepEqual(Step const &step, xrpl::Book const &book)
bool xrpEndpointStepEqual(Step const &step, AccountID const &acc)
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
base_uint< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition UintTypes.h:36
bool isDirectXrpToXrp(Strand const &strand)
Definition PaySteps.cpp:549
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:398
std::pair< TER, std::unique_ptr< Step > > make_XRPEndpointStep(StrandContext const &ctx, AccountID const &acc)
std::pair< TER, std::unique_ptr< Step > > make_BookStepXI(StrandContext const &ctx, Issue const &out)
std::string transHuman(TER code)
Definition TER.cpp:252
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:28
DebtDirection
Definition Steps.h:22
constexpr bool operator==(base_uint< Bits, Tag > const &lhs, base_uint< Bits, Tag > const &rhs)
Definition base_uint.h:552
StrandDirection
Definition Steps.h:24
TERSubset< CanCvtToTER > TER
Definition TER.h:620
QualityDirection
Definition Steps.h:23
std::pair< TER, std::unique_ptr< Step > > make_DirectStepI(StrandContext const &ctx, AccountID const &src, AccountID const &dst, Currency const &c)
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_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)
OfferCrossing
Definition Steps.h:25
@ sell
Definition Steps.h:25
@ no
Definition Steps.h:25
@ yes
Definition Steps.h:25
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:100
Context needed to build Strand Steps and for error checking.
Definition Steps.h:508
beast::Journal const j
Definition Steps.h:536
boost::container::flat_set< Issue > & seenBookOuts
A strand may not include an offer that output the same issue more than once.
Definition Steps.h:533
std::optional< uint256 > domainID
Definition Steps.h:535
AMMContext & ammContext
Definition Steps.h:534
std::optional< Quality > const limitQuality
Worst accepted quality.
Definition Steps.h:513
size_t const strandSize
Length of Strand.
Definition Steps.h:519
ReadView const & view
Current ReadView.
Definition Steps.h:509
bool const isFirst
true if Step is first in Strand
Definition Steps.h:514
AccountID const strandSrc
Strand source account.
Definition Steps.h:510
bool const ownerPaysTransferFee
true if owner, not sender, pays fee
Definition Steps.h:516
bool const isLast
true if Step is last in Strand
Definition Steps.h:515
bool const isDefaultPath
true if Strand is default path
Definition Steps.h:518
AccountID const strandDst
Strand destination account.
Definition Steps.h:511
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:529
Step const *const prevStep
The previous step in the strand.
Definition Steps.h:523
Issue const strandDeliver
Issue strand delivers.
Definition Steps.h:512
OfferCrossing const offerCrossing
Yes/Sell if offer crossing, not payment.
Definition Steps.h:517