20#include <xrpld/app/tx/apply.h>
21#include <xrpld/app/tx/detail/Batch.h>
22#include <xrpld/ledger/Sandbox.h>
23#include <xrpld/ledger/View.h>
25#include <xrpl/basics/Log.h>
26#include <xrpl/protocol/Feature.h>
27#include <xrpl/protocol/Indexes.h>
28#include <xrpl/protocol/TER.h>
29#include <xrpl/protocol/TxFlags.h>
77 "Raw Transactions array exceeds max entries.");
82 "Raw Transactions array exceeds max entries");
87 STTx const stx =
STTx{std::move(txn)};
90 stx.
getTxnType() != ttBATCH,
"Inner Batch transaction found.");
99 if (txnFees > maxAmount -
fee)
113 "Batch Signers array exceeds max entries.");
122 if (
signer.isFieldPresent(sfTxnSignature))
124 else if (
signer.isFieldPresent(sfSigners))
125 signerCount +=
signer.getFieldArray(sfSigners).size();
130 if (signerCount > 0 &&
view.
fees().
base > maxAmount / signerCount)
137 if (signerFees > maxAmount - txnFees)
139 if (txnFees + signerFees > maxAmount - batchBase)
144 return signerFees + txnFees + batchBase;
195 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]:"
204 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]:"
205 <<
"too many flags.";
210 if (rawTxns.size() <= 1)
212 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]:"
213 <<
"txns array must have at least 2 entries.";
219 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]:"
220 <<
"txns array exceeds 8 entries.";
231 STTx const stx =
STTx{std::move(rb)};
233 if (!uniqueHashes.
emplace(hash).second)
235 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]: "
236 <<
"duplicate Txn found. "
243 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]: "
244 <<
"batch cannot have an inner batch txn. "
252 <<
"BatchTrace[" << parentBatchId <<
"]: "
253 <<
"inner txn must have the tfInnerBatchTxn flag. "
260 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]: "
261 <<
"inner txn cannot include TxnSignature. "
268 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]: "
269 <<
"inner txn cannot include Signers. "
276 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]: "
277 <<
"inner txn SigningPubKey must be empty. "
287 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]: "
288 <<
"inner txn preflight failed: "
296 !
fee.native() ||
fee.xrp() != beast::zero)
298 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]: "
299 <<
"inner txn must have a fee of 0. "
309 <<
"BatchTrace[" << parentBatchId <<
"]: "
310 <<
"inner txn must have exactly one of Sequence and "
320 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]: "
321 <<
"inner txn must have either Sequence or "
332 if (!accountSeqTicket[innerAccount].insert(
seq).second)
335 <<
"BatchTrace[" << parentBatchId <<
"]: "
336 <<
"duplicate sequence found: "
344 if (
auto const ticket = stx.
getFieldU32(sfTicketSequence);
345 !accountSeqTicket[innerAccount].
insert(ticket).second)
348 <<
"BatchTrace[" << parentBatchId <<
"]: "
349 <<
"duplicate ticket found: "
358 if (innerAccount != outerAccount)
359 requiredSigners.
insert(innerAccount);
376 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]: "
377 <<
"signers array exceeds 8 entries.";
389 if (signerAccount == outerAccount)
392 <<
"BatchTrace[" << parentBatchId <<
"]: "
393 <<
"signer cannot be the outer account: " << signerAccount;
397 if (!batchSigners.
insert(signerAccount).second)
400 <<
"BatchTrace[" << parentBatchId <<
"]: "
401 <<
"duplicate signer found: " << signerAccount;
407 if (requiredSigners.
erase(signerAccount) == 0)
409 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]: "
410 <<
"no account signature for inner txn.";
422 <<
"BatchTrace[" << parentBatchId <<
"]: "
423 <<
"invalid batch txn signature: " << sigResult.error();
428 if (!requiredSigners.
empty())
430 JLOG(ctx.
j.
debug()) <<
"BatchTrace[" << parentBatchId <<
"]: "
431 <<
"invalid batch signers.";
UInt size() const
Number of values in array or object.
TER doApply() override
Applies the outer batch transaction.
static NotTEC preflight(PreflightContext const &ctx)
Performs preflight validation checks for a Batch transaction.
static NotTEC checkSign(PreclaimContext const &ctx)
Checks the validity of signatures for a batch transaction.
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Calculates the total base fee for a batch transaction.
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
AccountID getAccountID(SField const &field) const
STArray const & getFieldArray(SField const &field) const
std::uint16_t getFieldU16(SField const &field) const
std::uint32_t getFieldU32(SField const &field) const
STAmount const & getFieldAmount(SField const &field) const
bool isFieldPresent(SField const &field) const
std::uint32_t getFlags() const
Blob getSigningPubKey() const
TxType getTxnType() const
uint256 getTransactionID() const
Expected< void, std::string > checkBatchSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const &rules) const
static XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
static NotTEC checkSign(PreclaimContext const &ctx)
static NotTEC checkBatchSign(PreclaimContext const &ctx)
Json::Value signers(Account const &account, std::uint32_t quorum, std::vector< signer > const &v)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::string transHuman(TER code)
constexpr std::uint32_t tfAllOrNothing
constexpr std::uint32_t const tfBatchMask
PreflightResult preflight(Application &app, Rules const &rules, STTx const &tx, ApplyFlags flags, beast::Journal j)
Gate a transaction based on static information.
constexpr std::uint32_t tfOnlyOne
constexpr std::uint32_t tfIndependent
XRPAmount calculateBaseFee(ReadView const &view, STTx const &tx)
Compute only the expected base fee for a transaction.
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
constexpr std::uint32_t tfUntilFailure
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
bool isTesSuccess(TER x) noexcept
std::size_t constexpr maxBatchTxCount
The maximum number of transactions that can be in a batch.
constexpr std::uint32_t tfInnerBatchTxn
State information when determining if a tx is likely to claim a fee.
State information when preflighting a tx.
NotTEC const ter
Intermediate transaction result.
Set the sequence number on a JTx.
A signer in a SignerList.