1#include <xrpld/app/tx/apply.h> 
    2#include <xrpld/app/tx/detail/Batch.h> 
    4#include <xrpl/basics/Log.h> 
    5#include <xrpl/ledger/Sandbox.h> 
    6#include <xrpl/ledger/View.h> 
    7#include <xrpl/protocol/Feature.h> 
    8#include <xrpl/protocol/Indexes.h> 
    9#include <xrpl/protocol/TER.h> 
   10#include <xrpl/protocol/TxFlags.h> 
   46        JLOG(
debugLog().error()) << 
"BatchTrace: Base fee overflow detected.";
 
   63                << 
"BatchTrace: Raw Transactions array exceeds max entries.";
 
   70            STTx const stx = 
STTx{std::move(txn)};
 
   76                    << 
"BatchTrace: Inner Batch transaction found.";
 
   83            if (txnFees > maxAmount - fee)
 
   86                    << 
"BatchTrace: XRPAmount overflow in txnFees calculation.";
 
  104                << 
"BatchTrace: Batch Signers array exceeds max entries.";
 
  109        for (
STObject const& signer : signers)
 
  111            if (signer.isFieldPresent(sfTxnSignature))
 
  113            else if (signer.isFieldPresent(sfSigners))
 
  114                signerCount += signer.getFieldArray(sfSigners).size();
 
  119    if (signerCount > 0 && 
view.
fees().
base > maxAmount / signerCount)
 
  122            << 
"BatchTrace: XRPAmount overflow in signerCount calculation.";
 
  130    if (signerFees > maxAmount - txnFees)
 
  133            << 
"BatchTrace: XRPAmount overflow in signerFees calculation.";
 
  136    if (txnFees + signerFees > maxAmount - batchBase)
 
  139            << 
"BatchTrace: XRPAmount overflow in total fee calculation.";
 
  145    return signerFees + txnFees + batchBase;
 
 
  197        JLOG(ctx.
j.
debug()) << 
"BatchTrace[" << parentBatchId << 
"]:" 
  198                            << 
"too many flags.";
 
  203    if (rawTxns.size() <= 1)
 
  205        JLOG(ctx.
j.
debug()) << 
"BatchTrace[" << parentBatchId << 
"]:" 
  206                            << 
"txns array must have at least 2 entries.";
 
  212        JLOG(ctx.
j.
debug()) << 
"BatchTrace[" << parentBatchId << 
"]:" 
  213                            << 
"txns array exceeds 8 entries.";
 
  221    auto checkSignatureFields = [&parentBatchId, &j = ctx.
j](
 
  224                                    char const* label = 
"") -> 
NotTEC {
 
  225        if (sig.isFieldPresent(sfTxnSignature))
 
  228                << 
"BatchTrace[" << parentBatchId << 
"]: " 
  229                << 
"inner txn " << label << 
"cannot include TxnSignature. " 
  234        if (sig.isFieldPresent(sfSigners))
 
  237                << 
"BatchTrace[" << parentBatchId << 
"]: " 
  238                << 
"inner txn " << label << 
" cannot include Signers. " 
  243        if (!sig.getFieldVL(sfSigningPubKey).empty())
 
  246                << 
"BatchTrace[" << parentBatchId << 
"]: " 
  247                << 
"inner txn " << label << 
" SigningPubKey must be empty. " 
  256        STTx const stx = 
STTx{std::move(rb)};
 
  258        if (!uniqueHashes.
emplace(hash).second)
 
  260            JLOG(ctx.
j.
debug()) << 
"BatchTrace[" << parentBatchId << 
"]: " 
  261                                << 
"duplicate Txn found. " 
  268            JLOG(ctx.
j.
debug()) << 
"BatchTrace[" << parentBatchId << 
"]: " 
  269                                << 
"batch cannot have an inner batch txn. " 
  277                << 
"BatchTrace[" << parentBatchId << 
"]: " 
  278                << 
"inner txn must have the tfInnerBatchTxn flag. " 
  283        if (
auto const ret = checkSignatureFields(stx, hash))
 
  306            JLOG(ctx.
j.
debug()) << 
"BatchTrace[" << parentBatchId << 
"]: " 
  307                                << 
"inner txn preflight failed: " 
  315            !fee.native() || fee.xrp() != beast::zero)
 
  317            JLOG(ctx.
j.
debug()) << 
"BatchTrace[" << parentBatchId << 
"]: " 
  318                                << 
"inner txn must have a fee of 0. " 
  328                << 
"BatchTrace[" << parentBatchId << 
"]: " 
  329                << 
"inner txn must have exactly one of Sequence and " 
  339            JLOG(ctx.
j.
debug()) << 
"BatchTrace[" << parentBatchId << 
"]: " 
  340                                << 
"inner txn must have either Sequence or " 
  349            if (
auto const seq = stx.
getFieldU32(sfSequence); seq != 0)
 
  351                if (!accountSeqTicket[innerAccount].insert(seq).second)
 
  354                        << 
"BatchTrace[" << parentBatchId << 
"]: " 
  355                        << 
"duplicate sequence found: " 
  363                if (
auto const ticket = stx.
getFieldU32(sfTicketSequence);
 
  364                    !accountSeqTicket[innerAccount].
insert(ticket).second)
 
  367                        << 
"BatchTrace[" << parentBatchId << 
"]: " 
  368                        << 
"duplicate ticket found: " 
 
  390        auto const innerAccount = rb.getAccountID(sfAccount);
 
  394        if (innerAccount != outerAccount)
 
  395            requiredSigners.
insert(innerAccount);
 
  414            JLOG(ctx.
j.
debug()) << 
"BatchTrace[" << parentBatchId << 
"]: " 
  415                                << 
"signers array exceeds 8 entries.";
 
  424        for (
auto const& signer : signers)
 
  426            AccountID const signerAccount = signer.getAccountID(sfAccount);
 
  427            if (signerAccount == outerAccount)
 
  430                    << 
"BatchTrace[" << parentBatchId << 
"]: " 
  431                    << 
"signer cannot be the outer account: " << signerAccount;
 
  435            if (!batchSigners.
insert(signerAccount).second)
 
  438                    << 
"BatchTrace[" << parentBatchId << 
"]: " 
  439                    << 
"duplicate signer found: " << signerAccount;
 
  445            if (requiredSigners.
erase(signerAccount) == 0)
 
  447                JLOG(ctx.
j.
debug()) << 
"BatchTrace[" << parentBatchId << 
"]: " 
  448                                    << 
"no account signature for inner txn.";
 
  460                << 
"BatchTrace[" << parentBatchId << 
"]: " 
  461                << 
"invalid batch txn signature: " << sigResult.error();
 
  466    if (!requiredSigners.
empty())
 
  468        JLOG(ctx.
j.
debug()) << 
"BatchTrace[" << parentBatchId << 
"]: " 
  469                            << 
"invalid batch signers.";
 
 
static std::uint32_t getFlagsMask(PreflightContext const &ctx)
 
TER doApply() override
Applies the outer batch transaction.
 
static NotTEC preflight(PreflightContext const &ctx)
Performs preflight validation checks for a Batch transaction.
 
static NotTEC preflightSigValidated(PreflightContext const &ctx)
 
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.
 
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
 
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)
 
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.
 
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
 
constexpr std::uint32_t tfUntilFailure
 
beast::Journal debugLog()
Returns a debug journal.
 
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.