@@ -32,10 +32,11 @@ import (
3232)
3333
3434type ApplyConfig struct {
35- L1RPCUrl string
36- Workdir string
37- PrivateKey string
38- Logger log.Logger
35+ L1RPCUrl string
36+ Workdir string
37+ PrivateKey string
38+ DeploymentTarget DeploymentTarget
39+ Logger log.Logger
3940
4041 privateKeyECDSA * ecdsa.PrivateKey
4142}
@@ -57,16 +58,14 @@ func (a *ApplyConfig) Check() error {
5758 return fmt .Errorf ("logger must be specified" )
5859 }
5960
60- return nil
61- }
62-
63- func (a * ApplyConfig ) CheckLive () error {
64- if a .privateKeyECDSA == nil {
65- return fmt .Errorf ("private key must be specified" )
66- }
61+ if a .DeploymentTarget == DeploymentTargetLive {
62+ if a .L1RPCUrl == "" {
63+ return fmt .Errorf ("l1 RPC URL must be specified for live deployment" )
64+ }
6765
68- if a .L1RPCUrl == "" {
69- return fmt .Errorf ("l1RPCUrl must be specified" )
66+ if a .privateKeyECDSA == nil {
67+ return fmt .Errorf ("private key must be specified for live deployment" )
68+ }
7069 }
7170
7271 return nil
@@ -81,14 +80,19 @@ func ApplyCLI() func(cliCtx *cli.Context) error {
8180 l1RPCUrl := cliCtx .String (L1RPCURLFlagName )
8281 workdir := cliCtx .String (WorkdirFlagName )
8382 privateKey := cliCtx .String (PrivateKeyFlagName )
83+ depTarget , err := NewDeploymentTarget (cliCtx .String (DeploymentTargetFlag .Name ))
84+ if err != nil {
85+ return fmt .Errorf ("failed to parse deployment target: %w" , err )
86+ }
8487
8588 ctx := ctxinterrupt .WithCancelOnInterrupt (cliCtx .Context )
8689
8790 return Apply (ctx , ApplyConfig {
88- L1RPCUrl : l1RPCUrl ,
89- Workdir : workdir ,
90- PrivateKey : privateKey ,
91- Logger : l ,
91+ L1RPCUrl : l1RPCUrl ,
92+ Workdir : workdir ,
93+ PrivateKey : privateKey ,
94+ DeploymentTarget : depTarget ,
95+ Logger : l ,
9296 })
9397 }
9498}
@@ -110,6 +114,7 @@ func Apply(ctx context.Context, cfg ApplyConfig) error {
110114
111115 if err := ApplyPipeline (ctx , ApplyPipelineOpts {
112116 L1RPCUrl : cfg .L1RPCUrl ,
117+ DeploymentTarget : cfg .DeploymentTarget ,
113118 DeployerPrivateKey : cfg .privateKeyECDSA ,
114119 Intent : intent ,
115120 State : st ,
@@ -129,6 +134,7 @@ type pipelineStage struct {
129134
130135type ApplyPipelineOpts struct {
131136 L1RPCUrl string
137+ DeploymentTarget DeploymentTarget
132138 DeployerPrivateKey * ecdsa.PrivateKey
133139 Intent * state.Intent
134140 State * state.State
@@ -187,34 +193,11 @@ func ApplyPipeline(
187193 }
188194
189195 var bcaster broadcaster.Broadcaster
196+ var l1RPC * rpc.Client
190197 var l1Client * ethclient.Client
191198 var l1Host * script.Host
192- if intent .DeploymentStrategy == state .DeploymentStrategyLive {
193- l1RPC , err := rpc .Dial (opts .L1RPCUrl )
194- if err != nil {
195- return fmt .Errorf ("failed to connect to L1 RPC: %w" , err )
196- }
197-
198- l1Client = ethclient .NewClient (l1RPC )
199-
200- chainID , err := l1Client .ChainID (ctx )
201- if err != nil {
202- return fmt .Errorf ("failed to get chain ID: %w" , err )
203- }
204-
205- signer := opcrypto .SignerFnFromBind (opcrypto .PrivateKeySignerFn (opts .DeployerPrivateKey , chainID ))
206-
207- bcaster , err = broadcaster .NewKeyedBroadcaster (broadcaster.KeyedBroadcasterOpts {
208- Logger : opts .Logger ,
209- ChainID : new (big.Int ).SetUint64 (intent .L1ChainID ),
210- Client : l1Client ,
211- Signer : signer ,
212- From : deployer ,
213- })
214- if err != nil {
215- return fmt .Errorf ("failed to create broadcaster: %w" , err )
216- }
217199
200+ initForkHost := func () error {
218201 l1Host , err = env .DefaultScriptHost (
219202 bcaster ,
220203 opts .Logger ,
@@ -243,7 +226,54 @@ func ApplyPipeline(
243226 ); err != nil {
244227 return fmt .Errorf ("failed to select fork: %w" , err )
245228 }
246- } else {
229+
230+ return nil
231+ }
232+
233+ switch opts .DeploymentTarget {
234+ case DeploymentTargetLive :
235+ l1RPC , err = rpc .Dial (opts .L1RPCUrl )
236+ if err != nil {
237+ return fmt .Errorf ("failed to connect to L1 RPC: %w" , err )
238+ }
239+
240+ l1Client = ethclient .NewClient (l1RPC )
241+
242+ chainID , err := l1Client .ChainID (ctx )
243+ if err != nil {
244+ return fmt .Errorf ("failed to get chain ID: %w" , err )
245+ }
246+
247+ signer := opcrypto .SignerFnFromBind (opcrypto .PrivateKeySignerFn (opts .DeployerPrivateKey , chainID ))
248+
249+ bcaster , err = broadcaster .NewKeyedBroadcaster (broadcaster.KeyedBroadcasterOpts {
250+ Logger : opts .Logger ,
251+ ChainID : new (big.Int ).SetUint64 (intent .L1ChainID ),
252+ Client : l1Client ,
253+ Signer : signer ,
254+ From : deployer ,
255+ })
256+ if err != nil {
257+ return fmt .Errorf ("failed to create broadcaster: %w" , err )
258+ }
259+
260+ if err := initForkHost (); err != nil {
261+ return fmt .Errorf ("failed to initialize L1 host: %w" , err )
262+ }
263+ case DeploymentTargetCalldata , DeploymentTargetNoop :
264+ l1RPC , err = rpc .Dial (opts .L1RPCUrl )
265+ if err != nil {
266+ return fmt .Errorf ("failed to connect to L1 RPC: %w" , err )
267+ }
268+
269+ l1Client = ethclient .NewClient (l1RPC )
270+
271+ bcaster = new (broadcaster.CalldataBroadcaster )
272+
273+ if err := initForkHost (); err != nil {
274+ return fmt .Errorf ("failed to initialize L1 host: %w" , err )
275+ }
276+ case DeploymentTargetGenesis :
247277 bcaster = broadcaster .NoopBroadcaster ()
248278 l1Host , err = env .DefaultScriptHost (
249279 bcaster ,
@@ -254,6 +284,8 @@ func ApplyPipeline(
254284 if err != nil {
255285 return fmt .Errorf ("failed to create L1 script host: %w" , err )
256286 }
287+ default :
288+ return fmt .Errorf ("invalid deployment target: '%s'" , opts .DeploymentTarget )
257289 }
258290
259291 pEnv := & pipeline.Env {
@@ -267,11 +299,10 @@ func ApplyPipeline(
267299
268300 pline := []pipelineStage {
269301 {"init" , func () error {
270- if intent .DeploymentStrategy == state .DeploymentStrategyLive {
271- return pipeline .InitLiveStrategy (ctx , pEnv , intent , st )
272- } else {
302+ if opts .DeploymentTarget == DeploymentTargetGenesis {
273303 return pipeline .InitGenesisStrategy (pEnv , intent , st )
274304 }
305+ return pipeline .InitLiveStrategy (ctx , pEnv , intent , st )
275306 }},
276307 {"deploy-superchain" , func () error {
277308 return pipeline .DeploySuperchain (pEnv , intent , st )
@@ -314,23 +345,22 @@ func ApplyPipeline(
314345 pline = append (pline , pipelineStage {
315346 fmt .Sprintf ("set-start-block-%s" , chainID .Hex ()),
316347 func () error {
317- if intent .DeploymentStrategy == state .DeploymentStrategyLive {
318- return pipeline .SetStartBlockLiveStrategy (ctx , pEnv , st , chainID )
319- } else {
348+ if opts .DeploymentTarget == DeploymentTargetGenesis {
320349 return pipeline .SetStartBlockGenesisStrategy (pEnv , st , chainID )
321350 }
351+ return pipeline .SetStartBlockLiveStrategy (ctx , pEnv , st , chainID )
322352 },
323353 })
324354 }
325355
326- // Run through the pipeline. The state dump is captured between
327- // every step.
356+ // Run through the pipeline.
328357 for _ , stage := range pline {
329358 if err := stage .apply (); err != nil {
330359 return fmt .Errorf ("error in pipeline stage apply: %w" , err )
331360 }
332361
333- if intent .DeploymentStrategy == state .DeploymentStrategyGenesis {
362+ // Some steps use the L1StateDump, so we need to apply it to state after every step.
363+ if opts .DeploymentTarget == DeploymentTargetGenesis {
334364 dump , err := pEnv .L1ScriptHost .StateDump ()
335365 if err != nil {
336366 return fmt .Errorf ("failed to dump state: %w" , err )
@@ -348,6 +378,14 @@ func ApplyPipeline(
348378 }
349379 }
350380
381+ if opts .DeploymentTarget == DeploymentTargetCalldata {
382+ cdCaster := pEnv .Broadcaster .(* broadcaster.CalldataBroadcaster )
383+ st .DeploymentCalldata , err = cdCaster .Dump ()
384+ if err != nil {
385+ return fmt .Errorf ("failed to dump calldata: %w" , err )
386+ }
387+ }
388+
351389 st .AppliedIntent = intent
352390 if err := pEnv .StateWriter .WriteState (st ); err != nil {
353391 return fmt .Errorf ("failed to write state: %w" , err )
0 commit comments