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
24 changes: 24 additions & 0 deletions op-supervisor/supervisor/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,30 @@ func (su *SupervisorBackend) SafeView(ctx context.Context, chainID types.ChainID
}, nil
}

func (su *SupervisorBackend) LocalSafe(ctx context.Context, chainID types.ChainID) (eth.BlockID, eth.BlockID, error) {
df, d, err := su.chainDBs.LocalSafe(chainID)
if err != nil {
return eth.BlockID{}, eth.BlockID{}, err
}
return df.ID(), d.ID(), nil
}

func (su *SupervisorBackend) LatestUnsafe(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) {
v, err := su.chainDBs.LocalUnsafe(chainID)
if err != nil {
return eth.BlockID{}, err
}
return v.ID(), nil
}

func (su *SupervisorBackend) SafeDerivedAt(ctx context.Context, chainID types.ChainID, derivedFrom eth.BlockID) (eth.BlockID, error) {
v, err := su.chainDBs.SafeDerivedAt(chainID, derivedFrom)
if err != nil {
return eth.BlockID{}, err
}
return v.ID(), nil
}

func (su *SupervisorBackend) Finalized(ctx context.Context, chainID types.ChainID) (eth.BlockID, error) {
v, err := su.chainDBs.Finalized(chainID)
if err != nil {
Expand Down
12 changes: 12 additions & 0 deletions op-supervisor/supervisor/backend/db/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,18 @@ func (db *ChainsDB) IsLocalUnsafe(chainID types.ChainID, block eth.BlockID) erro
return nil
}

func (db *ChainsDB) SafeDerivedAt(chainID types.ChainID, derivedFrom eth.BlockID) (types.BlockSeal, error) {
lDB, ok := db.localDBs.Get(chainID)
if !ok {
return types.BlockSeal{}, types.ErrUnknownChain
}
derived, err := lDB.LastDerivedAt(derivedFrom)
if err != nil {
return types.BlockSeal{}, fmt.Errorf("failed to find derived block %s: %w", derivedFrom, err)
}
return derived, nil
}

func (db *ChainsDB) LocalUnsafe(chainID types.ChainID) (types.BlockSeal, error) {
eventsDB, ok := db.logDBs.Get(chainID)
if !ok {
Expand Down
48 changes: 45 additions & 3 deletions op-supervisor/supervisor/backend/syncnode/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ type chainsDB interface {
type backend interface {
UpdateLocalSafe(ctx context.Context, chainID types.ChainID, derivedFrom eth.BlockRef, lastDerived eth.BlockRef) error
UpdateLocalUnsafe(ctx context.Context, chainID types.ChainID, head eth.BlockRef) error
LocalSafe(ctx context.Context, chainID types.ChainID) (derivedFrom eth.BlockID, derived eth.BlockID, err error)
LatestUnsafe(ctx context.Context, chainID types.ChainID) (eth.BlockID, error)
SafeDerivedAt(ctx context.Context, chainID types.ChainID, derivedFrom eth.BlockID) (derived eth.BlockID, err error)
Finalized(ctx context.Context, chainID types.ChainID) (eth.BlockID, error)
}

const (
Expand Down Expand Up @@ -175,9 +179,47 @@ func (m *ManagedNode) onDerivationUpdate(pair types.DerivedPair) {
if err := m.backend.UpdateLocalSafe(ctx, m.chainID, pair.DerivedFrom, pair.Derived); err != nil {
m.log.Warn("Backend failed to process local-safe update",
"derived", pair.Derived, "derivedFrom", pair.DerivedFrom, "err", err)
// TODO: if conflict error -> send reset to drop
// TODO: if future error -> send reset to rewind
// TODO: if out of order -> warn, just old data
m.resetSignal(err, pair.DerivedFrom)
}
}

func (m *ManagedNode) resetSignal(errSignal error, l1Ref eth.BlockRef) {
// if conflict error -> send reset to drop
// if future error -> send reset to rewind
// if out of order -> warn, just old data
ctx, cancel := context.WithTimeout(m.ctx, dbTimeout)
defer cancel()
u, err := m.backend.LatestUnsafe(ctx, m.chainID)
if err != nil {
m.log.Warn("Node failed to reset", "err", err)
}
f, err := m.backend.Finalized(ctx, m.chainID)
if err != nil {
m.log.Warn("Node failed to reset", "err", err)
}
switch errSignal {
case types.ErrConflict:
s, err := m.backend.SafeDerivedAt(ctx, m.chainID, l1Ref.ID())
if err != nil {
m.log.Warn("Node failed to reset", "err", err)
}
log.Debug("Node detected conflict, resetting", "unsafe", u, "safe", s, "finalized", f)
err = m.Node.Reset(ctx, u, s, f)
if err != nil {
m.log.Warn("Node failed to reset", "err", err)
}
case types.ErrFuture:
_, s, err := m.backend.LocalSafe(ctx, m.chainID)
if err != nil {
m.log.Warn("Node failed to reset", "err", err)
}
log.Debug("Node detected future block, resetting", "unsafe", u, "safe", s, "finalized", f)
err = m.Node.Reset(ctx, u, s, f)
if err != nil {
m.log.Warn("Node failed to reset", "err", err)
}
case types.ErrOutOfOrder:
m.log.Warn("Node detected out of order block", "unsafe", u, "finalized", f)
}
}

Expand Down