xrpld
Loading...
Searching...
No Matches
Batch.cpp
1#include <xrpl/tx/transactors/system/Batch.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/base_uint.h>
5#include <xrpl/beast/utility/Zero.h>
6#include <xrpl/beast/utility/instrumentation.h>
7#include <xrpl/core/ServiceRegistry.h>
8#include <xrpl/ledger/ApplyView.h>
9#include <xrpl/ledger/ReadView.h>
10#include <xrpl/ledger/helpers/SponsorHelpers.h>
11#include <xrpl/protocol/AccountID.h>
12#include <xrpl/protocol/Feature.h>
13#include <xrpl/protocol/Protocol.h>
14#include <xrpl/protocol/SField.h>
15#include <xrpl/protocol/STAccount.h> // IWYU pragma: keep
16#include <xrpl/protocol/STLedgerEntry.h>
17#include <xrpl/protocol/STObject.h>
18#include <xrpl/protocol/STTx.h>
19#include <xrpl/protocol/TER.h>
20#include <xrpl/protocol/TxFlags.h>
21#include <xrpl/protocol/TxFormats.h>
22#include <xrpl/protocol/XRPAmount.h>
23#include <xrpl/tx/Transactor.h>
24#include <xrpl/tx/applySteps.h>
25
26#include <algorithm>
27#include <bit>
28#include <cstddef>
29#include <cstdint>
30#include <limits>
31#include <optional>
32#include <unordered_map>
33#include <unordered_set>
34#include <utility>
35#include <vector>
36
37namespace xrpl {
38
53std::optional<XRPAmount>
55{
57
58 // batchBase: view.fees().base for batch processing + default base fee
59 XRPAmount const baseFee = Transactor::calculateBaseFee(view, tx);
60
61 // LCOV_EXCL_START
62 if (baseFee > maxAmount - view.fees().base)
63 {
64 JLOG(debugLog().error()) << "BatchTrace: Base fee overflow detected.";
65 return std::nullopt;
66 }
67 // LCOV_EXCL_STOP
68
69 XRPAmount const batchBase = view.fees().base + baseFee;
70
71 // Calculate the Inner Txn Fees. Inners are built and validated (count,
72 // no nesting) at construction, so they are reused here directly.
73 XRPAmount txnFees{0};
74 for (auto const& stx : tx.getBatchTransactions())
75 {
76 auto const fee = xrpl::calculateBaseFee(view, *stx);
77 if (!fee)
78 {
79 JLOG(debugLog().error())
80 << "BatchTrace: base fee of inner transaction " << stx->getTransactionID()
81 << " could not be computed: " << transToken(fee.error());
82 return std::nullopt;
83 }
84
85 // LCOV_EXCL_START
86 if (txnFees > maxAmount - *fee)
87 {
88 UNREACHABLE("XRPAmount overflow in txnFees calculation");
89 JLOG(debugLog().error()) << "BatchTrace: XRPAmount overflow in txnFees calculation.";
90 return std::nullopt;
91 }
92 // LCOV_EXCL_STOP
93 txnFees += *fee;
94 }
95
96 // Calculate the Signers/BatchSigners Fees
97 std::uint32_t signerCount = 0;
98 if (tx.isFieldPresent(sfBatchSigners))
99 {
100 auto const& signers = tx.getFieldArray(sfBatchSigners);
101
102 // LCOV_EXCL_START
103 if (signers.size() > kMaxBatchSigners)
104 {
105 JLOG(debugLog().error()) << "BatchTrace: Batch Signers array exceeds max entries.";
106 return std::nullopt;
107 }
108 // LCOV_EXCL_STOP
109
110 for (STObject const& signer : signers)
111 {
112 if (signer.isFieldPresent(sfTxnSignature))
113 {
114 signerCount += 1;
115 }
116 else if (signer.isFieldPresent(sfSigners))
117 {
118 auto const& nestedSigners = signer.getFieldArray(sfSigners);
119 // LCOV_EXCL_START
120 if (nestedSigners.size() > STTx::kMaxMultiSigners)
121 {
122 JLOG(debugLog().error())
123 << "BatchTrace: Nested Signers array exceeds max entries.";
124 return std::nullopt;
125 }
126 // LCOV_EXCL_STOP
127 signerCount += nestedSigners.size();
128 }
129 }
130 }
131
132 // LCOV_EXCL_START
133 if (signerCount > 0 && view.fees().base > maxAmount / signerCount)
134 {
135 JLOG(debugLog().error()) << "BatchTrace: XRPAmount overflow in signerCount calculation.";
136 return std::nullopt;
137 }
138 // LCOV_EXCL_STOP
139
140 XRPAmount const signerFees = signerCount * view.fees().base;
141
142 // LCOV_EXCL_START
143 if (signerFees > maxAmount - txnFees)
144 {
145 JLOG(debugLog().error()) << "BatchTrace: XRPAmount overflow in signerFees calculation.";
146 return std::nullopt;
147 }
148 XRPAmount const innerFees = txnFees + signerFees;
149 if (innerFees > maxAmount - batchBase)
150 {
151 JLOG(debugLog().error()) << "BatchTrace: XRPAmount overflow in total fee calculation.";
152 return std::nullopt;
153 }
154 // LCOV_EXCL_STOP
155
156 // 10 drops per batch signature + sum of inner tx fees + batchBase
157 return innerFees + batchBase;
158}
159
162{
163 if (auto const fee = calculateBaseFeeImpl(view, tx))
164 return *fee;
165 // The fee could not be computed, so return a placeholder the account can
166 // pay; preclaim rejects the transaction with tecINSUFF_FEE.
167 return view.fees().base; // LCOV_EXCL_LINE
168}
169
170TER
172{
173 if (!calculateBaseFeeImpl(ctx.view, ctx.tx))
174 return tecINSUFF_FEE; // LCOV_EXCL_LINE
175 return tesSUCCESS;
176}
177
180{
181 return tfBatchMask;
182}
183
217NotTEC
219{
220 auto const parentBatchId = ctx.tx.getTransactionID();
221 auto const flags = ctx.tx.getFlags();
222
223 if (std::popcount(flags & (tfAllOrNothing | tfOnlyOne | tfUntilFailure | tfIndependent)) != 1)
224 {
225 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]:"
226 << "too many flags.";
227 return temINVALID_FLAG;
228 }
229
230 if (ctx.tx.isFieldPresent(sfSponsorFlags))
231 {
232 if (isReserveSponsored(ctx.tx))
233 {
234 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]:"
235 << "spfSponsorReserve is not allowed on outer Batch.";
236 return temINVALID_FLAG;
237 }
238 }
239
240 auto const& rawTxns = ctx.tx.getFieldArray(sfRawTransactions);
241 if (rawTxns.size() <= 1)
242 {
243 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]:"
244 << "txns array must have at least 2 entries.";
245 return temARRAY_EMPTY;
246 }
247
248 if (ctx.tx.isFieldPresent(sfBatchSigners) &&
249 ctx.tx.getFieldArray(sfBatchSigners).size() > kMaxBatchSigners)
250 {
251 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]:"
252 << "signers array exceeds " << kMaxBatchSigners << " entries.";
253 return temARRAY_TOO_LARGE;
254 }
255
256 // Validation Inner Batch Txns
257 std::unordered_set<UInt256> uniqueHashes;
259 auto checkSignatureFields =
260 [&parentBatchId, &j = ctx.j](
261 STObject const& sig, UInt256 const& hash, char const* label = "") -> NotTEC {
262 if (sig.isFieldPresent(sfTxnSignature))
263 {
264 JLOG(j.debug()) << "BatchTrace[" << parentBatchId << "]: "
265 << "inner txn " << label << "cannot include TxnSignature. "
266 << "txID: " << hash;
267 return temBAD_SIGNATURE;
268 }
269
270 if (sig.isFieldPresent(sfSigners))
271 {
272 JLOG(j.debug()) << "BatchTrace[" << parentBatchId << "]: "
273 << "inner txn " << label << " cannot include Signers. "
274 << "txID: " << hash;
275 return temBAD_SIGNER;
276 }
277
278 if (!sig.getFieldVL(sfSigningPubKey).empty())
279 {
280 JLOG(j.debug()) << "BatchTrace[" << parentBatchId << "]: "
281 << "inner txn " << label << " SigningPubKey must be empty. "
282 << "txID: " << hash;
283 return temBAD_REGKEY;
284 }
285
286 return tesSUCCESS;
287 };
288 for (auto const& stxPtr : ctx.tx.getBatchTransactions())
289 {
290 STTx const& stx = *stxPtr;
291 auto const hash = stx.getTransactionID();
292 if (!uniqueHashes.emplace(hash).second)
293 {
294 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
295 << "duplicate Txn found. "
296 << "txID: " << hash;
297 return temREDUNDANT;
298 }
299
300 auto const txType = stx.getFieldU16(sfTransactionType);
301 // Pre-LendingProtocolV1_2: SAV and Lending transactions cannot be Batch inners.
302 // Post-LendingProtocolV1_2: they continue through the normal Batch checks.
303 bool const rejectedPreV12 = !ctx.rules.enabled(featureLendingProtocolV1_2) &&
305 kDisabledTxTypes, [txType](auto const& disabled) { return txType == disabled; });
306 if (rejectedPreV12)
308
309 if (!stx.isFlag(tfInnerBatchTxn))
310 {
311 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
312 << "inner txn must have the tfInnerBatchTxn flag. "
313 << "txID: " << hash;
314 return temINVALID_FLAG;
315 }
316
317 if (auto const ret = checkSignatureFields(stx, hash))
318 return ret;
319
320 // Note that the CounterpartySignature is optional, and should not be
321 // included, but if it is, ensure it doesn't contain a signature.
322 if (stx.isFieldPresent(sfCounterpartySignature))
323 {
324 auto const counterpartySignature = stx.getFieldObject(sfCounterpartySignature);
325 if (auto const ret =
326 checkSignatureFields(counterpartySignature, hash, "counterparty signature "))
327 {
328 return ret;
329 }
330 }
331 if (stx.isFieldPresent(sfSponsorSignature))
332 {
333 auto const sponsorSignature = stx.getFieldObject(sfSponsorSignature);
334 if (auto const ret = checkSignatureFields(sponsorSignature, hash, "sponsor signature "))
335 {
336 return ret;
337 }
338 }
339
340 // Check that the Fee is native asset (XRP) and zero
341 if (auto const fee = stx.getFieldAmount(sfFee); !fee.native() || fee.xrp() != beast::kZero)
342 {
343 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
344 << "inner txn must have a fee of 0. "
345 << "txID: " << hash;
346 return temBAD_FEE;
347 }
348
349 // Disallow fee sponsorship on Batch inner txs
350 if (stx.isFieldPresent(sfSponsor) && isFeeSponsored(stx))
351 return temINVALID_FLAG;
352
353 auto const innerAccount = stx.getAccountID(sfAccount);
354 // TransactionProposalCreate preflights a proposed Batch with
355 // TapDryRun | TapProposal so signature-presence checks are deferred
356 // to collection time (On-Chain Cosigner spec §5.3.1.2). Inner
357 // preflight used to pass only TapBatch, so those bits never reached
358 // the inners: an unsigned account-reserve SponsorshipTransfer then
359 // demanded sfSponsorSignature and the Create failed with
360 // temINVALID_INNER_BATCH. Spec §6.1.1 names an inner Sponsor as a
361 // collectable slot, so forward TapProposal/TapDryRun. Always OR in
362 // TapBatch — PreflightContext with a parentBatchId requires it.
363 // LoanSet already short-circuits on tfInnerBatchTxn; it is also in
364 // kDisabledTxTypes, so it never reaches this call.
365 ApplyFlags const innerFlags = TapBatch | (ctx.flags & (TapProposal | TapDryRun));
366 if (auto const preflightResult =
367 xrpl::preflight(ctx.registry, ctx.rules, parentBatchId, stx, innerFlags, ctx.j);
368 !isTesSuccess(preflightResult.ter))
369 {
370 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
371 << "inner txn preflight failed: " << transHuman(preflightResult.ter)
372 << " "
373 << "txID: " << hash;
375 }
376
377 // Check that Sequence and TicketSequence are not both present
378 if (stx.isFieldPresent(sfTicketSequence) && stx.getFieldU32(sfSequence) != 0)
379 {
380 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
381 << "inner txn must have exactly one of Sequence and "
382 "TicketSequence. "
383 << "txID: " << hash;
384 return temSEQ_AND_TICKET;
385 }
386
387 // Verify that either Sequence or TicketSequence is present
388 if (!stx.isFieldPresent(sfTicketSequence) && stx.getFieldU32(sfSequence) == 0)
389 {
390 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
391 << "inner txn must have either Sequence or "
392 "TicketSequence. "
393 << "txID: " << hash;
394 return temSEQ_AND_TICKET;
395 }
396
397 // Duplicate sequence and ticket checks
398 if ((flags & (tfAllOrNothing | tfUntilFailure)) != 0u)
399 {
400 if (auto const seq = stx.getFieldU32(sfSequence); seq != 0)
401 {
402 if (!accountSeqTicket[innerAccount].insert(seq).second)
403 {
404 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
405 << "duplicate sequence found: "
406 << "txID: " << hash;
407 return temREDUNDANT;
408 }
409 }
410
411 if (stx.isFieldPresent(sfTicketSequence))
412 {
413 if (auto const ticket = stx.getFieldU32(sfTicketSequence);
414 !accountSeqTicket[innerAccount].insert(ticket).second)
415 {
416 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
417 << "duplicate ticket found: "
418 << "txID: " << hash;
419 return temREDUNDANT;
420 }
421 }
422 }
423 }
424
425 return tesSUCCESS;
426}
427
428NotTEC
430{
431 XRPL_ASSERT(
432 ctx.tx.getTxnType() == ttBATCH, "xrpl::Batch::preflightSigValidated : batch transaction");
433
434 // A proposed Batch is stored unsigned; its BatchSigners are collected
435 // on-ledger afterward, so the signer-presence match belongs to submission
436 // time, not proposal creation (On-Chain Cosigner spec §5.3.1.2).
437 if ((ctx.flags & TapProposal) != 0)
438 return tesSUCCESS;
439
440 auto const parentBatchId = ctx.tx.getTransactionID();
441 auto const outerAccount = ctx.tx.getAccountID(sfAccount);
442 // Accounts that must sign the batch: each inner authorizer and counterparty
443 // (excluding the outer account), sorted and de-duplicated to match against
444 // the ascending, unique batch signers.
445 std::vector<AccountID> requiredSigners;
446 requiredSigners.reserve(kMaxBatchSigners);
447 for (auto const& stxPtr : ctx.tx.getBatchTransactions())
448 {
449 STTx const& rb = *stxPtr;
450 // A delegated inner is signed by the delegate, not the account holder,
451 // so the delegate is the required signer when present.
452 AccountID const authorizer = rb.getInitiator();
453
454 // The outer account signs the batch itself, so it is never added to the
455 // required signers.
456 if (authorizer != outerAccount)
457 requiredSigners.push_back(authorizer);
458 // Some transactions have a Counterparty, who must also sign the
459 // transaction if they are not the outer account
460 if (auto const counterparty = rb[~sfCounterparty];
461 counterparty && counterparty != outerAccount)
462 requiredSigners.push_back(*counterparty);
463
464 if (auto const sponsor = rb.at(~sfSponsor);
465 sponsor && rb.isFieldPresent(sfSponsorSignature) && sponsor != outerAccount)
466 requiredSigners.push_back(*sponsor);
467 }
468 std::ranges::sort(requiredSigners);
469 auto const dupes = std::ranges::unique(requiredSigners);
470 requiredSigners.erase(dupes.begin(), dupes.end());
471
472 std::size_t numReqSignersMatched = 0;
473
474 // Validation Batch Signers
475 if (ctx.tx.isFieldPresent(sfBatchSigners))
476 {
477 STArray const& signers = ctx.tx.getFieldArray(sfBatchSigners);
478
479 // Batch signers must be strictly ascending and match the required
480 // signers exactly; since both are sorted, each must be the next
481 // required signer.
482 AccountID lastBatchSigner{beast::kZero};
483 for (auto const& signer : signers)
484 {
485 AccountID const signerAccount = signer.getAccountID(sfAccount);
486 if (signerAccount == outerAccount)
487 {
488 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
489 << "signer cannot be the outer account: " << signerAccount;
490 return temBAD_SIGNER;
491 }
492
493 if (lastBatchSigner == signerAccount)
494 {
495 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
496 << "duplicate signer found: " << signerAccount;
497 return temBAD_SIGNER;
498 }
499
500 if (lastBatchSigner > signerAccount)
501 {
502 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
503 << "unsorted signers array: " << signerAccount;
504 return temBAD_SIGNER;
505 }
506 lastBatchSigner = signerAccount;
507
508 if (numReqSignersMatched >= requiredSigners.size() ||
509 requiredSigners[numReqSignersMatched] != signerAccount)
510 {
511 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
512 << "missing signer or extra signer provided: " << signerAccount;
513 return temBAD_SIGNER;
514 }
515 ++numReqSignersMatched;
516 }
517 }
518
519 // Every required signer must be matched. Also covers sfBatchSigners being
520 // absent while inner txns require signers (numReqSignersMatched stays 0).
521 if (numReqSignersMatched != requiredSigners.size())
522 {
523 JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: "
524 << "invalid batch signers.";
525 return temBAD_SIGNER;
526 }
527
528 return tesSUCCESS;
529}
530
531NotTEC
533{
534 STArray const& signers{ctx.tx.getFieldArray(sfBatchSigners)};
535 for (auto const& signer : signers)
536 {
537 // Reuse the standard signer-authorization rules so the batch and
538 // non-batch paths cannot drift. permitUncreatedAccount allows an inner
539 // from an account that an earlier inner creates, which must be
540 // authorized by its own master key.
541 auto const idAccount = signer.getAccountID(sfAccount);
542 if (auto const ret = Transactor::checkSign(
543 ctx.view,
544 ctx.flags,
545 ctx.parentBatchId,
546 idAccount,
547 signer,
548 ctx.j,
549 /*permitUncreatedAccount=*/true);
550 !isTesSuccess(ret))
551 return ret;
552 }
553 return tesSUCCESS;
554}
555
573NotTEC
575{
576 if (auto ret = Transactor::checkSign(ctx); !isTesSuccess(ret))
577 return ret;
578
579 if (ctx.tx.isFieldPresent(sfBatchSigners))
580 {
581 if (auto ret = checkBatchSign(ctx); !isTesSuccess(ret))
582 return ret;
583 }
584
585 return tesSUCCESS;
586}
587
598TER
600{
601 return tesSUCCESS;
602}
603
604void
606{
607 // No transaction-specific invariants yet (future work).
608}
609
610bool
612{
613 // No transaction-specific invariants yet (future work).
614 return true;
615}
616
617} // namespace xrpl
T any_of(T... args)
A generic endpoint for log messages.
Definition Journal.h:44
Stream debug() const
Definition Journal.h:344
UInt size() const
Number of values in array or object.
static TER preclaim(PreclaimContext const &ctx)
Definition Batch.cpp:171
static std::optional< XRPAmount > calculateBaseFeeImpl(ReadView const &view, STTx const &tx)
Calculates the total base fee for a batch transaction.
Definition Batch.cpp:54
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Definition Batch.cpp:161
static NotTEC preflight(PreflightContext const &ctx)
Performs preflight validation checks for a Batch transaction.
Definition Batch.cpp:218
void visitInvariantEntry(bool isDelete, SLE::ConstRef before, SLE::ConstRef after) override
Inspect a single ledger entry modified by this transaction.
Definition Batch.cpp:605
static NotTEC checkBatchSign(PreclaimContext const &ctx)
Definition Batch.cpp:532
static NotTEC checkSign(PreclaimContext const &ctx)
Checks the validity of signatures for a batch transaction.
Definition Batch.cpp:574
TER doApply() override
Applies the outer batch transaction.
Definition Batch.cpp:599
bool finalizeInvariants(STTx const &tx, TER result, XRPAmount fee, ReadView const &view, beast::Journal const &j) override
Check transaction-specific post-conditions after all entries have been visited.
Definition Batch.cpp:611
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
Definition Batch.cpp:179
static constexpr auto kDisabledTxTypes
Inner transaction types that preflight rejects before LendingProtocolV1_2.
static NotTEC preflightSigValidated(PreflightContext const &ctx)
Definition Batch.cpp:429
A view into a ledger.
Definition ReadView.h:41
bool enabled(UInt256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:182
bool native() const noexcept
Definition STAmount.h:471
size_type size() const
Definition STArray.h:248
std::shared_ptr< STLedgerEntry const > const & ConstRef
T::value_type at(TypedField< T > const &f) const
Get the value of a field.
Definition STObject.h:1078
std::uint32_t getFieldU32(SField const &field) const
Definition STObject.cpp:601
STArray const & getFieldArray(SField const &field) const
Definition STObject.cpp:688
bool isFlag(std::uint32_t) const
Definition STObject.cpp:511
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:464
STObject getFieldObject(SField const &field) const
Definition STObject.cpp:678
AccountID getAccountID(SField const &field) const
Definition STObject.cpp:643
std::uint16_t getFieldU16(SField const &field) const
Definition STObject.cpp:595
STAmount const & getFieldAmount(SField const &field) const
Definition STObject.cpp:657
std::uint32_t getFlags() const
Definition STObject.cpp:517
static constexpr std::size_t kMaxMultiSigners
Definition STTx.h:49
TxType getTxnType() const
Definition STTx.h:250
UInt256 getTransactionID() const
Definition STTx.h:262
AccountID getInitiator() const
The account responsible for the authorization: the delegate when sfDelegate is present,...
Definition STTx.cpp:659
std::vector< std::shared_ptr< STTx const > > const & getBatchTransactions() const
The inner transactions of a Batch, built and validated at construction.
Definition STTx.cpp:648
static NotTEC checkSign(PreclaimContext const &ctx)
ApplyView & view()
Definition Transactor.h:184
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
T emplace(T... args)
T erase(T... args)
T insert(T... args)
T max(T... args)
constexpr Zero kZero
Definition Zero.h:30
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
constexpr FlagValue tfInnerBatchTxn
Definition TxFlags.h:44
constexpr std::size_t kMaxBatchSigners
The maximum number of batch signers.
Definition Protocol.h:460
PreflightResult preflight(ServiceRegistry &registry, Rules const &rules, STTx const &tx, ApplyFlags flags, beast::Journal j)
Gate a transaction based on static information.
std::expected< XRPAmount, TER > calculateBaseFee(ReadView const &view, STTx const &tx)
Compute only the expected base fee for a transaction.
beast::Journal debugLog()
Returns a debug journal.
Definition Log.cpp:399
std::string transHuman(TER code)
Definition TER.cpp:266
std::string transToken(TER code)
Definition TER.cpp:257
bool isReserveSponsored(STTx const &tx)
Whether the transaction's reserve is sponsored (sfSponsor present + spfSponsorReserve set).
BaseUInt< 256 > UInt256
Definition base_uint.h:580
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:614
bool isFeeSponsored(STTx const &tx)
Whether the transaction's fee is sponsored (sfSponsor present + spfSponsorFee set).
ApplyFlags
Definition ApplyView.h:27
@ TapDryRun
Definition ApplyView.h:46
@ TapProposal
Definition ApplyView.h:53
@ TapBatch
Definition ApplyView.h:42
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:34
@ temBAD_REGKEY
Definition TER.h:86
@ temARRAY_TOO_LARGE
Definition TER.h:129
@ temBAD_FEE
Definition TER.h:80
@ temINVALID_FLAG
Definition TER.h:99
@ temARRAY_EMPTY
Definition TER.h:128
@ temSEQ_AND_TICKET
Definition TER.h:114
@ temBAD_SIGNATURE
Definition TER.h:93
@ temINVALID_INNER_BATCH
Definition TER.h:131
@ temREDUNDANT
Definition TER.h:100
@ temBAD_SIGNER
Definition TER.h:103
bool isTesSuccess(TER x) noexcept
Definition TER.h:683
TERSubset< CanCvtToTER > TER
Definition TER.h:654
@ tecINSUFF_FEE
Definition TER.h:310
@ tesSUCCESS
Definition TER.h:250
T popcount(T... args)
T push_back(T... args)
T reserve(T... args)
T size(T... args)
T sort(T... args)
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:92
ReadView const & view
Definition Transactor.h:95
std::optional< UInt256 const > const parentBatchId
Definition Transactor.h:99
beast::Journal const j
Definition Transactor.h:100
State information when preflighting a tx.
Definition Transactor.h:39
beast::Journal const j
Definition Transactor.h:46
std::reference_wrapper< ServiceRegistry > registry
Definition Transactor.h:41
T unique(T... args)