rippled
Loading...
Searching...
No Matches
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 <xrpld/rpc/DeliveredAmount.h>
21
22#include <xrpld/app/ledger/LedgerMaster.h>
23#include <xrpld/app/ledger/OpenLedger.h>
24#include <xrpld/app/misc/Transaction.h>
25#include <xrpld/ledger/View.h>
26#include <xrpld/rpc/Context.h>
27#include <xrpld/rpc/detail/RPCHelpers.h>
28#include <xrpl/protocol/AccountID.h>
29#include <xrpl/protocol/Feature.h>
30#include <xrpl/protocol/RPCErr.h>
31#include <boost/algorithm/string/case_conv.hpp>
32
33namespace ripple {
34namespace 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 */
46template <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
86template <class GetFix1623Enabled>
87bool
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
114bool
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
132void
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
166template <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]() -> std::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
201void
203 Json::Value& meta,
204 RPC::JsonContext const& context,
205 std::shared_ptr<Transaction> const& transaction,
206 TxMeta const& transactionMeta)
207{
209 meta, context, transaction->getSTransaction(), transactionMeta);
210}
211
212void
214 Json::Value& meta,
215 RPC::JsonContext const& context,
216 std::shared_ptr<STTx const> const& transaction,
217 TxMeta const& transactionMeta)
218{
219 if (canHaveDeliveredAmount(context, transaction, transactionMeta))
220 {
221 auto amt = getDeliveredAmount(
222 context, transaction, transactionMeta, [&transactionMeta]() {
223 return transactionMeta.getLgrSeq();
224 });
225
226 if (amt)
227 {
228 meta[jss::delivered_amount] =
229 amt->getJson(JsonOptions::include_date);
230 }
231 else
232 {
233 // report "unavailable" which cannot be parsed into a sensible
234 // amount.
235 meta[jss::delivered_amount] = Json::Value("unavailable");
236 }
237 }
238}
239
240} // namespace RPC
241} // namespace ripple
Represents a JSON value.
Definition: json_value.h:147
virtual OpenLedger & openLedger()=0
std::optional< NetClock::time_point > getCloseTimeBySeq(LedgerIndex ledgerIndex)
std::shared_ptr< OpenView const > current() const
Returns a view to the current open ledger.
Definition: OpenLedger.cpp:50
A view into a ledger.
Definition: ReadView.h:55
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition: Rules.cpp:122
bool hasDeliveredAmount() const
Definition: TxMeta.h:126
STAmount getDeliveredAmount() const
Definition: TxMeta.h:117
std::uint32_t getLgrSeq() const
Definition: TxMeta.h:58
TER getResultTER() const
Definition: TxMeta.h:68
bool canHaveDeliveredAmount(RPC::Context const &context, std::shared_ptr< STTx const > const &serializedTx, TxMeta const &transactionMeta)
bool canHaveDeliveredAmountHelp(GetFix1623Enabled const &getFix1623Enabled, std::shared_ptr< STTx const > const &serializedTx, TxMeta const &transactionMeta)
std::optional< STAmount > getDeliveredAmount(RPC::Context const &context, std::shared_ptr< STTx const > const &serializedTx, TxMeta const &transactionMeta, LedgerIndex const &ledgerIndex)
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.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
TxType
Transaction type identifiers.
Definition: TxFormats.h:57
@ tesSUCCESS
Definition: TER.h:242
The context of information needed to call an RPC.
Definition: Context.h:40
Application & app
Definition: Context.h:42
LedgerMaster & ledgerMaster
Definition: Context.h:45