rippled
Loading...
Searching...
No Matches
apply.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 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/misc/HashRouter.h>
21#include <xrpld/app/tx/apply.h>
22#include <xrpld/app/tx/applySteps.h>
23
24#include <xrpl/basics/Log.h>
25#include <xrpl/protocol/Feature.h>
26#include <xrpl/protocol/TxFlags.h>
27
28namespace ripple {
29
30// These are the same flags defined as HashRouterFlags::PRIVATE1-4 in
31// HashRouter.h
33 HashRouterFlags::PRIVATE1; // Signature is bad
35 HashRouterFlags::PRIVATE2; // Signature is good
37 HashRouterFlags::PRIVATE3; // Local checks failed
39 HashRouterFlags::PRIVATE4; // Local checks passed
40
41//------------------------------------------------------------------------------
42
45 HashRouter& router,
46 STTx const& tx,
47 Rules const& rules,
48 Config const& config)
49{
50 auto const id = tx.getTransactionID();
51 auto const flags = router.getFlags(id);
52
53 // Ignore signature check on batch inner transactions
54 if (tx.isFlag(tfInnerBatchTxn) && rules.enabled(featureBatch))
55 {
56 // Defensive Check: These values are also checked in Batch::preflight
57 if (tx.isFieldPresent(sfTxnSignature) ||
58 !tx.getSigningPubKey().empty() || tx.isFieldPresent(sfSigners))
59 return {
61 "Malformed: Invalid inner batch transaction."};
62
63 std::string reason;
64 if (!passesLocalChecks(tx, reason))
65 {
66 router.setFlags(id, SF_LOCALBAD);
67 return {Validity::SigGoodOnly, reason};
68 }
69
70 router.setFlags(id, SF_SIGGOOD);
71 return {Validity::Valid, ""};
72 }
73
74 if (any(flags & SF_SIGBAD))
75 // Signature is known bad
76 return {Validity::SigBad, "Transaction has bad signature."};
77
78 if (!any(flags & SF_SIGGOOD))
79 {
80 // Don't know signature state. Check it.
81 auto const requireCanonicalSig =
82 rules.enabled(featureRequireFullyCanonicalSig)
85
86 auto const sigVerify = tx.checkSign(requireCanonicalSig, rules);
87 if (!sigVerify)
88 {
89 router.setFlags(id, SF_SIGBAD);
90 return {Validity::SigBad, sigVerify.error()};
91 }
92 router.setFlags(id, SF_SIGGOOD);
93 }
94
95 // Signature is now known good
96 if (any(flags & SF_LOCALBAD))
97 // ...but the local checks
98 // are known bad.
99 return {Validity::SigGoodOnly, "Local checks failed."};
100
101 if (any(flags & SF_LOCALGOOD))
102 // ...and the local checks
103 // are known good.
104 return {Validity::Valid, ""};
105
106 // Do the local checks
107 std::string reason;
108 if (!passesLocalChecks(tx, reason))
109 {
110 router.setFlags(id, SF_LOCALBAD);
111 return {Validity::SigGoodOnly, reason};
112 }
113 router.setFlags(id, SF_LOCALGOOD);
114 return {Validity::Valid, ""};
115}
116
117void
118forceValidity(HashRouter& router, uint256 const& txid, Validity validity)
119{
121 switch (validity)
122 {
123 case Validity::Valid:
124 flags |= SF_LOCALGOOD;
125 [[fallthrough]];
127 flags |= SF_SIGGOOD;
128 [[fallthrough]];
129 case Validity::SigBad:
130 // would be silly to call directly
131 break;
132 }
133 if (any(flags))
134 router.setFlags(txid, flags);
135}
136
137template <typename PreflightChecks>
138ApplyResult
139apply(Application& app, OpenView& view, PreflightChecks&& preflightChecks)
140{
141 STAmountSO stAmountSO{view.rules().enabled(fixSTAmountCanonicalize)};
142 NumberSO stNumberSO{view.rules().enabled(fixUniversalNumber)};
143
144 return doApply(preclaim(preflightChecks(), app, view), app, view);
145}
146
147ApplyResult
149 Application& app,
150 OpenView& view,
151 STTx const& tx,
152 ApplyFlags flags,
154{
155 return apply(app, view, [&]() mutable {
156 return preflight(app, view.rules(), tx, flags, j);
157 });
158}
159
160ApplyResult
162 Application& app,
163 OpenView& view,
164 uint256 const& parentBatchId,
165 STTx const& tx,
166 ApplyFlags flags,
168{
169 return apply(app, view, [&]() mutable {
170 return preflight(app, view.rules(), parentBatchId, tx, flags, j);
171 });
172}
173
174static bool
176 Application& app,
177 OpenView& batchView,
178 STTx const& batchTxn,
180{
181 XRPL_ASSERT(
182 batchTxn.getTxnType() == ttBATCH &&
183 batchTxn.getFieldArray(sfRawTransactions).size() != 0,
184 "Batch transaction missing sfRawTransactions");
185
186 auto const parentBatchId = batchTxn.getTransactionID();
187 auto const mode = batchTxn.getFlags();
188
189 auto applyOneTransaction =
190 [&app, &j, &parentBatchId, &batchView](STTx&& tx) {
191 OpenView perTxBatchView(batch_view, batchView);
192
193 auto const ret =
194 apply(app, perTxBatchView, parentBatchId, tx, tapBATCH, j);
195 XRPL_ASSERT(
196 ret.applied == (isTesSuccess(ret.ter) || isTecClaim(ret.ter)),
197 "Inner transaction should not be applied");
198
199 JLOG(j.debug()) << "BatchTrace[" << parentBatchId
200 << "]: " << tx.getTransactionID() << " "
201 << (ret.applied ? "applied" : "failure") << ": "
202 << transToken(ret.ter);
203
204 // If the transaction should be applied push its changes to the
205 // whole-batch view.
206 if (ret.applied && (isTesSuccess(ret.ter) || isTecClaim(ret.ter)))
207 perTxBatchView.apply(batchView);
208
209 return ret;
210 };
211
212 int applied = 0;
213
214 for (STObject rb : batchTxn.getFieldArray(sfRawTransactions))
215 {
216 auto const result = applyOneTransaction(STTx{std::move(rb)});
217 XRPL_ASSERT(
218 result.applied ==
219 (isTesSuccess(result.ter) || isTecClaim(result.ter)),
220 "Outer Batch failure, inner transaction should not be applied");
221
222 if (result.applied)
223 ++applied;
224
225 if (!isTesSuccess(result.ter))
226 {
227 if (mode & tfAllOrNothing)
228 return false;
229
230 if (mode & tfUntilFailure)
231 break;
232 }
233 else if (mode & tfOnlyOne)
234 break;
235 }
236
237 return applied != 0;
238}
239
242 Application& app,
243 OpenView& view,
244 STTx const& txn,
245 bool retryAssured,
246 ApplyFlags flags,
248{
249 // Returns false if the transaction has need not be retried.
250 if (retryAssured)
251 flags = flags | tapRETRY;
252
253 JLOG(j.debug()) << "TXN " << txn.getTransactionID()
254 << (retryAssured ? "/retry" : "/final");
255
256 try
257 {
258 auto const result = apply(app, view, txn, flags, j);
259
260 if (result.applied)
261 {
262 JLOG(j.debug())
263 << "Transaction applied: " << transToken(result.ter);
264
265 // The batch transaction was just applied; now we need to apply
266 // its inner transactions as necessary.
267 if (isTesSuccess(result.ter) && txn.getTxnType() == ttBATCH)
268 {
269 OpenView wholeBatchView(batch_view, view);
270
271 if (applyBatchTransactions(app, wholeBatchView, txn, j))
272 wholeBatchView.apply(view);
273 }
274
276 }
277
278 if (isTefFailure(result.ter) || isTemMalformed(result.ter) ||
279 isTelLocal(result.ter))
280 {
281 // failure
282 JLOG(j.debug())
283 << "Transaction failure: " << transHuman(result.ter);
285 }
286
287 JLOG(j.debug()) << "Transaction retry: " << transHuman(result.ter);
289 }
290 catch (std::exception const& ex)
291 {
292 JLOG(j.warn()) << "Throws: " << ex.what();
294 }
295}
296
297} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:60
Stream debug() const
Definition Journal.h:328
Stream warn() const
Definition Journal.h:340
Routing table for objects identified by hash.
Definition HashRouter.h:97
HashRouterFlags getFlags(uint256 const &key)
bool setFlags(uint256 const &key, HashRouterFlags flags)
Set the flags on a hash.
RAII class to set and restore the Number switchover.
Definition IOUAmount.h:211
Writable ledger view that accumulates state and tx changes.
Definition OpenView.h:65
Rules const & rules() const override
Returns the tx processing rules.
Definition OpenView.cpp:150
void apply(TxsRawView &to) const
Apply changes.
Definition OpenView.cpp:128
Rules controlling protocol behavior.
Definition Rules.h:38
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:130
RAII class to set and restore the STAmount canonicalize switchover.
Definition STAmount.h:727
size_type size() const
Definition STArray.h:248
STArray const & getFieldArray(SField const &field) const
Definition STObject.cpp:692
bool isFlag(std::uint32_t) const
Definition STObject.cpp:531
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:484
std::uint32_t getFlags() const
Definition STObject.cpp:537
Blob getSigningPubKey() const
Definition STTx.h:213
Expected< void, std::string > checkSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const &rules) const
Definition STTx.cpp:248
TxType getTxnType() const
Definition STTx.h:207
uint256 getTransactionID() const
Definition STTx.h:219
T empty(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::string transHuman(TER code)
Definition TER.cpp:273
constexpr std::uint32_t tfAllOrNothing
Definition TxFlags.h:276
PreflightResult preflight(Application &app, Rules const &rules, STTx const &tx, ApplyFlags flags, beast::Journal j)
Gate a transaction based on static information.
ApplyResult doApply(PreclaimResult const &preclaimResult, Application &app, OpenView &view)
Apply a prechecked transaction to an OpenView.
constexpr std::uint32_t tfOnlyOne
Definition TxFlags.h:277
constexpr struct ripple::batch_view_t batch_view
ApplyTransactionResult
Enum class for return value from applyTransaction
Definition apply.h:135
@ Success
Applied to this ledger.
@ Retry
Should be retried in this ledger.
@ Fail
Should not be retried in this ledger.
constexpr HashRouterFlags SF_SIGGOOD
Definition apply.cpp:34
PreclaimResult preclaim(PreflightResult const &preflightResult, Application &app, OpenView const &view)
Gate a transaction based on static ledger information.
bool isTefFailure(TER x) noexcept
Definition TER.h:662
HashRouterFlags
Definition HashRouter.h:34
constexpr std::uint32_t tfUntilFailure
Definition TxFlags.h:278
std::string transToken(TER code)
Definition TER.cpp:264
static bool applyBatchTransactions(Application &app, OpenView &batchView, STTx const &batchTxn, beast::Journal j)
Definition apply.cpp:175
constexpr HashRouterFlags SF_LOCALBAD
Definition apply.cpp:36
constexpr HashRouterFlags SF_SIGBAD
Definition apply.cpp:32
bool isTesSuccess(TER x) noexcept
Definition TER.h:674
ApplyResult apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
Definition apply.cpp:148
void forceValidity(HashRouter &router, uint256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
Definition apply.cpp:118
bool passesLocalChecks(STObject const &st, std::string &)
Definition STTx.cpp:781
Validity
Describes the pre-processing validity of a transaction.
Definition apply.h:41
@ SigBad
Signature is bad. Didn't do local checks.
@ Valid
Signature and local checks are good / passed.
@ SigGoodOnly
Signature is good, but local checks fail.
bool isTemMalformed(TER x) noexcept
Definition TER.h:656
@ tapRETRY
Definition ApplyView.h:39
@ tapBATCH
Definition ApplyView.h:45
ApplyTransactionResult applyTransaction(Application &app, OpenView &view, STTx const &tx, bool retryAssured, ApplyFlags flags, beast::Journal journal)
Transaction application helper.
Definition apply.cpp:241
std::pair< Validity, std::string > checkValidity(HashRouter &router, STTx const &tx, Rules const &rules, Config const &config)
Checks transaction signature and local checks.
Definition apply.cpp:44
bool isTecClaim(TER x) noexcept
Definition TER.h:681
bool isTelLocal(TER x) noexcept
Definition TER.h:650
constexpr std::uint32_t tfInnerBatchTxn
Definition TxFlags.h:61
constexpr HashRouterFlags SF_LOCALGOOD
Definition apply.cpp:38
T what(T... args)