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: introduce cli commands for the upgrade module #2910

Merged
merged 12 commits into from
Dec 8, 2023
2 changes: 1 addition & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ func New(
)

app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
app.UpgradeKeeper = upgrade.NewKeeper(keys[upgradetypes.StoreKey], upgradeHeight, app.StakingKeeper)
app.UpgradeKeeper = upgrade.NewKeeper(keys[upgradetypes.StoreKey], upgradeHeight, stakingKeeper)

app.BlobstreamKeeper = *bsmodulekeeper.NewKeeper(
appCodec,
Expand Down
4 changes: 4 additions & 0 deletions test/util/test_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
tmtypes "github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tm-db"

Expand Down Expand Up @@ -106,6 +107,9 @@ func SetupTestAppWithGenesisValSet(cparams *tmproto.ConsensusParams, genAccounts
AppHash: testApp.LastCommitID().Hash,
ValidatorsHash: valSet.Hash(),
NextValidatorsHash: valSet.Hash(),
Version: tmversion.Consensus{
App: cparams.Version.AppVersion,
},
}})

return testApp, kr
Expand Down
40 changes: 40 additions & 0 deletions x/upgrade/cli/cli_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package cli_test

import (
"testing"

"github.com/celestiaorg/celestia-app/test/util/testnode"
"github.com/celestiaorg/celestia-app/x/upgrade/cli"
testutil "github.com/cosmos/cosmos-sdk/testutil/cli"
"github.com/stretchr/testify/suite"
)

func TestCLITestSuite(t *testing.T) {
if testing.Short() {
t.Skip("skipping upgrade CLI test in short mode")
}
suite.Run(t, new(CLITestSuite))
}

type CLITestSuite struct {
suite.Suite

ctx testnode.Context
}

func (s *CLITestSuite) SetupSuite() {
s.T().Log("setting up integration test suite")
ctx, _, _ := testnode.NewNetwork(s.T(), testnode.DefaultConfig())
s.ctx = ctx
_, err := s.ctx.WaitForHeight(1)
s.Require().NoError(err)
}

func (s *CLITestSuite) TestCmdQueryTally() {
cmd := cli.CmdQueryTally()
output, err := testutil.ExecTestCLICmd(s.ctx.Context, cmd, []string{"1"})
s.Require().NoError(err)
s.Require().Contains(output.String(), "voting_power")
s.Require().Contains(output.String(), "threshold_power")
s.Require().Contains(output.String(), "total_voting_power")
}
58 changes: 58 additions & 0 deletions x/upgrade/cli/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package cli

import (
"fmt"
"strconv"

"github.com/celestiaorg/celestia-app/x/upgrade/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/spf13/cobra"
)

// GetQueryCmd returns the CLI query commands for this module
func GetQueryCmd() *cobra.Command {
// Group blob queries under a subcommand
cmwaters marked this conversation as resolved.
Show resolved Hide resolved
cmd := &cobra.Command{
Use: types.ModuleName,
Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName),
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}

cmd.AddCommand(CmdQueryTally())

return cmd
}

func CmdQueryTally() *cobra.Command {
cmd := &cobra.Command{
Use: "tally [version]",
cmwaters marked this conversation as resolved.
Show resolved Hide resolved
Short: "Query the tally of signal votes for a given version",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}

version, err := strconv.ParseUint(args[0], 10, 64)
if err != nil {
return err
}

upgradeQueryClient := types.NewQueryClient(clientCtx)

resp, err := upgradeQueryClient.VersionTally(cmd.Context(), &types.QueryVersionTallyRequest{Version: version})
if err != nil {
return err
}

return clientCtx.PrintProto(resp)
},
}

flags.AddQueryFlagsToCmd(cmd)
return cmd
}
88 changes: 88 additions & 0 deletions x/upgrade/cli/tx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package cli

import (
"fmt"
"strconv"

"github.com/celestiaorg/celestia-app/x/upgrade/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/cobra"
)

// GetTxCmd returns the transaction commands for this module
func GetTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: types.ModuleName,
Short: fmt.Sprintf("%s transactions subcommands", types.ModuleName),
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}

cmd.AddCommand(CmdSignalVersion())
cmd.AddCommand(CmdTryUpgrade())

return cmd
}

func CmdSignalVersion() *cobra.Command {
cmd := &cobra.Command{
Use: "signal [version]",
cmwaters marked this conversation as resolved.
Show resolved Hide resolved
Short: "Signal a software upgrade for the specified version",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

version, err := strconv.ParseUint(args[0], 10, 64)
if err != nil {
return err
}

addr := clientCtx.GetFromAddress().Bytes()
valAddr := sdk.ValAddress(addr)

msg := types.NewMsgSignalVersion(valAddr, version)
if err := msg.ValidateBasic(); err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)
return cmd
}

