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  boost::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  auto const view = context.app.openLedger().current();
123  if (!view)
124  return false;
125  return view->rules().enabled(fix1623);
126  };
127 
129  getFix1623Enabled, serializedTx, transactionMeta);
130 }
131 
132 void
134  Json::Value& meta,
135  ReadView const& ledger,
136  std::shared_ptr<STTx const> const& serializedTx,
137  TxMeta const& transactionMeta)
138 {
139  auto const info = ledger.info();
140  auto const getFix1623Enabled = [&ledger] {
141  return ledger.rules().enabled(fix1623);
142  };
143 
145  getFix1623Enabled, serializedTx, transactionMeta))
146  {
147  auto const getLedgerIndex = [&info] { return info.seq; };
148  auto const getCloseTime = [&info] { return info.closeTime; };
149 
150  auto amt = getDeliveredAmount(
151  getLedgerIndex,
152  getCloseTime,
153  std::move(serializedTx),
154  transactionMeta);
155  if (amt)
156  {
157  meta[jss::delivered_amount] =
158  amt->getJson(JsonOptions::include_date);
159  }
160  else
161  {
162  // report "unavailable" which cannot be parsed into a sensible
163  // amount.
164  meta[jss::delivered_amount] = Json::Value("unavailable");
165  }
166  }
167 }
168 
169 template <class GetLedgerIndex>
172  RPC::Context const& context,
173  std::shared_ptr<STTx const> const& serializedTx,
174  TxMeta const& transactionMeta,
175  GetLedgerIndex const& getLedgerIndex)
176 {
177  if (canHaveDeliveredAmount(context, serializedTx, transactionMeta))
178  {
179  auto const getCloseTime =
180  [&context,
181  &getLedgerIndex]() -> boost::optional<NetClock::time_point> {
182  return context.ledgerMaster.getCloseTimeBySeq(getLedgerIndex());
183  };
184  return getDeliveredAmount(
185  getLedgerIndex,
186  getCloseTime,
187  std::move(serializedTx),
188  transactionMeta);
189  }
190 
191  return {};
192 }
193 
196  RPC::Context const& context,
197  std::shared_ptr<STTx const> const& serializedTx,
198  TxMeta const& transactionMeta,
199  LedgerIndex const& ledgerIndex)
200 {
201  return getDeliveredAmount(
202  context, serializedTx, transactionMeta, [&ledgerIndex]() {
203  return ledgerIndex;
204  });
205 }
206 
207 void
209  Json::Value& meta,
210  RPC::JsonContext const& context,
211  std::shared_ptr<Transaction> const& transaction,
212  TxMeta const& transactionMeta)
213 {
214  auto const serializedTx = transaction->getSTransaction();
215  if (canHaveDeliveredAmount(context, serializedTx, transactionMeta))
216  {
217  auto amt = getDeliveredAmount(
218  context, serializedTx, transactionMeta, [&transaction]() {
219  return transaction->getLedger();
220  });
221 
222  if (amt)
223  {
224  meta[jss::delivered_amount] =
225  amt->getJson(JsonOptions::include_date);
226  }
227  else
228  {
229  // report "unavailable" which cannot be parsed into a sensible
230  // amount.
231  meta[jss::delivered_amount] = Json::Value("unavailable");
232  }
233  }
234 }
235 
236 } // namespace RPC
237 } // namespace ripple
ripple::ReadView::info
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
ripple::JsonOptions::include_date
@ include_date
ripple::RPC::JsonContext
Definition: Context.h:52
ripple::ttACCOUNT_DELETE
@ ttACCOUNT_DELETE
Definition: TxFormats.h:57
ripple::OpenLedger::current
std::shared_ptr< OpenView const > current() const
Returns a view to the current open ledger.
Definition: OpenLedger.cpp:50
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:195
ripple::RPC::Context::ledgerMaster
LedgerMaster & ledgerMaster
Definition: Context.h:45
ripple::sfAmount
const SF_Amount sfAmount(access, STI_AMOUNT, 1, "Amount")
Definition: SField.h:437
ripple::Application::openLedger
virtual OpenLedger & openLedger()=0
ripple::ttPAYMENT
@ ttPAYMENT
Definition: TxFormats.h:36
ripple::TxMeta
Definition: TxMeta.h:33
ripple::TxMeta::getResultTER
TER getResultTER() const
Definition: TxMeta.h:94
ripple::fix1623
const uint256 fix1623
Definition: Feature.cpp:170
ripple::RPC::Context::app
Application & app
Definition: Context.h:42
std::chrono::time_point
ripple::ttCHECK_CASH
@ ttCHECK_CASH
Definition: TxFormats.h:53
std::uint32_t
ripple::Rules::enabled
bool enabled(uint256 const &id) const
Returns true if a feature is enabled.
Definition: ReadView.cpp:103
ripple::TxType
TxType
Transaction type identifiers.
Definition: TxFormats.h:33
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:188
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::ReadView::rules
virtual Rules const & rules() const =0
Returns the tx processing rules.
ripple::LedgerMaster::getCloseTimeBySeq
boost::optional< NetClock::time_point > getCloseTimeBySeq(LedgerIndex ledgerIndex)
Definition: LedgerMaster.cpp:1528
ripple::TxMeta::hasDeliveredAmount
bool hasDeliveredAmount() const
Definition: TxMeta.h:149
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:133
std::optional
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:142
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:213
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