refactor: Extract invariant invocation into free checkInvariants runner

Move the invariant-check orchestration out of ApplyContext and Transactor
into a free function xrpl::checkInvariants(ApplyContext&, TER, XRPAmount,
optional<reference_wrapper<InvariantCheck>>).

The two previously separate traversals (one in ApplyContext driving the
protocol tuple fold, one in Transactor driving the tx-specific check) are
merged into a single ctx.visit walk.  Per-layer try/catch inside the
lambda isolates collection faults: a throw in one layer stops only that
layer from visiting further entries while the other continues.  A layer
whose collection faulted skips its finalize phase.

ApplyContext loses checkInvariants/checkInvariantsHelper/failInvariantCheck.
Transactor delegates to the free runner via a private InvariantCheckAdapter
that bridges visitInvariantEntry+finalizeInvariants into the InvariantCheck
interface.  A SkipTxInvariants::Yes/No enum makes the fee-claim-reset call
site explicit about omitting the tx-specific check.

Protocol checks remain duck-typed in the InvariantChecks tuple (static
dispatch, no vtable on the hot path).  InvariantCheck is the runtime
interface used only by InvariantCheckAdapter.
This commit is contained in:
Vito
2026-06-04 16:57:28 +02:00
parent 6c543426c3
commit 67037782af
8 changed files with 379 additions and 165 deletions

View File

@@ -199,7 +199,8 @@ class Invariants_test : public beast::unit_test::Suite
TER terActual = tesSUCCESS;
for (TER const& terExpect : ters)
{
terActual = transactor->checkInvariants(terActual, fee);
terActual =
transactor->checkInvariants(terActual, fee, Transactor::SkipTxInvariants::No);
BEAST_EXPECTS(
terExpect == terActual,
"expected: " + transToken(terExpect) + " got: " + transToken(terActual));