Commit 57a89fbb authored by Michael de Hoog's avatar Michael de Hoog

Receive latest block hash from admin_stopSequencer

Pass block hash to admin_startSequencer
parent f4b6928d
...@@ -113,12 +113,12 @@ func (s *l2VerifierBackend) ResetDerivationPipeline(ctx context.Context) error { ...@@ -113,12 +113,12 @@ func (s *l2VerifierBackend) ResetDerivationPipeline(ctx context.Context) error {
return nil return nil
} }
func (s *l2VerifierBackend) StartSequencer(ctx context.Context) error { func (s *l2VerifierBackend) StartSequencer(ctx context.Context, blockHash common.Hash) error {
return nil return nil
} }
func (s *l2VerifierBackend) StopSequencer(ctx context.Context) error { func (s *l2VerifierBackend) StopSequencer(ctx context.Context) (common.Hash, error) {
return errors.New("stopping the L2Verifier sequencer is not supported") return common.Hash{}, errors.New("stopping the L2Verifier sequencer is not supported")
} }
func (s *L2Verifier) L2Finalized() eth.L2BlockRef { func (s *L2Verifier) L2Finalized() eth.L2BlockRef {
......
...@@ -1153,7 +1153,8 @@ func TestStopStartSequencer(t *testing.T) { ...@@ -1153,7 +1153,8 @@ func TestStopStartSequencer(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel() defer cancel()
err = nodeRPC.CallContext(ctx, nil, "admin_stopSequencer") blockHash := common.Hash{}
err = nodeRPC.CallContext(ctx, &blockHash, "admin_stopSequencer")
require.Nil(t, err, "Error stopping sequencer") require.Nil(t, err, "Error stopping sequencer")
blockBefore = latestBlock(t, l2Seq) blockBefore = latestBlock(t, l2Seq)
...@@ -1163,7 +1164,7 @@ func TestStopStartSequencer(t *testing.T) { ...@@ -1163,7 +1164,7 @@ func TestStopStartSequencer(t *testing.T) {
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel() defer cancel()
err = nodeRPC.CallContext(ctx, nil, "admin_startSequencer") err = nodeRPC.CallContext(ctx, nil, "admin_startSequencer", blockHash)
require.Nil(t, err, "Error starting sequencer") require.Nil(t, err, "Error starting sequencer")
blockBefore = latestBlock(t, l2Seq) blockBefore = latestBlock(t, l2Seq)
......
...@@ -26,8 +26,8 @@ type driverClient interface { ...@@ -26,8 +26,8 @@ type driverClient interface {
SyncStatus(ctx context.Context) (*eth.SyncStatus, error) SyncStatus(ctx context.Context) (*eth.SyncStatus, error)
BlockRefWithStatus(ctx context.Context, num uint64) (eth.L2BlockRef, *eth.SyncStatus, error) BlockRefWithStatus(ctx context.Context, num uint64) (eth.L2BlockRef, *eth.SyncStatus, error)
ResetDerivationPipeline(context.Context) error ResetDerivationPipeline(context.Context) error
StartSequencer(context.Context) error StartSequencer(ctx context.Context, blockHash common.Hash) error
StopSequencer(context.Context) error StopSequencer(context.Context) (common.Hash, error)
} }
type rpcMetrics interface { type rpcMetrics interface {
...@@ -53,13 +53,13 @@ func (n *adminAPI) ResetDerivationPipeline(ctx context.Context) error { ...@@ -53,13 +53,13 @@ func (n *adminAPI) ResetDerivationPipeline(ctx context.Context) error {
return n.dr.ResetDerivationPipeline(ctx) return n.dr.ResetDerivationPipeline(ctx)
} }
func (n *adminAPI) StartSequencer(ctx context.Context) error { func (n *adminAPI) StartSequencer(ctx context.Context, blockHash common.Hash) error {
recordDur := n.m.RecordRPCServerRequest("admin_startSequencer") recordDur := n.m.RecordRPCServerRequest("admin_startSequencer")
defer recordDur() defer recordDur()
return n.dr.StartSequencer(ctx) return n.dr.StartSequencer(ctx, blockHash)
} }
func (n *adminAPI) StopSequencer(ctx context.Context) error { func (n *adminAPI) StopSequencer(ctx context.Context) (common.Hash, error) {
recordDur := n.m.RecordRPCServerRequest("admin_stopSequencer") recordDur := n.m.RecordRPCServerRequest("admin_stopSequencer")
defer recordDur() defer recordDur()
return n.dr.StopSequencer(ctx) return n.dr.StopSequencer(ctx)
......
...@@ -219,10 +219,10 @@ func (c *mockDriverClient) ResetDerivationPipeline(ctx context.Context) error { ...@@ -219,10 +219,10 @@ func (c *mockDriverClient) ResetDerivationPipeline(ctx context.Context) error {
return c.Mock.MethodCalled("ResetDerivationPipeline").Get(0).(error) return c.Mock.MethodCalled("ResetDerivationPipeline").Get(0).(error)
} }
func (c *mockDriverClient) StartSequencer(ctx context.Context) error { func (c *mockDriverClient) StartSequencer(ctx context.Context, blockHash common.Hash) error {
return c.Mock.MethodCalled("StartSequencer").Get(0).(error) return c.Mock.MethodCalled("StartSequencer").Get(0).(error)
} }
func (c *mockDriverClient) StopSequencer(ctx context.Context) error { func (c *mockDriverClient) StopSequencer(ctx context.Context) (common.Hash, error) {
return c.Mock.MethodCalled("StopSequencer").Get(0).(error) return c.Mock.MethodCalled("StopSequencer").Get(0).(common.Hash), nil
} }
...@@ -97,8 +97,8 @@ func NewDriver(driverCfg *Config, cfg *rollup.Config, l2 L2Chain, l1 L1Chain, ne ...@@ -97,8 +97,8 @@ func NewDriver(driverCfg *Config, cfg *rollup.Config, l2 L2Chain, l1 L1Chain, ne
idleDerivation: false, idleDerivation: false,
stateReq: make(chan chan struct{}), stateReq: make(chan chan struct{}),
forceReset: make(chan chan struct{}, 10), forceReset: make(chan chan struct{}, 10),
startSequencer: make(chan chan struct{}, 10), startSequencer: make(chan hashAndErrorChannel, 10),
stopSequencer: make(chan chan struct{}, 10), stopSequencer: make(chan chan hashAndError, 10),
config: cfg, config: cfg,
driverConfig: driverCfg, driverConfig: driverCfg,
done: make(chan struct{}), done: make(chan struct{}),
......
package driver package driver
import ( import (
"bytes"
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
...@@ -9,6 +10,7 @@ import ( ...@@ -9,6 +10,7 @@ import (
gosync "sync" gosync "sync"
"time" "time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/eth"
...@@ -42,13 +44,13 @@ type Driver struct { ...@@ -42,13 +44,13 @@ type Driver struct {
// It tells the caller that the reset occurred by closing the passed in channel. // It tells the caller that the reset occurred by closing the passed in channel.
forceReset chan chan struct{} forceReset chan chan struct{}
// Upon receiving a channel in this channel, the sequencer is started. // Upon receiving a hash in this channel, the sequencer is started at the given hash.
// It tells the caller that the sequencer started by closing the passed in channel. // It tells the caller that the sequencer started by closing the passed in channel (or returning an error).
startSequencer chan chan struct{} startSequencer chan hashAndErrorChannel
// Upon receiving a channel in this channel, the sequencer is stopped. // Upon receiving a channel in this channel, the sequencer is stopped.
// It tells the caller that the sequencer stopped by closing the passed in channel. // It tells the caller that the sequencer stopped by returning the latest sequenced L2 block hash.
stopSequencer chan chan struct{} stopSequencer chan chan hashAndError
// Rollup config: rollup chain configuration // Rollup config: rollup chain configuration
config *rollup.Config config *rollup.Config
...@@ -375,15 +377,26 @@ func (s *Driver) eventLoop() { ...@@ -375,15 +377,26 @@ func (s *Driver) eventLoop() {
s.derivation.Reset() s.derivation.Reset()
s.metrics.RecordPipelineReset() s.metrics.RecordPipelineReset()
close(respCh) close(respCh)
case respCh := <-s.startSequencer: case resp := <-s.startSequencer:
s.log.Info("Sequencer has been started") unsafeHead := s.derivation.UnsafeL2Head().Hash
s.driverConfig.SequencerEnabled = true if s.driverConfig.SequencerEnabled {
sequencingPlannedOnto = eth.BlockID{} resp.err <- errors.New("sequencer already running")
close(respCh) } else if !bytes.Equal(unsafeHead[:], resp.hash[:]) {
resp.err <- fmt.Errorf("block hash does not match: head %s, received %s", unsafeHead.String(), resp.hash.String())
} else {
s.log.Info("Sequencer has been started")
s.driverConfig.SequencerEnabled = true
sequencingPlannedOnto = eth.BlockID{}
close(resp.err)
}
case respCh := <-s.stopSequencer: case respCh := <-s.stopSequencer:
s.log.Warn("Sequencer has been stopped") if !s.driverConfig.SequencerEnabled {
s.driverConfig.SequencerEnabled = false respCh <- hashAndError{err: errors.New("sequencer not running")}
close(respCh) } else {
s.log.Warn("Sequencer has been stopped")
s.driverConfig.SequencerEnabled = false
respCh <- hashAndError{hash: s.derivation.UnsafeL2Head().Hash}
}
case <-s.done: case <-s.done:
return return
} }
...@@ -408,32 +421,35 @@ func (s *Driver) ResetDerivationPipeline(ctx context.Context) error { ...@@ -408,32 +421,35 @@ func (s *Driver) ResetDerivationPipeline(ctx context.Context) error {
} }
} }
func (s *Driver) StartSequencer(ctx context.Context) error { func (s *Driver) StartSequencer(ctx context.Context, blockHash common.Hash) error {
respCh := make(chan struct{}, 1) h := hashAndErrorChannel{
hash: blockHash,
err: make(chan error, 1),
}
select { select {
case <-ctx.Done(): case <-ctx.Done():
return ctx.Err() return ctx.Err()
case s.startSequencer <- respCh: case s.startSequencer <- h:
select { select {
case <-ctx.Done(): case <-ctx.Done():
return ctx.Err() return ctx.Err()
case <-respCh: case e := <-h.err:
return nil return e
} }
} }
} }
func (s *Driver) StopSequencer(ctx context.Context) error { func (s *Driver) StopSequencer(ctx context.Context) (common.Hash, error) {
respCh := make(chan struct{}, 1) respCh := make(chan hashAndError, 1)
select { select {
case <-ctx.Done(): case <-ctx.Done():
return ctx.Err() return common.Hash{}, ctx.Err()
case s.stopSequencer <- respCh: case s.stopSequencer <- respCh:
select { select {
case <-ctx.Done(): case <-ctx.Done():
return ctx.Err() return common.Hash{}, ctx.Err()
case <-respCh: case he := <-respCh:
return nil return he.hash, he.err
} }
} }
} }
...@@ -502,3 +518,13 @@ func (s *Driver) snapshot(event string) { ...@@ -502,3 +518,13 @@ func (s *Driver) snapshot(event string) {
"l2Safe", deferJSONString{s.derivation.SafeL2Head()}, "l2Safe", deferJSONString{s.derivation.SafeL2Head()},
"l2FinalizedHead", deferJSONString{s.derivation.Finalized()}) "l2FinalizedHead", deferJSONString{s.derivation.Finalized()})
} }
type hashAndError struct {
hash common.Hash
err error
}
type hashAndErrorChannel struct {
hash common.Hash
err chan error
}
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