Skip to content

Commit

Permalink
ci: add scripts to test upgrades
Browse files Browse the repository at this point in the history
  • Loading branch information
cosmic-vagabond committed Feb 8, 2024
1 parent 03df871 commit b4a1579
Show file tree
Hide file tree
Showing 35 changed files with 1,748 additions and 0 deletions.
28 changes: 28 additions & 0 deletions scripts/upgrade-assure/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# How to use a testnet snapshot in localnet?

```
make install
go run ./scripts/upgrade-assure/... https://snapshots.polkachu.com/testnet-snapshots/elys/elys_5724942.tar.lz4 ~/go/bin/elysd ~/go/bin/elysd --skip-proposal
```

# How can I perform a test with a version upgrade that involves extensive changes to data structures?

```
git checkout v0.28.1
make install
cp -a ~/go/bin/elysd /tmp/elysd-v0.28.1
```

```
go run ./scripts/upgrade-assure/... --home /tmp/elys https://snapshots.polkachu.com/testnet-snapshots/elys/elys_5511381.tar.lz4 /tmp/elysd-v0.28.1 /tmp/elysd-v0.29.0 --skip-node-start
```

```
git checkout v0.29.0
make install
cp -a ~/go/bin/elysd /tmp/elysd-v0.29.0
```

```
go run ./scripts/upgrade-assure/... --home /tmp/elys https://snapshots.polkachu.com/testnet-snapshots/elys/elys_5511381.tar.lz4 /tmp/elysd-v0.28.1 /tmp/elysd-v0.29.0 --skip-snapshot --skip-chain-init
```
38 changes: 38 additions & 0 deletions scripts/upgrade-assure/account-unmarshal-json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package main

import (
"encoding/json"
"fmt"
)

func (a *Account) UnmarshalJSON(data []byte) error {
var raw map[string]interface{}
if err := json.Unmarshal(data, &raw); err != nil {
return err
}

// Set the Type field from the raw data
typeStr, ok := raw["@type"].(string)
if !ok {
return fmt.Errorf("type field is missing or invalid")
}
a.Type = typeStr

switch a.Type {
case "/cosmos.auth.v1beta1.BaseAccount":
var ba BaseAccount
if err := json.Unmarshal(data, &ba); err != nil {
return err
}
a.BaseAccount = &ba
case "/cosmos.auth.v1beta1.ModuleAccount":
var ma ModuleAccount
if err := json.Unmarshal(data, &ma); err != nil {
return err
}
a.ModuleAccount = &ma
default:
return fmt.Errorf("unknown account type: %s", a.Type)
}
return nil
}
19 changes: 19 additions & 0 deletions scripts/upgrade-assure/add-genesis-account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

import (
"log"
"os/exec"
)

func addGenesisAccount(cmdPath, address, balance, homePath string) {
// Command and arguments
args := []string{"add-genesis-account", address, balance + "uelys", "--home", homePath}

// Execute the command
if err := exec.Command(cmdPath, args...).Run(); err != nil {
log.Fatalf(Red+"Command execution failed: %v", err) // nolint: goconst
}

// If execution reaches here, the command was successful
log.Printf(Yellow+"add genesis account with address %s, balance: %s and home path %s successfully", address, balance, homePath)
}
29 changes: 29 additions & 0 deletions scripts/upgrade-assure/add-key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package main

import (
"encoding/json"
"log"
"os/exec"
)

func addKey(cmdPath, name, homePath, keyringBackend string) string {
// Command and arguments
args := []string{"keys", "add", name, "--home", homePath, "--keyring-backend", keyringBackend, "--output", "json"}

// Execute the command
output, err := exec.Command(cmdPath, args...).CombinedOutput()
if err != nil {
log.Fatalf(Red+"Command execution failed: %v", err)
}

// Unmarshal the JSON output
var keyOutput KeyOutput
if err := json.Unmarshal(output, &keyOutput); err != nil {
log.Fatalf(Red+"Failed to unmarshal JSON output: %v", err)
}

// Log the address
log.Printf(Yellow+"add key with name %s, home path: %s, keyring backend %s and address %s successfully", name, homePath, keyringBackend, keyOutput.Address)

return keyOutput.Address
}
19 changes: 19 additions & 0 deletions scripts/upgrade-assure/collect-gentxs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

import (
"log"
"os/exec"
)

func collectGentxs(cmdPath, homePath string) {
// Command and arguments
args := []string{"collect-gentxs", "--home", homePath}

// Execute the command
if err := exec.Command(cmdPath, args...).Run(); err != nil {
log.Fatalf(Red+"Command execution failed: %v", err)
}

// If execution reaches here, the command was successful
log.Printf(Yellow+"collect gen txs with home path %s successfully", homePath)
}
109 changes: 109 additions & 0 deletions scripts/upgrade-assure/download-and-run-version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// nolint: nakedret
package main

import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"os/exec"
"regexp"
"strings"
)

func isURL(str string) bool {
return strings.HasPrefix(str, "http://") || strings.HasPrefix(str, "https://")
}

