Skip to content

Commit

Permalink
adjust to make tool more configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
MalteHerrmann committed Apr 24, 2024
1 parent 58117f0 commit 5de0e03
Show file tree
Hide file tree
Showing 12 changed files with 211 additions and 130 deletions.
2 changes: 2 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ linters:
# discontinued linters
- deadcode
- exhaustivestruct
- gochecknoglobals
- gochecknoinits
- golint
- ifshort
- interfacer
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
21 changes: 9 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 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
15 changes: 7 additions & 8 deletions gov/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import (
)

// buildUpgradeProposalCommand builds the command to submit a software upgrade proposal.
func buildUpgradeProposalCommand(targetVersion string, upgradeHeight int) []string {
func buildUpgradeProposalCommand(targetVersion string, upgradeHeight int, denom string) []string {
return []string{
"tx", "gov", "submit-legacy-proposal", "software-upgrade", targetVersion,
"--title", fmt.Sprintf("'Upgrade to %s'", targetVersion),
"--description", fmt.Sprintf("'Upgrade to %s'", targetVersion),
"--upgrade-height", strconv.Itoa(upgradeHeight),
"--deposit", "100000000000000000000aevmos",
"--deposit", "100000000000000000000" + denom,
"--output", "json",
"--no-validate",
}
Expand Down Expand Up @@ -49,7 +49,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 @@ -79,12 +79,11 @@ func QueryLatestProposalID(bin *utils.Binary) (int, error) {

// SubmitUpgradeProposal submits a software upgrade proposal with the given target version and upgrade height.
func SubmitUpgradeProposal(bin *utils.Binary, targetVersion string, upgradeHeight int) (int, error) {
upgradeProposal := buildUpgradeProposalCommand(targetVersion, upgradeHeight)
upgradeProposal := buildUpgradeProposalCommand(targetVersion, upgradeHeight, bin.Config.Denom)

out, err := utils.ExecuteBinaryCmd(bin, utils.BinaryCmdArgs{
Subcommand: upgradeProposal,
From: "dev0",
UseDefaults: true,
out, err := utils.ExecuteTx(bin, utils.TxArgs{
Subcommand: upgradeProposal,
From: "dev0",
})
if err != nil {
return 0, errors.Wrap(err,
Expand Down
9 changes: 4 additions & 5 deletions gov/vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,10 @@ func SubmitAllVotesForProposal(bin *utils.Binary, proposalID int) error {

// 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
87 changes: 50 additions & 37 deletions utils/binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import (
"fmt"
"os"
"os/exec"
"path"
"path/filepath"
"strings"

"github.com/cosmos/cosmos-sdk/codec"
"github.com/evmos/evmos/v17/app"
Expand All @@ -17,66 +18,78 @@ import (
// Binary is a struct to hold the necessary information to execute commands
// using a Cosmos SDK-based binary.
type Binary struct {
// Cdc is the codec to be used for the client.
Cdc *codec.ProtoCodec
// Home is the home directory of the binary.
Home string
// Appd is the name of the binary to be executed, e.g. "evmosd".
Appd string
// Accounts are the accounts stored in the local keyring.
Accounts []Account
// Cdc is the codec to be used for the client.
Cdc *codec.ProtoCodec

// Config is the configuration of the binary
Config BinaryConfig

// Logger is a logger to be used within all commands.
Logger zerolog.Logger
}

// BinaryConfig holds the configuration of the binary.
type BinaryConfig struct {
// Appd is the name of the binary to be executed, e.g. "evmosd".
Appd string
// ChainID is the chain ID of the network.
ChainID string
// Denom for the fee payments on transactions
Denom string
// Home is the home directory of the binary.
Home string
// KeyringBackend defines which keyring to use
KeyringBackend string
// Node is the endpoint for gRPC connections
Node string
}

// NewBinary returns a new Binary instance.
func NewBinary(home, appd string, logger zerolog.Logger) (*Binary, error) {
// check if home directory exists
if _, err := os.Stat(home); os.IsNotExist(err) {
return nil, errors.Wrap(err, "home directory does not exist: "+home)
func NewBinary(config BinaryConfig) (*Binary, error) {
userHome, err := os.UserHomeDir()
if err != nil {
return nil, errors.Wrap(err, "failed to get user home dir")
}

// strip the home directory from the given home if already included
var homeDir string
if strings.Contains(config.Home, userHome) {
homeDir = config.Home
} else {
homeDir = filepath.Join(userHome, config.Home)
}

if _, err = os.Stat(homeDir); os.IsNotExist(err) {
return nil, errors.Wrap(err, "home directory does not exist: "+homeDir)
}

config.Home = homeDir

// check if binary is installed
_, err := exec.LookPath(appd)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("binary %q not installed", appd))
if _, err = exec.LookPath(config.Appd); err != nil {
return nil, fmt.Errorf("binary %q not installed", config.Appd)
}

cdc, ok := GetCodec()
if !ok {
return nil, errors.Wrap(err, "failed to get codec")
}

return &Binary{
Cdc: cdc,
Home: home,
Appd: appd,
Logger: logger,
}, nil
}

// NewEvmosTestingBinary returns a new Binary instance with the default home and appd
// setup for the Evmos local node testing setup.
func NewEvmosTestingBinary() (*Binary, error) {
logger := log.Output(zerolog.ConsoleWriter{Out: os.Stdout})

userHome, err := os.UserHomeDir()
if err != nil {
return &Binary{Logger: logger}, errors.Wrap(err, "failed to get user home dir")
}

defaultEvmosdHome := path.Join(userHome, ".tmp-evmosd")

bin, err := NewBinary(defaultEvmosdHome, "evmosd", logger)
if err != nil {
return nil, err
binary := &Binary{
Cdc: cdc,
Config: config,
Logger: logger,
}

if err = bin.GetAccounts(); err != nil {
if err = binary.getAccounts(); err != nil {
return nil, err
}

return bin, nil
return binary, nil
}

// GetCodec returns the codec to be used for the client.
Expand Down
8 changes: 1 addition & 7 deletions utils/constants.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
package utils

import (
evmosutils "github.com/evmos/evmos/v17/utils"
)

const (
// defaultFees is the amount of fees to be sent with a default transaction.
defaultFees int = 1e18 // 1 aevmos
defaultFees int = 1e16 // 0.01 evmos
// DeltaHeight is the amount of blocks in the future that the upgrade will be scheduled.
DeltaHeight = 20
// denom is the denomination used for the local node.
denom = evmosutils.BaseDenom
)
Loading

0 comments on commit 5de0e03

Please sign in to comment.