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#include <xrpl/basics/Log.h>
25#include <xrpl/protocol/Quality.h>
26#include <xrpl/protocol/QualityFunction.h>
27#include <xrpl/protocol/STLedgerEntry.h>
28#include <xrpl/protocol/TER.h>
29
30#include <boost/container/flat_set.hpp>
31#include <optional>
32
33namespace ripple {
34class PaymentSandbox;
35class ReadView;
36class ApplyView;
37class AMMContext;
38
40enum class QualityDirection { in, out };
42enum OfferCrossing { no = 0, yes = 1, sell = 2 };
43
44inline bool
46{
47 return dir == DebtDirection::redeems;
48}
49
50inline bool
52{
53 return dir == DebtDirection::issues;
54}
55
82class Step
83{
84public:
85 virtual ~Step() = default;
86
101 ApplyView& afView,
102 boost::container::flat_set<uint256>& ofrsToRm,
103 EitherAmount const& out) = 0;
104
119 ApplyView& afView,
120 boost::container::flat_set<uint256>& ofrsToRm,
121 EitherAmount const& in) = 0;
122
128 cachedIn() const = 0;
129
135 cachedOut() const = 0;
136
143 {
144 return std::nullopt;
145 }
146
147 // for debugging. Return the src and dst accounts for a direct step
148 // For XRP endpoints, one of src or dst will be the root account
151 {
152 return std::nullopt;
153 }
154
163 virtual DebtDirection
164 debtDirection(ReadView const& sb, StrandDirection dir) const = 0;
165
169 virtual std::uint32_t
171 {
172 return QUALITY_ONE;
173 }
174
175 // clang-format off
190 // clang-format on
192 qualityUpperBound(ReadView const& v, DebtDirection prevStepDir) const = 0;
193
202 getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const;
203
211 virtual std::uint32_t
213 {
214 return 0;
215 }
216
220 virtual std::optional<Book>
222 {
223 return std::nullopt;
224 }
225
229 virtual bool
230 isZero(EitherAmount const& out) const = 0;
231
237 virtual bool
238 inactive() const
239 {
240 return false;
241 }
242
246 virtual bool
247 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
248
252 virtual bool
253 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
254
267
274 friend bool
275 operator==(Step const& lhs, Step const& rhs)
276 {
277 return lhs.equal(rhs);
278 }
279
286 friend bool
287 operator!=(Step const& lhs, Step const& rhs)
288 {
289 return !(lhs == rhs);
290 }
291
294 operator<<(std::ostream& stream, Step const& step)
295 {
296 stream << step.logString();
297 return stream;
298 }
299
300private:
301 virtual std::string
302 logString() const = 0;
303
304 virtual bool
305 equal(Step const& rhs) const = 0;
306};
307
309Step::getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const
310{
311 if (auto const res = qualityUpperBound(v, prevStepDir); res.first)
312 return {
314 res.second};
315 else
316 return {std::nullopt, res.second};
317}
318
321
322inline std::uint32_t
323offersUsed(Strand const& strand)
324{
325 std::uint32_t r = 0;
326 for (auto const& step : strand)
327 {
328 if (step)
329 r += step->offersUsed();
330 }
331 return r;
332}
334
336inline bool
337operator==(Strand const& lhs, Strand const& rhs)
338{
339 if (lhs.size() != rhs.size())
340 return false;
341 for (size_t i = 0, e = lhs.size(); i != e; ++i)
342 if (*lhs[i] != *rhs[i])
343 return false;
344 return true;
345}
347
348/*
349 Normalize a path by inserting implied accounts and offers
350
351 @param src Account that is sending assets
352 @param dst Account that is receiving assets
353 @param deliver Asset the dst account will receive
354 (if issuer of deliver == dst, then accept any issuer)
355 @param sendMax Optional asset to send.
356 @param path Liquidity sources to use for this strand of the payment. The path
357 contains an ordered collection of the offer books to use and
358 accounts to ripple through.
359 @return error code and normalized path
360*/
363 AccountID const& src,
364 AccountID const& dst,
365 Issue const& deliver,
366 std::optional<Issue> const& sendMaxIssue,
367 STPath const& path);
368
394 ReadView const& sb,
395 AccountID const& src,
396 AccountID const& dst,
397 Issue const& deliver,
398 std::optional<Quality> const& limitQuality,
399 std::optional<Issue> const& sendMaxIssue,
400 STPath const& path,
401 bool ownerPaysTransferFee,
402 OfferCrossing offerCrossing,
403 AMMContext& ammContext,
405
433 ReadView const& sb,
434 AccountID const& src,
435 AccountID const& dst,
436 Issue const& deliver,
437 std::optional<Quality> const& limitQuality,
438 std::optional<Issue> const& sendMax,
439 STPathSet const& paths,
440 bool addDefaultPath,
441 bool ownerPaysTransferFee,
442 OfferCrossing offerCrossing,
443 AMMContext& ammContext,
445
447template <class TIn, class TOut, class TDerived>
448struct StepImp : public Step
449{
450 explicit StepImp() = default;
451
453 rev(PaymentSandbox& sb,
454 ApplyView& afView,
455 boost::container::flat_set<uint256>& ofrsToRm,
456 EitherAmount const& out) override
457 {
458 auto const r = static_cast<TDerived*>(this)->revImp(
459 sb, afView, ofrsToRm, get<TOut>(out));
460 return {EitherAmount(r.first), EitherAmount(r.second)};
461 }
462
463 // Given the requested amount to consume, compute the amount produced.
464 // Return the consumed/produced
466 fwd(PaymentSandbox& sb,
467 ApplyView& afView,
468 boost::container::flat_set<uint256>& ofrsToRm,
469 EitherAmount const& in) override
470 {
471 auto const r = static_cast<TDerived*>(this)->fwdImp(
472 sb, afView, ofrsToRm, get<TIn>(in));
473 return {EitherAmount(r.first), EitherAmount(r.second)};
474 }
475
476 bool
477 isZero(EitherAmount const& out) const override
478 {
479 return get<TOut>(out) == beast::zero;
480 }
481
482 bool
483 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const override
484 {
485 return get<TOut>(lhs) == get<TOut>(rhs);
486 }
487
488 bool
489 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const override
490 {
491 return get<TIn>(lhs) == get<TIn>(rhs);
492 }
493};
495
497// Thrown when unexpected errors occur
498class FlowException : public std::runtime_error
499{
500public:
501 TER ter;
502
503 FlowException(TER t, std::string const& msg)
504 : std::runtime_error(msg), ter(t)
505 {
506 }
507
508 explicit FlowException(TER t) : std::runtime_error(transHuman(t)), ter(t)
509 {
510 }
511};
513
515// Check equal with tolerance
516bool
517checkNear(IOUAmount const& expected, IOUAmount const& actual);
518bool
519checkNear(XRPAmount const& expected, XRPAmount const& actual);
521
526{
527 ReadView const& view;
532 bool const isFirst;
533 bool const isLast = false;
535 OfferCrossing const
537 bool const isDefaultPath;
538 size_t const strandSize;
542 Step const* const prevStep = nullptr;
552 boost::container::flat_set<Issue>& seenBookOuts;
555
558 ReadView const& view_,
559 std::vector<std::unique_ptr<Step>> const& strand_,
560 // A strand may not include an inner node that
561 // replicates the source or destination.
562 AccountID const& strandSrc_,
563 AccountID const& strandDst_,
564 Issue const& strandDeliver_,
565 std::optional<Quality> const& limitQuality_,
566 bool isLast_,
567 bool ownerPaysTransferFee_,
568 OfferCrossing offerCrossing_,
569 bool isDefaultPath_,
570 std::array<boost::container::flat_set<Issue>, 2>&
571 seenDirectIssues_,
572 boost::container::flat_set<Issue>&
573 seenBookOuts_,
574 AMMContext& ammContext_,
575 beast::Journal j_);
576};
577
579namespace test {
580// Needed for testing
581bool
583 Step const& step,
584 AccountID const& src,
585 AccountID const& dst,
586 Currency const& currency);
587
588bool
589xrpEndpointStepEqual(Step const& step, AccountID const& acc);
590
591bool
592bookStepEqual(Step const& step, ripple::Book const& book);
593} // namespace test
594
597 StrandContext const& ctx,
598 AccountID const& src,
599 AccountID const& dst,
600 Currency const& c);
601
603make_BookStepII(StrandContext const& ctx, Issue const& in, Issue const& out);
604
606make_BookStepIX(StrandContext const& ctx, Issue const& in);
607
609make_BookStepXI(StrandContext const& ctx, Issue const& out);
610
612make_XRPEndpointStep(StrandContext const& ctx, AccountID const& acc);
613
614template <class InAmt, class OutAmt>
615bool
616isDirectXrpToXrp(Strand const& strand);
618
619} // namespace ripple
620
621#endif
A generic endpoint for log messages.
Definition: Journal.h:59
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:140
Specifies an order book.
Definition: Book.h:34
A currency issued by an account.
Definition: Issue.h:36
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:55
A step in a payment path.
Definition: Steps.h:83
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:170
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:287
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:238
virtual std::uint32_t offersUsed() const
Return the number of offers consumed or partially consumed the last time the step ran,...
Definition: Steps.h:212
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:221
virtual std::optional< std::pair< AccountID, AccountID > > directStepAccts() const
Definition: Steps.h:150
friend bool operator==(Step const &lhs, Step const &rhs)
Return true if lhs == rhs.
Definition: Steps.h:275
friend std::ostream & operator<<(std::ostream &stream, Step const &step)
Streaming operator for a Step.
Definition: Steps.h:294
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:309
virtual std::optional< AccountID > directStepSrcAcct() const
If this step is DirectStepI (IOU->IOU direct step), return the src account.
Definition: Steps.h:142
bool xrpEndpointStepEqual(Step const &step, AccountID const &acc)
bool bookStepEqual(Step const &step, ripple::Book const &book)
Definition: BookStep.cpp:1413
bool directStepEqual(Step const &step, AccountID const &src, AccountID const &dst, Currency const &currency)
Definition: DirectStep.cpp:966
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition: AccountID.h:49
std::string transHuman(TER code)
Definition: TER.cpp:260
std::pair< TER, std::unique_ptr< Step > > make_XRPEndpointStep(StrandContext const &ctx, AccountID const &acc)
StrandDirection
Definition: Steps.h:41
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, beast::Journal j)
Create a Strand for the specified path.
Definition: PaySteps.cpp:137
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, beast::Journal j)
Create a Strand for each specified path (including the default path, if indicated)
Definition: PaySteps.cpp:470
OfferCrossing
Definition: Steps.h:42
@ no
Definition: Steps.h:42
@ yes
Definition: Steps.h:42
@ sell
Definition: Steps.h:42
QualityDirection
Definition: Steps.h:40
std::pair< TER, std::unique_ptr< Step > > make_BookStepXI(StrandContext const &ctx, Issue const &out)
Definition: BookStep.cpp:1482
base_uint< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition: UintTypes.h:56
DebtDirection
Definition: Steps.h:39
std::pair< TER, std::unique_ptr< Step > > make_BookStepIX(StrandContext const &ctx, Issue const &in)
Definition: BookStep.cpp:1476
bool checkNear(IOUAmount const &expected, IOUAmount const &actual)
Definition: PaySteps.cpp:37
std::pair< TER, std::unique_ptr< Step > > make_BookStepII(StrandContext const &ctx, Issue const &in, Issue const &out)
Definition: BookStep.cpp:1470
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)
Definition: DirectStep.cpp:984
bool isDirectXrpToXrp(Strand const &strand)
Definition: PaySteps.cpp:620
constexpr bool operator==(base_uint< Bits, Tag > const &lhs, base_uint< Bits, Tag > const &rhs)
Definition: base_uint.h:584
TERSubset< CanCvtToTER > TER
Definition: TER.h:627
STL namespace.
Context needed to build Strand Steps and for error checking.
Definition: Steps.h:526
bool const isDefaultPath
true if Strand is default path
Definition: Steps.h:537
size_t const strandSize
Length of Strand.
Definition: Steps.h:538
beast::Journal const j
Definition: Steps.h:554
boost::container::flat_set< Issue > & seenBookOuts
A strand may not include an offer that output the same issue more than once.
Definition: Steps.h:552
AccountID const strandSrc
Strand source account.
Definition: Steps.h:528
ReadView const & view
Current ReadView.
Definition: Steps.h:527
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:548
Step const *const prevStep
The previous step in the strand.
Definition: Steps.h:542
bool const ownerPaysTransferFee
true if owner, not sender, pays fee
Definition: Steps.h:534
AccountID const strandDst
Strand destination account.
Definition: Steps.h:529
OfferCrossing const offerCrossing
Yes/Sell if offer crossing, not payment.
Definition: Steps.h:536
bool const isFirst
true if Step is first in Strand
Definition: Steps.h:532
bool const isLast
true if Step is last in Strand
Definition: Steps.h:533
std::optional< Quality > const limitQuality
Worst accepted quality.
Definition: Steps.h:531
Issue const strandDeliver
Issue strand delivers.
Definition: Steps.h:530
AMMContext & ammContext
Definition: Steps.h:553