Skip to content

Conversation

@Tristan-Wilson
Copy link
Member

@Tristan-Wilson Tristan-Wilson commented Dec 18, 2025

Implement infrastructure for filtering transactions based on addresses touched during execution. This supports compliance use cases on certain chains where transactions interacting with certain addresses must be rejected by the sequencer before inclusion.

Addresses are collected during execution via TxProcessor.PushContract, which captures the contract address and caller for every CALL, STATICCALL, CREATE, and CREATE2 operation. The sequencer's postTxFilter then checks all collected addresses (plus tx.From and tx.To) against a configurable AddressFilter interface.

SELFDESTRUCT is handled on the geth side by capturing the beneficiary address in opSelfdestruct and opSelfdestruct6780.

DELEGATECALL and CALLCODE are intentionally not filtered as they only borrow code from the target address without any actual interaction.

A StaticFilter implementation is provided for testing and as a demonstration for future integration.

pulls in OffchainLabs/go-ethereum#601

fixes: NIT-4221

Implement infrastructure for filtering transactions based on addresses
touched during execution. This supports compliance use cases on certain
chains where transactions interacting with certain addresses must be
rejected by the sequencer before inclusion.

Addresses are collected during execution via TxProcessor.PushContract,
which captures the contract address and caller for every CALL,
STATICCALL, CREATE, and CREATE2 operation. The sequencer's postTxFilter
then checks all collected addresses (plus tx.From and tx.To) against a
configurable AddressFilter interface.

DELEGATECALL and CALLCODE are intentionally not filtered as they only
borrow code from the target address without any actual interaction.

A StaticFilter implementation is provided for testing and as a
demonstration for future integration.
@Tristan-Wilson Tristan-Wilson marked this pull request as ready for review December 18, 2025 16:39
@codecov
Copy link

codecov bot commented Dec 18, 2025

Codecov Report

❌ Patch coverage is 15.62500% with 27 lines in your changes missing coverage. Please review.
✅ Project coverage is 33.11%. Comparing base (02566fc) to head (11357f3).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4157      +/-   ##
==========================================
- Coverage   33.41%   33.11%   -0.31%     
==========================================
  Files         461      462       +1     
  Lines       55901    55932      +31     
==========================================
- Hits        18681    18522     -159     
- Misses      33921    34151     +230     
+ Partials     3299     3259      -40     

@github-actions
Copy link

github-actions bot commented Dec 18, 2025

❌ 4 Tests Failed:

Tests completed Failed Passed Skipped
4461 4 4457 0
View the top 3 failed tests by shortest run time
TestFIFOSequentialLocking
Stack Traces | 0.030s run time
=== RUN   TestFIFOSequentialLocking
    fifo_lock_test.go:34: 
        	Error Trace:	/home/runner/work/nitro/nitro/bold/protocol/sol/fifo_lock_test.go:34
        	Error:      	Not equal: 
        	            	expected: []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
        	            	actual  : []int{0, 1, 2, 4, 3, 5, 6, 7, 8, 9}
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -4,4 +4,4 @@
        	            	  (int) 2,
        	            	+ (int) 4,
        	            	  (int) 3,
        	            	- (int) 4,
        	            	  (int) 5,
        	Test:       	TestFIFOSequentialLocking
