Skip to content

Construct init msg without consensus#4395

Open
pmikolajczyk41 wants to merge 47 commits intomasterfrom
pmikolajczyk/nit-4242-construct-init-msg
Open

Construct init msg without consensus#4395
pmikolajczyk41 wants to merge 47 commits intomasterfrom
pmikolajczyk/nit-4242-construct-init-msg

Conversation

@pmikolajczyk41
Copy link
Copy Markdown
Member

Previously we had a single method GetConsensusParsedInitMsg for restoring init message. Depending on a boolean flag as one of its parameters, nitro either talked with parent chain, or directly used chain config it got from the previous step. This PR replaces this with 3 functions:

  • GetParsedInitMsgFromConsensus - as name suggests, nitro reads the message directly from the parent chain (and then checks its chain config compatibility with the config it got from the previous step)
  • GetParsedInitMsgFromGenesis - if genesis object is available, nitro restores the init message from it; no consensus involved
  • GetParsedInitMsgFromChainConfig - the old fallback: in case neither parent chain (consensus) nor genesis is available, nitro restores the message from the chain config it got from gethexec.TryReadStoredChainConfig

closes NIT-4242

@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 17, 2026

Codecov Report

❌ Patch coverage is 8.21918% with 134 lines in your changes missing coverage. Please review.
✅ Project coverage is 32.75%. Comparing base (d7fe12c) to head (b563224).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4395      +/-   ##
==========================================
- Coverage   34.56%   32.75%   -1.81%     
==========================================
  Files         495      495              
  Lines       58648    58744      +96     
==========================================
- Hits        20272    19242    -1030     
- Misses      34772    36150    +1378     
+ Partials     3604     3352     -252     

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 17, 2026

❌ 10 Tests Failed:

