Commit 4cd07f52 authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

op-deployer: Add support for dumping calldata (#13680)

* op-deployer: Add support for dumping calldata

* Update state.go
parent fdb7edd6
...@@ -32,10 +32,11 @@ import ( ...@@ -32,10 +32,11 @@ import (
) )
type ApplyConfig struct { type ApplyConfig struct {
L1RPCUrl string L1RPCUrl string
Workdir string Workdir string
PrivateKey string PrivateKey string
Logger log.Logger DeploymentTarget DeploymentTarget
Logger log.Logger
privateKeyECDSA *ecdsa.PrivateKey privateKeyECDSA *ecdsa.PrivateKey
} }
...@@ -57,16 +58,14 @@ func (a *ApplyConfig) Check() error { ...@@ -57,16 +58,14 @@ func (a *ApplyConfig) Check() error {
return fmt.Errorf("logger must be specified") return fmt.Errorf("logger must be specified")
} }
return nil if a.DeploymentTarget == DeploymentTargetLive {
} if a.L1RPCUrl == "" {
return fmt.Errorf("l1 RPC URL must be specified for live deployment")
func (a *ApplyConfig) CheckLive() error { }
if a.privateKeyECDSA == nil {
return fmt.Errorf("private key must be specified")
}
if a.L1RPCUrl == "" { if a.privateKeyECDSA == nil {
return fmt.Errorf("l1RPCUrl must be specified") return fmt.Errorf("private key must be specified for live deployment")
}
} }
return nil return nil
...@@ -81,14 +80,19 @@ func ApplyCLI() func(cliCtx *cli.Context) error { ...@@ -81,14 +80,19 @@ func ApplyCLI() func(cliCtx *cli.Context) error {
l1RPCUrl := cliCtx.String(L1RPCURLFlagName) l1RPCUrl := cliCtx.String(L1RPCURLFlagName)
workdir := cliCtx.String(WorkdirFlagName) workdir := cliCtx.String(WorkdirFlagName)
privateKey := cliCtx.String(PrivateKeyFlagName) privateKey := cliCtx.String(PrivateKeyFlagName)
depTarget, err := NewDeploymentTarget(cliCtx.String(DeploymentTargetFlag.Name))
if err != nil {
return fmt.Errorf("failed to parse deployment target: %w", err)
}
ctx := ctxinterrupt.WithCancelOnInterrupt(cliCtx.Context) ctx := ctxinterrupt.WithCancelOnInterrupt(cliCtx.Context)
return Apply(ctx, ApplyConfig{ return Apply(ctx, ApplyConfig{
L1RPCUrl: l1RPCUrl, L1RPCUrl: l1RPCUrl,
Workdir: workdir, Workdir: workdir,
PrivateKey: privateKey, PrivateKey: privateKey,
Logger: l, DeploymentTarget: depTarget,
Logger: l,
}) })
} }
} }
...@@ -110,6 +114,7 @@ func Apply(ctx context.Context, cfg ApplyConfig) error { ...@@ -110,6 +114,7 @@ func Apply(ctx context.Context, cfg ApplyConfig) error {
if err := ApplyPipeline(ctx, ApplyPipelineOpts{ if err := ApplyPipeline(ctx, ApplyPipelineOpts{
L1RPCUrl: cfg.L1RPCUrl, L1RPCUrl: cfg.L1RPCUrl,
DeploymentTarget: cfg.DeploymentTarget,
DeployerPrivateKey: cfg.privateKeyECDSA, DeployerPrivateKey: cfg.privateKeyECDSA,
Intent: intent, Intent: intent,
State: st, State: st,
...@@ -129,6 +134,7 @@ type pipelineStage struct { ...@@ -129,6 +134,7 @@ type pipelineStage struct {
type ApplyPipelineOpts struct { type ApplyPipelineOpts struct {
L1RPCUrl string L1RPCUrl string
DeploymentTarget DeploymentTarget
DeployerPrivateKey *ecdsa.PrivateKey DeployerPrivateKey *ecdsa.PrivateKey
Intent *state.Intent Intent *state.Intent
State *state.State State *state.State
...@@ -187,34 +193,11 @@ func ApplyPipeline( ...@@ -187,34 +193,11 @@ func ApplyPipeline(
} }
var bcaster broadcaster.Broadcaster var bcaster broadcaster.Broadcaster
var l1RPC *rpc.Client
var l1Client *ethclient.Client var l1Client *ethclient.Client
var l1Host *script.Host var l1Host *script.Host
if intent.DeploymentStrategy == state.DeploymentStrategyLive {
l1RPC, err := rpc.Dial(opts.L1RPCUrl)
if err != nil {
return fmt.Errorf("failed to connect to L1 RPC: %w", err)
}
l1Client = ethclient.NewClient(l1RPC)
chainID, err := l1Client.ChainID(ctx)
if err != nil {
return fmt.Errorf("failed to get chain ID: %w", err)
}
signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(opts.DeployerPrivateKey, chainID))
bcaster, err = broadcaster.NewKeyedBroadcaster(broadcaster.KeyedBroadcasterOpts{
Logger: opts.Logger,
ChainID: new(big.Int).SetUint64(intent.L1ChainID),
Client: l1Client,
Signer: signer,
From: deployer,
})
if err != nil {
return fmt.Errorf("failed to create broadcaster: %w", err)
}
initForkHost := func() error {
l1Host, err = env.DefaultScriptHost( l1Host, err = env.DefaultScriptHost(
bcaster, bcaster,
opts.Logger, opts.Logger,
...@@ -243,7 +226,54 @@ func ApplyPipeline( ...@@ -243,7 +226,54 @@ func ApplyPipeline(
); err != nil { ); err != nil {
return fmt.Errorf("failed to select fork: %w", err) return fmt.Errorf("failed to select fork: %w", err)
} }
} else {
return nil
}
switch opts.DeploymentTarget {
case DeploymentTargetLive:
l1RPC, err = rpc.Dial(opts.L1RPCUrl)
if err != nil {
return fmt.Errorf("failed to connect to L1 RPC: %w", err)
}
l1Client = ethclient.NewClient(l1RPC)
chainID, err := l1Client.ChainID(ctx)
if err != nil {
return fmt.Errorf("failed to get chain ID: %w", err)
}
signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(opts.DeployerPrivateKey, chainID))
bcaster, err = broadcaster.NewKeyedBroadcaster(broadcaster.KeyedBroadcasterOpts{
Logger: opts.Logger,
ChainID: new(big.Int).SetUint64(intent.L1ChainID),
Client: l1Client,
Signer: signer,
From: deployer,
})
if err != nil {
return fmt.Errorf("failed to create broadcaster: %w", err)
}
if err := initForkHost(); err != nil {
return fmt.Errorf("failed to initialize L1 host: %w", err)
}
case DeploymentTargetCalldata, DeploymentTargetNoop:
l1RPC, err = rpc.Dial(opts.L1RPCUrl)
if err != nil {
return fmt.Errorf("failed to connect to L1 RPC: %w", err)
}
l1Client = ethclient.NewClient(l1RPC)
bcaster = new(broadcaster.CalldataBroadcaster)
if err := initForkHost(); err != nil {
return fmt.Errorf("failed to initialize L1 host: %w", err)
}
case DeploymentTargetGenesis:
bcaster = broadcaster.NoopBroadcaster() bcaster = broadcaster.NoopBroadcaster()
l1Host, err = env.DefaultScriptHost( l1Host, err = env.DefaultScriptHost(
bcaster, bcaster,
...@@ -254,6 +284,8 @@ func ApplyPipeline( ...@@ -254,6 +284,8 @@ func ApplyPipeline(
if err != nil { if err != nil {
return fmt.Errorf("failed to create L1 script host: %w", err) return fmt.Errorf("failed to create L1 script host: %w", err)
} }
default:
return fmt.Errorf("invalid deployment target: '%s'", opts.DeploymentTarget)
} }
pEnv := &pipeline.Env{ pEnv := &pipeline.Env{
...@@ -267,11 +299,10 @@ func ApplyPipeline( ...@@ -267,11 +299,10 @@ func ApplyPipeline(
pline := []pipelineStage{ pline := []pipelineStage{
{"init", func() error { {"init", func() error {
if intent.DeploymentStrategy == state.DeploymentStrategyLive { if opts.DeploymentTarget == DeploymentTargetGenesis {
return pipeline.InitLiveStrategy(ctx, pEnv, intent, st)
} else {
return pipeline.InitGenesisStrategy(pEnv, intent, st) return pipeline.InitGenesisStrategy(pEnv, intent, st)
} }
return pipeline.InitLiveStrategy(ctx, pEnv, intent, st)
}}, }},
{"deploy-superchain", func() error { {"deploy-superchain", func() error {
return pipeline.DeploySuperchain(pEnv, intent, st) return pipeline.DeploySuperchain(pEnv, intent, st)
...@@ -314,23 +345,22 @@ func ApplyPipeline( ...@@ -314,23 +345,22 @@ func ApplyPipeline(
pline = append(pline, pipelineStage{ pline = append(pline, pipelineStage{
fmt.Sprintf("set-start-block-%s", chainID.Hex()), fmt.Sprintf("set-start-block-%s", chainID.Hex()),
func() error { func() error {
if intent.DeploymentStrategy == state.DeploymentStrategyLive { if opts.DeploymentTarget == DeploymentTargetGenesis {
return pipeline.SetStartBlockLiveStrategy(ctx, pEnv, st, chainID)
} else {
return pipeline.SetStartBlockGenesisStrategy(pEnv, st, chainID) return pipeline.SetStartBlockGenesisStrategy(pEnv, st, chainID)
} }
return pipeline.SetStartBlockLiveStrategy(ctx, pEnv, st, chainID)
}, },
}) })
} }
// Run through the pipeline. The state dump is captured between // Run through the pipeline.
// every step.
for _, stage := range pline { for _, stage := range pline {
if err := stage.apply(); err != nil { if err := stage.apply(); err != nil {
return fmt.Errorf("error in pipeline stage apply: %w", err) return fmt.Errorf("error in pipeline stage apply: %w", err)
} }
if intent.DeploymentStrategy == state.DeploymentStrategyGenesis { // Some steps use the L1StateDump, so we need to apply it to state after every step.
if opts.DeploymentTarget == DeploymentTargetGenesis {
dump, err := pEnv.L1ScriptHost.StateDump() dump, err := pEnv.L1ScriptHost.StateDump()
if err != nil { if err != nil {
return fmt.Errorf("failed to dump state: %w", err) return fmt.Errorf("failed to dump state: %w", err)
...@@ -348,6 +378,14 @@ func ApplyPipeline( ...@@ -348,6 +378,14 @@ func ApplyPipeline(
} }
} }
if opts.DeploymentTarget == DeploymentTargetCalldata {
cdCaster := pEnv.Broadcaster.(*broadcaster.CalldataBroadcaster)
st.DeploymentCalldata, err = cdCaster.Dump()
if err != nil {
return fmt.Errorf("failed to dump calldata: %w", err)
}
}
st.AppliedIntent = intent st.AppliedIntent = intent
if err := pEnv.StateWriter.WriteState(st); err != nil { if err := pEnv.StateWriter.WriteState(st); err != nil {
return fmt.Errorf("failed to write state: %w", err) return fmt.Errorf("failed to write state: %w", err)
......
package broadcaster
import (
"context"
"sync"
"github.com/ethereum-optimism/optimism/op-chain-ops/script"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
const defaultGasLimit = 30_000_000
type CalldataDump struct {
To *common.Address
Data hexutil.Bytes
Value *hexutil.Big
}
type CalldataBroadcaster struct {
txs []txmgr.TxCandidate
mtx sync.Mutex
}
func (d *CalldataBroadcaster) Broadcast(ctx context.Context) ([]BroadcastResult, error) {
return nil, nil
}
func (d *CalldataBroadcaster) Hook(bcast script.Broadcast) {
candidate := asTxCandidate(bcast, defaultGasLimit)
d.mtx.Lock()
d.txs = append(d.txs, candidate)
d.mtx.Unlock()
}
func (d *CalldataBroadcaster) Dump() ([]CalldataDump, error) {
d.mtx.Lock()
defer d.mtx.Unlock()
var out []CalldataDump
for _, tx := range d.txs {
out = append(out, CalldataDump{
To: tx.To,
Value: (*hexutil.Big)(tx.Value),
Data: tx.TxData,
})
}
d.txs = nil
return out, nil
}
package broadcaster
import (
"context"
"testing"
"github.com/ethereum-optimism/optimism/op-chain-ops/script"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/holiman/uint256"
"github.com/stretchr/testify/require"
)
func TestCalldataBroadcaster(t *testing.T) {
bcast := new(CalldataBroadcaster)
bcasts := []script.Broadcast{
{
Type: script.BroadcastCall,
To: common.Address{'1'},
Input: []byte{'D', '1'},
Value: (*hexutil.U256)(new(uint256.Int).SetUint64(123)),
},
{
Type: script.BroadcastCreate,
Input: []byte{'D', '2'},
},
}
for _, b := range bcasts {
bcast.Hook(b)
}
res, err := bcast.Broadcast(context.Background())
require.NoError(t, err)
require.Nil(t, res)
dump, err := bcast.Dump()
require.NoError(t, err)
expValues := make([]CalldataDump, len(bcasts))
for i, b := range bcasts {
var to *common.Address
if b.To != (common.Address{}) {
to = &b.To
}
var value *hexutil.Big
if b.Value != nil {
value = (*hexutil.Big)((*uint256.Int)(b.Value).ToBig())
}
expValues[i] = CalldataDump{
To: to,
Value: value,
Data: b.Input,
}
}
require.EqualValues(t, expValues, dump)
}
...@@ -7,6 +7,8 @@ import ( ...@@ -7,6 +7,8 @@ import (
"sync" "sync"
"time" "time"
"github.com/holiman/uint256"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-chain-ops/script" "github.com/ethereum-optimism/optimism/op-chain-ops/script"
...@@ -18,7 +20,6 @@ import ( ...@@ -18,7 +20,6 @@ import (
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/hashicorp/go-multierror" "github.com/hashicorp/go-multierror"
"github.com/holiman/uint256"
) )
const ( const (
...@@ -184,6 +185,12 @@ func (t *KeyedBroadcaster) broadcast(ctx context.Context, bcast script.Broadcast ...@@ -184,6 +185,12 @@ func (t *KeyedBroadcaster) broadcast(ctx context.Context, bcast script.Broadcast
ch := make(chan txmgr.SendResponse, 1) ch := make(chan txmgr.SendResponse, 1)
id := bcast.ID() id := bcast.ID()
candidate := asTxCandidate(bcast, blockGasLimit)
t.mgr.SendAsync(ctx, candidate, ch)
return ch, id
}
func asTxCandidate(bcast script.Broadcast, blockGasLimit uint64) txmgr.TxCandidate {
value := ((*uint256.Int)(bcast.Value)).ToBig() value := ((*uint256.Int)(bcast.Value)).ToBig()
var candidate txmgr.TxCandidate var candidate txmgr.TxCandidate
switch bcast.Type { switch bcast.Type {
...@@ -212,10 +219,10 @@ func (t *KeyedBroadcaster) broadcast(ctx context.Context, bcast script.Broadcast ...@@ -212,10 +219,10 @@ func (t *KeyedBroadcaster) broadcast(ctx context.Context, bcast script.Broadcast
Value: value, Value: value,
GasLimit: padGasLimit(bcast.Input, bcast.GasUsed, true, blockGasLimit), GasLimit: padGasLimit(bcast.Input, bcast.GasUsed, true, blockGasLimit),
} }
default:
panic(fmt.Sprintf("unrecognized broadcast type: '%s'", bcast.Type))
} }
return candidate
t.mgr.SendAsync(ctx, candidate, ch)
return ch, id
} }
// padGasLimit calculates the gas limit for a transaction based on the intrinsic gas and the gas used by // padGasLimit calculates the gas limit for a transaction based on the intrinsic gas and the gas used by
......
...@@ -12,17 +12,40 @@ import ( ...@@ -12,17 +12,40 @@ import (
) )
const ( const (
EnvVarPrefix = "DEPLOYER" EnvVarPrefix = "DEPLOYER"
L1RPCURLFlagName = "l1-rpc-url" L1RPCURLFlagName = "l1-rpc-url"
L1ChainIDFlagName = "l1-chain-id" L1ChainIDFlagName = "l1-chain-id"
L2ChainIDsFlagName = "l2-chain-ids" L2ChainIDsFlagName = "l2-chain-ids"
WorkdirFlagName = "workdir" WorkdirFlagName = "workdir"
OutdirFlagName = "outdir" OutdirFlagName = "outdir"
PrivateKeyFlagName = "private-key" PrivateKeyFlagName = "private-key"
DeploymentStrategyFlagName = "deployment-strategy" IntentConfigTypeFlagName = "intent-config-type"
IntentConfigTypeFlagName = "intent-config-type"
) )
type DeploymentTarget string
const (
DeploymentTargetLive DeploymentTarget = "live"
DeploymentTargetGenesis DeploymentTarget = "genesis"
DeploymentTargetCalldata DeploymentTarget = "calldata"
DeploymentTargetNoop DeploymentTarget = "noop"
)
func NewDeploymentTarget(s string) (DeploymentTarget, error) {
switch s {
case string(DeploymentTargetLive):
return DeploymentTargetLive, nil
case string(DeploymentTargetGenesis):
return DeploymentTargetGenesis, nil
case string(DeploymentTargetCalldata):
return DeploymentTargetCalldata, nil
case string(DeploymentTargetNoop):
return DeploymentTargetNoop, nil
default:
return "", fmt.Errorf("invalid deployment target: %s", s)
}
}
var ( var (
L1RPCURLFlag = &cli.StringFlag{ L1RPCURLFlag = &cli.StringFlag{
Name: L1RPCURLFlagName, Name: L1RPCURLFlagName,
...@@ -57,11 +80,11 @@ var ( ...@@ -57,11 +80,11 @@ var (
Usage: "Private key of the deployer account.", Usage: "Private key of the deployer account.",
EnvVars: PrefixEnvVar("PRIVATE_KEY"), EnvVars: PrefixEnvVar("PRIVATE_KEY"),
} }
DeploymentStrategyFlag = &cli.StringFlag{ DeploymentTargetFlag = &cli.StringFlag{
Name: DeploymentStrategyFlagName, Name: "deployment-target",
Usage: fmt.Sprintf("Deployment strategy to use. Options: %s, %s", state.DeploymentStrategyLive, state.DeploymentStrategyGenesis), Usage: fmt.Sprintf("Where to deploy L1 contracts. Options: %s, %s, %s, %s", DeploymentTargetLive, DeploymentTargetGenesis, DeploymentTargetCalldata, DeploymentTargetNoop),
EnvVars: PrefixEnvVar("DEPLOYMENT_STRATEGY"), EnvVars: PrefixEnvVar("DEPLOYMENT_TARGET"),
Value: string(state.DeploymentStrategyLive), Value: string(DeploymentTargetLive),
} }
IntentConfigTypeFlag = &cli.StringFlag{ IntentConfigTypeFlag = &cli.StringFlag{
Name: IntentConfigTypeFlagName, Name: IntentConfigTypeFlagName,
...@@ -82,7 +105,6 @@ var InitFlags = []cli.Flag{ ...@@ -82,7 +105,6 @@ var InitFlags = []cli.Flag{
L1ChainIDFlag, L1ChainIDFlag,
L2ChainIDsFlag, L2ChainIDsFlag,
WorkdirFlag, WorkdirFlag,
DeploymentStrategyFlag,
IntentConfigTypeFlag, IntentConfigTypeFlag,
} }
...@@ -90,6 +112,7 @@ var ApplyFlags = []cli.Flag{ ...@@ -90,6 +112,7 @@ var ApplyFlags = []cli.Flag{
L1RPCURLFlag, L1RPCURLFlag,
WorkdirFlag, WorkdirFlag,
PrivateKeyFlag, PrivateKeyFlag,
DeploymentTargetFlag,
} }
func PrefixEnvVar(name string) []string { func PrefixEnvVar(name string) []string {
......
...@@ -16,18 +16,13 @@ import ( ...@@ -16,18 +16,13 @@ import (
) )
type InitConfig struct { type InitConfig struct {
DeploymentStrategy state.DeploymentStrategy IntentConfigType state.IntentConfigType
IntentConfigType state.IntentConfigType L1ChainID uint64
L1ChainID uint64 Outdir string
Outdir string L2ChainIDs []common.Hash
L2ChainIDs []common.Hash
} }
func (c *InitConfig) Check() error { func (c *InitConfig) Check() error {
if err := c.DeploymentStrategy.Check(); err != nil {
return err
}
if c.L1ChainID == 0 { if c.L1ChainID == 0 {
return fmt.Errorf("l1ChainID must be specified") return fmt.Errorf("l1ChainID must be specified")
} }
...@@ -45,7 +40,6 @@ func (c *InitConfig) Check() error { ...@@ -45,7 +40,6 @@ func (c *InitConfig) Check() error {
func InitCLI() func(ctx *cli.Context) error { func InitCLI() func(ctx *cli.Context) error {
return func(ctx *cli.Context) error { return func(ctx *cli.Context) error {
deploymentStrategy := ctx.String(DeploymentStrategyFlagName)
l1ChainID := ctx.Uint64(L1ChainIDFlagName) l1ChainID := ctx.Uint64(L1ChainIDFlagName)
outdir := ctx.String(OutdirFlagName) outdir := ctx.String(OutdirFlagName)
l2ChainIDsRaw := ctx.String(L2ChainIDsFlagName) l2ChainIDsRaw := ctx.String(L2ChainIDsFlagName)
...@@ -66,11 +60,10 @@ func InitCLI() func(ctx *cli.Context) error { ...@@ -66,11 +60,10 @@ func InitCLI() func(ctx *cli.Context) error {
} }
err := Init(InitConfig{ err := Init(InitConfig{
DeploymentStrategy: state.DeploymentStrategy(deploymentStrategy), IntentConfigType: state.IntentConfigType(intentConfigType),
IntentConfigType: state.IntentConfigType(intentConfigType), L1ChainID: l1ChainID,
L1ChainID: l1ChainID, Outdir: outdir,
Outdir: outdir, L2ChainIDs: l2ChainIDs,
L2ChainIDs: l2ChainIDs,
}) })
if err != nil { if err != nil {
return err return err
...@@ -86,11 +79,10 @@ func Init(cfg InitConfig) error { ...@@ -86,11 +79,10 @@ func Init(cfg InitConfig) error {
return fmt.Errorf("invalid config for init: %w", err) return fmt.Errorf("invalid config for init: %w", err)
} }
intent, err := state.NewIntent(cfg.IntentConfigType, cfg.DeploymentStrategy, cfg.L1ChainID, cfg.L2ChainIDs) intent, err := state.NewIntent(cfg.IntentConfigType, cfg.L1ChainID, cfg.L2ChainIDs)
if err != nil { if err != nil {
return err return err
} }
intent.DeploymentStrategy = cfg.DeploymentStrategy
intent.ConfigType = cfg.IntentConfigType intent.ConfigType = cfg.IntentConfigType
st := &state.State{ st := &state.State{
......
...@@ -132,6 +132,7 @@ func TestEndToEndApply(t *testing.T) { ...@@ -132,6 +132,7 @@ func TestEndToEndApply(t *testing.T) {
require.NoError(t, deployer.ApplyPipeline( require.NoError(t, deployer.ApplyPipeline(
ctx, ctx,
deployer.ApplyPipelineOpts{ deployer.ApplyPipelineOpts{
DeploymentTarget: deployer.DeploymentTargetLive,
L1RPCUrl: rpcURL, L1RPCUrl: rpcURL,
DeployerPrivateKey: pk, DeployerPrivateKey: pk,
Intent: intent, Intent: intent,
...@@ -148,6 +149,7 @@ func TestEndToEndApply(t *testing.T) { ...@@ -148,6 +149,7 @@ func TestEndToEndApply(t *testing.T) {
require.NoError(t, deployer.ApplyPipeline( require.NoError(t, deployer.ApplyPipeline(
ctx, ctx,
deployer.ApplyPipelineOpts{ deployer.ApplyPipelineOpts{
DeploymentTarget: deployer.DeploymentTargetLive,
L1RPCUrl: rpcURL, L1RPCUrl: rpcURL,
DeployerPrivateKey: pk, DeployerPrivateKey: pk,
Intent: intent, Intent: intent,
...@@ -169,6 +171,7 @@ func TestEndToEndApply(t *testing.T) { ...@@ -169,6 +171,7 @@ func TestEndToEndApply(t *testing.T) {
require.ErrorIs(t, deployer.ApplyPipeline( require.ErrorIs(t, deployer.ApplyPipeline(
ctx, ctx,
deployer.ApplyPipelineOpts{ deployer.ApplyPipelineOpts{
DeploymentTarget: deployer.DeploymentTargetLive,
L1RPCUrl: rpcURL, L1RPCUrl: rpcURL,
DeployerPrivateKey: pk, DeployerPrivateKey: pk,
Intent: intent, Intent: intent,
...@@ -178,6 +181,25 @@ func TestEndToEndApply(t *testing.T) { ...@@ -178,6 +181,25 @@ func TestEndToEndApply(t *testing.T) {
}, },
), pipeline.ErrRefusingToDeployTaggedReleaseWithoutOPCM) ), pipeline.ErrRefusingToDeployTaggedReleaseWithoutOPCM)
}) })
t.Run("with calldata broadcasts", func(t *testing.T) {
intent, st := newIntent(t, l1ChainID, dk, l2ChainID1, loc, loc)
require.NoError(t, deployer.ApplyPipeline(
ctx,
deployer.ApplyPipelineOpts{
DeploymentTarget: deployer.DeploymentTargetCalldata,
L1RPCUrl: rpcURL,
DeployerPrivateKey: pk,
Intent: intent,
State: st,
Logger: lgr,
StateWriter: pipeline.NoopStateWriter(),
},
))
require.Greater(t, len(st.DeploymentCalldata), 0)
})
} }
type existingOPCMTest struct { type existingOPCMTest struct {
...@@ -380,6 +402,7 @@ func testApplyExistingOPCM(t *testing.T, testInfo existingOPCMTest) { ...@@ -380,6 +402,7 @@ func testApplyExistingOPCM(t *testing.T, testInfo existingOPCMTest) {
require.NoError(t, deployer.ApplyPipeline( require.NoError(t, deployer.ApplyPipeline(
ctx, ctx,
deployer.ApplyPipelineOpts{ deployer.ApplyPipelineOpts{
DeploymentTarget: deployer.DeploymentTargetLive,
L1RPCUrl: runner.RPCUrl(), L1RPCUrl: runner.RPCUrl(),
DeployerPrivateKey: pk, DeployerPrivateKey: pk,
Intent: intent, Intent: intent,
...@@ -836,7 +859,6 @@ func TestInvalidL2Genesis(t *testing.T) { ...@@ -836,7 +859,6 @@ func TestInvalidL2Genesis(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
opts, intent, _ := setupGenesisChain(t, defaultL1ChainID) opts, intent, _ := setupGenesisChain(t, defaultL1ChainID)
intent.DeploymentStrategy = state.DeploymentStrategyGenesis
intent.GlobalDeployOverrides = tt.overrides intent.GlobalDeployOverrides = tt.overrides
err := deployer.ApplyPipeline(ctx, opts) err := deployer.ApplyPipeline(ctx, opts)
...@@ -1001,9 +1023,9 @@ func setupGenesisChain(t *testing.T, l1ChainID uint64) (deployer.ApplyPipelineOp ...@@ -1001,9 +1023,9 @@ func setupGenesisChain(t *testing.T, l1ChainID uint64) (deployer.ApplyPipelineOp
loc, _ := testutil.LocalArtifacts(t) loc, _ := testutil.LocalArtifacts(t)
intent, st := newIntent(t, l1ChainIDBig, dk, l2ChainID1, loc, loc) intent, st := newIntent(t, l1ChainIDBig, dk, l2ChainID1, loc, loc)
intent.DeploymentStrategy = state.DeploymentStrategyGenesis
opts := deployer.ApplyPipelineOpts{ opts := deployer.ApplyPipelineOpts{
DeploymentTarget: deployer.DeploymentTargetGenesis,
DeployerPrivateKey: priv, DeployerPrivateKey: priv,
Intent: intent, Intent: intent,
State: st, State: st,
...@@ -1029,9 +1051,8 @@ func newIntent( ...@@ -1029,9 +1051,8 @@ 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, ConfigType: state.IntentConfigTypeCustom,
DeploymentStrategy: state.DeploymentStrategyLive, L1ChainID: l1ChainID.Uint64(),
L1ChainID: l1ChainID.Uint64(),
SuperchainRoles: &state.SuperchainRoles{ SuperchainRoles: &state.SuperchainRoles{
ProxyAdminOwner: addrFor(t, dk, devkeys.L1ProxyAdminOwnerRole.Key(l1ChainID)), ProxyAdminOwner: addrFor(t, dk, devkeys.L1ProxyAdminOwnerRole.Key(l1ChainID)),
ProtocolVersionsOwner: addrFor(t, dk, devkeys.SuperchainDeployerKey.Key(l1ChainID)), ProtocolVersionsOwner: addrFor(t, dk, devkeys.SuperchainDeployerKey.Key(l1ChainID)),
......
...@@ -62,9 +62,8 @@ func TestDependencies(t *testing.T) { ...@@ -62,9 +62,8 @@ func TestDependencies(t *testing.T) {
deployerAddr := crypto.PubkeyToAddress(deployerPriv.PublicKey) deployerAddr := crypto.PubkeyToAddress(deployerPriv.PublicKey)
intent := &state.Intent{ intent := &state.Intent{
ConfigType: state.IntentConfigTypeCustom, ConfigType: state.IntentConfigTypeCustom,
DeploymentStrategy: state.DeploymentStrategyLive, L1ChainID: l1ChainID,
L1ChainID: l1ChainID,
SuperchainRoles: &state.SuperchainRoles{ SuperchainRoles: &state.SuperchainRoles{
ProxyAdminOwner: addrFor(devkeys.L1ProxyAdminOwnerRole), ProxyAdminOwner: addrFor(devkeys.L1ProxyAdminOwnerRole),
ProtocolVersionsOwner: addrFor(devkeys.SuperchainDeployerKey), ProtocolVersionsOwner: addrFor(devkeys.SuperchainDeployerKey),
...@@ -101,6 +100,7 @@ func TestDependencies(t *testing.T) { ...@@ -101,6 +100,7 @@ func TestDependencies(t *testing.T) {
} }
opts := deployer.ApplyPipelineOpts{ opts := deployer.ApplyPipelineOpts{
DeploymentTarget: deployer.DeploymentTargetLive,
L1RPCUrl: runner.RPCUrl(), L1RPCUrl: runner.RPCUrl(),
DeployerPrivateKey: deployerPriv, DeployerPrivateKey: deployerPriv,
Intent: intent, Intent: intent,
......
...@@ -24,7 +24,7 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro ...@@ -24,7 +24,7 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro
var standardVersionsTOML string var standardVersionsTOML string
var contractsRelease string var contractsRelease string
var err error var err error
if intent.L1ContractsLocator.IsTag() && intent.DeploymentStrategy == state.DeploymentStrategyLive { if intent.L1ContractsLocator.IsTag() {
standardVersionsTOML, err = standard.L1VersionsDataFor(intent.L1ChainID) standardVersionsTOML, err = standard.L1VersionsDataFor(intent.L1ChainID)
if err == nil { if err == nil {
contractsRelease = intent.L1ContractsLocator.Tag contractsRelease = intent.L1ContractsLocator.Tag
......
...@@ -16,22 +16,6 @@ import ( ...@@ -16,22 +16,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
type DeploymentStrategy string
const (
DeploymentStrategyLive DeploymentStrategy = "live"
DeploymentStrategyGenesis DeploymentStrategy = "genesis"
)
func (d DeploymentStrategy) Check() error {
switch d {
case DeploymentStrategyLive, DeploymentStrategyGenesis:
return nil
default:
return fmt.Errorf("deployment strategy must be 'live' or 'genesis'")
}
}
type IntentConfigType string type IntentConfigType string
const ( const (
...@@ -55,7 +39,6 @@ type SuperchainProofParams struct { ...@@ -55,7 +39,6 @@ type SuperchainProofParams struct {
} }
type Intent struct { type Intent struct {
DeploymentStrategy DeploymentStrategy `json:"deploymentStrategy" toml:"deploymentStrategy"`
ConfigType IntentConfigType `json:"configType" toml:"configType"` ConfigType IntentConfigType `json:"configType" toml:"configType"`
L1ChainID uint64 `json:"l1ChainID" toml:"l1ChainID"` L1ChainID uint64 `json:"l1ChainID" toml:"l1ChainID"`
SuperchainRoles *SuperchainRoles `json:"superchainRoles" toml:"superchainRoles,omitempty"` SuperchainRoles *SuperchainRoles `json:"superchainRoles" toml:"superchainRoles,omitempty"`
...@@ -211,10 +194,6 @@ func (c *Intent) Check() error { ...@@ -211,10 +194,6 @@ func (c *Intent) Check() error {
return fmt.Errorf("l1ChainID cannot be 0") return fmt.Errorf("l1ChainID cannot be 0")
} }
if err := c.DeploymentStrategy.Check(); err != nil {
return err
}
if c.L1ContractsLocator == nil { if c.L1ContractsLocator == nil {
return ErrL1ContractsLocatorUndefined return ErrL1ContractsLocatorUndefined
} }
...@@ -275,22 +254,22 @@ func (c *Intent) checkL2Prod() error { ...@@ -275,22 +254,22 @@ func (c *Intent) checkL2Prod() error {
return err return err
} }
func NewIntent(configType IntentConfigType, deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) { func NewIntent(configType IntentConfigType, l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) {
switch configType { switch configType {
case IntentConfigTypeCustom: case IntentConfigTypeCustom:
return NewIntentCustom(deploymentStrategy, l1ChainId, l2ChainIds) return NewIntentCustom(l1ChainId, l2ChainIds)
case IntentConfigTypeStandard: case IntentConfigTypeStandard:
return NewIntentStandard(deploymentStrategy, l1ChainId, l2ChainIds) return NewIntentStandard(l1ChainId, l2ChainIds)
case IntentConfigTypeStandardOverrides: case IntentConfigTypeStandardOverrides:
return NewIntentStandardOverrides(deploymentStrategy, l1ChainId, l2ChainIds) return NewIntentStandardOverrides(l1ChainId, l2ChainIds)
case IntentConfigTypeStrict: case IntentConfigTypeStrict:
return NewIntentStrict(deploymentStrategy, l1ChainId, l2ChainIds) return NewIntentStrict(l1ChainId, l2ChainIds)
case IntentConfigTypeStrictOverrides: case IntentConfigTypeStrictOverrides:
return NewIntentStrictOverrides(deploymentStrategy, l1ChainId, l2ChainIds) return NewIntentStrictOverrides(l1ChainId, l2ChainIds)
default: default:
return Intent{}, fmt.Errorf("intent config type not supported") return Intent{}, fmt.Errorf("intent config type not supported")
...@@ -299,9 +278,8 @@ func NewIntent(configType IntentConfigType, deploymentStrategy DeploymentStrateg ...@@ -299,9 +278,8 @@ func NewIntent(configType IntentConfigType, deploymentStrategy DeploymentStrateg
// Sets all Intent fields to their zero value with the expectation that the // Sets all Intent fields to their zero value with the expectation that the
// user will populate the values before running 'apply' // user will populate the values before running 'apply'
func NewIntentCustom(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) { func NewIntentCustom(l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) {
intent := Intent{ intent := Intent{
DeploymentStrategy: deploymentStrategy,
ConfigType: IntentConfigTypeCustom, ConfigType: IntentConfigTypeCustom,
L1ChainID: l1ChainId, L1ChainID: l1ChainId,
L1ContractsLocator: &artifacts.Locator{URL: &url.URL{}}, L1ContractsLocator: &artifacts.Locator{URL: &url.URL{}},
...@@ -317,9 +295,8 @@ func NewIntentCustom(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2 ...@@ -317,9 +295,8 @@ func NewIntentCustom(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2
return intent, nil return intent, nil
} }
func NewIntentStandard(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) { func NewIntentStandard(l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) {
intent := Intent{ intent := Intent{
DeploymentStrategy: deploymentStrategy,
ConfigType: IntentConfigTypeStandard, ConfigType: IntentConfigTypeStandard,
L1ChainID: l1ChainId, L1ChainID: l1ChainId,
L1ContractsLocator: artifacts.DefaultL1ContractsLocator, L1ContractsLocator: artifacts.DefaultL1ContractsLocator,
...@@ -343,8 +320,8 @@ func NewIntentStandard(deploymentStrategy DeploymentStrategy, l1ChainId uint64, ...@@ -343,8 +320,8 @@ func NewIntentStandard(deploymentStrategy DeploymentStrategy, l1ChainId uint64,
return intent, nil return intent, nil
} }
func NewIntentStandardOverrides(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) { func NewIntentStandardOverrides(l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) {
intent, err := NewIntentStandard(deploymentStrategy, l1ChainId, l2ChainIds) intent, err := NewIntentStandard(l1ChainId, l2ChainIds)
if err != nil { if err != nil {
return Intent{}, err return Intent{}, err
} }
...@@ -355,8 +332,8 @@ func NewIntentStandardOverrides(deploymentStrategy DeploymentStrategy, l1ChainId ...@@ -355,8 +332,8 @@ func NewIntentStandardOverrides(deploymentStrategy DeploymentStrategy, l1ChainId
// Same as NewIntentStandard, but also sets l2 Challenger and L1ProxyAdminOwner // Same as NewIntentStandard, but also sets l2 Challenger and L1ProxyAdminOwner
// addresses to standard values // addresses to standard values
func NewIntentStrict(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) { func NewIntentStrict(l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) {
intent, err := NewIntentStandard(deploymentStrategy, l1ChainId, l2ChainIds) intent, err := NewIntentStandard(l1ChainId, l2ChainIds)
if err != nil { if err != nil {
return Intent{}, err return Intent{}, err
} }
...@@ -371,8 +348,8 @@ func NewIntentStrict(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2 ...@@ -371,8 +348,8 @@ func NewIntentStrict(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2
return intent, nil return intent, nil
} }
func NewIntentStrictOverrides(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) { func NewIntentStrictOverrides(l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) {
intent, err := NewIntentStrict(deploymentStrategy, l1ChainId, l2ChainIds) intent, err := NewIntentStrict(l1ChainId, l2ChainIds)
if err != nil { if err != nil {
return Intent{}, err return Intent{}, err
} }
......
...@@ -8,7 +8,7 @@ import ( ...@@ -8,7 +8,7 @@ import (
) )
func TestValidateStandardValues(t *testing.T) { func TestValidateStandardValues(t *testing.T) {
intent, err := NewIntentStandard(DeploymentStrategyLive, 1, []common.Hash{common.HexToHash("0x336")}) intent, err := NewIntentStandard(1, []common.Hash{common.HexToHash("0x336")})
require.NoError(t, err) require.NoError(t, err)
err = intent.Check() err = intent.Check()
...@@ -64,7 +64,7 @@ func TestValidateStandardValues(t *testing.T) { ...@@ -64,7 +64,7 @@ func TestValidateStandardValues(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
intent, err := NewIntentStandard(DeploymentStrategyLive, 1, []common.Hash{common.HexToHash("0x336")}) intent, err := NewIntentStandard(1, []common.Hash{common.HexToHash("0x336")})
require.NoError(t, err) require.NoError(t, err)
setChainRoles(&intent) setChainRoles(&intent)
setFeeAddresses(&intent) setFeeAddresses(&intent)
...@@ -79,7 +79,7 @@ func TestValidateStandardValues(t *testing.T) { ...@@ -79,7 +79,7 @@ func TestValidateStandardValues(t *testing.T) {
} }
func TestValidateCustomValues(t *testing.T) { func TestValidateCustomValues(t *testing.T) {
intent, err := NewIntentCustom(DeploymentStrategyLive, 1, []common.Hash{common.HexToHash("0x336")}) intent, err := NewIntentCustom(1, []common.Hash{common.HexToHash("0x336")})
require.NoError(t, err) require.NoError(t, err)
err = intent.Check() err = intent.Check()
......
...@@ -3,6 +3,8 @@ package state ...@@ -3,6 +3,8 @@ package state
import ( import (
"fmt" "fmt"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum-optimism/optimism/op-chain-ops/foundry" "github.com/ethereum-optimism/optimism/op-chain-ops/foundry"
...@@ -40,6 +42,10 @@ type State struct { ...@@ -40,6 +42,10 @@ type State struct {
// L1StateDump contains the complete L1 state dump of the deployment. // L1StateDump contains the complete L1 state dump of the deployment.
L1StateDump *GzipData[foundry.ForgeAllocs] `json:"l1StateDump"` L1StateDump *GzipData[foundry.ForgeAllocs] `json:"l1StateDump"`
// DeploymentCalldata contains the calldata of each transaction in the deployment. This is only
// populated if apply is called with --deployment-target=calldata.
DeploymentCalldata []broadcaster.CalldataDump
} }
func (s *State) WriteToFile(path string) error { func (s *State) WriteToFile(path string) error {
......
...@@ -309,6 +309,7 @@ func initAllocType(root string, allocType AllocType) { ...@@ -309,6 +309,7 @@ func initAllocType(root string, allocType AllocType) {
if err := deployer.ApplyPipeline( if err := deployer.ApplyPipeline(
context.Background(), context.Background(),
deployer.ApplyPipelineOpts{ deployer.ApplyPipelineOpts{
DeploymentTarget: deployer.DeploymentTargetGenesis,
L1RPCUrl: "", L1RPCUrl: "",
DeployerPrivateKey: pk, DeployerPrivateKey: pk,
Intent: intent, Intent: intent,
...@@ -360,9 +361,8 @@ func defaultIntent(root string, loc *artifacts.Locator, deployer common.Address, ...@@ -360,9 +361,8 @@ func defaultIntent(root string, loc *artifacts.Locator, deployer common.Address,
defaultPrestate := common.HexToHash("0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98") defaultPrestate := common.HexToHash("0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98")
genesisOutputRoot := common.HexToHash("0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF") genesisOutputRoot := common.HexToHash("0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF")
return &state.Intent{ return &state.Intent{
ConfigType: state.IntentConfigTypeCustom, ConfigType: state.IntentConfigTypeCustom,
DeploymentStrategy: state.DeploymentStrategyGenesis, L1ChainID: 900,
L1ChainID: 900,
SuperchainRoles: &state.SuperchainRoles{ SuperchainRoles: &state.SuperchainRoles{
ProxyAdminOwner: deployer, ProxyAdminOwner: deployer,
ProtocolVersionsOwner: deployer, ProtocolVersionsOwner: deployer,
......
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