rippled
Loading...
Searching...
No Matches
Steps.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef RIPPLE_APP_PATHS_IMPL_PAYSTEPS_H_INCLUDED
21#define RIPPLE_APP_PATHS_IMPL_PAYSTEPS_H_INCLUDED
22
23#include <xrpld/app/paths/detail/AmountSpec.h>
24
25#include <xrpl/basics/Log.h>
26#include <xrpl/basics/base_uint.h>
27#include <xrpl/protocol/Quality.h>
28#include <xrpl/protocol/QualityFunction.h>
29#include <xrpl/protocol/STLedgerEntry.h>
30#include <xrpl/protocol/TER.h>
31
32#include <boost/container/flat_set.hpp>
33
34#include <optional>
35
36namespace ripple {
37class PaymentSandbox;
38class ReadView;
39class ApplyView;
40class AMMContext;
41
43enum class QualityDirection { in, out };
45enum OfferCrossing { no = 0, yes = 1, sell = 2 };
46
47inline bool
49{
50 return dir == DebtDirection::redeems;
51}
52
53inline bool
55{
56 return dir == DebtDirection::issues;
57}
58
85class Step
86{
87public:
88 virtual ~Step() = default;
89
104 ApplyView& afView,
105 boost::container::flat_set<uint256>& ofrsToRm,
106 EitherAmount const& out) = 0;
107
122 ApplyView& afView,
123 boost::container::flat_set<uint256>& ofrsToRm,
124 EitherAmount const& in) = 0;
125
131 cachedIn() const = 0;
132
138 cachedOut() const = 0;
139
146 {
147 return std::nullopt;
148 }
149
150 // for debugging. Return the src and dst accounts for a direct step
151 // For XRP endpoints, one of src or dst will be the root account
154 {
155 return std::nullopt;
156 }
157
166 virtual DebtDirection
167 debtDirection(ReadView const& sb, StrandDirection dir) const = 0;
168
172 virtual std::uint32_t
174 {
175 return QUALITY_ONE;
176 }
177
178 // clang-format off
193 // clang-format on
195 qualityUpperBound(ReadView const& v, DebtDirection prevStepDir) const = 0;
196
205 getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const;
206
214 virtual std::uint32_t
216 {
217 return 0;
218 }
219
223 virtual std::optional<Book>
225 {
226 return std::nullopt;
227 }
228
232 virtual bool
233 isZero(EitherAmount const& out) const = 0;
234
240 virtual bool
241 inactive() const
242 {
243 return false;
244 }
245
249 virtual bool
250 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
251
255 virtual bool
256 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
257
270
277 friend bool
278 operator==(Step const& lhs, Step const& rhs)
279 {
280 return lhs.equal(rhs);
281 }
282
289 friend bool
290 operator!=(Step const& lhs, Step const& rhs)
291 {
292 return !(lhs == rhs);
293 }
294
297 operator<<(std::ostream& stream, Step const& step)
298 {
299 stream << step.logString();
300 return stream;
301 }
302
303private:
304 virtual std::string
305 logString() const = 0;
306
307 virtual bool
308 equal(Step const& rhs) const = 0;
309};
310
312Step::getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const
313{
314 if (auto const res = qualityUpperBound(v, prevStepDir); res.first)
315 return {
317 res.second};
318 else
319 return {std::nullopt, res.second};
320}
321
324
325inline std::uint32_t
326offersUsed(Strand const& strand)
327{
328 std::uint32_t r = 0;
329 for (auto const& step : strand)
330 {
331 if (step)
332 r += step->offersUsed();
333 }
334 return r;
335}
337
339inline bool
340operator==(Strand const& lhs, Strand const& rhs)
341{
342 if (lhs.size() != rhs.size())
343 return false;
344 for (size_t i = 0, e = lhs.size(); i != e; ++i)
345 if (*lhs[i] != *rhs[i])
346 return false;
347 return true;
348}
350
351/*
352 Normalize a path by inserting implied accounts and offers
353
354 @param src Account that is sending assets
355 @param dst Account that is receiving assets
356 @param deliver Asset the dst account will receive
357 (if issuer of deliver == dst, then accept any issuer)
358 @param sendMax Optional asset to send.
359 @param path Liquidity sources to use for this strand of the payment. The path
360 contains an ordered collection of the offer books to use and
361 accounts to ripple through.
362 @return error code and normalized path
363*/
366 AccountID const& src,
367 AccountID const& dst,
368 Issue const& deliver,
369 std::optional<Issue> const& sendMaxIssue,
370 STPath const& path);
371
398 ReadView const& sb,
399 AccountID const& src,
400 AccountID const& dst,
401 Issue const& deliver,
402 std::optional<Quality> const& limitQuality,
403 std::optional<Issue> const& sendMaxIssue,
404 STPath const& path,
405 bool ownerPaysTransferFee,
406 OfferCrossing offerCrossing,
407 AMMContext& ammContext,
408 std::optional<uint256> const& domainID,
410
439 ReadView const& sb,
440 AccountID const& src,
441 AccountID const& dst,
442 Issue const& deliver,
443 std::optional<Quality> const& limitQuality,
444 std::optional<Issue> const& sendMax,
445 STPathSet const& paths,
446 bool addDefaultPath,
447 bool ownerPaysTransferFee,
448 OfferCrossing offerCrossing,
449 AMMContext& ammContext,
450 std::optional<uint256> const& domainID,
452
454template <class TIn, class TOut, class TDerived>
455struct StepImp : public Step
456{
457 explicit StepImp() = default;
458
460 rev(PaymentSandbox& sb,
461 ApplyView& afView,
462 boost::container::flat_set<uint256>& ofrsToRm,
463 EitherAmount const& out) override
464 {
465 auto const r = static_cast<TDerived*>(this)->revImp(
466 sb, afView, ofrsToRm, get<TOut>(out));
467 return {EitherAmount(r.first), EitherAmount(r.second)};
468 }
469
470 // Given the requested amount to consume, compute the amount produced.
471 // Return the consumed/produced
473 fwd(PaymentSandbox& sb,
474 ApplyView& afView,
475 boost::container::flat_set<uint256>& ofrsToRm,
476 EitherAmount const& in) override
477 {
478 auto const r = static_cast<TDerived*>(this)->fwdImp(
479 sb, afView, ofrsToRm, get<TIn>(in));
480 return {EitherAmount(r.first), EitherAmount(r.second)};
481 }
482
483 bool
484 isZero(EitherAmount const& out) const override
485 {
486 return get<TOut>(out) == beast::zero;
487 }
488
489 bool
490 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const override
491 {
492 return get<TOut>(lhs) == get<TOut>(rhs);
493 }
494
495 bool
496 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const override
497 {
498 return get<TIn>(lhs) == get<TIn>(rhs);
499 }
500};
502
504// Thrown when unexpected errors occur
505class FlowException : public std::runtime_error
506{
507public:
508 TER ter;
509
510 FlowException(TER t, std::string const& msg)
511 : std::runtime_error(msg), ter(t)
512 {
513 }
514
515 explicit FlowException(TER t) : std::runtime_error(transHuman(t)), ter(t)
516 {
517 }
518};
520
522// Check equal with tolerance
523bool
524checkNear(IOUAmount const& expected, IOUAmount const& actual);
525bool
526checkNear(XRPAmount const& expected, XRPAmount const& actual);
528
533{
534 ReadView const& view;
539 bool const isFirst;
540 bool const isLast = false;
542 OfferCrossing const
544 bool const isDefaultPath;
545 size_t const strandSize;
549 Step const* const prevStep = nullptr;
559 boost::container::flat_set<Issue>& seenBookOuts;
561 std::optional<uint256> domainID; // the domain the order book will use
563
566 ReadView const& view_,
567 std::vector<std::unique_ptr<Step>> const& strand_,
568 // A strand may not include an inner node that
569 // replicates the source or destination.
570 AccountID const& strandSrc_,
571 AccountID const& strandDst_,
572 Issue const& strandDeliver_,
573 std::optional<Quality> const& limitQuality_,
574 bool isLast_,
575 bool ownerPaysTransferFee_,
576 OfferCrossing offerCrossing_,
577 bool isDefaultPath_,
578 std::array<boost::container::flat_set<Issue>, 2>&
579 seenDirectIssues_,
580 boost::container::flat_set<Issue>&
581 seenBookOuts_,
582 AMMContext& ammContext_,
584 beast::Journal j_);
585};
586
588namespace test {
589// Needed for testing
590bool
592 Step const& step,
593 AccountID const& src,
594 AccountID const& dst,
595 Currency const& currency);
596
597bool
598xrpEndpointStepEqual(Step const& step, AccountID const& acc);
599
600bool
601bookStepEqual(Step const& step, ripple::Book const& book);
602} // namespace test
603
606 StrandContext const& ctx,
607 AccountID const& src,
608 AccountID const& dst,
609 Currency const& c);
610
612make_BookStepII(StrandContext const& ctx, Issue const& in, Issue const& out);
613
615make_BookStepIX(StrandContext const& ctx, Issue const& in);
616
618make_BookStepXI(StrandContext const& ctx, Issue const& out);
619
621make_XRPEndpointStep(StrandContext const& ctx, AccountID const& acc);
622
623template <class InAmt, class OutAmt>
624bool
625isDirectXrpToXrp(Strand const& strand);
627
628} // namespace ripple
629
630#endif
A generic endpoint for log messages.
Definition Journal.h:60
Maintains AMM info per overall payment engine execution and individual iteration.
Definition AMMContext.h:36
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:143
Specifies an order book.
Definition Book.h:36
A currency issued by an account.
Definition Issue.h:33
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:51
A step in a payment path.
Definition Steps.h:86
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:173
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:290
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:241
virtual std::uint32_t offersUsed() const
Return the number of offers consumed or partially consumed the last time the step ran,...
Definition Steps.h:215
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:224
virtual std::optional< std::pair< AccountID, AccountID > > directStepAccts() const
Definition Steps.h:153
friend bool operator==(Step const &lhs, Step const &rhs)
Return true if lhs == rhs.
Definition Steps.h:278
friend std::ostream & operator<<(std::ostream &stream, Step const &step)
Streaming operator for a Step.
Definition Steps.h:297
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:312
virtual std::optional< AccountID > directStepSrcAcct() const
If this step is DirectStepI (IOU->IOU direct step), return the src account.
Definition Steps.h:145
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:25
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:48
std::string transHuman(TER code)
Definition TER.cpp:273
std::pair< TER, std::unique_ptr< Step > > make_XRPEndpointStep(StrandContext const &ctx, AccountID const &acc)
StrandDirection
Definition Steps.h:44
OfferCrossing
Definition Steps.h:45
@ no
Definition Steps.h:45
@ yes
Definition Steps.h:45
@ sell
Definition Steps.h:45
QualityDirection
Definition Steps.h:43
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:56
DebtDirection
Definition Steps.h:42
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:34
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:630
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:475
constexpr bool operator==(base_uint< Bits, Tag > const &lhs, base_uint< Bits, Tag > const &rhs)
Definition base_uint.h:585
TERSubset< CanCvtToTER > TER
Definition TER.h:649
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:136
STL namespace.
Context needed to build Strand Steps and for error checking.
Definition Steps.h:533
bool const isDefaultPath
true if Strand is default path
Definition Steps.h:544
size_t const strandSize
Length of Strand.
Definition Steps.h:545
beast::Journal const j
Definition Steps.h:562
boost::container::flat_set< Issue > & seenBookOuts
A strand may not include an offer that output the same issue more than once.
Definition Steps.h:559
AccountID const strandSrc
Strand source account.
Definition Steps.h:535
ReadView const & view
Current ReadView.
Definition Steps.h:534
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:555
Step const *const prevStep
The previous step in the strand.
Definition Steps.h:549
bool const ownerPaysTransferFee
true if owner, not sender, pays fee
Definition Steps.h:541
AccountID const strandDst
Strand destination account.
Definition Steps.h:536
std::optional< uint256 > domainID
Definition Steps.h:561
OfferCrossing const offerCrossing
Yes/Sell if offer crossing, not payment.
Definition Steps.h:543
bool const isFirst
true if Step is first in Strand
Definition Steps.h:539
bool const isLast
true if Step is last in Strand
Definition Steps.h:540
std::optional< Quality > const limitQuality
Worst accepted quality.
Definition Steps.h:538
Issue const strandDeliver
Issue strand delivers.
Definition Steps.h:537
AMMContext & ammContext
Definition Steps.h:560