Merge PR #5005: Add support for halt-time
This commit is contained in:
parent
2c4faf983b
commit
c8d84b4df4
|
@ -57,6 +57,9 @@ via the `--cpu-profile` flag.
|
|||
* (store) [\#4724](https://github.com/cosmos/cosmos-sdk/issues/4724) Multistore supports substore migrations upon load. New `rootmulti.Store.LoadLatestVersionAndUpgrade` method in
|
||||
`Baseapp` supports `StoreLoader` to enable various upgrade strategies. It no
|
||||
longer panics if the store to load contains substores that we didn't explicitly mount.
|
||||
* [\#4979](https://github.com/cosmos/cosmos-sdk/issues/4979) Introduce a new `halt-time` config and
|
||||
CLI option to the `start` command. When provided, an application will halt during `Commit` when the
|
||||
block time is >= the `halt-time`.
|
||||
|
||||
### Improvements
|
||||
|
||||
|
@ -90,6 +93,8 @@ to detail this new feature and how state transitions occur.
|
|||
|
||||
* (cli) [\#4763](https://github.com/cosmos/cosmos-sdk/issues/4763) Fix flag `--min-self-delegation` for staking `EditValidator`
|
||||
* (keys) Fix ledger custom coin type support bug
|
||||
* [\#4979](https://github.com/cosmos/cosmos-sdk/issues/4979) Use `Signal(os.Interrupt)` over
|
||||
`os.Exit(0)` during configured halting to allow any `defer` calls to be executed.
|
||||
|
||||
## [v0.37.0] - 2019-08-21
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
|
@ -214,6 +215,24 @@ func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) (res abci.ResponseDeliv
|
|||
func (app *BaseApp) Commit() (res abci.ResponseCommit) {
|
||||
header := app.deliverState.ctx.BlockHeader()
|
||||
|
||||
var halt bool
|
||||
|
||||
switch {
|
||||
case app.haltHeight > 0 && uint64(header.Height) >= app.haltHeight:
|
||||
halt = true
|
||||
|
||||
case app.haltTime > 0 && header.Time.Unix() >= int64(app.haltTime):
|
||||
halt = true
|
||||
}
|
||||
|
||||
if halt {
|
||||
app.halt()
|
||||
|
||||
// Note: State is not actually committed when halted. Logs from Tendermint
|
||||
// can be ignored.
|
||||
return abci.ResponseCommit{}
|
||||
}
|
||||
|
||||
// Write the DeliverTx state which is cache-wrapped and commit the MultiStore.
|
||||
// The write to the DeliverTx state writes all state transitions to the root
|
||||
// MultiStore (app.cms) so when Commit() is called is persists those values.
|
||||
|
@ -230,18 +249,33 @@ func (app *BaseApp) Commit() (res abci.ResponseCommit) {
|
|||
// empty/reset the deliver state
|
||||
app.deliverState = nil
|
||||
|
||||
defer func() {
|
||||
if app.haltHeight > 0 && uint64(header.Height) == app.haltHeight {
|
||||
app.logger.Info("halting node per configuration", "height", app.haltHeight)
|
||||
os.Exit(0)
|
||||
}
|
||||
}()
|
||||
|
||||
return abci.ResponseCommit{
|
||||
Data: commitID.Hash,
|
||||
}
|
||||
}
|
||||
|
||||
// halt attempts to gracefully shutdown the node via SIGINT and SIGTERM falling
|
||||
// back on os.Exit if both fail.
|
||||
func (app *BaseApp) halt() {
|
||||
app.logger.Info("halting node per configuration", "height", app.haltHeight, "time", app.haltTime)
|
||||
|
||||
p, err := os.FindProcess(os.Getpid())
|
||||
if err == nil {
|
||||
// attempt cascading signals in case SIGINT fails (os dependent)
|
||||
sigIntErr := p.Signal(syscall.SIGINT)
|
||||
sigTermErr := p.Signal(syscall.SIGTERM)
|
||||
|
||||
if sigIntErr == nil || sigTermErr == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Resort to exiting immediately if the process could not be found or killed
|
||||
// via SIGINT/SIGTERM signals.
|
||||
app.logger.Info("failed to send SIGINT/SIGTERM; exiting...")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Query implements the ABCI interface. It delegates to CommitMultiStore if it
|
||||
// implements Queryable.
|
||||
func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
|
||||
|
|
|
@ -100,9 +100,12 @@ type BaseApp struct {
|
|||
// flag for sealing options and parameters to a BaseApp
|
||||
sealed bool
|
||||
|
||||
// height at which to halt the chain and gracefully shutdown
|
||||
// block height at which to halt the chain and gracefully shutdown
|
||||
haltHeight uint64
|
||||
|
||||
// minimum block time (in Unix seconds) at which to halt the chain and gracefully shutdown
|
||||
haltTime uint64
|
||||
|
||||
// application's version string
|
||||
appVersion string
|
||||
}
|
||||
|
@ -341,8 +344,12 @@ func (app *BaseApp) setMinGasPrices(gasPrices sdk.DecCoins) {
|
|||
app.minGasPrices = gasPrices
|
||||
}
|
||||
|
||||
func (app *BaseApp) setHaltHeight(height uint64) {
|
||||
app.haltHeight = height
|
||||
func (app *BaseApp) setHaltHeight(haltHeight uint64) {
|
||||
app.haltHeight = haltHeight
|
||||
}
|
||||
|
||||
func (app *BaseApp) setHaltTime(haltTime uint64) {
|
||||
app.haltTime = haltTime
|
||||
}
|
||||
|
||||
func (app *BaseApp) setInterBlockCache(cache sdk.MultiStorePersistentCache) {
|
||||
|
|
|
@ -29,9 +29,14 @@ func SetMinGasPrices(gasPricesStr string) func(*BaseApp) {
|
|||
return func(bap *BaseApp) { bap.setMinGasPrices(gasPrices) }
|
||||
}
|
||||
|
||||
// SetHaltHeight returns a BaseApp option function that sets the halt height.
|
||||
func SetHaltHeight(height uint64) func(*BaseApp) {
|
||||
return func(bap *BaseApp) { bap.setHaltHeight(height) }
|
||||
// SetHaltHeight returns a BaseApp option function that sets the halt block height.
|
||||
func SetHaltHeight(blockHeight uint64) func(*BaseApp) {
|
||||
return func(bap *BaseApp) { bap.setHaltHeight(blockHeight) }
|
||||
}
|
||||
|
||||
// SetHaltTime returns a BaseApp option function that sets the halt block time.
|
||||
func SetHaltTime(haltTime uint64) func(*BaseApp) {
|
||||
return func(bap *BaseApp) { bap.setHaltTime(haltTime) }
|
||||
}
|
||||
|
||||
// SetInterBlockCache provides a BaseApp option function that sets the
|
||||
|
|
|
@ -18,9 +18,23 @@ type BaseConfig struct {
|
|||
// specified in this config (e.g. 0.25token1;0.0001token2).
|
||||
MinGasPrices string `mapstructure:"minimum-gas-prices"`
|
||||
|
||||
// HaltHeight contains a non-zero height at which a node will gracefully halt
|
||||
// and shutdown that can be used to assist upgrades and testing.
|
||||
// HaltHeight contains a non-zero block height at which a node will gracefully
|
||||
// halt and shutdown that can be used to assist upgrades and testing.
|
||||
//
|
||||
// Note: State will not be committed on the corresponding height and any logs
|
||||
// indicating such can be safely ignored.
|
||||
HaltHeight uint64 `mapstructure:"halt-height"`
|
||||
|
||||
// HaltTime contains a non-zero minimum block time (in Unix seconds) at which
|
||||
// a node will gracefully halt and shutdown that can be used to assist
|
||||
// upgrades and testing.
|
||||
//
|
||||
// Note: State will not be committed on the corresponding height and any logs
|
||||
// indicating such can be safely ignored.
|
||||
HaltTime uint64 `mapstructure:"halt-time"`
|
||||
|
||||
// InterBlockCache enables inter-block caching.
|
||||
InterBlockCache bool `mapstructure:"inter-block-cache"`
|
||||
}
|
||||
|
||||
// Config defines the server's top level configuration
|
||||
|
@ -59,8 +73,8 @@ func (c *Config) GetMinGasPrices() sdk.DecCoins {
|
|||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
BaseConfig{
|
||||
MinGasPrices: defaultMinGasPrices,
|
||||
HaltHeight: 0,
|
||||
MinGasPrices: defaultMinGasPrices,
|
||||
InterBlockCache: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,23 @@ const defaultConfigTemplate = `# This is a TOML config file.
|
|||
# specified in this config (e.g. 0.25token1;0.0001token2).
|
||||
minimum-gas-prices = "{{ .BaseConfig.MinGasPrices }}"
|
||||
|
||||
# HaltHeight contains a non-zero height at which a node will gracefully halt
|
||||
# and shutdown that can be used to assist upgrades and testing.
|
||||
# HaltHeight contains a non-zero block height at which a node will gracefully
|
||||
# halt and shutdown that can be used to assist upgrades and testing.
|
||||
#
|
||||
# Note: State will not be committed on the corresponding height and any logs
|
||||
# indicating such can be safely ignored.
|
||||
halt-height = {{ .BaseConfig.HaltHeight }}
|
||||
|
||||
# HaltTime contains a non-zero minimum block time (in Unix seconds) at which
|
||||
# a node will gracefully halt and shutdown that can be used to assist upgrades
|
||||
# and testing.
|
||||
#
|
||||
# Note: State will not be committed on the corresponding height and any logs
|
||||
# indicating such can be safely ignored.
|
||||
halt-time = {{ .BaseConfig.HaltTime }}
|
||||
|
||||
# InterBlockCache enables inter-block caching.
|
||||
inter-block-cache = {{ .BaseConfig.InterBlockCache }}
|
||||
`
|
||||
|
||||
var configTemplate *template.Template
|
||||
|
|
|
@ -27,6 +27,7 @@ const (
|
|||
flagCPUProfile = "cpu-profile"
|
||||
FlagMinGasPrices = "minimum-gas-prices"
|
||||
FlagHaltHeight = "halt-height"
|
||||
FlagHaltTime = "halt-time"
|
||||
FlagInterBlockCache = "inter-block-cache"
|
||||
)
|
||||
|
||||
|
@ -36,6 +37,24 @@ func StartCmd(ctx *Context, appCreator AppCreator) *cobra.Command {
|
|||
cmd := &cobra.Command{
|
||||
Use: "start",
|
||||
Short: "Run the full node",
|
||||
Long: `Run the full node application with Tendermint in or out of process. By
|
||||
default, the application will run with Tendermint in process.
|
||||
|
||||
Pruning options can be provided via the '--pruning' flag. The options are as follows:
|
||||
|
||||
syncable: only those states not needed for state syncing will be deleted (keeps last 100 + every 10000th)
|
||||
nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
|
||||
everything: all saved states will be deleted, storing only the current state
|
||||
|
||||
Node halting configurations exist in the form of two flags: '--halt-height' and '--halt-time'. During
|
||||
the ABCI Commit phase, the node will check if the current block height is greater than or equal to
|
||||
the halt-height or if the current block time is greater than or equal to the halt-time. If so, the
|
||||
node will attempt to gracefully shutdown and the block will not be committed. In addition, the node
|
||||
will not be able to commit subsequent blocks.
|
||||
|
||||
For profiling and benchmarking purposes, CPU profiling can be enabled via the '--cpu-profile' flag
|
||||
which accepts a path for the resulting pprof file.
|
||||
`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if !viper.GetBool(flagWithTendermint) {
|
||||
ctx.Logger.Info("starting ABCI without Tendermint")
|
||||
|
@ -58,7 +77,8 @@ func StartCmd(ctx *Context, appCreator AppCreator) *cobra.Command {
|
|||
FlagMinGasPrices, "",
|
||||
"Minimum gas prices to accept for transactions; Any fee in a tx must meet this minimum (e.g. 0.01photino;0.0001stake)",
|
||||
)
|
||||
cmd.Flags().Uint64(FlagHaltHeight, 0, "Height at which to gracefully halt the chain and shutdown the node")
|
||||
cmd.Flags().Uint64(FlagHaltHeight, 0, "Block height at which to gracefully halt the chain and shutdown the node")
|
||||
cmd.Flags().Uint64(FlagHaltTime, 0, "Minimum block time (in Unix seconds) at which to gracefully halt the chain and shutdown the node")
|
||||
cmd.Flags().Bool(FlagInterBlockCache, true, "Enable inter-block caching")
|
||||
cmd.Flags().String(flagCPUProfile, "", "Enable CPU profiling and write to the provided file")
|
||||
|
||||
|
|
Loading…
Reference in New Issue