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/STLedgerEntry.h>
27 #include <ripple/protocol/TER.h>
28 
29 #include <boost/container/flat_set.hpp>
30 #include <optional>
31 
32 namespace ripple {
33 class PaymentSandbox;
34 class ReadView;
35 class ApplyView;
36 
37 enum class DebtDirection { issues, redeems };
38 enum class QualityDirection { in, out };
40 
41 inline bool
43 {
44  return dir == DebtDirection::redeems;
45 }
46 
47 inline bool
49 {
50  return dir == DebtDirection::issues;
51 }
52 
79 class Step
80 {
81 public:
82  virtual ~Step() = default;
83 
97  rev(PaymentSandbox& sb,
98  ApplyView& afView,
99  boost::container::flat_set<uint256>& ofrsToRm,
100  EitherAmount const& out) = 0;
101 
115  fwd(PaymentSandbox& sb,
116  ApplyView& afView,
117  boost::container::flat_set<uint256>& ofrsToRm,
118  EitherAmount const& in) = 0;
119 
125  cachedIn() const = 0;
126 
132  cachedOut() const = 0;
133 
140  {
141  return std::nullopt;
142  }
143 
144  // for debugging. Return the src and dst accounts for a direct step
145  // For XRP endpoints, one of src or dst will be the root account
148  {
149  return std::nullopt;
150  }
151 
160  virtual DebtDirection
161  debtDirection(ReadView const& sb, StrandDirection dir) const = 0;
162 
166  virtual std::uint32_t
167  lineQualityIn(ReadView const&) const
168  {
169  return QUALITY_ONE;
170  }
171 
172  // clang-format off
187  // clang-format on
189  qualityUpperBound(ReadView const& v, DebtDirection prevStepDir) const = 0;
190 
198  virtual std::uint32_t
199  offersUsed() const
200  {
201  return 0;
202  }
203 
207  virtual std::optional<Book>
208  bookStepBook() const
209  {
210  return std::nullopt;
211  }
212 
216  virtual bool
217  isZero(EitherAmount const& out) const = 0;
218 
224  virtual bool
225  inactive() const
226  {
227  return false;
228  }
229 
233  virtual bool
234  equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
235 
239  virtual bool
240  equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
241 
253  validFwd(PaymentSandbox& sb, ApplyView& afView, EitherAmount const& in) = 0;
254 
261  friend bool
262  operator==(Step const& lhs, Step const& rhs)
263  {
264  return lhs.equal(rhs);
265  }
266 
273  friend bool
274  operator!=(Step const& lhs, Step const& rhs)
275  {
276  return !(lhs == rhs);
277  }
278 
280  friend std::ostream&
281  operator<<(std::ostream& stream, Step const& step)
282  {
283  stream << step.logString();
284  return stream;
285  }
286 
287 private:
288  virtual std::string
289  logString() const = 0;
290 
291  virtual bool
292  equal(Step const& rhs) const = 0;
293 };
294 
296 using Strand = std::vector<std::unique_ptr<Step>>;
297 
298 inline std::uint32_t
299 offersUsed(Strand const& strand)
300 {
301  std::uint32_t r = 0;
302  for (auto const& step : strand)
303  {
304  if (step)
305  r += step->offersUsed();
306  }
307  return r;
308 }
310 
312 inline bool
313 operator==(Strand const& lhs, Strand const& rhs)
314 {
315  if (lhs.size() != rhs.size())
316  return false;
317  for (size_t i = 0, e = lhs.size(); i != e; ++i)
318  if (*lhs[i] != *rhs[i])
319  return false;
320  return true;
321 }
323 
324 /*
325  Normalize a path by inserting implied accounts and offers
326 
327  @param src Account that is sending assets
328  @param dst Account that is receiving assets
329  @param deliver Asset the dst account will receive
330  (if issuer of deliver == dst, then accept any issuer)
331  @param sendMax Optional asset to send.
332  @param path Liquidity sources to use for this strand of the payment. The path
333  contains an ordered collection of the offer books to use and
334  accounts to ripple through.
335  @return error code and normalized path
336 */
339  AccountID const& src,
340  AccountID const& dst,
341  Issue const& deliver,
342  std::optional<Issue> const& sendMaxIssue,
343  STPath const& path);
344 
368 toStrand(
369  ReadView const& sb,
370  AccountID const& src,
371  AccountID const& dst,
372  Issue const& deliver,
373  std::optional<Quality> const& limitQuality,
374  std::optional<Issue> const& sendMaxIssue,
375  STPath const& path,
376  bool ownerPaysTransferFee,
377  bool offerCrossing,
378  beast::Journal j);
379 
405 toStrands(
406  ReadView const& sb,
407  AccountID const& src,
408  AccountID const& dst,
409  Issue const& deliver,
410  std::optional<Quality> const& limitQuality,
411  std::optional<Issue> const& sendMax,
412  STPathSet const& paths,
413  bool addDefaultPath,
414  bool ownerPaysTransferFee,
415  bool offerCrossing,
416  beast::Journal j);
417 
419 template <class TIn, class TOut, class TDerived>
420 struct StepImp : public Step
421 {
422  explicit StepImp() = default;
423 
425  rev(PaymentSandbox& sb,
426  ApplyView& afView,
427  boost::container::flat_set<uint256>& ofrsToRm,
428  EitherAmount const& out) override
429  {
430  auto const r = static_cast<TDerived*>(this)->revImp(
431  sb, afView, ofrsToRm, get<TOut>(out));
432  return {EitherAmount(r.first), EitherAmount(r.second)};
433  }
434 
435  // Given the requested amount to consume, compute the amount produced.
436  // Return the consumed/produced
438  fwd(PaymentSandbox& sb,
439  ApplyView& afView,
440  boost::container::flat_set<uint256>& ofrsToRm,
441  EitherAmount const& in) override
442  {
443  auto const r = static_cast<TDerived*>(this)->fwdImp(
444  sb, afView, ofrsToRm, get<TIn>(in));
445  return {EitherAmount(r.first), EitherAmount(r.second)};
446  }
447 
448  bool
449  isZero(EitherAmount const& out) const override
450  {
451  return get<TOut>(out) == beast::zero;
452  }
453 
454  bool
455  equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const override
456  {
457  return get<TOut>(lhs) == get<TOut>(rhs);
458  }
459 
460  bool
461  equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const override
462  {
463  return get<TIn>(lhs) == get<TIn>(rhs);
464  }
465 };
467 
469 // Thrown when unexpected errors occur
470 class FlowException : public std::runtime_error
471 {
472 public:
473  TER ter;
474 
475  FlowException(TER t, std::string const& msg)
476  : std::runtime_error(msg), ter(t)
477  {
478  }
479 
480  explicit FlowException(TER t) : std::runtime_error(transHuman(t)), ter(t)
481  {
482  }
483 };
485 
487 // Check equal with tolerance
488 bool
489 checkNear(IOUAmount const& expected, IOUAmount const& actual);
490 bool
491 checkNear(XRPAmount const& expected, XRPAmount const& actual);
493 
498 {
499  ReadView const& view;
504  bool const isFirst;
505  bool const isLast = false;
506  bool const ownerPaysTransferFee;
507  bool const offerCrossing;
508  bool const isDefaultPath;
509  size_t const strandSize;
510 
513  Step const* const prevStep = nullptr;
523  boost::container::flat_set<Issue>& seenBookOuts;
525 
528  ReadView const& view_,
529  std::vector<std::unique_ptr<Step>> const& strand_,
530  // A strand may not include an inner node that
531  // replicates the source or destination.
532  AccountID const& strandSrc_,
533  AccountID const& strandDst_,
534  Issue const& strandDeliver_,
535  std::optional<Quality> const& limitQuality_,
536  bool isLast_,
537  bool ownerPaysTransferFee_,
538  bool offerCrossing_,
539  bool isDefaultPath_,
540  std::array<boost::container::flat_set<Issue>, 2>&
541  seenDirectIssues_,
542  boost::container::flat_set<Issue>&
543  seenBookOuts_,
544  beast::Journal j_);
545 };
546 
548 namespace test {
549 // Needed for testing
550 bool
552  Step const& step,
553  AccountID const& src,
554  AccountID const& dst,
555  Currency const& currency);
556 
557 bool
558 xrpEndpointStepEqual(Step const& step, AccountID const& acc);
559 
560 bool
561 bookStepEqual(Step const& step, ripple::Book const& book);
562 } // namespace test
563 
566  StrandContext const& ctx,
567  AccountID const& src,
568  AccountID const& dst,
569  Currency const& c);
570 
572 make_BookStepII(StrandContext const& ctx, Issue const& in, Issue const& out);
573 
575 make_BookStepIX(StrandContext const& ctx, Issue const& in);
576 
578 make_BookStepXI(StrandContext const& ctx, Issue const& out);
579 
581 make_XRPEndpointStep(StrandContext const& ctx, AccountID const& acc);
582 
583 template <class InAmt, class OutAmt>
584 bool
585 isDirectXrpToXrp(Strand const& strand);
587 
588 } // namespace ripple
589 
590 #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:497
ripple::StrandContext::strandSize
const size_t strandSize
Length of Strand.
Definition: Steps.h:509
ripple::issues
bool issues(DebtDirection dir)
Definition: Steps.h:48
ripple::Issue
A currency issued by an account.
Definition: Issue.h:34
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:502
ripple::DebtDirection
DebtDirection
Definition: Steps.h:37
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:1192
ripple::make_BookStepII
std::pair< TER, std::unique_ptr< Step > > make_BookStepII(StrandContext const &ctx, Issue const &in, Issue const &out)
Definition: BookStep.cpp:1180
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:139
std::pair
ripple::Step::operator!=
friend bool operator!=(Step const &lhs, Step const &rhs)
Return true if lhs != rhs.
Definition: Steps.h:274
std::vector
STL class.
ripple::StrandContext::ownerPaysTransferFee
const bool ownerPaysTransferFee
true if owner, not sender, pays fee
Definition: Steps.h:506
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:167
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:262
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, bool offerCrossing, beast::Journal j)
Create a Strand for the specified path.
Definition: PaySteps.cpp:135
ripple::test::bookStepEqual
bool bookStepEqual(Step const &step, ripple::Book const &book)
Definition: BookStep.cpp:1123
ripple::Step::operator<<
friend std::ostream & operator<<(std::ostream &stream, Step const &step)
Streaming operator for a Step.
Definition: Steps.h:281
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:39
ripple::operator==
bool operator==(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:165
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, bool offerCrossing, beast::Journal j)
Create a Strand for each specified path (including the default path, if indicated)
Definition: PaySteps.cpp:466
ripple::StrandContext::strandSrc
const AccountID strandSrc
Strand source account.
Definition: Steps.h:500
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:208
ripple::StrandContext::view
ReadView const & view
Current ReadView.
Definition: Steps.h:499
ripple::QualityDirection::out
@ out
ripple::Step::inactive
virtual bool inactive() const
Return true if the step should be considered inactive.
Definition: Steps.h:225
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::StrandContext::offerCrossing
const bool offerCrossing
true if offer crossing, not payment
Definition: Steps.h:507
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:503
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:79
ripple::TER
TERSubset< CanCvtToTER > TER
Definition: TER.h:568
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::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:523
std::runtime_error
STL class.
ripple::StrandContext::isLast
const bool isLast
true if Step is last in Strand
Definition: Steps.h:505
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:611
ripple::StrandContext::j
const beast::Journal j
Definition: Steps.h:524
ripple::transHuman
std::string transHuman(TER code)
Definition: TER.cpp:219
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:42
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:125
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::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::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_, bool offerCrossing_, bool isDefaultPath_, std::array< boost::container::flat_set< Issue >, 2 > &seenDirectIssues_, boost::container::flat_set< Issue > &seenBookOuts_, beast::Journal j_)
StrandContext constructor.
Definition: PaySteps.cpp:575
ripple::Step::logString
virtual std::string logString() const =0
std
STL namespace.
ripple::StrandContext::strandDst
const AccountID strandDst
Strand destination account.
Definition: Steps.h:501
ripple::EitherAmount
Definition: AmountSpec.h:59
ripple::StrandContext::isFirst
const bool isFirst
true if Step is first in Strand
Definition: Steps.h:504
ripple::StrandContext::prevStep
Step const *const prevStep
The previous step in the strand.
Definition: Steps.h:513
ripple::Step::directStepAccts
virtual std::optional< std::pair< AccountID, AccountID > > directStepAccts() const
Definition: Steps.h:147
optional
ripple::QualityDirection
QualityDirection
Definition: Steps.h:38
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::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:199
ripple::make_BookStepIX
std::pair< TER, std::unique_ptr< Step > > make_BookStepIX(StrandContext const &ctx, Issue const &in)
Definition: BookStep.cpp:1186
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:519
std::unique_ptr
STL class.
ripple::StrandContext::isDefaultPath
const bool isDefaultPath
true if Strand is default path
Definition: Steps.h:508
ripple::AccountID
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition: AccountID.h:47
ripple::StrandDirection::forward
@ forward