func CmdTryUpgrade() *cobra.Command {
cmd := &cobra.Command{
Use: "try-upgrade",
Short: "Try to perform a software upgrade",
Long: `This command will submit a TryUpgrade message to tally all
the signal votes. If a quorum has been reached, the network will upgrade
staheri14 marked this conversation as resolved.
Show resolved Hide resolved
to the signalled version at the following height.
`,
Comment on lines +63 to +70
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CmdTryUpgrade command's description provides information on the tallying of votes and the upgrade process. It would be beneficial to include additional details or output examples in the help text or documentation to guide users on what to expect after executing this command, especially regarding how they can confirm that an upgrade is in progress or will occur.

RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

msg := types.NewMsgTryUpgrade(clientCtx.GetFromAddress())
if err := msg.ValidateBasic(); err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)
return cmd
}
57 changes: 57 additions & 0 deletions x/upgrade/integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package upgrade_test

import (
"testing"

"github.com/celestiaorg/celestia-app/app"
testutil "github.com/celestiaorg/celestia-app/test/util"
"github.com/celestiaorg/celestia-app/x/upgrade/types"
"github.com/stretchr/testify/require"

sdk "github.com/cosmos/cosmos-sdk/types"
tmlog "github.com/tendermint/tendermint/libs/log"
tmtypes "github.com/tendermint/tendermint/proto/tendermint/types"
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
)

func TestUpgradeIntegration(t *testing.T) {
staheri14 marked this conversation as resolved.
Show resolved Hide resolved
app, _ := testutil.SetupTestAppWithGenesisValSet(app.DefaultConsensusParams())
ctx := sdk.NewContext(app.CommitMultiStore(), tmtypes.Header{
Version: tmversion.Consensus{
App: 1,
},
}, false, tmlog.NewNopLogger())
goCtx := sdk.WrapSDKContext(ctx)
ctx = sdk.UnwrapSDKContext(goCtx)

res, err := app.UpgradeKeeper.VersionTally(goCtx, &types.QueryVersionTallyRequest{
Version: 2,
})
require.NoError(t, err)
require.EqualValues(t, 0, res.VotingPower)

validators := app.StakingKeeper.GetAllValidators(ctx)
valAddr, err := sdk.ValAddressFromBech32(validators[0].OperatorAddress)
require.NoError(t, err)

_, err = app.UpgradeKeeper.SignalVersion(ctx, &types.MsgSignalVersion{
ValidatorAddress: valAddr.String(),
Version: 2,
})
require.NoError(t, err)

res, err = app.UpgradeKeeper.VersionTally(goCtx, &types.QueryVersionTallyRequest{
Version: 2,
})
require.NoError(t, err)
require.EqualValues(t, 1, res.VotingPower)
require.EqualValues(t, 0, res.ThresholdPower)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[optional] this threshold power seems weird b/c it makes me think that no votes are needed to trigger an upgrade.
Is it possible for this test case to have a non-zero threshold power potentially by adding another validator with some voting power?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So currently as it stands, there has to be strictly greater than the threshold power for the upgrade to occur. If we think it is better to present threshold as "greater or equal to" then I can increment this buy 1. Whatever we feel is more intuitive for users

require.EqualValues(t, 1, res.TotalVotingPower)

_, err = app.UpgradeKeeper.TryUpgrade(ctx, nil)
require.NoError(t, err)

shouldUpgrade, version := app.UpgradeKeeper.ShouldUpgrade()
require.True(t, shouldUpgrade)
require.EqualValues(t, 2, version)
}
1 change: 0 additions & 1 deletion x/upgrade/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ func (k Keeper) VersionTally(ctx context.Context, req *types.QueryVersionTallyRe
currentVotingPower = currentVotingPower.AddRaw(power)
}
}

threshold := k.GetVotingPowerThreshold(sdkCtx)
return &types.QueryVersionTallyResponse{
VotingPower: currentVotingPower.Uint64(),
Expand Down
2 changes: 1 addition & 1 deletion x/upgrade/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import (
"github.com/spf13/cobra"
abci "github.com/tendermint/tendermint/abci/types"

"github.com/celestiaorg/celestia-app/x/upgrade/cli"
"github.com/celestiaorg/celestia-app/x/upgrade/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/upgrade/client/cli"
)

func init() {
Expand Down
12 changes: 12 additions & 0 deletions x/upgrade/tally_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,18 @@ func TestTallyingLogic(t *testing.T) {
require.EqualValues(t, 119, res.TotalVotingPower)
}

func TestEmptyStore(t *testing.T) {
upgradeKeeper, ctx, _ := setup(t)
goCtx := sdk.WrapSDKContext(ctx)

res, err := upgradeKeeper.VersionTally(goCtx, &types.QueryVersionTallyRequest{
Version: 2,
})
require.NoError(t, err)
require.EqualValues(t, 0, res.VotingPower)
require.EqualValues(t, 120, res.TotalVotingPower)
staheri14 marked this conversation as resolved.
Show resolved Hide resolved
}

func setup(t *testing.T) (upgrade.Keeper, sdk.Context, *mockStakingKeeper) {
upgradeStore := sdk.NewKVStoreKey(types.StoreKey)
db := tmdb.NewMemDB()
Expand Down
Loading