Tests completed Failed Passed Skipped
4434 10 4424 0
View the top 3 failed tests by shortest run time
TestRedisProduceComplex/two_producers,_some_consumers_killed,_others_should_take_over_their_work,_some_invalid_entries,_unequal_number_of_requests_from_producers
Stack Traces | 2.110s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
�[36mDEBUG�[0m[03-12|15:39:46.424] redis producer: check responses starting
�[36mDEBUG�[0m[03-12|15:39:46.424] checkResponses                           �[36mresponded�[0m=0   �[36merrored�[0m=0 �[36mchecked�[0m=0
�[36mDEBUG�[0m[03-12|15:39:46.428] redis producer: check responses starting
�[36mDEBUG�[0m[03-12|15:39:46.432] redis producer: check responses starting
�[36mDEBUG�[0m[03-12|15:39:46.432] checkResponses                           �[36mresponded�[0m=0   �[36merrored�[0m=0 �[36mchecked�[0m=0
�[36mDEBUG�[0m[03-12|15:39:46.432] checkResponses                           �[36mresponded�[0m=0   �[36merrored�[0m=0 �[36mchecked�[0m=2
�[36mDEBUG�[0m[03-12|15:39:46.437] redis producer: check responses starting
�[36mDEBUG�[0m[03-12|15:39:46.437] redis producer: check responses starting
�[36mDEBUG�[0m[03-12|15:39:46.441] checkResponses                           �[36mresponded�[0m=0   �[36merrored�[0m=0 �[36mchecked�[0m=0
�[36mDEBUG�[0m[03-12|15:39:46.442] checkResponses                           �[36mresponded�[0m=0   �[36merrored�[0m=0 �[36mchecked�[0m=2
�[36mDEBUG�[0m[03-12|15:39:46.446] redis producer: check responses starting
�[36mDEBUG�[0m[03-12|15:39:46.446] checkResponses                           �[36mresponded�[0m=0   �[36merrored�[0m=0 �[36mchecked�[0m=0
�[36mDEBUG�[0m[03-12|15:39:46.448] redis producer: check responses starting
�[36mDEBUG�[0m[03-12|15:39:46.448] request timed out waiting for response   �[36mmsgId�[0m=1773329984446-18 �[36mallowedOldestId�[0m=1773329984448-0
�[36mDEBUG�[0m[03-12|15:39:46.449] request timed out waiting for response   �[36mmsgId�[0m=1773329984446-17 �[36mallowedOldestId�[0m=1773329984448-0
�[36mDEBUG�[0m[03-12|15:39:46.449] checkResponses                           �[36mresponded�[0m=0   �[36merrored�[0m=2 �[36mchecked�[0m=2
    pubsub_test.go:385: Unexpected error while awaiting responses, producer: 0, response: 38, err: error getting response, request has been waiting for too long
    pubsub_test.go:385: Unexpected error while awaiting responses, producer: 0, response: 39, err: error getting response, request has been waiting for too long
�[36mDEBUG�[0m[03-12|15:39:46.548] Error destroying a stream group          �[36merror�[0m="dial tcp 127.0.0.1:39759: connect: connection refused"
--- FAIL: TestRedisProduceComplex/two_producers,_some_consumers_killed,_others_should_take_over_their_work,_some_invalid_entries,_unequal_number_of_requests_from_producers (2.11s)
TestBroadcastClientConfirmedMessage
Stack Traces | 5.300s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
INFO [03-12|15:39:20.434] connecting to arbitrum inbox message broadcaster url=ws://127.0.0.1:40669/
WARN [03-12|15:39:20.435] client did not accept required compression, disconnecting connectingIP=127.0.0.1
INFO [03-12|15:39:20.435] Feed connected                           feedServerVersion=2 chainId=9742 requestedSeqNum=0
INFO [03-12|15:39:20.435] Feed connected                           feedServerVersion=2 chainId=9742 requestedSeqNum=0
WARN [03-12|15:39:20.435] readData returned EOF                    url=ws://127.0.0.1:40669/ opcode=0 err=EOF
WARN [03-12|15:39:20.435] client did not accept required compression, disconnecting connectingIP=127.0.0.1
INFO [03-12|15:39:20.435] First reconnection attempt, skipping backoff url=ws://127.0.0.1:40669/
INFO [03-12|15:39:20.435] connecting to arbitrum inbox message broadcaster url=ws://127.0.0.1:40669/
WARN [03-12|15:39:20.435] readData returned EOF                    url=ws://127.0.0.1:40669/ opcode=0 err=EOF
INFO [03-12|15:39:20.454] First reconnection attempt, skipping backoff url=ws://127.0.0.1:40669/
INFO [03-12|15:39:20.455] connecting to arbitrum inbox message broadcaster url=ws://127.0.0.1:40669/
WARN [03-12|15:39:20.456] client did not accept required compression, disconnecting connectingIP=127.0.0.1
WARN [03-12|15:39:20.459] client did not accept required compression, disconnecting connectingIP=127.0.0.1
INFO [03-12|15:39:20.460] Feed connected                           feedServerVersion=2 chainId=9742 requestedSeqNum=0
WARN [03-12|15:39:20.460] readData returned EOF                    url=ws://127.0.0.1:40669/ opcode=0 err=EOF
INFO [03-12|15:39:20.460] First reconnection attempt, skipping backoff url=ws://127.0.0.1:40669/
INFO [03-12|15:39:20.460] connecting to arbitrum inbox message broadcaster url=ws://127.0.0.1:40669/
INFO [03-12|15:39:20.464] Feed connected                           feedServerVersion=2 chainId=9742 requestedSeqNum=0
    broadcastclient_test.go:359: Client did not receive confirm message
--- FAIL: TestBroadcastClientConfirmedMessage (5.30s)
TestVersion30
Stack Traces | 7.730s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
INFO [03-12|15:48:40.551] Log index head rendering finished        firstblock=0 lastblock=1   processed=2  elapsed=1.233s
    precompile_inclusion_test.go:94: goroutine 602408 [running]:
        runtime/debug.Stack()
        	/opt/hostedtoolcache/go/1.25.7/x64/src/runtime/debug/stack.go:26 +0x5e
        github.com/offchainlabs/nitro/util/testhelpers.RequireImpl({0x4119030, 0xc05b7ed6c0}, {0x40d5260, 0xc0ec78a4b0}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/util/testhelpers/testhelpers.go:29 +0x55
        github.com/offchainlabs/nitro/system_tests.Require(0xc05b7ed6c0, {0x40d5260, 0xc0ec78a4b0}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/system_tests/common_test.go:2080 +0x5d
        github.com/offchainlabs/nitro/system_tests.testPrecompiles(0xc05b7ed6c0, 0x1e, {0xc0a9a27db0, 0x6, 0x0?})
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:94 +0x371
        github.com/offchainlabs/nitro/system_tests.TestVersion30(0xc05b7ed6c0?)
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:67 +0x798
        testing.tRunner(0xc05b7ed6c0, 0x3d4ccd8)
        	/opt/hostedtoolcache/go/1.25.7/x64/src/testing/testing.go:1934 +0xea
        created by testing.(*T).Run in goroutine 1
        	/opt/hostedtoolcache/go/1.25.7/x64/src/testing/testing.go:1997 +0x465
        
    precompile_inclusion_test.go:94: �[31;1m [] execution aborted (timeout = 5s) �[0;0m
INFO [03-12|15:48:48.106] Chain head was updated                   number=13  hash=6aa7f6..16e349 root=d21d28..bf0af7 elapsed="238.156µs"
--- FAIL: TestVersion30 (7.73s)

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

Copy link
Copy Markdown
Contributor

@bragaigor bragaigor left a comment

Choose a reason for hiding this comment

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

overall looks good, just some minor comments

Comment thread cmd/nitro/init/init.go Outdated
Comment thread cmd/nitro/init/init.go Outdated
Comment thread cmd/nitro/init/init.go Outdated
bragaigor
bragaigor previously approved these changes Feb 17, 2026
Copy link
Copy Markdown
Contributor

@bragaigor bragaigor left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors the init message restoration logic by splitting the monolithic GetConsensusParsedInitMsg function into three separate, purpose-specific functions. This improves code clarity and maintainability by explicitly separating the three distinct paths for constructing init messages: from parent chain (consensus), from genesis file, or from stored chain config.

Changes:

  • Replaced GetConsensusParsedInitMsg with three focused functions: GetParsedInitMsgFromConsensus, GetParsedInitMsgFromGenesis, and GetParsedInitMsgFromChainConfig
  • Updated GetInit to return *core.Genesis instead of *params.ArbOSInit to support the new genesis-based init message construction
  • Updated all call sites across the codebase to use the appropriate new function based on context

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
cmd/nitro/init/init.go Core refactoring: splits GetConsensusParsedInitMsg into three separate functions and updates GetInit return signature to include genesis object
cmd/nitro/init/init_test.go Updates test helper to handle new GetInit return signature and extract ArbOSInit from genesis when available
system_tests/nitro_init_test.go Renames and expands test to cover both new non-consensus functions (GetParsedInitMsgFromGenesis and GetParsedInitMsgFromChainConfig) and removes unused chaininfo import
system_tests/genesis_assertion_test.go Updates call to use new GetParsedInitMsgFromConsensus function
system_tests/common_test.go Updates call to use new GetParsedInitMsgFromConsensus function
system_tests/bold_customda_challenge_test.go Updates call to use new GetParsedInitMsgFromConsensus function
system_tests/bold_challenge_protocol_test.go Updates call to use new GetParsedInitMsgFromConsensus function
changelog/pmikolajczyk-nit-4242.md Documents the new capability to restore init message from genesis
Comments suppressed due to low confidence (1)

cmd/nitro/init/init.go:1116

  • The previous implementation logged a warning when creating an init message without reading from the parent chain ("Created fake init message as L1Reader is disabled..."). This warning has been removed. Consider adding a log message here to maintain visibility when the init message is constructed from the chain config fallback path, especially since this case indicates that neither parent chain reader nor genesis file are available.
func GetParsedInitMsgFromChainConfig(chainConfig *params.ChainConfig) (*arbostypes.ParsedInitMessage, error) {
	serializedChainConfig, err := json.Marshal(chainConfig)
	if err != nil {
		return nil, err
	}

	parsedInitMessage := &arbostypes.ParsedInitMessage{
		ChainId:               chainConfig.ChainID,
		InitialL1BaseFee:      arbostypes.DefaultInitialL1BaseFee,
		ChainConfig:           chainConfig,
		SerializedChainConfig: serializedChainConfig,
	}
	return parsedInitMessage, nil
}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

@diegoximenes diegoximenes left a comment

Choose a reason for hiding this comment

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

In this PR a new GetExecutionParsedInitMsg func should be created, that only relies on local config, such as genesis.json, to build the parsed init message.
In this PR, both GetConsensusParsedInitMsg and GetExecutionParsedInitMsg should be called, and a warning generated if they don't match.
Tsahi said at some point that he wants to fail node startup if there is a mismatch.
At this point I think this is too aggressive, and logging a warning is enough.
Please, bring that topic to be discussed in a standup.

Change OpenInitializeExecutionDB signature to accept a consensusParsedInitMessage *arbostypes.ParsedInitMessage, that can be nil if config.Node.ParentChainReader.Enable is set to false.

Move this code block

nitro/cmd/nitro/init/init.go

Lines 1065 to 1069 in 0b4a8fa

if parsedInitMessage.ChainConfig != nil {
if err := parsedInitMessage.ChainConfig.CheckCompatible(chainConfig, chainConfig.ArbitrumChainParams.GenesisBlockNum, 0); err != nil {
return nil, fmt.Errorf("incompatible chain config read from init message in L1 inbox: %w", err)
}
}
out of GetConsensusParsedInitMsg, to be executed by OpenInitializeExecutionDB.
Maybe a func to abstract that code block can improve code readability.

In this other task https://linear.app/offchain-labs/issue/NIT-4201/consensus-calls-executionvalidate-to-check-parsedinitmessage, when only running an Execution node, only GetExecutionParsedInitMsg will be called.
This task describes how the Consensus node will provide its parsed init message later to Execution, so it can validate if there is a mismatch.

Makes sense?

Comment thread cmd/nitro/init/init.go Outdated
Comment thread cmd/nitro/init/init.go Outdated
Comment thread cmd/nitro/init/init.go
Comment thread cmd/nitro/init/init.go Outdated
Comment thread cmd/conf/init.go Outdated
Comment thread cmd/nitro/init/init.go Outdated
Comment thread cmd/nitro/init/init.go Outdated
Comment thread cmd/nitro/init/init_test.go Outdated
@diegoximenes diegoximenes assigned tsahee and unassigned diegoximenes Mar 13, 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.

5 participants