Commit dee44ec6 authored by Axel Kingsley's avatar Axel Kingsley Committed by GitHub

Interop: Update Inputs (rebased) (#12204)

* op-node,op-supervisor: feed local-unsafe/local-safe/l1-finalized data to supervisor

* op-node,op-service,op-e2e: wip, fix interop op-node tests

* post-rebase compilation fixes

* BlockRef

* op-supervisor: fix service test, cleanup todo

* op-supervisor: link TODO comments to issue

* interop: fix e2e action test

---------
Co-authored-by: default avatarprotolambda <proto@protolambda.com>
parent 2c24e652
package interop package interop
import ( import (
"context"
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-e2e/actions/helpers"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-e2e/actions/helpers"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/rollup/interop" "github.com/ethereum-optimism/optimism/op-node/rollup/interop"
"github.com/ethereum-optimism/optimism/op-node/rollup/sync" "github.com/ethereum-optimism/optimism/op-node/rollup/sync"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum-optimism/optimism/op-service/testutils" "github.com/ethereum-optimism/optimism/op-service/testutils"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types"
) )
var _ interop.InteropBackend = (*testutils.MockInteropBackend)(nil) var _ interop.InteropBackend = (*testutils.FakeInteropBackend)(nil)
func TestInteropVerifier(gt *testing.T) { func TestInteropVerifier(gt *testing.T) {
t := helpers.NewDefaultTesting(gt) t := helpers.NewDefaultTesting(gt)
...@@ -26,14 +29,14 @@ func TestInteropVerifier(gt *testing.T) { ...@@ -26,14 +29,14 @@ func TestInteropVerifier(gt *testing.T) {
// The state genesis in this test is pre-interop however. // The state genesis in this test is pre-interop however.
sd.RollupCfg.InteropTime = new(uint64) sd.RollupCfg.InteropTime = new(uint64)
logger := testlog.Logger(t, log.LevelDebug) logger := testlog.Logger(t, log.LevelDebug)
seqMockBackend := &testutils.MockInteropBackend{} seqMockBackend := &testutils.FakeInteropBackend{}
l1Miner, seqEng, seq := helpers.SetupSequencerTest(t, sd, logger, l1Miner, seqEng, seq := helpers.SetupSequencerTest(t, sd, logger,
helpers.WithVerifierOpts(helpers.WithInteropBackend(seqMockBackend))) helpers.WithVerifierOpts(helpers.WithInteropBackend(seqMockBackend)))
batcher := helpers.NewL2Batcher(logger, sd.RollupCfg, helpers.DefaultBatcherCfg(dp), batcher := helpers.NewL2Batcher(logger, sd.RollupCfg, helpers.DefaultBatcherCfg(dp),
seq.RollupClient(), l1Miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) seq.RollupClient(), l1Miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg))
verMockBackend := &testutils.MockInteropBackend{} verMockBackend := &testutils.FakeInteropBackend{}
_, ver := helpers.SetupVerifier(t, sd, logger, _, ver := helpers.SetupVerifier(t, sd, logger,
l1Miner.L1Client(t, sd.RollupCfg), l1Miner.BlobStore(), &sync.Config{}, l1Miner.L1Client(t, sd.RollupCfg), l1Miner.BlobStore(), &sync.Config{},
helpers.WithInteropBackend(verMockBackend)) helpers.WithInteropBackend(verMockBackend))
...@@ -42,12 +45,21 @@ func TestInteropVerifier(gt *testing.T) { ...@@ -42,12 +45,21 @@ func TestInteropVerifier(gt *testing.T) {
ver.ActL2PipelineFull(t) ver.ActL2PipelineFull(t)
l2ChainID := types.ChainIDFromBig(sd.RollupCfg.L2ChainID) l2ChainID := types.ChainIDFromBig(sd.RollupCfg.L2ChainID)
seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.LocalUnsafe, nil) seqMockBackend.UpdateLocalUnsafeFn = func(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error {
require.Equal(t, chainID, l2ChainID)
require.Equal(t, uint64(1), head.Number)
return nil
}
seqMockBackend.UnsafeViewFn = func(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) {
require.Equal(t, chainID, l2ChainID)
require.Equal(t, uint64(1), unsafe.Local.Number)
require.Equal(t, uint64(0), unsafe.Cross.Number)
return unsafe, nil
}
// create an unsafe L2 block // create an unsafe L2 block
seq.ActL2StartBlock(t) seq.ActL2StartBlock(t)
seq.ActL2EndBlock(t) seq.ActL2EndBlock(t)
seq.ActL2PipelineFull(t) seq.ActL2PipelineFull(t)
seqMockBackend.AssertExpectations(t)
status := seq.SyncStatus() status := seq.SyncStatus()
require.Equal(t, uint64(1), status.UnsafeL2.Number) require.Equal(t, uint64(1), status.UnsafeL2.Number)
require.Equal(t, uint64(0), status.CrossUnsafeL2.Number) require.Equal(t, uint64(0), status.CrossUnsafeL2.Number)
...@@ -56,10 +68,16 @@ func TestInteropVerifier(gt *testing.T) { ...@@ -56,10 +68,16 @@ func TestInteropVerifier(gt *testing.T) {
// promote it to cross-unsafe in the backend // promote it to cross-unsafe in the backend
// and see if the node picks up on it // and see if the node picks up on it
seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.CrossUnsafe, nil) seqMockBackend.UnsafeViewFn = func(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) {
require.Equal(t, chainID, l2ChainID)
require.Equal(t, uint64(1), unsafe.Local.Number)
require.Equal(t, uint64(0), unsafe.Cross.Number)
out := unsafe
out.Cross = unsafe.Local
return out, nil
}
seq.ActInteropBackendCheck(t) seq.ActInteropBackendCheck(t)
seq.ActL2PipelineFull(t) seq.ActL2PipelineFull(t)
seqMockBackend.AssertExpectations(t)
status = seq.SyncStatus() status = seq.SyncStatus()
require.Equal(t, uint64(1), status.UnsafeL2.Number) require.Equal(t, uint64(1), status.UnsafeL2.Number)
require.Equal(t, uint64(1), status.CrossUnsafeL2.Number, "cross unsafe now") require.Equal(t, uint64(1), status.CrossUnsafeL2.Number, "cross unsafe now")
...@@ -74,10 +92,20 @@ func TestInteropVerifier(gt *testing.T) { ...@@ -74,10 +92,20 @@ func TestInteropVerifier(gt *testing.T) {
l1Miner.ActL1EndBlock(t) l1Miner.ActL1EndBlock(t)
// Sync the L1 block, to verify the L2 block as local-safe. // Sync the L1 block, to verify the L2 block as local-safe.
seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.CrossUnsafe, nil) // not cross-safe yet seqMockBackend.UpdateLocalUnsafeFn = nil
seqMockBackend.UpdateLocalSafeFn = func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error {
require.Equal(t, uint64(1), lastDerived.Number)
return nil
}
seqMockBackend.SafeViewFn = func(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error) {
require.Equal(t, chainID, l2ChainID)
require.Equal(t, uint64(1), safe.Local.Number)
require.Equal(t, uint64(0), safe.Cross.Number)
return safe, nil
}
seq.ActL1HeadSignal(t) seq.ActL1HeadSignal(t)
l1Head := seq.SyncStatus().HeadL1
seq.ActL2PipelineFull(t) seq.ActL2PipelineFull(t)
seqMockBackend.AssertExpectations(t)
status = seq.SyncStatus() status = seq.SyncStatus()
require.Equal(t, uint64(1), status.UnsafeL2.Number) require.Equal(t, uint64(1), status.UnsafeL2.Number)
...@@ -86,10 +114,23 @@ func TestInteropVerifier(gt *testing.T) { ...@@ -86,10 +114,23 @@ func TestInteropVerifier(gt *testing.T) {
require.Equal(t, uint64(0), status.SafeL2.Number) require.Equal(t, uint64(0), status.SafeL2.Number)
// Now mark it as cross-safe // Now mark it as cross-safe
seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.CrossSafe, nil) seqMockBackend.SafeViewFn = func(ctx context.Context, chainID types.ChainID, request types.ReferenceView) (types.ReferenceView, error) {
require.Equal(t, chainID, l2ChainID)
require.Equal(t, uint64(1), request.Local.Number)
require.Equal(t, uint64(0), request.Cross.Number)
out := request
out.Cross = request.Local
return out, nil
}
seqMockBackend.DerivedFromFn = func(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.L1BlockRef, error) {
require.Equal(t, uint64(1), blockNumber)
return l1Head, nil
}
seqMockBackend.FinalizedFn = func(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) {
return seq.RollupCfg.Genesis.L1, nil
}
seq.ActInteropBackendCheck(t) seq.ActInteropBackendCheck(t)
seq.ActL2PipelineFull(t) seq.ActL2PipelineFull(t)
seqMockBackend.AssertExpectations(t)
status = seq.SyncStatus() status = seq.SyncStatus()
require.Equal(t, uint64(1), status.UnsafeL2.Number) require.Equal(t, uint64(1), status.UnsafeL2.Number)
...@@ -98,12 +139,30 @@ func TestInteropVerifier(gt *testing.T) { ...@@ -98,12 +139,30 @@ func TestInteropVerifier(gt *testing.T) {
require.Equal(t, uint64(1), status.SafeL2.Number, "cross-safe reached") require.Equal(t, uint64(1), status.SafeL2.Number, "cross-safe reached")
require.Equal(t, uint64(0), status.FinalizedL2.Number) require.Equal(t, uint64(0), status.FinalizedL2.Number)
verMockBackend.UpdateLocalUnsafeFn = func(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error {
require.Equal(t, uint64(1), head.Number)
return nil
}
verMockBackend.UpdateLocalSafeFn = func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error {
require.Equal(t, uint64(1), lastDerived.Number)
require.Equal(t, l1Head.ID(), derivedFrom.ID())
return nil
}
// The verifier might not see the L2 block that was just derived from L1 as cross-verified yet. // The verifier might not see the L2 block that was just derived from L1 as cross-verified yet.
verMockBackend.ExpectCheckBlock(l2ChainID, 1, types.LocalUnsafe, nil) // for the local unsafe check verMockBackend.UnsafeViewFn = func(ctx context.Context, chainID types.ChainID, request types.ReferenceView) (types.ReferenceView, error) {
verMockBackend.ExpectCheckBlock(l2ChainID, 1, types.LocalUnsafe, nil) // for the local safe check require.Equal(t, uint64(1), request.Local.Number)
require.Equal(t, uint64(0), request.Cross.Number)
// Don't promote the Cross value yet
return request, nil
}
verMockBackend.SafeViewFn = func(ctx context.Context, chainID types.ChainID, request types.ReferenceView) (types.ReferenceView, error) {
require.Equal(t, uint64(1), request.Local.Number)
require.Equal(t, uint64(0), request.Cross.Number)
// Don't promote the Cross value yet
return request, nil
}
ver.ActL1HeadSignal(t) ver.ActL1HeadSignal(t)
ver.ActL2PipelineFull(t) ver.ActL2PipelineFull(t)
verMockBackend.AssertExpectations(t)
status = ver.SyncStatus() status = ver.SyncStatus()
require.Equal(t, uint64(1), status.UnsafeL2.Number, "synced the block") require.Equal(t, uint64(1), status.UnsafeL2.Number, "synced the block")
require.Equal(t, uint64(0), status.CrossUnsafeL2.Number, "not cross-verified yet") require.Equal(t, uint64(0), status.CrossUnsafeL2.Number, "not cross-verified yet")
...@@ -111,13 +170,16 @@ func TestInteropVerifier(gt *testing.T) { ...@@ -111,13 +170,16 @@ func TestInteropVerifier(gt *testing.T) {
require.Equal(t, uint64(0), status.SafeL2.Number, "not yet cross-safe") require.Equal(t, uint64(0), status.SafeL2.Number, "not yet cross-safe")
require.Equal(t, uint64(0), status.FinalizedL2.Number) require.Equal(t, uint64(0), status.FinalizedL2.Number)
seqMockBackend.UpdateFinalizedL1Fn = func(ctx context.Context, chainID types.ChainID, finalized eth.L1BlockRef) error {
require.Equal(t, l1Head, finalized)
return nil
}
// signal that L1 finalized; the cross-safe block we have should get finalized too // signal that L1 finalized; the cross-safe block we have should get finalized too
l1Miner.ActL1SafeNext(t) l1Miner.ActL1SafeNext(t)
l1Miner.ActL1FinalizeNext(t) l1Miner.ActL1FinalizeNext(t)
seq.ActL1SafeSignal(t) seq.ActL1SafeSignal(t)
seq.ActL1FinalizedSignal(t) seq.ActL1FinalizedSignal(t)
seq.ActL2PipelineFull(t) seq.ActL2PipelineFull(t)
seqMockBackend.AssertExpectations(t)
status = seq.SyncStatus() status = seq.SyncStatus()
require.Equal(t, uint64(1), status.FinalizedL2.Number, "finalized the block") require.Equal(t, uint64(1), status.FinalizedL2.Number, "finalized the block")
......
...@@ -229,6 +229,22 @@ func (ev PromoteFinalizedEvent) String() string { ...@@ -229,6 +229,22 @@ func (ev PromoteFinalizedEvent) String() string {
return "promote-finalized" return "promote-finalized"
} }
// FinalizedUpdateEvent signals that a block has been marked as finalized.
type FinalizedUpdateEvent struct {
Ref eth.L2BlockRef
}
func (ev FinalizedUpdateEvent) String() string {
return "finalized-update"
}
// RequestFinalizedUpdateEvent signals that a FinalizedUpdateEvent is needed.
type RequestFinalizedUpdateEvent struct{}
func (ev RequestFinalizedUpdateEvent) String() string {
return "request-finalized-update"
}
// CrossUpdateRequestEvent triggers update events to be emitted, repeating the current state. // CrossUpdateRequestEvent triggers update events to be emitted, repeating the current state.
type CrossUpdateRequestEvent struct { type CrossUpdateRequestEvent struct {
CrossUnsafe bool CrossUnsafe bool
...@@ -419,8 +435,11 @@ func (d *EngDeriver) OnEvent(ev event.Event) bool { ...@@ -419,8 +435,11 @@ func (d *EngDeriver) OnEvent(ev event.Event) bool {
return true return true
} }
d.ec.SetFinalizedHead(x.Ref) d.ec.SetFinalizedHead(x.Ref)
d.emitter.Emit(FinalizedUpdateEvent(x))
// Try to apply the forkchoice changes // Try to apply the forkchoice changes
d.emitter.Emit(TryUpdateEngineEvent{}) d.emitter.Emit(TryUpdateEngineEvent{})
case RequestFinalizedUpdateEvent:
d.emitter.Emit(FinalizedUpdateEvent{Ref: d.ec.Finalized()})
case CrossUpdateRequestEvent: case CrossUpdateRequestEvent:
if x.CrossUnsafe { if x.CrossUnsafe {
d.emitter.Emit(CrossUnsafeUpdateEvent{ d.emitter.Emit(CrossUnsafeUpdateEvent{
......
This diff is collapsed.
This diff is collapsed.
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum-optimism/optimism/op-service/client" "github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types"
) )
...@@ -65,20 +66,48 @@ func (cl *SupervisorClient) AddL2RPC( ...@@ -65,20 +66,48 @@ func (cl *SupervisorClient) AddL2RPC(
return result return result
} }
func (cl *SupervisorClient) CheckBlock(ctx context.Context, func (cl *SupervisorClient) UnsafeView(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) {
chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (types.SafetyLevel, error) { var result types.ReferenceView
var result types.SafetyLevel err := cl.client.CallContext(ctx, &result, "supervisor_unsafeView", (*hexutil.U256)(&chainID), unsafe)
err := cl.client.CallContext(
ctx,
&result,
"supervisor_checkBlock",
(*hexutil.U256)(&chainID), blockHash, hexutil.Uint64(blockNumber))
if err != nil { if err != nil {
return types.LocalUnsafe, fmt.Errorf("failed to check Block %s:%d (chain %s): %w", blockHash, blockNumber, chainID, err) return types.ReferenceView{}, fmt.Errorf("failed to share unsafe block view %s (chain %s): %w", unsafe, chainID, err)
} }
return result, nil return result, nil
} }
func (cl *SupervisorClient) SafeView(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error) {
var result types.ReferenceView
err := cl.client.CallContext(ctx, &result, "supervisor_safeView", (*hexutil.U256)(&chainID), safe)
if err != nil {
return types.ReferenceView{}, fmt.Errorf("failed to share safe block view %s (chain %s): %w", safe, chainID, err)
}
return result, nil
}
func (cl *SupervisorClient) Finalized(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) {
var result eth.BlockID
err := cl.client.CallContext(ctx, &result, "supervisor_finalized", chainID)
return result, err
}
func (cl *SupervisorClient) DerivedFrom(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.L1BlockRef, error) {
var result eth.L1BlockRef
err := cl.client.CallContext(ctx, &result, "supervisor_derivedFrom", chainID, blockHash, blockNumber)
return result, err
}
func (cl *SupervisorClient) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error {
return cl.client.CallContext(ctx, nil, "supervisor_updateLocalUnsafe", chainID, head)
}
func (cl *SupervisorClient) UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error {
return cl.client.CallContext(ctx, nil, "supervisor_updateLocalSafe", chainID, derivedFrom, lastDerived)
}
func (cl *SupervisorClient) UpdateFinalizedL1(ctx context.Context, chainID types.ChainID, finalizedL1 eth.L1BlockRef) error {
return cl.client.CallContext(ctx, nil, "supervisor_updateFinalizedL1", chainID, finalizedL1)
}
func (cl *SupervisorClient) Close() { func (cl *SupervisorClient) Close() {
cl.client.Close() cl.client.Close()
} }
package testutils
import (
"context"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types"
)
type FakeInteropBackend struct {
UnsafeViewFn func(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error)
SafeViewFn func(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error)
FinalizedFn func(ctx context.Context, chainID types.ChainID) (eth.BlockID, error)
DerivedFromFn func(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.L1BlockRef, error)
UpdateLocalUnsafeFn func(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error
UpdateLocalSafeFn func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error
UpdateFinalizedL1Fn func(ctx context.Context, chainID types.ChainID, finalized eth.L1BlockRef) error
}
func (m *FakeInteropBackend) UnsafeView(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) {
return m.UnsafeViewFn(ctx, chainID, unsafe)
}
func (m *FakeInteropBackend) SafeView(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error) {
return m.SafeViewFn(ctx, chainID, safe)
}
func (m *FakeInteropBackend) Finalized(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) {
return m.FinalizedFn(ctx, chainID)
}
func (m *FakeInteropBackend) DerivedFrom(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.L1BlockRef, error) {
return m.DerivedFromFn(ctx, chainID, blockHash, blockNumber)
}
func (m *FakeInteropBackend) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error {
return m.UpdateLocalUnsafeFn(ctx, chainID, head)
}
func (m *FakeInteropBackend) UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error {
return m.UpdateLocalSafeFn(ctx, chainID, derivedFrom, lastDerived)
}
func (m *FakeInteropBackend) UpdateFinalizedL1(ctx context.Context, chainID types.ChainID, finalized eth.L1BlockRef) error {
return m.UpdateFinalizedL1Fn(ctx, chainID, finalized)
}
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types"
) )
...@@ -14,13 +15,89 @@ type MockInteropBackend struct { ...@@ -14,13 +15,89 @@ type MockInteropBackend struct {
Mock mock.Mock Mock mock.Mock
} }
func (m *MockInteropBackend) ExpectCheckBlock(chainID types.ChainID, blockNumber uint64, safety types.SafetyLevel, err error) { func (m *MockInteropBackend) UnsafeView(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) {
m.Mock.On("CheckBlock", chainID, blockNumber).Once().Return(safety, &err) result := m.Mock.MethodCalled("UnsafeView", chainID, unsafe)
return result.Get(0).(types.ReferenceView), *result.Get(1).(*error)
} }
func (m *MockInteropBackend) CheckBlock(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (types.SafetyLevel, error) { func (m *MockInteropBackend) ExpectUnsafeView(chainID types.ChainID, unsafe types.ReferenceView, result types.ReferenceView, err error) {
result := m.Mock.MethodCalled("CheckBlock", chainID, blockNumber) m.Mock.On("UnsafeView", chainID, unsafe).Once().Return(result, &err)
return result.Get(0).(types.SafetyLevel), *result.Get(1).(*error) }
func (m *MockInteropBackend) OnUnsafeView(chainID types.ChainID, fn func(request types.ReferenceView) (result types.ReferenceView, err error)) {
var result types.ReferenceView
var err error
m.Mock.On("UnsafeView", chainID, mock.Anything).Run(func(args mock.Arguments) {
v := args[0].(types.ReferenceView)
result, err = fn(v)
}).Return(result, &err)
}
func (m *MockInteropBackend) SafeView(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error) {
result := m.Mock.MethodCalled("SafeView", chainID, safe)
return result.Get(0).(types.ReferenceView), *result.Get(1).(*error)
}
func (m *MockInteropBackend) ExpectSafeView(chainID types.ChainID, safe types.ReferenceView, result types.ReferenceView, err error) {
m.Mock.On("SafeView", chainID, safe).Once().Return(result, &err)
}
func (m *MockInteropBackend) OnSafeView(chainID types.ChainID, fn func(request types.ReferenceView) (result types.ReferenceView, err error)) {
var result types.ReferenceView
var err error
m.Mock.On("SafeView", chainID, mock.Anything).Run(func(args mock.Arguments) {
v := args[0].(types.ReferenceView)
result, err = fn(v)
}).Return(result, &err)
}
func (m *MockInteropBackend) Finalized(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) {
result := m.Mock.MethodCalled("Finalized", chainID)
return result.Get(0).(eth.BlockID), *result.Get(1).(*error)
}
func (m *MockInteropBackend) ExpectFinalized(chainID types.ChainID, result eth.BlockID, err error) {
m.Mock.On("Finalized", chainID).Once().Return(result, &err)
}
func (m *MockInteropBackend) DerivedFrom(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.L1BlockRef, error) {
result := m.Mock.MethodCalled("DerivedFrom", chainID, blockHash, blockNumber)
return result.Get(0).(eth.L1BlockRef), *result.Get(1).(*error)
}
func (m *MockInteropBackend) ExpectDerivedFrom(chainID types.ChainID, blockHash common.Hash, blockNumber uint64, result eth.L1BlockRef, err error) {
m.Mock.On("DerivedFrom", chainID, blockHash, blockNumber).Once().Return(result, &err)
}
func (m *MockInteropBackend) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error {
result := m.Mock.MethodCalled("UpdateLocalUnsafe", chainID, head)
return *result.Get(0).(*error)
}
func (m *MockInteropBackend) ExpectUpdateLocalUnsafe(chainID types.ChainID, head eth.L2BlockRef, err error) {
m.Mock.On("UpdateLocalUnsafe", chainID, head).Once().Return(&err)
}
func (m *MockInteropBackend) ExpectAnyUpdateLocalUnsafe(chainID types.ChainID, err error) {
m.Mock.On("UpdateLocalUnsafe", chainID, mock.Anything).Once().Return(&err)
}
func (m *MockInteropBackend) UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error {
result := m.Mock.MethodCalled("UpdateLocalSafe", chainID, derivedFrom, lastDerived)
return *result.Get(0).(*error)
}
func (m *MockInteropBackend) ExpectUpdateLocalSafe(chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef, err error) {
m.Mock.On("UpdateLocalSafe", chainID, derivedFrom, lastDerived).Once().Return(&err)
}
func (m *MockInteropBackend) UpdateFinalizedL1(ctx context.Context, chainID types.ChainID, finalized eth.L1BlockRef) error {
result := m.Mock.MethodCalled("UpdateFinalizedL1", chainID, finalized)
return *result.Get(0).(*error)
}
func (m *MockInteropBackend) ExpectUpdateFinalizedL1(chainID types.ChainID, finalized eth.L1BlockRef, err error) {
m.Mock.On("UpdateFinalizedL1", chainID, finalized).Once().Return(&err)
} }
func (m *MockInteropBackend) AssertExpectations(t mock.TestingT) { func (m *MockInteropBackend) AssertExpectations(t mock.TestingT) {
......
...@@ -226,3 +226,12 @@ func (su *SupervisorBackend) CheckBlock(chainID *hexutil.U256, blockHash common. ...@@ -226,3 +226,12 @@ func (su *SupervisorBackend) CheckBlock(chainID *hexutil.U256, blockHash common.
safest := su.db.Safest(types.ChainID(*chainID), uint64(blockNumber), 0) safest := su.db.Safest(types.ChainID(*chainID), uint64(blockNumber), 0)
return safest, nil return safest, nil
} }
func (su *SupervisorBackend) DerivedFrom(
ctx context.Context,
chainID types.ChainID,
blockHash common.Hash,
blockNumber uint64) (eth.BlockRef, error) {
// TODO(#12358): attach to backend
return eth.BlockRef{}, nil
}
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/frontend" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/frontend"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types"
) )
...@@ -55,6 +56,10 @@ func (m *MockBackend) CheckBlock(chainID *hexutil.U256, blockHash common.Hash, b ...@@ -55,6 +56,10 @@ func (m *MockBackend) CheckBlock(chainID *hexutil.U256, blockHash common.Hash, b
return types.CrossUnsafe, nil return types.CrossUnsafe, nil
} }
func (m *MockBackend) DerivedFrom(ctx context.Context, t types.ChainID, parentHash common.Hash, n uint64) (eth.BlockRef, error) {
return eth.BlockRef{}, nil
}
func (m *MockBackend) Close() error { func (m *MockBackend) Close() error {
return nil return nil
} }
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types"
) )
...@@ -19,6 +20,13 @@ type QueryBackend interface { ...@@ -19,6 +20,13 @@ type QueryBackend interface {
CheckMessage(identifier types.Identifier, payloadHash common.Hash) (types.SafetyLevel, error) CheckMessage(identifier types.Identifier, payloadHash common.Hash) (types.SafetyLevel, error)
CheckMessages(messages []types.Message, minSafety types.SafetyLevel) error CheckMessages(messages []types.Message, minSafety types.SafetyLevel) error
CheckBlock(chainID *hexutil.U256, blockHash common.Hash, blockNumber hexutil.Uint64) (types.SafetyLevel, error) CheckBlock(chainID *hexutil.U256, blockHash common.Hash, blockNumber hexutil.Uint64) (types.SafetyLevel, error)
DerivedFrom(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.BlockRef, error)
}
type UpdatesBackend interface {
UpdateLocalUnsafe(chainID types.ChainID, head eth.BlockRef)
UpdateLocalSafe(chainID types.ChainID, derivedFrom eth.BlockRef, lastDerived eth.BlockRef)
UpdateFinalizedL1(chainID types.ChainID, finalized eth.BlockRef)
} }
type Backend interface { type Backend interface {
...@@ -44,9 +52,24 @@ func (q *QueryFrontend) CheckMessages( ...@@ -44,9 +52,24 @@ func (q *QueryFrontend) CheckMessages(
return q.Supervisor.CheckMessages(messages, minSafety) return q.Supervisor.CheckMessages(messages, minSafety)
} }
// CheckBlock checks the safety-level of an L2 block as a whole. func (q *QueryFrontend) UnsafeView(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error) {
func (q *QueryFrontend) CheckBlock(chainID *hexutil.U256, blockHash common.Hash, blockNumber hexutil.Uint64) (types.SafetyLevel, error) { // TODO(#12358): attach to backend
return q.Supervisor.CheckBlock(chainID, blockHash, blockNumber) return types.ReferenceView{}, nil
}
func (q *QueryFrontend) SafeView(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error) {
// TODO(#12358): attach to backend
return types.ReferenceView{}, nil
}
func (q *QueryFrontend) Finalized(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) {
// TODO(#12358): attach to backend
return eth.BlockID{}, nil
}
func (q *QueryFrontend) DerivedFrom(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (eth.BlockRef, error) {
// TODO(#12358): attach to backend
return eth.BlockRef{}, nil
} }
type AdminFrontend struct { type AdminFrontend struct {
...@@ -67,3 +90,19 @@ func (a *AdminFrontend) Stop(ctx context.Context) error { ...@@ -67,3 +90,19 @@ func (a *AdminFrontend) Stop(ctx context.Context) error {
func (a *AdminFrontend) AddL2RPC(ctx context.Context, rpc string) error { func (a *AdminFrontend) AddL2RPC(ctx context.Context, rpc string) error {
return a.Supervisor.AddL2RPC(ctx, rpc) return a.Supervisor.AddL2RPC(ctx, rpc)
} }
type UpdatesFrontend struct {
Supervisor UpdatesBackend
}
func (u *UpdatesFrontend) UpdateLocalUnsafe(chainID types.ChainID, head eth.BlockRef) {
u.Supervisor.UpdateLocalUnsafe(chainID, head)
}
func (u *UpdatesFrontend) UpdateLocalSafe(chainID types.ChainID, derivedFrom eth.BlockRef, lastDerived eth.BlockRef) {
u.Supervisor.UpdateLocalSafe(chainID, derivedFrom, lastDerived)
}
func (u *UpdatesFrontend) UpdateFinalizedL1(chainID types.ChainID, finalized eth.BlockRef) {
u.Supervisor.UpdateFinalizedL1(chainID, finalized)
}
...@@ -5,12 +5,9 @@ import ( ...@@ -5,12 +5,9 @@ import (
"testing" "testing"
"time" "time"
"github.com/ethereum-optimism/optimism/op-supervisor/config"
"github.com/holiman/uint256"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-service/dial" "github.com/ethereum-optimism/optimism/op-service/dial"
...@@ -19,6 +16,7 @@ import ( ...@@ -19,6 +16,7 @@ import (
"github.com/ethereum-optimism/optimism/op-service/oppprof" "github.com/ethereum-optimism/optimism/op-service/oppprof"
oprpc "github.com/ethereum-optimism/optimism/op-service/rpc" oprpc "github.com/ethereum-optimism/optimism/op-service/rpc"
"github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum-optimism/optimism/op-supervisor/config"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types"
) )
...@@ -62,8 +60,14 @@ func TestSupervisorService(t *testing.T) { ...@@ -62,8 +60,14 @@ func TestSupervisorService(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
var dest types.SafetyLevel var dest types.SafetyLevel
err = cl.CallContext(ctx, &dest, "supervisor_checkBlock", err = cl.CallContext(ctx, &dest, "supervisor_checkMessage",
(*hexutil.U256)(uint256.NewInt(1)), common.Hash{0xab}, hexutil.Uint64(123)) types.Identifier{
Origin: common.Address{0xaa},
BlockNumber: 123,
LogIndex: 42,
Timestamp: 1234567,
ChainID: types.ChainID{0xbb},
}, common.Hash{0xcc})
cancel() cancel()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, types.CrossUnsafe, dest, "expecting mock to return cross-unsafe") require.Equal(t, types.CrossUnsafe, dest, "expecting mock to return cross-unsafe")
......
...@@ -11,6 +11,8 @@ import ( ...@@ -11,6 +11,8 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum-optimism/optimism/op-service/eth"
) )
type ExecutingMessage struct { type ExecutingMessage struct {
...@@ -160,3 +162,12 @@ func (id ChainID) ToUInt32() (uint32, error) { ...@@ -160,3 +162,12 @@ func (id ChainID) ToUInt32() (uint32, error) {
} }
return uint32(v64), nil return uint32(v64), nil
} }
type ReferenceView struct {
Local eth.BlockID `json:"local"`
Cross eth.BlockID `json:"cross"`
}
func (v ReferenceView) String() string {
return fmt.Sprintf("View(local: %s, cross: %s)", v.Local, v.Cross)
}
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