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 <boost/optional.hpp>
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 
124  virtual boost::optional<EitherAmount>
125  cachedIn() const = 0;
126 
131  virtual boost::optional<EitherAmount>
132  cachedOut() const = 0;
133 
138  virtual boost::optional<AccountID>
140  {
141  return boost::none;
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
146  virtual boost::optional<std::pair<AccountID, AccountID>>
148  {
149  return boost::none;
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 
194  virtual boost::optional<Book>
195  bookStepBook() const
196  {
197  return boost::none;
198  }
199 
203  virtual bool
204  isZero(EitherAmount const& out) const = 0;
205 
211  virtual bool
212  inactive() const
213  {
214  return false;
215  }
216 
220  virtual bool
221  equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
222 
226  virtual bool
227  equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const = 0;
228 
240  validFwd(PaymentSandbox& sb, ApplyView& afView, EitherAmount const& in) = 0;
241 
248  friend bool
249  operator==(Step const& lhs, Step const& rhs)
250  {
251  return lhs.equal(rhs);
252  }
253 
260  friend bool
261  operator!=(Step const& lhs, Step const& rhs)
262  {
263  return !(lhs == rhs);
264  }
265 
267  friend std::ostream&
268  operator<<(std::ostream& stream, Step const& step)
269  {
270  stream << step.logString();
271  return stream;
272  }
273 
274 private:
275  virtual std::string
276  logString() const = 0;
277 
278  virtual bool
279  equal(Step const& rhs) const = 0;
280 };
281 
283 using Strand = std::vector<std::unique_ptr<Step>>;
285 
287 inline bool
288 operator==(Strand const& lhs, Strand const& rhs)
289 {
290  if (lhs.size() != rhs.size())
291  return false;
292  for (size_t i = 0, e = lhs.size(); i != e; ++i)
293  if (*lhs[i] != *rhs[i])
294  return false;
295  return true;
296 }
298 
299 /*
300  Normalize a path by inserting implied accounts and offers
301 
302  @param src Account that is sending assets
303  @param dst Account that is receiving assets
304  @param deliver Asset the dst account will receive
305  (if issuer of deliver == dst, then accept any issuer)
306  @param sendMax Optional asset to send.
307  @param path Liquidity sources to use for this strand of the payment. The path
308  contains an ordered collection of the offer books to use and
309  accounts to ripple through.
310  @return error code and normalized path
311 */
314  AccountID const& src,
315  AccountID const& dst,
316  Issue const& deliver,
317  boost::optional<Issue> const& sendMaxIssue,
318  STPath const& path);
319 
343 toStrand(
344  ReadView const& sb,
345  AccountID const& src,
346  AccountID const& dst,
347  Issue const& deliver,
348  boost::optional<Quality> const& limitQuality,
349  boost::optional<Issue> const& sendMaxIssue,
350  STPath const& path,
351  bool ownerPaysTransferFee,
352  bool offerCrossing,
353  beast::Journal j);
354 
380 toStrands(
381  ReadView const& sb,
382  AccountID const& src,
383  AccountID const& dst,
384  Issue const& deliver,
385  boost::optional<Quality> const& limitQuality,
386  boost::optional<Issue> const& sendMax,
387  STPathSet const& paths,
388  bool addDefaultPath,
389  bool ownerPaysTransferFee,
390  bool offerCrossing,
391  beast::Journal j);
392 
394 template <class TIn, class TOut, class TDerived>
395 struct StepImp : public Step
396 {
397  explicit StepImp() = default;
398 
400  rev(PaymentSandbox& sb,
401  ApplyView& afView,
402  boost::container::flat_set<uint256>& ofrsToRm,
403  EitherAmount const& out) override
404  {
405  auto const r = static_cast<TDerived*>(this)->revImp(
406  sb, afView, ofrsToRm, get<TOut>(out));
407  return {EitherAmount(r.first), EitherAmount(r.second)};
408  }
409 
410  // Given the requested amount to consume, compute the amount produced.
411  // Return the consumed/produced
413  fwd(PaymentSandbox& sb,
414  ApplyView& afView,
415  boost::container::flat_set<uint256>& ofrsToRm,
416  EitherAmount const& in) override
417  {
418  auto const r = static_cast<TDerived*>(this)->fwdImp(
419  sb, afView, ofrsToRm, get<TIn>(in));
420  return {EitherAmount(r.first), EitherAmount(r.second)};
421  }
422 
423  bool
424  isZero(EitherAmount const& out) const override
425  {
426  return get<TOut>(out) == beast::zero;
427  }
428 
429  bool
430  equalOut(EitherAmount const& lhs, EitherAmount const& rhs) const override
431  {
432  return get<TOut>(lhs) == get<TOut>(rhs);
433  }
434 
435  bool
436  equalIn(EitherAmount const& lhs, EitherAmount const& rhs) const override
437  {
438  return get<TIn>(lhs) == get<TIn>(rhs);
439  }
440 };
442 
444 // Thrown when unexpected errors occur
445 class FlowException : public std::runtime_error
446 {
447 public:
448  TER ter;
449 
450  FlowException(TER t, std::string const& msg)
451  : std::runtime_error(msg), ter(t)
452  {
453  }
454 
455  explicit FlowException(TER t) : std::runtime_error(transHuman(t)), ter(t)
456  {
457  }
458 };
460 
462 // Check equal with tolerance
463 bool
464 checkNear(IOUAmount const& expected, IOUAmount const& actual);
465 bool
466 checkNear(XRPAmount const& expected, XRPAmount const& actual);
468 
473 {
474  ReadView const& view;
478  boost::optional<Quality> const limitQuality;
479  bool const isFirst;
480  bool const isLast = false;
481  bool const ownerPaysTransferFee;
482  bool const offerCrossing;
483  bool const isDefaultPath;
484  size_t const strandSize;
485 
488  Step const* const prevStep = nullptr;
498  boost::container::flat_set<Issue>& seenBookOuts;
500 
503  ReadView const& view_,
504  std::vector<std::unique_ptr<Step>> const& strand_,
505  // A strand may not include an inner node that
506  // replicates the source or destination.
507  AccountID const& strandSrc_,
508  AccountID const& strandDst_,
509  Issue const& strandDeliver_,
510  boost::optional<Quality> const& limitQuality_,
511  bool isLast_,
512  bool ownerPaysTransferFee_,
513  bool offerCrossing_,
514  bool isDefaultPath_,
515  std::array<boost::container::flat_set<Issue>, 2>&
516  seenDirectIssues_,
517  boost::container::flat_set<Issue>&
518  seenBookOuts_,
519  beast::Journal j_);
520 };
521 
523 namespace test {
524 // Needed for testing
525 bool
527  Step const& step,
528  AccountID const& src,
529  AccountID const& dst,
530  Currency const& currency);
531 
532 bool
533 xrpEndpointStepEqual(Step const& step, AccountID const& acc);
534 
535 bool
536 bookStepEqual(Step const& step, ripple::Book const& book);
537 } // namespace test
538 
541  StrandContext const& ctx,
542  AccountID const& src,
543  AccountID const& dst,
544  Currency const& c);
545 
547 make_BookStepII(StrandContext const& ctx, Issue const& in, Issue const& out);
548 
550 make_BookStepIX(StrandContext const& ctx, Issue const& in);
551 
553 make_BookStepXI(StrandContext const& ctx, Issue const& out);
554 
556 make_XRPEndpointStep(StrandContext const& ctx, AccountID const& acc);
557 
558 template <class InAmt, class OutAmt>
559 bool
560 isDirectXrpToXrp(Strand const& strand);
562 
563 } // namespace ripple
564 
565 #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:472
ripple::StrandContext::strandSize
const size_t strandSize
Length of Strand.
Definition: Steps.h:484
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::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:477
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:1173
ripple::make_BookStepII
std::pair< TER, std::unique_ptr< Step > > make_BookStepII(StrandContext const &ctx, Issue const &in, Issue const &out)
Definition: BookStep.cpp:1161
std::pair
ripple::Step::operator!=
friend bool operator!=(Step const &lhs, Step const &rhs)
Return true if lhs != rhs.
Definition: Steps.h:261
std::vector
STL class.
ripple::normalizePath
std::pair< TER, STPath > normalizePath(AccountID const &src, AccountID const &dst, Issue const &deliver, boost::optional< Issue > const &sendMaxIssue, STPath const &path)
ripple::StrandContext::ownerPaysTransferFee
const bool ownerPaysTransferFee
true if owner, not sender, pays fee
Definition: Steps.h:481
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::toStrand
std::pair< TER, Strand > toStrand(ReadView const &view, AccountID const &src, AccountID const &dst, Issue const &deliver, boost::optional< Quality > const &limitQuality, boost::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::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:977
ripple::QualityDirection::in
@ in
ripple::Step::operator==
friend bool operator==(Step const &lhs, Step const &rhs)
Return true if lhs == rhs.
Definition: Steps.h:249
ripple::Step::bookStepBook
virtual boost::optional< Book > bookStepBook() const
If this step is a BookStep, return the book.
Definition: Steps.h:195
ripple::test::bookStepEqual
bool bookStepEqual(Step const &step, ripple::Book const &book)
Definition: BookStep.cpp:1104
ripple::Step::operator<<
friend std::ostream & operator<<(std::ostream &stream, Step const &step)
Streaming operator for a Step.
Definition: Steps.h:268
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:140
ripple::StrandDirection
StrandDirection
Definition: Steps.h:39
ripple::operator==
bool operator==(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:155
ripple::Step::cachedOut
virtual boost::optional< EitherAmount > cachedOut() const =0
Amount of currency computed coming out of the Step the last time the step ran in reverse.
ripple::StrandContext::strandSrc
const AccountID strandSrc
Strand source account.
Definition: Steps.h:475
ripple::base_uint< 160, detail::AccountIDTag >
ripple::StrandContext::view
ReadView const & view
Current ReadView.
Definition: Steps.h:474
ripple::QualityDirection::out
@ out
ripple::Step::inactive
virtual bool inactive() const
Return true if the step should be considered inactive.
Definition: Steps.h:212
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:482
ripple::Step::equal
virtual bool equal(Step const &rhs) const =0
ripple::Step::cachedIn
virtual boost::optional< EitherAmount > cachedIn() const =0
Amount of currency computed coming into 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_, boost::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::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:547
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:498
std::runtime_error
STL class.
ripple::StrandContext::isLast
const bool isLast
true if Step is last in Strand
Definition: Steps.h:480
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:499
ripple::transHuman
std::string transHuman(TER code)
Definition: TER.cpp:202
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:959
ripple::redeems
bool redeems(DebtDirection dir)
Definition: Steps.h:42
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:188
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::logString
virtual std::string logString() const =0
std
STL namespace.
ripple::Step::qualityUpperBound
virtual std::pair< boost::optional< Quality >, DebtDirection > qualityUpperBound(ReadView const &v, DebtDirection prevStepDir) const =0
Find an upper bound of quality for the step.
ripple::StrandContext::strandDst
const AccountID strandDst
Strand destination account.
Definition: Steps.h:476
ripple::EitherAmount
Definition: AmountSpec.h:57
ripple::StrandContext::isFirst
const bool isFirst
true if Step is first in Strand
Definition: Steps.h:479
ripple::StrandContext::prevStep
Step const *const prevStep
The previous step in the strand.
Definition: Steps.h:488
ripple::QualityDirection
QualityDirection
Definition: Steps.h:38
ripple::StrandContext::limitQuality
const boost::optional< Quality > limitQuality
Worst accepted quality.
Definition: Steps.h:478
ripple::Book
Specifies an order book.
Definition: Book.h:32
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::toStrands
std::pair< TER, std::vector< Strand > > toStrands(ReadView const &view, AccountID const &src, AccountID const &dst, Issue const &deliver, boost::optional< Quality > const &limitQuality, boost::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::Step::~Step
virtual ~Step()=default
ripple::make_BookStepIX
std::pair< TER, std::unique_ptr< Step > > make_BookStepIX(StrandContext const &ctx, Issue const &in)
Definition: BookStep.cpp:1167
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:494
std::unique_ptr
STL class.
ripple::StrandContext::isDefaultPath
const bool isDefaultPath
true if Strand is default path
Definition: Steps.h:483
ripple::Step::directStepSrcAcct
virtual boost::optional< AccountID > directStepSrcAcct() const
If this step is DirectStepI (IOU->IOU direct step), return the src account.
Definition: Steps.h:139
ripple::Step::directStepAccts
virtual boost::optional< std::pair< AccountID, AccountID > > directStepAccts() const
Definition: Steps.h:147
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