Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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 tm2/pkg/bft/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,10 @@ type BaseConfig struct {

// TCP or UNIX socket address for the profiling server to listen on
ProfListenAddress string `toml:"prof_laddr" comment:"TCP or UNIX socket address for the profiling server to listen on"`

// If non-zero, the node will halt after committing this block height.
// Useful for coordinated chain upgrades.
HaltHeight int64 `toml:"halt_height" comment:"If non-zero, the node will halt after committing this block height.\n Useful for coordinated chain upgrades."`
}

// DefaultBaseConfig returns a default base configuration for a Tendermint node
Expand Down
17 changes: 17 additions & 0 deletions tm2/pkg/bft/consensus/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ type ConsensusState struct {
doPrevote func(height int64, round int)
setProposal func(proposal *types.Proposal) error

// if non-zero, the node will stop after committing this height
haltHeight int64

// closed when we finish shutting down
done chan struct{}
}
Expand Down Expand Up @@ -195,6 +198,12 @@ func (cs *ConsensusState) SetLogger(l *slog.Logger) {
cs.timeoutTicker.SetLogger(l)
}

// SetHaltHeight sets the height at which the node will stop after committing.
// If set to 0, the node runs indefinitely.
func (cs *ConsensusState) SetHaltHeight(height int64) {
cs.haltHeight = height
}

// SetEventSwitch sets event bus.
func (cs *ConsensusState) SetEventSwitch(evsw events.EventSwitch) {
cs.evsw = evsw
Expand Down Expand Up @@ -1402,6 +1411,14 @@ func (cs *ConsensusState) finalizeCommit(height int64) {

// Log the telemetry
cs.logTelemetry(block)

// Check if we should halt at this height
if cs.haltHeight > 0 && height >= cs.haltHeight {
cs.Logger.Info("Halt height reached, shutting down", "height", height, "halt_height", cs.haltHeight)
if err := osm.Kill(); err != nil {
cs.Logger.Error("Failed to halt node", "err", err)
}
}
}

// -----------------------------------------------------------------------------
Expand Down
23 changes: 23 additions & 0 deletions tm2/pkg/bft/consensus/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1807,3 +1807,26 @@ func TestStateOutputVoteStats(t *testing.T) {
func subscribe(evsw events.EventSwitch, protoevent events.Event) <-chan events.Event {
return events.SubscribeToEvent(evsw, testSubscriber, protoevent)
}

func TestSetHaltHeight(t *testing.T) {
t.Helper()
Comment thread
moul marked this conversation as resolved.
Outdated

cs := &ConsensusState{}

// Default should be 0 (no halt)
if cs.haltHeight != 0 {
t.Fatalf("expected default haltHeight to be 0, got %d", cs.haltHeight)
}

// Set halt height
cs.SetHaltHeight(100)
if cs.haltHeight != 100 {
t.Fatalf("expected haltHeight to be 100, got %d", cs.haltHeight)
}

// Set to 0 to disable
cs.SetHaltHeight(0)
if cs.haltHeight != 0 {
t.Fatalf("expected haltHeight to be 0, got %d", cs.haltHeight)
}
}
6 changes: 6 additions & 0 deletions tm2/pkg/bft/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,12 @@ func NewNode(config *cfg.Config,
option(node)
}

// Apply halt height from config
if config.BaseConfig.HaltHeight > 0 {
node.consensusState.SetHaltHeight(config.BaseConfig.HaltHeight)
logger.Info("Halt height configured", "height", config.BaseConfig.HaltHeight)
}

return node, nil
}

Expand Down
Loading