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
} }
......
...@@ -38,12 +38,13 @@ type DeployOPChainInput struct { ...@@ -38,12 +38,13 @@ type DeployOPChainInput struct {
SaltMixer string SaltMixer string
GasLimit uint64 GasLimit uint64
DisputeGameType uint32 DisputeGameType uint32
DisputeAbsolutePrestate common.Hash DisputeAbsolutePrestate common.Hash
DisputeMaxGameDepth uint64 DisputeMaxGameDepth uint64
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,27 +180,54 @@ func DeployOPChainGenesisStrategy(env *Env, intent *state.Intent, st *state.Stat ...@@ -171,27 +180,54 @@ 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 {
return opcm.DeployOPChainInput{ DisputeGameType uint32 `json:"disputeGameType" toml:"disputeGameType"`
OpChainProxyAdminOwner: thisIntent.Roles.L1ProxyAdminOwner, DisputeAbsolutePrestate common.Hash `json:"disputeAbsolutePrestate" toml:"disputeAbsolutePrestate"`
SystemConfigOwner: thisIntent.Roles.SystemConfigOwner, DisputeMaxGameDepth uint64 `json:"disputeMaxGameDepth" toml:"disputeMaxGameDepth"`
Batcher: thisIntent.Roles.Batcher, DisputeSplitDepth uint64 `json:"disputeSplitDepth" toml:"disputeSplitDepth"`
UnsafeBlockSigner: thisIntent.Roles.UnsafeBlockSigner, DisputeClockExtension uint64 `json:"disputeClockExtension" toml:"disputeClockExtension"`
Proposer: thisIntent.Roles.Proposer, DisputeMaxClockDuration uint64 `json:"disputeMaxClockDuration" toml:"disputeMaxClockDuration"`
Challenger: thisIntent.Roles.Challenger, DangerouslyAllowCustomDisputeParameters bool `json:"dangerouslyAllowCustomDisputeParameters" toml:"dangerouslyAllowCustomDisputeParameters"`
BasefeeScalar: 1368, }
BlobBaseFeeScalar: 801949,
L2ChainId: chainID.Big(), func makeDCI(intent *state.Intent, thisIntent *state.ChainIntent, chainID common.Hash, st *state.State) (opcm.DeployOPChainInput, error) {
OpcmProxy: st.ImplementationsDeployment.OpcmProxyAddress, proofParams, err := jsonutil.MergeJSON(
SaltMixer: st.Create2Salt.String(), // passing through salt generated at state initialization ChainProofParams{
GasLimit: 60_000_000, DisputeGameType: standard.DisputeGameType,
DisputeGameType: 1, // PERMISSIONED_CANNON Game Type DisputeAbsolutePrestate: standard.DisputeAbsolutePrestate,
DisputeAbsolutePrestate: common.HexToHash("0x038512e02c4c3f7bdaec27d00edf55b7155e0905301e1a88083e4e0a6764d54c"), DisputeMaxGameDepth: standard.DisputeMaxGameDepth,
DisputeMaxGameDepth: 73, DisputeSplitDepth: standard.DisputeSplitDepth,
DisputeSplitDepth: 30, DisputeClockExtension: standard.DisputeClockExtension,
DisputeClockExtension: 10800, // 3 hours (input in seconds) DisputeMaxClockDuration: standard.DisputeMaxClockDuration,
DisputeMaxClockDuration: 302400, // 3.5 days (input in seconds) },
intent.GlobalDeployOverrides,
thisIntent.DeployOverrides,
)
if err != nil {
return opcm.DeployOPChainInput{}, fmt.Errorf("error merging proof params from overrides: %w", err)
} }
return opcm.DeployOPChainInput{
OpChainProxyAdminOwner: thisIntent.Roles.L1ProxyAdminOwner,
SystemConfigOwner: thisIntent.Roles.SystemConfigOwner,
Batcher: thisIntent.Roles.Batcher,
UnsafeBlockSigner: thisIntent.Roles.UnsafeBlockSigner,
Proposer: thisIntent.Roles.Proposer,
Challenger: thisIntent.Roles.Challenger,
BasefeeScalar: standard.BasefeeScalar,
BlobBaseFeeScalar: standard.BlobBaseFeeScalar,
L2ChainId: chainID.Big(),
OpcmProxy: st.ImplementationsDeployment.OpcmProxyAddress,
SaltMixer: st.Create2Salt.String(), // passing through salt generated at state initialization
GasLimit: standard.GasLimit,
DisputeGameType: proofParams.DisputeGameType,
DisputeAbsolutePrestate: proofParams.DisputeAbsolutePrestate,
DisputeMaxGameDepth: proofParams.DisputeMaxGameDepth,
DisputeSplitDepth: proofParams.DisputeSplitDepth,
DisputeClockExtension: proofParams.DisputeClockExtension, // 3 hours (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