Skip to content

Pre-checker tx filtering (using estimate gas call)#4583

Merged
tsahee merged 44 commits intomasterfrom
prefilter-blockchain-api-2
Apr 6, 2026
Merged

Pre-checker tx filtering (using estimate gas call)#4583
tsahee merged 44 commits intomasterfrom
prefilter-blockchain-api-2

Conversation

@MishkaRogachev
Copy link
Copy Markdown
Contributor

fixes NIT-4344
Pulls in OffchainLabs/go-ethereum#643

Add address filtering to TxPreChecker via gas estimation dry-run. Pre-checker now runs transactions through gasestimator.Run to detect filtered addresses before forwarding, catching sender/recipient, aliased, retryable, and event-based address matches including cascading redeems.

MishkaRogachev and others added 23 commits March 2, 2026 15:58
@MishkaRogachev MishkaRogachev force-pushed the prefilter-blockchain-api-2 branch from 91af9cf to 2b91fd1 Compare March 31, 2026 15:18
Comment thread execution/gethexec/node.go Outdated

type TransactionFilteringConfig struct {
DisableDelayedSequencingFilter bool `koanf:"disable-delayed-sequencing-filter"`
EnableRPCFilter bool `koanf:"enable-rpc-filter"`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EnableRPCFilter is too generic to me, since publishing a transaction also happens through RPC.
I am inclined on using EnableNonMutatingRPCFilter, but I think Tsahi doesn't like it.
I will let @tsahee decide that.

Suggested change
EnableRPCFilter bool `koanf:"enable-rpc-filter"`
EnableNonMutatingRPCFilter bool `koanf:"enable-non-mutating-rpc-filter"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I indeed don't like non-mutating. enable-ethcall-filter? I know it's not exact but much more self-explanatory.

It should be identical to: https://github.com/OffchainLabs/nitro/pull/4591/changes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to enable-ethcall-filter

Comment thread execution/gethexec/tx_pre_checker.go Outdated
if err != nil {
return err
}
if err := c.checkFilteredAddresses(tx, block); err != nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkFilteredAddresses could be done in the beginning of PreCheckTx to avoid that.
But fully running current PreCheckTx can avoid unnecessary gas estimation anyway.

Comment thread system_tests/retryable_tickets_filtering_test.go Outdated
Comment thread system_tests/retryable_tickets_filtering_test.go Outdated
Comment thread system_tests/retryable_tickets_filtering_test.go Outdated
Comment thread system_tests/retryable_tickets_filtering_test.go Outdated
Comment thread system_tests/delayed_message_filter_test.go Outdated
Comment thread execution/gethexec/tx_filterer.go Outdated
}

func (f *txFilterer) TouchAddresses(statedb *state.StateDB, tx *types.Transaction, sender common.Address) {
touchAddresses(statedb, nil, tx, sender)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are retryables, so we need the full set: aliased sender and retryable-specific fields. The regular preTxFilter's from/to-only approach would miss those.

Current scenario:

  • For delayed sequencing, the post tx filter calls touchRetryableAddresses, to handle ArbitrumSubmitRetryableTx in a special way. It also handles "TxTypeAlias" in a special way.
  • For regular transaction sequencing, touchRetryableAddresses is not called, ArbitrumSubmitRetryableTx is not handled in a special way in any step of the filtering process.
  • For pre-checker/eth_estimateGas we are enforcing to use the same policy as the delayed sequencing.

All those scenarios handle scheduled transactions.

At this point this is confusing to me.
I don't understand if regular transaction sequencing has an issue right now, and it should actually handle ArbitrumSubmitRetryableTx in a special way.
Or if we are enforcing this ArbitrumSubmitRetryableTx handling in eth_estimateGas unnecessarily, which doesn't seem create wrong results, but the whole inconsistency is causing me confusion.
I will let the way it is right now, but depending on the reason we should revisit it in another task to clean up this inconsistency.

@tsahee am I missing something?

diegoximenes
diegoximenes previously approved these changes Apr 2, 2026
@diegoximenes diegoximenes assigned tsahee and unassigned diegoximenes Apr 2, 2026
Comment thread execution/gethexec/node.go Outdated
if n.AddressFilterService != nil {
n.AddressFilterService.Start(ctx)
checker := n.AddressFilterService.GetAddressChecker()
n.ExecEngine.SetAddressChecker(checker)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this o.k. in this order?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to move get/set address checker to (n *ExecutionNode) Initialize, and then ExecEngine, when started, will know it has an addresschecker (so it could do things like refuse transactions while the filter is not initialized)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now addressChecker is provided to ExecutionEngine through NewExecutionEngine.
n.ExecEngine.SetAddressChecker still exists, but only used by tests.

so it could do things like refuse transactions while the filter is not initialized

You mean the prechecker should refuse a transaction while the S3 file wasn't downloaded yet?
If so I think the load balancer should avoid sending a transaction to a prechecker that is not synced yet, and to decided if it is synced it should consider if it downloaded the S3 file already?
Same reasoning for nodes handling eth_call and eth_estimateGas.

Comment thread execution/gethexec/tx_filterer.go Outdated
}

func (f *txFilterer) TouchAddresses(statedb *state.StateDB, tx *types.Transaction, sender common.Address) {
touchAddresses(statedb, nil, tx, sender)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the event filter will be added in checkFiltered and de-facto will enforce the same policy as normal transactions. But it deserves more thought and possibly renaming

Comment thread execution/gethexec/executionengine.go Outdated
if tx.Type() == types.ArbitrumInternalTxType {
return nil
}
func touchAddresses(db *state.StateDB, ef *eventfilter.EventFilter, tx *types.Transaction, sender common.Address) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Diego's (justified) confusion comes from the fact that this function tries to do two things:
both "touch addresses" and apply event filter, while the function with the same name in core.TxFilterer only does one of those things, and eventFilter is applied later.

Either remove eventFilter from touchAddresses, or make the two funcs have different names.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My confusion is a little bit more than that.
It is also the fact that both eth_estimateGas and delayed filtering handle ArbitrumSubmitRetryableTx in a different way than regular sequencing.
I can see a world where only delayed sequencing filters ArbitrumSubmitRetryableTx differently compared to eth_estimateGas and regular sequencing, or a world in which all of them handle ArbitrumSubmitRetryableTx in the same way.

I added a commit that make all kinds of filtering (delayed sequencing, eth_estimateGas, regular sequencing) handle ArbitrumSubmitRetryableTx.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ArbitrumSubmitRetryableTx can only come from a L1, I don't think there is a way to create it with eth_call or eth_stimateGas

if config.Sequencer.Enable {
seqConfigFetcher := func() *SequencerConfig { return &configFetcher.Get().Sequencer }
sequencer, err = NewSequencer(execEngine, parentChainReader, seqConfigFetcher, seqParentChain)
if config.TransactionFiltering.TransactionFiltererRPCClient.URL != "" {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not critical for this PR - but reporting will also move and will also cover (at least) prechecker

Copy link
Copy Markdown
Contributor

@diegoximenes diegoximenes Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed out of GitHub, for reporting precheckers/sequencers will call cmd/filtering-report instead.

Comment thread execution/gethexec/node.go Outdated
if n.AddressFilterService != nil {
n.AddressFilterService.Start(ctx)
checker := n.AddressFilterService.GetAddressChecker()
n.ExecEngine.SetAddressChecker(checker)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to move get/set address checker to (n *ExecutionNode) Initialize, and then ExecEngine, when started, will know it has an addresschecker (so it could do things like refuse transactions while the filter is not initialized)

Copy link
Copy Markdown
Contributor

@tsahee tsahee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@tsahee tsahee enabled auto-merge April 6, 2026 21:37
@tsahee tsahee added this pull request to the merge queue Apr 6, 2026
Merged via the queue into master with commit 68da2ed Apr 6, 2026
43 of 44 checks passed
@tsahee tsahee deleted the prefilter-blockchain-api-2 branch April 6, 2026 22:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants