xrpld
Loading...
Searching...
No Matches
Transactor.h
1#pragma once
2
3#include <xrpl/basics/Slice.h>
4#include <xrpl/basics/base_uint.h>
5#include <xrpl/beast/utility/Journal.h>
6#include <xrpl/beast/utility/WrappedSink.h>
7#include <xrpl/beast/utility/instrumentation.h>
8#include <xrpl/core/ServiceRegistry.h>
9#include <xrpl/ledger/ApplyView.h>
10#include <xrpl/ledger/ReadView.h>
11#include <xrpl/protocol/AccountID.h>
12#include <xrpl/protocol/Fees.h>
13#include <xrpl/protocol/Keylet.h>
14#include <xrpl/protocol/Permissions.h>
15#include <xrpl/protocol/Rules.h>
16#include <xrpl/protocol/SField.h>
17#include <xrpl/protocol/STObject.h>
18#include <xrpl/protocol/TER.h>
19#include <xrpl/protocol/Units.h>
20#include <xrpl/protocol/XRPAmount.h>
21#include <xrpl/tx/ApplyContext.h>
22#include <xrpl/tx/applySteps.h>
23
24#include <cstddef>
25#include <cstdint>
26#include <functional>
27#include <optional>
28#include <tuple>
29#include <unordered_set>
30#include <utility>
31
32namespace xrpl {
33
38{
39public:
41 STTx const& tx;
42 Rules const rules;
46
49 STTx const& tx,
55 , tx(tx)
56 , rules(std::move(rules))
57 , flags(flags)
59 , j(j)
60 {
61 XRPL_ASSERT((flags & TapBatch) == TapBatch, "Batch apply flag should be set");
62 }
63
66 STTx const& tx,
70 : registry(registry), tx(tx), rules(std::move(rules)), flags(flags), j(j)
71 {
72 XRPL_ASSERT((flags & TapBatch) == 0, "Batch apply flag should not be set");
73 }
74
76 operator=(PreflightContext const&) = delete;
77};
78
83{
84public:
86 ReadView const& view;
89 STTx const& tx;
92
95 ReadView const& view,
97 STTx const& tx,
102 , view(view)
104 , flags(flags)
105 , tx(tx)
107 , j(j)
108 {
109 XRPL_ASSERT(
110 parentBatchId.has_value() == ((flags & TapBatch) == TapBatch),
111 "Parent Batch ID should be set if batch apply flag is set");
112 }
113
116 ReadView const& view,
118 STTx const& tx,
122 {
123 XRPL_ASSERT((flags & TapBatch) == 0, "Batch apply flag should not be set");
124 }
125
127 operator=(PreclaimContext const&) = delete;
128};
129
130class TxConsequences;
131struct PreflightResult;
132// Needed for preflight specialization
133class Change;
134
141
149
151{
152protected:
156
158 XRPAmount preFeeBalance_{}; // Balance before fees.
159
160public:
161 virtual ~Transactor() = default;
162 Transactor(Transactor const&) = delete;
164 operator=(Transactor const&) = delete;
165
167
172 operator()();
173
174 ApplyView&
176 {
177 return ctx_.view();
178 }
179
180 [[nodiscard]] ApplyView const&
181 view() const
182 {
183 return ctx_.view();
184 }
185
198 [[nodiscard]] TER
199 checkInvariants(TER result, XRPAmount fee);
200
202 /*
203 These static functions are called from invoke_preclaim<Tx>
204 using name hiding to accomplish compile-time polymorphism,
205 so derived classes can override for different or extra
206 functionality. Use with care, as these are not really
207 virtual and so don't have the compiler-time protection that
208 comes with it.
209 */
210
211 static NotTEC
212 checkSeqProxy(ReadView const& view, STTx const& tx, beast::Journal j);
213
214 static NotTEC
216
217 static TER
218 checkFee(PreclaimContext const& ctx, XRPAmount baseFee);
219
220 static NotTEC
221 checkSign(PreclaimContext const& ctx);
222
223 // Returns the fee in fee units, not scaled for load.
224 static XRPAmount
225 calculateBaseFee(ReadView const& view, STTx const& tx);
226
227 // Returns the base fee plus extra base fee units, not scaled for load.
228 static XRPAmount
229 calculateBaseFee(ReadView const& view, STTx const& tx, std::uint32_t extraBaseFeeMultiplier);
230
231 /* Do NOT define an invokePreflight function in a derived class.
232 Instead, define:
233
234 // Optional if the transaction is gated on an amendment that
235 // isn't specified in transactions.macro
236 static bool
237 checkExtraFeatures(PreflightContext const& ctx);
238
239 // Optional if the transaction uses any flags other than tfUniversal
240 static std::uint32_t
241 getFlagsMask(PreflightContext const& ctx);
242
243 // Required, even if it just returns tesSUCCESS.
244 static NotTEC
245 preflight(PreflightContext const& ctx);
246
247 // Optional, rarely needed, if the transaction does any expensive
248 // checks after the signature is verified.
249 static NotTEC preflightSigValidated(PreflightContext const& ctx);
250
251 * Do not try to call preflight1 or preflight2 directly.
252 * Do not check whether relevant amendments are enabled in preflight.
253 Instead, define checkExtraFeatures.
254 * Do not check flags in preflight. Instead, define getFlagsMask.
255 */
256 template <class T>
257 static NotTEC
259
260 static TER
262 {
263 // Most transactors do nothing
264 // after checkSeq/Fee/Sign.
265 return tesSUCCESS;
266 }
267
274 static NotTEC
276 ReadView const& view,
277 STTx const& tx,
278 std::unordered_set<GranularPermissionType> const& heldGranularPermissions)
279 {
280 return tesSUCCESS;
281 }
282
296 template <class T>
297 static NotTEC
299 {
300 // heldGranularPermissions is passed by reference into checkPermission.
301 // It is populated with the sender’s granular permissions only when the sender
302 // lacks tx-level permission but has granular permissions that satisfy the
303 // granular permission template.
304 //
305 // - result is terNO_DELEGATE_PERMISSION: return immediately.
306 // - result is tesSUCCESS and heldGranularPermissions is empty: tx-level permission was
307 // granted, so we returned success before populating it.
308 // - result is tesSUCCESS and heldGranularPermissions is not empty: tx-level permission was
309 // not granted, but the held granular permissions passed checkGranularSandbox, so we proceed
310 // to checkGranularSemantics.
311 //
312 // WARNING: Do not simplify checkPermission to return only
313 // heldGranularPermissions or the ter code. Both the result and the
314 // populated set are required to enforce the strict permission hierarchy
315 // described above.
316 std::unordered_set<GranularPermissionType> heldGranularPermissions;
317 if (NotTEC const result = checkPermission(view, tx, heldGranularPermissions);
318 !isTesSuccess(result) || heldGranularPermissions.empty())
319 {
320 return result;
321 }
322
323 return T::checkGranularSemantics(view, tx, heldGranularPermissions);
324 }
325
326 static NotTEC
327 checkSponsor(ReadView const& view, STTx const& tx);
328
330
331 // Interface used by AccountDelete
332 static TER
335 AccountID const& account,
336 uint256 const& ticketIndex,
338
339protected:
340 TER
341 apply();
342
343 explicit Transactor(ApplyContext& ctx);
344
345 virtual void
346 preCompute();
347
348 virtual TER
349 doApply() = 0;
350
368 virtual void
370
388 [[nodiscard]] virtual bool
390 STTx const& tx,
391 TER result,
392 XRPAmount fee,
393 ReadView const& view,
394 beast::Journal const& j) = 0;
395
406 static XRPAmount
407 minimumFee(ServiceRegistry& registry, XRPAmount baseFee, Fees const& fees, ApplyFlags flags);
408
409 // Returns the fee in fee units, not scaled for load.
410 static XRPAmount
411 calculateOwnerReserveFee(ReadView const& view, STTx const& tx);
412
413 static NotTEC
414 checkSign(
415 ReadView const& view,
416 ApplyFlags flags,
417 std::optional<uint256 const> const& parentBatchId,
418 AccountID const& idAccount,
419 STObject const& sigObject,
420 beast::Journal const j,
421 // A batch may carry an inner from an account that an earlier inner
422 // creates, so the signer account need not exist yet; when it does not,
423 // only its own master key may authorize it. Normal transactions require
424 // the account to already exist.
425 bool permitUncreatedAccount = false);
426
427 // Base class always returns true
428 static bool
430
431 // Base class always returns tfUniversalMask
432 static std::uint32_t
433 getFlagsMask(PreflightContext const& ctx);
434
435 // Base class always returns tesSUCCESS
436 static NotTEC
438
439 static bool
440 validDataLength(std::optional<Slice> const& slice, std::size_t maxLength);
441
442 template <class T>
443 static bool
444 validNumericRange(std::optional<T> value, T max, T min = T{});
445
446 template <class T, class Unit>
447 static bool
449 std::optional<T> value,
452
456 template <class T>
457 static bool
458 validNumericMinimum(std::optional<T> value, T min = T{});
459
463 template <class T, class Unit>
464 static bool
466 std::optional<T> value,
467 unit::ValueUnit<Unit, T> min = unit::ValueUnit<Unit, T>{});
468
469 // Signature-authorization helpers. protected so the Batch transactor can
470 // reuse them when validating each BatchSigner in Batch::checkBatchSign.
471 static NotTEC
473 ReadView const& view,
474 AccountID const& idSigner,
475 AccountID const& idAccount,
476 SLE::const_pointer sleAccount,
477 beast::Journal const j);
478
479 static NotTEC
481 ReadView const& view,
482 ApplyFlags flags,
483 AccountID const& id,
484 STObject const& sigObject,
485 beast::Journal const j);
486
487private:
488 static NotTEC
490 ReadView const& view,
491 STTx const& tx,
492 std::unordered_set<GranularPermissionType>& heldGranularPermissions);
493
494 std::pair<TER, XRPAmount>
495 reset(XRPAmount fee);
496
497 static FeePayer
498 getFeePayer(ReadView const& view, STTx const& tx);
499
500 TER
501 consumeSeqProxy(SLE::pointer const& sleAccount);
502 TER
503 payFee();
504
505 std::tuple<TER, XRPAmount, bool>
506 processPersistentChanges(TER result, XRPAmount fee);
507
508 void trapTransaction(uint256) const;
509
518 static NotTEC
519 preflight1(PreflightContext const& ctx, std::uint32_t flagMask);
520
527 static NotTEC
528 preflight2(PreflightContext const& ctx);
529
537 static NotTEC
538 preflightUniversal(PreflightContext const& ctx);
539
553 [[nodiscard]] TER
554 checkTransactionInvariants(TER result, XRPAmount fee);
555};
556
557inline bool
559{
560 return true;
561}
562
566NotTEC
567preflight0(PreflightContext const& ctx, std::uint32_t flagMask);
568
569namespace detail {
570
576NotTEC
578
586} // namespace detail
587
588// Defined in Change.cpp
589template <>
592
593template <class T>
594NotTEC
596{
597 // Using this lookup does NOT require checking the fixDelegateV1_1. The data
598 // exists regardless of whether it is enabled.
599 auto const feature = Permission::getInstance().getTxFeature(ctx.tx.getTxnType());
600
601 if (feature && !ctx.rules.enabled(*feature))
602 return temDISABLED;
603
604 if (!T::checkExtraFeatures(ctx))
605 return temDISABLED;
606
607 if (auto const ret = preflight1(ctx, T::getFlagsMask(ctx)))
608 return ret;
609
610 if (auto const ret = preflightUniversal(ctx))
611 return ret;
612
613 if (auto const ret = T::preflight(ctx))
614 return ret;
615
616 if (auto const ret = preflight2(ctx))
617 return ret;
618
619 return T::preflightSigValidated(ctx);
620}
621
622template <class T>
623bool
625{
626 if (!value)
627 return true;
628 return value >= min && value <= max;
629}
630
631template <class T, class Unit>
632bool
634 std::optional<T> value,
637{
638 return validNumericRange(value, max.value(), min.value());
639}
640
641template <class T>
642bool
644{
645 if (!value)
646 return true;
647 return value >= min;
648}
649
650template <class T, class Unit>
651bool
656
657} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
static Sink & getNullSink()
Returns a Sink which does nothing.
Wraps a Journal::Sink to prefix its output with a string.
Definition WrappedSink.h:19
State information when applying a tx.
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:134
std::optional< std::reference_wrapper< uint256 const > > getTxFeature(TxType txType) const
static Permission const & getInstance()
A view into a ledger.
Definition ReadView.h:41
Rules controlling protocol behavior.
Definition Rules.h:40
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:180
std::shared_ptr< STLedgerEntry > pointer
std::shared_ptr< STLedgerEntry const > const & const_ref
std::shared_ptr< STLedgerEntry const > const_pointer
TxType getTxnType() const
Definition STTx.h:226
Service registry for dependency injection.
static NotTEC preflight1(PreflightContext const &ctx, std::uint32_t flagMask)
Performs early sanity checks on the account and fee fields.
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
TER consumeSeqProxy(SLE::pointer const &sleAccount)
static NotTEC checkPermission(ReadView const &view, STTx const &tx, std::unordered_set< GranularPermissionType > &heldGranularPermissions)
void trapTransaction(uint256) const
static TER checkFee(PreclaimContext const &ctx, XRPAmount baseFee)
static NotTEC invokePreflight(PreflightContext const &ctx)
Definition Transactor.h:595
static NotTEC checkGranularSemantics(ReadView const &view, STTx const &tx, std::unordered_set< GranularPermissionType > const &heldGranularPermissions)
This function can be overridden to introduce additional semantic constraints beyond the granular temp...
Definition Transactor.h:275
Transactor & operator=(Transactor const &)=delete
beast::WrappedSink sink_
Definition Transactor.h:154
static XRPAmount minimumFee(ServiceRegistry &registry, XRPAmount baseFee, Fees const &fees, ApplyFlags flags)
Compute the minimum fee required to process a transaction with a given baseFee based on the current s...
static NotTEC checkSign(PreclaimContext const &ctx)
static NotTEC checkSponsor(ReadView const &view, STTx const &tx)
static XRPAmount calculateOwnerReserveFee(ReadView const &view, STTx const &tx)
ApplyResult operator()()
Process the transaction.
static bool validNumericMinimum(std::optional< T > value, T min=T{})
Minimum will usually be zero.
Definition Transactor.h:643
static NotTEC preflightSigValidated(PreflightContext const &ctx)
static NotTEC checkSeqProxy(ReadView const &view, STTx const &tx, beast::Journal j)
beast::Journal const j_
Definition Transactor.h:155
static TER preclaim(PreclaimContext const &ctx)
Definition Transactor.h:261
virtual ~Transactor()=default
virtual TER doApply()=0
static FeePayer getFeePayer(ReadView const &view, STTx const &tx)
static NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
static bool checkExtraFeatures(PreflightContext const &ctx)
Definition Transactor.h:558
static NotTEC checkSingleSign(ReadView const &view, AccountID const &idSigner, AccountID const &idAccount, SLE::const_pointer sleAccount, beast::Journal const j)
TER checkTransactionInvariants(TER result, XRPAmount fee)
Check transaction-specific invariants only.
ApplyView & view()
Definition Transactor.h:175
Transactor(Transactor const &)=delete
static NotTEC preflightUniversal(PreflightContext const &ctx)
Universal validations.
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
TER checkInvariants(TER result, XRPAmount fee)
Check all invariants for the current transaction.
AccountID const accountID_
Definition Transactor.h:157
static NotTEC checkPriorTxAndLastLedger(PreclaimContext const &ctx)
XRPAmount preFeeBalance_
Definition Transactor.h:158
static NotTEC invokeCheckPermission(ReadView const &view, STTx const &tx)
Checks whether the transaction is authorized to be executed by the delegated account.
Definition Transactor.h:298
static NotTEC checkMultiSign(ReadView const &view, ApplyFlags flags, AccountID const &id, STObject const &sigObject, beast::Journal const j)
static bool validDataLength(std::optional< Slice > const &slice, std::size_t maxLength)
virtual void preCompute()
ApplyContext & ctx_
Definition Transactor.h:153
ApplyView const & view() const
Definition Transactor.h:181
virtual void visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after)=0
Inspect a single ledger entry modified by this transaction.
std::pair< TER, XRPAmount > reset(XRPAmount fee)
Reset the context, discarding any changes made and adjust the fee.
static bool validNumericRange(std::optional< T > value, T max, T min=T{})
Definition Transactor.h:624
virtual bool finalizeInvariants(STTx const &tx, TER result, XRPAmount fee, ReadView const &view, beast::Journal const &j)=0
Check transaction-specific post-conditions after all entries have been visited.
static TER ticketDelete(ApplyView &view, AccountID const &account, uint256 const &ticketIndex, beast::Journal j)
std::tuple< TER, XRPAmount, bool > processPersistentChanges(TER result, XRPAmount fee)
Class describing the consequences to the account of applying a transaction if the transaction consume...
Definition applySteps.h:52
T empty(T... args)
STL namespace.
std::optional< NotTEC > preflightCheckSimulateKeys(ApplyFlags flags, STObject const &sigObject, beast::Journal j)
Checks the special signing key state needed for simulation.
NotTEC preflightCheckSigningKey(STObject const &sigObject, beast::Journal j)
Checks the validity of the transactor signing key.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
TypedField< STAmount > SF_AMOUNT
Definition SField.h:355
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:607
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:572
ApplyFlags
Definition ApplyView.h:27
@ TapBatch
Definition ApplyView.h:42
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:34
@ temDISABLED
Definition TER.h:102
bool isTesSuccess(TER x) noexcept
Definition TER.h:676
TERSubset< CanCvtToTER > TER
Definition TER.h:647
NotTEC preflight0(PreflightContext const &ctx, std::uint32_t flagMask)
Performs early sanity checks on the txid and flags.
FeePayerType
Definition Transactor.h:135
BaseUInt< 256 > uint256
Definition base_uint.h:580
@ tesSUCCESS
Definition TER.h:245
FeePayerType type
Definition Transactor.h:147
SF_AMOUNT const & balanceField
Definition Transactor.h:146
AccountID id
Definition Transactor.h:144
Reflects the fee settings for a particular ledger.
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:20
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:83
PreclaimContext(ServiceRegistry &registry, ReadView const &view, TER preflightResult, STTx const &tx, ApplyFlags flags, std::optional< uint256 > parentBatchId, beast::Journal j=beast::Journal{beast::Journal::getNullSink()})
Definition Transactor.h:93
ReadView const & view
Definition Transactor.h:86
std::reference_wrapper< ServiceRegistry > registry
Definition Transactor.h:85
PreclaimContext(ServiceRegistry &registry, ReadView const &view, TER preflightResult, STTx const &tx, ApplyFlags flags, beast::Journal j=beast::Journal{beast::Journal::getNullSink()})
Definition Transactor.h:114
PreclaimContext & operator=(PreclaimContext const &)=delete
beast::Journal const j
Definition Transactor.h:91
std::optional< uint256 const > const parentBatchId
Definition Transactor.h:90
State information when preflighting a tx.
Definition Transactor.h:38
PreflightContext(ServiceRegistry &registry, STTx const &tx, Rules rules, ApplyFlags flags, beast::Journal j=beast::Journal{beast::Journal::getNullSink()})
Definition Transactor.h:64
beast::Journal const j
Definition Transactor.h:45
PreflightContext & operator=(PreflightContext const &)=delete
std::optional< uint256 const > parentBatchId
Definition Transactor.h:44
std::reference_wrapper< ServiceRegistry > registry
Definition Transactor.h:40
PreflightContext(ServiceRegistry &registry, STTx const &tx, uint256 parentBatchId, Rules rules, ApplyFlags flags, beast::Journal j=beast::Journal{beast::Journal::getNullSink()})
Definition Transactor.h:47
Describes the results of the preflight check.
Definition applySteps.h:200