Commit 213f7627 authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

Add inspection commands, fix deployer bugs (#11964)

Adds `op-deployer inspection *` commands to expose the generated genesis and rollup configs via the CLI or Golang libraries. Also fixes a bug in deployment - I accidentally deleted the code that set the deployer nonce, so live chain deployments were reverting.
parent 5fe7df24
......@@ -4,6 +4,8 @@ import (
"fmt"
"os"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/inspect"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum-optimism/optimism/op-service/cliapp"
"github.com/urfave/cli/v2"
......@@ -27,6 +29,11 @@ func main() {
Flags: cliapp.ProtectFlags(deployer.ApplyFlags),
Action: deployer.ApplyCLI(),
},
{
Name: "inspect",
Usage: "inspects the state of a deployment",
Subcommands: inspect.Commands,
},
}
app.Writer = os.Stdout
app.ErrWriter = os.Stderr
......
......@@ -162,5 +162,11 @@ func ApplyPipeline(
return fmt.Errorf("error in pipeline stage: %w", err)
}
}
st.AppliedIntent = intent
if err := env.WriteState(st); err != nil {
return fmt.Errorf("failed to write state: %w", err)
}
return nil
}
package inspect
import (
"fmt"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/pipeline"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state"
"github.com/ethereum/go-ethereum/common"
"github.com/urfave/cli/v2"
)
const (
OutfileFlagName = "outfile"
)
var (
FlagOutfile = &cli.StringFlag{
Name: OutfileFlagName,
Usage: "output file. set to - to use stdout",
Value: "-",
}
)
var Flags = []cli.Flag{
deployer.WorkdirFlag,
FlagOutfile,
}
var Commands = []*cli.Command{
{
Name: "genesis",
Usage: "outputs the genesis for an L2 chain",
Args: true,
ArgsUsage: "<chain-id>",
Action: GenesisCLI,
Flags: Flags,
},
{
Name: "rollup",
Usage: "outputs the rollup config for an L2 chain",
Args: true,
ArgsUsage: "<chain-id>",
Action: RollupCLI,
Flags: Flags,
},
}
type cliConfig struct {
Workdir string
Outfile string
ChainID common.Hash
}
func readConfig(cliCtx *cli.Context) (cliConfig, error) {
var cfg cliConfig
outfile := cliCtx.String(OutfileFlagName)
if outfile == "" {
return cfg, fmt.Errorf("outfile flag is required")
}
workdir := cliCtx.String(deployer.WorkdirFlagName)
if workdir == "" {
return cfg, fmt.Errorf("workdir flag is required")
}
chainIDStr := cliCtx.Args().First()
if chainIDStr == "" {
return cfg, fmt.Errorf("chain-id argument is required")
}
chainID, err := chainIDStrToHash(chainIDStr)
if err != nil {
return cfg, fmt.Errorf("failed to parse chain ID: %w", err)
}
return cliConfig{
Workdir: cliCtx.String(deployer.WorkdirFlagName),
Outfile: cliCtx.String(OutfileFlagName),
ChainID: chainID,
}, nil
}
type inspectState struct {
GlobalState *state.State
ChainIntent *state.ChainIntent
ChainState *state.ChainState
}
func bootstrapState(cfg cliConfig) (*inspectState, error) {
env := &pipeline.Env{Workdir: cfg.Workdir}
globalState, err := env.ReadState()
if err != nil {
return nil, fmt.Errorf("failed to read intent: %w", err)
}
if globalState.AppliedIntent == nil {
return nil, fmt.Errorf("chain state is not applied - run op-deployer apply")
}
chainIntent, err := globalState.AppliedIntent.Chain(cfg.ChainID)
if err != nil {
return nil, fmt.Errorf("failed to get applied chain intent: %w", err)
}
chainState, err := globalState.Chain(cfg.ChainID)
if err != nil {
return nil, fmt.Errorf("failed to get chain ID %s: %w", cfg.ChainID.String(), err)
}
return &inspectState{
GlobalState: globalState,
ChainIntent: chainIntent,
ChainState: chainState,
}, nil
}
package inspect
import (
"fmt"
"math/big"
"strconv"
"strings"
"github.com/ethereum-optimism/optimism/op-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
"github.com/ethereum/go-ethereum/common"
"github.com/urfave/cli/v2"
)
func GenesisCLI(cliCtx *cli.Context) error {
cfg, err := readConfig(cliCtx)
if err != nil {
return err
}
st, err := bootstrapState(cfg)
if err != nil {
return err
}
genesis, err := st.ChainState.UnmarshalGenesis()
if err != nil {
return fmt.Errorf("failed to unmarshal genesis: %w", err)
}
if err := jsonutil.WriteJSON(genesis, ioutil.ToStdOutOrFileOrNoop(cfg.Outfile, 0o666)); err != nil {
return fmt.Errorf("failed to write genesis: %w", err)
}
return nil
}
func chainIDStrToHash(in string) (common.Hash, error) {
var chainIDBig *big.Int
if strings.HasPrefix(in, "0x") {
in = strings.TrimPrefix(in, "0x")
var ok bool
chainIDBig, ok = new(big.Int).SetString(in, 16)
if !ok {
return common.Hash{}, fmt.Errorf("failed to parse chain ID %s", in)
}
} else {
inUint, err := strconv.ParseUint(in, 10, 64)
if err != nil {
return common.Hash{}, fmt.Errorf("failed to parse chain ID %s: %w", in, err)
}
chainIDBig = new(big.Int).SetUint64(inUint)
}
return common.BigToHash(chainIDBig), nil
}
package inspect
import (
"fmt"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/pipeline"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
"github.com/ethereum/go-ethereum/common"
"github.com/urfave/cli/v2"
)
func RollupCLI(cliCtx *cli.Context) error {
cfg, err := readConfig(cliCtx)
if err != nil {
return err
}
env := &pipeline.Env{Workdir: cfg.Workdir}
globalState, err := env.ReadState()
if err != nil {
return fmt.Errorf("failed to read intent: %w", err)
}
rollupConfig, err := Rollup(globalState, cfg.ChainID)
if err != nil {
return fmt.Errorf("failed to generate rollup config: %w", err)
}
if err := jsonutil.WriteJSON(rollupConfig, ioutil.ToStdOutOrFileOrNoop(cfg.Outfile, 0o666)); err != nil {
return fmt.Errorf("failed to write rollup config: %w", err)
}
return nil
}
func Rollup(globalState *state.State, chainID common.Hash) (*rollup.Config, error) {
if globalState.AppliedIntent == nil {
return nil, fmt.Errorf("chain state is not applied - run op-deployer apply")
}
chainIntent, err := globalState.AppliedIntent.Chain(chainID)
if err != nil {
return nil, fmt.Errorf("failed to get applied chain intent: %w", err)
}
chainState, err := globalState.Chain(chainID)
if err != nil {
return nil, fmt.Errorf("failed to get chain ID %s: %w", chainID.String(), err)
}
l2Allocs, err := chainState.UnmarshalGenesis()
if err != nil {
return nil, fmt.Errorf("failed to unmarshal genesis: %w", err)
}
config, err := state.CombineDeployConfig(
globalState.AppliedIntent,
chainIntent,
globalState,
chainState,
)
if err != nil {
return nil, fmt.Errorf("failed to combine L2 init config: %w", err)
}
l2GenesisBuilt, err := genesis.BuildL2Genesis(&config, l2Allocs, chainState.StartBlock)
if err != nil {
return nil, fmt.Errorf("failed to build L2 genesis: %w", err)
}
l2GenesisBlock := l2GenesisBuilt.ToBlock()
rollupConfig, err := config.RollupConfig(
chainState.StartBlock,
l2GenesisBlock.Hash(),
l2GenesisBlock.Number().Uint64(),
)
if err != nil {
return nil, fmt.Errorf("failed to build rollup config: %w", err)
}
if err := rollupConfig.Check(); err != nil {
return nil, fmt.Errorf("generated rollup config does not pass validation: %w", err)
}
return rollupConfig, nil
}
......@@ -68,6 +68,12 @@ func CallScriptBroadcast(
return fmt.Errorf("failed to enable cheats: %w", err)
}
nonce, err := opts.Client.NonceAt(ctx, opts.Deployer, nil)
if err != nil {
return fmt.Errorf("failed to fetch nonce: %w", err)
}
h.SetNonce(opts.Deployer, nonce)
err = opts.Handler(h)
if err != nil {
return fmt.Errorf("failed to run handler: %w", err)
......
......@@ -40,7 +40,7 @@ func GenerateL2Genesis(ctx context.Context, env *Env, intent *state.Intent, st *
return fmt.Errorf("failed to get chain state: %w", err)
}
initCfg, err := state.CombineL2InitConfig(intent, thisIntent)
initCfg, err := state.CombineDeployConfig(intent, thisIntent, st, thisChainState)
if err != nil {
return fmt.Errorf("failed to combine L2 init config: %w", err)
}
......@@ -63,7 +63,7 @@ func GenerateL2Genesis(ctx context.Context, env *Env, intent *state.Intent, st *
L1StandardBridgeProxy: thisChainState.L1StandardBridgeProxyAddress,
L1ERC721BridgeProxy: thisChainState.L1ERC721BridgeProxyAddress,
},
L2Config: initCfg,
L2Config: initCfg.L2InitializationConfig,
})
if err != nil {
return fmt.Errorf("failed to call L2Genesis script: %w", err)
......@@ -93,6 +93,11 @@ func GenerateL2Genesis(ctx context.Context, env *Env, intent *state.Intent, st *
return fmt.Errorf("failed to close gzip writer: %w", err)
}
thisChainState.Genesis = buf.Bytes()
startHeader, err := env.L1Client.HeaderByNumber(ctx, nil)
if err != nil {
return fmt.Errorf("failed to get start block: %w", err)
}
thisChainState.StartBlock = startHeader
if err := env.WriteState(st); err != nil {
return fmt.Errorf("failed to write state: %w", err)
......
package state
import (
"encoding/json"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum/go-ethereum/common/hexutil"
)
var (
l2GenesisBlockBaseFeePerGas = hexutil.Big(*(big.NewInt(1000000000)))
vaultMinWithdrawalAmount = mustHexBigFromHex("0x8ac7230489e80000")
)
func DefaultDeployConfig() genesis.DeployConfig {
return genesis.DeployConfig{
L2InitializationConfig: genesis.L2InitializationConfig{
L2GenesisBlockDeployConfig: genesis.L2GenesisBlockDeployConfig{
L2GenesisBlockGasLimit: 30_000_000,
L2GenesisBlockBaseFeePerGas: &l2GenesisBlockBaseFeePerGas,
},
L2VaultsDeployConfig: genesis.L2VaultsDeployConfig{
BaseFeeVaultWithdrawalNetwork: "local",
L1FeeVaultWithdrawalNetwork: "local",
SequencerFeeVaultWithdrawalNetwork: "local",
SequencerFeeVaultMinimumWithdrawalAmount: vaultMinWithdrawalAmount,
BaseFeeVaultMinimumWithdrawalAmount: vaultMinWithdrawalAmount,
L1FeeVaultMinimumWithdrawalAmount: vaultMinWithdrawalAmount,
},
GovernanceDeployConfig: genesis.GovernanceDeployConfig{
EnableGovernance: true,
GovernanceTokenSymbol: "OP",
GovernanceTokenName: "Optimism",
},
GasPriceOracleDeployConfig: genesis.GasPriceOracleDeployConfig{
GasPriceOracleBaseFeeScalar: 1368,
GasPriceOracleBlobBaseFeeScalar: 810949,
},
EIP1559DeployConfig: genesis.EIP1559DeployConfig{
EIP1559Denominator: 50,
EIP1559DenominatorCanyon: 250,
EIP1559Elasticity: 6,
},
UpgradeScheduleDeployConfig: genesis.UpgradeScheduleDeployConfig{
L2GenesisRegolithTimeOffset: u64UtilPtr(0),
L2GenesisCanyonTimeOffset: u64UtilPtr(0),
L2GenesisDeltaTimeOffset: u64UtilPtr(0),
L2GenesisEcotoneTimeOffset: u64UtilPtr(0),
L2GenesisFjordTimeOffset: u64UtilPtr(0),
L2GenesisGraniteTimeOffset: u64UtilPtr(0),
UseInterop: false,
},
L2CoreDeployConfig: genesis.L2CoreDeployConfig{
L2BlockTime: 2,
FinalizationPeriodSeconds: 12,
MaxSequencerDrift: 600,
SequencerWindowSize: 3600,
ChannelTimeoutBedrock: 300,
SystemConfigStartBlock: 0,
},
},
}
}
func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State, chainState *ChainState) (genesis.DeployConfig, error) {
cfg := DefaultDeployConfig()
var err error
if len(intent.GlobalDeployOverrides) > 0 {
cfg, err = mergeJSON(cfg, intent.GlobalDeployOverrides)
if err != nil {
return genesis.DeployConfig{}, fmt.Errorf("error merging global L2 overrides: %w", err)
}
}
if len(chainIntent.DeployOverrides) > 0 {
cfg, err = mergeJSON(cfg, chainIntent.DeployOverrides)
if err != nil {
return genesis.DeployConfig{}, fmt.Errorf("error merging chain L2 overrides: %w", err)
}
}
cfg.L2ChainID = chainState.ID.Big().Uint64()
cfg.L1DependenciesConfig = genesis.L1DependenciesConfig{
L1StandardBridgeProxy: chainState.L1StandardBridgeProxyAddress,
L1CrossDomainMessengerProxy: chainState.L1CrossDomainMessengerProxyAddress,
L1ERC721BridgeProxy: chainState.L1ERC721BridgeProxyAddress,
SystemConfigProxy: chainState.SystemConfigProxyAddress,
OptimismPortalProxy: chainState.OptimismPortalProxyAddress,
ProtocolVersionsProxy: state.SuperchainDeployment.ProtocolVersionsProxyAddress,
}
cfg.OperatorDeployConfig = genesis.OperatorDeployConfig{
BatchSenderAddress: chainIntent.Roles.Batcher,
P2PSequencerAddress: chainIntent.Roles.UnsafeBlockSigner,
}
cfg.BatchInboxAddress = calculateBatchInboxAddr(chainState.ID)
cfg.L1ChainID = intent.L1ChainID
return cfg, nil
}
// mergeJSON merges the provided overrides into the input struct. Fields
// must be JSON-serializable for this to work. Overrides are applied in
// order of precedence - i.e., the last overrides will override keys from
// all preceding overrides.
func mergeJSON[T any](in T, overrides ...map[string]any) (T, error) {
var out T
inJSON, err := json.Marshal(in)
if err != nil {
return out, err
}
var tmpMap map[string]interface{}
if err := json.Unmarshal(inJSON, &tmpMap); err != nil {
return out, err
}
for _, override := range overrides {
for k, v := range override {
tmpMap[k] = v
}
}
inJSON, err = json.Marshal(tmpMap)
if err != nil {
return out, err
}
if err := json.Unmarshal(inJSON, &out); err != nil {
return out, err
}
return out, nil
}
func mustHexBigFromHex(hex string) *hexutil.Big {
num := hexutil.MustDecodeBig(hex)
hexBig := hexutil.Big(*num)
return &hexBig
}
func u64UtilPtr(in uint64) *hexutil.Uint64 {
util := hexutil.Uint64(in)
return &util
}
func calculateBatchInboxAddr(chainID common.Hash) common.Address {
var out common.Address
copy(out[1:], crypto.Keccak256(chainID[:])[:19])
return out
}
package state
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestMergeJSON(t *testing.T) {
type testStruct struct {
A string `json:"a"`
B int `json:"b"`
C bool `json:"c"`
}
out, err := mergeJSON(
testStruct{
"hello",
42,
true,
},
map[string]any{
"a": "world",
"c": false,
},
map[string]any{
"d": "shouldn't show up",
},
)
require.NoError(t, err)
require.EqualValues(t, out, testStruct{
"world",
42,
false,
})
}
......@@ -26,7 +26,7 @@ type Intent struct {
Chains []*ChainIntent `json:"chains" toml:"chains"`
GlobalInitOverrides map[string]any `json:"globalInitOverrides" toml:"globalInitOverrides"`
GlobalDeployOverrides map[string]any `json:"globalDeployOverrides" toml:"globalDeployOverrides"`
}
func (c *Intent) L1ChainIDBig() *big.Int {
......@@ -92,7 +92,7 @@ type ChainIntent struct {
Roles ChainRoles `json:"roles" toml:"roles"`
InitOverrides map[string]any `json:"initOverrides" toml:"initOverrides"`
DeployOverrides map[string]any `json:"deployOverrides" toml:"deployOverrides"`
}
type ChainRoles struct {
......
package state
import (
"encoding/json"
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum/go-ethereum/common/hexutil"
)
var (
l2GenesisBlockBaseFeePerGas = hexutil.Big(*(big.NewInt(1000000000)))
vaultMinWithdrawalAmount = mustHexBigFromHex("0x8ac7230489e80000")
)
func DefaultL2InitConfig() genesis.L2InitializationConfig {
return genesis.L2InitializationConfig{
L2GenesisBlockDeployConfig: genesis.L2GenesisBlockDeployConfig{
L2GenesisBlockGasLimit: 30_000_000,
L2GenesisBlockBaseFeePerGas: &l2GenesisBlockBaseFeePerGas,
},
L2VaultsDeployConfig: genesis.L2VaultsDeployConfig{
BaseFeeVaultWithdrawalNetwork: "local",
L1FeeVaultWithdrawalNetwork: "local",
SequencerFeeVaultWithdrawalNetwork: "local",
SequencerFeeVaultMinimumWithdrawalAmount: vaultMinWithdrawalAmount,
BaseFeeVaultMinimumWithdrawalAmount: vaultMinWithdrawalAmount,
L1FeeVaultMinimumWithdrawalAmount: vaultMinWithdrawalAmount,
},
GovernanceDeployConfig: genesis.GovernanceDeployConfig{
EnableGovernance: true,
GovernanceTokenSymbol: "OP",
GovernanceTokenName: "Optimism",
},
GasPriceOracleDeployConfig: genesis.GasPriceOracleDeployConfig{
GasPriceOracleBaseFeeScalar: 0,
GasPriceOracleBlobBaseFeeScalar: 1000000,
},
EIP1559DeployConfig: genesis.EIP1559DeployConfig{
EIP1559Denominator: 50,
EIP1559DenominatorCanyon: 250,
EIP1559Elasticity: 6,
},
UpgradeScheduleDeployConfig: genesis.UpgradeScheduleDeployConfig{
L2GenesisRegolithTimeOffset: u64UtilPtr(0),
L2GenesisCanyonTimeOffset: u64UtilPtr(0),
L2GenesisDeltaTimeOffset: u64UtilPtr(0),
L2GenesisEcotoneTimeOffset: u64UtilPtr(0),
L2GenesisFjordTimeOffset: u64UtilPtr(0),
L2GenesisGraniteTimeOffset: u64UtilPtr(0),
UseInterop: false,
},
L2CoreDeployConfig: genesis.L2CoreDeployConfig{
L2BlockTime: 2,
FinalizationPeriodSeconds: 12,
MaxSequencerDrift: 600,
SequencerWindowSize: 3600,
ChannelTimeoutBedrock: 300,
SystemConfigStartBlock: 0,
},
}
}
func CombineL2InitConfig(intent *Intent, chainIntent *ChainIntent) (genesis.L2InitializationConfig, error) {
cfg := DefaultL2InitConfig()
var err error
if len(intent.GlobalInitOverrides) > 0 {
cfg, err = mergeJSON(cfg, intent.GlobalInitOverrides)
if err != nil {
return genesis.L2InitializationConfig{}, fmt.Errorf("error merging global L2 overrides: %w", err)
}
}
if len(chainIntent.InitOverrides) > 0 {
cfg, err = mergeJSON(cfg, chainIntent.InitOverrides)
if err != nil {
return genesis.L2InitializationConfig{}, fmt.Errorf("error merging chain L2 overrides: %w", err)
}
}
return cfg, nil
}
func mergeJSON[T any](in T, overrides ...map[string]any) (T, error) {
var out T
inJSON, err := json.Marshal(in)
if err != nil {
return out, err
}
var tmpMap map[string]interface{}
if err := json.Unmarshal(inJSON, &tmpMap); err != nil {
return out, err
}
for _, override := range overrides {
for k, v := range override {
tmpMap[k] = v
}
}
inJSON, err = json.Marshal(tmpMap)
if err != nil {
return out, err
}
if err := json.Unmarshal(inJSON, &out); err != nil {
return out, err
}
return out, nil
}
func mustHexBigFromHex(hex string) *hexutil.Big {
num := hexutil.MustDecodeBig(hex)
hexBig := hexutil.Big(*num)
return &hexBig
}
func u64UtilPtr(in uint64) *hexutil.Uint64 {
util := hexutil.Uint64(in)
return &util
}
package state
import (
"bytes"
"compress/gzip"
"encoding/json"
"fmt"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum-optimism/optimism/op-chain-ops/foundry"
"github.com/ethereum-optimism/optimism/op-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
......@@ -94,4 +99,21 @@ type ChainState struct {
DelayedWETHPermissionlessGameProxyAddress common.Address `json:"delayedWETHPermissionlessGameProxyAddress"`
Genesis Base64Bytes `json:"genesis"`
StartBlock *types.Header `json:"startBlock"`
}
func (c *ChainState) UnmarshalGenesis() (*foundry.ForgeAllocs, error) {
gr, err := gzip.NewReader(bytes.NewReader(c.Genesis))
if err != nil {
return nil, fmt.Errorf("failed to create gzip reader: %w", err)
}
defer gr.Close()
var allocs foundry.ForgeAllocs
if err := json.NewDecoder(gr).Decode(&allocs); err != nil {
return nil, fmt.Errorf("failed to decode genesis: %w", err)
}
return &allocs, nil
}
......@@ -82,6 +82,10 @@ func (d *ForgeAllocs) Copy() *ForgeAllocs {
return &ForgeAllocs{Accounts: out}
}
func (d ForgeAllocs) MarshalJSON() ([]byte, error) {
return json.Marshal(d.Accounts)
}
func (d *ForgeAllocs) UnmarshalJSON(b []byte) error {
// forge, since integrating Alloy, likes to hex-encode everything.
type forgeAllocAccount struct {
......
package foundry
import (
"encoding/json"
"math/big"
"os"
"testing"
......@@ -96,3 +98,24 @@ func TestForgeAllocs_FromState(t *testing.T) {
require.Equal(t, "0", allocs.Accounts[contract].Balance.String())
require.Equal(t, uint64(30), allocs.Accounts[contract].Nonce)
}
func TestForgeAllocs_Marshaling(t *testing.T) {
data := &ForgeAllocs{
Accounts: map[common.Address]types.Account{
common.HexToAddress("0x12345"): {
Balance: big.NewInt(12345),
Code: []byte{0x01, 0x02, 0x03},
Nonce: 123,
Storage: map[common.Hash]common.Hash{
common.HexToHash("0x12345"): common.HexToHash("0x12345"),
},
},
},
}
out, err := json.Marshal(data)
require.NoError(t, err)
var in ForgeAllocs
require.NoError(t, json.Unmarshal(out, &in))
}
......@@ -732,6 +732,8 @@ type L1DependenciesConfig struct {
// DAChallengeProxy represents the L1 address of the DataAvailabilityChallenge contract.
DAChallengeProxy common.Address `json:"daChallengeProxy"`
ProtocolVersionsProxy common.Address `json:"protocolVersionsProxy"`
}
// DependencyContext is the contextual configuration needed to verify the L1 dependencies,
......@@ -877,7 +879,7 @@ func (d *DeployConfig) SetDeployments(deployments *L1Deployments) {
// RollupConfig converts a DeployConfig to a rollup.Config. If Ecotone is active at genesis, the
// Overhead value is considered a noop.
func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHash common.Hash, l2GenesisBlockNumber uint64) (*rollup.Config, error) {
func (d *DeployConfig) RollupConfig(l1StartBlock *types.Header, l2GenesisBlockHash common.Hash, l2GenesisBlockNumber uint64) (*rollup.Config, error) {
if d.OptimismPortalProxy == (common.Address{}) {
return nil, errors.New("OptimismPortalProxy cannot be address(0)")
}
......@@ -894,17 +896,19 @@ func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHas
}
}
l1StartTime := l1StartBlock.Time
return &rollup.Config{
Genesis: rollup.Genesis{
L1: eth.BlockID{
Hash: l1StartBlock.Hash(),
Number: l1StartBlock.NumberU64(),
Number: l1StartBlock.Number.Uint64(),
},
L2: eth.BlockID{
Hash: l2GenesisBlockHash,
Number: l2GenesisBlockNumber,
},
L2Time: l1StartBlock.Time(),
L2Time: l1StartBlock.Time,
SystemConfig: eth.SystemConfig{
BatcherAddr: d.BatchSenderAddress,
Overhead: eth.Bytes32(common.BigToHash(new(big.Int).SetUint64(d.GasPriceOracleOverhead))),
......@@ -921,13 +925,14 @@ func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHas
BatchInboxAddress: d.BatchInboxAddress,
DepositContractAddress: d.OptimismPortalProxy,
L1SystemConfigAddress: d.SystemConfigProxy,
RegolithTime: d.RegolithTime(l1StartBlock.Time()),
CanyonTime: d.CanyonTime(l1StartBlock.Time()),
DeltaTime: d.DeltaTime(l1StartBlock.Time()),
EcotoneTime: d.EcotoneTime(l1StartBlock.Time()),
FjordTime: d.FjordTime(l1StartBlock.Time()),
GraniteTime: d.GraniteTime(l1StartBlock.Time()),
InteropTime: d.InteropTime(l1StartBlock.Time()),
RegolithTime: d.RegolithTime(l1StartTime),
CanyonTime: d.CanyonTime(l1StartTime),
DeltaTime: d.DeltaTime(l1StartTime),
EcotoneTime: d.EcotoneTime(l1StartTime),
FjordTime: d.FjordTime(l1StartTime),
GraniteTime: d.GraniteTime(l1StartTime),
InteropTime: d.InteropTime(l1StartTime),
ProtocolVersionsAddress: d.ProtocolVersionsProxy,
AltDAConfig: altDA,
}, nil
}
......
......@@ -22,7 +22,7 @@ const defaultGasLimit = 30_000_000
var BedrockTransitionBlockExtraData = []byte("BEDROCK")
// NewL2Genesis will create a new L2 genesis
func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, error) {
func NewL2Genesis(config *DeployConfig, l1StartHeader *types.Header) (*core.Genesis, error) {
if config.L2ChainID == 0 {
return nil, errors.New("must define L2 ChainID")
}
......@@ -40,6 +40,8 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro
eip1559Elasticity = 10
}
l1StartTime := l1StartHeader.Time
optimismChainConfig := params.ChainConfig{
ChainID: new(big.Int).SetUint64(config.L2ChainID),
HomesteadBlock: big.NewInt(0),
......@@ -61,14 +63,14 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro
TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true,
BedrockBlock: new(big.Int).SetUint64(uint64(config.L2GenesisBlockNumber)),
RegolithTime: config.RegolithTime(block.Time()),
CanyonTime: config.CanyonTime(block.Time()),
ShanghaiTime: config.CanyonTime(block.Time()),
CancunTime: config.EcotoneTime(block.Time()),
EcotoneTime: config.EcotoneTime(block.Time()),
FjordTime: config.FjordTime(block.Time()),
GraniteTime: config.GraniteTime(block.Time()),
InteropTime: config.InteropTime(block.Time()),
RegolithTime: config.RegolithTime(l1StartTime),
CanyonTime: config.CanyonTime(l1StartTime),
ShanghaiTime: config.CanyonTime(l1StartTime),
CancunTime: config.EcotoneTime(l1StartTime),
EcotoneTime: config.EcotoneTime(l1StartTime),
FjordTime: config.FjordTime(l1StartTime),
GraniteTime: config.GraniteTime(l1StartTime),
InteropTime: config.InteropTime(l1StartTime),
Optimism: &params.OptimismConfig{
EIP1559Denominator: eip1559Denom,
EIP1559Elasticity: eip1559Elasticity,
......@@ -102,7 +104,7 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro
genesis := &core.Genesis{
Config: &optimismChainConfig,
Nonce: uint64(config.L2GenesisBlockNonce),
Timestamp: block.Time(),
Timestamp: l1StartTime,
ExtraData: extraData,
GasLimit: uint64(gasLimit),
Difficulty: difficulty.ToInt(),
......
......@@ -36,7 +36,7 @@ var (
type AllocsLoader func(mode L2AllocsMode) *foundry.ForgeAllocs
// BuildL2Genesis will build the L2 genesis block.
func BuildL2Genesis(config *DeployConfig, dump *foundry.ForgeAllocs, l1StartBlock *types.Block) (*core.Genesis, error) {
func BuildL2Genesis(config *DeployConfig, dump *foundry.ForgeAllocs, l1StartBlock *types.Header) (*core.Genesis, error) {
genspec, err := NewL2Genesis(config, l1StartBlock)
if err != nil {
return nil, err
......
......@@ -55,6 +55,7 @@
"systemConfigProxy": "0x4200000000000000000000000000000000000061",
"optimismPortalProxy": "0x4200000000000000000000000000000000000062",
"proxyAdminOwner": "0x0000000000000000000000000000000000000222",
"protocolVersionsProxy": "0x0000000000000000000000000000000000000000",
"gasPriceOracleBaseFeeScalar": 0,
"gasPriceOracleBlobBaseFeeScalar": 0,
"gasPriceOracleOverhead": 2100,
......
......@@ -289,7 +289,7 @@ func completeL2(l2Host *script.Host, cfg *L2Config, l1Block *types.Block, deploy
},
}
// l1Block is used to determine genesis time.
l2Genesis, err := genesis.NewL2Genesis(deployCfg, l1Block)
l2Genesis, err := genesis.NewL2Genesis(deployCfg, l1Block.Header())
if err != nil {
return nil, fmt.Errorf("failed to build L2 genesis config: %w", err)
}
......@@ -314,7 +314,7 @@ func completeL2(l2Host *script.Host, cfg *L2Config, l1Block *types.Block, deploy
l2Genesis.Alloc = allocs.Accounts
l2GenesisBlock := l2Genesis.ToBlock()
rollupCfg, err := deployCfg.RollupConfig(l1Block, l2GenesisBlock.Hash(), l2GenesisBlock.NumberU64())
rollupCfg, err := deployCfg.RollupConfig(l1Block.Header(), l2GenesisBlock.Hash(), l2GenesisBlock.NumberU64())
if err != nil {
return nil, fmt.Errorf("failed to build L2 rollup config: %w", err)
}
......
......@@ -134,7 +134,7 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) *
allocsMode = genesis.L2AllocsEcotone
}
l2Allocs := config.L2Allocs(allocsMode)
l2Genesis, err := genesis.BuildL2Genesis(deployConf, l2Allocs, l1Block)
l2Genesis, err := genesis.BuildL2Genesis(deployConf, l2Allocs, l1Block.Header())
require.NoError(t, err, "failed to create l2 genesis")
if alloc.PrefundTestUsers {
for _, addr := range deployParams.Addresses.All() {
......
......@@ -70,7 +70,7 @@ func NewOpGeth(t testing.TB, ctx context.Context, cfg *e2esys.SystemConfig) (*Op
allocsMode = genesis.L2AllocsEcotone
}
l2Allocs := config.L2Allocs(allocsMode)
l2Genesis, err := genesis.BuildL2Genesis(cfg.DeployConfig, l2Allocs, l1Block)
l2Genesis, err := genesis.BuildL2Genesis(cfg.DeployConfig, l2Allocs, l1Block.Header())
require.NoError(t, err)
l2GenesisBlock := l2Genesis.ToBlock()
......@@ -108,7 +108,7 @@ func NewOpGeth(t testing.TB, ctx context.Context, cfg *e2esys.SystemConfig) (*Op
require.NoError(t, err)
// Finally create the engine client
rollupCfg, err := cfg.DeployConfig.RollupConfig(l1Block, l2GenesisBlock.Hash(), l2GenesisBlock.NumberU64())
rollupCfg, err := cfg.DeployConfig.RollupConfig(l1Block.Header(), l2GenesisBlock.Hash(), l2GenesisBlock.NumberU64())
require.NoError(t, err)
rollupCfg.Genesis = rollupGenesis
l2Engine, err := sources.NewEngineClient(
......
......@@ -519,7 +519,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
t.Log("Generating L2 genesis", "l2_allocs_mode", string(allocsMode))
l2Allocs := config.L2Allocs(allocsMode)
l2Genesis, err := genesis.BuildL2Genesis(cfg.DeployConfig, l2Allocs, l1Block)
l2Genesis, err := genesis.BuildL2Genesis(cfg.DeployConfig, l2Allocs, l1Block.Header())
if err != nil {
return nil, err
}
......
......@@ -191,13 +191,13 @@ var Subcommands = cli.Commands{
}
// Build the L2 genesis block
l2Genesis, err := genesis.BuildL2Genesis(config, l2Allocs, l1StartBlock)
l2Genesis, err := genesis.BuildL2Genesis(config, l2Allocs, l1StartBlock.Header())
if err != nil {
return fmt.Errorf("error creating l2 genesis: %w", err)
}
l2GenesisBlock := l2Genesis.ToBlock()
rollupConfig, err := config.RollupConfig(l1StartBlock, l2GenesisBlock.Hash(), l2GenesisBlock.Number().Uint64())
rollupConfig, err := config.RollupConfig(l1StartBlock.Header(), l2GenesisBlock.Hash(), l2GenesisBlock.Number().Uint64())
if err != nil {
return err
}
......
......@@ -312,7 +312,7 @@ func setupOracle(t *testing.T, blockCount int, headBlockNumber int, enableEcoton
}
l1Genesis, err := genesis.NewL1Genesis(deployConfig)
require.NoError(t, err)
l2Genesis, err := genesis.NewL2Genesis(deployConfig, l1Genesis.ToBlock())
l2Genesis, err := genesis.NewL2Genesis(deployConfig, l1Genesis.ToBlock().Header())
require.NoError(t, err)
l2Genesis.Alloc[fundedAddress] = types.Account{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment