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: autoselect binary version #86

Merged
merged 9 commits into from
Nov 21, 2024
Empty file added Dockerfile.kyve
Empty file.
17 changes: 12 additions & 5 deletions cmd/ksync/commands/blocksync.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func init() {

blockSyncCmd.Flags().StringVarP(&appFlags, "app-flags", "f", "", "custom flags which are applied to the app binary start command. Example: --app-flags=\"--x-crisis-skip-assert-invariants,--iavl-disable-fastnode\"")

blockSyncCmd.Flags().BoolVarP(&autoselectBinaryVersion, "autoselect-binary-version", "a", false, "if provided binary is cosmovisor KSYNC will automatically change the \"current\" symlink to the correct upgrade version")
blockSyncCmd.Flags().BoolVarP(&reset, "reset-all", "r", false, "reset this node's validator to genesis state")
blockSyncCmd.Flags().BoolVar(&optOut, "opt-out", false, "disable the collection of anonymous usage data")
blockSyncCmd.Flags().BoolVarP(&debug, "debug", "d", false, "show logs from tendermint app")
Expand Down Expand Up @@ -81,11 +82,6 @@ var blockSyncCmd = &cobra.Command{
logger.Info().Msgf("loaded source \"%s\" from genesis file", source)
}

if engine == "" && binaryPath != "" {
engine = utils.GetEnginePathFromBinary(binaryPath)
logger.Info().Msgf("loaded engine \"%s\" from binary path", engine)
}

bId, _, err := sources.GetPoolIds(chainId, source, blockPoolId, "", registryUrl, true, false)
if err != nil {
return fmt.Errorf("failed to load pool-ids: %w", err)
Expand Down Expand Up @@ -120,10 +116,21 @@ var blockSyncCmd = &cobra.Command{
return fmt.Errorf("failed to close dbs in engine: %w", err)
}

if autoselectBinaryVersion {
if err := sources.SelectCosmovisorVersion(binaryPath, homePath, registryUrl, source, continuationHeight); err != nil {
return fmt.Errorf("failed to autoselect binary version: %w", err)
}
}

if err := sources.IsBinaryRecommendedVersion(binaryPath, registryUrl, source, continuationHeight, !y); err != nil {
return fmt.Errorf("failed to check if binary has the recommended version: %w", err)
}

if engine == "" && binaryPath != "" {
engine = utils.GetEnginePathFromBinary(binaryPath)
logger.Info().Msgf("loaded engine \"%s\" from binary path", engine)
}

consensusEngine, err := engines.EngineSourceFactory(engine, homePath, registryUrl, source, rpcServerPort, continuationHeight)
if err != nil {
return fmt.Errorf("failed to create consensus engine for source: %w", err)
Expand Down
17 changes: 12 additions & 5 deletions cmd/ksync/commands/heightsync.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func init() {

heightSyncCmd.Flags().Int64VarP(&targetHeight, "target-height", "t", 0, "target height (including), if not specified it will sync to the latest available block height")

heightSyncCmd.Flags().BoolVarP(&autoselectBinaryVersion, "autoselect-binary-version", "a", false, "if provided binary is cosmovisor KSYNC will automatically change the \"current\" symlink to the correct upgrade version")
heightSyncCmd.Flags().BoolVarP(&reset, "reset-all", "r", false, "reset this node's validator to genesis state")
heightSyncCmd.Flags().BoolVar(&optOut, "opt-out", false, "disable the collection of anonymous usage data")
heightSyncCmd.Flags().BoolVarP(&debug, "debug", "d", false, "show logs from tendermint app")
Expand Down Expand Up @@ -64,11 +65,6 @@ var heightSyncCmd = &cobra.Command{
homePath = utils.GetHomePathFromBinary(binaryPath)
}

if engine == "" && binaryPath != "" {
engine = utils.GetEnginePathFromBinary(binaryPath)
logger.Info().Msgf("Loaded engine \"%s\" from binary path", engine)
}

defaultEngine := engines.EngineFactory(engine, homePath, rpcServerPort)

if source == "" && blockPoolId == "" && snapshotPoolId == "" {
Expand Down Expand Up @@ -129,10 +125,21 @@ var heightSyncCmd = &cobra.Command{
return fmt.Errorf("failed to close dbs in engine: %w", err)
}

if autoselectBinaryVersion {
if err := sources.SelectCosmovisorVersion(binaryPath, homePath, registryUrl, source, continuationHeight); err != nil {
return fmt.Errorf("failed to autoselect binary version: %w", err)
}
}

if err := sources.IsBinaryRecommendedVersion(binaryPath, registryUrl, source, continuationHeight, !y); err != nil {
return fmt.Errorf("failed to check if binary has the recommended version: %w", err)
}

if engine == "" && binaryPath != "" {
engine = utils.GetEnginePathFromBinary(binaryPath)
logger.Info().Msgf("Loaded engine \"%s\" from binary path", engine)
}

consensusEngine, err := engines.EngineSourceFactory(engine, homePath, registryUrl, source, rpcServerPort, continuationHeight)
if err != nil {
return fmt.Errorf("failed to create consensus engine for source: %w", err)
Expand Down
60 changes: 30 additions & 30 deletions cmd/ksync/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,36 @@ import (
)

var (
engine string
binaryPath string
homePath string
chainId string
chainRest string
storageRest string
blockRpc string
snapshotPoolId string
blockPoolId string
startHeight int64
targetHeight int64
rpcServer bool
rpcServerPort int64
snapshotPort int64
blockRpcReqTimeout int64
source string
pruning bool
keepSnapshots bool
skipWaiting bool
backupInterval int64
backupKeepRecent int64
backupCompression string
backupDest string
appFlags string
skipCrisisInvariants bool
reset bool
keepAddrBook bool
optOut bool
debug bool
y bool
engine string
binaryPath string
homePath string
chainId string
chainRest string
storageRest string
blockRpc string
snapshotPoolId string
blockPoolId string
startHeight int64
targetHeight int64
rpcServer bool
rpcServerPort int64
snapshotPort int64
blockRpcReqTimeout int64
source string
pruning bool
keepSnapshots bool
skipWaiting bool
backupInterval int64
backupKeepRecent int64
backupCompression string
backupDest string
appFlags string
autoselectBinaryVersion bool
reset bool
keepAddrBook bool
optOut bool
debug bool
y bool
)

var (
Expand Down
17 changes: 12 additions & 5 deletions cmd/ksync/commands/serveblocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func init() {
serveBlocksCmd.Flags().StringVarP(&source, "source", "s", "", "chain-id of the source")
serveBlocksCmd.Flags().StringVar(&registryUrl, "registry-url", utils.DefaultRegistryURL, "URL to fetch latest KYVE Source-Registry")

serveBlocksCmd.Flags().BoolVarP(&autoselectBinaryVersion, "autoselect-binary-version", "a", false, "if provided binary is cosmovisor KSYNC will automatically change the \"current\" symlink to the correct upgrade version")
serveBlocksCmd.Flags().BoolVarP(&reset, "reset-all", "r", false, "reset this node's validator to genesis state")
serveBlocksCmd.Flags().BoolVar(&optOut, "opt-out", false, "disable the collection of anonymous usage data")
serveBlocksCmd.Flags().BoolVarP(&debug, "debug", "d", false, "show logs from tendermint app")
Expand All @@ -64,11 +65,6 @@ var serveBlocksCmd = &cobra.Command{
homePath = utils.GetHomePathFromBinary(binaryPath)
}

if engine == "" && binaryPath != "" {
engine = utils.GetEnginePathFromBinary(binaryPath)
logger.Info().Msgf("Loaded engine \"%s\" from binary path", engine)
}

defaultEngine := engines.EngineFactory(engine, homePath, rpcServerPort)

if source == "" && blockPoolId == "" {
Expand Down Expand Up @@ -109,10 +105,21 @@ var serveBlocksCmd = &cobra.Command{
return fmt.Errorf("failed to close dbs in engine: %w", err)
}

if autoselectBinaryVersion {
if err := sources.SelectCosmovisorVersion(binaryPath, homePath, registryUrl, source, continuationHeight); err != nil {
return fmt.Errorf("failed to autoselect binary version: %w", err)
}
}

if err := sources.IsBinaryRecommendedVersion(binaryPath, registryUrl, source, continuationHeight, !y); err != nil {
return fmt.Errorf("failed to check if binary has the recommended version: %w", err)
}

if engine == "" && binaryPath != "" {
engine = utils.GetEnginePathFromBinary(binaryPath)
logger.Info().Msgf("Loaded engine \"%s\" from binary path", engine)
}

consensusEngine, err := engines.EngineSourceFactory(engine, homePath, registryUrl, source, rpcServerPort, continuationHeight)
if err != nil {
return fmt.Errorf("failed to create consensus engine for source: %w", err)
Expand Down
17 changes: 12 additions & 5 deletions cmd/ksync/commands/servesnapshots.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func init() {

servesnapshotsCmd.Flags().StringVarP(&appFlags, "app-flags", "f", "", "custom flags which are applied to the app binary start command. Example: --app-flags=\"--x-crisis-skip-assert-invariants,--iavl-disable-fastnode\"")

servesnapshotsCmd.Flags().BoolVarP(&autoselectBinaryVersion, "autoselect-binary-version", "a", false, "if provided binary is cosmovisor KSYNC will automatically change the \"current\" symlink to the correct upgrade version")
servesnapshotsCmd.Flags().BoolVarP(&reset, "reset-all", "r", false, "reset this node's validator to genesis state")
servesnapshotsCmd.Flags().BoolVar(&optOut, "opt-out", false, "disable the collection of anonymous usage data")
servesnapshotsCmd.Flags().BoolVarP(&debug, "debug", "d", false, "show logs from tendermint app")
Expand All @@ -65,11 +66,6 @@ var servesnapshotsCmd = &cobra.Command{
homePath = utils.GetHomePathFromBinary(binaryPath)
}

if engine == "" && binaryPath != "" {
engine = utils.GetEnginePathFromBinary(binaryPath)
logger.Info().Msgf("Loaded engine \"%s\" from binary path", engine)
}

defaultEngine := engines.EngineFactory(engine, homePath, rpcServerPort)

if source == "" && blockPoolId == "" && snapshotPoolId == "" {
Expand Down Expand Up @@ -122,10 +118,21 @@ var servesnapshotsCmd = &cobra.Command{
return fmt.Errorf("failed to close dbs in engine: %w", err)
}

if autoselectBinaryVersion {
if err := sources.SelectCosmovisorVersion(binaryPath, homePath, registryUrl, source, snapshotHeight); err != nil {
return fmt.Errorf("failed to autoselect binary version: %w", err)
}
}

if err := sources.IsBinaryRecommendedVersion(binaryPath, registryUrl, source, continuationHeight, !y); err != nil {
return fmt.Errorf("failed to check if binary has the recommended version: %w", err)
}

if engine == "" && binaryPath != "" {
engine = utils.GetEnginePathFromBinary(binaryPath)
logger.Info().Msgf("Loaded engine \"%s\" from binary path", engine)
}

consensusEngine, err := engines.EngineSourceFactory(engine, homePath, registryUrl, source, rpcServerPort, continuationHeight)
if err != nil {
return fmt.Errorf("failed to create consensus engine for source: %w", err)
Expand Down
17 changes: 12 additions & 5 deletions cmd/ksync/commands/statesync.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func init() {

stateSyncCmd.Flags().Int64VarP(&targetHeight, "target-height", "t", 0, "snapshot height, if not specified it will use the latest available snapshot height")

stateSyncCmd.Flags().BoolVarP(&autoselectBinaryVersion, "autoselect-binary-version", "a", false, "if provided binary is cosmovisor KSYNC will automatically change the \"current\" symlink to the correct upgrade version")
stateSyncCmd.Flags().BoolVarP(&reset, "reset-all", "r", false, "reset this node's validator to genesis state")
stateSyncCmd.Flags().BoolVar(&optOut, "opt-out", false, "disable the collection of anonymous usage data")
stateSyncCmd.Flags().BoolVarP(&debug, "debug", "d", false, "show logs from tendermint app")
Expand Down Expand Up @@ -61,11 +62,6 @@ var stateSyncCmd = &cobra.Command{
homePath = utils.GetHomePathFromBinary(binaryPath)
}

if engine == "" && binaryPath != "" {
engine = utils.GetEnginePathFromBinary(binaryPath)
logger.Info().Msgf("Loaded engine \"%s\" from binary path", engine)
}

defaultEngine := engines.EngineFactory(engine, homePath, rpcServerPort)

if source == "" && snapshotPoolId == "" {
Expand Down Expand Up @@ -94,10 +90,21 @@ var stateSyncCmd = &cobra.Command{
return fmt.Errorf("state-sync validation checks failed: %w", err)
}

if autoselectBinaryVersion {
if err := sources.SelectCosmovisorVersion(binaryPath, homePath, registryUrl, source, snapshotHeight); err != nil {
return fmt.Errorf("failed to autoselect binary version: %w", err)
}
}

if err := sources.IsBinaryRecommendedVersion(binaryPath, registryUrl, source, snapshotHeight, !y); err != nil {
return fmt.Errorf("failed to check if binary has the recommended version: %w", err)
}

if engine == "" && binaryPath != "" {
engine = utils.GetEnginePathFromBinary(binaryPath)
logger.Info().Msgf("Loaded engine \"%s\" from binary path", engine)
}

consensusEngine, err := engines.EngineSourceFactory(engine, homePath, registryUrl, source, rpcServerPort, snapshotHeight)
if err != nil {
return fmt.Errorf("failed to create consensus engine for source: %w", err)
Expand Down
8 changes: 8 additions & 0 deletions engines/tendermint-v34/tendermint.go
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,14 @@ func (engine *Engine) BootstrapState(value []byte) error {
return fmt.Errorf("failed to unmarshal tendermint-ssync bundle: %w", err)
}

// if TimeIotaMs is zero we set it to 1 else the app would panic.
// in rare circumstances this can be zero if the snapshot got
// created with the engine cometbft-v0.37 or cometbft-v0.38 but the
// height is still for tendermint-v0.34
if bundle[0].Value.State.ConsensusParams.Block.TimeIotaMs == 0 {
bundle[0].Value.State.ConsensusParams.Block.TimeIotaMs = 1
}

err := engine.stateStore.Bootstrap(*bundle[0].Value.State)
if err != nil {
return fmt.Errorf("failed to bootstrap state: %s\"", err)
Expand Down
72 changes: 65 additions & 7 deletions sources/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"github.com/KYVENetwork/ksync/sources/helpers"
log "github.com/KYVENetwork/ksync/utils"
"os"
"os/exec"
"strconv"
"strings"
Expand All @@ -13,8 +14,65 @@ var (
logger = log.KsyncLogger("sources")
)

func SelectCosmovisorVersion(binaryPath, homePath, registryUrl, source string, continuationHeight int64) error {
if !strings.HasSuffix(binaryPath, "cosmovisor") || source == "" {
return nil
}

var upgradeName string

entry, err := helpers.GetSourceRegistryEntry(registryUrl, source)
if err != nil {
return fmt.Errorf("failed to get source registry entry: %w", err)
}

for _, upgrade := range entry.Codebase.Settings.Upgrades {
height, err := strconv.ParseInt(upgrade.Height, 10, 64)
if err != nil {
return fmt.Errorf("failed to parse upgrade height %s: %w", upgrade.Height, err)
}

if continuationHeight < height {
break
}

upgradeName = upgrade.Name
}

if upgradeName == "genesis" {
if _, err := os.Stat(fmt.Sprintf("%s/cosmovisor/%s", homePath, upgradeName)); err != nil {
return fmt.Errorf("\"%s\" not installed in cosmovisor", upgradeName)
}
} else {
if _, err := os.Stat(fmt.Sprintf("%s/cosmovisor/upgrades/%s", homePath, upgradeName)); err != nil {
return fmt.Errorf("upgrade \"%s\" not installed in cosmovisor", upgradeName)
}
}

symlinkPath := fmt.Sprintf("%s/cosmovisor/current", homePath)

if _, err := os.Lstat(symlinkPath); err == nil {
if err := os.Remove(symlinkPath); err != nil {
return fmt.Errorf("failed to remove symlink from path %s: %w", symlinkPath, err)
}
}

if upgradeName == "genesis" {
if err := os.Symlink(fmt.Sprintf("%s/cosmovisor/%s", homePath, upgradeName), symlinkPath); err != nil {
return fmt.Errorf("failed to create symlink: %w", err)
}
} else {
if err := os.Symlink(fmt.Sprintf("%s/cosmovisor/upgrades/%s", homePath, upgradeName), symlinkPath); err != nil {
return fmt.Errorf("failed to create symlink: %w", err)
}
}

logger.Info().Msgf("selected binary version \"%s\" from height %d for cosmovisor", upgradeName, continuationHeight)
return nil
}

func IsBinaryRecommendedVersion(binaryPath, registryUrl, source string, continuationHeight int64, userInput bool) error {
if source == "" || !userInput {
if binaryPath == "" || source == "" || !userInput {
return nil
}

Expand All @@ -23,16 +81,17 @@ func IsBinaryRecommendedVersion(binaryPath, registryUrl, source string, continua
return fmt.Errorf("failed to lookup binary path: %w", err)
}

startArgs := make([]string, 0)
cmd := exec.Command(cmdPath)

// if we run with cosmovisor we start with the cosmovisor run command
if strings.HasSuffix(binaryPath, "cosmovisor") {
startArgs = append(startArgs, "run")
cmd.Args = append(cmd.Args, "run")
cmd.Env = append(os.Environ(), "COSMOVISOR_DISABLE_LOGS=true")
}

startArgs = append(startArgs, "version")
cmd.Args = append(cmd.Args, "version")

out, err := exec.Command(cmdPath, startArgs...).Output()
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("failed to get output of binary: %w", err)
}
Expand Down Expand Up @@ -72,8 +131,7 @@ func IsBinaryRecommendedVersion(binaryPath, registryUrl, source string, continua
}

if strings.ToLower(answer) != "y" {
logger.Error().Msg("abort")
return nil
return fmt.Errorf("abort")
}

return nil
Expand Down
Loading