rippled
DeliveredAmount.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2019 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/rpc/DeliveredAmount.h>
21 
22 #include <ripple/app/ledger/LedgerMaster.h>
23 #include <ripple/app/ledger/OpenLedger.h>
24 #include <ripple/app/misc/Transaction.h>
25 #include <ripple/ledger/View.h>
26 #include <ripple/net/RPCErr.h>
27 #include <ripple/protocol/AccountID.h>
28 #include <ripple/protocol/Feature.h>
29 #include <ripple/rpc/Context.h>
30 #include <ripple/rpc/impl/RPCHelpers.h>
31 #include <boost/algorithm/string/case_conv.hpp>
32 
33 namespace ripple {
34 namespace RPC {
35 
36 /*
37  GetLedgerIndex and GetCloseTime are lambdas that allow the close time and
38  ledger index to be lazily calculated. Without these lambdas, these values
39  would be calculated even when not needed, and in some circumstances they are
40  not trivial to compute.
41 
42  GetLedgerIndex is a callable that returns a LedgerIndex
43  GetCloseTime is a callable that returns a
44  std::optional<NetClock::time_point>
45  */
46 template <class GetLedgerIndex, class GetCloseTime>
49  GetLedgerIndex const& getLedgerIndex,
50  GetCloseTime const& getCloseTime,
51  std::shared_ptr<STTx const> const& serializedTx,
52  TxMeta const& transactionMeta)
53 {
54  if (!serializedTx)
55  return {};
56 
57  if (transactionMeta.hasDeliveredAmount())
58  {
59  return transactionMeta.getDeliveredAmount();
60  }
61 
62  if (serializedTx->isFieldPresent(sfAmount))
63  {
64  using namespace std::chrono_literals;
65 
66  // Ledger 4594095 is the first ledger in which the DeliveredAmount field
67  // was present when a partial payment was made and its absence indicates
68  // that the amount delivered is listed in the Amount field.
69  //
70  // If the ledger closed long after the DeliveredAmount code was deployed
71  // then its absence indicates that the amount delivered is listed in the
72  // Amount field. DeliveredAmount went live January 24, 2014.
73  // 446000000 is in Feb 2014, well after DeliveredAmount went live
74  if (getLedgerIndex() >= 4594095 ||
75  getCloseTime() > NetClock::time_point{446000000s})
76  {
77  return serializedTx->getFieldAmount(sfAmount);
78  }
79  }
80 
81  return {};
82 }
83 
84 // Returns true if transaction meta could contain a delivered amount field,
85 // based on transaction type, transaction result and whether fix1623 is enabled
86 template <class GetFix1623Enabled>
87 bool
89  GetFix1623Enabled const& getFix1623Enabled,
90  std::shared_ptr<STTx const> const& serializedTx,
91  TxMeta const& transactionMeta)
92 {
93  if (!serializedTx)
94  return false;
95 
96  {
97  TxType const tt{serializedTx->getTxnType()};
98  if (tt != ttPAYMENT && tt != ttCHECK_CASH && tt != ttACCOUNT_DELETE)
99  return false;
100 
101  if (tt == ttCHECK_CASH && !getFix1623Enabled())
102  return false;
103  }
104 
105  // if the transaction failed nothing could have been delivered.
106  if (transactionMeta.getResultTER() != tesSUCCESS)
107  return false;
108 
109  return true;
110 }
111 
112 // Returns true if transaction meta could contain a delivered amount field,
113 // based on transaction type, transaction result and whether fix1623 is enabled
114 bool
116  RPC::Context const& context,
117  std::shared_ptr<STTx const> const& serializedTx,
118  TxMeta const& transactionMeta)
119 {
120  // These lambdas are used to compute the values lazily
121  auto const getFix1623Enabled = [&context]() -> bool {
122  if (context.app.config().reporting())
123  {
124  auto const view = context.ledgerMaster.getValidatedLedger();
125  if (!view)
126  return false;
127  return view->rules().enabled(fix1623);
128  }
129  else
130  {
131  auto const view = context.app.openLedger().current();
132  if (!view)
133  return false;
134  return view->rules().enabled(fix1623);
135  }
136  };
137 
139  getFix1623Enabled, serializedTx, transactionMeta);
140 }
141 
142 void
144  Json::Value& meta,
145  ReadView const& ledger,
146  std::shared_ptr<STTx const> const& serializedTx,
147  TxMeta const& transactionMeta)
148 {
149  auto const info = ledger.info();
150  auto const getFix1623Enabled = [&ledger] {
151  return ledger.rules().enabled(fix1623);
152  };
153 
155  getFix1623Enabled, serializedTx, transactionMeta))
156  {
157  auto const getLedgerIndex = [&info] { return info.seq; };
158  auto const getCloseTime = [&info] { return info.closeTime; };
159 
160  auto amt = getDeliveredAmount(
161  getLedgerIndex, getCloseTime, serializedTx, transactionMeta);
162  if (amt)
163  {
164  meta[jss::delivered_amount] =
165  amt->getJson(JsonOptions::include_date);
166  }
167  else
168  {
169  // report "unavailable" which cannot be parsed into a sensible
170  // amount.
171  meta[jss::delivered_amount] = Json::Value("unavailable");
172  }
173  }
174 }
175 
176 template <class GetLedgerIndex>
179  RPC::Context const& context,
180  std::shared_ptr<STTx const> const& serializedTx,
181  TxMeta const& transactionMeta,
182  GetLedgerIndex const& getLedgerIndex)
183 {
184  if (canHaveDeliveredAmount(context, serializedTx, transactionMeta))
185  {
186  auto const getCloseTime =
187  [&context,
188  &getLedgerIndex]() -> std::optional<NetClock::time_point> {
189  return context.ledgerMaster.getCloseTimeBySeq(getLedgerIndex());
190  };
191  return getDeliveredAmount(
192  getLedgerIndex, getCloseTime, serializedTx, transactionMeta);
193  }
194 
195  return {};
196 }
197 
200  RPC::Context const& context,
201  std::shared_ptr<STTx const> const& serializedTx,
202  TxMeta const& transactionMeta,
203  LedgerIndex const& ledgerIndex)
204 {
205  return getDeliveredAmount(
206  context, serializedTx, transactionMeta, [&ledgerIndex]() {
207  return ledgerIndex;
208  });
209 }
210 
211 void
213  Json::Value& meta,
214  RPC::JsonContext const& context,
215  std::shared_ptr<Transaction> const& transaction,
216  TxMeta const& transactionMeta)
217 {
219  meta, context, transaction->getSTransaction(), transactionMeta);
220 }
221 
222 void
224  Json::Value& meta,
225  RPC::JsonContext const& context,
226  std::shared_ptr<STTx const> const& transaction,
227  TxMeta const& transactionMeta)
228 {
229  if (canHaveDeliveredAmount(context, transaction, transactionMeta))
230  {
231  auto amt = getDeliveredAmount(
232  context, transaction, transactionMeta, [&transactionMeta]() {
233  return transactionMeta.getLgrSeq();
234  });
235 
236  if (amt)
237  {
238  meta[jss::delivered_amount] =
239  amt->getJson(JsonOptions::include_date);
240  }
241  else
242  {
243  // report "unavailable" which cannot be parsed into a sensible
244  // amount.
245  meta[jss::delivered_amount] = Json::Value("unavailable");
246  }
247  }
248 }
249 
250 } // namespace RPC
251 } // namespace ripple
ripple::ReadView::info
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
ripple::JsonOptions::include_date
@ include_date
ripple::ttACCOUNT_DELETE
@ ttACCOUNT_DELETE
This transaction type deletes an existing account.
Definition: TxFormats.h:122
ripple::RPC::JsonContext
Definition: Context.h:53
ripple::OpenLedger::current
std::shared_ptr< OpenView const > current() const
Returns a view to the current open ledger.
Definition: OpenLedger.cpp:50
ripple::Rules::enabled
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition: Rules.cpp:94
std::shared_ptr
STL class.
ripple::RPC::getDeliveredAmount
std::optional< STAmount > getDeliveredAmount(RPC::Context const &context, std::shared_ptr< STTx const > const &serializedTx, TxMeta const &transactionMeta, LedgerIndex const &ledgerIndex)
Definition: DeliveredAmount.cpp:199
ripple::sfAmount
const SF_AMOUNT sfAmount
ripple::RPC::Context::ledgerMaster
LedgerMaster & ledgerMaster
Definition: Context.h:45
ripple::TxType
TxType
Transaction type identifiers.
Definition: TxFormats.h:56
ripple::Application::openLedger
virtual OpenLedger & openLedger()=0
ripple::TxMeta
Definition: TxMeta.h:32
ripple::ttPAYMENT
@ ttPAYMENT
This transaction type executes a payment.
Definition: TxFormats.h:59
ripple::TxMeta::getResultTER
TER getResultTER() const
Definition: TxMeta.h:68
ripple::Config::reporting
bool reporting() const
Definition: Config.h:337
ripple::Application::config
virtual Config & config()=0
ripple::fix1623
const uint256 fix1623
ripple::RPC::Context::app
Application & app
Definition: Context.h:42
std::chrono::time_point
std::uint32_t
ripple::TxMeta::getLgrSeq
std::uint32_t getLgrSeq() const
Definition: TxMeta.h:58
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:125
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::LedgerMaster::getCloseTimeBySeq
std::optional< NetClock::time_point > getCloseTimeBySeq(LedgerIndex ledgerIndex)
Definition: LedgerMaster.cpp:1713
ripple::ReadView::rules
virtual Rules const & rules() const =0
Returns the tx processing rules.
ripple::TxMeta::hasDeliveredAmount
bool hasDeliveredAmount() const
Definition: TxMeta.h:124
ripple::RPC::insertDeliveredAmount
void insertDeliveredAmount(Json::Value &meta, ReadView const &, std::shared_ptr< STTx const > const &serializedTx, TxMeta const &)
Add a delivered_amount field to the meta input/output parameter.
Definition: DeliveredAmount.cpp:143
ripple::ttCHECK_CASH
@ ttCHECK_CASH
This transaction type cashes an existing check.
Definition: TxFormats.h:110
ripple::LedgerMaster::getValidatedLedger
std::shared_ptr< Ledger const > getValidatedLedger()
Definition: LedgerMaster.cpp:1664
std::optional< STAmount >
ripple::RPC::canHaveDeliveredAmount
bool canHaveDeliveredAmount(RPC::Context const &context, std::shared_ptr< STTx const > const &serializedTx, TxMeta const &transactionMeta)
Definition: DeliveredAmount.cpp:115
ripple::TxMeta::getDeliveredAmount
STAmount getDeliveredAmount() const
Definition: TxMeta.h:117
ripple::RPC::canHaveDeliveredAmountHelp
bool canHaveDeliveredAmountHelp(GetFix1623Enabled const &getFix1623Enabled, std::shared_ptr< STTx const > const &serializedTx, TxMeta const &transactionMeta)
Definition: DeliveredAmount.cpp:88
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:222
ripple::RPC::Context
The context of information needed to call an RPC.
Definition: Context.h:39
Json::Value
Represents a JSON value.
Definition: json_value.h:145