--- FAIL: TestFIFOSequentialLocking (0.03s)
TestVersion30
Stack Traces | 6.890s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
INFO [01-02|23:11:49.912] HTTP server stopped                      endpoint=127.0.0.1:45445
TRACE[01-02|23:11:49.912] P2P networking is spinning down
    precompile_inclusion_test.go:94: goroutine 610060 [running]:
        runtime/debug.Stack()
        	/opt/hostedtoolcache/go/1.25.5/x64/src/runtime/debug/stack.go:26 +0x5e
        github.com/offchainlabs/nitro/util/testhelpers.RequireImpl({0x4106750, 0xc073770700}, {0x40c3840, 0xc101ed1020}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/util/testhelpers/testhelpers.go:29 +0x55
        github.com/offchainlabs/nitro/system_tests.Require(0xc073770700, {0x40c3840, 0xc101ed1020}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/system_tests/common_test.go:2034 +0x5d
        github.com/offchainlabs/nitro/system_tests.testPrecompiles(0xc073770700, 0x1e, {0xc0ae8f3db0, 0x6, 0xc01ec1bc10?})
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:94 +0x371
        github.com/offchainlabs/nitro/system_tests.TestVersion30(0xc073770700?)
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:67 +0x798
        testing.tRunner(0xc073770700, 0x3d44a30)
        	/opt/hostedtoolcache/go/1.25.5/x64/src/testing/testing.go:1934 +0xea
        created by testing.(*T).Run in goroutine 1
        	/opt/hostedtoolcache/go/1.25.5/x64/src/testing/testing.go:1997 +0x465
        
    precompile_inclusion_test.go:94: �[31;1m [] execution aborted (timeout = 5s) �[0;0m
--- FAIL: TestVersion30 (6.89s)
TestVersion40
Stack Traces | 15.000s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
ERROR[01-02|23:11:48.694] Dangling trie nodes after full cleanup
�[38;5;48;1myay!! we validated block 5 in 493.15ms�[0;0m
    precompile_inclusion_test.go:94: goroutine 610061 [running]:
        runtime/debug.Stack()
        	/opt/hostedtoolcache/go/1.25.5/x64/src/runtime/debug/stack.go:26 +0x5e
        github.com/offchainlabs/nitro/util/testhelpers.RequireImpl({0x4106750, 0xc0737708c0}, {0x40c3840, 0xc12832b050}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/util/testhelpers/testhelpers.go:29 +0x55
        github.com/offchainlabs/nitro/system_tests.Require(0xc0737708c0, {0x40c3840, 0xc12832b050}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/system_tests/common_test.go:2034 +0x5d
        github.com/offchainlabs/nitro/system_tests.testPrecompiles(0xc0737708c0, 0x28, {0xc0ca083df8, 0x5, 0x39?})
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:94 +0x371
        github.com/offchainlabs/nitro/system_tests.TestVersion40(0xc0737708c0?)
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:71 +0x64b
        testing.tRunner(0xc0737708c0, 0x3d44a38)
        	/opt/hostedtoolcache/go/1.25.5/x64/src/testing/testing.go:1934 +0xea
        created by testing.(*T).Run in goroutine 1
        	/opt/hostedtoolcache/go/1.25.5/x64/src/testing/testing.go:1997 +0x465
        
    precompile_inclusion_test.go:94: �[31;1m [] execution aborted (timeout = 5s) �[0;0m
--- FAIL: TestVersion40 (15.00s)

📣 Thoughts on this report? Let Codecov know! | Powered by Codecov

Copy link
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.

see geth-side PR

@tsahee tsahee assigned Tristan-Wilson and unassigned tsahee Dec 26, 2025
All address filtering now goes through statedb.TouchAddress() and the
arbTxFilter mechanism. preTxFilter uses TouchAddress for from/to addresses,
while execution uses it for contract calls, creates, and selfdestruct.

The filter now lives in ExecutionEngine to simplify setting up statedb
with the filter.
Copy link
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.

also see geth side notes

return nil, err
}
if s.addressFilter != nil {
statedb.SetAddressFilter(s.addressFilter)
Copy link
Contributor

Choose a reason for hiding this comment

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

we also need to apply the filter in sequenceDelayedMessageWithBlockMutex (and test it)

Copy link
Member Author

Choose a reason for hiding this comment

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

Will work on it, otherwise in the meantime maybe we can merge this PR if it looks good and do that in a separate PR?

return &StaticFilter{addresses: m}
}

func (f *StaticFilter) IsFiltered(addr common.Address) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

see comments in geth about the interface

Copy link
Member Author

Choose a reason for hiding this comment

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

Addressed

@tsahee tsahee assigned Tristan-Wilson and unassigned tsahee Dec 29, 2025
Address review feedback requesting async-capable address filtering:
- TouchAddress submits addresses for checking (can start async checks)
- IsFiltered blocks until all checks complete and returns result
- Fresh state created per-tx in SetTxContext (replaces ClearAddresses)

This design allows implementations to check addresses in parallel using
separate goroutines while the main thread executes, enabling lookups in
large databases without blocking execution.
@Tristan-Wilson Tristan-Wilson removed their assignment Dec 31, 2025
Copy link
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 January 2, 2026 22:51
@tsahee tsahee added this pull request to the merge queue Jan 2, 2026
Any commits made after this event will not be merged.
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to no response for status checks Jan 3, 2026
@pmikolajczyk41 pmikolajczyk41 added this pull request to the merge queue Jan 7, 2026
Any commits made after this event will not be merged.
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jan 7, 2026
@pmikolajczyk41 pmikolajczyk41 added this pull request to the merge queue Jan 7, 2026
Any commits made after this event will not be merged.
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to no response for status checks Jan 7, 2026
@pmikolajczyk41 pmikolajczyk41 added this pull request to the merge queue Jan 7, 2026
Any commits made after this event will not be merged.
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jan 7, 2026
@pmikolajczyk41 pmikolajczyk41 added this pull request to the merge queue Jan 7, 2026
Any commits made after this event will not be merged.
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jan 7, 2026
@pmikolajczyk41 pmikolajczyk41 added this pull request to the merge queue Jan 8, 2026
Any commits made after this event will not be merged.
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.

3 participants