Commit c8f4b3a0 authored by Sam Stokes's avatar Sam Stokes Committed by GitHub

op-deployer: add intent-config-type (#12970)

* op-deployer: add config-intent-type

* op-deployer: revert name change of GasLimit

* op-deployer: add Intent.setStandardValues and Intent.validateStandardValues

* op-deployer: improve standard intent-config err messages

* op-deployr: chain intent custom err types

* op-deployer: add unit test for inent.validateStandardValues

* linter fix

* add intent-config-type custom

* add intent-config-type strict

* add intent-config-type standard-overrides,strict-overrides

* refactor intent.ConfigType validation methods, add intent NewIntent* funcs

* add TestValidateCustomValues, refactor contract tag check

* remove duplicate chainIntent.Check() code

* fix SuperchainRoles.ProxyAdminOwner for standard chains
parent 91099581
...@@ -141,6 +141,9 @@ func ApplyPipeline( ...@@ -141,6 +141,9 @@ func ApplyPipeline(
opts ApplyPipelineOpts, opts ApplyPipelineOpts,
) error { ) error {
intent := opts.Intent intent := opts.Intent
if err := intent.Check(); err != nil {
return err
}
st := opts.State st := opts.State
progressor := func(curr, total int64) { progressor := func(curr, total int64) {
......
...@@ -70,11 +70,7 @@ func (a *Locator) MarshalText() ([]byte, error) { ...@@ -70,11 +70,7 @@ func (a *Locator) MarshalText() ([]byte, error) {
return []byte(a.URL.String()), nil return []byte(a.URL.String()), nil
} }
if a.Tag != "" { return []byte("tag://" + a.Tag), nil
return []byte("tag://" + a.Tag), nil
}
return nil, fmt.Errorf("no URL, path or tag set")
} }
func (a *Locator) IsTag() bool { func (a *Locator) IsTag() bool {
......
...@@ -20,6 +20,7 @@ const ( ...@@ -20,6 +20,7 @@ const (
OutdirFlagName = "outdir" OutdirFlagName = "outdir"
PrivateKeyFlagName = "private-key" PrivateKeyFlagName = "private-key"
DeploymentStrategyFlagName = "deployment-strategy" DeploymentStrategyFlagName = "deployment-strategy"
IntentConfigTypeFlagName = "intent-config-type"
) )
var ( var (
...@@ -35,7 +36,7 @@ var ( ...@@ -35,7 +36,7 @@ var (
Name: L1ChainIDFlagName, Name: L1ChainIDFlagName,
Usage: "Chain ID of the L1 chain.", Usage: "Chain ID of the L1 chain.",
EnvVars: PrefixEnvVar("L1_CHAIN_ID"), EnvVars: PrefixEnvVar("L1_CHAIN_ID"),
Value: 900, Value: 11155111,
} }
L2ChainIDsFlag = &cli.StringFlag{ L2ChainIDsFlag = &cli.StringFlag{
Name: L2ChainIDsFlagName, Name: L2ChainIDsFlagName,
...@@ -62,6 +63,17 @@ var ( ...@@ -62,6 +63,17 @@ var (
EnvVars: PrefixEnvVar("DEPLOYMENT_STRATEGY"), EnvVars: PrefixEnvVar("DEPLOYMENT_STRATEGY"),
Value: string(state.DeploymentStrategyLive), Value: string(state.DeploymentStrategyLive),
} }
IntentConfigTypeFlag = &cli.StringFlag{
Name: IntentConfigTypeFlagName,
Usage: fmt.Sprintf("Intent config type to use. Options: %s (default), %s, %s, %s, %s",
state.IntentConfigTypeStandard,
state.IntentConfigTypeCustom,
state.IntentConfigTypeStrict,
state.IntentConfigTypeStandardOverrides,
state.IntentConfigTypeStrictOverrides),
EnvVars: PrefixEnvVar("INTENT_CONFIG_TYPE"),
Value: string(state.IntentConfigTypeStandard),
}
) )
var GlobalFlags = append([]cli.Flag{}, oplog.CLIFlags(EnvVarPrefix)...) var GlobalFlags = append([]cli.Flag{}, oplog.CLIFlags(EnvVarPrefix)...)
...@@ -71,6 +83,7 @@ var InitFlags = []cli.Flag{ ...@@ -71,6 +83,7 @@ var InitFlags = []cli.Flag{
L2ChainIDsFlag, L2ChainIDsFlag,
WorkdirFlag, WorkdirFlag,
DeploymentStrategyFlag, DeploymentStrategyFlag,
IntentConfigTypeFlag,
} }
var ApplyFlags = []cli.Flag{ var ApplyFlags = []cli.Flag{
......
...@@ -7,19 +7,17 @@ import ( ...@@ -7,19 +7,17 @@ import (
"path" "path"
"strings" "strings"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"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"
"github.com/ethereum-optimism/optimism/op-chain-ops/devkeys"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
type InitConfig struct { type InitConfig struct {
DeploymentStrategy state.DeploymentStrategy DeploymentStrategy state.DeploymentStrategy
IntentConfigType state.IntentConfigType
L1ChainID uint64 L1ChainID uint64
Outdir string Outdir string
L2ChainIDs []common.Hash L2ChainIDs []common.Hash
...@@ -51,6 +49,7 @@ func InitCLI() func(ctx *cli.Context) error { ...@@ -51,6 +49,7 @@ func InitCLI() func(ctx *cli.Context) error {
l1ChainID := ctx.Uint64(L1ChainIDFlagName) l1ChainID := ctx.Uint64(L1ChainIDFlagName)
outdir := ctx.String(OutdirFlagName) outdir := ctx.String(OutdirFlagName)
l2ChainIDsRaw := ctx.String(L2ChainIDsFlagName) l2ChainIDsRaw := ctx.String(L2ChainIDsFlagName)
intentConfigType := ctx.String(IntentConfigTypeFlagName)
if len(l2ChainIDsRaw) == 0 { if len(l2ChainIDsRaw) == 0 {
return fmt.Errorf("must specify at least one L2 chain ID") return fmt.Errorf("must specify at least one L2 chain ID")
...@@ -68,6 +67,7 @@ func InitCLI() func(ctx *cli.Context) error { ...@@ -68,6 +67,7 @@ func InitCLI() func(ctx *cli.Context) error {
err := Init(InitConfig{ err := Init(InitConfig{
DeploymentStrategy: state.DeploymentStrategy(deploymentStrategy), DeploymentStrategy: state.DeploymentStrategy(deploymentStrategy),
IntentConfigType: state.IntentConfigType(intentConfigType),
L1ChainID: l1ChainID, L1ChainID: l1ChainID,
Outdir: outdir, Outdir: outdir,
L2ChainIDs: l2ChainIDs, L2ChainIDs: l2ChainIDs,
...@@ -86,55 +86,12 @@ func Init(cfg InitConfig) error { ...@@ -86,55 +86,12 @@ func Init(cfg InitConfig) error {
return fmt.Errorf("invalid config for init: %w", err) return fmt.Errorf("invalid config for init: %w", err)
} }
intent := &state.Intent{ intent, err := state.NewIntent(cfg.IntentConfigType, cfg.DeploymentStrategy, cfg.L1ChainID, cfg.L2ChainIDs)
DeploymentStrategy: cfg.DeploymentStrategy,
L1ChainID: cfg.L1ChainID,
FundDevAccounts: true,
L1ContractsLocator: artifacts.DefaultL1ContractsLocator,
L2ContractsLocator: artifacts.DefaultL2ContractsLocator,
}
l1ChainIDBig := intent.L1ChainIDBig()
dk, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic)
if err != nil { if err != nil {
return fmt.Errorf("failed to create dev keys: %w", err) return err
}
addrFor := func(key devkeys.Key) common.Address {
// The error below should never happen, so panic if it does.
addr, err := dk.Address(key)
if err != nil {
panic(err)
}
return addr
}
intent.SuperchainRoles = &state.SuperchainRoles{
ProxyAdminOwner: addrFor(devkeys.L1ProxyAdminOwnerRole.Key(l1ChainIDBig)),
ProtocolVersionsOwner: addrFor(devkeys.SuperchainProtocolVersionsOwner.Key(l1ChainIDBig)),
Guardian: addrFor(devkeys.SuperchainConfigGuardianKey.Key(l1ChainIDBig)),
}
for _, l2ChainID := range cfg.L2ChainIDs {
l2ChainIDBig := l2ChainID.Big()
intent.Chains = append(intent.Chains, &state.ChainIntent{
ID: l2ChainID,
BaseFeeVaultRecipient: addrFor(devkeys.BaseFeeVaultRecipientRole.Key(l2ChainIDBig)),
L1FeeVaultRecipient: addrFor(devkeys.L1FeeVaultRecipientRole.Key(l2ChainIDBig)),
SequencerFeeVaultRecipient: addrFor(devkeys.SequencerFeeVaultRecipientRole.Key(l2ChainIDBig)),
Eip1559Denominator: 50,
Eip1559Elasticity: 6,
Roles: state.ChainRoles{
L1ProxyAdminOwner: addrFor(devkeys.L1ProxyAdminOwnerRole.Key(l2ChainIDBig)),
L2ProxyAdminOwner: addrFor(devkeys.L2ProxyAdminOwnerRole.Key(l2ChainIDBig)),
SystemConfigOwner: addrFor(devkeys.SystemConfigOwner.Key(l2ChainIDBig)),
UnsafeBlockSigner: addrFor(devkeys.SequencerP2PRole.Key(l2ChainIDBig)),
Batcher: addrFor(devkeys.BatcherRole.Key(l2ChainIDBig)),
Proposer: addrFor(devkeys.ProposerRole.Key(l2ChainIDBig)),
Challenger: addrFor(devkeys.ChallengerRole.Key(l2ChainIDBig)),
},
})
} }
intent.DeploymentStrategy = cfg.DeploymentStrategy
intent.ConfigType = cfg.IntentConfigType
st := &state.State{ st := &state.State{
Version: 1, Version: 1,
......
...@@ -714,6 +714,7 @@ func newIntent( ...@@ -714,6 +714,7 @@ func newIntent(
l2Loc *artifacts.Locator, l2Loc *artifacts.Locator,
) (*state.Intent, *state.State) { ) (*state.Intent, *state.State) {
intent := &state.Intent{ intent := &state.Intent{
ConfigType: state.IntentConfigTypeCustom,
DeploymentStrategy: state.DeploymentStrategyLive, DeploymentStrategy: state.DeploymentStrategyLive,
L1ChainID: l1ChainID.Uint64(), L1ChainID: l1ChainID.Uint64(),
SuperchainRoles: &state.SuperchainRoles{ SuperchainRoles: &state.SuperchainRoles{
...@@ -740,8 +741,9 @@ func newChainIntent(t *testing.T, dk *devkeys.MnemonicDevKeys, l1ChainID *big.In ...@@ -740,8 +741,9 @@ func newChainIntent(t *testing.T, dk *devkeys.MnemonicDevKeys, l1ChainID *big.In
BaseFeeVaultRecipient: addrFor(t, dk, devkeys.BaseFeeVaultRecipientRole.Key(l1ChainID)), BaseFeeVaultRecipient: addrFor(t, dk, devkeys.BaseFeeVaultRecipientRole.Key(l1ChainID)),
L1FeeVaultRecipient: addrFor(t, dk, devkeys.L1FeeVaultRecipientRole.Key(l1ChainID)), L1FeeVaultRecipient: addrFor(t, dk, devkeys.L1FeeVaultRecipientRole.Key(l1ChainID)),
SequencerFeeVaultRecipient: addrFor(t, dk, devkeys.SequencerFeeVaultRecipientRole.Key(l1ChainID)), SequencerFeeVaultRecipient: addrFor(t, dk, devkeys.SequencerFeeVaultRecipientRole.Key(l1ChainID)),
Eip1559Denominator: 50, Eip1559DenominatorCanyon: standard.Eip1559DenominatorCanyon,
Eip1559Elasticity: 6, Eip1559Denominator: standard.Eip1559Denominator,
Eip1559Elasticity: standard.Eip1559Elasticity,
Roles: state.ChainRoles{ Roles: state.ChainRoles{
L1ProxyAdminOwner: addrFor(t, dk, devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)), L1ProxyAdminOwner: addrFor(t, dk, devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)),
L2ProxyAdminOwner: addrFor(t, dk, devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)), L2ProxyAdminOwner: addrFor(t, dk, devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)),
......
...@@ -141,10 +141,10 @@ func displayWarning() error { ...@@ -141,10 +141,10 @@ func displayWarning() error {
####################### WARNING! WARNING WARNING! ####################### ####################### WARNING! WARNING WARNING! #######################
You are deploying a tagged release to a chain with no pre-deployed OPCM. You are deploying a tagged release to a chain with no pre-deployed OPCM.
The contracts you are deploying may not be audited, or match a governance The contracts you are deploying may not be audited, or match a governance
approved release. approved release.
USE OF THIS DEPLOYMENT IS NOT RECOMMENDED FOR PRODUCTION. USE AT YOUR OWN USE OF THIS DEPLOYMENT IS NOT RECOMMENDED FOR PRODUCTION. USE AT YOUR OWN
RISK. BUGS OR LOSS OF FUNDS MAY OCCUR. WE HOPE YOU KNOW WHAT YOU ARE RISK. BUGS OR LOSS OF FUNDS MAY OCCUR. WE HOPE YOU KNOW WHAT YOU ARE
DOING. DOING.
......
...@@ -26,6 +26,9 @@ const ( ...@@ -26,6 +26,9 @@ const (
DisputeSplitDepth uint64 = 30 DisputeSplitDepth uint64 = 30
DisputeClockExtension uint64 = 10800 DisputeClockExtension uint64 = 10800
DisputeMaxClockDuration uint64 = 302400 DisputeMaxClockDuration uint64 = 302400
Eip1559DenominatorCanyon uint64 = 250
Eip1559Denominator uint64 = 50
Eip1559Elasticity uint64 = 6
ContractsV160Tag = "op-contracts/v1.6.0" ContractsV160Tag = "op-contracts/v1.6.0"
ContractsV170Beta1L2Tag = "op-contracts/v1.7.0-beta.1+l2-contracts" ContractsV170Beta1L2Tag = "op-contracts/v1.7.0-beta.1+l2-contracts"
...@@ -97,6 +100,28 @@ func L1VersionsFor(chainID uint64) (L1Versions, error) { ...@@ -97,6 +100,28 @@ func L1VersionsFor(chainID uint64) (L1Versions, error) {
} }
} }
func GuardianAddressFor(chainID uint64) (common.Address, error) {
switch chainID {
case 1:
return common.HexToAddress("0x09f7150D8c019BeF34450d6920f6B3608ceFdAf2"), nil
case 11155111:
return common.HexToAddress("0x7a50f00e8D05b95F98fE38d8BeE366a7324dCf7E"), nil
default:
return common.Address{}, fmt.Errorf("unsupported chain ID: %d", chainID)
}
}
func ChallengerAddressFor(chainID uint64) (common.Address, error) {
switch chainID {
case 1:
return common.HexToAddress("0x9BA6e03D8B90dE867373Db8cF1A58d2F7F006b3A"), nil
case 11155111:
return common.HexToAddress("0xfd1D2e729aE8eEe2E146c033bf4400fE75284301"), nil
default:
return common.Address{}, fmt.Errorf("unsupported chain ID: %d", chainID)
}
}
func SuperchainFor(chainID uint64) (*superchain.Superchain, error) { func SuperchainFor(chainID uint64) (*superchain.Superchain, error) {
switch chainID { switch chainID {
case 1: case 1:
...@@ -115,7 +140,7 @@ func ChainNameFor(chainID uint64) (string, error) { ...@@ -115,7 +140,7 @@ func ChainNameFor(chainID uint64) (string, error) {
case 11155111: case 11155111:
return "sepolia", nil return "sepolia", nil
default: default:
return "", fmt.Errorf("unrecognized chain ID: %d", chainID) return "", fmt.Errorf("unrecognized l1 chain ID: %d", chainID)
} }
} }
...@@ -173,6 +198,17 @@ func SystemOwnerAddrFor(chainID uint64) (common.Address, error) { ...@@ -173,6 +198,17 @@ func SystemOwnerAddrFor(chainID uint64) (common.Address, error) {
} }
} }
func L1ProxyAdminOwner(chainID uint64) (common.Address, error) {
switch chainID {
case 1:
return common.HexToAddress("0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A"), nil
case 11155111:
return common.HexToAddress("0x1Eb2fFc903729a0F03966B917003800b145F56E2"), nil
default:
return common.Address{}, fmt.Errorf("unsupported chain ID: %d", chainID)
}
}
func ArtifactsURLForTag(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":
......
package state
import (
"fmt"
"reflect"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum/go-ethereum/common"
)
type ChainIntent struct {
ID common.Hash `json:"id" toml:"id"`
BaseFeeVaultRecipient common.Address `json:"baseFeeVaultRecipient" toml:"baseFeeVaultRecipient"`
L1FeeVaultRecipient common.Address `json:"l1FeeVaultRecipient" toml:"l1FeeVaultRecipient"`
SequencerFeeVaultRecipient common.Address `json:"sequencerFeeVaultRecipient" toml:"sequencerFeeVaultRecipient"`
Eip1559DenominatorCanyon uint64 `json:"eip1559DenominatorCanyon" toml:"eip1559DenominatorCanyon"`
Eip1559Denominator uint64 `json:"eip1559Denominator" toml:"eip1559Denominator"`
Eip1559Elasticity uint64 `json:"eip1559Elasticity" toml:"eip1559Elasticity"`
Roles ChainRoles `json:"roles" toml:"roles"`
DeployOverrides map[string]any `json:"deployOverrides" toml:"deployOverrides"`
DangerousAltDAConfig genesis.AltDADeployConfig `json:"dangerousAltDAConfig,omitempty" toml:"dangerousAltDAConfig,omitempty"`
}
type ChainRoles struct {
L1ProxyAdminOwner common.Address `json:"l1ProxyAdminOwner" toml:"l1ProxyAdminOwner"`
L2ProxyAdminOwner common.Address `json:"l2ProxyAdminOwner" toml:"l2ProxyAdminOwner"`
SystemConfigOwner common.Address `json:"systemConfigOwner" toml:"systemConfigOwner"`
UnsafeBlockSigner common.Address `json:"unsafeBlockSigner" toml:"unsafeBlockSigner"`
Batcher common.Address `json:"batcher" toml:"batcher"`
Proposer common.Address `json:"proposer" toml:"proposer"`
Challenger common.Address `json:"challenger" toml:"challenger"`
}
var ErrChainRoleZeroAddress = fmt.Errorf("ChainRole is set to zero address")
var ErrFeeVaultZeroAddress = fmt.Errorf("chain has a fee vault set to zero address")
var ErrNonStandardValue = fmt.Errorf("chain contains non-standard config value")
var ErrEip1559ZeroValue = fmt.Errorf("eip1559 param is set to zero value")
func (c *ChainIntent) Check() error {
if c.ID == emptyHash {
return fmt.Errorf("id must be set")
}
if err := c.Roles.CheckNoZeroAddresses(); err != nil {
return err
}
if c.Eip1559DenominatorCanyon == 0 ||
c.Eip1559Denominator == 0 ||
c.Eip1559Elasticity == 0 {
return fmt.Errorf("%w: chainId=%s", ErrEip1559ZeroValue, c.ID)
}
if c.BaseFeeVaultRecipient == emptyAddress ||
c.L1FeeVaultRecipient == emptyAddress ||
c.SequencerFeeVaultRecipient == emptyAddress {
return fmt.Errorf("%w: chainId=%s", ErrFeeVaultZeroAddress, c.ID)
}
if c.DangerousAltDAConfig.UseAltDA {
return c.DangerousAltDAConfig.Check(nil)
}
return nil
}
// Returns an error if any fields in ChainRoles is set to common.Address{}
func (cr *ChainRoles) CheckNoZeroAddresses() error {
val := reflect.ValueOf(*cr)
typ := reflect.TypeOf(*cr)
// Iterate through all the fields
for i := 0; i < val.NumField(); i++ {
fieldValue := val.Field(i)
fieldName := typ.Field(i).Name
if fieldValue.Interface() == (common.Address{}) {
return fmt.Errorf("%w: %s", ErrChainRoleZeroAddress, fieldName)
}
}
return nil
}
This diff is collapsed.
package state
import (
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
func TestValidateStandardValues(t *testing.T) {
intent, err := NewIntentStandard(DeploymentStrategyLive, 1, []common.Hash{common.HexToHash("0x336")})
require.NoError(t, err)
err = intent.Check()
require.Error(t, err)
require.ErrorIs(t, err, ErrChainRoleZeroAddress)
setChainRoles(&intent)
err = intent.Check()
require.Error(t, err)
require.ErrorIs(t, err, ErrFeeVaultZeroAddress)
setFeeAddresses(&intent)
err = intent.Check()
require.NoError(t, err)
intent.Chains[0].Eip1559Denominator = 3 // set to non-standard value
err = intent.Check()
require.Error(t, err)
require.ErrorIs(t, err, ErrNonStandardValue)
}
func TestValidateCustomValues(t *testing.T) {
intent, err := NewIntentCustom(DeploymentStrategyLive, 1, []common.Hash{common.HexToHash("0x336")})
require.NoError(t, err)
err = intent.Check()
require.Error(t, err)
require.ErrorIs(t, err, ErrSuperchainRoleZeroAddress)
setSuperchainRoles(&intent)
err = intent.Check()
require.Error(t, err)
require.ErrorIs(t, err, ErrChainRoleZeroAddress)
setChainRoles(&intent)
err = intent.Check()
require.Error(t, err)
require.ErrorIs(t, err, ErrEip1559ZeroValue)
setEip1559Params(&intent)
err = intent.Check()
require.Error(t, err)
require.ErrorIs(t, err, ErrFeeVaultZeroAddress)
setFeeAddresses(&intent)
err = intent.Check()
require.NoError(t, err)
}
func setSuperchainRoles(intent *Intent) {
intent.SuperchainRoles = &SuperchainRoles{
ProxyAdminOwner: common.HexToAddress("0xa"),
ProtocolVersionsOwner: common.HexToAddress("0xb"),
Guardian: common.HexToAddress("0xc"),
}
}
func setEip1559Params(intent *Intent) {
intent.Chains[0].Eip1559Denominator = 5000
intent.Chains[0].Eip1559DenominatorCanyon = 5000
intent.Chains[0].Eip1559Elasticity = 5000
}
func setChainRoles(intent *Intent) {
intent.Chains[0].Roles.L1ProxyAdminOwner = common.HexToAddress("0x01")
intent.Chains[0].Roles.L2ProxyAdminOwner = common.HexToAddress("0x02")
intent.Chains[0].Roles.SystemConfigOwner = common.HexToAddress("0x03")
intent.Chains[0].Roles.UnsafeBlockSigner = common.HexToAddress("0x04")
intent.Chains[0].Roles.Batcher = common.HexToAddress("0x05")
intent.Chains[0].Roles.Proposer = common.HexToAddress("0x06")
intent.Chains[0].Roles.Challenger = common.HexToAddress("0x07")
}
func setFeeAddresses(intent *Intent) {
intent.Chains[0].BaseFeeVaultRecipient = common.HexToAddress("0x08")
intent.Chains[0].L1FeeVaultRecipient = common.HexToAddress("0x09")
intent.Chains[0].SequencerFeeVaultRecipient = common.HexToAddress("0x0A")
}
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