xrpld
Loading...
Searching...
No Matches
Steps.h
1#pragma once
2
3#include <xrpl/basics/base_uint.h>
4#include <xrpl/beast/utility/Journal.h>
5#include <xrpl/beast/utility/Zero.h>
6#include <xrpl/protocol/AccountID.h>
7#include <xrpl/protocol/Book.h>
8#include <xrpl/protocol/Concepts.h>
9#include <xrpl/protocol/Quality.h>
10#include <xrpl/protocol/QualityFunction.h>
11#include <xrpl/protocol/STPathSet.h>
12#include <xrpl/protocol/TER.h>
13#include <xrpl/protocol/UintTypes.h>
14#include <xrpl/tx/paths/detail/EitherAmount.h>
15
16#include <boost/container/flat_set.hpp>
17
18#include <array>
19#include <cstddef>
20#include <cstdint>
21#include <memory>
22#include <optional>
23#include <ostream>
24#include <stdexcept>
25#include <string>
26#include <utility>
27#include <vector>
28
29namespace xrpl {
30class PaymentSandbox;
31class ReadView;
32class ApplyView;
33class AMMContext;
34
36enum class QualityDirection { In, Out };
38enum class OfferCrossing { No = 0, Yes = 1, Sell = 2 };
39
40inline bool
42{
43 return dir == DebtDirection::Redeems;
44}
45
46inline bool
48{
49 return dir == DebtDirection::Issues;
50}
51
79class Step
80{
81public:
82 virtual ~Step() = default;
83
98 ApplyView& afView,
99 boost::container::flat_set<uint256>& ofrsToRm,
100 EitherAmount const& out) = 0;
101
116 ApplyView& afView,
117 boost::container::flat_set<uint256>& ofrsToRm,
118 EitherAmount const& in) = 0;
119
124 [[nodiscard]] virtual std::optional<EitherAmount>
125 cachedIn() const = 0;
126
131 [[nodiscard]] virtual std::optional<EitherAmount>
132 cachedOut() const = 0;
133
138 [[nodiscard]] virtual std::optional<AccountID>
140 {
141 return std::nullopt;
142 }
143
144 // for debugging. Return the src and dst accounts for a direct step
145 // For XRP endpoints, one of src or dst will be the root account
148 {
149 return std::nullopt;
150 }
151
160 [[nodiscard]] virtual DebtDirection
161 debtDirection(ReadView const& sb, StrandDirection dir) const = 0;
162
166 [[nodiscard]] virtual std::uint32_t
168 {
169 return QUALITY_ONE;
170 }
171
185 [[nodiscard]] virtual std::pair<std::optional<Quality>, DebtDirection>
186 qualityUpperBound(ReadView const& v, DebtDirection prevStepDir) const = 0;
187
197 getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const;
198
207 [[nodiscard]] virtual std::uint32_t
209 {
210 return 0;
211 }
212
216 [[nodiscard]] virtual std::optional<Book>
218 {
219 return std::nullopt;
220 }
221
225 [[nodiscard]] virtual bool
226 isZero(EitherAmount const& out) const = 0;
227
233 [[nodiscard]] virtual bool
234 inactive() const
235 {
236 return false;
237 }
238
242 [[nodiscard]] virtual bool
243 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
244
248 [[nodiscard]] virtual bool
249 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
250
262 validFwd(PaymentSandbox& sb, ApplyView& afView, EitherAmount const& in) = 0;
263
271 friend bool
272 operator==(Step const& lhs, Step const& rhs)
273 {
274 return lhs.equal(rhs);
275 }
276
281 operator<<(std::ostream& stream, Step const& step)
282 {
283 stream << step.logString();
284 return stream;
285 }
286
287private:
288 [[nodiscard]] virtual std::string
289 logString() const = 0;
290
291 [[nodiscard]] virtual bool
292 equal(Step const& rhs) const = 0;
293};
294
296Step::getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const
297{
298 auto const res = qualityUpperBound(v, prevStepDir);
299 if (res.first)
300 return {QualityFunction{*res.first, QualityFunction::CLOBLikeTag{}}, res.second};
301 return {std::nullopt, res.second};
302}
303
306
307inline std::uint32_t
308offersUsed(Strand const& strand)
309{
310 std::uint32_t r = 0;
311 for (auto const& step : strand)
312 {
313 if (step)
314 r += step->offersUsed();
315 }
316 return r;
317}
319
321inline bool
322operator==(Strand const& lhs, Strand const& rhs)
323{
324 if (lhs.size() != rhs.size())
325 return false;
326 for (size_t i = 0, e = lhs.size(); i != e; ++i)
327 {
328 if (*lhs[i] != *rhs[i])
329 return false;
330 }
331 return true;
332}
334
348std::pair<TER, STPath>
350 AccountID const& src,
351 AccountID const& dst,
352 Asset const& deliver,
353 std::optional<Asset> const& sendMaxAsset,
354 STPath const& path);
355
382 ReadView const& sb,
383 AccountID const& src,
384 AccountID const& dst,
385 Asset const& deliver,
386 std::optional<Quality> const& limitQuality,
387 std::optional<Asset> const& sendMaxAsset,
388 STPath const& path,
389 bool ownerPaysTransferFee,
390 OfferCrossing offerCrossing,
391 AMMContext& ammContext,
392 std::optional<uint256> const& domainID,
394
423 ReadView const& sb,
424 AccountID const& src,
425 AccountID const& dst,
426 Asset const& deliver,
427 std::optional<Quality> const& limitQuality,
428 std::optional<Asset> const& sendMax,
429 STPathSet const& paths,
430 bool addDefaultPath,
431 bool ownerPaysTransferFee,
432 OfferCrossing offerCrossing,
433 AMMContext& ammContext,
434 std::optional<uint256> const& domainID,
436
438template <StepAmount TIn, StepAmount TOut, class TDerived>
439struct StepImp : public Step
440{
441private:
442 explicit StepImp() = default;
443
444public:
446 rev(PaymentSandbox& sb,
447 ApplyView& afView,
448 boost::container::flat_set<uint256>& ofrsToRm,
449 EitherAmount const& out) override
450 {
451 auto const r = static_cast<TDerived*>(this)->revImp(sb, afView, ofrsToRm, get<TOut>(out));
452 return {EitherAmount(r.first), EitherAmount(r.second)};
453 }
454
455 // Given the requested amount to consume, compute the amount produced.
456 // Return the consumed/produced
457 std::pair<EitherAmount, EitherAmount>
458 fwd(PaymentSandbox& sb,
459 ApplyView& afView,
460 boost::container::flat_set<uint256>& ofrsToRm,
461 EitherAmount const& in) override
462 {
463 auto const r = static_cast<TDerived*>(this)->fwdImp(sb, afView, ofrsToRm, get<TIn>(in));
464 return {EitherAmount(r.first), EitherAmount(r.second)};
465 }
466
467 [[nodiscard]] bool
468 isZero(EitherAmount const& out) const override
469 {
470 return get<TOut>(out) == beast::kZero;
471 }
472
473 [[nodiscard]] bool
474 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const override
475 {
476 return get<TOut>(lhs) == get<TOut>(rhs);
477 }
478
479 [[nodiscard]] bool
480 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const override
481 {
482 return get<TIn>(lhs) == get<TIn>(rhs);
483 }
484 friend TDerived;
485};
487
489// Thrown when unexpected errors occur
490class FlowException : public std::runtime_error
491{
492public:
493 TER ter;
494
495 FlowException(TER t, std::string const& msg) : std::runtime_error(msg), ter(t)
496 {
497 }
498
499 explicit FlowException(TER t) : std::runtime_error(transHuman(t)), ter(t)
500 {
501 }
502};
504
506// Check equal with tolerance
507bool
508checkNear(IOUAmount const& expected, IOUAmount const& actual);
509inline bool
510checkNear(MPTAmount const& expected, MPTAmount const& actual)
511{
512 return expected == actual;
513}
514inline bool
515checkNear(XRPAmount const& expected, XRPAmount const& actual)
516{
517 return expected == actual;
518}
520
525{
526 ReadView const& view;
531 bool const isFirst;
532 bool const isLast = false;
535 bool const isDefaultPath;
536 size_t const strandSize;
541 Step const* const prevStep = nullptr;
553 boost::container::flat_set<Asset>& seenBookOuts;
555 std::optional<uint256> domainID; // the domain the order book will use
557
562 ReadView const& view,
563 std::vector<std::unique_ptr<Step>> const& strand,
564 // A strand may not include an inner node that
565 // replicates the source or destination.
566 AccountID const& strandSrc,
567 AccountID const& strandDst,
568 Asset const& strandDeliver,
570 bool isLast,
573 bool isDefaultPath,
574 std::array<boost::container::flat_set<Asset>, 2>&
576 boost::container::flat_set<Asset>& seenBookOuts,
580};
581
583namespace test {
584// Needed for testing
585bool
587 Step const& step,
588 AccountID const& src,
589 AccountID const& dst,
590 Currency const& currency);
591
592bool
594 Step const& step,
595 AccountID const& src,
596 AccountID const& dst,
597 MPTID const& mptid);
598
599bool
600xrpEndpointStepEqual(Step const& step, AccountID const& acc);
601
602bool
603bookStepEqual(Step const& step, xrpl::Book const& book);
604} // namespace test
605
608 StrandContext const& ctx,
609 AccountID const& src,
610 AccountID const& dst,
611 Currency const& c);
612
615 StrandContext const& ctx,
616 AccountID const& src,
617 AccountID const& dst,
618 MPTID const& a);
619
621makeBookStepIi(StrandContext const& ctx, Issue const& in, Issue const& out);
622
624makeBookStepIx(StrandContext const& ctx, Issue const& in);
625
627makeBookStepXi(StrandContext const& ctx, Issue const& out);
628
630makeXrpEndpointStep(StrandContext const& ctx, AccountID const& acc);
631
633makeBookStepMm(StrandContext const& ctx, MPTIssue const& in, MPTIssue const& out);
634
636makeBookStepMx(StrandContext const& ctx, MPTIssue const& in);
637
639makeBookStepXm(StrandContext const& ctx, MPTIssue const& out);
640
642makeBookStepMi(StrandContext const& ctx, MPTIssue const& in, Issue const& out);
643
645makeBookStepIm(StrandContext const& ctx, Issue const& in, MPTIssue const& out);
646
647template <StepAmount InAmt, StepAmount OutAmt>
648bool
649isDirectXrpToXrp(Strand const& strand)
650{
652 {
653 return strand.size() == 2;
654 }
655 else
656 {
657 return false;
658 }
659}
661
662} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
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:134
Specifies an order book.
Definition Book.h:28
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:26
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:41
A step in a payment path.
Definition Steps.h:80
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:139
virtual std::string logString() const =0
virtual std::optional< std::pair< AccountID, AccountID > > directStepAccts() const
Definition Steps.h:147
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:208
virtual std::pair< std::optional< QualityFunction >, DebtDirection > getQualityFunc(ReadView const &v, DebtDirection prevStepDir) const
Get QualityFunction.
Definition Steps.h:296
virtual bool inactive() const
Return true if the step should be considered inactive.
Definition Steps.h:234
friend bool operator==(Step const &lhs, Step const &rhs)
Return true if lhs == rhs.
Definition Steps.h:272
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:217
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:281
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:167
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
constexpr Zero kZero
Definition Zero.h:30
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:606
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:47
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:42
std::string transHuman(TER code)
Definition TER.cpp:260
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)
Normalize a path by inserting implied accounts and offers.
DebtDirection
Definition Steps.h:35
std::pair< TER, std::unique_ptr< Step > > makeBookStepIx(StrandContext const &ctx, Issue const &in)
StrandDirection
Definition Steps.h:37
@ Yes
We have consensus along with the network.
@ No
We do not have consensus.
QualityDirection
Definition Steps.h:36
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:54
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:34
std::pair< TER, std::unique_ptr< Step > > makeBookStepIm(StrandContext const &ctx, Issue const &in, MPTIssue const &out)
TERSubset< CanCvtToTER > TER
Definition TER.h:647
bool redeems(DebtDirection dir)
Definition Steps.h:41
OfferCrossing
Definition Steps.h:38
std::pair< TER, std::unique_ptr< Step > > makeBookStepMm(StrandContext const &ctx, MPTIssue const &in, MPTIssue const &out)
beast::Journal const j
Definition Steps.h:556
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:529
std::optional< uint256 > domainID
Definition Steps.h:555
AMMContext & ammContext
Definition Steps.h:554
std::optional< Quality > const limitQuality
Worst accepted quality.
Definition Steps.h:530
size_t const strandSize
Length of Strand.
Definition Steps.h:536
ReadView const & view
Current ReadView.
Definition Steps.h:526
bool const isFirst
true if Step is first in Strand
Definition Steps.h:531
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:548
AccountID const strandSrc
Strand source account.
Definition Steps.h:527
bool const ownerPaysTransferFee
true if owner, not sender, pays fee
Definition Steps.h:533
bool const isLast
true if Step is last in Strand
Definition Steps.h:532
bool const isDefaultPath
true if Strand is default path
Definition Steps.h:535
boost::container::flat_set< Asset > & seenBookOuts
A strand may not include an offer that output the same issue more than once.
Definition Steps.h:553
AccountID const strandDst
Strand destination account.
Definition Steps.h:528
Step const *const prevStep
The previous step in the strand.
Definition Steps.h:541
OfferCrossing const offerCrossing
Yes/Sell if offer crossing, not payment.
Definition Steps.h:534