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/app/ledger/LedgerMaster.h>
21#include <xrpld/app/ledger/OpenLedger.h>
22#include <xrpld/app/misc/Transaction.h>
23#include <xrpld/rpc/Context.h>
24#include <xrpld/rpc/DeliveredAmount.h>
25
26#include <xrpl/protocol/Feature.h>
27#include <xrpl/protocol/RPCErr.h>
28
29namespace ripple {
30namespace RPC {
31
32/*
33 GetLedgerIndex and GetCloseTime are lambdas that allow the close time and
34 ledger index to be lazily calculated. Without these lambdas, these values
35 would be calculated even when not needed, and in some circumstances they are
36 not trivial to compute.
37
38 GetLedgerIndex is a callable that returns a LedgerIndex
39 GetCloseTime is a callable that returns a
40 std::optional<NetClock::time_point>
41 */
42template <class GetLedgerIndex, class GetCloseTime>
45 GetLedgerIndex const& getLedgerIndex,
46 GetCloseTime const& getCloseTime,
47 std::shared_ptr<STTx const> const& serializedTx,
48 TxMeta const& transactionMeta)
49{
50 if (!serializedTx)
51 return {};
52
53 if (transactionMeta.hasDeliveredAmount())
54 {
55 return transactionMeta.getDeliveredAmount();
56 }
57
58 if (serializedTx->isFieldPresent(sfAmount))
59 {
60 using namespace std::chrono_literals;
61
62 // Ledger 4594095 is the first ledger in which the DeliveredAmount field
63 // was present when a partial payment was made and its absence indicates
64 // that the amount delivered is listed in the Amount field.
65 //
66 // If the ledger closed long after the DeliveredAmount code was deployed
67 // then its absence indicates that the amount delivered is listed in the
68 // Amount field. DeliveredAmount went live January 24, 2014.
69 // 446000000 is in Feb 2014, well after DeliveredAmount went live
70 if (getLedgerIndex() >= 4594095 ||
71 getCloseTime() > NetClock::time_point{446000000s})
72 {
73 return serializedTx->getFieldAmount(sfAmount);
74 }
75 }
76
77 return {};
78}
79
80// Returns true if transaction meta could contain a delivered amount field,
81// based on transaction type, transaction result and whether fix1623 is enabled
82template <class GetFix1623Enabled>
83bool
85 GetFix1623Enabled const& getFix1623Enabled,
86 std::shared_ptr<STTx const> const& serializedTx,
87 TxMeta const& transactionMeta)
88{
89 if (!serializedTx)
90 return false;
91
92 {
93 TxType const tt{serializedTx->getTxnType()};
94 if (tt != ttPAYMENT && tt != ttCHECK_CASH && tt != ttACCOUNT_DELETE)
95 return false;
96
97 if (tt == ttCHECK_CASH && !getFix1623Enabled())
98 return false;
99 }
100
101 // if the transaction failed nothing could have been delivered.
102 if (transactionMeta.getResultTER() != tesSUCCESS)
103 return false;
104
105 return true;
106}
107
108// Returns true if transaction meta could contain a delivered amount field,
109// based on transaction type, transaction result and whether fix1623 is enabled
110bool
112 RPC::Context const& context,
113 std::shared_ptr<STTx const> const& serializedTx,
114 TxMeta const& transactionMeta)
115{
116 // These lambdas are used to compute the values lazily
117 auto const getFix1623Enabled = [&context]() -> bool {
118 auto const view = context.app.openLedger().current();
119 if (!view)
120 return false;
121 return view->rules().enabled(fix1623);
122 };
123
125 getFix1623Enabled, serializedTx, transactionMeta);
126}
127
128void
130 Json::Value& meta,
131 ReadView const& ledger,
132 std::shared_ptr<STTx const> const& serializedTx,
133 TxMeta const& transactionMeta)
134{
135 auto const info = ledger.info();
136 auto const getFix1623Enabled = [&ledger] {
137 return ledger.rules().enabled(fix1623);
138 };
139
141 getFix1623Enabled, serializedTx, transactionMeta))
142 {
143 auto const getLedgerIndex = [&info] { return info.seq; };
144 auto const getCloseTime = [&info] { return info.closeTime; };
145
146 auto amt = getDeliveredAmount(
147 getLedgerIndex, getCloseTime, serializedTx, transactionMeta);
148 if (amt)
149 {
150 meta[jss::delivered_amount] =
151 amt->getJson(JsonOptions::include_date);
152 }
153 else
154 {
155 // report "unavailable" which cannot be parsed into a sensible
156 // amount.
157 meta[jss::delivered_amount] = Json::Value("unavailable");
158 }
159 }
160}
161
162template <class GetLedgerIndex>
165 RPC::Context const& context,
166 std::shared_ptr<STTx const> const& serializedTx,
167 TxMeta const& transactionMeta,
168 GetLedgerIndex const& getLedgerIndex)
169{
170 if (canHaveDeliveredAmount(context, serializedTx, transactionMeta))
171 {
172 auto const getCloseTime =
173 [&context,
174 &getLedgerIndex]() -> std::optional<NetClock::time_point> {
175 return context.ledgerMaster.getCloseTimeBySeq(getLedgerIndex());
176 };
177 return getDeliveredAmount(
178 getLedgerIndex, getCloseTime, serializedTx, transactionMeta);
179 }
180
181 return {};
182}
183
186 RPC::Context const& context,
187 std::shared_ptr<STTx const> const& serializedTx,
188 TxMeta const& transactionMeta,
189 LedgerIndex const& ledgerIndex)
190{
191 return getDeliveredAmount(
192 context, serializedTx, transactionMeta, [&ledgerIndex]() {
193 return ledgerIndex;
194 });
195}
196
197void
199 Json::Value& meta,
200 RPC::JsonContext const& context,
201 std::shared_ptr<Transaction> const& transaction,
202 TxMeta const& transactionMeta)
203{
205 meta, context, transaction->getSTransaction(), transactionMeta);
206}
207
208void
210 Json::Value& meta,
211 RPC::JsonContext const& context,
212 std::shared_ptr<STTx const> const& transaction,
213 TxMeta const& transactionMeta)
214{
215 if (canHaveDeliveredAmount(context, transaction, transactionMeta))
216 {
217 auto amt = getDeliveredAmount(
218 context, transaction, transactionMeta, [&transactionMeta]() {
219 return transactionMeta.getLgrSeq();
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
Represents a JSON value.
Definition json_value.h:149
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.
A view into a ledger.
Definition ReadView.h:51
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:130
bool hasDeliveredAmount() const
Definition TxMeta.h:131
STAmount getDeliveredAmount() const
Definition TxMeta.h:122
std::uint32_t getLgrSeq() const
Definition TxMeta.h:63
TER getResultTER() const
Definition TxMeta.h:73
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:25
TxType
Transaction type identifiers.
Definition TxFormats.h:57
@ tesSUCCESS
Definition TER.h:244
The context of information needed to call an RPC.
Definition Context.h:39
Application & app
Definition Context.h:41
LedgerMaster & ledgerMaster
Definition Context.h:44