func downloadAndRunVersion(binaryPathOrURL string, skipDownload bool) (path string, version string, err error) {
if !isURL(binaryPathOrURL) {
// If the input is a local path
path = binaryPathOrURL

// Check if the path exists
if _, err = os.Stat(path); os.IsNotExist(err) {
err = errors.New(fmt.Sprintf("binary file does not exist at the specified path: %v", path))
return
}

// Run the command 'binary version'
cmd := exec.Command(path, "version")
var versionOutput []byte
versionOutput, err = cmd.CombinedOutput()
if err != nil {
return
}
version = strings.TrimSpace(string(versionOutput))

return
}

if skipDownload {
// Extract version from the URL
re := regexp.MustCompile(`v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?`)
versionMatches := re.FindStringSubmatch(binaryPathOrURL)
if len(versionMatches) == 0 {
err = errors.New("no version found in URL")
return
}
version = versionMatches[0]

// Set the binary path based on the version
path = "/tmp/elysd-" + version

// Check if the path exists
if _, err = os.Stat(path); os.IsNotExist(err) {
err = errors.New(fmt.Sprintf("binary file does not exist at the specified path: %v", path))
}

return
}

// Download the binary
resp, err := http.Get(binaryPathOrURL) // nolint: gosec
if err != nil {
return
}
defer resp.Body.Close()

// Create a temporary file
tmpFile, err := ioutil.TempFile("", "binary-*")
if err != nil {
return
}
tmpFilePath := tmpFile.Name()
defer os.Remove(tmpFilePath) // Clean up

// Write the downloaded content to the file
_, err = io.Copy(tmpFile, resp.Body)
tmpFile.Close()
if err != nil {
return
}

// Make the file executable
err = os.Chmod(tmpFilePath, 0755)
if err != nil {
return
}

// Run the command 'binary version'
cmd := exec.Command(tmpFilePath, "version")
versionOutput, err := cmd.CombinedOutput()
if err != nil {
return
}
version = strings.TrimSpace(string(versionOutput))

// Rename the temporary file
newFilePath := "/tmp/elysd-" + version
err = os.Rename(tmpFilePath, newFilePath)
if err != nil {
return
}
path = newFilePath

return
}
18 changes: 18 additions & 0 deletions scripts/upgrade-assure/export.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import (
"log"
"os/exec"
)

func export(cmdPath, homePath, genesisFilePath string) {
// Command and arguments
args := []string{"export", "--home", homePath, "--output-document", genesisFilePath, "--modules-to-export", "amm,assetprofile,auth,authz,bank,burner,capability,clock,commitment,consensus,crisis,epochs,evidence,feegrant,genutil,group,ibc,incentive,interchainaccounts,leveragelp,perpetual,mint,oracle,parameter,params,poolaccounted,stablestake,staking,tokenomics,transfer,transferhook,upgrade,vesting"}

// Execute the command and capture the output
if err := exec.Command(cmdPath, args...).Run(); err != nil {
log.Fatalf(Red+"Command execution failed: %v", err)
}

log.Printf(Yellow+"Output successfully written to %s", genesisFilePath)
}
17 changes: 17 additions & 0 deletions scripts/upgrade-assure/filter-accounts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

func filterAccounts(accounts []Account, filterAddresses []string) []Account {
filterMap := make(map[string]struct{})
for _, addr := range filterAddresses {
filterMap[addr] = struct{}{}
}

newAccounts := []Account{}
for _, account := range accounts {
if shouldFilterAccount(account, filterMap) {
continue
}
newAccounts = append(newAccounts, account)
}
return newAccounts
}
24 changes: 24 additions & 0 deletions scripts/upgrade-assure/filter-balances.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
)

func filterBalances(balances []banktypes.Balance, filterAddresses []string) ([]banktypes.Balance, sdk.Coins) {
filterMap := make(map[string]struct{})
for _, addr := range filterAddresses {
filterMap[addr] = struct{}{}
}

newBalances := []banktypes.Balance{}
var coinsToRemove sdk.Coins
for _, balance := range balances {
if _, exists := filterMap[balance.Address]; exists {
coinsToRemove = coinsToRemove.Add(balance.Coins...)
continue
}
newBalances = append(newBalances, balance)
}
return newBalances, coinsToRemove
}
19 changes: 19 additions & 0 deletions scripts/upgrade-assure/gen-tx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

import (
"log"
"os/exec"
)

func genTx(cmdPath, name, amount, chainId, homePath, keyringBackend string) {
// Command and arguments
args := []string{"gentx", name, amount + "uelys", "--chain-id", chainId, "--home", homePath, "--keyring-backend", keyringBackend}

// Execute the command
if err := exec.Command(cmdPath, args...).Run(); err != nil {
log.Fatalf(Red+"Command execution failed: %v", err)
}

// If execution reaches here, the command was successful
log.Printf(Yellow+"gen tx with name %s, amount: %s, chain id %s, home path %s and keyring backend %s successfully", name, amount, chainId, homePath, keyringBackend)
}
24 changes: 24 additions & 0 deletions scripts/upgrade-assure/get-args.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
"log"
)

func getArgs(args []string) (snapshotUrl, oldBinaryUrl, newBinaryUrl string) {
snapshotUrl = args[0] // https://snapshots.polkachu.com/testnet-snapshots/elys/elys_4392223.tar.lz4
if snapshotUrl == "" {
log.Fatalf(Red + "snapshot url is required")
}

oldBinaryUrl = args[1] // https://github.com/elys-network/elys/releases/download/v0.19.0/elysd-v0.19.0-darwin-arm64
if oldBinaryUrl == "" {
log.Fatalf(Red + "old binary url is required")
}

newBinaryUrl = args[2] // https://github.com/elys-network/elys/releases/download/v0.20.0/elysd-v0.20.0-darwin-arm64
if newBinaryUrl == "" {
log.Fatalf(Red + "new binary url is required")
}

return
}
Loading

0 comments on commit b4a1579

Please sign in to comment.