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