Skip to content

Commit

Permalink
op-program: Add L2 Chain ID to client boot
Browse files Browse the repository at this point in the history
  • Loading branch information
Inphi committed Aug 3, 2023
1 parent 20f1176 commit 665cb53
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package config
package chainconfig

import (
"fmt"
"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"
)

Expand Down Expand Up @@ -97,3 +101,24 @@ var L2ChainConfigsByName = map[string]*params.ChainConfig{
"sepolia": OPSepoliaChainConfig,
"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
}
49 changes: 38 additions & 11 deletions op-program/client/boot.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package client
import (
"encoding/binary"
"encoding/json"
"math"

"github.com/ethereum-optimism/optimism/op-node/rollup"
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/params"
)
Expand All @@ -15,17 +17,25 @@ const (
L2OutputRootLocalIndex
L2ClaimLocalIndex
L2ClaimBlockNumberLocalIndex
L2ChainIDLocalIndex

// These local keys are only used for custom chains
L2ChainConfigLocalIndex
RollupConfigLocalIndex
)

// CustomChainIDIndicator is used to detect when the program should load custom chain configuration
const CustomChainIDIndicator = uint64(math.MaxUint64)

type BootInfo struct {
L1Head common.Hash
L2OutputRoot common.Hash
L2Claim common.Hash
L2ClaimBlockNumber uint64
L2ChainConfig *params.ChainConfig
RollupConfig *rollup.Config
L2ChainID uint64

L2ChainConfig *params.ChainConfig
RollupConfig *rollup.Config
}

