ethereum-optimism / specs

OP Stack Specifications
https://specs.optimism.io
Creative Commons Zero v1.0 Universal
94 stars 88 forks source link

L2 Genesis Simplification (L2 MCP) #350

Closed tynes closed 1 month ago

tynes commented 2 months ago

Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Right now there is not a great way to do L2 contracts releases because there is network specific configuration in the L2 genesis allocs in the form of storage and bytecode (immutables). This makes it difficult to release an allocs.json artifact as a release of the L2 genesis, as well as ensuring that no malicious code has been set in the genesis state of a chain. Ideally there should be a single deterministic L2 genesis state per hardfork and all network specific config should be sourced from L1.

This project involves moving all of the network specific configuration in the L2 predeploys to be sourced from L1. We want a system similar to interop's setConfig as described here that sets the network specific values into storage via deposit transactions when the SystemConfig is initialized.

Examples of this network specific config:

Instead of reading these values from storage on L2, they could be exposed via getters on the L1Block contract and then read from a single source of truth. The L1 setConfig path would be able to issue deposit transactions that can modify these values. This would decouple the L2 genesis state from network specific config and simplify the process of spinning up a new chain because all chains can use the same allocs.json

tynes commented 2 months ago

This is very much related to https://github.com/ethereum-optimism/specs/issues/122#issuecomment-2308584680 and we may want to use a similar architecture for setting network specific config into L2. We don't want to expose setters that the chain operator can change, but we do want the initialize on the SystemConfig to trigger deposit transactions that set network specific values in the L1Block contract.

Each predeploy that has network specific configuration (for example, the L1CrossDomainMessenger.otherMessenger) should be updated to read the value from a call to the L1Block contract rather than read from storage.

When the SystemConfig is initialized the first time, it will trigger a bunch of deposit transactions (should be the first deposits that the network accepts, like "bootloader transactions") and these pass the network specific configuration into the L2. Then L2 genesis generation doesn't need to be aware of network specific config and all L2s can use the same genesis state, making a standardness check as easy as looking at a state root.

To solve this, we would want to go through all of the predeploy contracts and find network specific configuration and then add setters/getters to the L1Block contract for these values. They should be only be able to be set by the DEPOSITOR_ACCOUNT and we would do something like this to set it. See here for more examples of this flow, we already use it for interop today.

Some values like the FeeVault recipient/network should have setters in the SystemConfig. We don't need setters for the otherBridge/otherMessenger though as those should only be set on initialize

tynes commented 2 months ago

Working on a spec: https://github.com/ethereum-optimism/specs/pull/358