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/protocol/Quality.h>
27#include <xrpl/protocol/QualityFunction.h>
28#include <xrpl/protocol/STLedgerEntry.h>
29#include <xrpl/protocol/TER.h>
30
31#include <boost/container/flat_set.hpp>
32
33#include <optional>
34
35namespace ripple {
36class PaymentSandbox;
37class ReadView;
38class ApplyView;
39class AMMContext;
40
42enum class QualityDirection { in, out };
44enum OfferCrossing { no = 0, yes = 1, sell = 2 };
45
46inline bool
48{
49 return dir == DebtDirection::redeems;
50}
51
52inline bool
54{
55 return dir == DebtDirection::issues;
56}
57
84class Step
85{
86public:
87 virtual ~Step() = default;
88
103 ApplyView& afView,
104 boost::container::flat_set<uint256>& ofrsToRm,
105 EitherAmount const& out) = 0;
106
121 ApplyView& afView,
122 boost::container::flat_set<uint256>& ofrsToRm,
123 EitherAmount const& in) = 0;
124
130 cachedIn() const = 0;
131
137 cachedOut() const = 0;
138
145 {
146 return std::nullopt;
147 }
148
149 // for debugging. Return the src and dst accounts for a direct step
150 // For XRP endpoints, one of src or dst will be the root account
153 {
154 return std::nullopt;
155 }
156
165 virtual DebtDirection
166 debtDirection(ReadView const& sb, StrandDirection dir) const = 0;
167
171 virtual std::uint32_t
173 {
174 return QUALITY_ONE;
175 }
176
177 // clang-format off
192 // clang-format on
194 qualityUpperBound(ReadView const& v, DebtDirection prevStepDir) const = 0;
195
204 getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const;
205
213 virtual std::uint32_t
215 {
216 return 0;
217 }
218
222 virtual std::optional<Book>
224 {
225 return std::nullopt;
226 }
227
231 virtual bool
232 isZero(EitherAmount const& out) const = 0;
233
239 virtual bool
240 inactive() const
241 {
242 return false;
243 }
244
248 virtual bool
249 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
250
254 virtual bool
255 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
256
269
276 friend bool
277 operator==(Step const& lhs, Step const& rhs)
278 {
279 return lhs.equal(rhs);
280 }
281
288 friend bool
289 operator!=(Step const& lhs, Step const& rhs)
290 {
291 return !(lhs == rhs);
292 }
293
296 operator<<(std::ostream& stream, Step const& step)
297 {
298 stream << step.logString();
299 return stream;
300 }
301
302private:
303 virtual std::string
304 logString() const = 0;
305
306 virtual bool
307 equal(Step const& rhs) const = 0;
308};
309
311Step::getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const
312{
313 if (auto const res = qualityUpperBound(v, prevStepDir); res.first)
314 return {
316 res.second};
317 else
318 return {std::nullopt, res.second};
319}
320
323
324inline std::uint32_t
325offersUsed(Strand const& strand)
326{
327 std::uint32_t r = 0;
328 for (auto const& step : strand)
329 {
330 if (step)
331 r += step->offersUsed();
332 }
333 return r;
334}
336
338inline bool
339operator==(Strand const& lhs, Strand const& rhs)
340{
341 if (lhs.size() != rhs.size())
342 return false;
343 for (size_t i = 0, e = lhs.size(); i != e; ++i)
344 if (*lhs[i] != *rhs[i])
345 return false;
346 return true;
347}
349
350/*
351 Normalize a path by inserting implied accounts and offers
352
353 @param src Account that is sending assets
354 @param dst Account that is receiving assets
355 @param deliver Asset the dst account will receive
356 (if issuer of deliver == dst, then accept any issuer)
357 @param sendMax Optional asset to send.
358 @param path Liquidity sources to use for this strand of the payment. The path
359 contains an ordered collection of the offer books to use and
360 accounts to ripple through.
361 @return error code and normalized path
362*/
365 AccountID const& src,
366 AccountID const& dst,
367 Issue const& deliver,
368 std::optional<Issue> const& sendMaxIssue,
369 STPath const& path);
370
396 ReadView const& sb,
397 AccountID const& src,
398 AccountID const& dst,
399 Issue const& deliver,
400 std::optional<Quality> const& limitQuality,
401 std::optional<Issue> const& sendMaxIssue,
402 STPath const& path,
403 bool ownerPaysTransferFee,
404 OfferCrossing offerCrossing,
405 AMMContext& ammContext,
407
435 ReadView const& sb,
436 AccountID const& src,
437 AccountID const& dst,
438 Issue const& deliver,
439 std::optional<Quality> const& limitQuality,
440 std::optional<Issue> const& sendMax,
441 STPathSet const& paths,
442 bool addDefaultPath,
443 bool ownerPaysTransferFee,
444 OfferCrossing offerCrossing,
445 AMMContext& ammContext,
447
449template <class TIn, class TOut, class TDerived>
450struct StepImp : public Step
451{
452 explicit StepImp() = default;
453
455 rev(PaymentSandbox& sb,
456 ApplyView& afView,
457 boost::container::flat_set<uint256>& ofrsToRm,
458 EitherAmount const& out) override
459 {
460 auto const r = static_cast<TDerived*>(this)->revImp(
461 sb, afView, ofrsToRm, get<TOut>(out));
462 return {EitherAmount(r.first), EitherAmount(r.second)};
463 }
464
465 // Given the requested amount to consume, compute the amount produced.
466 // Return the consumed/produced
468 fwd(PaymentSandbox& sb,
469 ApplyView& afView,
470 boost::container::flat_set<uint256>& ofrsToRm,
471 EitherAmount const& in) override
472 {
473 auto const r = static_cast<TDerived*>(this)->fwdImp(
474 sb, afView, ofrsToRm, get<TIn>(in));
475 return {EitherAmount(r.first), EitherAmount(r.second)};
476 }
477
478 bool
479 isZero(EitherAmount const& out) const override
480 {
481 return get<TOut>(out) == beast::zero;
482 }
483
484 bool
485 equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const override
486 {
487 return get<TOut>(lhs) == get<TOut>(rhs);
488 }
489
490 bool
491 equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const override
492 {
493 return get<TIn>(lhs) == get<TIn>(rhs);
494 }
495};
497
499// Thrown when unexpected errors occur
500class FlowException : public std::runtime_error
501{
502public:
503 TER ter;
504
505 FlowException(TER t, std::string const& msg)
506 : std::runtime_error(msg), ter(t)
507 {
508 }
509
510 explicit FlowException(TER t) : std::runtime_error(transHuman(t)), ter(t)
511 {
512 }
513};
515
517// Check equal with tolerance
518bool
519checkNear(IOUAmount const& expected, IOUAmount const& actual);
520bool
521checkNear(XRPAmount const& expected, XRPAmount const& actual);
523
528{
529 ReadView const& view;
534 bool const isFirst;
535 bool const isLast = false;
537 OfferCrossing const
539 bool const isDefaultPath;
540 size_t const strandSize;
544 Step const* const prevStep = nullptr;
554 boost::container::flat_set<Issue>& seenBookOuts;
557
560 ReadView const& view_,
561 std::vector<std::unique_ptr<Step>> const& strand_,
562 // A strand may not include an inner node that
563 // replicates the source or destination.
564 AccountID const& strandSrc_,
565 AccountID const& strandDst_,
566 Issue const& strandDeliver_,
567 std::optional<Quality> const& limitQuality_,
568 bool isLast_,
569 bool ownerPaysTransferFee_,
570 OfferCrossing offerCrossing_,
571 bool isDefaultPath_,
572 std::array<boost::container::flat_set<Issue>, 2>&
573 seenDirectIssues_,
574 boost::container::flat_set<Issue>&
575 seenBookOuts_,
576 AMMContext& ammContext_,
577 beast::Journal j_);
578};
579
581namespace test {
582// Needed for testing
583bool
585 Step const& step,
586 AccountID const& src,
587 AccountID const& dst,
588 Currency const& currency);
589
590bool
591xrpEndpointStepEqual(Step const& step, AccountID const& acc);
592
593bool
594bookStepEqual(Step const& step, ripple::Book const& book);
595} // namespace test
596
599 StrandContext const& ctx,
600 AccountID const& src,
601 AccountID const& dst,
602 Currency const& c);
603
605make_BookStepII(StrandContext const& ctx, Issue const& in, Issue const& out);
606
608make_BookStepIX(StrandContext const& ctx, Issue const& in);
609
611make_BookStepXI(StrandContext const& ctx, Issue const& out);
612
614make_XRPEndpointStep(StrandContext const& ctx, AccountID const& acc);
615
616template <class InAmt, class OutAmt>
617bool
618isDirectXrpToXrp(Strand const& strand);
620
621} // namespace ripple
622
623#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:141
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:52
A step in a payment path.
Definition: Steps.h:85
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:172
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:289
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:240
virtual std::uint32_t offersUsed() const
Return the number of offers consumed or partially consumed the last time the step ran,...
Definition: Steps.h:214
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:223
virtual std::optional< std::pair< AccountID, AccountID > > directStepAccts() const
Definition: Steps.h:152
friend bool operator==(Step const &lhs, Step const &rhs)
Return true if lhs == rhs.
Definition: Steps.h:277
friend std::ostream & operator<<(std::ostream &stream, Step const &step)
Streaming operator for a Step.
Definition: Steps.h:296
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:311
virtual std::optional< AccountID > directStepSrcAcct() const
If this step is DirectStepI (IOU->IOU direct step), return the src account.
Definition: Steps.h:144
Add a path.
Definition: paths.h:58
Set Paths, SendMax on a JTx.
Definition: paths.h:35
bool xrpEndpointStepEqual(Step const &step, AccountID const &acc)
bool bookStepEqual(Step const &step, ripple::Book const &book)
Definition: BookStep.cpp:1415
bool directStepEqual(Step const &step, AccountID const &src, AccountID const &dst, Currency const &currency)
Definition: DirectStep.cpp:967
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:270
std::pair< TER, std::unique_ptr< Step > > make_XRPEndpointStep(StrandContext const &ctx, AccountID const &acc)
StrandDirection
Definition: Steps.h:43
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:134
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:467
OfferCrossing
Definition: Steps.h:44
@ no
Definition: Steps.h:44
@ yes
Definition: Steps.h:44
@ sell
Definition: Steps.h:44
QualityDirection
Definition: Steps.h:42
std::pair< TER, std::unique_ptr< Step > > make_BookStepXI(StrandContext const &ctx, Issue const &out)
Definition: BookStep.cpp:1484
base_uint< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition: UintTypes.h:56
DebtDirection
Definition: Steps.h:41
std::pair< TER, std::unique_ptr< Step > > make_BookStepIX(StrandContext const &ctx, Issue const &in)
Definition: BookStep.cpp:1478
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)
Definition: BookStep.cpp:1472
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:985
bool isDirectXrpToXrp(Strand const &strand)
Definition: PaySteps.cpp:617
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:643
STL namespace.
Context needed to build Strand Steps and for error checking.
Definition: Steps.h:528
bool const isDefaultPath
true if Strand is default path
Definition: Steps.h:539
size_t const strandSize
Length of Strand.
Definition: Steps.h:540
beast::Journal const j
Definition: Steps.h:556
boost::container::flat_set< Issue > & seenBookOuts
A strand may not include an offer that output the same issue more than once.
Definition: Steps.h:554
AccountID const strandSrc
Strand source account.
Definition: Steps.h:530
ReadView const & view
Current ReadView.
Definition: Steps.h:529
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:550
Step const *const prevStep
The previous step in the strand.
Definition: Steps.h:544
bool const ownerPaysTransferFee
true if owner, not sender, pays fee
Definition: Steps.h:536
AccountID const strandDst
Strand destination account.
Definition: Steps.h:531
OfferCrossing const offerCrossing
Yes/Sell if offer crossing, not payment.
Definition: Steps.h:538
bool const isFirst
true if Step is first in Strand
Definition: Steps.h:534
bool const isLast
true if Step is last in Strand
Definition: Steps.h:535
std::optional< Quality > const limitQuality
Worst accepted quality.
Definition: Steps.h:533
Issue const strandDeliver
Issue strand delivers.
Definition: Steps.h:532
AMMContext & ammContext
Definition: Steps.h:555