rippled
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/Quality.h>
6#include <xrpl/protocol/QualityFunction.h>
7#include <xrpl/protocol/STLedgerEntry.h>
8#include <xrpl/protocol/TER.h>
9#include <xrpl/tx/paths/detail/AmountSpec.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 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
64class Step
65{
66public:
67 virtual ~Step() = default;
68
83 ApplyView& afView,
84 boost::container::flat_set<uint256>& ofrsToRm,
85 EitherAmount const& out) = 0;
86
101 ApplyView& afView,
102 boost::container::flat_set<uint256>& ofrsToRm,
103 EitherAmount const& in) = 0;
104
110 cachedIn() const = 0;
111
117 cachedOut() const = 0;
118
125 {
126 return std::nullopt;
127 }
128
129 // for debugging. Return the src and dst accounts for a direct step
130 // For XRP endpoints, one of src or dst will be the root account
133 {
134 return std::nullopt;
135 }
136
145 virtual DebtDirection
146 debtDirection(ReadView const& sb, StrandDirection dir) const = 0;
147
151 virtual std::uint32_t
153 {
154 return QUALITY_ONE;
155 }
156
171 qualityUpperBound(ReadView const& v, DebtDirection prevStepDir) const = 0;
172
181 getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const;
182
190 virtual std::uint32_t
192 {
193 return 0;
194 }
195
199 virtual std::optional<Book>
201 {
202 return std::nullopt;
203 }
204
208 virtual bool
209 isZero(EitherAmount const& out) const = 0;
210
216 virtual bool
217 inactive() const
218 {
219 return false;
220 }
221
225 virtual bool
226 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
227
231 virtual bool
232 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
233
246
253 friend bool
254 operator==(Step const& lhs, Step const& rhs)
255 {
256 return lhs.equal(rhs);
257 }
258
265 friend bool
266 operator!=(Step const& lhs, Step const& rhs)
267 {
268 return !(lhs == rhs);
269 }
270
273 operator<<(std::ostream& stream, Step const& step)
274 {
275 stream << step.logString();
276 return stream;
277 }
278
279private:
280 virtual std::string
281 logString() const = 0;
282
283 virtual bool
284 equal(Step const& rhs) const = 0;
285};
286
288Step::getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const
289{
290 if (auto const res = qualityUpperBound(v, prevStepDir); res.first)
291 return {QualityFunction{*res.first, QualityFunction::CLOBLikeTag{}}, res.second};
292 else
293 return {std::nullopt, res.second};
294}
295
298
299inline std::uint32_t
300offersUsed(Strand const& strand)
301{
302 std::uint32_t r = 0;
303 for (auto const& step : strand)
304 {
305 if (step)
306 r += step->offersUsed();
307 }
308 return r;
309}
311
313inline bool
314operator==(Strand const& lhs, Strand const& rhs)
315{
316 if (lhs.size() != rhs.size())
317 return false;
318 for (size_t i = 0, e = lhs.size(); i != e; ++i)
319 if (*lhs[i] != *rhs[i])
320 return false;
321 return true;
322}
324
325/*
326 Normalize a path by inserting implied accounts and offers
327
328 @param src Account that is sending assets
329 @param dst Account that is receiving assets
330 @param deliver Asset the dst account will receive
331 (if issuer of deliver == dst, then accept any issuer)
332 @param sendMax Optional asset to send.
333 @param path Liquidity sources to use for this strand of the payment. The path
334 contains an ordered collection of the offer books to use and
335 accounts to ripple through.
336 @return error code and normalized path
337*/
340 AccountID const& src,
341 AccountID const& dst,
342 Issue const& deliver,
343 std::optional<Issue> const& sendMaxIssue,
344 STPath const& path);
345
372 ReadView const& sb,
373 AccountID const& src,
374 AccountID const& dst,
375 Issue const& deliver,
376 std::optional<Quality> const& limitQuality,
377 std::optional<Issue> const& sendMaxIssue,
378 STPath const& path,
379 bool ownerPaysTransferFee,
380 OfferCrossing offerCrossing,
381 AMMContext& ammContext,
382 std::optional<uint256> const& domainID,
384
413 ReadView const& sb,
414 AccountID const& src,
415 AccountID const& dst,
416 Issue const& deliver,
417 std::optional<Quality> const& limitQuality,
418 std::optional<Issue> const& sendMax,
419 STPathSet const& paths,
420 bool addDefaultPath,
421 bool ownerPaysTransferFee,
422 OfferCrossing offerCrossing,
423 AMMContext& ammContext,
424 std::optional<uint256> const& domainID,
426
428template <class TIn, class TOut, class TDerived>
429struct StepImp : public Step
430{
431 explicit StepImp() = default;
432
434 rev(PaymentSandbox& sb,
435 ApplyView& afView,
436 boost::container::flat_set<uint256>& ofrsToRm,
437 EitherAmount const& out) override
438 {
439 auto const r = static_cast<TDerived*>(this)->revImp(sb, afView, ofrsToRm, get<TOut>(out));
440 return {EitherAmount(r.first), EitherAmount(r.second)};
441 }
442
443 // Given the requested amount to consume, compute the amount produced.
444 // Return the consumed/produced
446 fwd(PaymentSandbox& sb,
447 ApplyView& afView,
448 boost::container::flat_set<uint256>& ofrsToRm,
449 EitherAmount const& in) override
450 {
451 auto const r = static_cast<TDerived*>(this)->fwdImp(sb, afView, ofrsToRm, get<TIn>(in));
452 return {EitherAmount(r.first), EitherAmount(r.second)};
453 }
454
455 bool
456 isZero(EitherAmount const& out) const override
457 {
458 return get<TOut>(out) == beast::zero;
459 }
460
461 bool
462 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const override
463 {
464 return get<TOut>(lhs) == get<TOut>(rhs);
465 }
466
467 bool
468 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const override
469 {
470 return get<TIn>(lhs) == get<TIn>(rhs);
471 }
472};
474
476// Thrown when unexpected errors occur
477class FlowException : public std::runtime_error
478{
479public:
480 TER ter;
481
482 FlowException(TER t, std::string const& msg) : std::runtime_error(msg), ter(t)
483 {
484 }
485
486 explicit FlowException(TER t) : std::runtime_error(transHuman(t)), ter(t)
487 {
488 }
489};
491
493// Check equal with tolerance
494bool
495checkNear(IOUAmount const& expected, IOUAmount const& actual);
496bool
497checkNear(XRPAmount const& expected, XRPAmount const& actual);
499
504{
505 ReadView const& view;
510 bool const isFirst;
511 bool const isLast = false;
514 bool const isDefaultPath;
515 size_t const strandSize;
519 Step const* const prevStep = nullptr;
529 boost::container::flat_set<Issue>& seenBookOuts;
531 std::optional<uint256> domainID; // the domain the order book will use
533
536 ReadView const& view_,
537 std::vector<std::unique_ptr<Step>> const& strand_,
538 // A strand may not include an inner node that
539 // replicates the source or destination.
540 AccountID const& strandSrc_,
541 AccountID const& strandDst_,
542 Issue const& strandDeliver_,
543 std::optional<Quality> const& limitQuality_,
544 bool isLast_,
545 bool ownerPaysTransferFee_,
546 OfferCrossing offerCrossing_,
547 bool isDefaultPath_,
548 std::array<boost::container::flat_set<Issue>, 2>&
549 seenDirectIssues_,
550 boost::container::flat_set<Issue>& seenBookOuts_,
551 AMMContext& ammContext_,
553 beast::Journal j_);
554};
555
557namespace test {
558// Needed for testing
559bool
561 Step const& step,
562 AccountID const& src,
563 AccountID const& dst,
564 Currency const& currency);
565
566bool
567xrpEndpointStepEqual(Step const& step, AccountID const& acc);
568
569bool
570bookStepEqual(Step const& step, xrpl::Book const& book);
571} // namespace test
572
575 StrandContext const& ctx,
576 AccountID const& src,
577 AccountID const& dst,
578 Currency const& c);
579
581make_BookStepII(StrandContext const& ctx, Issue const& in, Issue const& out);
582
584make_BookStepIX(StrandContext const& ctx, Issue const& in);
585
587make_BookStepXI(StrandContext const& ctx, Issue const& out);
588
590make_XRPEndpointStep(StrandContext const& ctx, AccountID const& acc);
591
592template <class InAmt, class OutAmt>
593bool
594isDirectXrpToXrp(Strand const& strand);
596
597} // 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:116
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:65
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:124
virtual std::string logString() const =0
virtual std::optional< std::pair< AccountID, AccountID > > directStepAccts() const
Definition Steps.h:132
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:191
friend bool operator!=(Step const &lhs, Step const &rhs)
Return true if lhs != rhs.
Definition Steps.h:266
virtual std::pair< std::optional< QualityFunction >, DebtDirection > getQualityFunc(ReadView const &v, DebtDirection prevStepDir) const
Get QualityFunction.
Definition Steps.h:288
virtual bool inactive() const
Return true if the step should be considered inactive.
Definition Steps.h:217
friend bool operator==(Step const &lhs, Step const &rhs)
Return true if lhs == rhs.
Definition Steps.h:254
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:200
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:273
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:152
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:575
std::pair< TER, std::vector< Strand > > toStrands(ReadView const &sb, 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:423
std::pair< TER, Strand > toStrand(ReadView const &sb, 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:111
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:21
constexpr bool operator==(base_uint< Bits, Tag > const &lhs, base_uint< Bits, Tag > const &rhs)
Definition base_uint.h:557
StrandDirection
Definition Steps.h:23
TERSubset< CanCvtToTER > TER
Definition TER.h:622
QualityDirection
Definition Steps.h:22
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:14
std::pair< TER, std::unique_ptr< Step > > make_BookStepII(StrandContext const &ctx, Issue const &in, Issue const &out)
OfferCrossing
Definition Steps.h:24
@ sell
Definition Steps.h:24
@ no
Definition Steps.h:24
@ yes
Definition Steps.h:24
Context needed to build Strand Steps and for error checking.
Definition Steps.h:504
beast::Journal const j
Definition Steps.h:532
boost::container::flat_set< Issue > & seenBookOuts
A strand may not include an offer that output the same issue more than once.
Definition Steps.h:529
std::optional< uint256 > domainID
Definition Steps.h:531
AMMContext & ammContext
Definition Steps.h:530
std::optional< Quality > const limitQuality
Worst accepted quality.
Definition Steps.h:509
size_t const strandSize
Length of Strand.
Definition Steps.h:515
ReadView const & view
Current ReadView.
Definition Steps.h:505
bool const isFirst
true if Step is first in Strand
Definition Steps.h:510
AccountID const strandSrc
Strand source account.
Definition Steps.h:506
bool const ownerPaysTransferFee
true if owner, not sender, pays fee
Definition Steps.h:512
bool const isLast
true if Step is last in Strand
Definition Steps.h:511
bool const isDefaultPath
true if Strand is default path
Definition Steps.h:514
AccountID const strandDst
Strand destination account.
Definition Steps.h:507
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:525
Step const *const prevStep
The previous step in the strand.
Definition Steps.h:519
Issue const strandDeliver
Issue strand delivers.
Definition Steps.h:508
OfferCrossing const offerCrossing
Yes/Sell if offer crossing, not payment.
Definition Steps.h:513