rippled
Loading...
Searching...
No Matches
apply.cpp
1#include <xrpl/basics/Log.h>
2#include <xrpl/core/HashRouter.h>
3#include <xrpl/core/ServiceRegistry.h>
4#include <xrpl/protocol/Feature.h>
5#include <xrpl/protocol/TxFlags.h>
6#include <xrpl/tx/apply.h>
7#include <xrpl/tx/applySteps.h>
8
9namespace xrpl {
10
11// These are the same flags defined as HashRouterFlags::PRIVATE1-4 in
12// HashRouter.h
13constexpr HashRouterFlags SF_SIGBAD = HashRouterFlags::PRIVATE1; // Signature is bad
14constexpr HashRouterFlags SF_SIGGOOD = HashRouterFlags::PRIVATE2; // Signature is good
15constexpr HashRouterFlags SF_LOCALBAD = HashRouterFlags::PRIVATE3; // Local checks failed
16constexpr HashRouterFlags SF_LOCALGOOD = HashRouterFlags::PRIVATE4; // Local checks passed
17
18//------------------------------------------------------------------------------
19
21checkValidity(HashRouter& router, STTx const& tx, Rules const& rules)
22{
23 auto const id = tx.getTransactionID();
24 auto const flags = router.getFlags(id);
25
26 // Ignore signature check on batch inner transactions
27 if (tx.isFlag(tfInnerBatchTxn) && rules.enabled(featureBatch))
28 {
29 // Defensive Check: These values are also checked in Batch::preflight
30 if (tx.isFieldPresent(sfTxnSignature) || !tx.getSigningPubKey().empty() ||
31 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 {
54 // Signature is known bad
55 return {Validity::SigBad, "Transaction has bad signature."};
56 }
57
58 if (!any(flags & SF_SIGGOOD))
59 {
60 auto const sigVerify = tx.checkSign(rules);
61 if (!sigVerify)
62 {
63 router.setFlags(id, SF_SIGBAD);
64 return {Validity::SigBad, sigVerify.error()};
65 }
66 router.setFlags(id, SF_SIGGOOD);
67 }
68
69 // Signature is now known good
70 if (any(flags & SF_LOCALBAD))
71 {
72 // ...but the local checks
73 // are known bad.
74 return {Validity::SigGoodOnly, "Local checks failed."};
75 }
76
77 if (any(flags & SF_LOCALGOOD))
78 {
79 // ...and the local checks
80 // are known good.
81 return {Validity::Valid, ""};
82 }
83
84 // Do the local checks
85 std::string reason;
86 if (!passesLocalChecks(tx, reason))
87 {
88 router.setFlags(id, SF_LOCALBAD);
89 return {Validity::SigGoodOnly, reason};
90 }
91 router.setFlags(id, SF_LOCALGOOD);
92 return {Validity::Valid, ""};
93}
94
95void
96forceValidity(HashRouter& router, uint256 const& txid, Validity validity)
97{
99 switch (validity)
100 {
101 case Validity::Valid:
102 flags |= SF_LOCALGOOD;
103 [[fallthrough]];
105 flags |= SF_SIGGOOD;
106 [[fallthrough]];
107 case Validity::SigBad:
108 // would be silly to call directly
109 break;
110 }
111 if (any(flags))
112 router.setFlags(txid, flags);
113}
114
115template <typename PreflightChecks>
116ApplyResult
117apply(ServiceRegistry& registry, OpenView& view, PreflightChecks&& preflightChecks)
118{
119 NumberSO const stNumberSO{view.rules().enabled(fixUniversalNumber)};
120 return doApply(preclaim(preflightChecks(), registry, view), registry, view);
121}
122
123ApplyResult
124apply(ServiceRegistry& registry, OpenView& view, STTx const& tx, ApplyFlags flags, beast::Journal j)
125{
126 return apply(
127 registry, view, [&]() mutable { return preflight(registry, view.rules(), tx, flags, j); });
128}
129
130ApplyResult
132 ServiceRegistry& registry,
133 OpenView& view,
134 uint256 const& parentBatchId,
135 STTx const& tx,
136 ApplyFlags flags,
138{
139 return apply(registry, view, [&]() mutable {
140 return preflight(registry, view.rules(), parentBatchId, tx, flags, j);
141 });
142}
143
144static bool
146 ServiceRegistry& registry,
147 OpenView& batchView,
148 STTx const& batchTxn,
150{
151 XRPL_ASSERT(
152 batchTxn.getTxnType() == ttBATCH && !batchTxn.getFieldArray(sfRawTransactions).empty(),
153 "Batch transaction missing sfRawTransactions");
154
155 auto const parentBatchId = batchTxn.getTransactionID();
156 auto const mode = batchTxn.getFlags();
157
158 auto applyOneTransaction = [&registry, &j, &parentBatchId, &batchView](STTx const& tx) {
159 OpenView perTxBatchView(batch_view, batchView);
160
161 auto const ret = apply(registry, perTxBatchView, parentBatchId, tx, tapBATCH, j);
162 XRPL_ASSERT(
163 ret.applied == (isTesSuccess(ret.ter) || isTecClaim(ret.ter)),
164 "Inner transaction should not be applied");
165
166 JLOG(j.debug()) << "BatchTrace[" << parentBatchId << "]: " << tx.getTransactionID() << " "
167 << (ret.applied ? "applied" : "failure") << ": " << transToken(ret.ter);
168
169 // If the transaction should be applied push its changes to the
170 // whole-batch view.
171 if (ret.applied && (isTesSuccess(ret.ter) || isTecClaim(ret.ter)))
172 perTxBatchView.apply(batchView);
173
174 return ret;
175 };
176
177 int applied = 0;
178
179 for (STObject rb : batchTxn.getFieldArray(sfRawTransactions))
180 {
181 auto const result = applyOneTransaction(STTx{std::move(rb)});
182 XRPL_ASSERT(
183 result.applied == (isTesSuccess(result.ter) || isTecClaim(result.ter)),
184 "Outer Batch failure, inner transaction should not be applied");
185
186 if (result.applied)
187 ++applied;
188
189 if (!isTesSuccess(result.ter))
190 {
191 if ((mode & tfAllOrNothing) != 0u)
192 return false;
193
194 if ((mode & tfUntilFailure) != 0u)
195 break;
196 }
197 else if ((mode & tfOnlyOne) != 0u)
198 {
199 break;
200 }
201 }
202
203 return applied != 0;
204}
205
208 ServiceRegistry& registry,
209 OpenView& view,
210 STTx const& txn,
211 bool retryAssured,
212 ApplyFlags flags,
214{
215 // Returns false if the transaction has need not be retried.
216 if (retryAssured)
217 flags = flags | tapRETRY;
218
219 JLOG(j.debug()) << "TXN " << txn.getTransactionID() << (retryAssured ? "/retry" : "/final");
220
221 try
222 {
223 auto const result = apply(registry, view, txn, flags, j);
224
225 if (result.applied)
226 {
227 JLOG(j.debug()) << "Transaction applied: " << transToken(result.ter);
228
229 // The batch transaction was just applied; now we need to apply
230 // its inner transactions as necessary.
231 if (isTesSuccess(result.ter) && txn.getTxnType() == ttBATCH)
232 {
233 OpenView wholeBatchView(batch_view, view);
234
235 if (applyBatchTransactions(registry, wholeBatchView, txn, j))
236 wholeBatchView.apply(view);
237 }
238
240 }
241
242 if (isTefFailure(result.ter) || isTemMalformed(result.ter) || isTelLocal(result.ter))
243 {
244 // failure
245 JLOG(j.debug()) << "Transaction failure: " << transHuman(result.ter);
247 }
248
249 JLOG(j.debug()) << "Transaction retry: " << transHuman(result.ter);
251 }
252 catch (std::exception const& ex)
253 {
254 JLOG(j.warn()) << "Throws: " << ex.what();
256 }
257}
258
259} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:40
Stream debug() const
Definition Journal.h:301
Stream warn() const
Definition Journal.h:313
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:193
Writable ledger view that accumulates state and tx changes.
Definition OpenView.h:45
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:18
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:120
bool empty() const
Definition STArray.h:231
STArray const & getFieldArray(SField const &field) const
Definition STObject.cpp:680
bool isFlag(std::uint32_t) const
Definition STObject.cpp:503
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:456
std::uint32_t getFlags() const
Definition STObject.cpp:509
Expected< void, std::string > checkSign(Rules const &rules) const
Check the signature.
Definition STTx.cpp:272
TxType getTxnType() const
Definition STTx.h:188
Blob getSigningPubKey() const
Definition STTx.h:194
uint256 getTransactionID() const
Definition STTx.h:200
Service registry for dependency injection.
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
constexpr FlagValue tfInnerBatchTxn
Definition TxFlags.h:41
PreflightResult preflight(ServiceRegistry &registry, Rules const &rules, STTx const &tx, ApplyFlags flags, beast::Journal j)
Gate a transaction based on static information.
PreclaimResult preclaim(PreflightResult const &preflightResult, ServiceRegistry &registry, OpenView const &view)
Gate a transaction based on static ledger information.
Validity
Describes the pre-processing validity of a transaction.
Definition apply.h:19
@ 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.
ApplyResult apply(ServiceRegistry &registry, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
Definition apply.cpp:124
constexpr HashRouterFlags SF_LOCALBAD
Definition apply.cpp:15
ApplyTransactionResult applyTransaction(ServiceRegistry &registry, OpenView &view, STTx const &tx, bool retryAssured, ApplyFlags flags, beast::Journal journal)
Transaction application helper.
Definition apply.cpp:207
std::pair< Validity, std::string > checkValidity(HashRouter &router, STTx const &tx, Rules const &rules)
Checks transaction signature and local checks.
Definition apply.cpp:21
ApplyTransactionResult
Enum class for return value from applyTransaction
Definition apply.h:109
@ 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:13
std::string transToken(TER code)
Definition TER.cpp:243
constexpr HashRouterFlags SF_SIGGOOD
Definition apply.cpp:14
bool isTefFailure(TER x) noexcept
Definition TER.h:639
bool passesLocalChecks(STObject const &st, std::string &)
Definition STTx.cpp:770
HashRouterFlags
Definition HashRouter.h:14
constexpr HashRouterFlags SF_LOCALGOOD
Definition apply.cpp:16
static bool applyBatchTransactions(ServiceRegistry &registry, OpenView &batchView, STTx const &batchTxn, beast::Journal j)
Definition apply.cpp:145
ApplyFlags
Definition ApplyView.h:10
@ tapRETRY
Definition ApplyView.h:19
@ tapBATCH
Definition ApplyView.h:25
bool isTelLocal(TER x) noexcept
Definition TER.h:627
bool isTesSuccess(TER x) noexcept
Definition TER.h:651
bool isTecClaim(TER x) noexcept
Definition TER.h:658
void forceValidity(HashRouter &router, uint256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
Definition apply.cpp:96
ApplyResult doApply(PreclaimResult const &preclaimResult, ServiceRegistry &registry, OpenView &view)
Apply a prechecked transaction to an OpenView.
bool isTemMalformed(TER x) noexcept
Definition TER.h:633
T what(T... args)