Skip to content

Conversation

@pmikolajczyk41
Copy link
Member

@pmikolajczyk41 pmikolajczyk41 commented Dec 23, 2025

  1. Extend InitConfig with InitialL1BaseFee field. Since the fee might exceed 1<<64, the field type is string and we have a getter InitialL1BaseFeeParsed that returns:
  • DefaultInitialL1BaseFee when the string is empty or it cannot be parsed in decimal system
  • parsed value (in decimal system)
  1. Extend InitConfig with SerializedChainConfig field.
  2. In the cmd/nitro/init.go resolve† the new parameters from either CLI flag or genesis configuration. Ensure they match what was in the parsed init message on the parent chain.

† config resolution:

  • in case genesis.json is absent, use the --chain.initial-l1base-fee flag value
  • in case genesis.json is present and --chain.initial-l1base-fee is not empty, ensure the values match
  • use genesis.json

Similar logic is applied to the serialized chain configuration resolution. Both resolutions are covered with tests.


closes NIT-4242, NIT-4264
pulls in OffchainLabs/go-ethereum#603

@codecov
Copy link

codecov bot commented Dec 23, 2025

Codecov Report

❌ Patch coverage is 72.09302% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.93%. Comparing base (416e512) to head (255893c).
⚠️ Report is 4 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff             @@
##           master    #4171       +/-   ##
===========================================
+ Coverage   33.01%   56.93%   +23.92%     
===========================================
  Files         459      461        +2     
  Lines       55830    55942      +112     
===========================================
+ Hits        18430    31850    +13420     
+ Misses      34185    19260    -14925     
- Partials     3215     4832     +1617     

@github-actions
Copy link

github-actions bot commented Dec 23, 2025

❌ 4 Tests Failed:

