diff --git a/go.mod b/go.mod index d96ccbb76bbc..034fc6c402ab 100644 --- a/go.mod +++ b/go.mod @@ -265,7 +265,7 @@ require ( rsc.io/tmplfunc v0.0.3 // indirect ) -replace github.com/ethereum/go-ethereum v1.13.11 => github.com/ethereum-optimism/op-geth v1.101311.0 +replace github.com/ethereum/go-ethereum v1.13.11 => github.com/ethereum-optimism/op-geth v1.101311.1-rc.1 //replace github.com/ethereum/go-ethereum v1.13.9 => ../op-geth diff --git a/go.sum b/go.sum index 56ac703a6407..af0e2897a9b9 100644 --- a/go.sum +++ b/go.sum @@ -223,8 +223,8 @@ github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/ github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs= -github.com/ethereum-optimism/op-geth v1.101311.0 h1:n0e5WD9kEwuXb5prAO7b+2ctz/sLy6tlJ2qmbbPEi9Y= -github.com/ethereum-optimism/op-geth v1.101311.0/go.mod h1:K23yb9efVf9DdUOv/vl/Ux57Tng00rLaFqWYlFF45CA= +github.com/ethereum-optimism/op-geth v1.101311.1-rc.1 h1:oOLkib+1GGZAgOMc5cG0dcku928ml/L+1SsbBnXoGko= +github.com/ethereum-optimism/op-geth v1.101311.1-rc.1/go.mod h1:K23yb9efVf9DdUOv/vl/Ux57Tng00rLaFqWYlFF45CA= github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240418160534-4156733e7232 h1:jRdLJs4E3ilsDGK7+k39QPi3QKL/b1cLnyv8mfOCVo4= github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240418160534-4156733e7232/go.mod h1:7xh2awFQqsiZxFrHKTgEd+InVfDRrkKVUIuK8SAFHp0= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= diff --git a/op-chain-ops/genesis/genesis.go b/op-chain-ops/genesis/genesis.go index 1919aac1f7e7..1df9e683c9de 100644 --- a/op-chain-ops/genesis/genesis.go +++ b/op-chain-ops/genesis/genesis.go @@ -66,6 +66,7 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro ShanghaiTime: config.CanyonTime(block.Time()), CancunTime: config.EcotoneTime(block.Time()), EcotoneTime: config.EcotoneTime(block.Time()), + FjordTime: config.FjordTime(block.Time()), InteropTime: config.InteropTime(block.Time()), Optimism: ¶ms.OptimismConfig{ EIP1559Denominator: eip1559Denom, diff --git a/op-e2e/op_geth_test.go b/op-e2e/op_geth_test.go index aaad0c3474f6..90b117084ce7 100644 --- a/op-e2e/op_geth_test.go +++ b/op-e2e/op_geth_test.go @@ -22,6 +22,14 @@ import ( "github.com/stretchr/testify/require" ) +var ( + rip7212Precompile = common.HexToAddress("0x0000000000000000000000000000000000000100") + invalid7212Data = []byte{0x00} + // This is a valid hash, r, s, x, y params for RIP-7212 taken from: + // https://gist.github.com/ulerdogan/8f1714895e23a54147fc529ea30517eb + valid7212Data = common.FromHex("4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e") +) + // TestMissingGasLimit tests that op-geth cannot build a block without gas limit while optimism is active in the chain config. func TestMissingGasLimit(t *testing.T) { InitParallel(t) @@ -1015,3 +1023,108 @@ func TestEcotone(t *testing.T) { }) } } + +func TestPreFjord(t *testing.T) { + futureTimestamp := hexutil.Uint64(4) + + tests := []struct { + name string + fjordTime *hexutil.Uint64 + }{ + {name: "FjordNotScheduled"}, + {name: "FjordNotYetActive", fjordTime: &futureTimestamp}, + } + for _, test := range tests { + test := test + + t.Run(fmt.Sprintf("RIP7212_%s", test.name), func(t *testing.T) { + InitParallel(t) + cfg := DefaultSystemConfig(t) + s := hexutil.Uint64(0) + cfg.DeployConfig.L2GenesisCanyonTimeOffset = &s + cfg.DeployConfig.L2GenesisDeltaTimeOffset = &s + cfg.DeployConfig.L2GenesisEcotoneTimeOffset = &s + cfg.DeployConfig.L2GenesisFjordTimeOffset = test.fjordTime + + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + + opGeth, err := NewOpGeth(t, ctx, &cfg) + require.NoError(t, err) + defer opGeth.Close() + + // valid request pre-fjord returns empty response + response, err := opGeth.L2Client.CallContract(ctx, ethereum.CallMsg{ + To: &rip7212Precompile, + Data: valid7212Data, + }, nil) + + require.NoError(t, err) + require.Equal(t, []byte{}, response, "should return empty response pre-fjord for valid signature") + + // invalid request returns returns empty response + response, err = opGeth.L2Client.CallContract(ctx, ethereum.CallMsg{ + To: &rip7212Precompile, + Data: invalid7212Data, + }, nil) + + require.NoError(t, err) + require.Equal(t, []byte{}, response, "should return empty response for invalid signature") + }) + } +} + +func TestFjord(t *testing.T) { + tests := []struct { + name string + fjordTime hexutil.Uint64 + activateFjord func(ctx context.Context, opGeth *OpGeth) + }{ + {name: "ActivateAtGenesis", fjordTime: 0, activateFjord: func(ctx context.Context, opGeth *OpGeth) {}}, + {name: "ActivateAfterGenesis", fjordTime: 2, activateFjord: func(ctx context.Context, opGeth *OpGeth) { + // Adding this block advances us to the fork time. + _, err := opGeth.AddL2Block(ctx) + require.NoError(t, err) + }}, + } + + for _, test := range tests { + test := test + t.Run(fmt.Sprintf("RIP7212_%s", test.name), func(t *testing.T) { + InitParallel(t) + cfg := DefaultSystemConfig(t) + s := hexutil.Uint64(0) + cfg.DeployConfig.L2GenesisCanyonTimeOffset = &s + cfg.DeployConfig.L2GenesisDeltaTimeOffset = &s + cfg.DeployConfig.L2GenesisEcotoneTimeOffset = &s + cfg.DeployConfig.L2GenesisFjordTimeOffset = &test.fjordTime + + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + + opGeth, err := NewOpGeth(t, ctx, &cfg) + require.NoError(t, err) + defer opGeth.Close() + + test.activateFjord(ctx, opGeth) + + // valid request returns one + response, err := opGeth.L2Client.CallContract(ctx, ethereum.CallMsg{ + To: &rip7212Precompile, + Data: valid7212Data, + }, nil) + + require.NoError(t, err) + require.Equal(t, common.LeftPadBytes([]byte{1}, 32), response, "should return 1 for valid signature") + + // invalid request returns empty response, this is how the spec denotes an error. + response, err = opGeth.L2Client.CallContract(ctx, ethereum.CallMsg{ + To: &rip7212Precompile, + Data: invalid7212Data, + }, nil) + + require.NoError(t, err) + require.Equal(t, []byte{}, response, "should return empty response for invalid signature") + }) + } +}