Commit 882d261b authored by protolambda's avatar protolambda Committed by GitHub

op-supervisor: make frontend/backend/client interfaces consistent (#12699)

parent 73094cb3
......@@ -41,12 +41,12 @@ func TestInteropVerifier(gt *testing.T) {
helpers.WithInteropBackend(verMockBackend))
// Genesis block will be registered as local-safe when we first trigger the derivation pipeline
seqMockBackend.UpdateLocalSafeFn = func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error {
seqMockBackend.UpdateLocalSafeFn = func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.BlockRef) error {
require.Equal(t, sd.RollupCfg.Genesis.L1, derivedFrom.ID())
require.Equal(t, sd.RollupCfg.Genesis.L2, lastDerived.ID())
return nil
}
verMockBackend.UpdateLocalSafeFn = func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error {
verMockBackend.UpdateLocalSafeFn = func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.BlockRef) error {
require.Equal(t, sd.RollupCfg.Genesis.L1, derivedFrom.ID())
require.Equal(t, sd.RollupCfg.Genesis.L2, lastDerived.ID())
return nil
......@@ -56,7 +56,7 @@ func TestInteropVerifier(gt *testing.T) {
ver.ActL2PipelineFull(t)
l2ChainID := types.ChainIDFromBig(sd.RollupCfg.L2ChainID)
seqMockBackend.UpdateLocalUnsafeFn = func(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error {
seqMockBackend.UpdateLocalUnsafeFn = func(ctx context.Context, chainID types.ChainID, head eth.BlockRef) error {
require.Equal(t, chainID, l2ChainID)
require.Equal(t, uint64(1), head.Number)
return nil
......@@ -105,7 +105,7 @@ func TestInteropVerifier(gt *testing.T) {
// Sync the L1 block, to verify the L2 block as local-safe.
seqMockBackend.UpdateLocalUnsafeFn = nil
nextL2 := uint64(0)
seqMockBackend.UpdateLocalSafeFn = func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error {
seqMockBackend.UpdateLocalSafeFn = func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.BlockRef) error {
require.Equal(t, nextL2, lastDerived.Number)
nextL2 += 1
return nil
......@@ -153,12 +153,12 @@ func TestInteropVerifier(gt *testing.T) {
require.Equal(t, uint64(1), status.SafeL2.Number, "cross-safe reached")
require.Equal(t, uint64(0), status.FinalizedL2.Number)
verMockBackend.UpdateLocalUnsafeFn = func(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error {
verMockBackend.UpdateLocalUnsafeFn = func(ctx context.Context, chainID types.ChainID, head eth.BlockRef) error {
require.Equal(t, uint64(1), head.Number)
return nil
}
nextL2 = 0
verMockBackend.UpdateLocalSafeFn = func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error {
verMockBackend.UpdateLocalSafeFn = func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.BlockRef) error {
require.Equal(t, nextL2, lastDerived.Number)
nextL2 += 1
require.Equal(t, l1Head.ID(), derivedFrom.ID())
......
......@@ -15,6 +15,8 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup/event"
"github.com/ethereum-optimism/optimism/op-node/rollup/finality"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types"
)
......@@ -27,11 +29,17 @@ type InteropBackend interface {
DerivedFrom(ctx context.Context, chainID types.ChainID, derived eth.BlockID) (eth.L1BlockRef, error)
UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error
UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error
UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.BlockRef) error
UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.BlockRef) error
UpdateFinalizedL1(ctx context.Context, chainID types.ChainID, finalized eth.L1BlockRef) error
}
// For testing usage, the backend of the supervisor implements the interface, no need for RPC.
var _ InteropBackend = (*backend.SupervisorBackend)(nil)
// For RPC usage, the supervisor client implements the interop backend.
var _ InteropBackend = (*sources.SupervisorClient)(nil)
type L2Source interface {
L2BlockRefByNumber(context.Context, uint64) (eth.L2BlockRef, error)
L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error)
......@@ -117,7 +125,7 @@ func (d *InteropDeriver) onLocalUnsafeUpdate(x engine.UnsafeUpdateEvent) {
d.log.Debug("Signaling unsafe L2 head update to interop backend", "head", x.Ref)
ctx, cancel := context.WithTimeout(d.driverCtx, rpcTimeout)
defer cancel()
if err := d.backend.UpdateLocalUnsafe(ctx, d.chainID, x.Ref); err != nil {
if err := d.backend.UpdateLocalUnsafe(ctx, d.chainID, x.Ref.BlockRef()); err != nil {
d.log.Warn("Failed to signal unsafe L2 head to interop backend", "head", x.Ref, "err", err)
// still continue to try and do a cross-unsafe update
}
......@@ -129,7 +137,7 @@ func (d *InteropDeriver) onInteropPendingSafeChangedEvent(x engine.InteropPendin
d.log.Debug("Signaling derived-from update to interop backend", "derivedFrom", x.DerivedFrom, "block", x.Ref)
ctx, cancel := context.WithTimeout(d.driverCtx, rpcTimeout)
defer cancel()
if err := d.backend.UpdateLocalSafe(ctx, d.chainID, x.DerivedFrom, x.Ref); err != nil {
if err := d.backend.UpdateLocalSafe(ctx, d.chainID, x.DerivedFrom, x.Ref.BlockRef()); err != nil {
d.log.Debug("Failed to signal derived-from update to interop backend", "derivedFrom", x.DerivedFrom, "block", x.Ref)
// still continue to try and do a cross-safe update
}
......
......@@ -36,7 +36,7 @@ func TestInteropDeriver(t *testing.T) {
t.Run("local-unsafe blocks push to supervisor and trigger cross-unsafe attempts", func(t *testing.T) {
emitter.ExpectOnce(engine.RequestCrossUnsafeEvent{})
unsafeHead := testutils.RandomL2BlockRef(rng)
interopBackend.ExpectUpdateLocalUnsafe(chainID, unsafeHead, nil)
interopBackend.ExpectUpdateLocalUnsafe(chainID, unsafeHead.BlockRef(), nil)
interopDeriver.OnEvent(engine.UnsafeUpdateEvent{Ref: unsafeHead})
emitter.AssertExpectations(t)
interopBackend.AssertExpectations(t)
......@@ -93,7 +93,7 @@ func TestInteropDeriver(t *testing.T) {
emitter.ExpectOnce(engine.RequestCrossSafeEvent{})
derivedFrom := testutils.RandomBlockRef(rng)
localSafe := testutils.RandomL2BlockRef(rng)
interopBackend.ExpectUpdateLocalSafe(chainID, derivedFrom, localSafe, nil)
interopBackend.ExpectUpdateLocalSafe(chainID, derivedFrom, localSafe.BlockRef(), nil)
interopDeriver.OnEvent(engine.InteropPendingSafeChangedEvent{
Ref: localSafe,
DerivedFrom: derivedFrom,
......
......@@ -49,6 +49,15 @@ func (id L2BlockRef) TerminalString() string {
return fmt.Sprintf("%s:%d", id.Hash.TerminalString(), id.Number)
}
func (id L2BlockRef) BlockRef() BlockRef {
return BlockRef{
Hash: id.Hash,
Number: id.Number,
ParentHash: id.ParentHash,
Time: id.Time,
}
}
type L1BlockRef struct {
Hash common.Hash `json:"hash"`
Number uint64 `json:"number"`
......
......@@ -97,17 +97,17 @@ func (cl *SupervisorClient) Finalized(ctx context.Context, chainID types.ChainID
return result, err
}
func (cl *SupervisorClient) DerivedFrom(ctx context.Context, chainID types.ChainID, derived eth.BlockID) (eth.L1BlockRef, error) {
var result eth.L1BlockRef
func (cl *SupervisorClient) DerivedFrom(ctx context.Context, chainID types.ChainID, derived eth.BlockID) (eth.BlockRef, error) {
var result eth.BlockRef
err := cl.client.CallContext(ctx, &result, "supervisor_derivedFrom", chainID, derived)
return result, err
}
func (cl *SupervisorClient) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error {
func (cl *SupervisorClient) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.BlockRef) 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 {
func (cl *SupervisorClient) UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.BlockRef) error {
return cl.client.CallContext(ctx, nil, "supervisor_updateLocalSafe", chainID, derivedFrom, lastDerived)
}
......
......@@ -12,8 +12,8 @@ type FakeInteropBackend struct {
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, derived eth.BlockID) (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
UpdateLocalUnsafeFn func(ctx context.Context, chainID types.ChainID, head eth.BlockRef) error
UpdateLocalSafeFn func(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.BlockRef) error
UpdateFinalizedL1Fn func(ctx context.Context, chainID types.ChainID, finalized eth.L1BlockRef) error
}
......@@ -33,11 +33,11 @@ func (m *FakeInteropBackend) DerivedFrom(ctx context.Context, chainID types.Chai
return m.DerivedFromFn(ctx, chainID, derived)
}
func (m *FakeInteropBackend) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error {
func (m *FakeInteropBackend) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.BlockRef) error {
return m.UpdateLocalUnsafeFn(ctx, chainID, head)
}
func (m *FakeInteropBackend) UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.L2BlockRef) error {
func (m *FakeInteropBackend) UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.BlockRef) error {
return m.UpdateLocalSafeFn(ctx, chainID, derivedFrom, lastDerived)
}
......
......@@ -67,12 +67,12 @@ func (m *MockInteropBackend) ExpectDerivedFrom(chainID types.ChainID, derived et
m.Mock.On("DerivedFrom", chainID, derived).Once().Return(result, &err)
}
func (m *MockInteropBackend) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.L2BlockRef) error {
func (m *MockInteropBackend) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.BlockRef) 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) {
func (m *MockInteropBackend) ExpectUpdateLocalUnsafe(chainID types.ChainID, head eth.BlockRef, err error) {
m.Mock.On("UpdateLocalUnsafe", chainID, head).Once().Return(&err)
}
......@@ -80,12 +80,12 @@ func (m *MockInteropBackend) ExpectAnyUpdateLocalUnsafe(chainID types.ChainID, e
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 {
func (m *MockInteropBackend) UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.BlockRef) 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) {
func (m *MockInteropBackend) ExpectUpdateLocalSafe(chainID types.ChainID, derivedFrom eth.L1BlockRef, lastDerived eth.BlockRef, err error) {
m.Mock.On("UpdateLocalSafe", chainID, derivedFrom, lastDerived).Once().Return(&err)
}
......
......@@ -402,21 +402,21 @@ func (su *SupervisorBackend) Finalized(ctx context.Context, chainID types.ChainI
return v.ID(), nil
}
func (su *SupervisorBackend) DerivedFrom(ctx context.Context, chainID types.ChainID, derived eth.BlockID) (derivedFrom eth.BlockID, err error) {
func (su *SupervisorBackend) DerivedFrom(ctx context.Context, chainID types.ChainID, derived eth.BlockID) (derivedFrom eth.BlockRef, err error) {
su.mu.RLock()
defer su.mu.RUnlock()
v, err := su.chainDBs.DerivedFrom(chainID, derived)
if err != nil {
return eth.BlockID{}, err
return eth.BlockRef{}, err
}
return v.ID(), nil
return v, nil
}
// Update methods
// ----------------------------
func (su *SupervisorBackend) UpdateLocalUnsafe(chainID types.ChainID, head eth.BlockRef) error {
func (su *SupervisorBackend) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.BlockRef) error {
su.mu.RLock()
defer su.mu.RUnlock()
ch, ok := su.chainProcessors[chainID]
......@@ -426,14 +426,14 @@ func (su *SupervisorBackend) UpdateLocalUnsafe(chainID types.ChainID, head eth.B
return ch.OnNewHead(head)
}
func (su *SupervisorBackend) UpdateLocalSafe(chainID types.ChainID, derivedFrom eth.BlockRef, lastDerived eth.BlockRef) error {
func (su *SupervisorBackend) UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.BlockRef, lastDerived eth.BlockRef) error {
su.mu.RLock()
defer su.mu.RUnlock()
return su.chainDBs.UpdateLocalSafe(chainID, derivedFrom, lastDerived)
}
func (su *SupervisorBackend) UpdateFinalizedL1(chainID types.ChainID, finalized eth.BlockRef) error {
func (su *SupervisorBackend) UpdateFinalizedL1(ctx context.Context, chainID types.ChainID, finalized eth.BlockRef) error {
su.mu.RLock()
defer su.mu.RUnlock()
......
......@@ -113,7 +113,7 @@ func TestBackendLifetime(t *testing.T) {
src.ExpectL1BlockRefByNumber(2, eth.L1BlockRef{}, ethereum.NotFound)
err = b.UpdateLocalUnsafe(chainA, blockY)
err = b.UpdateLocalUnsafe(context.Background(), chainA, blockY)
require.NoError(t, err)
// Make the processing happen, so we can rely on the new chain information,
// and not run into errors for future data that isn't mocked at this time.
......
......@@ -167,15 +167,23 @@ func (db *ChainsDB) LastDerivedFrom(chainID types.ChainID, derivedFrom eth.Block
return crossDB.LastDerivedAt(derivedFrom)
}
func (db *ChainsDB) DerivedFrom(chainID types.ChainID, derived eth.BlockID) (derivedFrom types.BlockSeal, err error) {
func (db *ChainsDB) DerivedFrom(chainID types.ChainID, derived eth.BlockID) (derivedFrom eth.BlockRef, err error) {
db.mu.RLock()
defer db.mu.RUnlock()
localDB, ok := db.localDBs[chainID]
if !ok {
return types.BlockSeal{}, types.ErrUnknownChain
return eth.BlockRef{}, types.ErrUnknownChain
}
res, err := localDB.DerivedFrom(derived)
if err != nil {
return eth.BlockRef{}, err
}
parent, err := localDB.PreviousDerivedFrom(res.ID())
if err != nil {
return eth.BlockRef{}, err
}
return localDB.DerivedFrom(derived)
return res.WithParent(parent.ID()), nil
}
// Check calls the underlying logDB to determine if the given log entry exists at the given location.
......
......@@ -62,19 +62,19 @@ func (m *MockBackend) Finalized(ctx context.Context, chainID types.ChainID) (eth
return eth.BlockID{}, nil
}
func (m *MockBackend) DerivedFrom(ctx context.Context, chainID types.ChainID, derived eth.BlockID) (derivedFrom eth.BlockID, err error) {
return eth.BlockID{}, nil
func (m *MockBackend) DerivedFrom(ctx context.Context, chainID types.ChainID, derived eth.BlockID) (derivedFrom eth.BlockRef, err error) {
return eth.BlockRef{}, nil
}
func (m *MockBackend) UpdateLocalUnsafe(chainID types.ChainID, head eth.BlockRef) error {
func (m *MockBackend) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.BlockRef) error {
return nil
}
func (m *MockBackend) UpdateLocalSafe(chainID types.ChainID, derivedFrom eth.BlockRef, lastDerived eth.BlockRef) error {
func (m *MockBackend) UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.BlockRef, lastDerived eth.BlockRef) error {
return nil
}
func (m *MockBackend) UpdateFinalizedL1(chainID types.ChainID, finalized eth.BlockRef) error {
func (m *MockBackend) UpdateFinalizedL1(ctx context.Context, chainID types.ChainID, finalized eth.BlockRef) error {
return nil
}
......
......@@ -17,16 +17,16 @@ type AdminBackend interface {
type QueryBackend interface {
CheckMessage(identifier types.Identifier, payloadHash common.Hash) (types.SafetyLevel, error)
CheckMessages(messages []types.Message, minSafety types.SafetyLevel) error
DerivedFrom(ctx context.Context, chainID types.ChainID, derived eth.BlockID) (derivedFrom eth.BlockID, err error)
DerivedFrom(ctx context.Context, chainID types.ChainID, derived eth.BlockID) (derivedFrom eth.BlockRef, err error)
UnsafeView(ctx context.Context, chainID types.ChainID, unsafe types.ReferenceView) (types.ReferenceView, error)
SafeView(ctx context.Context, chainID types.ChainID, safe types.ReferenceView) (types.ReferenceView, error)
Finalized(ctx context.Context, chainID types.ChainID) (eth.BlockID, error)
}
type UpdatesBackend interface {
UpdateLocalUnsafe(chainID types.ChainID, head eth.BlockRef) error
UpdateLocalSafe(chainID types.ChainID, derivedFrom eth.BlockRef, lastDerived eth.BlockRef) error
UpdateFinalizedL1(chainID types.ChainID, finalized eth.BlockRef) error
UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.BlockRef) error
UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.BlockRef, lastDerived eth.BlockRef) error
UpdateFinalizedL1(ctx context.Context, chainID types.ChainID, finalized eth.BlockRef) error
}
type Backend interface {
......@@ -39,6 +39,8 @@ type QueryFrontend struct {
Supervisor QueryBackend
}
var _ QueryBackend = (*QueryFrontend)(nil)
// CheckMessage checks the safety-level of an individual message.
// The payloadHash references the hash of the message-payload of the message.
func (q *QueryFrontend) CheckMessage(identifier types.Identifier, payloadHash common.Hash) (types.SafetyLevel, error) {
......@@ -65,7 +67,7 @@ func (q *QueryFrontend) Finalized(ctx context.Context, chainID types.ChainID) (e
return q.Supervisor.Finalized(ctx, chainID)
}
func (q *QueryFrontend) DerivedFrom(ctx context.Context, chainID types.ChainID, derived eth.BlockID) (derivedFrom eth.BlockID, err error) {
func (q *QueryFrontend) DerivedFrom(ctx context.Context, chainID types.ChainID, derived eth.BlockID) (derivedFrom eth.BlockRef, err error) {
return q.Supervisor.DerivedFrom(ctx, chainID, derived)
}
......@@ -73,6 +75,8 @@ type AdminFrontend struct {
Supervisor Backend
}
var _ AdminBackend = (*AdminFrontend)(nil)
// Start starts the service, if it was previously stopped.
func (a *AdminFrontend) Start(ctx context.Context) error {
return a.Supervisor.Start(ctx)
......@@ -92,14 +96,16 @@ type UpdatesFrontend struct {
Supervisor UpdatesBackend
}
func (u *UpdatesFrontend) UpdateLocalUnsafe(chainID types.ChainID, head eth.BlockRef) error {
return u.Supervisor.UpdateLocalUnsafe(chainID, head)
var _ UpdatesBackend = (*UpdatesFrontend)(nil)
func (u *UpdatesFrontend) UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.BlockRef) error {
return u.Supervisor.UpdateLocalUnsafe(ctx, chainID, head)
}
func (u *UpdatesFrontend) UpdateLocalSafe(chainID types.ChainID, derivedFrom eth.BlockRef, lastDerived eth.BlockRef) error {
return u.Supervisor.UpdateLocalSafe(chainID, derivedFrom, lastDerived)
func (u *UpdatesFrontend) UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.BlockRef, lastDerived eth.BlockRef) error {
return u.Supervisor.UpdateLocalSafe(ctx, chainID, derivedFrom, lastDerived)
}
func (u *UpdatesFrontend) UpdateFinalizedL1(chainID types.ChainID, finalized eth.BlockRef) error {
return u.Supervisor.UpdateFinalizedL1(chainID, finalized)
func (u *UpdatesFrontend) UpdateFinalizedL1(ctx context.Context, chainID types.ChainID, finalized eth.BlockRef) error {
return u.Supervisor.UpdateFinalizedL1(ctx, chainID, finalized)
}
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