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 NumberSO stNumberSO{view.rules().enabled(fixUniversalNumber)};
142 return doApply(preclaim(preflightChecks(), app, view), app, view);
143}
144
145ApplyResult
147 Application& app,
148 OpenView& view,
149 STTx const& tx,
150 ApplyFlags flags,
152{
153 return apply(app, view, [&]() mutable {
154 return preflight(app, view.rules(), tx, flags, j);
155 });
156}
157
158ApplyResult
160 Application& app,
161 OpenView& view,
162 uint256 const& parentBatchId,
163 STTx const& tx,
164 ApplyFlags flags,
166{
167 return apply(app, view, [&]() mutable {
168 return preflight(app, view.rules(), parentBatchId, tx, flags, j);
169 });
170}
171
172static bool
174 Application& app,
175 OpenView& batchView,
176 STTx const& batchTxn,
178{
179 XRPL_ASSERT(
180 batchTxn.getTxnType() == ttBATCH &&
181 batchTxn.getFieldArray(sfRawTransactions).size() != 0,
182 "Batch transaction missing sfRawTransactions");
183
184 auto const parentBatchId = batchTxn.getTransactionID();
185 auto const mode = batchTxn.getFlags();
186
187 auto applyOneTransaction =
188 [&app, &j, &parentBatchId, &batchView](STTx&& tx) {
189 OpenView perTxBatchView(batch_view, batchView);
190
191 auto const ret =
192 apply(app, perTxBatchView, parentBatchId, tx, tapBATCH, j);
193 XRPL_ASSERT(
194 ret.applied == (isTesSuccess(ret.ter) || isTecClaim(ret.ter)),
195 "Inner transaction should not be applied");
196
197 JLOG(j.debug()) << "BatchTrace[" << parentBatchId
198 << "]: " << tx.getTransactionID() << " "
199 << (ret.applied ? "applied" : "failure") << ": "
200 << transToken(ret.ter);
201
202 // If the transaction should be applied push its changes to the
203 // whole-batch view.
204 if (ret.applied && (isTesSuccess(ret.ter) || isTecClaim(ret.ter)))
205 perTxBatchView.apply(batchView);
206
207 return ret;
208 };
209
210 int applied = 0;
211
212 for (STObject rb : batchTxn.getFieldArray(sfRawTransactions))
213 {
214 auto const result = applyOneTransaction(STTx{std::move(rb)});
215 XRPL_ASSERT(
216 result.applied ==
217 (isTesSuccess(result.ter) || isTecClaim(result.ter)),
218 "Outer Batch failure, inner transaction should not be applied");
219
220 if (result.applied)
221 ++applied;
222
223 if (!isTesSuccess(result.ter))
224 {
225 if (mode & tfAllOrNothing)
226 return false;
227
228 if (mode & tfUntilFailure)
229 break;
230 }
231 else if (mode & tfOnlyOne)
232 break;
233 }
234
235 return applied != 0;
236}
237
240 Application& app,
241 OpenView& view,
242 STTx const& txn,
243 bool retryAssured,
244 ApplyFlags flags,
246{
247 // Returns false if the transaction has need not be retried.
248 if (retryAssured)
249 flags = flags | tapRETRY;
250
251 JLOG(j.debug()) << "TXN " << txn.getTransactionID()
252 << (retryAssured ? "/retry" : "/final");
253
254 try
255 {
256 auto const result = apply(app, view, txn, flags, j);
257
258 if (result.applied)
259 {
260 JLOG(j.debug())
261 << "Transaction applied: " << transToken(result.ter);
262
263 // The batch transaction was just applied; now we need to apply
264 // its inner transactions as necessary.
265 if (isTesSuccess(result.ter) && txn.getTxnType() == ttBATCH)
266 {
267 OpenView wholeBatchView(batch_view, view);
268
269 if (applyBatchTransactions(app, wholeBatchView, txn, j))
270 wholeBatchView.apply(view);
271 }
272
274 }
275
276 if (isTefFailure(result.ter) || isTemMalformed(result.ter) ||
277 isTelLocal(result.ter))
278 {
279 // failure
280 JLOG(j.debug())
281 << "Transaction failure: " << transHuman(result.ter);
283 }
284
285 JLOG(j.debug()) << "Transaction retry: " << transHuman(result.ter);
287 }
288 catch (std::exception const& ex)
289 {
290 JLOG(j.warn()) << "Throws: " << ex.what();
292 }
293}
294
295} // 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
size_type size() const
Definition STArray.h:248
STArray const & getFieldArray(SField const &field) const
Definition STObject.cpp:702
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:243
Expected< void, std::string > checkSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const &rules) const
Check the signature.
Definition STTx.cpp:282
TxType getTxnType() const
Definition STTx.h:237
uint256 getTransactionID() const
Definition STTx.h:249
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:666
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:173
constexpr HashRouterFlags SF_LOCALBAD
Definition apply.cpp:36
constexpr HashRouterFlags SF_SIGBAD
Definition apply.cpp:32
bool isTesSuccess(TER x) noexcept
Definition TER.h:678
ApplyResult apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
Definition apply.cpp:146
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:831
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:660
@ 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:239
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:685
bool isTelLocal(TER x) noexcept
Definition TER.h:654
constexpr std::uint32_t tfInnerBatchTxn
Definition TxFlags.h:61
constexpr HashRouterFlags SF_LOCALGOOD
Definition apply.cpp:38
T what(T... args)