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

feat(manager): allow starting node when sequencer is sentinel #1275

Merged
merged 6 commits into from
Feb 3, 2025
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
1 change: 0 additions & 1 deletion block/fork.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ func (m *Manager) MonitorForkUpdateLoop(ctx context.Context) error {

for {
if err := m.checkForkUpdate(ForkMonitorMessage); err != nil {
m.logger.Error("Check for update.", err)
if errors.Is(err, ErrNonRecoverable) {
return err
}
Expand Down
9 changes: 6 additions & 3 deletions block/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,10 @@ func (m *Manager) Start(ctx context.Context) error {
if m.State.GetProposer() == nil {
m.logger.Info("No proposer on the rollapp, fallback to the hub proposer, if available")
err := m.UpdateProposerFromSL()
if errors.Is(err, settlement.ErrProposerIsSentinel) {
m.logger.Info("No active proposer. Chain is halted. Waiting for a new proposer.", "height", m.State.Height())
err = m.WaitForActiveProposer(ctx)
}
if err != nil {
return err
}
Expand Down Expand Up @@ -316,10 +320,10 @@ func (m *Manager) Start(ctx context.Context) error {
} else if errors.Is(err, gerrc.ErrFault) {
// Here we handle the fault by calling the fraud handler.
// it publishes a DataHealthStatus event to the pubsub and stops the block manager.
m.logger.Error("block manager exited with fault", "error", err)
m.logger.Error("block manager exited with fault")
m.FraudHandler.HandleFault(err)
} else if err != nil {
m.logger.Error("block manager exited with error", "error", err)
m.logger.Error("block manager exited with error")
m.StopManager(err)
}
}()
Expand Down Expand Up @@ -445,7 +449,6 @@ func (m *Manager) setFraudHandler(handler *FreezeHandler) {

// StopManager sets the node as unhealthy and stops the block manager context
func (m *Manager) StopManager(err error) {
m.logger.Info("Freezing node", "err", err)
m.setUnhealthy(err)
m.Cancel()
}
Expand Down
5 changes: 4 additions & 1 deletion block/modes.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package block

import (
"context"
"errors"
"fmt"

"github.com/dymensionxyz/dymint/p2p"
Expand Down Expand Up @@ -52,7 +53,9 @@ func (m *Manager) runAsProposer(ctx context.Context, eg *errgroup.Group) error {

// it is checked again whether the node is the active proposer, since this could have changed after syncing.
amIProposerOnSL, err := m.AmIProposerOnSL()
if err != nil {
if errors.Is(err, settlement.ErrProposerIsSentinel) {
amIProposerOnSL = false
} else if err != nil {
return fmt.Errorf("am i proposer on SL: %w", err)
}
if !amIProposerOnSL {
Expand Down
41 changes: 40 additions & 1 deletion block/sequencers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ package block
import (
"bytes"
"context"
"errors"
"fmt"
"time"

"github.com/dymensionxyz/dymint/settlement"
)

const (
Expand Down Expand Up @@ -63,6 +66,10 @@ func (m *Manager) AmIProposerOnSL() (bool, error) {
localProposerKeyBytes, _ := m.LocalKey.GetPublic().Raw()
// get hub proposer key
SLProposer, err := m.SLClient.GetProposerAtHeight(-1)
// if no proposer set return nil
if errors.Is(err, settlement.ErrProposerIsSentinel) {
return false, nil
}
if err != nil {
return false, fmt.Errorf("get proposer at height: %w", err)
}
Expand Down Expand Up @@ -94,7 +101,11 @@ func (m *Manager) ShouldRotate() (bool, error) {
// At this point we know that there is a next proposer,
// so we should rotate only if we are the current proposer on the hub
amIProposerOnSL, err := m.AmIProposerOnSL()
if err != nil {

// if no proposer assigned, return false without error
if errors.Is(err, settlement.ErrProposerIsSentinel) {
return false, nil
} else if err != nil {
return false, fmt.Errorf("am i proposer on SL: %w", err)
}
return amIProposerOnSL, nil
Expand Down Expand Up @@ -185,3 +196,31 @@ func (m *Manager) UpdateProposerFromSL() error {
m.State.SetProposer(SLProposer)
return nil
}

func (m *Manager) WaitForActiveProposer(ctx context.Context) error {
ticker := time.NewTicker(ProposerMonitorInterval) // TODO: make this configurable
defer ticker.Stop()

for {
select {
case <-ctx.Done():
return nil
case <-ticker.C:

proposer, err := m.SLClient.GetProposerAtHeight(-1)

// no next proposer yet
if errors.Is(err, settlement.ErrProposerIsSentinel) {
continue
}

if err != nil {
return err
}

m.logger.Info("New proposer set.", "nextSeqAddr", proposer.SettlementAddress)
m.State.SetProposer(proposer)
return nil
}
}
}
2 changes: 1 addition & 1 deletion da/weavevm/wvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ func (c *DataAvailabilityLayerClient) waitForTxReceipt(ctx context.Context, txHa
return nil
},
retry.Context(ctx),
retry.Attempts(uint(*c.config.RetryAttempts)),
retry.Attempts(uint(*c.config.RetryAttempts)), //nolint:gosec // RetryAttempts should be always positive
retry.Delay(c.config.RetryDelay),
retry.DelayType(retry.FixedDelay), // Force fixed delay between attempts
retry.LastErrorOnly(true), // Only log the last error
Expand Down
6 changes: 3 additions & 3 deletions settlement/dymension/dymension.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,8 @@ func (c *Client) GetProposerAtHeight(height int64) (*types.Sequencer, error) {
}
}

if proposerAddr == SENTINEL_PROPOSER {
return nil, fmt.Errorf("proposer is sentinel")
if proposerAddr == "" || proposerAddr == SENTINEL_PROPOSER {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when does == "" happens?

return nil, settlement.ErrProposerIsSentinel
}

// Find and return the matching sequencer
Expand Down Expand Up @@ -544,7 +544,7 @@ func (c *Client) GetNextProposer() (*types.Sequencer, error) {
if !found {
return nil, nil
}
if nextAddr == SENTINEL_PROPOSER {
if nextAddr == "" || nextAddr == SENTINEL_PROPOSER {
return &types.Sequencer{}, nil
}

Expand Down
3 changes: 3 additions & 0 deletions settlement/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (
// ErrBatchNotAccepted is returned when a batch is not accepted by the settlement layer.
var ErrBatchNotAccepted = fmt.Errorf("batch not accepted: %w", gerrc.ErrUnknown)

// ErrProposerIsSentinel is returned when a rollapp has no sequencer assigned.
var ErrProposerIsSentinel = fmt.Errorf("proposer is sentinel")

type ErrNextSequencerAddressFraud struct {
Expected string
Actual string
Expand Down
Loading