Commit 9ee5ac1f authored by Hamdi Allam's avatar Hamdi Allam Committed by GitHub

Merge pull request #7614 from ethereum-optimism/indexer.config

fix(indexer): indexer config precedence
parents 16132b26 3ff19490
......@@ -144,60 +144,72 @@ type ServerConfig struct {
func LoadConfig(log log.Logger, path string) (Config, error) {
log.Debug("loading config", "path", path)
var conf Config
var cfg Config
data, err := os.ReadFile(path)
if err != nil {
return conf, err
return cfg, err
}
data = []byte(os.ExpandEnv(string(data)))
log.Debug("parsed config file", "data", string(data))
if _, err := toml.Decode(string(data), &conf); err != nil {
log.Info("failed to decode config file", "err", err)
return conf, err
if _, err := toml.Decode(string(data), &cfg); err != nil {
log.Error("failed to decode config file", "err", err)
return cfg, err
}
if conf.Chain.Preset == DEVNET_L2_CHAIN_ID {
preset, err := GetDevnetPreset()
if cfg.Chain.Preset == DevnetPresetId {
preset, err := DevnetPreset()
if err != nil {
return conf, err
return cfg, err
}
conf.Chain = preset.ChainConfig
} else if conf.Chain.Preset != 0 {
preset, ok := Presets[conf.Chain.Preset]
log.Info("loaded local devnet preset")
cfg.Chain = preset.ChainConfig
} else if cfg.Chain.Preset != 0 {
preset, ok := Presets[cfg.Chain.Preset]
if !ok {
return conf, fmt.Errorf("unknown preset: %d", conf.Chain.Preset)
return cfg, fmt.Errorf("unknown preset: %d", cfg.Chain.Preset)
}
log.Info("detected preset", "preset", conf.Chain.Preset, "name", preset.Name)
log.Info("setting L1 information from preset")
conf.Chain = preset.ChainConfig
log.Info("detected preset", "preset", cfg.Chain.Preset, "name", preset.Name)
cfg.Chain = preset.ChainConfig
}
// Setup L2Contracts from predeploys
conf.Chain.L2Contracts = L2ContractsFromPredeploys()
cfg.Chain.L2Contracts = L2ContractsFromPredeploys()
// Deserialize the config file again when a preset is configured such that
// precedence is given to the config file vs the preset
if cfg.Chain.Preset > 0 {
if _, err := toml.Decode(string(data), &cfg); err != nil {
log.Error("failed to decode config file", "err", err)
return cfg, err
}
}
// Setup defaults for some unset options
// Defaults for any unset options
if conf.Chain.L1PollingInterval == 0 {
if cfg.Chain.L1PollingInterval == 0 {
log.Info("setting default L1 polling interval", "interval", defaultLoopInterval)
conf.Chain.L1PollingInterval = defaultLoopInterval
cfg.Chain.L1PollingInterval = defaultLoopInterval
}
if conf.Chain.L2PollingInterval == 0 {
if cfg.Chain.L2PollingInterval == 0 {
log.Info("setting default L2 polling interval", "interval", defaultLoopInterval)
conf.Chain.L2PollingInterval = defaultLoopInterval
cfg.Chain.L2PollingInterval = defaultLoopInterval
}
if conf.Chain.L1HeaderBufferSize == 0 {
if cfg.Chain.L1HeaderBufferSize == 0 {
log.Info("setting default L1 header buffer", "size", defaultHeaderBufferSize)
conf.Chain.L1HeaderBufferSize = defaultHeaderBufferSize
cfg.Chain.L1HeaderBufferSize = defaultHeaderBufferSize
}
if conf.Chain.L2HeaderBufferSize == 0 {
if cfg.Chain.L2HeaderBufferSize == 0 {
log.Info("setting default L2 header buffer", "size", defaultHeaderBufferSize)
conf.Chain.L2HeaderBufferSize = defaultHeaderBufferSize
cfg.Chain.L2HeaderBufferSize = defaultHeaderBufferSize
}
log.Info("loaded config")
return conf, nil
return cfg, nil
}
......@@ -141,6 +141,8 @@ func TestLoadConfigWithUnknownPreset(t *testing.T) {
logger := testlog.Logger(t, log.LvlInfo)
conf, err := LoadConfig(logger, tmpfile.Name())
require.Error(t, err)
var faultyPreset = 1234567890
require.Equal(t, conf.Chain.Preset, faultyPreset)
require.Error(t, err)
......@@ -170,10 +172,88 @@ func TestLoadConfigPollingValues(t *testing.T) {
logger := testlog.Logger(t, log.LvlInfo)
conf, err := LoadConfig(logger, tmpfile.Name())
require.NoError(t, err)
require.Equal(t, conf.Chain.L1PollingInterval, uint(1000))
require.Equal(t, conf.Chain.L2PollingInterval, uint(1005))
require.Equal(t, conf.Chain.L1HeaderBufferSize, uint(100))
require.Equal(t, conf.Chain.L2HeaderBufferSize, uint(105))
}
func TestLoadedConfigPresetPrecendence(t *testing.T) {
tmpfile, err := os.CreateTemp("", "test_bad_preset.toml")
require.NoError(t, err)
defer os.Remove(tmpfile.Name())
defer tmpfile.Close()
testData := `
[chain]
preset = 10 # Optimism Mainnet
# confirmation depths are explicitly set
l1-confirmation-depth = 50
l2-confirmation-depth = 100
# override a contract address
[chain.l1-contracts]
optimism-portal = "0x0000000000000000000000000000000000000001"
[rpcs]
l1-rpc = "https://l1.example.com"
l2-rpc = "https://l2.example.com"
`
data := []byte(testData)
err = os.WriteFile(tmpfile.Name(), data, 0644)
require.NoError(t, err)
defer os.Remove(tmpfile.Name())
err = tmpfile.Close()
require.NoError(t, err)
logger := testlog.Logger(t, log.LvlInfo)
conf, err := LoadConfig(logger, tmpfile.Name())
require.NoError(t, err)
// confirmation depths
require.Equal(t, uint(50), conf.Chain.L1ConfirmationDepth)
require.Equal(t, uint(100), conf.Chain.L2ConfirmationDepth)
// preset is used but does not overwrite config
require.Equal(t, common.HexToAddress("0x0000000000000000000000000000000000000001"), conf.Chain.L1Contracts.OptimismPortalProxy)
require.Equal(t, Presets[10].ChainConfig.L1Contracts.AddressManager, conf.Chain.L1Contracts.AddressManager)
}
func TestLocalDevnet(t *testing.T) {
tmpfile, err := os.CreateTemp("", "test_user_values.toml")
require.NoError(t, err)
defer os.Remove(tmpfile.Name())
defer tmpfile.Close()
testData := `
[chain]
preset = 901
[rpcs]
l1-rpc = "https://l1.example.com"
l2-rpc = "https://l2.example.com"
`
data := []byte(testData)
err = os.WriteFile(tmpfile.Name(), data, 0644)
require.NoError(t, err)
defer os.Remove(tmpfile.Name())
err = tmpfile.Close()
require.NoError(t, err)
logger := testlog.Logger(t, log.LvlInfo)
conf, err := LoadConfig(logger, tmpfile.Name())
require.NoError(t, err)
devnetPreset, err := DevnetPreset()
require.NoError(t, err)
require.Equal(t, devnetPreset.ChainConfig.L1Contracts, conf.Chain.L1Contracts)
}
......@@ -3,38 +3,64 @@ package config
import (
"encoding/json"
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
)
var (
filePath = "../.devnet/addresses.json"
DEVNET_L2_CHAIN_ID = 901
)
var DevnetPresetId = 901
func GetDevnetPreset() (*Preset, error) {
if _, err := os.Stat(filePath); errors.Is(err, fs.ErrNotExist) {
func DevnetPreset() (*Preset, error) {
cwd, err := os.Getwd()
if err != nil {
return nil, err
}
content, err := os.ReadFile(filePath)
root, err := findMonorepoRoot(cwd)
if err != nil {
return nil, err
}
var l1Contracts L1Contracts
if err := json.Unmarshal(content, &l1Contracts); err != nil {
devnetFilepath := filepath.Join(root, ".devnet", "addresses.json")
if _, err := os.Stat(devnetFilepath); errors.Is(err, fs.ErrNotExist) {
return nil, err
}
content, err := os.ReadFile(devnetFilepath)
if err != nil {
return nil, err
}
var l1Contracts L1Contracts
if err := json.Unmarshal(content, &l1Contracts); err != nil {
return nil, err
}
return &Preset{
Name: "devnet",
ChainConfig: ChainConfig{
Preset: DEVNET_L2_CHAIN_ID,
L1Contracts: l1Contracts,
},
Name: "Local Devnet",
ChainConfig: ChainConfig{Preset: DevnetPresetId, L1Contracts: l1Contracts},
}, nil
}
// findMonorepoRoot will recursively search upwards for a go.mod file.
// This depends on the structure of the monorepo having a go.mod file at the root.
func findMonorepoRoot(startDir string) (string, error) {
dir, err := filepath.Abs(startDir)
if err != nil {
return "", err
}
for {
modulePath := filepath.Join(dir, "go.mod")
if _, err := os.Stat(modulePath); err == nil {
return dir, nil
}
parentDir := filepath.Dir(dir)
// Check if we reached the filesystem root
if parentDir == dir {
break
}
dir = parentDir
}
return "", fmt.Errorf("monorepo root not found")
}
......@@ -57,6 +57,22 @@ var Presets = map[int]Preset{
L2BedrockStartingHeight: 4061224,
},
},
11155420: {
Name: "Optimism Sepolia",
ChainConfig: ChainConfig{
Preset: 11155420,
L1Contracts: L1Contracts{
AddressManager: common.HexToAddress("0x9bFE9c5609311DF1c011c47642253B78a4f33F4B"),
SystemConfigProxy: common.HexToAddress("0x034edD2A225f7f429A63E0f1D2084B9E0A93b538"),
OptimismPortalProxy: common.HexToAddress("0x16Fc5058F25648194471939df75CF27A2fdC48BC"),
L2OutputOracleProxy: common.HexToAddress("0x90E9c4f8a994a250F6aEfd61CAFb4F2e895D458F"),
L1CrossDomainMessengerProxy: common.HexToAddress("0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef"),
L1StandardBridgeProxy: common.HexToAddress("0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1"),
L1ERC721BridgeProxy: common.HexToAddress("0xd83e03D576d23C9AEab8cC44Fa98d058D2176D1f"),
},
L1StartingHeight: 4071408,
},
},
8453: {
Name: "Base",
ChainConfig: ChainConfig{
......@@ -137,22 +153,6 @@ var Presets = map[int]Preset{
L1StartingHeight: 8942381,
},
},
11155420: {
Name: "OP Sepolia",
ChainConfig: ChainConfig{
Preset: 11155420,
L1Contracts: L1Contracts{
AddressManager: common.HexToAddress("0x9bFE9c5609311DF1c011c47642253B78a4f33F4B"),
SystemConfigProxy: common.HexToAddress("0x034edD2A225f7f429A63E0f1D2084B9E0A93b538"),
OptimismPortalProxy: common.HexToAddress("0x16Fc5058F25648194471939df75CF27A2fdC48BC"),
L2OutputOracleProxy: common.HexToAddress("0x90E9c4f8a994a250F6aEfd61CAFb4F2e895D458F"),
L1CrossDomainMessengerProxy: common.HexToAddress("0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef"),
L1StandardBridgeProxy: common.HexToAddress("0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1"),
L1ERC721BridgeProxy: common.HexToAddress("0xd83e03D576d23C9AEab8cC44Fa98d058D2176D1f"),
},
L1StartingHeight: 4071408,
},
},
424: {
Name: "PGN",
ChainConfig: ChainConfig{
......
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