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