Tests completed Failed Passed Skipped
4471 4 4467 0
View the top 3 failed tests by shortest run time
TestOutOfGasInStorageCacheFlush
Stack Traces | 2.950s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
�[90mposted new batch 35�[0;0m
�[90mposted new batch 35�[0;0m
    program_test.go:2834: goroutine 848885 [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({0x4101310, 0xc024fb9500}, {0x40bdfa0, 0xc0b93940e0}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/util/testhelpers/testhelpers.go:29 +0x55
        github.com/offchainlabs/nitro/system_tests.Require(0xc024fb9500, {0x40bdfa0, 0xc0b93940e0}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/system_tests/common_test.go:2034 +0x5d
        github.com/offchainlabs/nitro/system_tests.TestOutOfGasInStorageCacheFlush(0xc024fb9500)
        	/home/runner/work/nitro/nitro/system_tests/program_test.go:2834 +0x1006
        testing.tRunner(0xc024fb9500, 0x3d3f738)
        	/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
        
    program_test.go:2834: �[31;1m [] failed calculating position for validation: batch not found on L1 yet �[0;0m
INFO [01-06|14:48:57.898] HTTP server stopped                      endpoint=127.0.0.1:43565
TRACE[01-06|14:48:57.898] P2P networking is spinning down
--- FAIL: TestOutOfGasInStorageCacheFlush (2.95s)
TestVersion30
Stack Traces | 10.830s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
�[90mEmitting 3 topics�[0;0m
�[90mEmitting 4 topics�[0;0m
    precompile_inclusion_test.go:94: goroutine 611888 [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({0x4101310, 0xc0723bd6c0}, {0x40be420, 0xc0a12c8fc0}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/util/testhelpers/testhelpers.go:29 +0x55
        github.com/offchainlabs/nitro/system_tests.Require(0xc0723bd6c0, {0x40be420, 0xc0a12c8fc0}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/system_tests/common_test.go:2034 +0x5d
        github.com/offchainlabs/nitro/system_tests.testPrecompiles(0xc0723bd6c0, 0x1e, {0xc0d4cbfdb0, 0x6, 0x0?})
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:94 +0x371
        github.com/offchainlabs/nitro/system_tests.TestVersion30(0xc0723bd6c0?)
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:67 +0x798
        testing.tRunner(0xc0723bd6c0, 0x3d3fc20)
        	/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 (10.83s)
TestVersion40
Stack Traces | 11.550s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
=== PAUSE TestVersion40
=== CONT  TestVersion40
    precompile_inclusion_test.go:94: goroutine 611889 [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({0x4101310, 0xc0723bd880}, {0x40be420, 0xc1b48684e0}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/util/testhelpers/testhelpers.go:29 +0x55
        github.com/offchainlabs/nitro/system_tests.Require(0xc0723bd880, {0x40be420, 0xc1b48684e0}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/system_tests/common_test.go:2034 +0x5d
        github.com/offchainlabs/nitro/system_tests.testPrecompiles(0xc0723bd880, 0x28, {0xc096df1df8, 0x5, 0x39?})
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:94 +0x371
        github.com/offchainlabs/nitro/system_tests.TestVersion40(0xc0723bd880?)
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:71 +0x64b
        testing.tRunner(0xc0723bd880, 0x3d3fc28)
        	/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 (11.55s)

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

bragaigor
bragaigor previously approved these changes Dec 24, 2025
@bragaigor
Copy link
Contributor

LGTM

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

As you mentioned in a meeting, since there are multiple valid ways to serialize chain config, in order to Execution build parsedInitMessage only through its local config, users will also need to have a way to provide the serialized chain config.
This can be done in this PR, a new PR, or even a new linear task can be created for that, up to you to decide the best path to move forward 🙂

@diegoximenes diegoximenes assigned tsahee and unassigned diegoximenes Dec 31, 2025
return fmt.Errorf("invalid value of rebuild-local-wasm, want: auto or force or false, got: %s", c.RebuildLocalWasm)
}
if _, success := big.NewInt(0).SetString(c.InitialL1BaseFee, 10); !success {
return fmt.Errorf("failed to parse L1 BaseFee for L2 config: `%s`", c.InitialL1BaseFee)
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: change error message to not use "L2 config", and use something related to init instead.


parsed, success := big.NewInt(0).SetString(c.InitialL1BaseFee, 10)
if !success {
return nil, fmt.Errorf("failed to parse L1 BaseFee for L2 config: `%s` (passed with `initial-l1base-fee` flag)", c.InitialL1BaseFee)
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: change error message to not use "L2 config", and use something related to init instead.

return executionDB, nil, fmt.Errorf("incompatible chain config read from init message in L1 inbox: %w", err)
}
}
if configuredInitialL1BaseFee.Cmp(parsedInitMessage.InitialL1BaseFee) != 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

In the same way we can also compare the provided serialized chain config with the parsedInitMessage's serialized chain config.

return executionDB, nil, fmt.Errorf("incompatible chain config read from init message in L1 inbox: %w", err)
}
}
if configuredInitialL1BaseFee.Cmp(parsedInitMessage.InitialL1BaseFee) != 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

How about also creating a function, such as getExecutionParsedInitMessage, similar to the GetConsensusParsedInitMessage that Igor is proposing here?

log.Info("Read serialized chain config from init message", "json", string(parsedInitMessage.SerializedChainConfig))
} else {
serializedChainConfig, err := json.Marshal(chainConfig)
serializedChainConfig, err := resolveSerializedChainConfig(genesisArbOSInit, &config.Init, chainConfig)
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not where this resolveSerializedChainConfig call should be.
This else represents a use case in which a L2 node doesn't have connection with the parent chain.
Think of it as a child chain that doesn't settle data in the parent chain.
I am not sure if anyone is relying on this use case today.

The returns of resolveSerializedChainConfig and resolveInitialL1BaseFee should be used to build a ParsedInitMessage object (parsedInitMessage built only through local configs, and only to be used by Execution).
In this PR, if the user provided enough info to build this ParsedInitMessage object, it should be compared with the parsedInitMessage returned from initMessage.ParseInitMessage (parsedInitMessage read from the parent chain, and only to be retrieved by Consensus).

This affects where to place resolveSerializedChainConfig and resolveInitialL1BaseFee calls, parsedInitMessage comparison, and this PR overall design.

Maybe checking Igor's PR will be simpler to understand what openInitializaExecutionDB does.

Makes sense?

return rebuildLocalWasm(ctx, &config.Execution, l2BlockChain, executionDB, wasmDB, config.Init.RebuildLocalWasm)
}

func resolveInitialL1BaseFee(genesisArbOSInit *params.ArbOSInit, initConfig *conf.InitConfig) (*big.Int, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This func will be easier to read if you follow a similar approach that you followed in resolveSerializedChainConfig.
You don't assign a default value to feeCLIFlag and feeGenesisJSON, and only compare them if both are provided.
You only look for a default value if both are not provided.
WDYT?

if !tc.shouldErr && err != nil {
Fail(t, "unexpected error:", err)
}
if !reflect.DeepEqual(resolvedConfig, tc.expected) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: Here bytes.Equal can be used instead of DeepEqual.

Comment on lines +356 to +357
chainConfigSerialized1 := []byte(`{"chainId":1}`)
chainConfigSerialized2 := []byte(`{"chainId":2}`)
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: renaming these to chainConfigGenesisJSON and chainConfigInitFlag can help with reading the code. WDYT?

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