type oracleClient interface {
Expand All @@ -45,22 +55,39 @@ func (br *BootstrapClient) BootInfo() *BootInfo {
l2OutputRoot := common.BytesToHash(br.r.Get(L2OutputRootLocalIndex))
l2Claim := common.BytesToHash(br.r.Get(L2ClaimLocalIndex))
l2ClaimBlockNumber := binary.BigEndian.Uint64(br.r.Get(L2ClaimBlockNumberLocalIndex))
l2ChainConfig := new(params.ChainConfig)
err := json.Unmarshal(br.r.Get(L2ChainConfigLocalIndex), &l2ChainConfig)
if err != nil {
panic("failed to bootstrap l2ChainConfig")
}
rollupConfig := new(rollup.Config)
err = json.Unmarshal(br.r.Get(RollupConfigLocalIndex), rollupConfig)
if err != nil {
panic("failed to bootstrap rollup config")
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)
if err != nil {
panic("failed to bootstrap l2ChainConfig")
}
rollupConfig = new(rollup.Config)
err = json.Unmarshal(br.r.Get(RollupConfigLocalIndex), rollupConfig)
if err != nil {
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{
L1Head: l1Head,
L2OutputRoot: l2OutputRoot,
L2Claim: l2Claim,
L2ClaimBlockNumber: l2ClaimBlockNumber,
L2ChainID: l2ChainID,
L2ChainConfig: l2ChainConfig,
RollupConfig: rollupConfig,
}
Expand Down
46 changes: 42 additions & 4 deletions op-program/client/boot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (

"github.com/ethereum-optimism/optimism/op-node/chaincfg"
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/params"
"github.com/stretchr/testify/require"
)

Expand All @@ -18,16 +18,46 @@ func TestBootstrapClient(t *testing.T) {
L2OutputRoot: common.HexToHash("0x2222"),
L2Claim: common.HexToHash("0x3333"),
L2ClaimBlockNumber: 1,
L2ChainConfig: params.GoerliChainConfig,
L2ChainID: chaincfg.Goerli.L2ChainID.Uint64(),
L2ChainConfig: chainconfig.OPGoerliChainConfig,
RollupConfig: &chaincfg.Goerli,
}
mockOracle := &mockBoostrapOracle{bootInfo}
mockOracle := &mockBoostrapOracle{bootInfo, false}
readBootInfo := NewBootstrapClient(mockOracle).BootInfo()
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 {
b *BootInfo
b *BootInfo
custom bool
}

func (o *mockBoostrapOracle) Get(key preimage.Key) []byte {
Expand All @@ -40,10 +70,18 @@ func (o *mockBoostrapOracle) Get(key preimage.Key) []byte {
return o.b.L2Claim[:]
case L2ClaimBlockNumberLocalIndex.PreimageKey():
return binary.BigEndian.AppendUint64(nil, o.b.L2ClaimBlockNumber)
case L2ChainIDLocalIndex.PreimageKey():
return binary.BigEndian.AppendUint64(nil, o.b.L2ChainID)
case L2ChainConfigLocalIndex.PreimageKey():
if !o.custom {
panic("unexpected key")
}
b, _ := json.Marshal(o.b.L2ChainConfig)
return b
case RollupConfigLocalIndex.PreimageKey():
if !o.custom {
panic("unexpected key")
}
b, _ := json.Marshal(o.b.RollupConfig)
return b
default:
Expand Down
5 changes: 3 additions & 2 deletions op-program/host/cmd/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"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/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
Expand Down Expand Up @@ -46,7 +47,7 @@ func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs())
defaultCfg := config.NewConfig(
&chaincfg.Goerli,
config.OPGoerliChainConfig,
chainconfig.OPGoerliChainConfig,
common.HexToHash(l1HeadValue),
common.HexToHash(l2HeadValue),
common.HexToHash(l2OutputRoot),
Expand Down Expand Up @@ -114,7 +115,7 @@ func TestL2Genesis(t *testing.T) {

t.Run("NotRequiredForGoerli", func(t *testing.T) {
cfg := configForArgs(t, replaceRequiredArg("--network", "goerli"))
require.Equal(t, config.OPGoerliChainConfig, cfg.L2ChainConfig)
require.Equal(t, chainconfig.OPGoerliChainConfig, cfg.L2ChainConfig)
})
}

Expand Down
3 changes: 2 additions & 1 deletion op-program/host/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
opnode "github.com/ethereum-optimism/optimism/op-node"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"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/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
Expand Down Expand Up @@ -156,7 +157,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
var l2ChainConfig *params.ChainConfig
if l2GenesisPath == "" {
networkName := ctx.String(flags.Network.Name)
l2ChainConfig = L2ChainConfigsByName[networkName]
l2ChainConfig = chainconfig.L2ChainConfigsByName[networkName]
if l2ChainConfig == nil {
return nil, fmt.Errorf("flag %s is required for network %s", flags.L2GenesisPath.Name, networkName)
}
Expand Down
3 changes: 2 additions & 1 deletion op-program/host/host_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/testlog"
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/l1"
"github.com/ethereum-optimism/optimism/op-program/host/config"
Expand All @@ -24,7 +25,7 @@ func TestServerMode(t *testing.T) {

l1Head := common.Hash{0x11}
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.ServerMode = true

Expand Down
3 changes: 3 additions & 0 deletions op-program/host/kvstore/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var (
l2OutputRootKey = client.L2OutputRootLocalIndex.PreimageKey()
l2ClaimKey = client.L2ClaimLocalIndex.PreimageKey()
l2ClaimBlockNumberKey = client.L2ClaimBlockNumberLocalIndex.PreimageKey()
l2ChainIDKey = client.L2ChainIDLocalIndex.PreimageKey()
l2ChainConfigKey = client.L2ChainConfigLocalIndex.PreimageKey()
rollupKey = client.RollupConfigLocalIndex.PreimageKey()
)
Expand All @@ -36,6 +37,8 @@ func (s *LocalPreimageSource) Get(key common.Hash) ([]byte, error) {
return s.config.L2Claim.Bytes(), nil
case l2ClaimBlockNumberKey:
return binary.BigEndian.AppendUint64(nil, s.config.L2ClaimBlockNumber), nil
case l2ChainIDKey:
return binary.BigEndian.AppendUint64(nil, client.CustomChainIDIndicator), nil
case l2ChainConfigKey:
return json.Marshal(s.config.L2ChainConfig)
case rollupKey:
Expand Down
2 changes: 2 additions & 0 deletions op-program/host/kvstore/local_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/ethereum-optimism/optimism/op-node/chaincfg"
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/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
Expand All @@ -32,6 +33,7 @@ func TestLocalPreimageSource(t *testing.T) {
{"L2OutputRoot", l2OutputRootKey, cfg.L2OutputRoot.Bytes()},
{"L2Claim", l2ClaimKey, cfg.L2Claim.Bytes()},
{"L2ClaimBlockNumber", l2ClaimBlockNumberKey, binary.BigEndian.AppendUint64(nil, cfg.L2ClaimBlockNumber)},
{"L2ChainID", l2ChainIDKey, binary.BigEndian.AppendUint64(nil, client.CustomChainIDIndicator)},
{"Rollup", rollupKey, asJson(t, cfg.Rollup)},
{"ChainConfig", l2ChainConfigKey, asJson(t, cfg.L2ChainConfig)},
{"Unknown", preimage.LocalIndexKey(1000).PreimageKey(), nil},
Expand Down

0 comments on commit 665cb53

Please sign in to comment.