Skip to content

[MEL] - Implement a Unified Replay Binary for MEL#4553

Open
rauljordan wants to merge 18 commits intomasterfrom
raul/mel-unified-binary
Open

[MEL] - Implement a Unified Replay Binary for MEL#4553
rauljordan wants to merge 18 commits intomasterfrom
raul/mel-unified-binary

Conversation

@rauljordan
Copy link
Copy Markdown
Contributor

@rauljordan rauljordan commented Mar 23, 2026

This PR brings over changes from #4152 into master.

Summary

  • Introduces a new unified-replay binary (cmd/unified-replay/) that combines both MEL (Message Extraction Layer) message extraction and block production into a single WASM-compilable replay program
  • Adds a new GetEndParentChainBlockHash host I/O opcode to support MEL proving
  • Adds the melwavmio package providing WASM imports and native stubs for MEL
  • Updates the Makefile with build targets for the unified replay WASM binary

How it Works

The unified replay binary is quite easy to understand in pythonic pseudocode. It essentially either runs message extraction or block production depending on some of the input or computed values. This means that validation of Arbitrum becomes a message extraction followed by execution of those extracted messages:

def main():
    # Initialize MEL WASM I/O stubs and hook into geth
    melwavmio.stub_init()
    require_hooked_geth()
    setup_logger(level=ERROR)
    
    # Pre-warm ECDSA signature verification caches
    populate_ecdsa_caches()

    # Read initial state from the machine's global state slots
    mel_msg_hash = melwavmio.get_mel_msg_hash()        # bytes32 slot 3
    start_mel_state_hash = melwavmio.get_start_mel_root()  # bytes32 slot 2
    mel_state = rlp_decode(read_preimage(start_mel_state_hash))

    # === MODE 1: Block Production (when there's a message to execute) ===
    if mel_msg_hash != ZERO_HASH:
        produce_block(mel_msg_hash)
        melwavmio.increase_position_in_mel()  # pos++
    
    # === MODE 2: Message Extraction (walk parent chain to find new messages) ===
    else:
        target_block_hash = melwavmio.get_end_parent_chain_block_hash()
        chain_config = read_chain_config_from_last_block()
        mel_state = extract_messages_up_to(chain_config, mel_state, target_block_hash)
        melwavmio.set_end_mel_root(mel_state.hash())

    # === Schedule next message (if any remain) ===
    position = melwavmio.get_position_in_mel()
    if mel_state.msg_count > position:
        next_msg = MessageReader(preimage_resolver).read(mel_state, position)
        melwavmio.set_mel_msg_hash(next_msg.hash())
    else:
        melwavmio.set_mel_msg_hash(ZERO_HASH)  # no more messages

Changes

New files

  • cmd/unified-replay/main.go — Unified replay entry point handling two modes: block production (when a MEL message hash is present) and message extraction (walking parent chain blocks backward to extract messages)
  • cmd/unified-replay/db.go — Preimage-backed database adapter for state trie lookups during replay
  • cmd/unified-replay/preimage_resolver.go — WAVM preimage resolver and blob reader implementations
  • melwavmio/ — MEL-specific WAVM I/O package with WASM imports

Modified files

  • Prover (Rust) — Extended GlobalState to 4 bytes32 slots with backward-compatible hashing, added GetEndParentChainBlockHash opcode, and made binary output filenames configurable
  • Makefile — Added build-unified-replay-env and build-unified-wasm-bin targets

@rauljordan rauljordan self-assigned this Mar 23, 2026
@rauljordan rauljordan assigned tsahee and unassigned rauljordan Mar 23, 2026
@rauljordan rauljordan requested review from eljobe and tsahee March 23, 2026 21:34
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 23, 2026

Codecov Report

❌ Patch coverage is 0% with 349 lines in your changes missing coverage. Please review.
✅ Project coverage is 33.99%. Comparing base (4676f43) to head (371044f).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4553      +/-   ##
==========================================
- Coverage   34.16%   33.99%   -0.18%     
==========================================
  Files         494      499       +5     
  Lines       58932    59271     +339     
==========================================
+ Hits        20137    20152      +15     
- Misses      35249    35581     +332     
+ Partials     3546     3538       -8     

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 23, 2026

❌ 15 Tests Failed:

