Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var AddNewChainCmd = cli.Command{ Name: "add-new-chain", Usage: "Add a new chain to the superchain-registry", Flags: []cli.Flag{ flags.PublicRpcFlag, flags.SequencerRpcFlag, flags.ExplorerFlag, flags.SuperchainTargetFlag, flags.MonorepoDirFlag, flags.ChainNameFlag, flags.ChainShortNameFlag, flags.RollupConfigFlag, flags.GenesisFlag, flags.DeploymentsDirFlag, flags.StandardChainCandidateFlag, flags.GenesisCreationCommit, flags.DeployConfigFlag, }, Action: func(c *cli.Context) error { standardChainCandidate := c.Bool(flags.StandardChainCandidateFlag.Name) superchainLevel := superchain.Frontier publicRPC := c.String(flags.PublicRpcFlag.Name) sequencerRPC := c.String(flags.SequencerRpcFlag.Name) explorer := c.String(flags.ExplorerFlag.Name) superchainTarget := c.String(flags.SuperchainTargetFlag.Name) monorepoDir := c.String(flags.MonorepoDirFlag.Name) chainName := c.String(flags.ChainNameFlag.Name) rollupConfigPath := c.String(flags.RollupConfigFlag.Name) genesisPath := c.String(flags.GenesisFlag.Name) deployConfigPath := c.String(flags.DeployConfigFlag.Name) genesisCreationCommit := c.String(flags.GenesisCreationCommit.Name) deploymentsDir := c.String(flags.DeploymentsDirFlag.Name) chainShortName := c.String(flags.ChainShortNameFlag.Name) _, thisFile, _, ok := runtime.Caller(0) if !ok { panic("error getting current filepath") } superchainRepoRoot := filepath.Dir(filepath.Dir(filepath.Dir(thisFile))) fmt.Printf("Chain Name: %s\n", chainName) fmt.Printf("Chain Short Name: %s\n", chainShortName) fmt.Printf("Superchain target: %s\n", superchainTarget) fmt.Printf("Superchain-registry repo dir: %s\n", superchainRepoRoot) fmt.Printf("Monorepo dir: %s\n", monorepoDir) fmt.Printf("Deployments directory: %s\n", deploymentsDir) fmt.Printf("Rollup config filepath: %s\n", rollupConfigPath) fmt.Printf("Genesis filepath: %s\n", genesisPath) fmt.Printf("Deploy config filepath: %s\n", deployConfigPath) fmt.Printf("Genesis creation commit: %s\n", genesisCreationCommit) fmt.Printf("Public RPC endpoint: %s\n", publicRPC) fmt.Printf("Sequencer RPC endpoint: %s\n", sequencerRPC) fmt.Printf("Block Explorer: %s\n", explorer) fmt.Println() targetDir := filepath.Join(superchainRepoRoot, "superchain", "configs", superchainTarget) if _, err := os.Stat(targetDir); os.IsNotExist(err) { return fmt.Errorf("superchain target directory not found. Please follow instructions to add a superchain target in CONTRIBUTING.md: %s", targetDir) } l1RpcUrl, err := config.GetL1RpcUrl(superchainTarget) if err != nil { return fmt.Errorf("failed to retrieve L1 rpc url: %w", err) } var addresses superchain.AddressList err = utils.ReadAddressesFromJSON(&addresses, deploymentsDir) if err != nil { return fmt.Errorf("failed to read addresses from JSON files: %w", err) } isFaultProofs, err := inferIsFaultProofs(addresses.SystemConfigProxy, addresses.OptimismPortalProxy, l1RpcUrl) if err != nil { return fmt.Errorf("failed to infer fault proofs status of chain: %w", err) } rollupConfig, err := config.ConstructChainConfig(rollupConfigPath, genesisPath, chainName, publicRPC, sequencerRPC, explorer, superchainLevel, standardChainCandidate) if err != nil { return fmt.Errorf("failed to construct rollup config: %w", err) } fmt.Printf("✅ Rollup config successfully constructed\n") err = utils.ReadAddressesFromChain(&addresses, l1RpcUrl, isFaultProofs) if err != nil { return fmt.Errorf("failed to read addresses from chain: %w", err) } fmt.Printf("✅ Addresses read from chain\n") if rollupConfig.AltDA != nil { addresses.DAChallengeAddress = *rollupConfig.AltDA.DAChallengeAddress } rollupConfig.Addresses = addresses l1RpcUrl, err = config.GetL1RpcUrl(superchainTarget) if err != nil { return fmt.Errorf("error getting l1RpcUrl: %w", err) } gpt, err := getGasPayingToken(l1RpcUrl, addresses.SystemConfigProxy) if err != nil { return fmt.Errorf("error inferring gas paying token: %w", err) } rollupConfig.GasPayingToken = gpt targetFilePath := filepath.Join(targetDir, chainShortName+".toml") err = config.WriteChainConfigTOML(rollupConfig, targetFilePath) if err != nil { return fmt.Errorf("error generating chain config %s.toml file: %w", chainShortName, err) } fmt.Printf("✅ Wrote config for new chain to %s\n", targetFilePath) folderName := fmt.Sprintf("%d", rollupConfig.ChainID) if runningTests := os.Getenv("SCR_RUN_TESTS"); runningTests == "true" { folderName = folderName + "-test" } genesisValidationInputsDir := filepath.Join(superchainRepoRoot, "validation", "genesis", "validation-inputs", folderName) err = os.MkdirAll(genesisValidationInputsDir, os.ModePerm) if err != nil { return err } err = copyDeployConfigFile(deployConfigPath, genesisValidationInputsDir) if err != nil { return fmt.Errorf("error copying deploy-config json file: %w", err) } fmt.Printf("✅ Copied deploy-config json file to validation module\n") err = writeGenesisValidationMetadata(genesisCreationCommit, genesisValidationInputsDir) if err != nil { return fmt.Errorf("error writing genesis validation metadata file: %w", err) } fmt.Printf("✅ Wrote genesis validation metadata file\n") return nil }, }
View Source
var CheckGenesisCmd = cli.Command{ Name: "check-genesis", Flags: []cli.Flag{flags.GenesisFlag}, Usage: "Sanity check genesis (genesis.json) is reproducible", Action: func(ctx *cli.Context) error { genesisPath := ctx.String(flags.GenesisFlag.Name) fmt.Printf("Attempting to read from %s\n", genesisPath) file, err := os.ReadFile(genesisPath) if err != nil { return fmt.Errorf("failed to read from local genesis.json config file: %w", err) } var localGenesis *core.Genesis if err = json.Unmarshal(file, &localGenesis); err != nil { return fmt.Errorf("failed to unmarshal local genesis.json into core.Genesis struct: %w", err) } chainId := localGenesis.Config.ChainID.Uint64() gethGenesis, err := core.LoadOPStackGenesis(chainId) if err != nil { return fmt.Errorf("failed to load genesis via op-geth: ensure chainId has already been added to registry: %w", err) } opts := cmp.Options{cmpopts.IgnoreUnexported(big.Int{})} if diff := cmp.Diff(localGenesis, gethGenesis, opts...); diff != "" { return fmt.Errorf("local genesis.json (-) does not match config generated by op-geth (+): %s", diff) } fmt.Println("👌 Regenerated genesis config matches existing one") return nil }, }
View Source
var CheckRollupConfigCmd = cli.Command{ Name: "check-rollup-config", Flags: []cli.Flag{flags.RollupConfigFlag}, Usage: "Sanity check rollup config (rollup.json) is reproducible", Action: func(ctx *cli.Context) error { rollupConfigPath := ctx.String(flags.RollupConfigFlag.Name) fmt.Printf("Attempting to read from %s\n", rollupConfigPath) file, err := os.ReadFile(rollupConfigPath) if err != nil { return fmt.Errorf("failed to read from local rollup.json config file: %w", err) } var localRollupConfig *rollup.Config if err = json.Unmarshal(file, &localRollupConfig); err != nil { return fmt.Errorf("failed to unmarshal local rollup.json into rollup.Config struct: %w", err) } opNodeRollupConfig, err := rollup.LoadOPStackRollupConfig(localRollupConfig.L2ChainID.Uint64()) if err != nil { return fmt.Errorf("op-node failed to generate rollup config: %w", err) } localRollupConfig.ProtocolVersionsAddress = common.Address{} opNodeRollupConfig.ProtocolVersionsAddress = common.Address{} opts := cmp.Options{cmpopts.IgnoreUnexported(big.Int{})} if diff := cmp.Diff(localRollupConfig, opNodeRollupConfig, opts...); diff != "" { return fmt.Errorf("local rollup.json (-) does not match config generated by op-node (+): %s", diff) } fmt.Println("👌 Regenerated rollup config matches existing one") return nil }, }
View Source
var CompressGenesisCmd = cli.Command{ Name: "compress-genesis", Flags: []cli.Flag{ flags.GenesisFlag, flags.L2GenesisHeaderFlag, flags.ChainShortNameFlag, flags.SuperchainTargetFlag, }, Usage: "Generate a single gzipped data file from a bytecode hex string", Action: func(ctx *cli.Context) error { _, thisFile, _, ok := runtime.Caller(0) if !ok { panic("error getting current filepath") } superchainRepoRoot := filepath.Dir(filepath.Dir(filepath.Dir(thisFile))) superchainTarget := ctx.String(flags.SuperchainTargetFlag.Name) chainShortName := ctx.String(flags.ChainShortNameFlag.Name) zipOutputDir := filepath.Join(superchainRepoRoot, "/superchain/extra/genesis", superchainTarget, chainShortName+".json.gz") genesisPath := ctx.Path(flags.GenesisFlag.Name) if genesisPath == "" { genesisHeaderPath := ctx.Path(flags.L2GenesisHeaderFlag.Name) genesisHeader, err := utils.LoadJSON[types.Header](genesisHeaderPath) if err != nil { return fmt.Errorf("genesis-header %q failed to load: %w", genesisHeaderPath, err) } if genesisHeader.TxHash != types.EmptyTxsHash { return errors.New("genesis-header based genesis must have no transactions") } if genesisHeader.ReceiptHash != types.EmptyReceiptsHash { return errors.New("genesis-header based genesis must have no receipts") } if genesisHeader.UncleHash != types.EmptyUncleHash { return errors.New("genesis-header based genesis must have no uncle hashes") } if genesisHeader.WithdrawalsHash != nil && *genesisHeader.WithdrawalsHash != types.EmptyWithdrawalsHash { return errors.New("genesis-header based genesis must have no withdrawals") } out := Genesis{ Nonce: genesisHeader.Nonce.Uint64(), Timestamp: genesisHeader.Time, ExtraData: genesisHeader.Extra, GasLimit: genesisHeader.GasLimit, Difficulty: (*hexutil.Big)(genesisHeader.Difficulty), Mixhash: genesisHeader.MixDigest, Coinbase: genesisHeader.Coinbase, Number: genesisHeader.Number.Uint64(), GasUsed: genesisHeader.GasUsed, ParentHash: genesisHeader.ParentHash, BaseFee: (*hexutil.Big)(genesisHeader.BaseFee), ExcessBlobGas: genesisHeader.ExcessBlobGas, BlobGasUsed: genesisHeader.BlobGasUsed, Alloc: make(jsonutil.LazySortedJsonMap[common.Address, GenesisAccount]), StateHash: &genesisHeader.Root, } if err := writeGzipJSON(zipOutputDir, out); err != nil { return fmt.Errorf("failed to write output: %w", err) } return nil } genesis, err := utils.LoadJSON[core.Genesis](genesisPath) if err != nil { return fmt.Errorf("failed to load L2 genesis: %w", err) } bytecodesDir := filepath.Join(superchainRepoRoot, "/superchain/extra/bytecodes") fmt.Printf("using output bytecodes dir: %s\n", bytecodesDir) if err := os.MkdirAll(bytecodesDir, 0o755); err != nil { return fmt.Errorf("failed to make bytecodes dir: %w", err) } for addr, account := range genesis.Alloc { if len(account.Code) > 0 { err = writeBytecode(bytecodesDir, account.Code, addr) if err != nil { return err } } } fmt.Printf("✅ Inserted bytecodes to hash->code database %s\n", zipOutputDir) out := Genesis{ Nonce: genesis.Nonce, Timestamp: genesis.Timestamp, ExtraData: genesis.ExtraData, GasLimit: genesis.GasLimit, Difficulty: (*hexutil.Big)(genesis.Difficulty), Mixhash: genesis.Mixhash, Coinbase: genesis.Coinbase, Number: genesis.Number, GasUsed: genesis.GasUsed, ParentHash: genesis.ParentHash, BaseFee: (*hexutil.Big)(genesis.BaseFee), ExcessBlobGas: genesis.ExcessBlobGas, BlobGasUsed: genesis.BlobGasUsed, Alloc: make(jsonutil.LazySortedJsonMap[common.Address, GenesisAccount]), } for addr, account := range genesis.Alloc { var codeHash common.Hash if len(account.Code) > 0 { codeHash = crypto.Keccak256Hash(account.Code) } outAcc := GenesisAccount{ CodeHash: codeHash, Nonce: account.Nonce, } if account.Balance != nil && account.Balance.Cmp(common.Big0) != 0 { outAcc.Balance = (*hexutil.Big)(account.Balance) } if len(account.Storage) > 0 { outAcc.Storage = make(jsonutil.LazySortedJsonMap[common.Hash, common.Hash]) for k, v := range account.Storage { outAcc.Storage[k] = v } } out.Alloc[addr] = outAcc } if err := writeGzipJSON(zipOutputDir, out); err != nil { return fmt.Errorf("failed to write output: %w", err) } fmt.Printf("✅ Wrote compressed genesis file to %s\n", zipOutputDir) return nil }, }
View Source
var PromoteToStandardCmd = cli.Command{ Name: "promote-to-standard", Flags: []cli.Flag{flags.ChainIdFlag}, Aliases: []string{"p"}, Usage: "Promote a chain to standard.", Action: func(ctx *cli.Context) error { chainId := flags.ChainIdFlag.Get(ctx) chain, ok := superchain.OPChains[chainId] if !ok { panic(fmt.Sprintf("No chain found with id %d", chainId)) } copy, err := chain.PromoteToStandard() if err != nil { panic(err) } chain = copy _, thisFile, _, ok := runtime.Caller(0) if !ok { panic("Unable to get the current file path") } superchainRepoPath := filepath.Dir(filepath.Dir(filepath.Dir(thisFile))) targetDir := filepath.Join(superchainRepoPath, "superchain", "configs", chain.Superchain) targetFilePath := filepath.Join(targetDir, chain.Chain+".toml") err = config.WriteChainConfigTOML(*chain, targetFilePath) if err != nil { panic(err) } fmt.Println("Promoted chain to standard: ", chainId) return nil }, }
View Source
var UpdateConfigsCmd = cli.Command{ Name: "update-configs", Aliases: []string{"u"}, Usage: "Update all config toml files after superchain.ChainConfig struct is updated", Action: func(ctx *cli.Context) error { for _, chain := range superchain.OPChains { _, thisFile, _, ok := runtime.Caller(0) if !ok { panic("Unable to get the current file path") } err := chain.CheckDataAvailability() if err != nil { panic(err) } superchainRepoPath := filepath.Dir(filepath.Dir(filepath.Dir(thisFile))) targetDir := filepath.Join(superchainRepoPath, "superchain", "configs", chain.Superchain) targetFilePath := filepath.Join(targetDir, chain.Chain+".toml") err = config.WriteChainConfigTOML(*chain, targetFilePath) if err != nil { panic(err) } } return nil }, }
Functions ¶
This section is empty.
Types ¶
type Genesis ¶
type Genesis struct { Nonce uint64 `json:"nonce"` Timestamp uint64 `json:"timestamp"` ExtraData []byte `json:"extraData"` GasLimit uint64 `json:"gasLimit"` Difficulty *hexutil.Big `json:"difficulty"` Mixhash common.Hash `json:"mixHash"` Coinbase common.Address `json:"coinbase"` Number uint64 `json:"number"` GasUsed uint64 `json:"gasUsed"` ParentHash common.Hash `json:"parentHash"` BaseFee *hexutil.Big `json:"baseFeePerGas"` ExcessBlobGas *uint64 `json:"excessBlobGas"` // EIP-4844 BlobGasUsed *uint64 `json:"blobGasUsed"` // EIP-4844 Alloc jsonutil.LazySortedJsonMap[common.Address, GenesisAccount] `json:"alloc"` // For genesis definitions without full state (OP-Mainnet, OP-Goerli) StateHash *common.Hash `json:"stateHash,omitempty"` }
Click to show internal directories.
Click to hide internal directories.