Skip to content

Conversation

@ganeshvanahalli
Copy link
Contributor

@ganeshvanahalli ganeshvanahalli commented Jul 11, 2025

This PR implements delayed message accumulation logic for native mode of MEL. We introduce a new data structure DelayedMessageBacklog to enable validation of seen but not-yet-read delayed messages against the current merkle root formed by accumulating all the delayed messages seen by MEL up until now.

For optimization, future messages that are prefetched for generating the merkle root are also pre-validated (or pre-read) i.e we don't re-validate them again when we read them in the future, instead we check that the pre-validated message's hash matches the hash of delayed message we fetch from the DB using the same delayed message index.

This PR is based off of #3297 and adding its description below-
We introduce the delayed messages accumulation logic and its verification using MerkleAccumulator. MEL state has been updated to store DelayedMessageMerklePartials instead of a single head merkle root as that can anyway be calculated using partials.

Testing

Added multiple unit tests to check the working of delayed message accumulation and the handling of intermediary merkle roots (of messages that are seen but not read) in conditions like reorgs and advancing of finalized block.

Design

melDelayedAcc

rauljordan
rauljordan previously approved these changes Jul 15, 2025
Base automatically changed from mel-database-impl to master July 17, 2025 15:36
@ganeshvanahalli ganeshvanahalli assigned amsanghi and unassigned tsahee Nov 21, 2025
@github-actions
Copy link

github-actions bot commented Nov 21, 2025

❌ 2 Tests Failed:

Tests completed Failed Passed Skipped
1235 2 1233 0
View the top 2 failed tests by shortest run time
TestVersion40
Stack Traces | 7.590s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
�[38;5;48;1myay!! we validated block 19 in 261.29ms�[0;0m
ERROR[12-15|08:06:53.125] Dangling trie nodes after full cleanup
    precompile_inclusion_test.go:94: goroutine 610171 [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({0x40ed530, 0xc07c4e68c0}, {0x40aab80, 0xc0e49ba180}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/util/testhelpers/testhelpers.go:29 +0x55
        github.com/offchainlabs/nitro/system_tests.Require(0xc07c4e68c0, {0x40aab80, 0xc0e49ba180}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/system_tests/common_test.go:1998 +0x5d
        github.com/offchainlabs/nitro/system_tests.testPrecompiles(0xc07c4e68c0, 0x28, {0xc0b4f9ddf8, 0x5, 0x39?})
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:94 +0x371
        github.com/offchainlabs/nitro/system_tests.TestVersion40(0xc07c4e68c0?)
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:71 +0x64b
        testing.tRunner(0xc07c4e68c0, 0x3d2d7f8)
        	/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 (7.59s)
TestTwoNodesLong
Stack Traces | 61.310s run time
=== RUN   TestTwoNodesLong
=== PAUSE TestTwoNodesLong
=== CONT  TestTwoNodesLong
    common_test.go:694: BuildL1 deployConfig: DeployBold=true, DeployReferenceDAContracts=false
    twonodeslong_test.go:79: DelayedFaucet has 80008000000000000800, per delayed: 100000000000000001, baseprice: 1e+08
�[90mTime to activate hostio-test: 432.663101ms�[0;0m
�[90mmulticall: len 4.44K vs 12.50K�[0;0m
�[90mmulticall: deployed to 0xA02062aa4Cb0872315ACA3eA6dBF077d90B2DAC1�[0;0m
�[90mTime to activate multicall: 255.379638ms�[0;0m
    twonodeslong_test.go:135: Done sending 94 delayed transfers 251 direct transfers
    twonodeslong_test.go:168: delayed balance 9400000000000000094 expected 9400000000000000094 transfers 94
    twonodeslong_test.go:169: direct balance 49600744 expected 50200753 transfers 251
    twonodeslong_test.go:172: owner balance 115792089237316195423570985008687907853269984665640564039457583997258729639927 delayed faucet 70607802597900000706
    twonodeslong_test.go:173: �[31;1m [Unexpected balance] �[0;0m
ERROR[12-15|08:07:26.102] a large batch posting backlog exists     recentlyHitL1Bounds=false currentPosition=17 messageCount=103 messagesPerBatch=1 postedMessages=1 unpostedMessages=86  batchBacklogEstimate=86
ERROR[12-15|08:07:26.112] Dangling trie nodes after full cleanup
ERROR[12-15|08:07:26.136] Error getting finality msg count         scenario=safe err="io: read/write on closed pipe"
ERROR[12-15|08:07:26.141] Error getting finality msg count         scenario=safe err="io: read/write on closed pipe"
--- FAIL: TestTwoNodesLong (61.31s)

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

@eljobe eljobe self-requested a review December 2, 2025 15:09
amsanghi
amsanghi previously approved these changes Dec 12, 2025
@amsanghi amsanghi assigned eljobe and unassigned amsanghi Dec 12, 2025

// InitializeDelayedMessageBacklog is to be only called by the Start fsm step of MEL. This function fills the backlog based on the seen and read count from the given mel state
func InitializeDelayedMessageBacklog(ctx context.Context, d *mel.DelayedMessageBacklog, db *Database, state *mel.State, finalizedAndReadIndexFetcher func(context.Context) (uint64, error)) error {
if state.DelayedMessagesSeen == 0 && state.DelayedMessagesRead == 0 { // this is the first mel state so no need to initialize backlog even if the state isnt finalized yet
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Typo "isn't"

@eljobe eljobe assigned ganeshvanahalli and unassigned eljobe Dec 12, 2025
@eljobe eljobe disabled auto-merge December 15, 2025 10:37
@eljobe eljobe enabled auto-merge December 15, 2025 10:37
@eljobe eljobe added this pull request to the merge queue Dec 15, 2025
Any commits made after this event will not be merged.
github-merge-queue bot pushed a commit that referenced this pull request Dec 15, 2025
* [MEL] - Implement delayed message accumulation in native mode

* address PR comments

* add documentation for checkAgainstAccumulator and a minor fix

* undo changes to addressed review comments from other PRs

* dont make L2msg rlp optional

* make meldb take a KeyValueStore

* handle reorg in start step- reducing code diff

* Message extraction function works with logs instead of receipts

* only keep delayed message accumulation changes

* cleanup non related code

* address PR comments

---------

Co-authored-by: Raul Jordan <[email protected]>
Co-authored-by: Pepper Lebeck-Jobe <[email protected]>
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.

6 participants