Commit a68e3ef4 authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

op-deployer: Support overriding proof parameters (#12732)

* op-deployer: Support overriding proof parameters

This PR adds support for overiding proofs params using the `GlobalDeployOverrides` and `DeployOverrides` fields. Previously, these values were hardcoded. To prevent a recursive import, I refactored the `standard.go` file into a standalone package.

Closes https://github.com/ethereum-optimism/optimism/issues/12711.

* import cycle

* add tests, ability to disable post-checks

* rename to dangerously

* op-deployer: Add support for deploying interop chains

* code review updates
parent 96ef7bb4
...@@ -5,6 +5,8 @@ import ( ...@@ -5,6 +5,8 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -173,7 +175,7 @@ func DeploySuperchainToL1(l1Host *script.Host, superCfg *SuperchainConfig) (*Sup ...@@ -173,7 +175,7 @@ func DeploySuperchainToL1(l1Host *script.Host, superCfg *SuperchainConfig) (*Sup
ProtocolVersionsProxy: superDeployment.ProtocolVersionsProxy, ProtocolVersionsProxy: superDeployment.ProtocolVersionsProxy,
OpcmProxyOwner: superDeployment.SuperchainProxyAdmin, OpcmProxyOwner: superDeployment.SuperchainProxyAdmin,
UseInterop: superCfg.Implementations.UseInterop, UseInterop: superCfg.Implementations.UseInterop,
StandardVersionsToml: opcm.StandardVersionsMainnetData, StandardVersionsToml: standard.VersionsMainnetData,
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to deploy Implementations contracts: %w", err) return nil, fmt.Errorf("failed to deploy Implementations contracts: %w", err)
......
...@@ -4,7 +4,7 @@ import ( ...@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
...@@ -79,7 +79,7 @@ func (r *InteropDevRecipe) Build(addrs devkeys.Addresses) (*WorldConfig, error) ...@@ -79,7 +79,7 @@ func (r *InteropDevRecipe) Build(addrs devkeys.Addresses) (*WorldConfig, error)
MipsVersion: big.NewInt(1), MipsVersion: big.NewInt(1),
}, },
UseInterop: true, UseInterop: true,
StandardVersionsToml: opcm.StandardVersionsMainnetData, StandardVersionsToml: standard.VersionsMainnetData,
}, },
SuperchainL1DeployConfig: genesis.SuperchainL1DeployConfig{ SuperchainL1DeployConfig: genesis.SuperchainL1DeployConfig{
RequiredProtocolVersion: params.OPStackSupport, RequiredProtocolVersion: params.OPStackSupport,
......
...@@ -2,12 +2,19 @@ package bootstrap ...@@ -2,12 +2,19 @@ package bootstrap
import ( import (
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-service/cliapp" "github.com/ethereum-optimism/optimism/op-service/cliapp"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
const ( const (
ArtifactsLocatorFlagName = "artifacts-locator" ArtifactsLocatorFlagName = "artifacts-locator"
WithdrawalDelaySecondsFlagName = "withdrawal-delay-seconds"
MinProposalSizeBytesFlagName = "min-proposal-size-bytes"
ChallengePeriodSecondsFlagName = "challenge-period-seconds"
ProofMaturityDelaySecondsFlagName = "proof-maturity-delay-seconds"
DisputeGameFinalityDelaySecondsFlagName = "dispute-game-finality-delay-seconds"
MIPSVersionFlagName = "mips-version"
) )
var ( var (
...@@ -16,12 +23,54 @@ var ( ...@@ -16,12 +23,54 @@ var (
Usage: "Locator for artifacts.", Usage: "Locator for artifacts.",
EnvVars: deployer.PrefixEnvVar("ARTIFACTS_LOCATOR"), EnvVars: deployer.PrefixEnvVar("ARTIFACTS_LOCATOR"),
} }
WithdrawalDelaySecondsFlag = &cli.Uint64Flag{
Name: WithdrawalDelaySecondsFlagName,
Usage: "Withdrawal delay in seconds.",
EnvVars: deployer.PrefixEnvVar("WITHDRAWAL_DELAY_SECONDS"),
Value: standard.WithdrawalDelaySeconds,
}
MinProposalSizeBytesFlag = &cli.Uint64Flag{
Name: MinProposalSizeBytesFlagName,
Usage: "Minimum proposal size in bytes.",
EnvVars: deployer.PrefixEnvVar("MIN_PROPOSAL_SIZE_BYTES"),
Value: standard.MinProposalSizeBytes,
}
ChallengePeriodSecondsFlag = &cli.Uint64Flag{
Name: ChallengePeriodSecondsFlagName,
Usage: "Challenge period in seconds.",
EnvVars: deployer.PrefixEnvVar("CHALLENGE_PERIOD_SECONDS"),
Value: standard.ChallengePeriodSeconds,
}
ProofMaturityDelaySecondsFlag = &cli.Uint64Flag{
Name: ProofMaturityDelaySecondsFlagName,
Usage: "Proof maturity delay in seconds.",
EnvVars: deployer.PrefixEnvVar("PROOF_MATURITY_DELAY_SECONDS"),
Value: standard.ProofMaturityDelaySeconds,
}
DisputeGameFinalityDelaySecondsFlag = &cli.Uint64Flag{
Name: DisputeGameFinalityDelaySecondsFlagName,
Usage: "Dispute game finality delay in seconds.",
EnvVars: deployer.PrefixEnvVar("DISPUTE_GAME_FINALITY_DELAY_SECONDS"),
Value: standard.DisputeGameFinalityDelaySeconds,
}
MIPSVersionFlag = &cli.Uint64Flag{
Name: MIPSVersionFlagName,
Usage: "MIPS version.",
EnvVars: deployer.PrefixEnvVar("MIPS_VERSION"),
Value: standard.MIPSVersion,
}
) )
var OPCMFlags = []cli.Flag{ var OPCMFlags = []cli.Flag{
deployer.L1RPCURLFlag, deployer.L1RPCURLFlag,
deployer.PrivateKeyFlag, deployer.PrivateKeyFlag,
ArtifactsLocatorFlag, ArtifactsLocatorFlag,
WithdrawalDelaySecondsFlag,
MinProposalSizeBytesFlag,
ChallengePeriodSecondsFlag,
ProofMaturityDelaySecondsFlag,
DisputeGameFinalityDelaySecondsFlag,
MIPSVersionFlag,
} }
var Commands = []*cli.Command{ var Commands = []*cli.Command{
......
...@@ -8,6 +8,8 @@ import ( ...@@ -8,6 +8,8 @@ import (
"math/big" "math/big"
"strings" "strings"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer"
...@@ -28,6 +30,8 @@ import ( ...@@ -28,6 +30,8 @@ import (
) )
type OPCMConfig struct { type OPCMConfig struct {
pipeline.SuperchainProofParams
L1RPCUrl string L1RPCUrl string
PrivateKey string PrivateKey string
Logger log.Logger Logger log.Logger
...@@ -59,6 +63,30 @@ func (c *OPCMConfig) Check() error { ...@@ -59,6 +63,30 @@ func (c *OPCMConfig) Check() error {
return fmt.Errorf("artifacts locator must be specified") return fmt.Errorf("artifacts locator must be specified")
} }
if c.WithdrawalDelaySeconds == 0 {
c.WithdrawalDelaySeconds = standard.WithdrawalDelaySeconds
}
if c.MinProposalSizeBytes == 0 {
c.MinProposalSizeBytes = standard.MinProposalSizeBytes
}
if c.ChallengePeriodSeconds == 0 {
c.ChallengePeriodSeconds = standard.ChallengePeriodSeconds
}
if c.ProofMaturityDelaySeconds == 0 {
c.ProofMaturityDelaySeconds = standard.ProofMaturityDelaySeconds
}
if c.DisputeGameFinalityDelaySeconds == 0 {
c.DisputeGameFinalityDelaySeconds = standard.DisputeGameFinalityDelaySeconds
}
if c.MIPSVersion == 0 {
c.MIPSVersion = standard.MIPSVersion
}
return nil return nil
} }
...@@ -82,6 +110,14 @@ func OPCMCLI(cliCtx *cli.Context) error { ...@@ -82,6 +110,14 @@ func OPCMCLI(cliCtx *cli.Context) error {
PrivateKey: privateKey, PrivateKey: privateKey,
Logger: l, Logger: l,
ArtifactsLocator: artifactsLocator, ArtifactsLocator: artifactsLocator,
SuperchainProofParams: pipeline.SuperchainProofParams{
WithdrawalDelaySeconds: cliCtx.Uint64(WithdrawalDelaySecondsFlagName),
MinProposalSizeBytes: cliCtx.Uint64(MinProposalSizeBytesFlagName),
ChallengePeriodSeconds: cliCtx.Uint64(ChallengePeriodSecondsFlagName),
ProofMaturityDelaySeconds: cliCtx.Uint64(ProofMaturityDelaySecondsFlagName),
DisputeGameFinalityDelaySeconds: cliCtx.Uint64(DisputeGameFinalityDelaySecondsFlagName),
MIPSVersion: cliCtx.Uint64(MIPSVersionFlagName),
},
}) })
} }
...@@ -116,15 +152,15 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error { ...@@ -116,15 +152,15 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error {
} }
chainIDU64 := chainID.Uint64() chainIDU64 := chainID.Uint64()
superCfg, err := opcm.SuperchainFor(chainIDU64) superCfg, err := standard.SuperchainFor(chainIDU64)
if err != nil { if err != nil {
return fmt.Errorf("error getting superchain config: %w", err) return fmt.Errorf("error getting superchain config: %w", err)
} }
standardVersionsTOML, err := opcm.StandardL1VersionsDataFor(chainIDU64) standardVersionsTOML, err := standard.L1VersionsDataFor(chainIDU64)
if err != nil { if err != nil {
return fmt.Errorf("error getting standard versions TOML: %w", err) return fmt.Errorf("error getting standard versions TOML: %w", err)
} }
opcmProxyOwnerAddr, err := opcm.ManagerOwnerAddrFor(chainIDU64) opcmProxyOwnerAddr, err := standard.ManagerOwnerAddrFor(chainIDU64)
if err != nil { if err != nil {
return fmt.Errorf("error getting superchain proxy admin: %w", err) return fmt.Errorf("error getting superchain proxy admin: %w", err)
} }
...@@ -192,11 +228,12 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error { ...@@ -192,11 +228,12 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error {
host, host,
opcm.DeployImplementationsInput{ opcm.DeployImplementationsInput{
Salt: salt, Salt: salt,
WithdrawalDelaySeconds: big.NewInt(604800), WithdrawalDelaySeconds: new(big.Int).SetUint64(cfg.WithdrawalDelaySeconds),
MinProposalSizeBytes: big.NewInt(126000), MinProposalSizeBytes: new(big.Int).SetUint64(cfg.MinProposalSizeBytes),
ChallengePeriodSeconds: big.NewInt(86400), ChallengePeriodSeconds: new(big.Int).SetUint64(cfg.ChallengePeriodSeconds),
ProofMaturityDelaySeconds: big.NewInt(604800), ProofMaturityDelaySeconds: new(big.Int).SetUint64(cfg.ProofMaturityDelaySeconds),
DisputeGameFinalityDelaySeconds: big.NewInt(302400), DisputeGameFinalityDelaySeconds: new(big.Int).SetUint64(cfg.DisputeGameFinalityDelaySeconds),
MipsVersion: new(big.Int).SetUint64(cfg.MIPSVersion),
Release: release, Release: release,
SuperchainConfigProxy: superchainConfigAddr, SuperchainConfigProxy: superchainConfigAddr,
ProtocolVersionsProxy: protocolVersionsAddr, ProtocolVersionsProxy: protocolVersionsAddr,
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"strings" "strings"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
op_service "github.com/ethereum-optimism/optimism/op-service" op_service "github.com/ethereum-optimism/optimism/op-service"
......
...@@ -14,6 +14,8 @@ import ( ...@@ -14,6 +14,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-chain-ops/script" "github.com/ethereum-optimism/optimism/op-chain-ops/script"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
"github.com/ethereum-optimism/optimism/op-service/testutils/anvil" "github.com/ethereum-optimism/optimism/op-service/testutils/anvil"
...@@ -368,10 +370,10 @@ func validateOPChainDeployment(t *testing.T, cg codeGetter, st *state.State, int ...@@ -368,10 +370,10 @@ func validateOPChainDeployment(t *testing.T, cg codeGetter, st *state.State, int
alloc := chainState.Allocs.Data.Accounts alloc := chainState.Allocs.Data.Accounts
chainIntent := intent.Chains[i] chainIntent := intent.Chains[i]
checkImmutable(t, alloc, predeploys.BaseFeeVaultAddr, chainIntent.BaseFeeVaultRecipient) checkImmutableBehindProxy(t, alloc, predeploys.BaseFeeVaultAddr, chainIntent.BaseFeeVaultRecipient)
checkImmutable(t, alloc, predeploys.L1FeeVaultAddr, chainIntent.L1FeeVaultRecipient) checkImmutableBehindProxy(t, alloc, predeploys.L1FeeVaultAddr, chainIntent.L1FeeVaultRecipient)
checkImmutable(t, alloc, predeploys.SequencerFeeVaultAddr, chainIntent.SequencerFeeVaultRecipient) checkImmutableBehindProxy(t, alloc, predeploys.SequencerFeeVaultAddr, chainIntent.SequencerFeeVaultRecipient)
checkImmutable(t, alloc, predeploys.OptimismMintableERC721FactoryAddr, common.BigToHash(new(big.Int).SetUint64(intent.L1ChainID))) checkImmutableBehindProxy(t, alloc, predeploys.OptimismMintableERC721FactoryAddr, common.BigToHash(new(big.Int).SetUint64(intent.L1ChainID)))
// ownership slots // ownership slots
var addrAsSlot common.Hash var addrAsSlot common.Hash
...@@ -399,8 +401,12 @@ type bytesMarshaler interface { ...@@ -399,8 +401,12 @@ type bytesMarshaler interface {
Bytes() []byte Bytes() []byte
} }
func checkImmutable(t *testing.T, allocations types.GenesisAlloc, proxyContract common.Address, thing bytesMarshaler) { func checkImmutableBehindProxy(t *testing.T, allocations types.GenesisAlloc, proxyContract common.Address, thing bytesMarshaler) {
implementationAddress := getEIP1967ImplementationAddress(t, allocations, proxyContract) implementationAddress := getEIP1967ImplementationAddress(t, allocations, proxyContract)
checkImmutable(t, allocations, implementationAddress, thing)
}
func checkImmutable(t *testing.T, allocations types.GenesisAlloc, implementationAddress common.Address, thing bytesMarshaler) {
account, ok := allocations[implementationAddress] account, ok := allocations[implementationAddress]
require.True(t, ok, "%s not found in allocations", implementationAddress) require.True(t, ok, "%s not found in allocations", implementationAddress)
require.NotEmpty(t, account.Code, "%s should have code", implementationAddress) require.NotEmpty(t, account.Code, "%s should have code", implementationAddress)
...@@ -613,6 +619,168 @@ func TestApplyGenesisStrategy(t *testing.T) { ...@@ -613,6 +619,168 @@ func TestApplyGenesisStrategy(t *testing.T) {
} }
} }
func TestProofParamOverrides(t *testing.T) {
op_e2e.InitParallel(t)
lgr := testlog.Logger(t, slog.LevelDebug)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
depKey := new(deployerKey)
l1ChainID := big.NewInt(77799777)
dk, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic)
require.NoError(t, err)
l2ChainID1 := uint256.NewInt(1)
deployerAddr, err := dk.Address(depKey)
require.NoError(t, err)
loc := localArtifactsLocator(t)
env, bundle, _ := createEnv(t, ctx, lgr, nil, broadcaster.NoopBroadcaster(), deployerAddr)
intent, st := newIntent(t, l1ChainID, dk, l2ChainID1, loc, loc)
intent.Chains = append(intent.Chains, newChainIntent(t, dk, l1ChainID, l2ChainID1))
intent.DeploymentStrategy = state.DeploymentStrategyGenesis
intent.GlobalDeployOverrides = map[string]any{
"withdrawalDelaySeconds": standard.WithdrawalDelaySeconds + 1,
"minProposalSizeBytes": standard.MinProposalSizeBytes + 1,
"challengePeriodSeconds": standard.ChallengePeriodSeconds + 1,
"proofMaturityDelaySeconds": standard.ProofMaturityDelaySeconds + 1,
"disputeGameFinalityDelaySeconds": standard.DisputeGameFinalityDelaySeconds + 1,
"mipsVersion": standard.MIPSVersion + 1,
"disputeGameType": standard.DisputeGameType, // This must be set to the permissioned game
"disputeAbsolutePrestate": common.Hash{'A', 'B', 'S', 'O', 'L', 'U', 'T', 'E'},
"disputeMaxGameDepth": standard.DisputeMaxGameDepth + 1,
"disputeSplitDepth": standard.DisputeSplitDepth + 1,
"disputeClockExtension": standard.DisputeClockExtension + 1,
"disputeMaxClockDuration": standard.DisputeMaxClockDuration + 1,
"dangerouslyAllowCustomDisputeParameters": true,
}
require.NoError(t, deployer.ApplyPipeline(
ctx,
env,
bundle,
intent,
st,
))
allocs := st.L1StateDump.Data.Accounts
chainState := st.Chains[0]
uint64Caster := func(t *testing.T, val any) common.Hash {
return common.BigToHash(new(big.Int).SetUint64(val.(uint64)))
}
tests := []struct {
name string
caster func(t *testing.T, val any) common.Hash
address common.Address
}{
{
"withdrawalDelaySeconds",
uint64Caster,
st.ImplementationsDeployment.DelayedWETHImplAddress,
},
{
"minProposalSizeBytes",
uint64Caster,
st.ImplementationsDeployment.PreimageOracleSingletonAddress,
},
{
"challengePeriodSeconds",
uint64Caster,
st.ImplementationsDeployment.PreimageOracleSingletonAddress,
},
{
"proofMaturityDelaySeconds",
uint64Caster,
st.ImplementationsDeployment.OptimismPortalImplAddress,
},
{
"disputeGameFinalityDelaySeconds",
uint64Caster,
st.ImplementationsDeployment.OptimismPortalImplAddress,
},
{
"disputeAbsolutePrestate",
func(t *testing.T, val any) common.Hash {
return val.(common.Hash)
},
chainState.PermissionedDisputeGameAddress,
},
{
"disputeMaxGameDepth",
uint64Caster,
chainState.PermissionedDisputeGameAddress,
},
{
"disputeSplitDepth",
uint64Caster,
chainState.PermissionedDisputeGameAddress,
},
{
"disputeClockExtension",
uint64Caster,
chainState.PermissionedDisputeGameAddress,
},
{
"disputeMaxClockDuration",
uint64Caster,
chainState.PermissionedDisputeGameAddress,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
checkImmutable(t, allocs, tt.address, tt.caster(t, intent.GlobalDeployOverrides[tt.name]))
})
}
}
func TestInteropDeployment(t *testing.T) {
op_e2e.InitParallel(t)
lgr := testlog.Logger(t, slog.LevelDebug)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
depKey := new(deployerKey)
l1ChainID := big.NewInt(77799777)
dk, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic)
require.NoError(t, err)
l2ChainID1 := uint256.NewInt(1)
deployerAddr, err := dk.Address(depKey)
require.NoError(t, err)
loc := localArtifactsLocator(t)
env, bundle, _ := createEnv(t, ctx, lgr, nil, broadcaster.NoopBroadcaster(), deployerAddr)
intent, st := newIntent(t, l1ChainID, dk, l2ChainID1, loc, loc)
intent.Chains = append(intent.Chains, newChainIntent(t, dk, l1ChainID, l2ChainID1))
intent.DeploymentStrategy = state.DeploymentStrategyGenesis
intent.UseInterop = true
require.NoError(t, deployer.ApplyPipeline(
ctx,
env,
bundle,
intent,
st,
))
chainState := st.Chains[0]
depManagerSlot := common.HexToHash("0x1708e077affb93e89be2665fb0fb72581be66f84dc00d25fed755ae911905b1c")
checkImmutable(t, st.L1StateDump.Data.Accounts, st.ImplementationsDeployment.SystemConfigImplAddress, depManagerSlot)
proxyAdminOwnerHash := common.BytesToHash(intent.Chains[0].Roles.L1ProxyAdminOwner.Bytes())
checkStorageSlot(t, st.L1StateDump.Data.Accounts, chainState.SystemConfigProxyAddress, depManagerSlot, proxyAdminOwnerHash)
}
func TestInvalidL2Genesis(t *testing.T) { func TestInvalidL2Genesis(t *testing.T) {
op_e2e.InitParallel(t) op_e2e.InitParallel(t)
......
...@@ -4,6 +4,8 @@ import ( ...@@ -4,6 +4,8 @@ import (
"fmt" "fmt"
"net/url" "net/url"
"strings" "strings"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
) )
type schemeUnmarshaler func(string) (*ArtifactsLocator, error) type schemeUnmarshaler func(string) (*ArtifactsLocator, error)
...@@ -14,6 +16,14 @@ var schemeUnmarshalerDispatch = map[string]schemeUnmarshaler{ ...@@ -14,6 +16,14 @@ var schemeUnmarshalerDispatch = map[string]schemeUnmarshaler{
"https": unmarshalURL, "https": unmarshalURL,
} }
var DefaultL1ContractsLocator = &ArtifactsLocator{
Tag: standard.DefaultL1ContractsTag,
}
var DefaultL2ContractsLocator = &ArtifactsLocator{
Tag: standard.DefaultL2ContractsTag,
}
type ArtifactsLocator struct { type ArtifactsLocator struct {
URL *url.URL URL *url.URL
Tag string Tag string
...@@ -61,7 +71,7 @@ func unmarshalTag(tag string) (*ArtifactsLocator, error) { ...@@ -61,7 +71,7 @@ func unmarshalTag(tag string) (*ArtifactsLocator, error) {
return nil, fmt.Errorf("invalid tag: %s", tag) return nil, fmt.Errorf("invalid tag: %s", tag)
} }
if _, err := StandardArtifactsURLForTag(tag); err != nil { if _, err := standard.ArtifactsURLForTag(tag); err != nil {
return nil, err return nil, err
} }
......
...@@ -44,6 +44,7 @@ type DeployOPChainInput struct { ...@@ -44,6 +44,7 @@ type DeployOPChainInput struct {
DisputeSplitDepth uint64 DisputeSplitDepth uint64
DisputeClockExtension uint64 DisputeClockExtension uint64
DisputeMaxClockDuration uint64 DisputeMaxClockDuration uint64
AllowCustomDisputeParameters bool
} }
func (input *DeployOPChainInput) InputSet() bool { func (input *DeployOPChainInput) InputSet() bool {
......
...@@ -15,6 +15,8 @@ import ( ...@@ -15,6 +15,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
...@@ -42,7 +44,7 @@ func DownloadArtifacts(ctx context.Context, loc *opcm.ArtifactsLocator, progress ...@@ -42,7 +44,7 @@ func DownloadArtifacts(ctx context.Context, loc *opcm.ArtifactsLocator, progress
var u *url.URL var u *url.URL
var err error var err error
if loc.IsTag() { if loc.IsTag() {
u, err = opcm.StandardArtifactsURLForTag(loc.Tag) u, err = standard.ArtifactsURLForTag(loc.Tag)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to get standard artifacts URL for tag %s: %w", loc.Tag, err) return nil, nil, fmt.Errorf("failed to get standard artifacts URL for tag %s: %w", loc.Tag, err)
} }
......
...@@ -4,10 +4,22 @@ import ( ...@@ -4,10 +4,22 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
) )
type SuperchainProofParams struct {
WithdrawalDelaySeconds uint64 `json:"withdrawalDelaySeconds" toml:"withdrawalDelaySeconds"`
MinProposalSizeBytes uint64 `json:"minProposalSizeBytes" toml:"minProposalSizeBytes"`
ChallengePeriodSeconds uint64 `json:"challengePeriodSeconds" toml:"challengePeriodSeconds"`
ProofMaturityDelaySeconds uint64 `json:"proofMaturityDelaySeconds" toml:"proofMaturityDelaySeconds"`
DisputeGameFinalityDelaySeconds uint64 `json:"disputeGameFinalityDelaySeconds" toml:"disputeGameFinalityDelaySeconds"`
MIPSVersion uint64 `json:"mipsVersion" toml:"mipsVersion"`
}
func DeployImplementations(env *Env, intent *state.Intent, st *state.State) error { func DeployImplementations(env *Env, intent *state.Intent, st *state.State) error {
lgr := env.Logger.New("stage", "deploy-implementations") lgr := env.Logger.New("stage", "deploy-implementations")
...@@ -22,7 +34,7 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro ...@@ -22,7 +34,7 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro
var contractsRelease string var contractsRelease string
var err error var err error
if intent.L1ContractsLocator.IsTag() && intent.DeploymentStrategy == state.DeploymentStrategyLive { if intent.L1ContractsLocator.IsTag() && intent.DeploymentStrategy == state.DeploymentStrategyLive {
standardVersionsTOML, err = opcm.StandardL1VersionsDataFor(intent.L1ChainID) standardVersionsTOML, err = standard.L1VersionsDataFor(intent.L1ChainID)
if err != nil { if err != nil {
return fmt.Errorf("error getting standard versions TOML: %w", err) return fmt.Errorf("error getting standard versions TOML: %w", err)
} }
...@@ -31,24 +43,39 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro ...@@ -31,24 +43,39 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro
contractsRelease = "dev" contractsRelease = "dev"
} }
proofParams, err := jsonutil.MergeJSON(
SuperchainProofParams{
WithdrawalDelaySeconds: standard.WithdrawalDelaySeconds,
MinProposalSizeBytes: standard.MinProposalSizeBytes,
ChallengePeriodSeconds: standard.ChallengePeriodSeconds,
ProofMaturityDelaySeconds: standard.ProofMaturityDelaySeconds,
DisputeGameFinalityDelaySeconds: standard.DisputeGameFinalityDelaySeconds,
MIPSVersion: standard.MIPSVersion,
},
intent.GlobalDeployOverrides,
)
if err != nil {
return fmt.Errorf("error merging proof params from overrides: %w", err)
}
env.L1ScriptHost.ImportState(st.L1StateDump.Data) env.L1ScriptHost.ImportState(st.L1StateDump.Data)
dio, err := opcm.DeployImplementations( dio, err := opcm.DeployImplementations(
env.L1ScriptHost, env.L1ScriptHost,
opcm.DeployImplementationsInput{ opcm.DeployImplementationsInput{
Salt: st.Create2Salt, Salt: st.Create2Salt,
WithdrawalDelaySeconds: big.NewInt(604800), WithdrawalDelaySeconds: new(big.Int).SetUint64(proofParams.WithdrawalDelaySeconds),
MinProposalSizeBytes: big.NewInt(126000), MinProposalSizeBytes: new(big.Int).SetUint64(proofParams.MinProposalSizeBytes),
ChallengePeriodSeconds: big.NewInt(86400), ChallengePeriodSeconds: new(big.Int).SetUint64(proofParams.ChallengePeriodSeconds),
ProofMaturityDelaySeconds: big.NewInt(604800), ProofMaturityDelaySeconds: new(big.Int).SetUint64(proofParams.ProofMaturityDelaySeconds),
DisputeGameFinalityDelaySeconds: big.NewInt(302400), DisputeGameFinalityDelaySeconds: new(big.Int).SetUint64(proofParams.DisputeGameFinalityDelaySeconds),
MipsVersion: big.NewInt(1), MipsVersion: new(big.Int).SetUint64(proofParams.MIPSVersion),
Release: contractsRelease, Release: contractsRelease,
SuperchainConfigProxy: st.SuperchainDeployment.SuperchainConfigProxyAddress, SuperchainConfigProxy: st.SuperchainDeployment.SuperchainConfigProxyAddress,
ProtocolVersionsProxy: st.SuperchainDeployment.ProtocolVersionsProxyAddress, ProtocolVersionsProxy: st.SuperchainDeployment.ProtocolVersionsProxyAddress,
OpcmProxyOwner: st.SuperchainDeployment.ProxyAdminAddress, OpcmProxyOwner: st.SuperchainDeployment.ProxyAdminAddress,
StandardVersionsToml: standardVersionsTOML, StandardVersionsToml: standardVersionsTOML,
UseInterop: false, UseInterop: intent.UseInterop,
}, },
) )
if err != nil { if err != nil {
......
...@@ -5,7 +5,8 @@ import ( ...@@ -5,7 +5,8 @@ import (
"crypto/rand" "crypto/rand"
"fmt" "fmt"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
"github.com/ethereum-optimism/optimism/op-chain-ops/script" "github.com/ethereum-optimism/optimism/op-chain-ops/script"
...@@ -26,12 +27,12 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s ...@@ -26,12 +27,12 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s
} }
if intent.L1ContractsLocator.IsTag() { if intent.L1ContractsLocator.IsTag() {
superCfg, err := opcm.SuperchainFor(intent.L1ChainID) superCfg, err := standard.SuperchainFor(intent.L1ChainID)
if err != nil { if err != nil {
return fmt.Errorf("error getting superchain config: %w", err) return fmt.Errorf("error getting superchain config: %w", err)
} }
proxyAdmin, err := opcm.ManagerOwnerAddrFor(intent.L1ChainID) proxyAdmin, err := standard.ManagerOwnerAddrFor(intent.L1ChainID)
if err != nil { if err != nil {
return fmt.Errorf("error getting superchain proxy admin address: %w", err) return fmt.Errorf("error getting superchain proxy admin address: %w", err)
} }
...@@ -44,7 +45,7 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s ...@@ -44,7 +45,7 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s
SuperchainConfigProxyAddress: common.Address(*superCfg.Config.SuperchainConfigAddr), SuperchainConfigProxyAddress: common.Address(*superCfg.Config.SuperchainConfigAddr),
} }
opcmProxy, err := opcm.ManagerImplementationAddrFor(intent.L1ChainID) opcmProxy, err := standard.ManagerImplementationAddrFor(intent.L1ChainID)
if err != nil { if err != nil {
return fmt.Errorf("error getting OPCM proxy address: %w", err) return fmt.Errorf("error getting OPCM proxy address: %w", err)
} }
......
...@@ -6,6 +6,9 @@ import ( ...@@ -6,6 +6,9 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
...@@ -26,7 +29,10 @@ func DeployOPChainLiveStrategy(ctx context.Context, env *Env, bundle ArtifactsBu ...@@ -26,7 +29,10 @@ func DeployOPChainLiveStrategy(ctx context.Context, env *Env, bundle ArtifactsBu
return fmt.Errorf("failed to get chain intent: %w", err) return fmt.Errorf("failed to get chain intent: %w", err)
} }
input := makeDCI(thisIntent, chainID, st) input, err := makeDCI(intent, thisIntent, chainID, st)
if err != nil {
return fmt.Errorf("error making deploy OP chain input: %w", err)
}
var dco opcm.DeployOPChainOutput var dco opcm.DeployOPChainOutput
lgr.Info("deploying OP chain using existing OPCM", "id", chainID.Hex(), "opcmAddress", st.ImplementationsDeployment.OpcmProxyAddress.Hex()) lgr.Info("deploying OP chain using existing OPCM", "id", chainID.Hex(), "opcmAddress", st.ImplementationsDeployment.OpcmProxyAddress.Hex())
...@@ -152,7 +158,10 @@ func DeployOPChainGenesisStrategy(env *Env, intent *state.Intent, st *state.Stat ...@@ -152,7 +158,10 @@ func DeployOPChainGenesisStrategy(env *Env, intent *state.Intent, st *state.Stat
return fmt.Errorf("failed to get chain intent: %w", err) return fmt.Errorf("failed to get chain intent: %w", err)
} }
input := makeDCI(thisIntent, chainID, st) input, err := makeDCI(intent, thisIntent, chainID, st)
if err != nil {
return fmt.Errorf("error making deploy OP chain input: %w", err)
}
env.L1ScriptHost.ImportState(st.L1StateDump.Data) env.L1ScriptHost.ImportState(st.L1StateDump.Data)
...@@ -171,7 +180,33 @@ func DeployOPChainGenesisStrategy(env *Env, intent *state.Intent, st *state.Stat ...@@ -171,7 +180,33 @@ func DeployOPChainGenesisStrategy(env *Env, intent *state.Intent, st *state.Stat
return nil return nil
} }
func makeDCI(thisIntent *state.ChainIntent, chainID common.Hash, st *state.State) opcm.DeployOPChainInput { type ChainProofParams struct {
DisputeGameType uint32 `json:"disputeGameType" toml:"disputeGameType"`
DisputeAbsolutePrestate common.Hash `json:"disputeAbsolutePrestate" toml:"disputeAbsolutePrestate"`
DisputeMaxGameDepth uint64 `json:"disputeMaxGameDepth" toml:"disputeMaxGameDepth"`
DisputeSplitDepth uint64 `json:"disputeSplitDepth" toml:"disputeSplitDepth"`
DisputeClockExtension uint64 `json:"disputeClockExtension" toml:"disputeClockExtension"`
DisputeMaxClockDuration uint64 `json:"disputeMaxClockDuration" toml:"disputeMaxClockDuration"`
DangerouslyAllowCustomDisputeParameters bool `json:"dangerouslyAllowCustomDisputeParameters" toml:"dangerouslyAllowCustomDisputeParameters"`
}
func makeDCI(intent *state.Intent, thisIntent *state.ChainIntent, chainID common.Hash, st *state.State) (opcm.DeployOPChainInput, error) {
proofParams, err := jsonutil.MergeJSON(
ChainProofParams{
DisputeGameType: standard.DisputeGameType,
DisputeAbsolutePrestate: standard.DisputeAbsolutePrestate,
DisputeMaxGameDepth: standard.DisputeMaxGameDepth,
DisputeSplitDepth: standard.DisputeSplitDepth,
DisputeClockExtension: standard.DisputeClockExtension,
DisputeMaxClockDuration: standard.DisputeMaxClockDuration,
},
intent.GlobalDeployOverrides,
thisIntent.DeployOverrides,
)
if err != nil {
return opcm.DeployOPChainInput{}, fmt.Errorf("error merging proof params from overrides: %w", err)
}
return opcm.DeployOPChainInput{ return opcm.DeployOPChainInput{
OpChainProxyAdminOwner: thisIntent.Roles.L1ProxyAdminOwner, OpChainProxyAdminOwner: thisIntent.Roles.L1ProxyAdminOwner,
SystemConfigOwner: thisIntent.Roles.SystemConfigOwner, SystemConfigOwner: thisIntent.Roles.SystemConfigOwner,
...@@ -179,19 +214,20 @@ func makeDCI(thisIntent *state.ChainIntent, chainID common.Hash, st *state.State ...@@ -179,19 +214,20 @@ func makeDCI(thisIntent *state.ChainIntent, chainID common.Hash, st *state.State
UnsafeBlockSigner: thisIntent.Roles.UnsafeBlockSigner, UnsafeBlockSigner: thisIntent.Roles.UnsafeBlockSigner,
Proposer: thisIntent.Roles.Proposer, Proposer: thisIntent.Roles.Proposer,
Challenger: thisIntent.Roles.Challenger, Challenger: thisIntent.Roles.Challenger,
BasefeeScalar: 1368, BasefeeScalar: standard.BasefeeScalar,
BlobBaseFeeScalar: 801949, BlobBaseFeeScalar: standard.BlobBaseFeeScalar,
L2ChainId: chainID.Big(), L2ChainId: chainID.Big(),
OpcmProxy: st.ImplementationsDeployment.OpcmProxyAddress, OpcmProxy: st.ImplementationsDeployment.OpcmProxyAddress,
SaltMixer: st.Create2Salt.String(), // passing through salt generated at state initialization SaltMixer: st.Create2Salt.String(), // passing through salt generated at state initialization
GasLimit: 60_000_000, GasLimit: standard.GasLimit,
DisputeGameType: 1, // PERMISSIONED_CANNON Game Type DisputeGameType: proofParams.DisputeGameType,
DisputeAbsolutePrestate: common.HexToHash("0x038512e02c4c3f7bdaec27d00edf55b7155e0905301e1a88083e4e0a6764d54c"), DisputeAbsolutePrestate: proofParams.DisputeAbsolutePrestate,
DisputeMaxGameDepth: 73, DisputeMaxGameDepth: proofParams.DisputeMaxGameDepth,
DisputeSplitDepth: 30, DisputeSplitDepth: proofParams.DisputeSplitDepth,
DisputeClockExtension: 10800, // 3 hours (input in seconds) DisputeClockExtension: proofParams.DisputeClockExtension, // 3 hours (input in seconds)
DisputeMaxClockDuration: 302400, // 3.5 days (input in seconds) DisputeMaxClockDuration: proofParams.DisputeMaxClockDuration, // 3.5 days (input in seconds)
} AllowCustomDisputeParameters: proofParams.DangerouslyAllowCustomDisputeParameters,
}, nil
} }
func makeChainState(chainID common.Hash, dco opcm.DeployOPChainOutput) *state.ChainState { func makeChainState(chainID common.Hash, dco opcm.DeployOPChainOutput) *state.ChainState {
......
package opcm package standard
import ( import (
"embed" "embed"
...@@ -11,45 +11,60 @@ import ( ...@@ -11,45 +11,60 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
const (
GasLimit uint64 = 60_000_000
BasefeeScalar uint32 = 1368
BlobBaseFeeScalar uint32 = 801949
WithdrawalDelaySeconds uint64 = 604800
MinProposalSizeBytes uint64 = 126000
ChallengePeriodSeconds uint64 = 86400
ProofMaturityDelaySeconds uint64 = 604800
DisputeGameFinalityDelaySeconds uint64 = 302400
MIPSVersion uint64 = 1
DisputeGameType uint32 = 1 // PERMISSIONED game type
DisputeMaxGameDepth uint64 = 73
DisputeSplitDepth uint64 = 30
DisputeClockExtension uint64 = 10800
DisputeMaxClockDuration uint64 = 302400
)
var DisputeAbsolutePrestate = common.HexToHash("0x038512e02c4c3f7bdaec27d00edf55b7155e0905301e1a88083e4e0a6764d54c")
//go:embed standard-versions-mainnet.toml //go:embed standard-versions-mainnet.toml
var StandardVersionsMainnetData string var VersionsMainnetData string
//go:embed standard-versions-sepolia.toml //go:embed standard-versions-sepolia.toml
var StandardVersionsSepoliaData string var VersionsSepoliaData string
var StandardL1VersionsSepolia StandardL1Versions var L1VersionsSepolia L1Versions
var StandardL1VersionsMainnet StandardL1Versions var L1VersionsMainnet L1Versions
var DefaultL1ContractsLocator = &ArtifactsLocator{ var DefaultL1ContractsTag = "op-contracts/v1.6.0"
Tag: "op-contracts/v1.6.0",
}
var DefaultL2ContractsLocator = &ArtifactsLocator{ var DefaultL2ContractsTag = "op-contracts/v1.7.0-beta.1+l2-contracts"
Tag: "op-contracts/v1.7.0-beta.1+l2-contracts",
}
type StandardL1Versions struct { type L1Versions struct {
Releases map[string]StandardL1VersionsReleases `toml:"releases"` Releases map[string]L1VersionsReleases `toml:"releases"`
} }
type StandardL1VersionsReleases struct { type L1VersionsReleases struct {
OptimismPortal StandardVersionRelease `toml:"optimism_portal"` OptimismPortal VersionRelease `toml:"optimism_portal"`
SystemConfig StandardVersionRelease `toml:"system_config"` SystemConfig VersionRelease `toml:"system_config"`
AnchorStateRegistry StandardVersionRelease `toml:"anchor_state_registry"` AnchorStateRegistry VersionRelease `toml:"anchor_state_registry"`
DelayedWETH StandardVersionRelease `toml:"delayed_weth"` DelayedWETH VersionRelease `toml:"delayed_weth"`
DisputeGameFactory StandardVersionRelease `toml:"dispute_game_factory"` DisputeGameFactory VersionRelease `toml:"dispute_game_factory"`
FaultDisputeGame StandardVersionRelease `toml:"fault_dispute_game"` FaultDisputeGame VersionRelease `toml:"fault_dispute_game"`
PermissionedDisputeGame StandardVersionRelease `toml:"permissioned_dispute_game"` PermissionedDisputeGame VersionRelease `toml:"permissioned_dispute_game"`
MIPS StandardVersionRelease `toml:"mips"` MIPS VersionRelease `toml:"mips"`
PreimageOracle StandardVersionRelease `toml:"preimage_oracle"` PreimageOracle VersionRelease `toml:"preimage_oracle"`
L1CrossDomainMessenger StandardVersionRelease `toml:"l1_cross_domain_messenger"` L1CrossDomainMessenger VersionRelease `toml:"l1_cross_domain_messenger"`
L1ERC721Bridge StandardVersionRelease `toml:"l1_erc721_bridge"` L1ERC721Bridge VersionRelease `toml:"l1_erc721_bridge"`
L1StandardBridge StandardVersionRelease `toml:"l1_standard_bridge"` L1StandardBridge VersionRelease `toml:"l1_standard_bridge"`
OptimismMintableERC20Factory StandardVersionRelease `toml:"optimism_mintable_erc20_factory"` OptimismMintableERC20Factory VersionRelease `toml:"optimism_mintable_erc20_factory"`
} }
type StandardVersionRelease struct { type VersionRelease struct {
Version string `toml:"version"` Version string `toml:"version"`
ImplementationAddress common.Address `toml:"implementation_address"` ImplementationAddress common.Address `toml:"implementation_address"`
Address common.Address `toml:"address"` Address common.Address `toml:"address"`
...@@ -57,25 +72,25 @@ type StandardVersionRelease struct { ...@@ -57,25 +72,25 @@ type StandardVersionRelease struct {
var _ embed.FS var _ embed.FS
func StandardL1VersionsDataFor(chainID uint64) (string, error) { func L1VersionsDataFor(chainID uint64) (string, error) {
switch chainID { switch chainID {
case 1: case 1:
return StandardVersionsMainnetData, nil return VersionsMainnetData, nil
case 11155111: case 11155111:
return StandardVersionsSepoliaData, nil return VersionsSepoliaData, nil
default: default:
return "", fmt.Errorf("unsupported chain ID: %d", chainID) return "", fmt.Errorf("unsupported chain ID: %d", chainID)
} }
} }
func StandardL1VersionsFor(chainID uint64) (StandardL1Versions, error) { func L1VersionsFor(chainID uint64) (L1Versions, error) {
switch chainID { switch chainID {
case 1: case 1:
return StandardL1VersionsMainnet, nil return L1VersionsMainnet, nil
case 11155111: case 11155111:
return StandardL1VersionsSepolia, nil return L1VersionsSepolia, nil
default: default:
return StandardL1Versions{}, fmt.Errorf("unsupported chain ID: %d", chainID) return L1Versions{}, fmt.Errorf("unsupported chain ID: %d", chainID)
} }
} }
...@@ -116,7 +131,7 @@ func ManagerOwnerAddrFor(chainID uint64) (common.Address, error) { ...@@ -116,7 +131,7 @@ func ManagerOwnerAddrFor(chainID uint64) (common.Address, error) {
} }
} }
func StandardArtifactsURLForTag(tag string) (*url.URL, error) { func ArtifactsURLForTag(tag string) (*url.URL, error) {
switch tag { switch tag {
case "op-contracts/v1.6.0": case "op-contracts/v1.6.0":
return url.Parse(standardArtifactsURL("ee07c78c3d8d4cd8f7a933c050f5afeebaa281b57b226cc6f092b19de2a8d61f")) return url.Parse(standardArtifactsURL("ee07c78c3d8d4cd8f7a933c050f5afeebaa281b57b226cc6f092b19de2a8d61f"))
...@@ -132,13 +147,13 @@ func standardArtifactsURL(checksum string) string { ...@@ -132,13 +147,13 @@ func standardArtifactsURL(checksum string) string {
} }
func init() { func init() {
StandardL1VersionsMainnet = StandardL1Versions{} L1VersionsMainnet = L1Versions{}
if err := toml.Unmarshal([]byte(StandardVersionsMainnetData), &StandardL1VersionsMainnet); err != nil { if err := toml.Unmarshal([]byte(VersionsMainnetData), &L1VersionsMainnet); err != nil {
panic(err) panic(err)
} }
StandardL1VersionsSepolia = StandardL1Versions{} L1VersionsSepolia = L1Versions{}
if err := toml.Unmarshal([]byte(StandardVersionsSepoliaData), &StandardL1VersionsSepolia); err != nil { if err := toml.Unmarshal([]byte(VersionsSepoliaData), &L1VersionsSepolia); err != nil {
panic(err) panic(err)
} }
} }
package state package state
import ( import (
"encoding/json"
"fmt" "fmt"
"math/big" "math/big"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -135,7 +136,7 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State, ...@@ -135,7 +136,7 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State,
// Apply overrides after setting the main values. // Apply overrides after setting the main values.
var err error var err error
if len(intent.GlobalDeployOverrides) > 0 { if len(intent.GlobalDeployOverrides) > 0 {
cfg, err = mergeJSON(cfg, intent.GlobalDeployOverrides) cfg, err = jsonutil.MergeJSON(cfg, intent.GlobalDeployOverrides)
if err != nil { if err != nil {
return genesis.DeployConfig{}, fmt.Errorf("error merging global L2 overrides: %w", err) return genesis.DeployConfig{}, fmt.Errorf("error merging global L2 overrides: %w", err)
...@@ -143,7 +144,7 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State, ...@@ -143,7 +144,7 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State,
} }
if len(chainIntent.DeployOverrides) > 0 { if len(chainIntent.DeployOverrides) > 0 {
cfg, err = mergeJSON(cfg, chainIntent.DeployOverrides) cfg, err = jsonutil.MergeJSON(cfg, chainIntent.DeployOverrides)
if err != nil { if err != nil {
return genesis.DeployConfig{}, fmt.Errorf("error merging chain L2 overrides: %w", err) return genesis.DeployConfig{}, fmt.Errorf("error merging chain L2 overrides: %w", err)
} }
...@@ -156,40 +157,6 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State, ...@@ -156,40 +157,6 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State,
return cfg, nil 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 { func mustHexBigFromHex(hex string) *hexutil.Big {
num := hexutil.MustDecodeBig(hex) num := hexutil.MustDecodeBig(hex)
hexBig := hexutil.Big(*num) hexBig := hexutil.Big(*num)
......
...@@ -4,6 +4,8 @@ import ( ...@@ -4,6 +4,8 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum-optimism/optimism/op-service/ioutil"
...@@ -38,6 +40,8 @@ type Intent struct { ...@@ -38,6 +40,8 @@ type Intent struct {
FundDevAccounts bool `json:"fundDevAccounts" toml:"fundDevAccounts"` FundDevAccounts bool `json:"fundDevAccounts" toml:"fundDevAccounts"`
UseInterop bool `json:"useInterop" toml:"useInterop"`
L1ContractsLocator *opcm.ArtifactsLocator `json:"l1ContractsLocator" toml:"l1ContractsLocator"` L1ContractsLocator *opcm.ArtifactsLocator `json:"l1ContractsLocator" toml:"l1ContractsLocator"`
L2ContractsLocator *opcm.ArtifactsLocator `json:"l2ContractsLocator" toml:"l2ContractsLocator"` L2ContractsLocator *opcm.ArtifactsLocator `json:"l2ContractsLocator" toml:"l2ContractsLocator"`
...@@ -102,7 +106,7 @@ func (c *Intent) WriteToFile(path string) error { ...@@ -102,7 +106,7 @@ func (c *Intent) WriteToFile(path string) error {
} }
func (c *Intent) checkL1Prod() error { func (c *Intent) checkL1Prod() error {
versions, err := opcm.StandardL1VersionsFor(c.L1ChainID) versions, err := standard.L1VersionsFor(c.L1ChainID)
if err != nil { if err != nil {
return err return err
} }
...@@ -131,7 +135,7 @@ func (c *Intent) checkL1Dev() error { ...@@ -131,7 +135,7 @@ func (c *Intent) checkL1Dev() error {
} }
func (c *Intent) checkL2Prod() error { func (c *Intent) checkL2Prod() error {
_, err := opcm.StandardArtifactsURLForTag(c.L2ContractsLocator.Tag) _, err := standard.ArtifactsURLForTag(c.L2ContractsLocator.Tag)
return err return err
} }
......
package jsonutil
import "encoding/json"
// 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
}
package state package jsonutil
import ( import (
"testing" "testing"
...@@ -13,7 +13,7 @@ func TestMergeJSON(t *testing.T) { ...@@ -13,7 +13,7 @@ func TestMergeJSON(t *testing.T) {
C bool `json:"c"` C bool `json:"c"`
} }
out, err := mergeJSON( out, err := MergeJSON(
testStruct{ testStruct{
"hello", "hello",
42, 42,
......
...@@ -58,6 +58,7 @@ contract DeployOPChainInput is BaseDeployIO { ...@@ -58,6 +58,7 @@ contract DeployOPChainInput is BaseDeployIO {
uint256 internal _disputeSplitDepth; uint256 internal _disputeSplitDepth;
Duration internal _disputeClockExtension; Duration internal _disputeClockExtension;
Duration internal _disputeMaxClockDuration; Duration internal _disputeMaxClockDuration;
bool internal _allowCustomDisputeParameters;
function set(bytes4 _sel, address _addr) public { function set(bytes4 _sel, address _addr) public {
require(_addr != address(0), "DeployOPChainInput: cannot set zero address"); require(_addr != address(0), "DeployOPChainInput: cannot set zero address");
...@@ -107,6 +108,11 @@ contract DeployOPChainInput is BaseDeployIO { ...@@ -107,6 +108,11 @@ contract DeployOPChainInput is BaseDeployIO {
else revert("DeployImplementationsInput: unknown selector"); else revert("DeployImplementationsInput: unknown selector");
} }
function set(bytes4 _sel, bool _value) public {
if (_sel == this.allowCustomDisputeParameters.selector) _allowCustomDisputeParameters = _value;
else revert("DeployOPChainInput: unknown selector");
}
function opChainProxyAdminOwner() public view returns (address) { function opChainProxyAdminOwner() public view returns (address) {
require(_opChainProxyAdminOwner != address(0), "DeployOPChainInput: not set"); require(_opChainProxyAdminOwner != address(0), "DeployOPChainInput: not set");
return _opChainProxyAdminOwner; return _opChainProxyAdminOwner;
...@@ -206,6 +212,10 @@ contract DeployOPChainInput is BaseDeployIO { ...@@ -206,6 +212,10 @@ contract DeployOPChainInput is BaseDeployIO {
function disputeMaxClockDuration() public view returns (Duration) { function disputeMaxClockDuration() public view returns (Duration) {
return _disputeMaxClockDuration; return _disputeMaxClockDuration;
} }
function allowCustomDisputeParameters() public view returns (bool) {
return _allowCustomDisputeParameters;
}
} }
contract DeployOPChainOutput is BaseDeployIO { contract DeployOPChainOutput is BaseDeployIO {
...@@ -457,6 +467,11 @@ contract DeployOPChain is Script { ...@@ -457,6 +467,11 @@ contract DeployOPChain is Script {
IPermissionedDisputeGame game = _doo.permissionedDisputeGame(); IPermissionedDisputeGame game = _doo.permissionedDisputeGame();
require(GameType.unwrap(game.gameType()) == GameType.unwrap(GameTypes.PERMISSIONED_CANNON), "DPG-10"); require(GameType.unwrap(game.gameType()) == GameType.unwrap(GameTypes.PERMISSIONED_CANNON), "DPG-10");
if (_doi.allowCustomDisputeParameters()) {
return;
}
// This hex string is the absolutePrestate of the latest op-program release, see where the // This hex string is the absolutePrestate of the latest op-program release, see where the
// `EXPECTED_PRESTATE_HASH` is defined in `config.yml`. // `EXPECTED_PRESTATE_HASH` is defined in `config.yml`.
require( require(
......
...@@ -59,6 +59,7 @@ contract DeployOPChainInput_Test is Test { ...@@ -59,6 +59,7 @@ contract DeployOPChainInput_Test is Test {
doi.set(doi.basefeeScalar.selector, basefeeScalar); doi.set(doi.basefeeScalar.selector, basefeeScalar);
doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar); doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar);
doi.set(doi.l2ChainId.selector, l2ChainId); doi.set(doi.l2ChainId.selector, l2ChainId);
doi.set(doi.allowCustomDisputeParameters.selector, true);
(IProxy opcmProxy) = DeployUtils.buildERC1967ProxyWithImpl("opcmProxy"); (IProxy opcmProxy) = DeployUtils.buildERC1967ProxyWithImpl("opcmProxy");
doi.set(doi.opcmProxy.selector, address(opcmProxy)); doi.set(doi.opcmProxy.selector, address(opcmProxy));
...@@ -74,6 +75,7 @@ contract DeployOPChainInput_Test is Test { ...@@ -74,6 +75,7 @@ contract DeployOPChainInput_Test is Test {
assertEq(blobBaseFeeScalar, doi.blobBaseFeeScalar(), "900"); assertEq(blobBaseFeeScalar, doi.blobBaseFeeScalar(), "900");
assertEq(l2ChainId, doi.l2ChainId(), "1000"); assertEq(l2ChainId, doi.l2ChainId(), "1000");
assertEq(address(opcmProxy), address(doi.opcmProxy()), "1100"); assertEq(address(opcmProxy), address(doi.opcmProxy()), "1100");
assertEq(true, doi.allowCustomDisputeParameters(), "1200");
} }
function test_getters_whenNotSet_revert() public { function test_getters_whenNotSet_revert() public {
...@@ -531,6 +533,42 @@ contract DeployOPChain_Test is DeployOPChain_TestBase { ...@@ -531,6 +533,42 @@ contract DeployOPChain_Test is DeployOPChain_TestBase {
assertEq(address(doo.opChainProxyAdmin().addressManager()), address(doo.addressManager()), "3700"); assertEq(address(doo.opChainProxyAdmin().addressManager()), address(doo.addressManager()), "3700");
assertEq(address(doo.opChainProxyAdmin().owner()), opChainProxyAdminOwner, "3800"); assertEq(address(doo.opChainProxyAdmin().owner()), opChainProxyAdminOwner, "3800");
} }
function test_customDisputeGame_customDisabled_reverts() public {
setDOI();
doi.set(doi.disputeSplitDepth.selector, disputeSplitDepth + 1);
vm.expectRevert("DPG-90");
deployOPChain.run(doi, doo);
}
function test_customDisputeGame_customEnabled_doesNotRevert() public {
setDOI();
doi.set(doi.allowCustomDisputeParameters.selector, true);
doi.set(doi.disputeSplitDepth.selector, disputeSplitDepth + 1);
deployOPChain.run(doi, doo);
assertEq(doo.permissionedDisputeGame().splitDepth(), disputeSplitDepth + 1);
}
function setDOI() internal {
doi.set(doi.opChainProxyAdminOwner.selector, opChainProxyAdminOwner);
doi.set(doi.systemConfigOwner.selector, systemConfigOwner);
doi.set(doi.batcher.selector, batcher);
doi.set(doi.unsafeBlockSigner.selector, unsafeBlockSigner);
doi.set(doi.proposer.selector, proposer);
doi.set(doi.challenger.selector, challenger);
doi.set(doi.basefeeScalar.selector, basefeeScalar);
doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar);
doi.set(doi.l2ChainId.selector, l2ChainId);
doi.set(doi.opcmProxy.selector, address(opcm));
doi.set(doi.saltMixer.selector, saltMixer);
doi.set(doi.gasLimit.selector, gasLimit);
doi.set(doi.disputeGameType.selector, disputeGameType);
doi.set(doi.disputeAbsolutePrestate.selector, disputeAbsolutePrestate);
doi.set(doi.disputeMaxGameDepth.selector, disputeMaxGameDepth);
doi.set(doi.disputeSplitDepth.selector, disputeSplitDepth);
doi.set(doi.disputeClockExtension.selector, disputeClockExtension);
doi.set(doi.disputeMaxClockDuration.selector, disputeMaxClockDuration);
}
} }
contract DeployOPChain_Test_Interop is DeployOPChain_Test { contract DeployOPChain_Test_Interop is DeployOPChain_Test {
......
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