Compare commits

...

3 Commits

Author SHA1 Message Date
Vito
23e117bde7 Merge remote-tracking branch 'origin/develop' into tapanito/transaction-invariant 2026-03-16 19:09:43 +01:00
Vito
40ee1e1ff3 feat: Add no-op transaction invariant overrides to all transactors 2026-03-16 19:05:11 +01:00
Vito
10cb46c3f0 feat: Add transaction-specific invariant checking
Introduce a two-phase visitor pattern (visitInvariantEntry /
finalizeInvariants) on Transactor so individual transaction types
can define their own post-condition checks.  These run before the
existing protocol-wide invariants and short-circuit on failure to
avoid misleading secondary errors.

- Add pure virtual visitInvariantEntry and finalizeInvariants to
  Transactor
- Implement checkTransactionInvariants to drive the visitor loop
- Extract checkInvariants to orchestrate transaction-specific then
  protocol-wide checks with reset-and-retry on failure
- Move failInvariantCheck from private to public in ApplyContext
2026-03-16 19:05:03 +01:00
138 changed files with 2396 additions and 13 deletions

View File

@@ -117,12 +117,12 @@ protected:
XRPAmount mPriorBalance; // Balance before fees.
XRPAmount mSourceBalance; // Balance after fees.
virtual ~Transactor() = default;
Transactor(Transactor const&) = delete;
Transactor&
operator=(Transactor const&) = delete;
public:
virtual ~Transactor() = default;
enum ConsequencesFactoryType { Normal, Blocker, Custom };
/** Process the transaction. */
ApplyResult
@@ -140,6 +140,20 @@ public:
return ctx_.view();
}
/** Check all invariants for the current transaction.
*
* Runs transaction-specific invariants first (visitInvariantEntry +
* finalizeInvariants), then protocol-level invariants. Protocol
* invariants are skipped if a transaction invariant already failed.
*
* @param result the tentative TER from transaction processing.
* @param fee the fee consumed by the transaction.
*
* @return the final TER after all invariant checks.
*/
[[nodiscard]] TER
checkInvariants(TER result, XRPAmount fee);
/////////////////////////////////////////////////////
/*
These static functions are called from invoke_preclaim<Tx>
@@ -230,6 +244,49 @@ protected:
virtual TER
doApply() = 0;
/** Inspect a single ledger entry modified by this transaction.
*
* Called once for every SLE created, modified, or deleted by the
* transaction, before finalizeInvariants. Implementations should
* accumulate whatever state they need to verify transaction-specific
* post-conditions.
*
* @param isDelete true if the entry was erased from the ledger.
* @param before the entry's state before the transaction (nullptr
* for newly created entries).
* @param after the entry's state after the transaction (nullptr
* when isDelete is true).
*/
virtual void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) = 0;
/** Check transaction-specific post-conditions after all entries have
* been visited.
*
* Called once after every modified ledger entry has been passed to
* visitInvariantEntry. Returns true if all transaction-specific
* invariants hold, or false to fail the transaction with
* tecINVARIANT_FAILED.
*
* @param tx the transaction being applied.
* @param result the tentative TER result so far.
* @param fee the fee consumed by the transaction.
* @param view read-only view of the ledger after the transaction.
* @param j journal for logging invariant failures.
*
* @return true if all invariants pass; false otherwise.
*/
[[nodiscard]] virtual bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) = 0;
/** Compute the minimum fee required to process a transaction
with a given baseFee based on the current server load.
@@ -335,6 +392,21 @@ private:
*/
static NotTEC
preflight2(PreflightContext const& ctx);
/** Check transaction-specific invariants only.
*
* Walks every modified ledger entry via visitInvariantEntry, then
* calls finalizeInvariants on the derived transactor. Returns
* tecINVARIANT_FAILED if any transaction invariant is violated.
*
* @param result the tentative TER from transaction processing.
* @param fee the fee consumed by the transaction.
*
* @return the original result if all invariants pass, or
* tecINVARIANT_FAILED otherwise.
*/
[[nodiscard]] TER
checkTransactionInvariants(TER result, XRPAmount fee);
};
inline bool

View File

@@ -3,6 +3,8 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyViewImpl.h>
#include <memory>
namespace xrpl {
class ServiceRegistry;
@@ -341,4 +343,15 @@ calculateDefaultBaseFee(ReadView const& view, STTx const& tx);
ApplyResult
doApply(PreclaimResult const& preclaimResult, ServiceRegistry& registry, OpenView& view);
class ApplyContext;
class Transactor;
/** Create a concrete Transactor subclass for the given ApplyContext.
*
* The transaction type is determined from the STTx held in the context.
* Returns nullptr if the transaction type is unknown.
*/
std::unique_ptr<Transactor>
makeTransactor(ApplyContext& ctx);
} // namespace xrpl

View File

@@ -27,6 +27,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using AccountDelete = DeleteAccount;

View File

@@ -31,6 +31,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using AccountSet = SetAccount;

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -41,6 +41,20 @@ public:
void
preCompute() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
// Interface used by DeleteAccount
static TER
removeFromLedger(

View File

@@ -26,6 +26,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
class BridgeModify : public Transactor
@@ -48,6 +62,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using XChainModifyBridge = BridgeModify;
@@ -81,6 +109,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
//------------------------------------------------------------------------------
@@ -108,6 +150,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
//------------------------------------------------------------------------------
@@ -137,6 +193,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
//------------------------------------------------------------------------------
@@ -166,6 +236,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
class XChainAddAccountCreateAttestation : public Transactor
@@ -186,6 +270,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
//------------------------------------------------------------------------------
@@ -230,6 +328,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using XChainAccountCreateCommit = XChainCreateAccountCommit;

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using CheckCancel = CancelCheck;

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using CheckCash = CashCheck;

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using CheckCreate = CreateCheck;

View File

@@ -24,6 +24,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -24,6 +24,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -24,6 +24,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -22,6 +22,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
// Interface used by DeleteAccount
static TER
deleteDelegate(

View File

@@ -62,6 +62,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -25,6 +25,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
private:
TER
applyGuts(Sandbox& view);

View File

@@ -58,6 +58,20 @@ public:
/** Attempt to create the AMM instance. */
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -30,6 +30,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -63,6 +63,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
private:
std::pair<TER, bool>
applyGuts(Sandbox& view);

View File

@@ -47,6 +47,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -70,6 +70,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
/** Equal-asset withdrawal (LPTokens) of some AMM instance pools
* shares represented by the number of LPTokens .
* The trading fee is not charged.

View File

@@ -22,6 +22,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using OfferCancel = CancelOffer;

View File

@@ -40,6 +40,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
private:
std::pair<TER, bool>
applyGuts(Sandbox& view, Sandbox& view_cancel);

View File

@@ -24,6 +24,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -18,6 +18,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -24,6 +24,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -30,6 +30,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -24,6 +24,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
//------------------------------------------------------------------------------

View File

@@ -24,6 +24,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
//------------------------------------------------------------------------------

View File

@@ -24,6 +24,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
//------------------------------------------------------------------------------

View File

@@ -24,6 +24,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
//------------------------------------------------------------------------------

View File

@@ -27,6 +27,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
//------------------------------------------------------------------------------

View File

@@ -24,6 +24,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
//------------------------------------------------------------------------------

View File

@@ -58,6 +58,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
//------------------------------------------------------------------------------

View File

@@ -30,6 +30,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
//------------------------------------------------------------------------------

View File

@@ -38,6 +38,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
public:
static std::uint32_t constexpr minPaymentTotal = 1;
static std::uint32_t constexpr defaultPaymentTotal = 1;

View File

@@ -34,6 +34,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -24,6 +24,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -30,6 +30,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
// Public to support unit tests.
static uint256
createNFTokenID(

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -31,6 +31,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
static TER
deleteOracle(
ApplyView& view,

View File

@@ -30,6 +30,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using OracleSet = SetOracle;

View File

@@ -25,6 +25,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
// Interface used by DeleteAccount
static TER
removeFromLedger(ApplyView& view, uint256 const& delIndex, beast::Journal j);

View File

@@ -39,6 +39,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -27,6 +27,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using PaymentChannelClaim = PayChanClaim;

View File

@@ -24,6 +24,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using PaymentChannelCreate = PayChanCreate;

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using PaymentChannelFund = PayChanFund;

View File

@@ -22,6 +22,20 @@ public:
/** Attempt to delete the Permissioned Domain. */
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -25,6 +25,20 @@ public:
/** Attempt to create the Permissioned Domain. */
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -33,6 +33,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
static constexpr auto disabledTxTypes = std::to_array<TxType>({
ttVAULT_CREATE,
ttVAULT_SET,

View File

@@ -18,6 +18,20 @@ public:
void
preCompute() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
static XRPAmount
calculateBaseFee(ReadView const& view, STTx const& tx)
{

View File

@@ -59,6 +59,20 @@ public:
/** Precondition: fee collection is likely. Attempt to create ticket(s). */
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using TicketCreate = CreateTicket;

View File

@@ -28,6 +28,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -40,6 +40,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -41,6 +41,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
static Expected<MPTID, TER>
create(ApplyView& view, beast::Journal journal, MPTCreateArgs const& args);
};

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -30,6 +30,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -28,6 +28,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
using TrustSet = SetTrust;

View File

@@ -22,6 +22,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
private:
Expected<std::pair<STAmount, STAmount>, TER>
assetsToClawback(

View File

@@ -27,6 +27,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -24,6 +24,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -21,6 +21,20 @@ public:
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -104,7 +104,7 @@ ApplyContext::checkInvariantsHelper(
// call each check's finalizer to see that it passes
if (!std::all_of(finalizers.cbegin(), finalizers.cend(), [](auto const& b) { return b; }))
{
JLOG(journal.fatal()) << "Transaction has failed one or more invariants: "
JLOG(journal.fatal()) << "Transaction has failed one or more global invariants: "
<< to_string(tx.getJson(JsonOptions::none));
return failInvariantCheck(result);
@@ -112,7 +112,7 @@ ApplyContext::checkInvariantsHelper(
}
catch (std::exception const& ex)
{
JLOG(journal.fatal()) << "Transaction caused an exception in an invariant"
JLOG(journal.fatal()) << "Transaction caused an exception in a global invariant"
<< ", ex: " << ex.what()
<< ", tx: " << to_string(tx.getJson(JsonOptions::none));

View File

@@ -1070,6 +1070,56 @@ Transactor::trapTransaction(uint256 txHash) const
JLOG(j_.debug()) << "Transaction trapped: " << txHash;
}
[[nodiscard]] TER
Transactor::checkTransactionInvariants(TER result, XRPAmount fee)
{
try
{
// Phase 1: visit modified entries
ctx_.visit([this](
uint256 const&,
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) {
this->visitInvariantEntry(isDelete, before, after);
});
// Phase 2: finalize
if (!this->finalizeInvariants(ctx_.tx, result, fee, ctx_.view(), j_))
{
JLOG(j_.fatal()) << "Transaction has failed one or more transaction invariants";
return tecINVARIANT_FAILED;
}
}
catch (std::exception const& ex)
{
JLOG(j_.fatal()) << "Exception while checking transaction invariants: " << ex.what()
<< ", tx: " << to_string(ctx_.tx.getJson(JsonOptions::none));
return tecINVARIANT_FAILED;
}
return result;
}
[[nodiscard]] TER
Transactor::checkInvariants(TER result, XRPAmount fee)
{
// Transaction invariants first (more specific). These check post-conditions of the specific
// transaction. If these fail, the transaction's core logic is wrong — there is no point running
// protocol invariants on a known-bad state.
result = checkTransactionInvariants(result, fee);
// Protocol invariants second (broader), only if transaction invariants passed. These check
// properties that must hold regardless of transaction type. Running protocol invariants after
// that is wasteful, the transaction is already going to be rejected. Worse, a transaction
// invariant failure could cause protocol invariants to produce misleading secondary failures
// (e.g., a broken deposit leaves the vault in a state that also trips the protocol check,
// generating confusing double-failure logs).
if (isTesSuccess(result) || isTecClaim(result))
result = ctx_.checkInvariants(result, fee);
return result;
}
//------------------------------------------------------------------------------
ApplyResult
Transactor::operator()()
@@ -1222,22 +1272,20 @@ Transactor::operator()()
if (applied)
{
// Check invariants: if `tecINVARIANT_FAILED` is not returned, we can
// proceed to apply the tx
result = ctx_.checkInvariants(result, fee);
result = checkInvariants(result, fee);
if (result == tecINVARIANT_FAILED)
{
// if invariants checking failed again, reset the context and
// attempt to only claim a fee.
// Reset to fee-claim only
auto const resetResult = reset(fee);
if (!isTesSuccess(resetResult.first))
result = resetResult.first;
fee = resetResult.second;
// Check invariants again to ensure the fee claiming doesn't
// violate invariants.
// Check invariants again to ensure the fee claiming doesn't violate
// invariants. After reset, only protocol invariants are re-checked.
// Transaction invariants are not meaningful here — the transaction's
// effects have been rolled back.
if (isTesSuccess(result) || isTecClaim(result))
result = ctx_.checkInvariants(result, fee);
}

View File

@@ -295,6 +295,15 @@ invoke_apply(ApplyContext& ctx)
}
}
std::unique_ptr<Transactor>
makeTransactor(ApplyContext& ctx)
{
return with_txn_type(
ctx.view().rules(), ctx.tx.getTxnType(), [&]<typename T>() -> std::unique_ptr<Transactor> {
return std::make_unique<T>(ctx);
});
}
PreflightResult
preflight(
ServiceRegistry& registry,

View File

@@ -396,4 +396,23 @@ DeleteAccount::doApply()
return tesSUCCESS;
}
void
DeleteAccount::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
DeleteAccount::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -608,4 +608,18 @@ SetAccount::doApply()
return tesSUCCESS;
}
void
SetAccount::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
SetAccount::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -68,4 +68,23 @@ SetRegularKey::doApply()
return tesSUCCESS;
}
void
SetRegularKey::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
SetRegularKey::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -385,4 +385,23 @@ SetSignerList::writeSignersToSLE(SLE::pointer const& ledgerEntry, std::uint32_t
ledgerEntry->setFieldArray(sfSignerEntries, toLedger);
}
void
SetSignerList::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
SetSignerList::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -2157,4 +2157,151 @@ XChainCreateAccountCommit::doApply()
return tesSUCCESS;
}
void
XChainCreateBridge::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
XChainCreateBridge::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
void
BridgeModify::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
BridgeModify::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
void
XChainClaim::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
XChainClaim::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
void
XChainCommit::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
XChainCommit::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
void
XChainCreateClaimID::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
XChainCreateClaimID::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
void
XChainAddClaimAttestation::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
XChainAddClaimAttestation::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
void
XChainAddAccountCreateAttestation::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
XChainAddAccountCreateAttestation::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
void
XChainCreateAccountCommit::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
XChainCreateAccountCommit::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -96,4 +96,18 @@ CancelCheck::doApply()
return tesSUCCESS;
}
void
CancelCheck::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
CancelCheck::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -444,4 +444,18 @@ CashCheck::doApply()
return tesSUCCESS;
}
void
CashCheck::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
CashCheck::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -200,4 +200,18 @@ CreateCheck::doApply()
return tesSUCCESS;
}
void
CreateCheck::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
CreateCheck::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -110,4 +110,22 @@ CredentialAccept::doApply()
return tesSUCCESS;
}
void
CredentialAccept::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
CredentialAccept::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -161,4 +161,22 @@ CredentialCreate::doApply()
return tesSUCCESS;
}
void
CredentialCreate::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
CredentialCreate::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -87,4 +87,22 @@ CredentialDelete::doApply()
return deleteSLE(view(), sleCred, j_);
}
void
CredentialDelete::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
CredentialDelete::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -124,4 +124,18 @@ DelegateSet::deleteDelegate(
return tesSUCCESS;
}
void
DelegateSet::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
DelegateSet::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -335,4 +335,18 @@ AMMBid::doApply()
return result.first;
}
void
AMMBid::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
AMMBid::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -305,4 +305,18 @@ AMMClawback::equalWithdrawMatchingOneAmount(
ctx_.journal);
}
void
AMMClawback::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
AMMClawback::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -301,4 +301,18 @@ AMMCreate::doApply()
return result.first;
}
void
AMMCreate::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
AMMCreate::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -51,4 +51,18 @@ AMMDelete::doApply()
return ter;
}
void
AMMDelete::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
AMMDelete::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -922,4 +922,18 @@ AMMDeposit::equalDepositInEmptyState(
tfee);
}
void
AMMDeposit::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
AMMDeposit::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -209,4 +209,18 @@ AMMVote::doApply()
return result.first;
}
void
AMMVote::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
AMMVote::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -1006,4 +1006,18 @@ AMMWithdraw::isWithdrawAll(STTx const& tx)
return WithdrawAll::Yes;
return WithdrawAll::No;
}
void
AMMWithdraw::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
AMMWithdraw::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -60,4 +60,18 @@ CancelOffer::doApply()
return tesSUCCESS;
}
void
CancelOffer::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
CancelOffer::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -861,4 +861,18 @@ CreateOffer::doApply()
return result.first;
}
void
CreateOffer::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
CreateOffer::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -56,4 +56,17 @@ DIDDelete::doApply()
return deleteSLE(ctx_, keylet::did(account_), account_);
}
void
DIDDelete::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
DIDDelete::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -134,4 +134,18 @@ DIDSet::doApply()
return addSLE(ctx_, sleDID, account_);
}
void
DIDSet::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
DIDSet::finalizeInvariants(STTx const&, TER, XRPAmount, ReadView const&, beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -198,4 +198,22 @@ EscrowCancel::doApply()
return tesSUCCESS;
}
void
EscrowCancel::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
EscrowCancel::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -495,4 +495,22 @@ EscrowCreate::doApply()
return tesSUCCESS;
}
void
EscrowCreate::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
EscrowCreate::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -369,4 +369,22 @@ EscrowFinish::doApply()
return tesSUCCESS;
}
void
EscrowFinish::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
EscrowFinish::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
} // namespace xrpl

