Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions op-deployer/pkg/deployer/inspect/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ func GenesisAndRollup(globalState *state.State, chainID common.Hash) (*core.Gene
return nil, nil, fmt.Errorf("failed to combine L2 init config: %w", err)
}

l2GenesisBuilt, err := genesis.BuildL2Genesis(&config, l2Allocs, chainState.StartBlock)
l2GenesisBuilt, err := genesis.BuildL2Genesis(&config, l2Allocs, chainState.StartBlock.ToBlockRef())
if err != nil {
return nil, nil, fmt.Errorf("failed to build L2 genesis: %w", err)
}
l2GenesisBlock := l2GenesisBuilt.ToBlock()

rollupConfig, err := config.RollupConfig(
chainState.StartBlock,
chainState.StartBlock.ToBlockRef(),
l2GenesisBlock.Hash(),
l2GenesisBlock.Number().Uint64(),
)
Expand Down
7 changes: 4 additions & 3 deletions op-deployer/pkg/deployer/inspect/rollup.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ func RollupCLI(cliCtx *cli.Context) error {
}

_, rollupConfig, err := GenesisAndRollup(globalState, cfg.ChainID)
if rollupConfig.HoloceneTime == nil {
rollupConfig.Genesis.SystemConfig.MarshalPreHolocene = true
}
if err != nil {
return fmt.Errorf("failed to generate rollup config: %w", err)
}

if rollupConfig.HoloceneTime == nil {
rollupConfig.Genesis.SystemConfig.MarshalPreHolocene = true
}

if err := jsonutil.WriteJSON(rollupConfig, ioutil.ToStdOutOrFileOrNoop(cfg.Outfile, 0o666)); err != nil {
return fmt.Errorf("failed to write rollup config: %w", err)
}
Expand Down
26 changes: 6 additions & 20 deletions op-deployer/pkg/deployer/pipeline/start_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,18 @@ import (

"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rpc"
)

type l1BlockRefJSON struct {
Hash common.Hash `json:"hash"`
Number hexutil.Uint64 `json:"number"`
ParentHash common.Hash `json:"parentHash"`
Time hexutil.Uint64 `json:"timestamp"`
}

func blockRefFromRpc(ctx context.Context, l1Client *rpc.Client, numberArg string) (eth.BlockRef, error) {
var l1BRJ l1BlockRefJSON
func blockRefFromRpc(ctx context.Context, l1Client *rpc.Client, numberArg string) (*state.L1BlockRefJSON, error) {
var l1BRJ state.L1BlockRefJSON
if err := l1Client.CallContext(ctx, &l1BRJ, "eth_getBlockByNumber", numberArg, false); err != nil {
return eth.BlockRef{}, fmt.Errorf("failed to get L1 block header for block: %w", err)
return nil, fmt.Errorf("failed to get L1 block header for block: %w", err)
}

headerBlockRef := eth.BlockRef{
Number: uint64(l1BRJ.Number),
Hash: l1BRJ.Hash,
ParentHash: l1BRJ.ParentHash,
Time: uint64(l1BRJ.Time),
}
return headerBlockRef, nil
return &l1BRJ, nil
}

func SetStartBlockLiveStrategy(ctx context.Context, env *Env, st *state.State, chainID common.Hash) error {
Expand All @@ -49,7 +35,7 @@ func SetStartBlockLiveStrategy(ctx context.Context, env *Env, st *state.State, c
return fmt.Errorf("failed to get L1 block header: %w", err)
}

thisChainState.StartBlock = &headerBlockRef
thisChainState.StartBlock = headerBlockRef

return nil
}
Expand Down Expand Up @@ -82,7 +68,7 @@ func SetStartBlockGenesisStrategy(env *Env, st *state.State, chainID common.Hash
if err != nil {
return fmt.Errorf("failed to build L1 developer genesis: %w", err)
}
thisChainState.StartBlock = eth.BlockRefFromHeader(devGenesis.ToBlock().Header())
thisChainState.StartBlock = state.BlockRefJsonFromHeader(devGenesis.ToBlock().Header())

return nil
}
33 changes: 32 additions & 1 deletion op-deployer/pkg/deployer/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/ethereum-optimism/optimism/op-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
)

// State contains the data needed to recreate the deployment
Expand Down Expand Up @@ -114,5 +116,34 @@ type ChainState struct {

Allocs *GzipData[foundry.ForgeAllocs] `json:"allocs"`

StartBlock *eth.BlockRef `json:"startBlock"`
StartBlock *L1BlockRefJSON `json:"startBlock"`
}

type L1BlockRefJSON struct {
Hash common.Hash `json:"hash"`
ParentHash common.Hash `json:"parentHash"`
Number hexutil.Uint64 `json:"number"`
Time hexutil.Uint64 `json:"timestamp"`
}

