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