-
Notifications
You must be signed in to change notification settings - Fork 4.1k
feat(tools/cosmovisor): cosmovisor batch upgrades #21790
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
Merged
Merged
Changes from 23 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
c347f6c
wip: batch upgrade
psiphi5 cd54cb2
add logic for batch upgrade cmd; logic for swapping upgrade files
psiphi5 e38739d
fmt
psiphi5 322ff72
made some fixes; command now runs successfuly on my machine
psiphi5 b30a8d1
lint
psiphi5 980201d
lint
psiphi5 bc0651d
go mod tidy
psiphi5 68bc6f9
godoc; lint; changelog
psiphi5 34bb0c8
ty coderabbitai
psiphi5 071c677
cometbftrpc default value
psiphi5 054d9ce
fix test; better naming
psiphi5 a7e6459
switch from cometbft websocket to cosmos grpc
psiphi5 3f3c787
cpu opti
psiphi5 d4bdb57
ty coderabbitai
psiphi5 4ae231e
improve ux; nit
psiphi5 bc9fb9b
ty coderabbitai
psiphi5 96dd220
minute things
psiphi5 7f4309e
ty coderabbitai
psiphi5 13be656
gracefully handle corrupted batch files
psiphi5 88da1ba
merge main
psiphi5 1d21f55
Merge branch 'main' into issue-20630
psiphi5 250eae9
switch to using csv file
psiphi5 7e8112d
mark flags with mutex
psiphi5 57bf0a0
nit
psiphi5 ebc78ba
Merge branch 'main' into issue-20630
psiphi5 f91bfc3
fix tests
psiphi5 28d03fe
Merge branch 'main' into issue-20630
psiphi5 4c12e9b
Merge branch 'main' into issue-20630
julienrbrt 4f31076
fix merge
psiphi5 33be971
Merge branch 'main' into issue-20630
psiphi5 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "encoding/csv" | ||
| "encoding/json" | ||
| "fmt" | ||
| "os" | ||
| "path/filepath" | ||
| "strconv" | ||
| "strings" | ||
|
|
||
| "github.com/spf13/cobra" | ||
|
|
||
| "cosmossdk.io/tools/cosmovisor" | ||
| ) | ||
|
|
||
| func NewBatchAddUpgradeCmd() *cobra.Command { | ||
| cmd := &cobra.Command{ | ||
| Use: "add-batch-upgrade [flags]", | ||
| Short: "Add multiple upgrade binaries at specified heights to cosmovisor", | ||
| Long: `This command allows you to specify multiple upgrades at once at specific heights, copying or creating a batch upgrade file that's actively watched during 'cosmovisor run'. | ||
| You can provide upgrades in two ways: | ||
|
|
||
| 1. Using --upgrade-file: Specify a path to a headerless CSV batch upgrade file in the format: | ||
| upgrade-name,path-to-exec,upgrade-height | ||
|
|
||
| 2. Using --upgrade-list: Provide a comma-separated list of upgrades. | ||
| Each upgrade is defined by three colon-separated values: | ||
| a. upgrade-name: A unique identifier for the upgrade | ||
| b. path-to-exec: The file path to the upgrade's executable binary | ||
| c. upgrade-height: The block height at which the upgrade should occur | ||
| This creates a batch upgrade JSON file with the upgrade-info objects in the upgrade directory. | ||
|
|
||
| Note: You must provide either --upgrade-file or --upgrade-list.`, | ||
| Example: `cosmovisor add-batch-upgrade --upgrade-list upgrade_v2:/path/to/v2/binary:1000000,upgrade_v3:/path/to/v3/binary:2000000 | ||
|
|
||
| cosmovisor add-batch-upgrade --upgrade-file /path/to/batch_upgrade.json`, | ||
psiphi5 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| SilenceUsage: true, | ||
| Args: cobra.NoArgs, | ||
| RunE: addBatchUpgrade, | ||
| } | ||
|
|
||
| cmd.Flags().String("upgrade-file", "", "Path to a batch upgrade file which is a JSON array of upgrade-info objects") | ||
| cmd.Flags().StringSlice("upgrade-list", []string{}, "List of comma-separated upgrades in the format 'name:path/to/binary:height'") | ||
| cmd.MarkFlagsMutuallyExclusive("upgrade-file", "upgrade-list") | ||
|
|
||
| return cmd | ||
| } | ||
|
|
||
| // addBatchUpgrade takes in multiple specified upgrades and creates a single | ||
| // batch upgrade file out of them | ||
| func addBatchUpgrade(cmd *cobra.Command, args []string) error { | ||
| cfg, err := getConfigFromCmd(cmd) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| upgradeFile, err := cmd.Flags().GetString("upgrade-file") | ||
| if err == nil && upgradeFile != "" { | ||
| return processUpgradeFile(cfg, upgradeFile) | ||
| } | ||
| upgradeList, err := cmd.Flags().GetStringSlice("upgrade-list") | ||
| if err != nil || len(upgradeList) == 0 { | ||
| return fmt.Errorf("either --upgrade-file or --upgrade-list must be provided") | ||
| } | ||
| var splitUpgrades [][]string | ||
| for _, upgrade := range upgradeList { | ||
| splitUpgrades = append(splitUpgrades, strings.Split(upgrade, ":")) | ||
| } | ||
| return processUpgradeList(cfg, splitUpgrades) | ||
| } | ||
psiphi5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // processUpgradeList takes in a list of upgrades and creates a batch upgrade file | ||
| func processUpgradeList(cfg *cosmovisor.Config, upgradeList [][]string) error { | ||
| upgradeInfoPaths := []string{} | ||
| for i, upgrade := range upgradeList { | ||
| if len(upgrade) != 3 { | ||
| return fmt.Errorf("argument at position %d (%s) is invalid", i, upgrade) | ||
| } | ||
| upgradeName := filepath.Base(upgrade[0]) | ||
| upgradePath := upgrade[1] | ||
| upgradeHeight, err := strconv.ParseInt(upgrade[2], 10, 64) | ||
| if err != nil { | ||
| return fmt.Errorf("upgrade height at position %d (%s) is invalid", i, upgrade[2]) | ||
| } | ||
| upgradeInfoPath := cfg.UpgradeInfoFilePath() + "." + upgradeName | ||
| upgradeInfoPaths = append(upgradeInfoPaths, upgradeInfoPath) | ||
| if err := addUpgrade(cfg, true, upgradeHeight, upgradeName, upgradePath, upgradeInfoPath); err != nil { | ||
| return err | ||
| } | ||
| } | ||
psiphi5 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| var allData []json.RawMessage | ||
| for _, uip := range upgradeInfoPaths { | ||
| fileData, err := os.ReadFile(uip) | ||
| if err != nil { | ||
| return fmt.Errorf("error reading file %s: %w", uip, err) | ||
| } | ||
|
|
||
| // Verify it's valid JSON | ||
| var jsonData json.RawMessage | ||
| if err := json.Unmarshal(fileData, &jsonData); err != nil { | ||
| return fmt.Errorf("error parsing JSON from file %s: %w", uip, err) | ||
| } | ||
|
|
||
| // Add to our slice | ||
| allData = append(allData, jsonData) | ||
| } | ||
|
|
||
| // Marshal the combined data | ||
| batchData, err := json.MarshalIndent(allData, "", " ") | ||
| if err != nil { | ||
| return fmt.Errorf("error marshaling combined JSON: %w", err) | ||
| } | ||
|
|
||
| // Write to output file | ||
| err = os.WriteFile(cfg.UpgradeInfoBatchFilePath(), batchData, 0o600) | ||
| if err != nil { | ||
| return fmt.Errorf("error writing combined JSON to file: %w", err) | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
psiphi5 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| // processUpgradeFile takes in a CSV batch upgrade file, parses it and calls processUpgradeList | ||
| func processUpgradeFile(cfg *cosmovisor.Config, upgradeFile string) error { | ||
| file, err := os.Open(upgradeFile) | ||
| if err != nil { | ||
| return fmt.Errorf("error opening upgrade CSV file %s: %w", upgradeFile, err) | ||
| } | ||
| defer file.Close() | ||
|
|
||
| r := csv.NewReader(file) | ||
| r.FieldsPerRecord = 3 | ||
| r.TrimLeadingSpace = true | ||
| records, err := r.ReadAll() | ||
| if err != nil { | ||
| return fmt.Errorf("error parsing upgrade CSV file %s: %w", upgradeFile, err) | ||
| } | ||
| if err := processUpgradeList(cfg, records); err != nil { | ||
| return err | ||
| } | ||
| return nil | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.