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 SF_PRIVATE1-4 in HashRouter.h
31#define SF_SIGBAD SF_PRIVATE1 // Signature is bad
32#define SF_SIGGOOD SF_PRIVATE2 // Signature is good
33#define SF_LOCALBAD SF_PRIVATE3 // Local checks failed
34#define SF_LOCALGOOD SF_PRIVATE4 // Local checks passed
35
36//------------------------------------------------------------------------------
37
40 HashRouter& router,
41 STTx const& tx,
42 Rules const& rules,
43 Config const& config)
44{
45 auto const id = tx.getTransactionID();
46 auto const flags = router.getFlags(id);
47
48 // Ignore signature check on batch inner transactions
49 if (tx.isFlag(tfInnerBatchTxn) && rules.enabled(featureBatch))
50 {
51 // Defensive Check: These values are also checked in Batch::preflight
52 if (tx.isFieldPresent(sfTxnSignature) ||
53 !tx.getSigningPubKey().empty() || tx.isFieldPresent(sfSigners))
54 return {
56 "Malformed: Invalid inner batch transaction."};
57
58 std::string reason;
59 if (!passesLocalChecks(tx, reason))
60 {
61 router.setFlags(id, SF_LOCALBAD);
62 return {Validity::SigGoodOnly, reason};
63 }
64
65 router.setFlags(id, SF_SIGGOOD);
66 return {Validity::Valid, ""};
67 }
68
69 if (flags & SF_SIGBAD)
70 // Signature is known bad
71 return {Validity::SigBad, "Transaction has bad signature."};
72
73 if (!(flags & SF_SIGGOOD))
74 {
75 // Don't know signature state. Check it.
76 auto const requireCanonicalSig =
77 rules.enabled(featureRequireFullyCanonicalSig)
80
81 auto const sigVerify = tx.checkSign(requireCanonicalSig, rules);
82 if (!sigVerify)
83 {
84 router.setFlags(id, SF_SIGBAD);
85 return {Validity::SigBad, sigVerify.error()};
86 }
87 router.setFlags(id, SF_SIGGOOD);
88 }
89
90 // Signature is now known good
91 if (flags & SF_LOCALBAD)
92 // ...but the local checks
93 // are known bad.
94 return {Validity::SigGoodOnly, "Local checks failed."};
95
96 if (flags & SF_LOCALGOOD)
97 // ...and the local checks
98 // are known good.
99 return {Validity::Valid, ""};
100
101 // Do the local checks
102 std::string reason;
103 if (!passesLocalChecks(tx, reason))
104 {
105 router.setFlags(id, SF_LOCALBAD);
106 return {Validity::SigGoodOnly, reason};
107 }
108 router.setFlags(id, SF_LOCALGOOD);
109 return {Validity::Valid, ""};
110}
111
112void
113forceValidity(HashRouter& router, uint256 const& txid, Validity validity)
114{
115 int flags = 0;
116 switch (validity)
117 {
118 case Validity::Valid:
119 flags |= SF_LOCALGOOD;
120 [[fallthrough]];
122 flags |= SF_SIGGOOD;
123 [[fallthrough]];
124 case Validity::SigBad:
125 // would be silly to call directly
126 break;
127 }
128 if (flags)
129 router.setFlags(txid, flags);
130}
131
132template <typename PreflightChecks>
133ApplyResult
134apply(Application& app, OpenView& view, PreflightChecks&& preflightChecks)
135{
136 STAmountSO stAmountSO{view.rules().enabled(fixSTAmountCanonicalize)};
137 NumberSO stNumberSO{view.rules().enabled(fixUniversalNumber)};
138
139 return doApply(preclaim(preflightChecks(), app, view), app, view);
140}
141
142ApplyResult
144 Application& app,
145 OpenView& view,
146 STTx const& tx,
147 ApplyFlags flags,
149{
150 return apply(app, view, [&]() mutable {
151 return preflight(app, view.rules(), tx, flags, j);
152 });
153}
154
155ApplyResult
157 Application& app,
158 OpenView& view,
159 uint256 const& parentBatchId,
160 STTx const& tx,
161 ApplyFlags flags,
163{
164 return apply(app, view, [&]() mutable {
165 return preflight(app, view.rules(), parentBatchId, tx, flags, j);
166 });
167}
168
169static bool
171 Application& app,
172 OpenView& batchView,
173 STTx const& batchTxn,
175{
176 XRPL_ASSERT(
177 batchTxn.getTxnType() == ttBATCH &&
178 batchTxn.getFieldArray(sfRawTransactions).size() != 0,
179 "Batch transaction missing sfRawTransactions");
180
181 auto const parentBatchId = batchTxn.getTransactionID();
182 auto const mode = batchTxn.getFlags();
183
184 auto applyOneTransaction =
185 [&app, &j, &parentBatchId, &batchView](STTx&& tx) {
186 OpenView perTxBatchView(batch_view, batchView);
187
188 auto const ret =
189 apply(app, perTxBatchView, parentBatchId, tx, tapBATCH, j);
190 XRPL_ASSERT(
191 ret.applied == (isTesSuccess(ret.ter) || isTecClaim(ret.ter)),
192 "Inner transaction should not be applied");
193
194 JLOG(j.debug()) << "BatchTrace[" << parentBatchId
195 << "]: " << tx.getTransactionID() << " "
196 << (ret.applied ? "applied" : "failure") << ": "
197 << transToken(ret.ter);
198
199 // If the transaction should be applied push its changes to the
200 // whole-batch view.
201 if (ret.applied && (isTesSuccess(ret.ter) || isTecClaim(ret.ter)))
202 perTxBatchView.apply(batchView);
203
204 return ret;
205 };
206
207 int applied = 0;
208
209 for (STObject rb : batchTxn.getFieldArray(sfRawTransactions))
210 {
211 auto const result = applyOneTransaction(STTx{std::move(rb)});
212 XRPL_ASSERT(
213 result.applied ==
214 (isTesSuccess(result.ter) || isTecClaim(result.ter)),
215 "Outer Batch failure, inner transaction should not be applied");
216
217 if (result.applied)
218 ++applied;
219
220 if (!isTesSuccess(result.ter))
221 {
222 if (mode & tfAllOrNothing)
223 return false;
224
225 if (mode & tfUntilFailure)
226 break;
227 }
228 else if (mode & tfOnlyOne)
229 break;
230 }
231
232 return applied != 0;
233}
234
237 Application& app,
238 OpenView& view,
239 STTx const& txn,
240 bool retryAssured,
241 ApplyFlags flags,
243{
244 // Returns false if the transaction has need not be retried.
245 if (retryAssured)
246 flags = flags | tapRETRY;
247
248 JLOG(j.debug()) << "TXN " << txn.getTransactionID()
249 << (retryAssured ? "/retry" : "/final");
250
251 try
252 {
253 auto const result = apply(app, view, txn, flags, j);
254
255 if (result.applied)
256 {
257 JLOG(j.debug())
258 << "Transaction applied: " << transToken(result.ter);
259
260 // The batch transaction was just applied; now we need to apply
261 // its inner transactions as necessary.
262 if (isTesSuccess(result.ter) && txn.getTxnType() == ttBATCH)
263 {
264 OpenView wholeBatchView(batch_view, view);
265
266 if (applyBatchTransactions(app, wholeBatchView, txn, j))
267 wholeBatchView.apply(view);
268 }
269
271 }
272
273 if (isTefFailure(result.ter) || isTemMalformed(result.ter) ||
274 isTelLocal(result.ter))
275 {
276 // failure
277 JLOG(j.debug())
278 << "Transaction failure: " << transHuman(result.ter);
280 }
281
282 JLOG(j.debug()) << "Transaction retry: " << transHuman(result.ter);
284 }
285 catch (std::exception const& ex)
286 {
287 JLOG(j.warn()) << "Throws: " << ex.what();
289 }
290}
291
292} // 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:57
int getFlags(uint256 const &key)
Definition: HashRouter.cpp:95
bool setFlags(uint256 const &key, int flags)
Set the flags on a hash.
Definition: HashRouter.cpp:103
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:66
Rules const & rules() const override
Returns the tx processing rules.
Definition: OpenView.cpp:151
void apply(TxsRawView &to) const
Apply changes.
Definition: OpenView.cpp:129
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:721
size_type size() const
Definition: STArray.h:248
STArray const & getFieldArray(SField const &field) const
Definition: STObject.cpp:686
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:26
std::string transHuman(TER code)
Definition: TER.cpp:271
constexpr std::uint32_t tfAllOrNothing
Definition: TxFlags.h:246
PreflightResult preflight(Application &app, Rules const &rules, STTx const &tx, ApplyFlags flags, beast::Journal j)
Gate a transaction based on static information.
Definition: applySteps.cpp:325
ApplyResult doApply(PreclaimResult const &preclaimResult, Application &app, OpenView &view)
Apply a prechecked transaction to an OpenView.
Definition: applySteps.cpp:439
constexpr std::uint32_t tfOnlyOne
Definition: TxFlags.h:247
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.
PreclaimResult preclaim(PreflightResult const &preflightResult, Application &app, OpenView const &view)
Gate a transaction based on static ledger information.
Definition: applySteps.cpp:366
bool isTefFailure(TER x) noexcept
Definition: TER.h:660
constexpr std::uint32_t tfUntilFailure
Definition: TxFlags.h:248
std::string transToken(TER code)
Definition: TER.cpp:262
static bool applyBatchTransactions(Application &app, OpenView &batchView, STTx const &batchTxn, beast::Journal j)
Definition: apply.cpp:170
bool isTesSuccess(TER x) noexcept
Definition: TER.h:672
ApplyResult apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
Definition: apply.cpp:143
void forceValidity(HashRouter &router, uint256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
Definition: apply.cpp:113
bool passesLocalChecks(STObject const &st, std::string &)
Definition: STTx.cpp:775
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:654
ApplyFlags
Definition: ApplyView.h:31
@ tapRETRY
Definition: ApplyView.h:40
@ tapBATCH
Definition: ApplyView.h:46
ApplyTransactionResult applyTransaction(Application &app, OpenView &view, STTx const &tx, bool retryAssured, ApplyFlags flags, beast::Journal journal)
Transaction application helper.
Definition: apply.cpp:236
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:39
bool isTecClaim(TER x) noexcept
Definition: TER.h:678
bool isTelLocal(TER x) noexcept
Definition: TER.h:648
constexpr std::uint32_t tfInnerBatchTxn
Definition: TxFlags.h:61
T what(T... args)