func (b *L1BlockRefJSON) ToBlockRef() *eth.BlockRef {
return &eth.BlockRef{
Hash: b.Hash,
Number: uint64(b.Number),
ParentHash: b.ParentHash,
Time: uint64(b.Time),
}
}

func BlockRefJsonFromBlockRef(br *eth.BlockRef) *L1BlockRefJSON {
return &L1BlockRefJSON{
Hash: br.Hash,
Number: hexutil.Uint64(br.Number),
ParentHash: br.ParentHash,
Time: hexutil.Uint64(br.Time),
}
}

func BlockRefJsonFromHeader(h *types.Header) *L1BlockRefJSON {
return BlockRefJsonFromBlockRef(eth.BlockRefFromHeader(h))
}
96 changes: 96 additions & 0 deletions op-deployer/pkg/deployer/state/state_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package state

import (
"encoding/json"
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)

func TestBlockRef_Deserialize(t *testing.T) {
tests := []struct {
name string
input string
expected L1BlockRefJSON
expectedErrSubString string
}{
{
name: "typical block",
input: `{"hash":"0xd84d7e6e3de812c7e0305d52971dc7488acaa2b2611ecc5e222e6bfc350d1940","parentHash":"0xbfbf7e85c93e031b97fad589175d509631672c62f76c4b12280614cce4031ff9","number":"0x727172","timestamp":"0x67884564"}`,
expected: L1BlockRefJSON{
Hash: common.HexToHash("0xd84d7e6e3de812c7e0305d52971dc7488acaa2b2611ecc5e222e6bfc350d1940"),
ParentHash: common.HexToHash("0xbfbf7e85c93e031b97fad589175d509631672c62f76c4b12280614cce4031ff9"),
Number: 7500146,
Time: 1736983908,
},
},
{
name: "non-hex number",
input: `{"hash":"0xd84d7e6e3de812c7e0305d52971dc7488acaa2b2611ecc5e222e6bfc350d1940","parentHash":"0xbfbf7e85c93e031b97fad589175d509631672c62f76c4b12280614cce4031ff9","number":1234,"timestamp":2345}`,
expectedErrSubString: "cannot unmarshal non-string",
},
{
name: "negative number",
input: `{"hash":"0xd84d7e6e3de812c7e0305d52971dc7488acaa2b2611ecc5e222e6bfc350d1940","parentHash":"0xbfbf7e85c93e031b97fad589175d509631672c62f76c4b12280614cce4031ff9","number":-1234,"timestamp":2345}`,
expectedErrSubString: "cannot unmarshal non-string",
},
{
name: "invalid number",
input: `{"hash":"0xd84d7e6e3de812c7e0305d52971dc7488acaa2b2611ecc5e222e6bfc350d1940","parentHash":"0xbfbf7e85c93e031b97fad589175d509631672c62f76c4b12280614cce4031ff9","number":"foo","timestamp":"bar"}`,
expectedErrSubString: "cannot unmarshal hex string without 0x",
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
var blockRef L1BlockRefJSON
err := json.Unmarshal([]byte(test.input), &blockRef)
if test.expectedErrSubString != "" {
require.Error(t, err)
require.Contains(t, err.Error(), test.expectedErrSubString)
} else {
require.NoError(t, err)
require.Equal(t, test.expected, blockRef)
}
})
}
}

func TestBlockRef_Serialize(t *testing.T) {
tests := []struct {
name string
input L1BlockRefJSON
expected string
}{
{
name: "typical block",
input: L1BlockRefJSON{
Hash: common.HexToHash("0xd84d7e6e3de812c7e0305d52971dc7488acaa2b2611ecc5e222e6bfc350d1940"),
ParentHash: common.HexToHash("0xbfbf7e85c93e031b97fad589175d509631672c62f76c4b12280614cce4031ff9"),
Number: 7500146,
Time: 1736983908,
},
expected: `{"hash":"0xd84d7e6e3de812c7e0305d52971dc7488acaa2b2611ecc5e222e6bfc350d1940","number":"0x727172","parentHash":"0xbfbf7e85c93e031b97fad589175d509631672c62f76c4b12280614cce4031ff9","timestamp":"0x67884564"}`,
},
{
name: "zero values",
input: L1BlockRefJSON{
Hash: common.Hash{},
ParentHash: common.Hash{},
Number: 0,
Time: 0,
},
expected: `{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","number":"0x0","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","timestamp":"0x0"}`,
},
}

for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
data, err := json.Marshal(test.input)
require.NoError(t, err)
require.JSONEq(t, test.expected, string(data))
})
}
}