rippled
Flow.cpp
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 #include <ripple/app/paths/Credit.h>
21 #include <ripple/app/paths/Flow.h>
22 #include <ripple/app/paths/impl/AmountSpec.h>
23 #include <ripple/app/paths/impl/Steps.h>
24 #include <ripple/app/paths/impl/StrandFlow.h>
25 #include <ripple/basics/IOUAmount.h>
26 #include <ripple/basics/Log.h>
27 #include <ripple/basics/XRPAmount.h>
28 
29 #include <boost/container/flat_set.hpp>
30 
31 #include <numeric>
32 #include <sstream>
33 
34 namespace ripple {
35 
36 template <class FlowResult>
37 static auto
38 finishFlow(
39  PaymentSandbox& sb,
40  Issue const& srcIssue,
41  Issue const& dstIssue,
42  FlowResult&& f)
43 {
44  path::RippleCalc::Output result;
45  if (f.ter == tesSUCCESS)
46  f.sandbox->apply(sb);
47  else
48  result.removableOffers = std::move(f.removableOffers);
49 
50  result.setResult(f.ter);
51  result.actualAmountIn = toSTAmount(f.in, srcIssue);
52  result.actualAmountOut = toSTAmount(f.out, dstIssue);
53 
54  return result;
55 };
56 
57 path::RippleCalc::Output
58 flow(
59  PaymentSandbox& sb,
60  STAmount const& deliver,
61  AccountID const& src,
62  AccountID const& dst,
63  STPathSet const& paths,
64  bool defaultPaths,
65  bool partialPayment,
66  bool ownerPaysTransferFee,
67  bool offerCrossing,
68  std::optional<Quality> const& limitQuality,
69  std::optional<STAmount> const& sendMax,
71  path::detail::FlowDebugInfo* flowDebugInfo)
72 {
73  Issue const srcIssue = [&] {
74  if (sendMax)
75  return sendMax->issue();
76  if (!isXRP(deliver.issue().currency))
77  return Issue(deliver.issue().currency, src);
78  return xrpIssue();
79  }();
80 
81  Issue const dstIssue = deliver.issue();
82 
83  std::optional<Issue> sendMaxIssue;
84  if (sendMax)
85  sendMaxIssue = sendMax->issue();
86 
87  // convert the paths to a collection of strands. Each strand is the
88  // collection of account->account steps and book steps that may be used in
89  // this payment.
90  auto [toStrandsTer, strands] = toStrands(
91  sb,
92  src,
93  dst,
94  dstIssue,
95  limitQuality,
96  sendMaxIssue,
97  paths,
98  defaultPaths,
99  ownerPaysTransferFee,
100  offerCrossing,
101  j);
102 
103  if (toStrandsTer != tesSUCCESS)
104  {
105  path::RippleCalc::Output result;
106  result.setResult(toStrandsTer);
107  return result;
108  }
109 
110  if (j.trace())
111  {
112  j.trace() << "\nsrc: " << src << "\ndst: " << dst
113  << "\nsrcIssue: " << srcIssue << "\ndstIssue: " << dstIssue;
114  j.trace() << "\nNumStrands: " << strands.size();
115  for (auto const& curStrand : strands)
116  {
117  j.trace() << "NumSteps: " << curStrand.size();
118  for (auto const& step : curStrand)
119  {
120  j.trace() << '\n' << *step << '\n';
121  }
122  }
123  }
124 
125  const bool srcIsXRP = isXRP(srcIssue.currency);
126  const bool dstIsXRP = isXRP(dstIssue.currency);
127 
128  auto const asDeliver = toAmountSpec(deliver);
129 
130  // The src account may send either xrp or iou. The dst account may receive
131  // either xrp or iou. Since XRP and IOU amounts are represented by different
132  // types, use templates to tell `flow` about the amount types.
133  if (srcIsXRP && dstIsXRP)
134  {
135  return finishFlow(
136  sb,
137  srcIssue,
138  dstIssue,
139  flow<XRPAmount, XRPAmount>(
140  sb,
141  strands,
142  asDeliver.xrp,
143  partialPayment,
144  offerCrossing,
145  limitQuality,
146  sendMax,
147  j,
148  flowDebugInfo));
149  }
150 
151  if (srcIsXRP && !dstIsXRP)
152  {
153  return finishFlow(
154  sb,
155  srcIssue,
156  dstIssue,
157  flow<XRPAmount, IOUAmount>(
158  sb,
159  strands,
160  asDeliver.iou,
161  partialPayment,
162  offerCrossing,
163  limitQuality,
164  sendMax,
165  j,
166  flowDebugInfo));
167  }
168 
169  if (!srcIsXRP && dstIsXRP)
170  {
171  return finishFlow(
172  sb,
173  srcIssue,
174  dstIssue,
175  flow<IOUAmount, XRPAmount>(
176  sb,
177  strands,
178  asDeliver.xrp,
179  partialPayment,
180  offerCrossing,
181  limitQuality,
182  sendMax,
183  j,
184  flowDebugInfo));
185  }
186 
187  assert(!srcIsXRP && !dstIsXRP);
188  return finishFlow(
189  sb,
190  srcIssue,
191  dstIssue,
192  flow<IOUAmount, IOUAmount>(
193  sb,
194  strands,
195  asDeliver.iou,
196  partialPayment,
197  offerCrossing,
198  limitQuality,
199  sendMax,
200  j,
201  flowDebugInfo));
202 }
203 
204 } // namespace ripple
sstream
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
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::flow
path::RippleCalc::Output flow(PaymentSandbox &view, STAmount const &deliver, AccountID const &src, AccountID const &dst, STPathSet const &paths, bool defaultPaths, bool partialPayment, bool ownerPaysTransferFee, bool offerCrossing, std::optional< Quality > const &limitQuality, std::optional< STAmount > const &sendMax, beast::Journal j, path::detail::FlowDebugInfo *flowDebugInfo=nullptr)
Make a payment from the src account to the dst account.
ripple::toAmountSpec
AmountSpec toAmountSpec(STAmount const &amt)
Definition: AmountSpec.h:165
ripple::toSTAmount
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
Definition: AmountConversions.h:30
ripple::isXRP
bool isXRP(AccountID const &c)
Definition: AccountID.h:89
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::xrpIssue
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
Definition: Issue.h:95
std::optional< Quality >
numeric
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:222
ripple::AccountID
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition: AccountID.h:47