Commit a9dcc0b1 authored by OptimismBot's avatar OptimismBot Committed by GitHub

Merge pull request #6452 from ethereum-optimism/inphi/op-program-chain-id

op-program: Add L2 Chain ID to client boot
parents 20f11766 9e7ec4dd
package config package chainconfig
import ( import (
"fmt"
"math/big" "math/big"
"strconv"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
...@@ -97,3 +101,24 @@ var L2ChainConfigsByName = map[string]*params.ChainConfig{ ...@@ -97,3 +101,24 @@ var L2ChainConfigsByName = map[string]*params.ChainConfig{
"sepolia": OPSepoliaChainConfig, "sepolia": OPSepoliaChainConfig,
"mainnet": OPMainnetChainConfig, "mainnet": OPMainnetChainConfig,
} }
func RollupConfigByChainID(chainID uint64) (*rollup.Config, error) {
network := chaincfg.L2ChainIDToNetworkName[strconv.FormatUint(chainID, 10)]
if network == "" {
return nil, fmt.Errorf("unknown chain ID: %d", chainID)
}
config, ok := chaincfg.NetworksByName[network]
if !ok {
return nil, fmt.Errorf("unknown network %s for chain ID %d", network, chainID)
}
return &config, nil
}
func ChainConfigByChainID(chainID uint64) (*params.ChainConfig, error) {
network := chaincfg.L2ChainIDToNetworkName[strconv.FormatUint(chainID, 10)]
chainConfig, ok := L2ChainConfigsByName[network]
if !ok {
return nil, fmt.Errorf("unknown network %s for chain ID %d", network, chainID)
}
return chainConfig, nil
}
...@@ -3,9 +3,11 @@ package client ...@@ -3,9 +3,11 @@ package client
import ( import (
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"math"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
preimage "github.com/ethereum-optimism/optimism/op-preimage" preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/chainconfig"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
...@@ -15,15 +17,23 @@ const ( ...@@ -15,15 +17,23 @@ const (
L2OutputRootLocalIndex L2OutputRootLocalIndex
L2ClaimLocalIndex L2ClaimLocalIndex
L2ClaimBlockNumberLocalIndex L2ClaimBlockNumberLocalIndex
L2ChainIDLocalIndex
// These local keys are only used for custom chains
L2ChainConfigLocalIndex L2ChainConfigLocalIndex
RollupConfigLocalIndex RollupConfigLocalIndex
) )
// CustomChainIDIndicator is used to detect when the program should load custom chain configuration
const CustomChainIDIndicator = uint64(math.MaxUint64)
type BootInfo struct { type BootInfo struct {
L1Head common.Hash L1Head common.Hash
L2OutputRoot common.Hash L2OutputRoot common.Hash
L2Claim common.Hash L2Claim common.Hash
L2ClaimBlockNumber uint64 L2ClaimBlockNumber uint64
L2ChainID uint64
L2ChainConfig *params.ChainConfig L2ChainConfig *params.ChainConfig
RollupConfig *rollup.Config RollupConfig *rollup.Config
} }
...@@ -45,22 +55,39 @@ func (br *BootstrapClient) BootInfo() *BootInfo { ...@@ -45,22 +55,39 @@ func (br *BootstrapClient) BootInfo() *BootInfo {
l2OutputRoot := common.BytesToHash(br.r.Get(L2OutputRootLocalIndex)) l2OutputRoot := common.BytesToHash(br.r.Get(L2OutputRootLocalIndex))
l2Claim := common.BytesToHash(br.r.Get(L2ClaimLocalIndex)) l2Claim := common.BytesToHash(br.r.Get(L2ClaimLocalIndex))
l2ClaimBlockNumber := binary.BigEndian.Uint64(br.r.Get(L2ClaimBlockNumberLocalIndex)) l2ClaimBlockNumber := binary.BigEndian.Uint64(br.r.Get(L2ClaimBlockNumberLocalIndex))
l2ChainConfig := new(params.ChainConfig) l2ChainID := binary.BigEndian.Uint64(br.r.Get(L2ChainIDLocalIndex))
var l2ChainConfig *params.ChainConfig
var rollupConfig *rollup.Config
if l2ChainID == CustomChainIDIndicator {
l2ChainConfig = new(params.ChainConfig)
err := json.Unmarshal(br.r.Get(L2ChainConfigLocalIndex), &l2ChainConfig) err := json.Unmarshal(br.r.Get(L2ChainConfigLocalIndex), &l2ChainConfig)
if err != nil { if err != nil {
panic("failed to bootstrap l2ChainConfig") panic("failed to bootstrap l2ChainConfig")
} }
rollupConfig := new(rollup.Config) rollupConfig = new(rollup.Config)
err = json.Unmarshal(br.r.Get(RollupConfigLocalIndex), rollupConfig) err = json.Unmarshal(br.r.Get(RollupConfigLocalIndex), rollupConfig)
if err != nil { if err != nil {
panic("failed to bootstrap rollup config") panic("failed to bootstrap rollup config")
} }
} else {
var err error
rollupConfig, err = chainconfig.RollupConfigByChainID(l2ChainID)
if err != nil {
panic(err)
}
l2ChainConfig, err = chainconfig.ChainConfigByChainID(l2ChainID)
if err != nil {
panic(err)
}
}
return &BootInfo{ return &BootInfo{
L1Head: l1Head, L1Head: l1Head,
L2OutputRoot: l2OutputRoot, L2OutputRoot: l2OutputRoot,
L2Claim: l2Claim, L2Claim: l2Claim,
L2ClaimBlockNumber: l2ClaimBlockNumber, L2ClaimBlockNumber: l2ClaimBlockNumber,
L2ChainID: l2ChainID,
L2ChainConfig: l2ChainConfig, L2ChainConfig: l2ChainConfig,
RollupConfig: rollupConfig, RollupConfig: rollupConfig,
} }
......
...@@ -3,12 +3,13 @@ package client ...@@ -3,12 +3,13 @@ package client
import ( import (
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"fmt"
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/chaincfg"
preimage "github.com/ethereum-optimism/optimism/op-preimage" preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/chainconfig"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -18,16 +19,46 @@ func TestBootstrapClient(t *testing.T) { ...@@ -18,16 +19,46 @@ func TestBootstrapClient(t *testing.T) {
L2OutputRoot: common.HexToHash("0x2222"), L2OutputRoot: common.HexToHash("0x2222"),
L2Claim: common.HexToHash("0x3333"), L2Claim: common.HexToHash("0x3333"),
L2ClaimBlockNumber: 1, L2ClaimBlockNumber: 1,
L2ChainConfig: params.GoerliChainConfig, L2ChainID: chaincfg.Goerli.L2ChainID.Uint64(),
L2ChainConfig: chainconfig.OPGoerliChainConfig,
RollupConfig: &chaincfg.Goerli, RollupConfig: &chaincfg.Goerli,
} }
mockOracle := &mockBoostrapOracle{bootInfo} mockOracle := &mockBoostrapOracle{bootInfo, false}
readBootInfo := NewBootstrapClient(mockOracle).BootInfo() readBootInfo := NewBootstrapClient(mockOracle).BootInfo()
require.EqualValues(t, bootInfo, readBootInfo) require.EqualValues(t, bootInfo, readBootInfo)
} }
func TestBootstrapClient_CustomChain(t *testing.T) {
bootInfo := &BootInfo{
L1Head: common.HexToHash("0x1111"),
L2OutputRoot: common.HexToHash("0x2222"),
L2Claim: common.HexToHash("0x3333"),
L2ClaimBlockNumber: 1,
L2ChainID: CustomChainIDIndicator,
L2ChainConfig: chainconfig.OPGoerliChainConfig,
RollupConfig: &chaincfg.Goerli,
}
mockOracle := &mockBoostrapOracle{bootInfo, true}
readBootInfo := NewBootstrapClient(mockOracle).BootInfo()
require.EqualValues(t, bootInfo, readBootInfo)
}
func TestBootstrapClient_UnknownChainPanics(t *testing.T) {
bootInfo := &BootInfo{
L1Head: common.HexToHash("0x1111"),
L2OutputRoot: common.HexToHash("0x2222"),
L2Claim: common.HexToHash("0x3333"),
L2ClaimBlockNumber: 1,
L2ChainID: uint64(0xdead),
}
mockOracle := &mockBoostrapOracle{bootInfo, false}
client := NewBootstrapClient(mockOracle)
require.Panics(t, func() { client.BootInfo() })
}
type mockBoostrapOracle struct { type mockBoostrapOracle struct {
b *BootInfo b *BootInfo
custom bool
} }
func (o *mockBoostrapOracle) Get(key preimage.Key) []byte { func (o *mockBoostrapOracle) Get(key preimage.Key) []byte {
...@@ -40,10 +71,18 @@ func (o *mockBoostrapOracle) Get(key preimage.Key) []byte { ...@@ -40,10 +71,18 @@ func (o *mockBoostrapOracle) Get(key preimage.Key) []byte {
return o.b.L2Claim[:] return o.b.L2Claim[:]
case L2ClaimBlockNumberLocalIndex.PreimageKey(): case L2ClaimBlockNumberLocalIndex.PreimageKey():
return binary.BigEndian.AppendUint64(nil, o.b.L2ClaimBlockNumber) return binary.BigEndian.AppendUint64(nil, o.b.L2ClaimBlockNumber)
case L2ChainIDLocalIndex.PreimageKey():
return binary.BigEndian.AppendUint64(nil, o.b.L2ChainID)
case L2ChainConfigLocalIndex.PreimageKey(): case L2ChainConfigLocalIndex.PreimageKey():
if !o.custom {
panic(fmt.Sprintf("unexpected oracle request for preimage key %x", key.PreimageKey()))
}
b, _ := json.Marshal(o.b.L2ChainConfig) b, _ := json.Marshal(o.b.L2ChainConfig)
return b return b
case RollupConfigLocalIndex.PreimageKey(): case RollupConfigLocalIndex.PreimageKey():
if !o.custom {
panic(fmt.Sprintf("unexpected oracle request for preimage key %x", key.PreimageKey()))
}
b, _ := json.Marshal(o.b.RollupConfig) b, _ := json.Marshal(o.b.RollupConfig)
return b return b
default: default:
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/sources" "github.com/ethereum-optimism/optimism/op-node/sources"
"github.com/ethereum-optimism/optimism/op-program/chainconfig"
"github.com/ethereum-optimism/optimism/op-program/host/config" "github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
...@@ -46,7 +47,7 @@ func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) { ...@@ -46,7 +47,7 @@ func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs()) cfg := configForArgs(t, addRequiredArgs())
defaultCfg := config.NewConfig( defaultCfg := config.NewConfig(
&chaincfg.Goerli, &chaincfg.Goerli,
config.OPGoerliChainConfig, chainconfig.OPGoerliChainConfig,
common.HexToHash(l1HeadValue), common.HexToHash(l1HeadValue),
common.HexToHash(l2HeadValue), common.HexToHash(l2HeadValue),
common.HexToHash(l2OutputRoot), common.HexToHash(l2OutputRoot),
...@@ -114,7 +115,7 @@ func TestL2Genesis(t *testing.T) { ...@@ -114,7 +115,7 @@ func TestL2Genesis(t *testing.T) {
t.Run("NotRequiredForGoerli", func(t *testing.T) { t.Run("NotRequiredForGoerli", func(t *testing.T) {
cfg := configForArgs(t, replaceRequiredArg("--network", "goerli")) cfg := configForArgs(t, replaceRequiredArg("--network", "goerli"))
require.Equal(t, config.OPGoerliChainConfig, cfg.L2ChainConfig) require.Equal(t, chainconfig.OPGoerliChainConfig, cfg.L2ChainConfig)
}) })
} }
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
opnode "github.com/ethereum-optimism/optimism/op-node" opnode "github.com/ethereum-optimism/optimism/op-node"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/sources" "github.com/ethereum-optimism/optimism/op-node/sources"
"github.com/ethereum-optimism/optimism/op-program/chainconfig"
"github.com/ethereum-optimism/optimism/op-program/host/flags" "github.com/ethereum-optimism/optimism/op-program/host/flags"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
...@@ -156,7 +157,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) { ...@@ -156,7 +157,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
var l2ChainConfig *params.ChainConfig var l2ChainConfig *params.ChainConfig
if l2GenesisPath == "" { if l2GenesisPath == "" {
networkName := ctx.String(flags.Network.Name) networkName := ctx.String(flags.Network.Name)
l2ChainConfig = L2ChainConfigsByName[networkName] l2ChainConfig = chainconfig.L2ChainConfigsByName[networkName]
if l2ChainConfig == nil { if l2ChainConfig == nil {
return nil, fmt.Errorf("flag %s is required for network %s", flags.L2GenesisPath.Name, networkName) return nil, fmt.Errorf("flag %s is required for network %s", flags.L2GenesisPath.Name, networkName)
} }
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
preimage "github.com/ethereum-optimism/optimism/op-preimage" preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/chainconfig"
"github.com/ethereum-optimism/optimism/op-program/client" "github.com/ethereum-optimism/optimism/op-program/client"
"github.com/ethereum-optimism/optimism/op-program/client/l1" "github.com/ethereum-optimism/optimism/op-program/client/l1"
"github.com/ethereum-optimism/optimism/op-program/host/config" "github.com/ethereum-optimism/optimism/op-program/host/config"
...@@ -24,7 +25,7 @@ func TestServerMode(t *testing.T) { ...@@ -24,7 +25,7 @@ func TestServerMode(t *testing.T) {
l1Head := common.Hash{0x11} l1Head := common.Hash{0x11}
l2OutputRoot := common.Hash{0x33} l2OutputRoot := common.Hash{0x33}
cfg := config.NewConfig(&chaincfg.Goerli, config.OPGoerliChainConfig, l1Head, common.Hash{0x22}, l2OutputRoot, common.Hash{0x44}, 1000) cfg := config.NewConfig(&chaincfg.Goerli, chainconfig.OPGoerliChainConfig, l1Head, common.Hash{0x22}, l2OutputRoot, common.Hash{0x44}, 1000)
cfg.DataDir = dir cfg.DataDir = dir
cfg.ServerMode = true cfg.ServerMode = true
......
...@@ -22,6 +22,7 @@ var ( ...@@ -22,6 +22,7 @@ var (
l2OutputRootKey = client.L2OutputRootLocalIndex.PreimageKey() l2OutputRootKey = client.L2OutputRootLocalIndex.PreimageKey()
l2ClaimKey = client.L2ClaimLocalIndex.PreimageKey() l2ClaimKey = client.L2ClaimLocalIndex.PreimageKey()
l2ClaimBlockNumberKey = client.L2ClaimBlockNumberLocalIndex.PreimageKey() l2ClaimBlockNumberKey = client.L2ClaimBlockNumberLocalIndex.PreimageKey()
l2ChainIDKey = client.L2ChainIDLocalIndex.PreimageKey()
l2ChainConfigKey = client.L2ChainConfigLocalIndex.PreimageKey() l2ChainConfigKey = client.L2ChainConfigLocalIndex.PreimageKey()
rollupKey = client.RollupConfigLocalIndex.PreimageKey() rollupKey = client.RollupConfigLocalIndex.PreimageKey()
) )
...@@ -36,6 +37,8 @@ func (s *LocalPreimageSource) Get(key common.Hash) ([]byte, error) { ...@@ -36,6 +37,8 @@ func (s *LocalPreimageSource) Get(key common.Hash) ([]byte, error) {
return s.config.L2Claim.Bytes(), nil return s.config.L2Claim.Bytes(), nil
case l2ClaimBlockNumberKey: case l2ClaimBlockNumberKey:
return binary.BigEndian.AppendUint64(nil, s.config.L2ClaimBlockNumber), nil return binary.BigEndian.AppendUint64(nil, s.config.L2ClaimBlockNumber), nil
case l2ChainIDKey:
return binary.BigEndian.AppendUint64(nil, client.CustomChainIDIndicator), nil
case l2ChainConfigKey: case l2ChainConfigKey:
return json.Marshal(s.config.L2ChainConfig) return json.Marshal(s.config.L2ChainConfig)
case rollupKey: case rollupKey:
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/chaincfg"
preimage "github.com/ethereum-optimism/optimism/op-preimage" preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/client"
"github.com/ethereum-optimism/optimism/op-program/host/config" "github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
...@@ -32,6 +33,7 @@ func TestLocalPreimageSource(t *testing.T) { ...@@ -32,6 +33,7 @@ func TestLocalPreimageSource(t *testing.T) {
{"L2OutputRoot", l2OutputRootKey, cfg.L2OutputRoot.Bytes()}, {"L2OutputRoot", l2OutputRootKey, cfg.L2OutputRoot.Bytes()},
{"L2Claim", l2ClaimKey, cfg.L2Claim.Bytes()}, {"L2Claim", l2ClaimKey, cfg.L2Claim.Bytes()},
{"L2ClaimBlockNumber", l2ClaimBlockNumberKey, binary.BigEndian.AppendUint64(nil, cfg.L2ClaimBlockNumber)}, {"L2ClaimBlockNumber", l2ClaimBlockNumberKey, binary.BigEndian.AppendUint64(nil, cfg.L2ClaimBlockNumber)},
{"L2ChainID", l2ChainIDKey, binary.BigEndian.AppendUint64(nil, client.CustomChainIDIndicator)},
{"Rollup", rollupKey, asJson(t, cfg.Rollup)}, {"Rollup", rollupKey, asJson(t, cfg.Rollup)},
{"ChainConfig", l2ChainConfigKey, asJson(t, cfg.L2ChainConfig)}, {"ChainConfig", l2ChainConfigKey, asJson(t, cfg.L2ChainConfig)},
{"Unknown", preimage.LocalIndexKey(1000).PreimageKey(), nil}, {"Unknown", preimage.LocalIndexKey(1000).PreimageKey(), nil},
......
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