Add prechecker address filtering via dry-run ProduceBlockAdvanced#4382
Open
Tristan-Wilson wants to merge 1 commit intofilter-submit-retryablefrom
Open
Add prechecker address filtering via dry-run ProduceBlockAdvanced#4382Tristan-Wilson wants to merge 1 commit intofilter-submit-retryablefrom
Tristan-Wilson wants to merge 1 commit intofilter-submit-retryablefrom
Conversation
Add address filtering to the prechecker by running the full block production pipeline on a throwaway statedb. For each RPC-submitted transaction, when filtering is enabled, the prechecker calls ProduceBlockAdvanced(dryRun=true) through a thin PrefiltererSequencingHooks adapter that implements the same TouchAddress/IsAddressFiltered logic the sequencer uses. This catches direct address touches, direct redeems, contract-triggered redeems (where a contract internally calls ArbRetryableTx.redeem), event-filter hits, and cascading redeem chains -- all with zero coupling to retryable internals. The approach is unified: every tx goes through ProduceBlockAdvanced rather than trying to detect redeem-related transactions statically. A regular contract can call ArbRetryableTx.redeem(ticketId) internally, making static detection impossible. Running the real block processor as a black box sidesteps this entirely. Key design decisions: - No isRedeemTx gate: the unified approach runs ALL txs through ProduceBlockAdvanced when filtering is enabled. A static gate on To == 0x6e misses contract-triggered redeems. The only gate is addressChecker != nil. - No statedb.Copy(): each PublishTransaction opens its own statedb via bc.StateAt, never uses it after the dry-run, and ProduceBlockAdvanced doesn't call Commit. The statedb is passed directly and GC'd on return. This eliminates the main cost objection to running the full pipeline. - dryRun mode: a new bool parameter on ProduceBlockAdvanced causes an early return after the tx processing loop, skipping FinalizeBlock (which calls IntermediateRoot -- likely the dominant fixed overhead per call), receipt construction, block assembly, and balance delta checks. The prechecker only needs hooks.filtered, not a valid block. - Forwarder-only wiring: on the sequencer node, the sequencer already returns ErrArbTxFilter synchronously from real block production so the prechecker dry-run is redundant. The addressChecker/eventFilter are only wired to TxPreChecker on forwarder nodes (which don't run a sequencer and relay to a remote sequencer after prechecking). - Config refactor: TransactionFilteringConfig is moved from SequencerConfig to a top-level execution.transaction-filtering.* namespace. Forwarders don't have a Sequencer component, so they couldn't access the filter config when it lived under execution.sequencer. The new location makes it available to any node role.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## filter-submit-retryable #4382 +/- ##
===========================================================
- Coverage 33.09% 32.78% -0.32%
===========================================================
Files 489 490 +1
Lines 58145 58221 +76
===========================================================
- Hits 19244 19088 -156
- Misses 35530 35789 +259
+ Partials 3371 3344 -27 |
Contributor
❌ 8 Tests Failed:
View the top 3 failed tests by shortest run time
📣 Thoughts on this report? Let Codecov know! | Powered by Codecov |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add address filtering to the prechecker by running the full block production pipeline on a throwaway statedb. For each RPC-submitted transaction, when filtering is enabled, the prechecker calls ProduceBlockAdvanced(dryRun=true) through a thin PrefiltererSequencingHooks adapter that implements the same TouchAddress/IsAddressFiltered logic the sequencer uses. This catches direct address touches, direct redeems, contract-triggered redeems (where a contract internally calls ArbRetryableTx.redeem), event-filter hits, and cascading redeem chains -- all with zero coupling to retryable internals.
The approach is unified: every tx goes through ProduceBlockAdvanced rather than trying to detect redeem-related transactions statically. A regular contract can call ArbRetryableTx.redeem(ticketId) internally, making static detection impossible. Running the real block processor as a black box sidesteps this entirely.
Key design decisions:
No isRedeemTx gate: the unified approach runs ALL txs through ProduceBlockAdvanced when filtering is enabled. A static gate on To == 0x6e misses contract-triggered redeems. The only gate is addressChecker != nil.
No statedb.Copy(): each PublishTransaction opens its own statedb via bc.StateAt, never uses it after the dry-run, and ProduceBlockAdvanced doesn't call Commit. The statedb is passed directly and GC'd on return. This eliminates the main cost objection to running the full pipeline.
dryRun mode: a new bool parameter on ProduceBlockAdvanced causes an early return after the tx processing loop, skipping FinalizeBlock (which calls IntermediateRoot -- likely the dominant fixed overhead per call), receipt construction, block assembly, and balance delta checks. The prechecker only needs hooks.filtered, not a valid block.
Forwarder-only wiring: on the sequencer node, the sequencer already returns ErrArbTxFilter synchronously from real block production so the prechecker dry-run is redundant. The addressChecker/eventFilter are only wired to TxPreChecker on forwarder nodes (which don't run a sequencer and relay to a remote sequencer after prechecking).
Config refactor: TransactionFilteringConfig is moved from SequencerConfig to a top-level execution.transaction-filtering.* namespace. Forwarders don't have a Sequencer component, so they couldn't access the filter config when it lived under execution.sequencer. The new location makes it available to any node role.
fixes NIT-4344