rippled
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 <ripple/app/paths/impl/AmountSpec.h>
24 #include <ripple/basics/Log.h>
25 #include <ripple/protocol/Quality.h>
26 #include <ripple/protocol/QualityFunction.h>
27 #include <ripple/protocol/STLedgerEntry.h>
28 #include <ripple/protocol/TER.h>
29 
30 #include <boost/container/flat_set.hpp>
31 #include <optional>
32 
33 namespace ripple {
34 class PaymentSandbox;
35 class ReadView;
36 class ApplyView;
37 class AMMContext;
38 
39 enum class DebtDirection { issues, redeems };
40 enum class QualityDirection { in, out };
42 enum OfferCrossing { no = 0, yes = 1, sell = 2 };
43 
44 inline bool
46 {
47  return dir == DebtDirection::redeems;
48 }
49 
50 inline bool
52 {
53  return dir == DebtDirection::issues;
54 }
55 
82 class Step
83 {
84 public:
85  virtual ~Step() = default;
86 
100  rev(PaymentSandbox& sb,
101  ApplyView& afView,
102  boost::container::flat_set<uint256>& ofrsToRm,
103  EitherAmount const& out) = 0;
104 
118  fwd(PaymentSandbox& sb,
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
170  lineQualityIn(ReadView const&) const
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
212  offersUsed() const
213  {
214  return 0;
215  }
216 
220  virtual std::optional<Book>
221  bookStepBook() const
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 
266  validFwd(PaymentSandbox& sb, ApplyView& afView, EitherAmount const& in) = 0;
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 
293  friend std::ostream&
294  operator<<(std::ostream& stream, Step const& step)
295  {
296  stream << step.logString();
297  return stream;
298  }
299 
300 private:
301  virtual std::string
302  logString() const = 0;
303 
304  virtual bool
305  equal(Step const& rhs) const = 0;
306 };
307 
309 Step::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 
320 using Strand = std::vector<std::unique_ptr<Step>>;
321 
322 inline std::uint32_t
323 offersUsed(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 
336 inline bool
337 operator==(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 
393 toStrand(
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,
404  beast::Journal j);
405 
432 toStrands(
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,
444  beast::Journal j);
445 
447 template <class TIn, class TOut, class TDerived>
448 struct 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
498 class FlowException : public std::runtime_error
499 {
500 public:
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
516 bool
517 checkNear(IOUAmount const& expected, IOUAmount const& actual);
518 bool
519 checkNear(XRPAmount const& expected, XRPAmount const& actual);
521 
526 {
527  ReadView const& view;
532  bool const isFirst;
533  bool const isLast = false;
534  bool const ownerPaysTransferFee;
535  OfferCrossing const
537  bool const isDefaultPath;
538  size_t const strandSize;
539 
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 
579 namespace test {
580 // Needed for testing
581 bool
583  Step const& step,
584  AccountID const& src,
585  AccountID const& dst,
586  Currency const& currency);
587 
588 bool
589 xrpEndpointStepEqual(Step const& step, AccountID const& acc);
590 
591 bool
592 bookStepEqual(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 
603 make_BookStepII(StrandContext const& ctx, Issue const& in, Issue const& out);
604 
606 make_BookStepIX(StrandContext const& ctx, Issue const& in);
607 
609 make_BookStepXI(StrandContext const& ctx, Issue const& out);
610 
612 make_XRPEndpointStep(StrandContext const& ctx, AccountID const& acc);
613 
614 template <class InAmt, class OutAmt>
615 bool
616 isDirectXrpToXrp(Strand const& strand);
618 
619 } // namespace ripple
620 
621 #endif
ripple::Step::equalIn
virtual bool equalIn(EitherAmount const &lhs, EitherAmount const &rhs) const =0
Return true if In of lhs == In of rhs.
ripple::StrandContext
Context needed to build Strand Steps and for error checking.
Definition: Steps.h:525
ripple::StrandContext::strandSize
const size_t strandSize
Length of Strand.
Definition: Steps.h:538
ripple::OfferCrossing
OfferCrossing
Definition: Steps.h:42
ripple::issues
bool issues(DebtDirection dir)
Definition: Steps.h:51
ripple::Issue
A currency issued by an account.
Definition: Issue.h:35
std::string
STL class.
ripple::Step::cachedIn
virtual std::optional< EitherAmount > cachedIn() const =0
Amount of currency computed coming into the Step the last time the step ran in reverse.
ripple::normalizePath
std::pair< TER, STPath > normalizePath(AccountID const &src, AccountID const &dst, Issue const &deliver, std::optional< Issue > const &sendMaxIssue, STPath const &path)
ripple::Step::isZero
virtual bool isZero(EitherAmount const &out) const =0
Check if amount is zero.
ripple::StrandContext::strandDeliver
const Issue strandDeliver
Issue strand delivers.
Definition: Steps.h:530
ripple::DebtDirection
DebtDirection
Definition: Steps.h:39
ripple::PaymentSandbox
A wrapper which makes credits unavailable to balances.
Definition: PaymentSandbox.h:112
ripple::make_BookStepXI
std::pair< TER, std::unique_ptr< Step > > make_BookStepXI(StrandContext const &ctx, Issue const &out)
Definition: BookStep.cpp:1368
ripple::make_BookStepII
std::pair< TER, std::unique_ptr< Step > > make_BookStepII(StrandContext const &ctx, Issue const &in, Issue const &out)
Definition: BookStep.cpp:1356
ripple::Step::directStepSrcAcct
virtual std::optional< AccountID > directStepSrcAcct() const
If this step is DirectStepI (IOU->IOU direct step), return the src account.
Definition: Steps.h:142
std::pair
ripple::Step::operator!=
friend bool operator!=(Step const &lhs, Step const &rhs)
Return true if lhs != rhs.
Definition: Steps.h:287
std::vector
STL class.
ripple::toStrand
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:135
ripple::StrandContext::ownerPaysTransferFee
const bool ownerPaysTransferFee
true if owner, not sender, pays fee
Definition: Steps.h:534
ripple::Step::debtDirection
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.
ripple::Step::lineQualityIn
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
ripple::checkNear
bool checkNear(IOUAmount const &expected, IOUAmount const &actual)
Definition: PaySteps.cpp:36
ripple::make_DirectStepI
std::pair< TER, std::unique_ptr< Step > > make_DirectStepI(StrandContext const &ctx, AccountID const &src, AccountID const &dst, Currency const &c)
Definition: DirectStep.cpp:976
ripple::QualityDirection::in
@ in
ripple::Step::operator==
friend bool operator==(Step const &lhs, Step const &rhs)
Return true if lhs == rhs.
Definition: Steps.h:275
ripple::StrandContext::offerCrossing
const OfferCrossing offerCrossing
Yes/Sell if offer crossing, not payment.
Definition: Steps.h:536
ripple::test::bookStepEqual
bool bookStepEqual(Step const &step, ripple::Book const &book)
Definition: BookStep.cpp:1299
ripple::Step::operator<<
friend std::ostream & operator<<(std::ostream &stream, Step const &step)
Streaming operator for a Step.
Definition: Steps.h:294
ripple::Step::equalOut
virtual bool equalOut(EitherAmount const &lhs, EitherAmount const &rhs) const =0
Return true if Out of lhs == Out of rhs.
ripple::ApplyView
Writeable view to a ledger, for applying a transaction.
Definition: ApplyView.h:134
ripple::StrandDirection
StrandDirection
Definition: Steps.h:41
ripple::operator==
bool operator==(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:165
ripple::StrandContext::strandSrc
const AccountID strandSrc
Strand source account.
Definition: Steps.h:528
ripple::base_uint< 160, detail::AccountIDTag >
ripple::Step::bookStepBook
virtual std::optional< Book > bookStepBook() const
If this step is a BookStep, return the book.
Definition: Steps.h:221
ripple::StrandContext::view
ReadView const & view
Current ReadView.
Definition: Steps.h:527
ripple::QualityDirection::out
@ out
ripple::AMMContext
Maintains AMM info per overall payment engine execution and individual iteration.
Definition: AMMContext.h:35
ripple::Step::inactive
virtual bool inactive() const
Return true if the step should be considered inactive.
Definition: Steps.h:238
ripple::Step::fwd
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.
std::ostream
STL class.
ripple::Step::equal
virtual bool equal(Step const &rhs) const =0
ripple::StrandContext::limitQuality
const std::optional< Quality > limitQuality
Worst accepted quality.
Definition: Steps.h:531
ripple::make_XRPEndpointStep
std::pair< TER, std::unique_ptr< Step > > make_XRPEndpointStep(StrandContext const &ctx, AccountID const &acc)
Definition: XRPEndpointStep.cpp:399
ripple::Step
A step in a payment path.
Definition: Steps.h:82
ripple::TER
TERSubset< CanCvtToTER > TER
Definition: TER.h:614
ripple::Step::qualityUpperBound
virtual std::pair< std::optional< Quality >, DebtDirection > qualityUpperBound(ReadView const &v, DebtDirection prevStepDir) const =0
Find an upper bound of quality for the step.
std::array
STL class.
ripple::Step::validFwd
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.
ripple::DebtDirection::redeems
@ redeems
ripple::StrandContext::ammContext
AMMContext & ammContext
Definition: Steps.h:553
ripple::StrandContext::seenBookOuts
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
std::runtime_error
STL class.
ripple::StrandContext::isLast
const bool isLast
true if Step is last in Strand
Definition: Steps.h:533
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
ripple::isDirectXrpToXrp
bool isDirectXrpToXrp(Strand const &strand)
Definition: PaySteps.cpp:618
ripple::StrandContext::j
const beast::Journal j
Definition: Steps.h:554
ripple::transHuman
std::string transHuman(TER code)
Definition: TER.cpp:255
ripple::Step::getQualityFunc
virtual std::pair< std::optional< QualityFunction >, DebtDirection > getQualityFunc(ReadView const &v, DebtDirection prevStepDir) const
Get QualityFunction.
Definition: Steps.h:309
ripple::StrandDirection::reverse
@ reverse
ripple::DebtDirection::issues
@ issues
ripple::test::directStepEqual
bool directStepEqual(Step const &step, AccountID const &src, AccountID const &dst, Currency const &currency)
Definition: DirectStep.cpp:958
ripple::redeems
bool redeems(DebtDirection dir)
Definition: Steps.h:45
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:54
ripple::Currency
base_uint< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition: UintTypes.h:56
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::StrandContext::StrandContext
StrandContext(ReadView const &view_, std::vector< std::unique_ptr< Step >> const &strand_, AccountID const &strandSrc_, AccountID const &strandDst_, Issue const &strandDeliver_, std::optional< Quality > const &limitQuality_, bool isLast_, bool ownerPaysTransferFee_, OfferCrossing offerCrossing_, bool isDefaultPath_, std::array< boost::container::flat_set< Issue >, 2 > &seenDirectIssues_, boost::container::flat_set< Issue > &seenBookOuts_, AMMContext &ammContext_, beast::Journal j_)
StrandContext constructor.
Definition: PaySteps.cpp:580
ripple::Step::cachedOut
virtual std::optional< EitherAmount > cachedOut() const =0
Amount of currency computed coming out of the Step the last time the step ran in reverse.
ripple::Step::logString
virtual std::string logString() const =0
std
STL namespace.
ripple::toStrands
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:468
ripple::no
@ no
Definition: Steps.h:42
ripple::StrandContext::strandDst
const AccountID strandDst
Strand destination account.
Definition: Steps.h:529
ripple::EitherAmount
Definition: AmountSpec.h:59
ripple::QualityFunction
Average quality of a path as a function of out: q(out) = m * out + b, where m = -1 / poolGets,...
Definition: QualityFunction.h:39
ripple::StrandContext::isFirst
const bool isFirst
true if Step is first in Strand
Definition: Steps.h:532
ripple::StrandContext::prevStep
Step const *const prevStep
The previous step in the strand.
Definition: Steps.h:542
ripple::Step::directStepAccts
virtual std::optional< std::pair< AccountID, AccountID > > directStepAccts() const
Definition: Steps.h:150
optional
ripple::QualityDirection
QualityDirection
Definition: Steps.h:40
ripple::Book
Specifies an order book.
Definition: Book.h:33
ripple::Step::rev
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.
ripple::test::xrpEndpointStepEqual
bool xrpEndpointStepEqual(Step const &step, AccountID const &acc)
Definition: XRPEndpointStep.cpp:385
ripple::Step::~Step
virtual ~Step()=default
ripple::QualityFunction::CLOBLikeTag
Definition: QualityFunction.h:55
ripple::Step::offersUsed
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
ripple::make_BookStepIX
std::pair< TER, std::unique_ptr< Step > > make_BookStepIX(StrandContext const &ctx, Issue const &in)
Definition: BookStep.cpp:1362
ripple::yes
@ yes
Definition: Steps.h:42
ripple::StrandContext::seenDirectIssues
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
std::unique_ptr
STL class.
ripple::StrandContext::isDefaultPath
const bool isDefaultPath
true if Strand is default path
Definition: Steps.h:537
ripple::AccountID
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition: AccountID.h:49
ripple::StrandDirection::forward
@ forward
ripple::sell
@ sell
Definition: Steps.h:42