Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

op-node: Add admin_sequencerActive RPC method #6190

Merged
merged 2 commits into from
Jun 29, 2023
Merged
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
4 changes: 4 additions & 0 deletions op-e2e/actions/l2_verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ func (s *l2VerifierBackend) StopSequencer(ctx context.Context) (common.Hash, err
return common.Hash{}, errors.New("stopping the L2Verifier sequencer is not supported")
}

func (s *l2VerifierBackend) SequencerActive(ctx context.Context) (bool, error) {
return false, nil
}

func (s *L2Verifier) L2Finalized() eth.L2BlockRef {
return s.derivation.Finalized()
}
Expand Down
26 changes: 22 additions & 4 deletions op-e2e/system_adminrpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,46 @@ func TestStopStartSequencer(t *testing.T) {

nodeRPC, err := rpc.DialContext(context.Background(), rollupNode.HTTPEndpoint())
require.Nil(t, err, "Error dialing node")
rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(nodeRPC))

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
active, err := rollupClient.SequencerActive(ctx)
require.NoError(t, err)
require.True(t, active, "sequencer should be active")

blockBefore := latestBlock(t, l2Seq)
time.Sleep(time.Duration(cfg.DeployConfig.L2BlockTime+1) * time.Second)
blockAfter := latestBlock(t, l2Seq)
require.Greaterf(t, blockAfter, blockBefore, "Chain did not advance")

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
blockHash := common.Hash{}
err = nodeRPC.CallContext(ctx, &blockHash, "admin_stopSequencer")
blockHash, err := rollupClient.StopSequencer(ctx)
require.Nil(t, err, "Error stopping sequencer")

ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
active, err = rollupClient.SequencerActive(ctx)
require.NoError(t, err)
require.False(t, active, "sequencer should be inactive")

blockBefore = latestBlock(t, l2Seq)
time.Sleep(time.Duration(cfg.DeployConfig.L2BlockTime+1) * time.Second)
blockAfter = latestBlock(t, l2Seq)
require.Equal(t, blockAfter, blockBefore, "Chain advanced after stopping sequencer")

ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err = nodeRPC.CallContext(ctx, nil, "admin_startSequencer", blockHash)
err = rollupClient.StartSequencer(ctx, blockHash)
require.Nil(t, err, "Error starting sequencer")

ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
active, err = rollupClient.SequencerActive(ctx)
require.NoError(t, err)
require.True(t, active, "sequencer should be active again")

blockBefore = latestBlock(t, l2Seq)
time.Sleep(time.Duration(cfg.DeployConfig.L2BlockTime+1) * time.Second)
blockAfter = latestBlock(t, l2Seq)
Expand Down
7 changes: 7 additions & 0 deletions op-node/node/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type driverClient interface {
ResetDerivationPipeline(context.Context) error
StartSequencer(ctx context.Context, blockHash common.Hash) error
StopSequencer(context.Context) (common.Hash, error)
SequencerActive(context.Context) (bool, error)
}

type rpcMetrics interface {
Expand Down Expand Up @@ -65,6 +66,12 @@ func (n *adminAPI) StopSequencer(ctx context.Context) (common.Hash, error) {
return n.dr.StopSequencer(ctx)
}

func (n *adminAPI) SequencerActive(ctx context.Context) (bool, error) {
recordDur := n.m.RecordRPCServerRequest("admin_sequencerActive")
defer recordDur()
return n.dr.SequencerActive(ctx)
}

type nodeAPI struct {
config *rollup.Config
client l2EthClient
Expand Down
4 changes: 4 additions & 0 deletions op-node/node/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,7 @@ func (c *mockDriverClient) StartSequencer(ctx context.Context, blockHash common.
func (c *mockDriverClient) StopSequencer(ctx context.Context) (common.Hash, error) {
return c.Mock.MethodCalled("StopSequencer").Get(0).(common.Hash), nil
}

func (c *mockDriverClient) SequencerActive(ctx context.Context) (bool, error) {
return c.Mock.MethodCalled("SequencerActive").Get(0).(bool), nil
}
1 change: 1 addition & 0 deletions op-node/rollup/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ func NewDriver(driverCfg *Config, cfg *rollup.Config, l2 L2Chain, l1 L1Chain, al
forceReset: make(chan chan struct{}, 10),
startSequencer: make(chan hashAndErrorChannel, 10),
stopSequencer: make(chan chan hashAndError, 10),
sequencerActive: make(chan chan bool, 10),
sequencerNotifs: sequencerStateListener,
config: cfg,
driverConfig: driverCfg,
Expand Down
25 changes: 25 additions & 0 deletions op-node/rollup/driver/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ type Driver struct {
// It tells the caller that the sequencer stopped by returning the latest sequenced L2 block hash.
stopSequencer chan chan hashAndError

// Upon receiving a channel in this channel, the current sequencer status is queried.
// It tells the caller the status by outputting a boolean to the provided channel:
// true when the sequencer is active, false when it is not.
sequencerActive chan chan bool

// sequencerNotifs is notified when the sequencer is started or stopped
sequencerNotifs SequencerStateListener

Expand Down Expand Up @@ -373,6 +378,8 @@ func (s *Driver) eventLoop() {
s.driverConfig.SequencerStopped = true
respCh <- hashAndError{hash: s.derivation.UnsafeL2Head().Hash}
}
case respCh := <-s.sequencerActive:
respCh <- !s.driverConfig.SequencerStopped
case <-s.done:
return
}
Expand Down Expand Up @@ -436,6 +443,24 @@ func (s *Driver) StopSequencer(ctx context.Context) (common.Hash, error) {
}
}

func (s *Driver) SequencerActive(ctx context.Context) (bool, error) {
if !s.driverConfig.SequencerEnabled {
return false, nil
}
respCh := make(chan bool, 1)
select {
case <-ctx.Done():
return false, ctx.Err()
case s.sequencerActive <- respCh:
select {
case <-ctx.Done():
return false, ctx.Err()
case active := <-respCh:
return active, nil
}
}
}

// syncStatus returns the current sync status, and should only be called synchronously with
// the driver event loop to avoid retrieval of an inconsistent status.
func (s *Driver) syncStatus() *eth.SyncStatus {
Expand Down
6 changes: 6 additions & 0 deletions op-node/sources/rollupclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,9 @@ func (r *RollupClient) StopSequencer(ctx context.Context) (common.Hash, error) {
err := r.rpc.CallContext(ctx, &result, "admin_stopSequencer")
return result, err
}

func (r *RollupClient) SequencerActive(ctx context.Context) (bool, error) {
var result bool
err := r.rpc.CallContext(ctx, &result, "admin_sequencerActive")
return result, err
}