Skip to content

Conversation

@ganeshvanahalli
Copy link
Contributor

This PR adds required code to handle the rollbacks in MEL and Block validators during a reorg (L1 or L2 or both). Whenever a reorg is detected MELValidator (if) is rollbacked first and then the BlockValidator (if).

Resolves NIT-4480

@codecov
Copy link

codecov bot commented Feb 10, 2026

Codecov Report

❌ Patch coverage is 0% with 85 lines in your changes missing coverage. Please review.
✅ Project coverage is 28.95%. Comparing base (8ad11cf) to head (955587d).
⚠️ Report is 1 commits behind head on raul/mel-block-validator-enabled.

Additional details and impacted files
@@                         Coverage Diff                          @@
##           raul/mel-block-validator-enabled    #4360      +/-   ##
====================================================================
- Coverage                             28.96%   28.95%   -0.02%     
====================================================================
  Files                                   497      497              
  Lines                                 58774    58835      +61     
====================================================================
+ Hits                                  17022    17033      +11     
- Misses                                38647    38701      +54     
+ Partials                               3105     3101       -4     

@github-actions
Copy link
Contributor

github-actions bot commented Feb 11, 2026

❌ 55 Tests Failed:

Tests completed Failed Passed Skipped
4183 55 4128 0
View the top 3 failed tests by shortest run time
TestFastConfirmationWithdrawal
Stack Traces | 20.140s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
ERROR[02-11|22:15:11.992] latest L1 block is old                   l1Block=0 l1Timestamp=1970-01-01T00:00:00+0000 age=491902h15m11.991993846s
ERROR[02-11|22:15:12.010] latest L1 block is old                   l1Block=0 l1Timestamp=1970-01-01T00:00:00+0000 age=491902h15m12.010057386s
ERROR[02-11|22:15:12.020] latest L1 block is old                   l1Block=0 l1Timestamp=1970-01-01T00:00:00+0000 age=491902h15m12.020976736s
ERROR[02-11|22:15:12.042] latest L1 block is old                   l1Block=0 l1Timestamp=1970-01-01T00:00:00+0000 age=491902h15m12.042265174s
    fast_confirm_test.go:114: goroutine 8889 [running]:
        runtime/debug.Stack()
        	/opt/hostedtoolcache/go/1.25.6/x64/src/runtime/debug/stack.go:26 +0x5e
        github.com/offchainlabs/nitro/util/testhelpers.RequireImpl({0x440a990, 0xc004539880}, {0x43c5fc0, 0xc001104e60}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/util/testhelpers/testhelpers.go:29 +0x9f
        github.com/offchainlabs/nitro/system_tests.Require(0xc004539880, {0x43c5fc0, 0xc001104e60}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/system_tests/common_test.go:2125 +0x5d
        github.com/offchainlabs/nitro/system_tests.TestFastConfirmationWithdrawal(0xc004539880)
        	/home/runner/work/nitro/nitro/system_tests/fast_confirm_test.go:114 +0xda6
        testing.tRunner(0xc004539880, 0x403df78)
        	/opt/hostedtoolcache/go/1.25.6/x64/src/testing/testing.go:1934 +0xea
        created by testing.(*T).Run in goroutine 1
        	/opt/hostedtoolcache/go/1.25.6/x64/src/testing/testing.go:1997 +0x465
        
    fast_confirm_test.go:114: �[31;1m [] execution reverted: UnknownRoot(0x6bb77b369bf9f2ba18d3facbed12474dc8758a43354b2ea20f6385713f998ff1) �[0;0m
--- FAIL: TestFastConfirmationWithdrawal (20.14s)
TestMessageExtractionLayer_TxStreamerHandleReorg
Stack Traces | 28.720s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
INFO [02-11|22:27:14.229] Writing snapshot state to disk           root=3150c9..4d6b53
INFO [02-11|22:27:14.229] Persisted trie from memory database      nodes=0    flushnodes=0 size=0.00B      flushsize=0.00B time="2.004µs"    flushtime=0s gcnodes=0 gcsize=0.00B gctime=0s          livenodes=282   livesize=52.69KiB
INFO [02-11|22:27:14.230] Blockchain stopped
WARN [02-11|22:27:14.230] Served eth_call                          reqid=1433  duration="33.973µs"    err="header not found"
WARN [02-11|22:27:14.231] Served eth_call                          reqid=2716  duration="32.851µs"    err="header not found"
INFO [02-11|22:27:14.231] Writing cached state to disk             block=16   hash=e84b1c..bf62ae root=03ce40..8e9a5d
INFO [02-11|22:27:14.233] Persisted trie from memory database      nodes=237  flushnodes=0 size=27.96KiB   flushsize=0.00B time=1.119965ms   flushtime=0s gcnodes=0 gcsize=0.00B gctime="21.757µs"  livenodes=616   livesize=116.62KiB
INFO [02-11|22:27:14.233] Writing cached state to disk             block=15   hash=506981..35a79d root=dfe3fd..5407b2
INFO [02-11|22:27:14.233] Persisted trie from memory database      nodes=38   flushnodes=0 size=6.83KiB    flushsize=0.00B time="175.248µs"  flushtime=0s gcnodes=0 gcsize=0.00B gctime=0s          livenodes=578   livesize=109.79KiB
INFO [02-11|22:27:14.233] Writing cached state to disk             block=1    hash=d64b35..6f683c root=9e0351..4d32e2
INFO [02-11|22:27:14.233] Persisted trie from memory database      nodes=36   flushnodes=0 size=5.94KiB    flushsize=0.00B time="145.292µs"  flushtime=0s gcnodes=0 gcsize=0.00B gctime=0s          livenodes=542   livesize=103.86KiB
INFO [02-11|22:27:14.233] Writing snapshot state to disk           root=3150c9..4d6b53
INFO [02-11|22:27:14.233] Persisted trie from memory database      nodes=0    flushnodes=0 size=0.00B      flushsize=0.00B time="1.734µs"    flushtime=0s gcnodes=0 gcsize=0.00B gctime=0s          livenodes=542   livesize=103.86KiB
INFO [02-11|22:27:14.235] Blockchain stopped
INFO [02-11|22:27:14.235] Ethereum protocol stopped
INFO [02-11|22:27:14.235] Transaction pool stopped
INFO [02-11|22:27:14.236] Persisting dirty state                   head=110 root=f8bc60..eeb9db layers=110
INFO [02-11|22:27:14.242] Persisted dirty state to disk            size=473.17KiB  elapsed=6.021ms
INFO [02-11|22:27:14.242] Blockchain stopped
--- FAIL: TestMessageExtractionLayer_TxStreamerHandleReorg (28.72s)
TestMessageExtractionLayer_TxStreamerHandleReorg
Stack Traces | 30.470s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
INFO [02-11|22:34:40.721] Persisting dirty state                   head=15  root=2a6ca8..f5819c layers=15
WARN [02-11|22:34:40.722] Served eth_call                          reqid=5455  duration="37.231µs"    err="header not found"
INFO [02-11|22:34:40.723] Persisted dirty state to disk            size=109.21KiB elapsed=1.974ms
INFO [02-11|22:34:40.724] Blockchain stopped
INFO [02-11|22:34:40.724] Persisting dirty state                   head=16  root=23084f..6d5816 layers=16
WARN [02-11|22:34:40.726] Served eth_call                          reqid=5892  duration="59.355µs"    err="header not found"
INFO [02-11|22:34:40.726] Persisted dirty state to disk            size=117.02KiB elapsed=2.002ms
INFO [02-11|22:34:40.727] Blockchain stopped
WARN [02-11|22:34:40.727] Served eth_call                          reqid=5459  duration="32.251µs"    err="header not found"
INFO [02-11|22:34:40.727] Ethereum protocol stopped
INFO [02-11|22:34:40.728] Transaction pool stopped
INFO [02-11|22:34:40.728] Persisting dirty state                   head=110 root=51b9f8..5b0efa layers=110
WARN [02-11|22:34:40.731] Served eth_call                          reqid=5899  duration="62.894µs"    err="header not found"
WARN [02-11|22:34:40.775] Served eth_call                          reqid=5466  duration="55.861µs"    err="header not found"
WARN [02-11|22:34:40.775] Served eth_call                          reqid=5903  duration="36.321µs"    err="header not found"
INFO [02-11|22:34:40.780] Persisted dirty state to disk            size=471.37KiB elapsed=52.899ms
INFO [02-11|22:34:40.781] Blockchain stopped
WARN [02-11|22:34:40.781] Served eth_call                          reqid=5904  duration="53.553µs"    err="header not found"
WARN [02-11|22:34:40.782] Sequencer ReadFromTxQueueTimeout is higher than MaxBlockSpeed ReadFromTxQueueTimeout=1s MaxBlockSpeed=10ms
--- FAIL: TestMessageExtractionLayer_TxStreamerHandleReorg (30.47s)

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

}

type MELValidator interface {
Rewind(parentChainBlockNumber uint64)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this the parent chain block number we want to rewind to?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yep

return err
}
if m.melValidator != nil {
m.melValidator.Rewind(parentChainBlockNumber)
Copy link
Contributor

Choose a reason for hiding this comment

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

This introduces a circular dependency. It would be more idiomatic if the mel validator can subscribe to a channel and we send over that channel to anyone that cares about rewinding. That way, the runner does not need to know anything about validation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

makes sense, I added this change

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants