Skip to content

Commit

Permalink
imp(cli): Add flags to CLI commands to enable more configuration (#38)
Browse files Browse the repository at this point in the history
* adjust to make tool more configurable

* add changelog entry

* separately deposit for upgrade

* wait for number of blocks instead of seconds and check successful votes

* address linters
  • Loading branch information
MalteHerrmann authored May 7, 2024
1 parent 58117f0 commit 9d44d35
Show file tree
Hide file tree
Showing 13 changed files with 256 additions and 152 deletions.
25 changes: 6 additions & 19 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,21 @@ linters:
disable:
# unwanted linters
- depguard # would have loved to add but doesn't seem to work correctly
- err113
- exhaustruct
- gomoddirectives
- goerr113
- gochecknoglobals
- gochecknoinits
- gomnd
# discontinued linters
- deadcode
- exhaustivestruct
- golint
- ifshort
- interfacer
- nosnakecase
- maligned
- scopelint
- structcheck
- varcheck
- gomoddirectives
- mnd

linters-settings:
dogsled:
max-blank-identifiers: 3
gofumpt:
lang-version: "1.21"
maligned:
suggest-new: true
max-blank-identifiers: 1
misspell:
locale: US
nolintlint:
allow-unused: false
allow-leading-space: true
require-explanation: true
require-specific: true
varnamelen:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

- [#32](https://github.com/MalteHerrmann/evmos-utils/pull/32) Minor refactor in CLI commands
- [#35](https://github.com/MalteHerrman/evmos-utils/pull/35) Update to Evmos v17.
- [#38](https://github.com/MalteHerrmann/evmos-utils/pull/38) Add flags to CLI commands to enable more configuration.

## [v0.4.0](https://github.com/MalteHerrmann/evmos-utils/releases/tag/v0.4.0) - 2023-12-18

Expand Down
2 changes: 1 addition & 1 deletion cmd/deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var depositCmd = &cobra.Command{
If no proposal ID is given by the user, the latest proposal is queried and deposited for.`,
Args: cobra.RangeArgs(0, 1),
Run: func(_ *cobra.Command, args []string) {
bin, err := utils.NewEvmosTestingBinary()
bin, err := utils.NewBinary(collectConfig())
if err != nil {
bin.Logger.Error().Msgf("error creating binary: %v", err)

Expand Down
85 changes: 76 additions & 9 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,93 @@ package cmd
import (
"os"

"github.com/MalteHerrmann/evmos-utils/utils"
evmosutils "github.com/evmos/evmos/v17/utils"
"github.com/spf13/cobra"
)

// rootCmd represents the base command when called without any subcommands.
//
//nolint:gochecknoglobals // required by cobra
var rootCmd = &cobra.Command{
Use: "evmos-utils",
Short: "A collection of utilities to interact with an Evmos node during development.",
Long: `The evmos-utils collection offers helpers to interact with an Evmos node during development.
var (
// rootCmd represents the base command when called without any subcommands.
//
//nolint:gochecknoglobals // required by cobra
rootCmd = &cobra.Command{
Use: "evmos-utils",
Short: "A collection of utilities to interact with an Evmos node during development.",
Long: `The evmos-utils collection offers helpers to interact with an Evmos node during development.
It can be used to test upgrades, deposit or vote for specific or the latest proposals, etc.`,
}
}

// appd is the name of the binary to execute commands with.
appd string
// chainID is the chain ID of the network.
chainID string
// denom of the chain's fee token.
denom string
// home is the home directory of the binary.
home string
// keyringBackend is the keyring to use.
keyringBackend string
// node to post requests and transactions to.
node string
)

//nolint:gochecknoinits // required by cobra
func init() {
rootCmd.AddCommand(depositCmd)
rootCmd.PersistentFlags().StringVar(
&appd,
"bin",
"evmosd",
"Name of the binary to be executed",
)
rootCmd.PersistentFlags().StringVar(
&chainID,
"chain-id",
evmosutils.TestnetChainID+"-1",
"Chain ID of the network",
)
rootCmd.PersistentFlags().StringVar(
&denom,
"denom",
"aevmos",
"Fee token denomination of the network",
)
rootCmd.PersistentFlags().StringVar(
&home,
"home",
".tmp-evmosd",
"Home directory of the binary",
)
rootCmd.PersistentFlags().StringVar(
&keyringBackend,
"keyring-backend",
"test",
"Keyring to use",
)
rootCmd.PersistentFlags().StringVar(
&node,
"node",
"http://localhost:26657",
"Node to post queries and transactions to",
)

rootCmd.AddCommand(upgradeCmd)
rootCmd.AddCommand(depositCmd)
rootCmd.AddCommand(voteCmd)
}

// collectConfig returns a BinaryConfig filled with the current configuration options
// that depend on the passed flags to the given CLI commands.
func collectConfig() utils.BinaryConfig {
return utils.BinaryConfig{
Appd: appd,
ChainID: chainID,
Denom: denom,
Home: home,
KeyringBackend: keyringBackend,
Node: node,
}
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
Expand Down
25 changes: 13 additions & 12 deletions cmd/upgrade.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"fmt"
"regexp"

"github.com/MalteHerrmann/evmos-utils/gov"
Expand All @@ -16,28 +17,24 @@ var upgradeCmd = &cobra.Command{
Long: `Prepare an upgrade of a node by submitting a governance proposal,
voting for it using all keys of in the keyring and having it pass.`,
Args: cobra.ExactArgs(1),
Run: func(_ *cobra.Command, args []string) {
bin, err := utils.NewEvmosTestingBinary()
RunE: func(_ *cobra.Command, args []string) error {
bin, err := utils.NewBinary(collectConfig())
if err != nil {
bin.Logger.Error().Msgf("error creating binary: %v", err)

return
return errors.Wrap(err, "error creating binary")
}

targetVersion := args[0]
if matched, _ := regexp.MatchString(`v\d+\.\d+\.\d(-rc\d+)?`, targetVersion); !matched {
bin.Logger.Error().Msgf("invalid target version: %s; please use the format vX.Y.Z(-rc*).", targetVersion)

return
return fmt.Errorf("invalid target version: %s; please use the format vX.Y.Z(-rc*)", targetVersion)
}

if err := upgradeLocalNode(bin, targetVersion); err != nil {
bin.Logger.Error().Msgf("error upgrading local node: %v", err)

return
if err = upgradeLocalNode(bin, targetVersion); err != nil {
return errors.Wrap(err, "error upgrading local node")
}

bin.Logger.Info().Msgf("successfully prepared upgrade to %s", targetVersion)

return nil
},
}

Expand All @@ -60,6 +57,10 @@ func upgradeLocalNode(bin *utils.Binary, targetVersion string) error {

bin.Logger.Info().Msgf("scheduled upgrade to %s at height %d.\n", targetVersion, upgradeHeight)

if _, err = gov.Deposit(bin, []string{}); err != nil {
return errors.Wrapf(err, "error depositing for proposal %d", proposalID)
}

if err = gov.SubmitAllVotesForProposal(bin, proposalID); err != nil {
return errors.Wrapf(err, "error submitting votes for proposal %d", proposalID)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var voteCmd = &cobra.Command{
If no proposal ID is passed, the latest proposal on chain is queried and used.`,
Args: cobra.RangeArgs(0, 1),
Run: func(_ *cobra.Command, args []string) {
bin, err := utils.NewEvmosTestingBinary()
bin, err := utils.NewBinary(collectConfig())
if err != nil {
bin.Logger.Error().Msgf("error creating binary: %v", err)

Expand Down
9 changes: 4 additions & 5 deletions gov/deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,12 @@ func Deposit(bin *utils.Binary, args []string) (int, error) {
// DepositForProposal deposits the given amount for the proposal with the given proposalID
// from the given account.
func DepositForProposal(bin *utils.Binary, proposalID int, sender, deposit string) error {
_, err := utils.ExecuteBinaryCmd(bin, utils.BinaryCmdArgs{
_, err := utils.ExecuteTx(bin, utils.TxArgs{
Subcommand: []string{
"tx", "gov", "deposit", strconv.Itoa(proposalID), deposit,
},
From: sender,
UseDefaults: true,
Quiet: true,
From: sender,
Quiet: true,
})
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to deposit for proposal %d", proposalID))
Expand All @@ -48,7 +47,7 @@ func DepositForProposal(bin *utils.Binary, proposalID int, sender, deposit strin
// GetMinDeposit returns the minimum deposit necessary for a proposal from the governance parameters of
// the running chain.
func GetMinDeposit(bin *utils.Binary) (sdk.Coins, error) {
out, err := utils.ExecuteBinaryCmd(bin, utils.BinaryCmdArgs{
out, err := utils.ExecuteQuery(bin, utils.QueryArgs{
Subcommand: []string{"q", "gov", "param", "deposit", "--output=json"},
Quiet: true,
})
Expand Down
10 changes: 4 additions & 6 deletions gov/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ func buildUpgradeProposalCommand(targetVersion string, upgradeHeight int) []stri
"--title", fmt.Sprintf("'Upgrade to %s'", targetVersion),
"--description", fmt.Sprintf("'Upgrade to %s'", targetVersion),
"--upgrade-height", strconv.Itoa(upgradeHeight),
"--deposit", "100000000000000000000aevmos",
"--output", "json",
"--no-validate",
}
Expand Down Expand Up @@ -49,7 +48,7 @@ func GetProposalIDFromSubmitEvents(events []sdk.StringEvent) (int, error) {

// QueryLatestProposalID queries the latest proposal ID.
func QueryLatestProposalID(bin *utils.Binary) (int, error) {
out, err := utils.ExecuteBinaryCmd(bin, utils.BinaryCmdArgs{
out, err := utils.ExecuteQuery(bin, utils.QueryArgs{
Subcommand: []string{"q", "gov", "proposals", "--output=json"},
Quiet: true,
})
Expand Down Expand Up @@ -81,10 +80,9 @@ func QueryLatestProposalID(bin *utils.Binary) (int, error) {
func SubmitUpgradeProposal(bin *utils.Binary, targetVersion string, upgradeHeight int) (int, error) {
upgradeProposal := buildUpgradeProposalCommand(targetVersion, upgradeHeight)

out, err := utils.ExecuteBinaryCmd(bin, utils.BinaryCmdArgs{
Subcommand: upgradeProposal,
From: "dev0",
UseDefaults: true,
out, err := utils.ExecuteTx(bin, utils.TxArgs{
Subcommand: upgradeProposal,
From: bin.Accounts[0].Name,
})
if err != nil {
return 0, errors.Wrap(err,
Expand Down
25 changes: 18 additions & 7 deletions gov/vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,16 @@ func SubmitAllVotesForProposal(bin *utils.Binary, proposalID int) error {
return errors.New("no accounts with delegations found")
}

utils.Wait(1)
if err := utils.WaitNBlocks(bin, 1); err != nil {
return errors.Wrapf(err, "error waiting for blocks")
}

bin.Logger.Info().Msgf("voting for proposal %d", proposalID)

var out string
var (
out string
successfulVotes int
)

for _, acc := range accsWithDelegations {
out, err = VoteForProposal(bin, proposalID, acc.Name)
Expand All @@ -49,19 +55,24 @@ func SubmitAllVotesForProposal(bin *utils.Binary, proposalID int) error {
bin.Logger.Error().Msgf("could not vote using key %s: %v", acc.Name, err)
} else {
bin.Logger.Info().Msgf("voted using key %s", acc.Name)

successfulVotes++
}
}

if successfulVotes == 0 {
return errors.New("there were no successful votes for the proposal, please check logs")
}

return nil
}

// VoteForProposal votes for the proposal with the given ID using the given account.
func VoteForProposal(bin *utils.Binary, proposalID int, sender string) (string, error) {
out, err := utils.ExecuteBinaryCmd(bin, utils.BinaryCmdArgs{
Subcommand: []string{"tx", "gov", "vote", strconv.Itoa(proposalID), "yes"},
From: sender,
UseDefaults: true,
Quiet: true,
out, err := utils.ExecuteTx(bin, utils.TxArgs{
Subcommand: []string{"tx", "gov", "vote", strconv.Itoa(proposalID), "yes"},
From: sender,
Quiet: true,
})
if err != nil {
return out, errors.Wrap(err, fmt.Sprintf("failed to vote for proposal %d", proposalID))
Expand Down
Loading

0 comments on commit 9d44d35

Please sign in to comment.