Tests completed Failed Passed Skipped
4783 15 4768 0
View the top 3 failed tests by shortest run time
TestAliasingFlaky
Stack Traces | -0.000s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
INFO [04-06|20:15:35.324] Writing cached state to disk             block=1  hash=5c1883..a748de root=c349f6..9b02e2
INFO [04-06|20:15:35.324] Updated payload                          id=0x03dea2c59ecefe35                      number=46 hash=14f6f5..d5a64a txs=0  withdrawals=0 gas=0         fees=0              root=12ee91..0c354f elapsed="477.55µs"
INFO [04-06|20:15:35.324] Persisted trie from memory database      nodes=25  flushnodes=0 size=4.56KiB  flushsize=0.00B time="195.417µs" flushtime=0s gcnodes=0 gcsize=0.00B gctime=0s          livenodes=86  livesize=15.99KiB
INFO [04-06|20:15:35.324] Writing snapshot state to disk           root=77ae46..2fbcae
INFO [04-06|20:15:35.324] Persisted trie from memory database      nodes=0   flushnodes=0 size=0.00B    flushsize=0.00B time=721ns       flushtime=0s gcnodes=0 gcsize=0.00B gctime=0s          livenodes=86  livesize=15.99KiB
INFO [04-06|20:15:35.324] Stopping work on payload                 id=0x03dea2c59ecefe35                      reason=delivery
INFO [04-06|20:15:35.324] Blockchain stopped
INFO [04-06|20:15:35.324] Imported new potential chain segment     number=46 hash=14f6f5..d5a64a blocks=1  txs=0  mgas=0.000 elapsed="323.864µs" mgasps=0.000    triediffs=221.04KiB triedirty=0.00B
INFO [04-06|20:15:35.325] Chain head was updated                   number=46 hash=14f6f5..d5a64a root=12ee91..0c354f elapsed="19.417µs"
INFO [04-06|20:15:35.325] Ethereum protocol stopped
INFO [04-06|20:15:35.325] Submitted transaction                    hash=0x57e601445b3627d121f392223c7ddaf5b9f69d47135ad2f827a6de00c52de5fa from=0xaF24Ca6c2831f4d4F629418b50C227DF0885613A nonce=5  recipient=0xaF24Ca6c2831f4d4F629418b50C227DF0885613A value=1,000,000,000,000
INFO [04-06|20:15:35.325] Transaction pool stopped
INFO [04-06|20:15:35.325] Persisting dirty state                   head=33 root=23d214..94f403 layers=33
INFO [04-06|20:15:35.325] Starting work on payload                 id=0x039e3d1118fd95a4
INFO [04-06|20:15:35.325] Updated payload                          id=0x039e3d1118fd95a4                      number=47 hash=3958df..ac6673 txs=1  withdrawals=0 gas=21000     fees=0.002092911308 root=a60093..148e7e elapsed="294.453µs"
INFO [04-06|20:15:35.326] Persisted dirty state to disk            size=160.85KiB elapsed="866.214µs"
INFO [04-06|20:15:35.326] Stopping work on payload                 id=0x039e3d1118fd95a4                      reason=delivery
INFO [04-06|20:15:35.326] Blockchain stopped
INFO [04-06|20:15:35.326] Imported new potential chain segment     number=47 hash=3958df..ac6673 blocks=1  txs=1  mgas=0.021 elapsed="398.613µs" mgasps=52.683   triediffs=225.07KiB triedirty=0.00B
INFO [04-06|20:15:35.326] Chain head was updated                   number=47 hash=3958df..ac6673 root=a60093..148e7e elapsed="43.943µs"
TestPruningDBSizeReduction
Stack Traces | 0.000s run time
=== RUN   TestPruningDBSizeReduction
--- FAIL: TestPruningDBSizeReduction (0.00s)
TestBatchPosterL1SurplusMatchesBatchGasFlaky
Stack Traces | 0.560s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
panic: runtime error: invalid memory address or nil pointer dereference [recovered, repanicked]
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x207e912]

goroutine 55 [running]:
testing.tRunner.func1.2({0x37e7220, 0x62039b0})
	/opt/hostedtoolcache/go/1.25.8/x64/src/testing/testing.go:1872 +0x237
testing.tRunner.func1()
	/opt/hostedtoolcache/go/1.25.8/x64/src/testing/testing.go:1875 +0x35b
panic({0x37e7220?, 0x62039b0?})
	/opt/hostedtoolcache/go/1.25.8/x64/src/runtime/panic.go:783 +0x132
github.com/offchainlabs/nitro/arbnode.(*InboxTracker).GetBatchCount(0x1e071900?)
	/home/runner/work/nitro/nitro/arbnode/inbox_tracker.go:210 +0x12
github.com/offchainlabs/nitro/arbnode.(*InboxTracker).FindInboxBatchContainingMessage(0x0, 0x8)
	/home/runner/work/nitro/nitro/arbnode/inbox_tracker.go:225 +0x2f
github.com/offchainlabs/nitro/system_tests.TestBatchPosterL1SurplusMatchesBatchGasFlaky(0xc0002c3180)
	/home/runner/work/nitro/nitro/system_tests/batch_poster_test.go:839 +0x725
testing.tRunner(0xc0002c3180, 0x41b9dc8)
	/opt/hostedtoolcache/go/1.25.8/x64/src/testing/testing.go:1934 +0xea
created by testing.(*T).Run in goroutine 1
	/opt/hostedtoolcache/go/1.25.8/x64/src/testing/testing.go:1997 +0x465

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

@rauljordan rauljordan assigned eljobe and unassigned tsahee Apr 15, 2026
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.

3 participants