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, getCloseTime, serializedTx, transactionMeta);
152  if (amt)
153  {
154  meta[jss::delivered_amount] =
155  amt->getJson(JsonOptions::include_date);
156  }
157  else
158  {
159  // report "unavailable" which cannot be parsed into a sensible
160  // amount.
161  meta[jss::delivered_amount] = Json::Value("unavailable");
162  }
163  }
164 }
165 
166 template <class GetLedgerIndex>
169  RPC::Context const& context,
170  std::shared_ptr<STTx const> const& serializedTx,
171  TxMeta const& transactionMeta,
172  GetLedgerIndex const& getLedgerIndex)
173 {
174  if (canHaveDeliveredAmount(context, serializedTx, transactionMeta))
175  {
176  auto const getCloseTime =
177  [&context,
178  &getLedgerIndex]() -> boost::optional<NetClock::time_point> {
179  return context.ledgerMaster.getCloseTimeBySeq(getLedgerIndex());
180  };
181  return getDeliveredAmount(
182  getLedgerIndex, getCloseTime, serializedTx, transactionMeta);
183  }
184 
185  return {};
186 }
187 
190  RPC::Context const& context,
191  std::shared_ptr<STTx const> const& serializedTx,
192  TxMeta const& transactionMeta,
193  LedgerIndex const& ledgerIndex)
194 {
195  return getDeliveredAmount(
196  context, serializedTx, transactionMeta, [&ledgerIndex]() {
197  return ledgerIndex;
198  });
199 }
200 
201 void
203  Json::Value& meta,
204  RPC::JsonContext const& context,
205  std::shared_ptr<Transaction> const& transaction,
206  TxMeta const& transactionMeta)
207 {
208  auto const serializedTx = transaction->getSTransaction();
209  if (canHaveDeliveredAmount(context, serializedTx, transactionMeta))
210  {
211  auto amt = getDeliveredAmount(
212  context, serializedTx, transactionMeta, [&transaction]() {
213  return transaction->getLedger();
214  });
215 
216  if (amt)
217  {
218  meta[jss::delivered_amount] =
219  amt->getJson(JsonOptions::include_date);
220  }
221  else
222  {
223  // report "unavailable" which cannot be parsed into a sensible
224  // amount.
225  meta[jss::delivered_amount] = Json::Value("unavailable");
226  }
227  }
228 }
229 
230 } // namespace RPC
231 } // 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:53
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:189
ripple::RPC::Context::ledgerMaster
LedgerMaster & ledgerMaster
Definition: Context.h:45
ripple::sfAmount
const SF_Amount sfAmount(access, STI_AMOUNT, 1, "Amount")
Definition: SField.h:440
ripple::Application::openLedger
virtual OpenLedger & openLedger()=0
ripple::ttPAYMENT
@ ttPAYMENT
Definition: TxFormats.h:36
ripple::TxMeta
Definition: TxMeta.h:32
ripple::TxMeta::getResultTER
TER getResultTER() const
Definition: TxMeta.h:68
ripple::fix1623
const uint256 fix1623
Definition: Feature.cpp:173
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:1565
ripple::TxMeta::hasDeliveredAmount
bool hasDeliveredAmount() const
Definition: TxMeta.h:119
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:112
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