Skip to content

Commit 12b9983

Browse files
feat: initial impl of super root verification (#15514)
* feat: initial impl of super root verification * fix: error if rpc url is invalid * fix: switch from unsafe blocks to finalized blocks * fix: error instead of fallback when parsing finalized target block * fix: remove checks that wont be hit * chore: get parentHeader by hash * fix: use latest block instead of finalized and remove unrreachable check * fix: remove redundant sorting * feat: add optimal timestamp flag * fix: remove empty branch * fix: update how the anchorTimestamp is determined * chore: remove unused vars * op-chain-ops: Super root calculation fixes. * op-e2e: Add action test for super root creation script --------- Co-authored-by: Adrian Sutton <[email protected]>
1 parent a30dd55 commit 12b9983

File tree

4 files changed

+512
-0
lines changed

4 files changed

+512
-0
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
8+
"github.com/ethereum/go-ethereum/log"
9+
"github.com/urfave/cli/v2"
10+
11+
"github.com/ethereum-optimism/optimism/op-chain-ops/script"
12+
"github.com/ethereum-optimism/optimism/op-service/cliapp"
13+
oplog "github.com/ethereum-optimism/optimism/op-service/log"
14+
)
15+
16+
const (
17+
// RPCEndpointsFlagName defines the flag name for the RPC endpoints.
18+
RPCEndpointsFlagName = "rpc-endpoints"
19+
// TimestampFlagName defines the flag name for the optional target timestamp.
20+
TimestampFlagName = "timestamp"
21+
)
22+
23+
// Config holds the configuration for the check-super-root command.
24+
type Config struct {
25+
Logger log.Logger
26+
RPCEndpoints []string
27+
TargetTimestamp *uint64 // Optional target timestamp
28+
}
29+
30+
// NewConfig parses the Config from the provided flags or environment variables.
31+
func NewConfig(ctx *cli.Context) (*Config, error) {
32+
rpcs := ctx.StringSlice(RPCEndpointsFlagName)
33+
if len(rpcs) == 0 {
34+
return nil, fmt.Errorf("flag %s is required", RPCEndpointsFlagName)
35+
}
36+
37+
var targetTimestamp *uint64
38+
if ctx.IsSet(TimestampFlagName) {
39+
ts := ctx.Uint64(TimestampFlagName)
40+
targetTimestamp = &ts
41+
}
42+
43+
return &Config{
44+
Logger: oplog.NewLogger(oplog.AppOut(ctx), oplog.ReadCLIConfig(ctx)),
45+
RPCEndpoints: rpcs,
46+
TargetTimestamp: targetTimestamp,
47+
}, nil
48+
}
49+
50+
// Main is the entrypoint for the check-super-root command.
51+
func Main(cfg *Config, ctx *cli.Context) error {
52+
migrator, err := script.NewSuperRootMigrator(cfg.Logger, cfg.RPCEndpoints, cfg.TargetTimestamp)
53+
if err != nil {
54+
return fmt.Errorf("failed to create SuperRootMigrator: %w", err)
55+
}
56+
57+
if _, err := migrator.Run(ctx.Context); err != nil {
58+
return err
59+
}
60+
61+
return nil
62+
}
63+
64+
// Flags contains the list of configuration options available to the binary.
65+
var Flags = []cli.Flag{
66+
&cli.StringSliceFlag{
67+
Name: RPCEndpointsFlagName,
68+
Usage: "Required: List of L2 execution client RPC endpoints (e.g., http://host:port).",
69+
Required: true,
70+
EnvVars: []string{"CHECK_SUPER_ROOT_RPC_ENDPOINTS"},
71+
},
72+
&cli.Uint64Flag{
73+
Name: TimestampFlagName,
74+
Usage: "Optional: Target timestamp for super root calculation. If not set, uses the latest common finalized block timestamp.",
75+
EnvVars: []string{"CHECK_SUPER_ROOT_TIMESTAMP"},
76+
},
77+
}
78+
79+
func main() {
80+
oplog.SetupDefaults()
81+
82+
app := cli.NewApp()
83+
app.Name = "check-super-root"
84+
app.Usage = "Calculates a super root from multiple L2 EL endpoints based on their common finalized state."
85+
// Combine specific flags with log flags
86+
app.Flags = append(Flags, oplog.CLIFlags("CHECK_SUPER_ROOT")...)
87+
88+
app.Action = cliapp.LifecycleCmd(func(ctx *cli.Context, close context.CancelCauseFunc) (cliapp.Lifecycle, error) {
89+
// Parse config from CLI flags
90+
cfg, err := NewConfig(ctx)
91+
if err != nil {
92+
return nil, err
93+
}
94+
// Create a lifecycle that wraps our Main function
95+
return &superRootLifecycle{
96+
cfg: cfg,
97+
ctx: ctx,
98+
close: close,
99+
}, nil
100+
})
101+
102+
if err := app.Run(os.Args); err != nil {
103+
log.Crit("Application failed", "err", err)
104+
}
105+
}
106+
107+
type superRootLifecycle struct {
108+
cfg *Config
109+
ctx *cli.Context
110+
close context.CancelCauseFunc
111+
}
112+
113+
func (s *superRootLifecycle) Start(ctx context.Context) error {
114+
// Execute the main function
115+
err := Main(s.cfg, s.ctx)
116+
117+
// Signal that the application should terminate, regardless of whether there was an error
118+
s.close(err)
119+
120+
// Return the error from Main, if any
121+
return err
122+
}
123+
124+
func (s *superRootLifecycle) Stop(ctx context.Context) error {
125+
return nil
126+
}
127+
128+
func (s *superRootLifecycle) Stopped() bool {
129+
return true
130+
}

0 commit comments

Comments
 (0)