View File

@@ -327,6 +327,25 @@ LoanBrokerCoverClawback::doApply()
return accountSend(view(), brokerPseudoID, account, clawAmount, j_, WaiveTransferFee::Yes);
}
void
LoanBrokerCoverClawback::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
LoanBrokerCoverClawback::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
//------------------------------------------------------------------------------
} // namespace xrpl

View File

@@ -120,6 +120,25 @@ LoanBrokerCoverDeposit::doApply()
return tesSUCCESS;
}
void
LoanBrokerCoverDeposit::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
LoanBrokerCoverDeposit::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
//------------------------------------------------------------------------------
} // namespace xrpl

View File

@@ -170,6 +170,25 @@ LoanBrokerCoverWithdraw::doApply()
return doWithdraw(view(), tx, account_, dstAcct, brokerPseudoID, mPriorBalance, amount, j_);
}
void
LoanBrokerCoverWithdraw::visitInvariantEntry(
bool,
std::shared_ptr<SLE const> const&,
std::shared_ptr<SLE const> const&)
{
}
bool
LoanBrokerCoverWithdraw::finalizeInvariants(
STTx const&,
TER,
XRPAmount,
ReadView const&,
beast::Journal const&)
{
return true;
}
//------------------------------------------------------------------------------
} // namespace xrpl

Some files were not shown because too many files have changed in this diff Show More