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
32#include <optional>
33
34namespace ripple {
35class PaymentSandbox;
36class ReadView;
37class ApplyView;
38class AMMContext;
39
41enum class QualityDirection { in, out };
43enum OfferCrossing { no = 0, yes = 1, sell = 2 };
44
45inline bool
47{
48 return dir == DebtDirection::redeems;
49}
50
51inline bool
53{
54 return dir == DebtDirection::issues;
55}
56
83class Step
84{
85public:
86 virtual ~Step() = default;
87
102 ApplyView& afView,
103 boost::container::flat_set<uint256>& ofrsToRm,
104 EitherAmount const& out) = 0;
105
120 ApplyView& afView,
121 boost::container::flat_set<uint256>& ofrsToRm,
122 EitherAmount const& in) = 0;
123
129 cachedIn() const = 0;
130
136 cachedOut() const = 0;
137
144 {
145 return std::nullopt;
146 }
147
148 // for debugging. Return the src and dst accounts for a direct step
149 // For XRP endpoints, one of src or dst will be the root account
152 {
153 return std::nullopt;
154 }
155
164 virtual DebtDirection
165 debtDirection(ReadView const& sb, StrandDirection dir) const = 0;
166
170 virtual std::uint32_t
172 {
173 return QUALITY_ONE;
174 }
175
176 // clang-format off
191 // clang-format on
193 qualityUpperBound(ReadView const& v, DebtDirection prevStepDir) const = 0;
194
203 getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const;
204
212 virtual std::uint32_t
214 {
215 return 0;
216 }
217
221 virtual std::optional<Book>
223 {
224 return std::nullopt;
225 }
226
230 virtual bool
231 isZero(EitherAmount const& out) const = 0;
232
238 virtual bool
239 inactive() const
240 {
241 return false;
242 }
243
247 virtual bool
248 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
249
253 virtual bool
254 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
255
268
275 friend bool
276 operator==(Step const& lhs, Step const& rhs)
277 {
278 return lhs.equal(rhs);
279 }
280
287 friend bool
288 operator!=(Step const& lhs, Step const& rhs)
289 {
290 return !(lhs == rhs);
291 }
292
295 operator<<(std::ostream& stream, Step const& step)
296 {
297 stream << step.logString();
298 return stream;
299 }
300
301private:
302 virtual std::string
303 logString() const = 0;
304
305 virtual bool
306 equal(Step const& rhs) const = 0;
307};
308
310Step::getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const
311{
312 if (auto const res = qualityUpperBound(v, prevStepDir); res.first)
313 return {
315 res.second};
316 else
317 return {std::nullopt, res.second};
318}
319
322
323inline std::uint32_t
324offersUsed(Strand const& strand)
325{
326 std::uint32_t r = 0;
327 for (auto const& step : strand)
328 {
329 if (step)
330 r += step->offersUsed();
331 }
332 return r;
333}
335
337inline bool
338operator==(Strand const& lhs, Strand const& rhs)
339{
340 if (lhs.size() != rhs.size())
341 return false;
342 for (size_t i = 0, e = lhs.size(); i != e; ++i)
343 if (*lhs[i] != *rhs[i])
344 return false;
345 return true;
346}
348
349/*
350 Normalize a path by inserting implied accounts and offers
351
352 @param src Account that is sending assets
353 @param dst Account that is receiving assets
354 @param deliver Asset the dst account will receive
355 (if issuer of deliver == dst, then accept any issuer)
356 @param sendMax Optional asset to send.
357 @param path Liquidity sources to use for this strand of the payment. The path
358 contains an ordered collection of the offer books to use and
359 accounts to ripple through.
360 @return error code and normalized path
361*/
364 AccountID const& src,
365 AccountID const& dst,
366 Issue const& deliver,
367 std::optional<Issue> const& sendMaxIssue,
368 STPath const& path);
369
395 ReadView const& sb,
396 AccountID const& src,
397 AccountID const& dst,
398 Issue const& deliver,
399 std::optional<Quality> const& limitQuality,
400 std::optional<Issue> const& sendMaxIssue,
401 STPath const& path,
402 bool ownerPaysTransferFee,
403 OfferCrossing offerCrossing,
404 AMMContext& ammContext,
406
434 ReadView const& sb,
435 AccountID const& src,
436 AccountID const& dst,
437 Issue const& deliver,
438 std::optional<Quality> const& limitQuality,
439 std::optional<Issue> const& sendMax,
440 STPathSet const& paths,
441 bool addDefaultPath,
442 bool ownerPaysTransferFee,
443 OfferCrossing offerCrossing,
444 AMMContext& ammContext,
446
448template <class TIn, class TOut, class TDerived>
449struct StepImp : public Step
450{
451 explicit StepImp() = default;
452
454 rev(PaymentSandbox& sb,
455 ApplyView& afView,
456 boost::container::flat_set<uint256>& ofrsToRm,
457 EitherAmount const& out) override
458 {
459 auto const r = static_cast<TDerived*>(this)->revImp(
460 sb, afView, ofrsToRm, get<TOut>(out));
461 return {EitherAmount(r.first), EitherAmount(r.second)};
462 }
463
464 // Given the requested amount to consume, compute the amount produced.
465 // Return the consumed/produced
467 fwd(PaymentSandbox& sb,
468 ApplyView& afView,
469 boost::container::flat_set<uint256>& ofrsToRm,
470 EitherAmount const& in) override
471 {
472 auto const r = static_cast<TDerived*>(this)->fwdImp(
473 sb, afView, ofrsToRm, get<TIn>(in));
474 return {EitherAmount(r.first), EitherAmount(r.second)};
475 }
476
477 bool
478 isZero(EitherAmount const& out) const override
479 {
480 return get<TOut>(out) == beast::zero;
481 }
482
483 bool
484 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const override
485 {
486 return get<TOut>(lhs) == get<TOut>(rhs);
487 }
488
489 bool
490 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const override
491 {
492 return get<TIn>(lhs) == get<TIn>(rhs);
493 }
494};
496
498// Thrown when unexpected errors occur
499class FlowException : public std::runtime_error
500{
501public:
502 TER ter;
503
504 FlowException(TER t, std::string const& msg)
505 : std::runtime_error(msg), ter(t)
506 {
507 }
508
509 explicit FlowException(TER t) : std::runtime_error(transHuman(t)), ter(t)
510 {
511 }
512};
514
516// Check equal with tolerance
517bool
518checkNear(IOUAmount const& expected, IOUAmount const& actual);
519bool
520checkNear(XRPAmount const& expected, XRPAmount const& actual);
522
527{
528 ReadView const& view;
533 bool const isFirst;
534 bool const isLast = false;
536 OfferCrossing const
538 bool const isDefaultPath;
539 size_t const strandSize;
543 Step const* const prevStep = nullptr;
553 boost::container::flat_set<Issue>& seenBookOuts;
556
559 ReadView const& view_,
560 std::vector<std::unique_ptr<Step>> const& strand_,
561 // A strand may not include an inner node that
562 // replicates the source or destination.
563 AccountID const& strandSrc_,
564 AccountID const& strandDst_,
565 Issue const& strandDeliver_,
566 std::optional<Quality> const& limitQuality_,
567 bool isLast_,
568 bool ownerPaysTransferFee_,
569 OfferCrossing offerCrossing_,
570 bool isDefaultPath_,
571 std::array<boost::container::flat_set<Issue>, 2>&
572 seenDirectIssues_,
573 boost::container::flat_set<Issue>&
574 seenBookOuts_,
575 AMMContext& ammContext_,
576 beast::Journal j_);
577};
578
580namespace test {
581// Needed for testing
582bool
584 Step const& step,
585 AccountID const& src,
586 AccountID const& dst,
587 Currency const& currency);
588
589bool
590xrpEndpointStepEqual(Step const& step, AccountID const& acc);
591
592bool
593bookStepEqual(Step const& step, ripple::Book const& book);
594} // namespace test
595
598 StrandContext const& ctx,
599 AccountID const& src,
600 AccountID const& dst,
601 Currency const& c);
602
604make_BookStepII(StrandContext const& ctx, Issue const& in, Issue const& out);
605
607make_BookStepIX(StrandContext const& ctx, Issue const& in);
608
610make_BookStepXI(StrandContext const& ctx, Issue const& out);
611
613make_XRPEndpointStep(StrandContext const& ctx, AccountID const& acc);
614
615template <class InAmt, class OutAmt>
616bool
617isDirectXrpToXrp(Strand const& strand);
619
620} // namespace ripple
621
622#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:140
Specifies an order book.
Definition: Book.h:35
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:51
A step in a payment path.
Definition: Steps.h:84
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:171
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:288
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:239
virtual std::uint32_t offersUsed() const
Return the number of offers consumed or partially consumed the last time the step ran,...
Definition: Steps.h:213
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:222
virtual std::optional< std::pair< AccountID, AccountID > > directStepAccts() const
Definition: Steps.h:151
friend bool operator==(Step const &lhs, Step const &rhs)
Return true if lhs == rhs.
Definition: Steps.h:276
friend std::ostream & operator<<(std::ostream &stream, Step const &step)
Streaming operator for a Step.
Definition: Steps.h:295
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:310
virtual std::optional< AccountID > directStepSrcAcct() const
If this step is DirectStepI (IOU->IOU direct step), return the src account.
Definition: Steps.h:143
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:965
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:266
std::pair< TER, std::unique_ptr< Step > > make_XRPEndpointStep(StrandContext const &ctx, AccountID const &acc)
StrandDirection
Definition: Steps.h:42
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:133
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:466
OfferCrossing
Definition: Steps.h:43
@ no
Definition: Steps.h:43
@ yes
Definition: Steps.h:43
@ sell
Definition: Steps.h:43
QualityDirection
Definition: Steps.h:41
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:40
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:33
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:983
bool isDirectXrpToXrp(Strand const &strand)
Definition: PaySteps.cpp:616
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:627
STL namespace.
Context needed to build Strand Steps and for error checking.
Definition: Steps.h:527
bool const isDefaultPath
true if Strand is default path
Definition: Steps.h:538
size_t const strandSize
Length of Strand.
Definition: Steps.h:539
beast::Journal const j
Definition: Steps.h:555
boost::container::flat_set< Issue > & seenBookOuts
A strand may not include an offer that output the same issue more than once.
Definition: Steps.h:553
AccountID const strandSrc
Strand source account.
Definition: Steps.h:529
ReadView const & view
Current ReadView.
Definition: Steps.h:528
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:549
Step const *const prevStep
The previous step in the strand.
Definition: Steps.h:543
bool const ownerPaysTransferFee
true if owner, not sender, pays fee
Definition: Steps.h:535
AccountID const strandDst
Strand destination account.
Definition: Steps.h:530
OfferCrossing const offerCrossing
Yes/Sell if offer crossing, not payment.
Definition: Steps.h:537
bool const isFirst
true if Step is first in Strand
Definition: Steps.h:533
bool const isLast
true if Step is last in Strand
Definition: Steps.h:534
std::optional< Quality > const limitQuality
Worst accepted quality.
Definition: Steps.h:532
Issue const strandDeliver
Issue strand delivers.
Definition: Steps.h:531
AMMContext & ammContext
Definition: Steps.h:554