Commit d895830a authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

op-program: Move towards using eth.ChainID instead of uint64 (#13850)

* op-program: Move towards using eth.ChainID instead of uint64

* op-program: Move oracle API over to ChainID

* Review feedback
parent 0a327e67
......@@ -5,7 +5,7 @@ import "github.com/ethereum-optimism/optimism/op-service/eth"
func responseToSuper(prevRoot eth.SuperRootResponse) *eth.SuperV1 {
prevChainOutputs := make([]eth.ChainIDAndOutput, 0, len(prevRoot.Chains))
for _, chain := range prevRoot.Chains {
prevChainOutputs = append(prevChainOutputs, eth.ChainIDAndOutput{ChainID: chain.ChainID.ToBig().Uint64(), Output: chain.Canonical})
prevChainOutputs = append(prevChainOutputs, eth.ChainIDAndOutput{ChainID: chain.ChainID, Output: chain.Canonical})
}
superV1 := eth.NewSuperV1(prevRoot.Timestamp, prevChainOutputs...)
return superV1
......
......@@ -23,7 +23,7 @@ func TestResponseToSuper(t *testing.T) {
expected := &eth.SuperV1{
Timestamp: 4978924,
Chains: []eth.ChainIDAndOutput{
{ChainID: 2987, Output: eth.Bytes32{0x88}},
{ChainID: eth.ChainIDFromUInt64(2987), Output: eth.Bytes32{0x88}},
},
}
actual := responseToSuper(input)
......@@ -50,8 +50,8 @@ func TestResponseToSuper(t *testing.T) {
expected := &eth.SuperV1{
Timestamp: 4978924,
Chains: []eth.ChainIDAndOutput{
{ChainID: 100, Output: eth.Bytes32{0x10}},
{ChainID: 2987, Output: eth.Bytes32{0x88}},
{ChainID: eth.ChainIDFromUInt64(100), Output: eth.Bytes32{0x10}},
{ChainID: eth.ChainIDFromUInt64(2987), Output: eth.Bytes32{0x88}},
},
}
actual := responseToSuper(input)
......
......@@ -75,11 +75,11 @@ func TestGet(t *testing.T) {
outputB2 := testutils.RandomOutputV0(rng)
superRoot1 := eth.NewSuperV1(
prestateTimestamp,
eth.ChainIDAndOutput{ChainID: 1, Output: eth.OutputRoot(outputA1)},
eth.ChainIDAndOutput{ChainID: 2, Output: eth.OutputRoot(outputB1)})
eth.ChainIDAndOutput{ChainID: eth.ChainIDFromUInt64(1), Output: eth.OutputRoot(outputA1)},
eth.ChainIDAndOutput{ChainID: eth.ChainIDFromUInt64(2), Output: eth.OutputRoot(outputB1)})
superRoot2 := eth.NewSuperV1(prestateTimestamp+1,
eth.ChainIDAndOutput{ChainID: 1, Output: eth.OutputRoot(outputA2)},
eth.ChainIDAndOutput{ChainID: 2, Output: eth.OutputRoot(outputB2)})
eth.ChainIDAndOutput{ChainID: eth.ChainIDFromUInt64(1), Output: eth.OutputRoot(outputA2)},
eth.ChainIDAndOutput{ChainID: eth.ChainIDFromUInt64(2), Output: eth.OutputRoot(outputB2)})
stubSupervisor.Add(eth.SuperRootResponse{
Timestamp: prestateTimestamp,
SuperRoot: eth.SuperRoot(superRoot1),
......
......@@ -3,7 +3,6 @@ package interop
import (
"context"
"fmt"
"math/big"
"slices"
"github.com/ethereum-optimism/optimism/op-node/rollup"
......@@ -16,7 +15,7 @@ type OutputRootSource interface {
}
type chainInfo struct {
chainID *big.Int
chainID eth.ChainID
source OutputRootSource
config *rollup.Config
}
......@@ -33,7 +32,7 @@ func NewSuperRootSource(ctx context.Context, sources ...OutputRootSource) (*Supe
if err != nil {
return nil, fmt.Errorf("failed to load rollup config: %w", err)
}
chainID := config.L2ChainID
chainID := eth.ChainIDFromBig(config.L2ChainID)
chains = append(chains, &chainInfo{
chainID: chainID,
source: source,
......@@ -57,7 +56,7 @@ func (s *SuperRootSource) CreateSuperRoot(ctx context.Context, timestamp uint64)
if err != nil {
return nil, fmt.Errorf("failed to load output root for chain %v at block %v: %w", chain.chainID, blockNum, err)
}
chains[i] = eth.ChainIDAndOutput{ChainID: chain.chainID.Uint64(), Output: output.OutputRoot}
chains[i] = eth.ChainIDAndOutput{ChainID: chain.chainID, Output: output.OutputRoot}
}
output := eth.SuperV1{
Timestamp: timestamp,
......
......@@ -2,6 +2,7 @@ package helpers
import (
"github.com/ethereum-optimism/optimism/op-e2e/actions/helpers"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
)
......@@ -23,7 +24,7 @@ type FixtureInputs struct {
L2Claim common.Hash `toml:"l2-claim"`
L2Head common.Hash `toml:"l2-head"`
L2OutputRoot common.Hash `toml:"l2-output-root"`
L2ChainID uint64 `toml:"l2-chain-id"`
L2ChainID eth.ChainID `toml:"l2-chain-id"`
L1Head common.Hash `toml:"l1-head"`
AgreedPrestate []byte `toml:"agreed-prestate"`
InteropEnabled bool `toml:"use-interop"`
......
......@@ -13,6 +13,7 @@ import (
"github.com/ethereum-optimism/optimism/op-program/host/kvstore"
"github.com/ethereum-optimism/optimism/op-program/host/prefetcher"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
......@@ -44,7 +45,7 @@ func WithPreInteropDefaults(t helpers.Testing, l2ClaimBlockNum uint64, l2 *helpe
f.L2Claim = common.Hash(claimRoot.OutputRoot)
f.L2Head = preRoot.BlockRef.Hash
f.L2OutputRoot = common.Hash(preRoot.OutputRoot)
f.L2ChainID = l2.RollupCfg.L2ChainID.Uint64()
f.L2ChainID = eth.ChainIDFromBig(l2.RollupCfg.L2ChainID)
f.L2Sources = []*FaultProofProgramL2Source{
{
......
......@@ -9,6 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/params"
)
......@@ -21,21 +22,21 @@ func OPSepoliaChainConfig() *params.ChainConfig {
//go:embed configs/*json
var customChainConfigFS embed.FS
func RollupConfigByChainID(chainID uint64) (*rollup.Config, error) {
config, err := rollup.LoadOPStackRollupConfig(chainID)
func RollupConfigByChainID(chainID eth.ChainID) (*rollup.Config, error) {
config, err := rollup.LoadOPStackRollupConfig(eth.EvilChainIDToUInt64(chainID))
if err == nil {
return config, err
}
return rollupConfigByChainID(chainID, customChainConfigFS)
}
func rollupConfigByChainID(chainID uint64, customChainFS embed.FS) (*rollup.Config, error) {
func rollupConfigByChainID(chainID eth.ChainID, customChainFS embed.FS) (*rollup.Config, error) {
// Load custom rollup configs from embed FS
file, err := customChainFS.Open(fmt.Sprintf("configs/%d-rollup.json", chainID))
file, err := customChainFS.Open(fmt.Sprintf("configs/%v-rollup.json", chainID))
if errors.Is(err, os.ErrNotExist) {
return nil, fmt.Errorf("no rollup config available for chain ID: %d", chainID)
} else if err != nil {
return nil, fmt.Errorf("failed to get rollup config for chain ID %d: %w", chainID, err)
return nil, fmt.Errorf("failed to get rollup config for chain ID %v: %w", chainID, err)
}
defer file.Close()
......@@ -43,26 +44,26 @@ func rollupConfigByChainID(chainID uint64, customChainFS embed.FS) (*rollup.Conf
return &customRollupConfig, customRollupConfig.ParseRollupConfig(file)
}
func ChainConfigByChainID(chainID uint64) (*params.ChainConfig, error) {
config, err := params.LoadOPStackChainConfig(chainID)
func ChainConfigByChainID(chainID eth.ChainID) (*params.ChainConfig, error) {
config, err := params.LoadOPStackChainConfig(eth.EvilChainIDToUInt64(chainID))
if err == nil {
return config, err
}
return chainConfigByChainID(chainID, customChainConfigFS)
}
func chainConfigByChainID(chainID uint64, customChainFS embed.FS) (*params.ChainConfig, error) {
func chainConfigByChainID(chainID eth.ChainID, customChainFS embed.FS) (*params.ChainConfig, error) {
// Load from custom chain configs from embed FS
data, err := customChainFS.ReadFile(fmt.Sprintf("configs/%d-genesis-l2.json", chainID))
data, err := customChainFS.ReadFile(fmt.Sprintf("configs/%v-genesis-l2.json", chainID))
if errors.Is(err, os.ErrNotExist) {
return nil, fmt.Errorf("no chain config available for chain ID: %d", chainID)
} else if err != nil {
return nil, fmt.Errorf("failed to get chain config for chain ID %d: %w", chainID, err)
return nil, fmt.Errorf("failed to get chain config for chain ID %v: %w", chainID, err)
}
var genesis core.Genesis
err = json.Unmarshal(data, &genesis)
if err != nil {
return nil, fmt.Errorf("failed to parse chain config for chain ID %d: %w", chainID, err)
return nil, fmt.Errorf("failed to parse chain config for chain ID %v: %w", chainID, err)
}
return genesis.Config, nil
}
......@@ -72,7 +73,7 @@ func mustLoadChainConfig(name string) *params.ChainConfig {
if chainCfg == nil {
panic(fmt.Errorf("unknown chain config %q", name))
}
cfg, err := ChainConfigByChainID(chainCfg.ChainID)
cfg, err := ChainConfigByChainID(eth.ChainIDFromUInt64(chainCfg.ChainID))
if err != nil {
panic(fmt.Errorf("failed to load rollup config: %q: %w", name, err))
}
......
......@@ -4,26 +4,27 @@ import (
"testing"
"github.com/ethereum-optimism/optimism/op-program/chainconfig/test"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/stretchr/testify/require"
)
// TestGetCustomRollupConfig tests loading the custom rollup configs from test embed FS.
func TestGetCustomRollupConfig(t *testing.T) {
config, err := rollupConfigByChainID(901, test.TestCustomChainConfigFS)
config, err := rollupConfigByChainID(eth.ChainIDFromUInt64(901), test.TestCustomChainConfigFS)
require.NoError(t, err)
require.Equal(t, config.L1ChainID.Uint64(), uint64(900))
require.Equal(t, config.L2ChainID.Uint64(), uint64(901))
_, err = rollupConfigByChainID(900, test.TestCustomChainConfigFS)
_, err = rollupConfigByChainID(eth.ChainIDFromUInt64(900), test.TestCustomChainConfigFS)
require.Error(t, err)
}
// TestGetCustomChainConfig tests loading the custom chain configs from test embed FS.
func TestGetCustomChainConfig(t *testing.T) {
config, err := chainConfigByChainID(901, test.TestCustomChainConfigFS)
config, err := chainConfigByChainID(eth.ChainIDFromUInt64(901), test.TestCustomChainConfigFS)
require.NoError(t, err)
require.Equal(t, config.ChainID.Uint64(), uint64(901))
_, err = chainConfigByChainID(900, test.TestCustomChainConfigFS)
_, err = chainConfigByChainID(eth.ChainIDFromUInt64(900), test.TestCustomChainConfigFS)
require.Error(t, err)
}
......@@ -7,19 +7,20 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-program/chainconfig"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
)
// CustomChainIDIndicator is used to detect when the program should load custom chain configuration
const CustomChainIDIndicator = uint64(math.MaxUint64)
var CustomChainIDIndicator = eth.ChainIDFromUInt64(uint64(math.MaxUint64))
type BootInfo struct {
L1Head common.Hash
L2OutputRoot common.Hash
L2Claim common.Hash
L2ClaimBlockNumber uint64
L2ChainID uint64
L2ChainID eth.ChainID
L2ChainConfig *params.ChainConfig
RollupConfig *rollup.Config
......@@ -38,7 +39,7 @@ 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))
l2ChainID := binary.BigEndian.Uint64(br.r.Get(L2ChainIDLocalIndex))
l2ChainID := eth.ChainIDFromUInt64(binary.BigEndian.Uint64(br.r.Get(L2ChainIDLocalIndex)))
var l2ChainConfig *params.ChainConfig
var rollupConfig *rollup.Config
......
......@@ -8,6 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-program/chainconfig"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
)
......@@ -26,19 +27,19 @@ type BootInfoInterop struct {
}
type ConfigSource interface {
RollupConfig(chainID uint64) (*rollup.Config, error)
ChainConfig(chainID uint64) (*params.ChainConfig, error)
RollupConfig(chainID eth.ChainID) (*rollup.Config, error)
ChainConfig(chainID eth.ChainID) (*params.ChainConfig, error)
}
type OracleConfigSource struct {
oracle oracleClient
customConfigsLoaded bool
l2ChainConfigs map[uint64]*params.ChainConfig
rollupConfigs map[uint64]*rollup.Config
l2ChainConfigs map[eth.ChainID]*params.ChainConfig
rollupConfigs map[eth.ChainID]*rollup.Config
}
func (c *OracleConfigSource) RollupConfig(chainID uint64) (*rollup.Config, error) {
func (c *OracleConfigSource) RollupConfig(chainID eth.ChainID) (*rollup.Config, error) {
if cfg, ok := c.rollupConfigs[chainID]; ok {
return cfg, nil
}
......@@ -57,7 +58,7 @@ func (c *OracleConfigSource) RollupConfig(chainID uint64) (*rollup.Config, error
return cfg, nil
}
func (c *OracleConfigSource) ChainConfig(chainID uint64) (*params.ChainConfig, error) {
func (c *OracleConfigSource) ChainConfig(chainID eth.ChainID) (*params.ChainConfig, error) {
if cfg, ok := c.l2ChainConfigs[chainID]; ok {
return cfg, nil
}
......@@ -83,7 +84,7 @@ func (c *OracleConfigSource) loadCustomConfigs() {
panic("failed to bootstrap rollup configs")
}
for _, config := range rollupConfigs {
c.rollupConfigs[config.L2ChainID.Uint64()] = config
c.rollupConfigs[eth.ChainIDFromBig(config.L2ChainID)] = config
}
var chainConfigs []*params.ChainConfig
......@@ -92,7 +93,7 @@ func (c *OracleConfigSource) loadCustomConfigs() {
panic("failed to bootstrap chain configs")
}
for _, config := range chainConfigs {
c.l2ChainConfigs[config.ChainID.Uint64()] = config
c.l2ChainConfigs[eth.ChainIDFromBig(config.ChainID)] = config
}
c.customConfigsLoaded = true
}
......@@ -106,8 +107,8 @@ func BootstrapInterop(r oracleClient) *BootInfoInterop {
return &BootInfoInterop{
Configs: &OracleConfigSource{
oracle: r,
l2ChainConfigs: make(map[uint64]*params.ChainConfig),
rollupConfigs: make(map[uint64]*rollup.Config),
l2ChainConfigs: make(map[eth.ChainID]*params.ChainConfig),
rollupConfigs: make(map[eth.ChainID]*rollup.Config),
},
L1Head: l1Head,
AgreedPrestate: agreedPrestate,
......
......@@ -10,6 +10,7 @@ import (
"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-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
......@@ -40,7 +41,7 @@ func TestInteropBootstrap_RollupConfigBuiltIn(t *testing.T) {
}
mockOracle := newMockInteropBootstrapOracle(expected, false)
actual := BootstrapInterop(mockOracle)
actualCfg, err := actual.Configs.RollupConfig(expectedCfg.L2ChainID.Uint64())
actualCfg, err := actual.Configs.RollupConfig(eth.ChainIDFromBig(expectedCfg.L2ChainID))
require.NoError(t, err)
require.Equal(t, expectedCfg, actualCfg)
}
......@@ -57,11 +58,11 @@ func TestInteropBootstrap_RollupConfigCustom(t *testing.T) {
mockOracle := newMockInteropBootstrapOracle(source, true)
mockOracle.rollupCfgs = []*rollup.Config{config1, config2}
actual := BootstrapInterop(mockOracle)
actualCfg, err := actual.Configs.RollupConfig(config1.L2ChainID.Uint64())
actualCfg, err := actual.Configs.RollupConfig(eth.ChainIDFromBig(config1.L2ChainID))
require.NoError(t, err)
require.Equal(t, config1, actualCfg)
actualCfg, err = actual.Configs.RollupConfig(config2.L2ChainID.Uint64())
actualCfg, err = actual.Configs.RollupConfig(eth.ChainIDFromBig(config2.L2ChainID))
require.NoError(t, err)
require.Equal(t, config2, actualCfg)
}
......@@ -76,7 +77,7 @@ func TestInteropBootstrap_ChainConfigBuiltIn(t *testing.T) {
}
mockOracle := newMockInteropBootstrapOracle(expected, false)
actual := BootstrapInterop(mockOracle)
actualCfg, err := actual.Configs.ChainConfig(expectedCfg.ChainID.Uint64())
actualCfg, err := actual.Configs.ChainConfig(eth.ChainIDFromBig(expectedCfg.ChainID))
require.NoError(t, err)
require.Equal(t, expectedCfg, actualCfg)
}
......@@ -94,11 +95,11 @@ func TestInteropBootstrap_ChainConfigCustom(t *testing.T) {
mockOracle.chainCfgs = []*params.ChainConfig{config1, config2}
actual := BootstrapInterop(mockOracle)
actualCfg, err := actual.Configs.ChainConfig(config1.ChainID.Uint64())
actualCfg, err := actual.Configs.ChainConfig(eth.ChainIDFromBig(config1.ChainID))
require.NoError(t, err)
require.Equal(t, config1, actualCfg)
actualCfg, err = actual.Configs.ChainConfig(config2.ChainID.Uint64())
actualCfg, err = actual.Configs.ChainConfig(eth.ChainIDFromBig(config2.ChainID))
require.NoError(t, err)
require.Equal(t, config2, actualCfg)
}
......
......@@ -9,6 +9,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/chainconfig"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
......@@ -20,7 +21,7 @@ func TestBootstrapClient(t *testing.T) {
L2OutputRoot: common.HexToHash("0x2222"),
L2Claim: common.HexToHash("0x3333"),
L2ClaimBlockNumber: 1,
L2ChainID: rollupCfg.L2ChainID.Uint64(),
L2ChainID: eth.ChainIDFromBig(rollupCfg.L2ChainID),
L2ChainConfig: chainconfig.OPSepoliaChainConfig(),
RollupConfig: rollupCfg,
}
......@@ -50,7 +51,7 @@ func TestBootstrapClient_UnknownChainPanics(t *testing.T) {
L2OutputRoot: common.HexToHash("0x2222"),
L2Claim: common.HexToHash("0x3333"),
L2ClaimBlockNumber: 1,
L2ChainID: uint64(0xdead),
L2ChainID: eth.ChainID{0xdead},
}
mockOracle := newMockPreinteropBootstrapOracle(bootInfo, false)
client := NewBootstrapClient(mockOracle)
......@@ -79,7 +80,7 @@ type mockPreinteropBoostrapOracle struct {
func (o *mockPreinteropBoostrapOracle) Get(key preimage.Key) []byte {
switch key.PreimageKey() {
case L2ChainIDLocalIndex.PreimageKey():
return binary.BigEndian.AppendUint64(nil, o.b.L2ChainID)
return binary.BigEndian.AppendUint64(nil, eth.EvilChainIDToUInt64(o.b.L2ChainID))
case L2ChainConfigLocalIndex.PreimageKey():
if !o.custom {
panic(fmt.Sprintf("unexpected oracle request for preimage key %x", key.PreimageKey()))
......
......@@ -55,7 +55,7 @@ func RunConsolidation(deps ConsolidateCheckDeps,
Number: block.NumberU64(),
Timestamp: block.Time(),
}
if err := checkHazards(deps, candidate, eth.ChainIDFromUInt64(chain.ChainID), execMsgs); err != nil {
if err := checkHazards(deps, candidate, chain.ChainID, execMsgs); err != nil {
// TODO(#13776): replace with deposit-only block if ErrConflict, ErrCycle, or ErrFuture
return eth.Bytes32{}, err
}
......@@ -106,7 +106,7 @@ func checkHazards(
type consolidateCheckDeps struct {
oracle l2.Oracle
depset depset.DependencySet
canonBlocks map[uint64]*l2.CanonicalBlockHeaderOracle
canonBlocks map[eth.ChainID]*l2.CanonicalBlockHeaderOracle
}
func newConsolidateCheckDeps(chains []eth.ChainIDAndOutput, oracle l2.Oracle) (*consolidateCheckDeps, error) {
......@@ -114,14 +114,14 @@ func newConsolidateCheckDeps(chains []eth.ChainIDAndOutput, oracle l2.Oracle) (*
// TODO: Also replace dep set stubs with the actual dependency set in the RollupConfig.
deps := make(map[eth.ChainID]*depset.StaticConfigDependency)
for i, chain := range chains {
deps[eth.ChainIDFromUInt64(chain.ChainID)] = &depset.StaticConfigDependency{
deps[chain.ChainID] = &depset.StaticConfigDependency{
ChainIndex: supervisortypes.ChainIndex(i),
ActivationTime: 0,
HistoryMinTime: 0,
}
}
canonBlocks := make(map[uint64]*l2.CanonicalBlockHeaderOracle)
canonBlocks := make(map[eth.ChainID]*l2.CanonicalBlockHeaderOracle)
for _, chain := range chains {
output := oracle.OutputByRoot(common.Hash(chain.Output), chain.ChainID)
outputV0, ok := output.(*eth.OutputV0)
......@@ -155,7 +155,7 @@ func (d *consolidateCheckDeps) Check(
logHash common.Hash,
) (includedIn supervisortypes.BlockSeal, err error) {
// We can assume the oracle has the block the executing message is in
block, err := d.BlockByNumber(d.oracle, blockNum, chain.ToBig().Uint64())
block, err := d.BlockByNumber(d.oracle, blockNum, chain)
if err != nil {
return supervisortypes.BlockSeal{}, err
}
......@@ -177,7 +177,7 @@ func (d *consolidateCheckDeps) IsLocalUnsafe(chainID eth.ChainID, block eth.Bloc
}
func (d *consolidateCheckDeps) ParentBlock(chainID eth.ChainID, parentOf eth.BlockID) (parent eth.BlockID, err error) {
block, err := d.BlockByNumber(d.oracle, parentOf.Number-1, chainID.ToBig().Uint64())
block, err := d.BlockByNumber(d.oracle, parentOf.Number-1, chainID)
if err != nil {
return eth.BlockID{}, err
}
......@@ -191,7 +191,7 @@ func (d *consolidateCheckDeps) OpenBlock(
chainID eth.ChainID,
blockNum uint64,
) (ref eth.BlockRef, logCount uint32, execMsgs map[uint32]*supervisortypes.ExecutingMessage, err error) {
block, err := d.BlockByNumber(d.oracle, blockNum, chainID.ToBig().Uint64())
block, err := d.BlockByNumber(d.oracle, blockNum, chainID)
if err != nil {
return eth.BlockRef{}, 0, nil, err
}
......@@ -199,7 +199,7 @@ func (d *consolidateCheckDeps) OpenBlock(
Hash: block.Hash(),
Number: block.NumberU64(),
}
_, receipts := d.oracle.ReceiptsByBlockHash(block.Hash(), chainID.ToBig().Uint64())
_, receipts := d.oracle.ReceiptsByBlockHash(block.Hash(), chainID)
execs, logCount, err := ReceiptsToExecutingMessages(d.depset, receipts)
if err != nil {
return eth.BlockRef{}, 0, nil, err
......@@ -215,7 +215,7 @@ func (d *consolidateCheckDeps) DependencySet() depset.DependencySet {
return d.depset
}
func (d *consolidateCheckDeps) BlockByNumber(oracle l2.Oracle, blockNum uint64, chainID uint64) (*ethtypes.Block, error) {
func (d *consolidateCheckDeps) BlockByNumber(oracle l2.Oracle, blockNum uint64, chainID eth.ChainID) (*ethtypes.Block, error) {
head := d.canonBlocks[chainID].GetHeaderByNumber(blockNum)
if head == nil {
return nil, fmt.Errorf("head not found for chain %v", chainID)
......
......@@ -36,8 +36,8 @@ func setupTwoChains() (*staticConfigSource, *eth.SuperV1, stubTasks) {
agreedSuperRoot := &eth.SuperV1{
Timestamp: rollupCfg1.Genesis.L2Time + 1234,
Chains: []eth.ChainIDAndOutput{
{ChainID: rollupCfg1.L2ChainID.Uint64(), Output: eth.OutputRoot(&eth.OutputV0{BlockHash: common.Hash{0x11}})},
{ChainID: rollupCfg2.L2ChainID.Uint64(), Output: eth.OutputRoot(&eth.OutputV0{BlockHash: common.Hash{0x22}})},
{ChainID: eth.ChainIDFromBig(rollupCfg1.L2ChainID), Output: eth.OutputRoot(&eth.OutputV0{BlockHash: common.Hash{0x11}})},
{ChainID: eth.ChainIDFromBig(rollupCfg2.L2ChainID), Output: eth.OutputRoot(&eth.OutputV0{BlockHash: common.Hash{0x22}})},
},
}
configSource := &staticConfigSource{
......@@ -152,11 +152,11 @@ func TestDeriveBlockForConsolidateStep(t *testing.T) {
Timestamp: agreedSuperRoot.Timestamp + 1,
Chains: []eth.ChainIDAndOutput{
{
ChainID: configSource.rollupCfgs[0].L2ChainID.Uint64(),
ChainID: eth.ChainIDFromBig(configSource.rollupCfgs[0].L2ChainID),
Output: agreedTransitionState.PendingProgress[0].OutputRoot,
},
{
ChainID: configSource.rollupCfgs[1].L2ChainID.Uint64(),
ChainID: eth.ChainIDFromBig(configSource.rollupCfgs[1].L2ChainID),
Output: agreedTransitionState.PendingProgress[1].OutputRoot,
},
},
......@@ -248,18 +248,18 @@ type staticConfigSource struct {
chainConfigs []*params.ChainConfig
}
func (s *staticConfigSource) RollupConfig(chainID uint64) (*rollup.Config, error) {
func (s *staticConfigSource) RollupConfig(chainID eth.ChainID) (*rollup.Config, error) {
for _, cfg := range s.rollupCfgs {
if cfg.L2ChainID.Uint64() == chainID {
if eth.ChainIDFromBig(cfg.L2ChainID) == chainID {
return cfg, nil
}
}
return nil, fmt.Errorf("no rollup config found for chain %d", chainID)
}
func (s *staticConfigSource) ChainConfig(chainID uint64) (*params.ChainConfig, error) {
func (s *staticConfigSource) ChainConfig(chainID eth.ChainID) (*params.ChainConfig, error) {
for _, cfg := range s.chainConfigs {
if cfg.ChainID.Uint64() == chainID {
if eth.ChainIDFromBig(cfg.ChainID) == chainID {
return cfg, nil
}
}
......
......@@ -13,8 +13,8 @@ func TestTransitionStateCodec(t *testing.T) {
superRoot := &eth.SuperV1{
Timestamp: 9842494,
Chains: []eth.ChainIDAndOutput{
{ChainID: 34, Output: eth.Bytes32{0x01}},
{ChainID: 35, Output: eth.Bytes32{0x02}},
{ChainID: eth.ChainIDFromUInt64(34), Output: eth.Bytes32{0x01}},
{ChainID: eth.ChainIDFromUInt64(35), Output: eth.Bytes32{0x02}},
},
}
state := &TransitionState{
......@@ -35,8 +35,8 @@ func TestTransitionStateCodec(t *testing.T) {
superRoot := &eth.SuperV1{
Timestamp: 9842494,
Chains: []eth.ChainIDAndOutput{
{ChainID: 34, Output: eth.Bytes32{0x01}},
{ChainID: 35, Output: eth.Bytes32{0x02}},
{ChainID: eth.ChainIDFromUInt64(34), Output: eth.Bytes32{0x01}},
{ChainID: eth.ChainIDFromUInt64(35), Output: eth.Bytes32{0x02}},
},
}
expected := &TransitionState{
......
......@@ -40,7 +40,7 @@ func NewCachingOracle(oracle Oracle) *CachingOracle {
}
}
func (o *CachingOracle) NodeByHash(nodeHash common.Hash, chainID uint64) []byte {
func (o *CachingOracle) NodeByHash(nodeHash common.Hash, chainID eth.ChainID) []byte {
node, ok := o.nodes.Get(nodeHash)
if ok {
return node
......@@ -50,7 +50,7 @@ func (o *CachingOracle) NodeByHash(nodeHash common.Hash, chainID uint64) []byte
return node
}
func (o *CachingOracle) ReceiptsByBlockHash(blockHash common.Hash, chainID uint64) (*types.Block, types.Receipts) {
func (o *CachingOracle) ReceiptsByBlockHash(blockHash common.Hash, chainID eth.ChainID) (*types.Block, types.Receipts) {
rcpts, ok := o.rcpts.Get(blockHash)
if ok {
return o.BlockByHash(blockHash, chainID), rcpts
......@@ -61,7 +61,7 @@ func (o *CachingOracle) ReceiptsByBlockHash(blockHash common.Hash, chainID uint6
return block, rcpts
}
func (o *CachingOracle) CodeByHash(codeHash common.Hash, chainID uint64) []byte {
func (o *CachingOracle) CodeByHash(codeHash common.Hash, chainID eth.ChainID) []byte {
code, ok := o.codes.Get(codeHash)
if ok {
return code
......@@ -71,7 +71,7 @@ func (o *CachingOracle) CodeByHash(codeHash common.Hash, chainID uint64) []byte
return code
}
func (o *CachingOracle) BlockByHash(blockHash common.Hash, chainID uint64) *types.Block {
func (o *CachingOracle) BlockByHash(blockHash common.Hash, chainID eth.ChainID) *types.Block {
block, ok := o.blocks.Get(blockHash)
if ok {
return block
......@@ -81,7 +81,7 @@ func (o *CachingOracle) BlockByHash(blockHash common.Hash, chainID uint64) *type
return block
}
func (o *CachingOracle) OutputByRoot(root common.Hash, chainID uint64) eth.Output {
func (o *CachingOracle) OutputByRoot(root common.Hash, chainID eth.ChainID) eth.Output {
output, ok := o.outputs.Get(root)
if ok {
return output
......@@ -91,7 +91,7 @@ func (o *CachingOracle) OutputByRoot(root common.Hash, chainID uint64) eth.Outpu
return output
}
func (o *CachingOracle) BlockDataByHash(agreedBlockHash, blockHash common.Hash, chainID uint64) *types.Block {
func (o *CachingOracle) BlockDataByHash(agreedBlockHash, blockHash common.Hash, chainID eth.ChainID) *types.Block {
// Always request from the oracle even on cache hit. as we want the effects of the host oracle hinting
block := o.oracle.BlockDataByHash(agreedBlockHash, blockHash, chainID)
o.blocks.Add(blockHash, block)
......
......@@ -24,12 +24,12 @@ func TestBlockByHash(t *testing.T) {
// Initial call retrieves from the stub
stub.Blocks[block.Hash()] = block
actual := oracle.BlockByHash(block.Hash(), chainID)
actual := oracle.BlockByHash(block.Hash(), eth.ChainIDFromUInt64(chainID))
require.Equal(t, block, actual)
// Later calls should retrieve from cache (even if chain ID is different)
delete(stub.Blocks, block.Hash())
actual = oracle.BlockByHash(block.Hash(), 9982)
actual = oracle.BlockByHash(block.Hash(), eth.ChainIDFromUInt64(9982))
require.Equal(t, block, actual)
}
......@@ -42,17 +42,17 @@ func TestNodeByHash(t *testing.T) {
// Initial call retrieves from the stub
stateStub.Data[hash] = node
actual := oracle.NodeByHash(hash, 1234)
actual := oracle.NodeByHash(hash, eth.ChainIDFromUInt64(1234))
require.Equal(t, node, actual)
// Later calls should retrieve from cache (even if chain ID is different)
delete(stateStub.Data, hash)
actual = oracle.NodeByHash(hash, 997845)
actual = oracle.NodeByHash(hash, eth.ChainIDFromUInt64(997845))
require.Equal(t, node, actual)
}
func TestReceiptsByBlockHash(t *testing.T) {
chainID := uint64(48294)
chainID := eth.ChainIDFromUInt64(48294)
stub, _ := test.NewStubOracle(t)
oracle := NewCachingOracle(stub)
......@@ -69,7 +69,7 @@ func TestReceiptsByBlockHash(t *testing.T) {
// Later calls should retrieve from cache (even if chain ID is different)
delete(stub.Blocks, block.Hash())
delete(stub.Receipts, block.Hash())
actualBlock, actualRcpts = oracle.ReceiptsByBlockHash(block.Hash(), 9982)
actualBlock, actualRcpts = oracle.ReceiptsByBlockHash(block.Hash(), eth.ChainIDFromUInt64(9982))
require.EqualValues(t, block, actualBlock)
require.EqualValues(t, rcpts, actualRcpts)
}
......@@ -83,12 +83,12 @@ func TestCodeByHash(t *testing.T) {
// Initial call retrieves from the stub
stateStub.Code[hash] = node
actual := oracle.CodeByHash(hash, 342)
actual := oracle.CodeByHash(hash, eth.ChainIDFromUInt64(342))
require.Equal(t, node, actual)
// Later calls should retrieve from cache (even if the chain ID is different)
delete(stateStub.Code, hash)
actual = oracle.CodeByHash(hash, 986776)
actual = oracle.CodeByHash(hash, eth.ChainIDFromUInt64(986776))
require.Equal(t, node, actual)
}
......@@ -102,11 +102,11 @@ func TestOutputByRoot(t *testing.T) {
// Initial call retrieves from the stub
root := common.Hash(eth.OutputRoot(output))
stub.Outputs[root] = output
actual := oracle.OutputByRoot(root, 59284)
actual := oracle.OutputByRoot(root, eth.ChainIDFromUInt64(59284))
require.Equal(t, output, actual)
// Later calls should retrieve from cache (even if the chain ID is different)
delete(stub.Outputs, root)
actual = oracle.OutputByRoot(root, 9193)
actual = oracle.OutputByRoot(root, eth.ChainIDFromUInt64(9193))
require.Equal(t, output, actual)
}
......@@ -3,6 +3,7 @@ package l2
import (
"testing"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/require"
......@@ -21,7 +22,7 @@ func TestCanonicalBlockNumberOracle_GetHeaderByNumber(t *testing.T) {
t.Fatalf("Requested duplicate block: %v", hash)
}
requestedBlocks[hash] = true
return oracle.BlockByHash(hash, chainCfg.ChainID.Uint64())
return oracle.BlockByHash(hash, eth.ChainIDFromBig(chainCfg.ChainID))
}
canon := NewCanonicalBlockHeaderOracle(head, blockByHash)
require.Equal(t, head.Hash(), canon.CurrentHeader().Hash())
......@@ -63,7 +64,7 @@ func TestCanonicalBlockNumberOracle_SetCanonical(t *testing.T) {
blockRequestCount := 0
blockByHash := func(hash common.Hash) *types.Block {
blockRequestCount++
return oracle.BlockByHash(hash, chainCfg.ChainID.Uint64())
return oracle.BlockByHash(hash, eth.ChainIDFromBig(chainCfg.ChainID))
}
canon := NewCanonicalBlockHeaderOracle(head, blockByHash)
oracle.Blocks[blocks[2].Hash()] = blocks[2]
......@@ -100,7 +101,7 @@ func TestCanonicalBlockNumberOracle_SetCanonical(t *testing.T) {
head := blocks[headBlockNumber].Header()
blockByHash := func(hash common.Hash) *types.Block {
return oracle.BlockByHash(hash, chainCfg.ChainID.Uint64())
return oracle.BlockByHash(hash, eth.ChainIDFromBig(chainCfg.ChainID))
}
canon := NewCanonicalBlockHeaderOracle(head, blockByHash)
oracle.Blocks[blocks[2].Hash()] = blocks[2]
......
......@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
......@@ -18,10 +19,10 @@ var ErrInvalidKeyLength = errors.New("pre-images must be identified by 32-byte h
type OracleKeyValueStore struct {
db ethdb.KeyValueStore
oracle StateOracle
chainID uint64
chainID eth.ChainID
}
func NewOracleBackedDB(oracle StateOracle, chainID uint64) *OracleKeyValueStore {
func NewOracleBackedDB(oracle StateOracle, chainID eth.ChainID) *OracleKeyValueStore {
return &OracleKeyValueStore{
db: memorydb.New(),
oracle: oracle,
......
......@@ -6,6 +6,7 @@ import (
"testing"
"github.com/ethereum-optimism/optimism/op-program/client/l2/test"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
......@@ -34,7 +35,7 @@ var _ ethdb.KeyValueStore = (*OracleKeyValueStore)(nil)
func TestGet(t *testing.T) {
t.Run("IncorrectLengthKey", func(t *testing.T) {
oracle := test.NewStubStateOracle(t)
db := NewOracleBackedDB(oracle, 1234)
db := NewOracleBackedDB(oracle, eth.ChainIDFromUInt64(1234))
val, err := db.Get([]byte{1, 2, 3})
require.ErrorIs(t, err, ErrInvalidKeyLength)
require.Nil(t, val)
......@@ -42,7 +43,7 @@ func TestGet(t *testing.T) {
t.Run("KeyWithCodePrefix", func(t *testing.T) {
oracle := test.NewStubStateOracle(t)
db := NewOracleBackedDB(oracle, 1234)
db := NewOracleBackedDB(oracle, eth.ChainIDFromUInt64(1234))
key := common.HexToHash("0x12345678")
prefixedKey := append(rawdb.CodePrefix, key.Bytes()...)
......@@ -56,7 +57,7 @@ func TestGet(t *testing.T) {
t.Run("NormalKeyThatHappensToStartWithCodePrefix", func(t *testing.T) {
oracle := test.NewStubStateOracle(t)
db := NewOracleBackedDB(oracle, 1234)
db := NewOracleBackedDB(oracle, eth.ChainIDFromUInt64(1234))
key := make([]byte, common.HashLength)
copy(rawdb.CodePrefix, key)
fmt.Println(key[0])
......@@ -73,7 +74,7 @@ func TestGet(t *testing.T) {
expected := []byte{2, 6, 3, 8}
oracle := test.NewStubStateOracle(t)
oracle.Data[key] = expected
db := NewOracleBackedDB(oracle, 1234)
db := NewOracleBackedDB(oracle, eth.ChainIDFromUInt64(1234))
val, err := db.Get(key.Bytes())
require.NoError(t, err)
require.Equal(t, expected, val)
......@@ -83,7 +84,7 @@ func TestGet(t *testing.T) {
func TestPut(t *testing.T) {
t.Run("NewKey", func(t *testing.T) {
oracle := test.NewStubStateOracle(t)
db := NewOracleBackedDB(oracle, 1234)
db := NewOracleBackedDB(oracle, eth.ChainIDFromUInt64(1234))
key := common.HexToHash("0xAA4488")
value := []byte{2, 6, 3, 8}
err := db.Put(key.Bytes(), value)
......@@ -95,7 +96,7 @@ func TestPut(t *testing.T) {
})
t.Run("ReplaceKey", func(t *testing.T) {
oracle := test.NewStubStateOracle(t)
db := NewOracleBackedDB(oracle, 1234)
db := NewOracleBackedDB(oracle, eth.ChainIDFromUInt64(1234))
key := common.HexToHash("0xAA4488")
value1 := []byte{2, 6, 3, 8}
value2 := []byte{1, 2, 3}
......@@ -117,13 +118,13 @@ func TestSupportsStateDBOperations(t *testing.T) {
genesisBlock := l2Genesis.MustCommit(realDb, trieDB)
loader := test.NewKvStateOracle(t, realDb)
assertStateDataAvailable(t, NewOracleBackedDB(loader, 1234), l2Genesis, genesisBlock)
assertStateDataAvailable(t, NewOracleBackedDB(loader, eth.ChainIDFromUInt64(1234)), l2Genesis, genesisBlock)
}
func TestUpdateState(t *testing.T) {
l2Genesis := createGenesis()
oracle := test.NewStubStateOracle(t)
db := rawdb.NewDatabase(NewOracleBackedDB(oracle, 1234))
db := rawdb.NewDatabase(NewOracleBackedDB(oracle, eth.ChainIDFromUInt64(1234)))
trieDB := triedb.NewDatabase(db, &triedb.Config{HashDB: hashdb.Defaults})
genesisBlock := l2Genesis.MustCommit(db, trieDB)
......
......@@ -42,7 +42,7 @@ type OracleBackedL2Chain struct {
var _ engineapi.CachingEngineBackend = (*OracleBackedL2Chain)(nil)
func NewOracleBackedL2Chain(logger log.Logger, oracle Oracle, precompileOracle engineapi.PrecompileOracle, chainCfg *params.ChainConfig, l2OutputRoot common.Hash) (*OracleBackedL2Chain, error) {
chainID := chainCfg.ChainID.Uint64()
chainID := eth.ChainIDFromBig(chainCfg.ChainID)
output := oracle.OutputByRoot(l2OutputRoot, chainID)
outputV0, ok := output.(*eth.OutputV0)
if !ok {
......@@ -107,7 +107,7 @@ func (o *OracleBackedL2Chain) GetBlockByHash(hash common.Hash) *types.Block {
return block
}
// Retrieve from the oracle
return o.oracle.BlockByHash(hash, o.chainCfg.ChainID.Uint64())
return o.oracle.BlockByHash(hash, eth.ChainIDFromBig(o.chainCfg.ChainID))
}
func (o *OracleBackedL2Chain) GetBlock(hash common.Hash, number uint64) *types.Block {
......
......@@ -378,7 +378,7 @@ func createBlock(t *testing.T, chain *OracleBackedL2Chain, opts ...blockCreateOp
require.NoError(t, err)
nonce := parentDB.GetNonce(fundedAddress)
config := chain.Config()
db := rawdb.NewDatabase(NewOracleBackedDB(chain.oracle, config.ChainID.Uint64()))
db := rawdb.NewDatabase(NewOracleBackedDB(chain.oracle, eth.ChainIDFromBig(config.ChainID)))
blocks, _ := core.GenerateChain(config, parent, chain.Engine(), db, 1, func(i int, gen *core.BlockGen) {
rawTx := &types.DynamicFeeTx{
ChainID: config.ChainID,
......
......@@ -4,6 +4,7 @@ import (
"encoding/binary"
"fmt"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
......@@ -31,13 +32,13 @@ func (l LegacyBlockHeaderHint) Hint() string {
type HashAndChainID struct {
Hash common.Hash
ChainID uint64
ChainID eth.ChainID
}
func (h HashAndChainID) Marshal() []byte {
d := make([]byte, 32+8)
copy(d[:32], h.Hash[:])
binary.BigEndian.PutUint64(d[32:], h.ChainID)
binary.BigEndian.PutUint64(d[32:], eth.EvilChainIDToUInt64(h.ChainID))
return d
}
......@@ -124,7 +125,7 @@ func (l LegacyL2OutputHint) Hint() string {
type L2BlockDataHint struct {
AgreedBlockHash common.Hash
BlockHash common.Hash
ChainID uint64
ChainID eth.ChainID
}
var _ preimage.Hint = L2BlockDataHint{}
......@@ -133,7 +134,7 @@ func (l L2BlockDataHint) Hint() string {
hintBytes := make([]byte, 32+32+8)
copy(hintBytes[:32], (common.Hash)(l.AgreedBlockHash).Bytes())
copy(hintBytes[32:64], (common.Hash)(l.BlockHash).Bytes())
binary.BigEndian.PutUint64(hintBytes[64:], l.ChainID)
binary.BigEndian.PutUint64(hintBytes[64:], eth.EvilChainIDToUInt64(l.ChainID))
return fmt.Sprintf("%s 0x%s", HintL2BlockData, common.Bytes2Hex(hintBytes))
}
......
......@@ -19,11 +19,11 @@ type StateOracle interface {
// NodeByHash retrieves the merkle-patricia trie node pre-image for a given hash.
// Trie nodes may be from the world state trie or any account storage trie.
// Contract code is not stored as part of the trie and must be retrieved via CodeByHash
NodeByHash(nodeHash common.Hash, chainID uint64) []byte
NodeByHash(nodeHash common.Hash, chainID eth.ChainID) []byte
// CodeByHash retrieves the contract code pre-image for a given hash.
// codeHash should be retrieved from the world state account for a contract.
CodeByHash(codeHash common.Hash, chainID uint64) []byte
CodeByHash(codeHash common.Hash, chainID eth.ChainID) []byte
}
// Oracle defines the high-level API used to retrieve L2 data.
......@@ -32,16 +32,16 @@ type Oracle interface {
StateOracle
// BlockByHash retrieves the block with the given hash.
BlockByHash(blockHash common.Hash, chainID uint64) *types.Block
BlockByHash(blockHash common.Hash, chainID eth.ChainID) *types.Block
OutputByRoot(root common.Hash, chainID uint64) eth.Output
OutputByRoot(root common.Hash, chainID eth.ChainID) eth.Output
// BlockDataByHash retrieves the block, including all data used to construct it.
BlockDataByHash(agreedBlockHash, blockHash common.Hash, chainID uint64) *types.Block
BlockDataByHash(agreedBlockHash, blockHash common.Hash, chainID eth.ChainID) *types.Block
TransitionStateByRoot(root common.Hash) *interopTypes.TransitionState
ReceiptsByBlockHash(blockHash common.Hash, chainID uint64) (*types.Block, types.Receipts)
ReceiptsByBlockHash(blockHash common.Hash, chainID eth.ChainID) (*types.Block, types.Receipts)
}
// PreimageOracle implements Oracle using by interfacing with the pure preimage.Oracle
......@@ -62,7 +62,7 @@ func NewPreimageOracle(raw preimage.Oracle, hint preimage.Hinter, hintL2ChainIDs
}
}
func (p *PreimageOracle) headerByBlockHash(blockHash common.Hash, chainID uint64) *types.Header {
func (p *PreimageOracle) headerByBlockHash(blockHash common.Hash, chainID eth.ChainID) *types.Header {
if p.hintL2ChainIDs {
p.hint.Hint(BlockHeaderHint{Hash: blockHash, ChainID: chainID})
} else {
......@@ -76,14 +76,14 @@ func (p *PreimageOracle) headerByBlockHash(blockHash common.Hash, chainID uint64
return &header
}
func (p *PreimageOracle) BlockByHash(blockHash common.Hash, chainID uint64) *types.Block {
func (p *PreimageOracle) BlockByHash(blockHash common.Hash, chainID eth.ChainID) *types.Block {
header := p.headerByBlockHash(blockHash, chainID)
txs := p.LoadTransactions(blockHash, header.TxHash, chainID)
return types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs})
}
func (p *PreimageOracle) LoadTransactions(blockHash common.Hash, txHash common.Hash, chainID uint64) []*types.Transaction {
func (p *PreimageOracle) LoadTransactions(blockHash common.Hash, txHash common.Hash, chainID eth.ChainID) []*types.Transaction {
if p.hintL2ChainIDs {
p.hint.Hint(TransactionsHint{Hash: blockHash, ChainID: chainID})
} else {
......@@ -101,7 +101,7 @@ func (p *PreimageOracle) LoadTransactions(blockHash common.Hash, txHash common.H
return txs
}
func (p *PreimageOracle) NodeByHash(nodeHash common.Hash, chainID uint64) []byte {
func (p *PreimageOracle) NodeByHash(nodeHash common.Hash, chainID eth.ChainID) []byte {
if p.hintL2ChainIDs {
p.hint.Hint(StateNodeHint{Hash: nodeHash, ChainID: chainID})
} else {
......@@ -110,7 +110,7 @@ func (p *PreimageOracle) NodeByHash(nodeHash common.Hash, chainID uint64) []byte
return p.oracle.Get(preimage.Keccak256Key(nodeHash))
}
func (p *PreimageOracle) CodeByHash(codeHash common.Hash, chainID uint64) []byte {
func (p *PreimageOracle) CodeByHash(codeHash common.Hash, chainID eth.ChainID) []byte {
if p.hintL2ChainIDs {
p.hint.Hint(CodeHint{Hash: codeHash, ChainID: chainID})
} else {
......@@ -119,7 +119,7 @@ func (p *PreimageOracle) CodeByHash(codeHash common.Hash, chainID uint64) []byte
return p.oracle.Get(preimage.Keccak256Key(codeHash))
}
func (p *PreimageOracle) OutputByRoot(l2OutputRoot common.Hash, chainID uint64) eth.Output {
func (p *PreimageOracle) OutputByRoot(l2OutputRoot common.Hash, chainID eth.ChainID) eth.Output {
if p.hintL2ChainIDs {
p.hint.Hint(L2OutputHint{Hash: l2OutputRoot, ChainID: chainID})
} else {
......@@ -133,7 +133,7 @@ func (p *PreimageOracle) OutputByRoot(l2OutputRoot common.Hash, chainID uint64)
return output
}
func (p *PreimageOracle) BlockDataByHash(agreedBlockHash, blockHash common.Hash, chainID uint64) *types.Block {
func (p *PreimageOracle) BlockDataByHash(agreedBlockHash, blockHash common.Hash, chainID eth.ChainID) *types.Block {
hint := L2BlockDataHint{
AgreedBlockHash: agreedBlockHash,
BlockHash: blockHash,
......@@ -155,7 +155,7 @@ func (p *PreimageOracle) TransitionStateByRoot(root common.Hash) *interopTypes.T
return output
}
func (p *PreimageOracle) ReceiptsByBlockHash(blockHash common.Hash, chainID uint64) (*types.Block, types.Receipts) {
func (p *PreimageOracle) ReceiptsByBlockHash(blockHash common.Hash, chainID eth.ChainID) (*types.Block, types.Receipts) {
block := p.BlockByHash(blockHash, chainID)
p.hint.Hint(ReceiptsHint{Hash: blockHash, ChainID: chainID})
opaqueReceipts := mpt.ReadTrie(block.ReceiptHash(), func(key common.Hash) []byte {
......
......@@ -52,7 +52,7 @@ func testBlock(t *testing.T, block *types.Block, hintL2ChainIDs bool) {
preimages[preimage.Keccak256Key(crypto.Keccak256Hash(p)).PreimageKey()] = p
}
chainID := uint64(4924)
chainID := eth.ChainIDFromUInt64(4924)
// Prepare a raw mock pre-image oracle that will serve the pre-image data and handle hints
......@@ -94,7 +94,7 @@ func TestPreimageOracleNodeByHash(t *testing.T) {
rng := rand.New(rand.NewSource(123))
for i := 0; i < 10; i++ {
chainID := rng.Uint64()
chainID := eth.ChainIDFromUInt64(rng.Uint64())
t.Run(fmt.Sprintf("legacy_node_%d", i), func(t *testing.T) {
po, hints, preimages := mockPreimageOracle(t, false)
......@@ -131,7 +131,7 @@ func TestPreimageOracleCodeByHash(t *testing.T) {
rng := rand.New(rand.NewSource(123))
for i := 0; i < 10; i++ {
chainID := rng.Uint64()
chainID := eth.ChainIDFromUInt64(rng.Uint64())
t.Run(fmt.Sprintf("legacy_code_%d", i), func(t *testing.T) {
po, hints, preimages := mockPreimageOracle(t, false)
......@@ -168,7 +168,7 @@ func TestPreimageOracleOutputByRoot(t *testing.T) {
rng := rand.New(rand.NewSource(123))
for i := 0; i < 10; i++ {
chainID := rng.Uint64()
chainID := eth.ChainIDFromUInt64(rng.Uint64())
t.Run(fmt.Sprintf("legacy_output_%d", i), func(t *testing.T) {
po, hints, preimages := mockPreimageOracle(t, false)
output := testutils.RandomOutputV0(rng)
......
......@@ -15,8 +15,8 @@ import (
// Same as l2.StateOracle but need to use our own copy to avoid dependency loops
type stateOracle interface {
NodeByHash(nodeHash common.Hash, chainID uint64) []byte
CodeByHash(codeHash common.Hash, chainID uint64) []byte
NodeByHash(nodeHash common.Hash, chainID eth.ChainID) []byte
CodeByHash(codeHash common.Hash, chainID eth.ChainID) []byte
}
type StubBlockOracle struct {
......@@ -58,7 +58,7 @@ func NewStubOracleWithBlocks(t *testing.T, chain []*gethTypes.Block, outputs []e
}
}
func (o StubBlockOracle) BlockByHash(blockHash common.Hash, chainID uint64) *gethTypes.Block {
func (o StubBlockOracle) BlockByHash(blockHash common.Hash, chainID eth.ChainID) *gethTypes.Block {
block, ok := o.Blocks[blockHash]
if !ok {
o.t.Fatalf("requested unknown block %s", blockHash)
......@@ -66,7 +66,7 @@ func (o StubBlockOracle) BlockByHash(blockHash common.Hash, chainID uint64) *get
return block
}
func (o StubBlockOracle) OutputByRoot(root common.Hash, chainID uint64) eth.Output {
func (o StubBlockOracle) OutputByRoot(root common.Hash, chainID eth.ChainID) eth.Output {
output, ok := o.Outputs[root]
if !ok {
o.t.Fatalf("requested unknown output root %s", root)
......@@ -81,7 +81,7 @@ func (o StubBlockOracle) TransitionStateByRoot(root common.Hash) *interopTypes.T
return output
}
func (o StubBlockOracle) BlockDataByHash(agreedBlockHash, blockHash common.Hash, chainID uint64) *gethTypes.Block {
func (o StubBlockOracle) BlockDataByHash(agreedBlockHash, blockHash common.Hash, chainID eth.ChainID) *gethTypes.Block {
block, ok := o.Blocks[blockHash]
if !ok {
o.t.Fatalf("requested unknown block %s", blockHash)
......@@ -89,7 +89,7 @@ func (o StubBlockOracle) BlockDataByHash(agreedBlockHash, blockHash common.Hash,
return block
}
func (o StubBlockOracle) ReceiptsByBlockHash(blockHash common.Hash, chainID uint64) (*gethTypes.Block, gethTypes.Receipts) {
func (o StubBlockOracle) ReceiptsByBlockHash(blockHash common.Hash, chainID eth.ChainID) (*gethTypes.Block, gethTypes.Receipts) {
receipts, ok := o.Receipts[blockHash]
if !ok {
o.t.Fatalf("requested unknown receipts for block %s", blockHash)
......@@ -110,7 +110,7 @@ func NewKvStateOracle(t *testing.T, db ethdb.KeyValueStore) *KvStateOracle {
}
}
func (o *KvStateOracle) NodeByHash(nodeHash common.Hash, chainID uint64) []byte {
func (o *KvStateOracle) NodeByHash(nodeHash common.Hash, chainID eth.ChainID) []byte {
val, err := o.Source.Get(nodeHash.Bytes())
if err != nil {
o.t.Fatalf("error retrieving node %v: %v", nodeHash, err)
......@@ -118,7 +118,7 @@ func (o *KvStateOracle) NodeByHash(nodeHash common.Hash, chainID uint64) []byte
return val
}
func (o *KvStateOracle) CodeByHash(hash common.Hash, chainID uint64) []byte {
func (o *KvStateOracle) CodeByHash(hash common.Hash, chainID eth.ChainID) []byte {
return rawdb.ReadCode(o.Source, hash)
}
......@@ -137,7 +137,7 @@ type StubStateOracle struct {
Code map[common.Hash][]byte
}
func (o *StubStateOracle) NodeByHash(nodeHash common.Hash, chainID uint64) []byte {
func (o *StubStateOracle) NodeByHash(nodeHash common.Hash, chainID eth.ChainID) []byte {
data, ok := o.Data[nodeHash]
if !ok {
o.t.Fatalf("no value for node %v", nodeHash)
......@@ -145,7 +145,7 @@ func (o *StubStateOracle) NodeByHash(nodeHash common.Hash, chainID uint64) []byt
return data
}
func (o *StubStateOracle) CodeByHash(hash common.Hash, chainID uint64) []byte {
func (o *StubStateOracle) CodeByHash(hash common.Hash, chainID eth.ChainID) []byte {
data, ok := o.Code[hash]
if !ok {
o.t.Fatalf("no value for code %v", hash)
......
......@@ -15,6 +15,7 @@ import (
"github.com/ethereum-optimism/optimism/op-program/client/boot"
"github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-program/host/types"
"github.com/ethereum-optimism/optimism/op-service/eth"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum/go-ethereum/crypto"
......@@ -206,14 +207,14 @@ func TestMultipleNetworkConfigs(t *testing.T) {
func TestL2ChainID(t *testing.T) {
t.Run("DefaultToNetworkChainID", func(t *testing.T) {
cfg := configForArgs(t, replaceRequiredArg("--network", "op-mainnet"))
require.Equal(t, uint64(10), cfg.L2ChainID)
require.Equal(t, eth.ChainIDFromUInt64(10), cfg.L2ChainID)
})
t.Run("DefaultToGenesisChainID", func(t *testing.T) {
rollupCfgFile := writeValidRollupConfig(t)
genesisFile := writeValidGenesis(t)
cfg := configForArgs(t, addRequiredArgsExcept("--network", "--rollup.config", rollupCfgFile, "--l2.genesis", genesisFile))
require.Equal(t, l2GenesisConfig.ChainID.Uint64(), cfg.L2ChainID)
require.Equal(t, eth.ChainIDFromBig(l2GenesisConfig.ChainID), cfg.L2ChainID)
})
t.Run("OverrideToCustomIndicator", func(t *testing.T) {
......
......@@ -6,12 +6,12 @@ import (
"fmt"
"os"
"slices"
"strconv"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-program/chainconfig"
"github.com/ethereum-optimism/optimism/op-program/client/boot"
"github.com/ethereum-optimism/optimism/op-program/host/types"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum-optimism/optimism/op-node/rollup"
......@@ -46,7 +46,7 @@ var (
)
type Config struct {
L2ChainID uint64 // TODO: Forbid for interop
L2ChainID eth.ChainID // TODO: Forbid for interop
Rollups []*rollup.Config
// DataDir is the directory to read/write pre-image data from/to.
// If not set, an in-memory key-value store is used and fetching data must be enabled
......@@ -97,7 +97,7 @@ type Config struct {
}
func (c *Config) Check() error {
if !c.InteropEnabled && c.L2ChainID == 0 {
if !c.InteropEnabled && c.L2ChainID == (eth.ChainID{}) {
return ErrMissingL2ChainID
}
if len(c.Rollups) == 0 {
......@@ -183,8 +183,8 @@ func NewSingleChainConfig(
l2Claim common.Hash,
l2ClaimBlockNum uint64,
) *Config {
l2ChainID := l2ChainConfig.ChainID.Uint64()
_, err := params.LoadOPStackChainConfig(l2ChainID)
l2ChainID := eth.ChainIDFromBig(l2ChainConfig.ChainID)
_, err := params.LoadOPStackChainConfig(eth.EvilChainIDToUInt64(l2ChainID))
if err != nil {
// Unknown chain ID so assume it is custom
l2ChainID = boot.CustomChainIDIndicator
......@@ -268,16 +268,16 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
var err error
var rollupCfgs []*rollup.Config
var l2ChainConfigs []*params.ChainConfig
var l2ChainID uint64
var l2ChainID eth.ChainID
networkNames := ctx.StringSlice(flags.Network.Name)
for _, networkName := range networkNames {
var chainID uint64
if chainID, err = strconv.ParseUint(networkName, 10, 64); err != nil {
var chainID eth.ChainID
if chainID, err = eth.ParseDecimalChainID(networkName); err != nil {
ch := chaincfg.ChainByName(networkName)
if ch == nil {
return nil, fmt.Errorf("invalid network: %q", networkName)
}
chainID = ch.ChainID
chainID = eth.ChainIDFromUInt64(ch.ChainID)
}
l2ChainConfig, err := chainconfig.ChainConfigByChainID(chainID)
......@@ -300,7 +300,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
return nil, fmt.Errorf("invalid genesis: %w", err)
}
l2ChainConfigs = append(l2ChainConfigs, l2ChainConfig)
l2ChainID = l2ChainConfig.ChainID.Uint64()
l2ChainID = eth.ChainIDFromBig(l2ChainConfig.ChainID)
}
rollupPaths := ctx.StringSlice(flags.RollupConfig.Name)
......@@ -317,7 +317,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
l2ChainID = boot.CustomChainIDIndicator
} else if len(rollupCfgs) > 1 {
// L2ChainID is not applicable when multiple L2 sources are used and not using custom configs
l2ChainID = 0
l2ChainID = eth.ChainID{}
}
dbFormat := types.DataFormat(ctx.String(flags.DataFormat.Name))
......
......@@ -10,6 +10,7 @@ import (
"github.com/ethereum-optimism/optimism/op-program/chainconfig"
"github.com/ethereum-optimism/optimism/op-program/client/boot"
"github.com/ethereum-optimism/optimism/op-program/host/types"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
......@@ -42,13 +43,13 @@ func TestValidInteropConfigIsValid(t *testing.T) {
func TestL2BlockNum(t *testing.T) {
t.Run("RequiredForPreInterop", func(t *testing.T) {
cfg := validConfig()
cfg.L2ChainID = 0
cfg.L2ChainID = eth.ChainID{}
require.ErrorIs(t, cfg.Check(), ErrMissingL2ChainID)
})
t.Run("NotRequiredForInterop", func(t *testing.T) {
cfg := validInteropConfig()
cfg.L2ChainID = 0
cfg.L2ChainID = eth.ChainID{}
require.NoError(t, cfg.Check())
})
}
......@@ -221,7 +222,7 @@ func TestRejectExecAndServerMode(t *testing.T) {
func TestCustomL2ChainID(t *testing.T) {
t.Run("nonCustom", func(t *testing.T) {
cfg := validConfig()
require.Equal(t, cfg.L2ChainID, validL2Genesis.ChainID.Uint64())
require.Equal(t, cfg.L2ChainID, eth.ChainIDFromBig(validL2Genesis.ChainID))
})
t.Run("custom", func(t *testing.T) {
customChainConfig := &params.ChainConfig{ChainID: big.NewInt(0x1212121212)}
......
......@@ -14,6 +14,7 @@ import (
opservice "github.com/ethereum-optimism/optimism/op-service"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/ctxinterrupt"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
......@@ -98,7 +99,7 @@ func makeDefaultPrefetcher(ctx context.Context, logger log.Logger, kv kvstore.KV
}
executor := MakeProgramExecutor(logger, cfg)
return prefetcher.NewPrefetcher(logger, l1Cl, l1BlobFetcher, cfg.Rollups[0].L2ChainID.Uint64(), sources, kv, executor, cfg.L2Head, cfg.AgreedPrestate), nil
return prefetcher.NewPrefetcher(logger, l1Cl, l1BlobFetcher, eth.ChainIDFromBig(cfg.Rollups[0].L2ChainID), sources, kv, executor, cfg.L2Head, cfg.AgreedPrestate), nil
}
type programExecutor struct {
......@@ -110,7 +111,7 @@ func (p *programExecutor) RunProgram(
ctx context.Context,
prefetcher hostcommon.Prefetcher,
blockNum uint64,
chainID uint64,
chainID eth.ChainID,
) error {
newCfg := *p.cfg
newCfg.L2ChainID = chainID
......
......@@ -6,6 +6,7 @@ import (
"github.com/ethereum-optimism/optimism/op-program/client/boot"
"github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
)
......@@ -38,7 +39,7 @@ func (s *LocalPreimageSource) Get(key common.Hash) ([]byte, error) {
case l2ClaimBlockNumberKey:
return binary.BigEndian.AppendUint64(nil, s.config.L2ClaimBlockNumber), nil
case l2ChainIDKey:
return binary.BigEndian.AppendUint64(nil, s.config.L2ChainID), nil
return binary.BigEndian.AppendUint64(nil, eth.EvilChainIDToUInt64(s.config.L2ChainID)), nil
case l2ChainConfigKey:
if s.config.L2ChainID != boot.CustomChainIDIndicator {
return nil, ErrNotFound
......
......@@ -11,6 +11,7 @@ import (
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/client/boot"
"github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
......@@ -18,7 +19,7 @@ import (
func TestLocalPreimageSource(t *testing.T) {
cfg := &config.Config{
L2ChainID: 86,
L2ChainID: eth.ChainIDFromUInt64(86),
Rollups: []*rollup.Config{chaincfg.OPSepolia()},
L1Head: common.HexToHash("0x1111"),
L2OutputRoot: common.HexToHash("0x2222"),
......
......@@ -11,6 +11,7 @@ import (
"github.com/ethereum-optimism/optimism/op-program/host/common"
"github.com/ethereum-optimism/optimism/op-program/host/types"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"
)
......@@ -25,7 +26,7 @@ var (
)
type RetryingL2Sources struct {
Sources map[uint64]*RetryingL2Source
Sources map[eth.ChainID]*RetryingL2Source
}
func NewRetryingL2SourcesFromURLs(ctx context.Context, logger log.Logger, configs []*rollup.Config, l2URLs []string, l2ExperimentalURLs []string) (*RetryingL2Sources, error) {
......@@ -58,11 +59,11 @@ func NewRetryingL2Sources(ctx context.Context, logger log.Logger, configs []*rol
if len(configs) == 0 {
return nil, ErrNoSources
}
rollupConfigs := make(map[uint64]*rollup.Config)
rollupConfigs := make(map[eth.ChainID]*rollup.Config)
for _, rollupCfg := range configs {
rollupConfigs[rollupCfg.L2ChainID.Uint64()] = rollupCfg
rollupConfigs[eth.ChainIDFromBig(rollupCfg.L2ChainID)] = rollupCfg
}
l2RPCs := make(map[uint64]client.RPC)
l2RPCs := make(map[eth.ChainID]client.RPC)
for _, rpc := range l2Clients {
chainID, err := loadChainID(ctx, rpc)
if err != nil {
......@@ -77,7 +78,7 @@ func NewRetryingL2Sources(ctx context.Context, logger log.Logger, configs []*rol
}
}
l2ExperimentalRPCs := make(map[uint64]client.RPC)
l2ExperimentalRPCs := make(map[eth.ChainID]client.RPC)
for _, rpc := range l2ExperimentalClients {
chainID, err := loadChainID(ctx, rpc)
if err != nil {
......@@ -92,9 +93,9 @@ func NewRetryingL2Sources(ctx context.Context, logger log.Logger, configs []*rol
}
}
sources := make(map[uint64]*RetryingL2Source, len(configs))
sources := make(map[eth.ChainID]*RetryingL2Source, len(configs))
for _, rollupCfg := range rollupConfigs {
chainID := rollupCfg.L2ChainID.Uint64()
chainID := eth.ChainIDFromBig(rollupCfg.L2ChainID)
l2RPC, ok := l2RPCs[chainID]
if !ok {
return nil, fmt.Errorf("%w: %v", ErrNoL2ForRollup, chainID)
......@@ -112,7 +113,7 @@ func NewRetryingL2Sources(ctx context.Context, logger log.Logger, configs []*rol
}, nil
}
func (s *RetryingL2Sources) ForChainID(chainID uint64) (types.L2Source, error) {
func (s *RetryingL2Sources) ForChainID(chainID eth.ChainID) (types.L2Source, error) {
source, ok := s.Sources[chainID]
if !ok {
return nil, fmt.Errorf("no source available for chain ID: %v", chainID)
......@@ -120,7 +121,7 @@ func (s *RetryingL2Sources) ForChainID(chainID uint64) (types.L2Source, error) {
return source, nil
}
func (s *RetryingL2Sources) ForChainIDWithoutRetries(chainID uint64) (types.L2Source, error) {
func (s *RetryingL2Sources) ForChainIDWithoutRetries(chainID eth.ChainID) (types.L2Source, error) {
retrying, ok := s.Sources[chainID]
if !ok {
return nil, fmt.Errorf("no source available for chain ID: %v", chainID)
......@@ -128,11 +129,11 @@ func (s *RetryingL2Sources) ForChainIDWithoutRetries(chainID uint64) (types.L2So
return retrying.source, nil
}
func loadChainID(ctx context.Context, rpc client.RPC) (uint64, error) {
func loadChainID(ctx context.Context, rpc client.RPC) (eth.ChainID, error) {
var id hexutil.Big
err := rpc.CallContext(ctx, &id, "eth_chainId")
if err != nil {
return 0, err
return eth.ChainID{}, err
}
return (*big.Int)(&id).Uint64(), nil
return eth.ChainIDFromBig((*big.Int)(&id)), nil
}
......@@ -8,6 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common/hexutil"
......@@ -32,7 +33,7 @@ func TestNewL2Sources(t *testing.T) {
[]client.RPC{experimentalRpc})
require.NoError(t, err)
require.Len(t, src.Sources, 1)
require.True(t, src.Sources[uint64(4)].ExperimentalEnabled())
require.True(t, src.Sources[eth.ChainIDFromUInt64(4)].ExperimentalEnabled())
})
t.Run("MultipleSources", func(t *testing.T) {
......@@ -45,8 +46,8 @@ func TestNewL2Sources(t *testing.T) {
[]client.RPC{experimentalRpc1, experimentalRpc2})
require.NoError(t, err)
require.Len(t, src.Sources, 2)
require.True(t, src.Sources[uint64(1)].ExperimentalEnabled())
require.True(t, src.Sources[uint64(2)].ExperimentalEnabled())
require.True(t, src.Sources[eth.ChainIDFromUInt64(1)].ExperimentalEnabled())
require.True(t, src.Sources[eth.ChainIDFromUInt64(2)].ExperimentalEnabled())
})
t.Run("ExperimentalRPCsAreOptional", func(t *testing.T) {
......@@ -59,11 +60,11 @@ func TestNewL2Sources(t *testing.T) {
[]client.RPC{experimentalRpc2})
require.NoError(t, err)
require.Len(t, src.Sources, 2)
require.Same(t, src.Sources[uint64(1)].RollupConfig(), config1)
require.False(t, src.Sources[uint64(1)].ExperimentalEnabled())
require.Same(t, src.Sources[eth.ChainIDFromUInt64(1)].RollupConfig(), config1)
require.False(t, src.Sources[eth.ChainIDFromUInt64(1)].ExperimentalEnabled())
require.Same(t, src.Sources[uint64(2)].RollupConfig(), config2)
require.True(t, src.Sources[uint64(2)].ExperimentalEnabled())
require.Same(t, src.Sources[eth.ChainIDFromUInt64(2)].RollupConfig(), config2)
require.True(t, src.Sources[eth.ChainIDFromUInt64(2)].ExperimentalEnabled())
})
t.Run("RollupMissingL2URL", func(t *testing.T) {
......
......@@ -53,7 +53,7 @@ type Prefetcher struct {
logger log.Logger
l1Fetcher L1Source
l1BlobFetcher L1BlobSource
defaultChainID uint64
defaultChainID eth.ChainID
l2Sources hosttypes.L2Sources
lastHint string
kvStore kvstore.KV
......@@ -69,7 +69,7 @@ func NewPrefetcher(
logger log.Logger,
l1Fetcher L1Source,
l1BlobFetcher L1BlobSource,
defaultChainID uint64,
defaultChainID eth.ChainID,
l2Sources hosttypes.L2Sources,
kvStore kvstore.KV,
executor ProgramExecutor,
......@@ -373,7 +373,7 @@ func (p *Prefetcher) prefetch(ctx context.Context, hint string) error {
}
agreedBlockHash := common.Hash(hintBytes[:32])
blockHash := common.Hash(hintBytes[32:64])
chainID := binary.BigEndian.Uint64(hintBytes[64:72])
chainID := eth.ChainIDFromUInt64(binary.BigEndian.Uint64(hintBytes[64:72]))
key := BlockDataKey(blockHash)
if _, err := p.kvStore.Get(key.Key()); err == nil {
return nil
......@@ -392,14 +392,14 @@ func (p *Prefetcher) prefetch(ctx context.Context, hint string) error {
return fmt.Errorf("unknown hint type: %v", hintType)
}
func (p *Prefetcher) parseHashAndChainID(hintType string, hintBytes []byte) (common.Hash, uint64, error) {
func (p *Prefetcher) parseHashAndChainID(hintType string, hintBytes []byte) (common.Hash, eth.ChainID, error) {
switch len(hintBytes) {
case 32:
return common.Hash(hintBytes), p.defaultChainID, nil
case 40:
return common.Hash(hintBytes[0:32]), binary.BigEndian.Uint64(hintBytes[32:]), nil
return common.Hash(hintBytes[0:32]), eth.ChainIDFromUInt64(binary.BigEndian.Uint64(hintBytes[32:])), nil
default:
return common.Hash{}, 0, fmt.Errorf("invalid %s hint: %x", hintType, hintBytes)
return common.Hash{}, eth.ChainID{}, fmt.Errorf("invalid %s hint: %x", hintType, hintBytes)
}
}
......
......@@ -5,6 +5,7 @@ import (
"errors"
hostcommon "github.com/ethereum-optimism/optimism/op-program/host/common"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/retry"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
......@@ -12,14 +13,14 @@ import (
type ProgramExecutor interface {
// RunProgram derives the block at the specified blockNumber
RunProgram(ctx context.Context, prefetcher hostcommon.Prefetcher, blockNumber uint64, chainID uint64) error
RunProgram(ctx context.Context, prefetcher hostcommon.Prefetcher, blockNumber uint64, chainID eth.ChainID) error
}
// nativeReExecuteBlock is a helper function that re-executes a block natively.
// It is used to populate the kv store with the data needed for the program to
// re-derive the block.
func (p *Prefetcher) nativeReExecuteBlock(
ctx context.Context, agreedBlockHash, blockHash common.Hash, chainID uint64) error {
ctx context.Context, agreedBlockHash, blockHash common.Hash, chainID eth.ChainID) error {
// Avoid using the retrying source to prevent indefinite retries as the block may not be canonical and unavailable
source, err := p.l2Sources.ForChainIDWithoutRetries(chainID)
if err != nil {
......
......@@ -31,6 +31,6 @@ type L2Source interface {
}
type L2Sources interface {
ForChainID(chainID uint64) (L2Source, error)
ForChainIDWithoutRetries(chainID uint64) (L2Source, error)
ForChainID(chainID eth.ChainID) (L2Source, error)
ForChainIDWithoutRetries(chainID eth.ChainID) (L2Source, error)
}
......@@ -7,6 +7,7 @@ import (
"os"
"github.com/ethereum-optimism/optimism/op-program/verify"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
)
......@@ -44,7 +45,7 @@ func main() {
}
// Apply the custom configs by running op-program
runner, err := verify.NewRunner(l1RpcUrl, l1RpcKind, l1BeaconUrl, l2RpcUrl, dataDir, "901", 901, false)
runner, err := verify.NewRunner(l1RpcUrl, l1RpcKind, l1BeaconUrl, l2RpcUrl, dataDir, "901", eth.ChainIDFromUInt64(901), false)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "Failed to create runner: %v\n", err.Error())
os.Exit(1)
......
......@@ -7,10 +7,11 @@ import (
"os"
"github.com/ethereum-optimism/optimism/op-program/verify"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
)
const opMainnetChainID = 10
var opMainnetChainID = eth.ChainIDFromUInt64(10)
func main() {
var l1RpcUrl string
......
......@@ -7,10 +7,11 @@ import (
"os"
"github.com/ethereum-optimism/optimism/op-program/verify"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
)
const opSepoliaChainID = 11155420
var opSepoliaChainID = eth.ChainIDFromUInt64(11155420)
func main() {
var l1RpcUrl string
......
......@@ -43,7 +43,7 @@ type Runner struct {
runInProcess bool
}
func NewRunner(l1RpcUrl string, l1RpcKind string, l1BeaconUrl string, l2RpcUrl string, dataDir string, network string, chainID uint64, runInProcess bool) (*Runner, error) {
func NewRunner(l1RpcUrl string, l1RpcKind string, l1BeaconUrl string, l2RpcUrl string, dataDir string, network string, chainID eth.ChainID, runInProcess bool) (*Runner, error) {
ctx := context.Background()
logCfg := oplog.DefaultCLIConfig()
logCfg.Level = log.LevelDebug
......
......@@ -18,6 +18,19 @@ func ChainIDFromUInt64(i uint64) ChainID {
return ChainID(*uint256.NewInt(i))
}
func ChainIDFromBytes32(b [32]byte) ChainID {
val := new(uint256.Int).SetBytes(b[:])
return ChainID(*val)
}
func ParseDecimalChainID(chainID string) (ChainID, error) {
v, err := uint256.FromDecimal(chainID)
if err != nil {
return ChainID{}, err
}
return ChainID(*v), nil
}
func (id ChainID) String() string {
return ((*uint256.Int)(&id)).Dec()
}
......@@ -34,6 +47,22 @@ func (id ChainID) ToUInt32() (uint32, error) {
return uint32(v64), nil
}
func (id ChainID) Bytes32() [32]byte {
return (*uint256.Int)(&id).Bytes32()
}
// EvilChainIDToUInt64 converts a ChainID to a uint64 and panic's if the ChainID is too large for a UInt64
// It is "evil" because 32 byte ChainIDs should be universally supported which this method breaks. It is provided
// for legacy purposes to facilitate a transition to full 32 byte chain ID support and should not be used in new code.
// Existing calls should be replaced with full 32 byte support whenever possible.
func EvilChainIDToUInt64(id ChainID) uint64 {
v := (*uint256.Int)(&id)
if !v.IsUint64() {
panic(fmt.Errorf("ChainID too large for uint64: %v", id))
}
return v.Uint64()
}
func (id *ChainID) ToBig() *big.Int {
return (*uint256.Int)(id).ToBig()
}
......
package eth
import (
"cmp"
"encoding/binary"
"encoding/json"
"errors"
......@@ -35,20 +34,21 @@ func SuperRoot(super Super) Bytes32 {
}
type ChainIDAndOutput struct {
ChainID uint64
ChainID ChainID
Output Bytes32
}
func (c *ChainIDAndOutput) Marshal() []byte {
d := make([]byte, 64)
binary.BigEndian.PutUint64(d[24:32], c.ChainID)
chainID := c.ChainID.Bytes32()
copy(d[0:32], chainID[:])
copy(d[32:], c.Output[:])
return d
}
func NewSuperV1(timestamp uint64, chains ...ChainIDAndOutput) *SuperV1 {
slices.SortFunc(chains, func(a, b ChainIDAndOutput) int {
return cmp.Compare(a.ChainID, b.ChainID)
return a.ChainID.Cmp(b.ChainID)
})
return &SuperV1{
Timestamp: timestamp,
......@@ -103,7 +103,7 @@ func unmarshalSuperRootV1(data []byte) (*SuperV1, error) {
output.Timestamp = binary.BigEndian.Uint64(data[1:9])
for i := 9; i < len(data); i += 64 {
chainOutput := ChainIDAndOutput{
ChainID: binary.BigEndian.Uint64(data[i+24 : i+32]),
ChainID: ChainIDFromBytes32([32]byte(data[i : i+32])),
Output: Bytes32(data[i+32 : i+64]),
}
output.Chains = append(output.Chains, chainOutput)
......
......@@ -19,9 +19,9 @@ func TestUnmarshalSuperRoot_TooShortForVersion(t *testing.T) {
func TestSuperRootV1Codec(t *testing.T) {
t.Run("Valid", func(t *testing.T) {
chainA := ChainIDAndOutput{ChainID: 11, Output: Bytes32{0x01}}
chainB := ChainIDAndOutput{ChainID: 12, Output: Bytes32{0x02}}
chainC := ChainIDAndOutput{ChainID: 13, Output: Bytes32{0x03}}
chainA := ChainIDAndOutput{ChainID: ChainIDFromUInt64(11), Output: Bytes32{0x01}}
chainB := ChainIDAndOutput{ChainID: ChainIDFromUInt64(12), Output: Bytes32{0x02}}
chainC := ChainIDAndOutput{ChainID: ChainIDFromUInt64(13), Output: Bytes32{0x03}}
superRoot := SuperV1{
Timestamp: 7000,
Chains: []ChainIDAndOutput{chainA, chainB, chainC},
......
......@@ -540,7 +540,7 @@ func (su *SupervisorBackend) SuperRootAtTimestamp(ctx context.Context, timestamp
Canonical: canonicalRoot,
Pending: pending.Marshal(),
}
superRootChains[i] = eth.ChainIDAndOutput{ChainID: chainID.ToBig().Uint64(), Output: canonicalRoot}
superRootChains[i] = eth.ChainIDAndOutput{ChainID: chainID, Output: canonicalRoot}
}
superRoot := eth.SuperRoot(&eth.SuperV1{
Timestamp: uint64(timestamp),
......
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