Skip to content

Commit

Permalink
feat(app): better upgrade management (#1488)
Browse files Browse the repository at this point in the history
* feat: upgrades

* fix: remove ineffassign

* chore: rename apptesting -> testutil

* chore: move ante handler in to app.go

* chore: remove appconfig.go

* chore: move test_helpers.go to testutil package

* chore: rename test

* fix: consolidate files, avoid import cycle

* fix: fix test

* fix: better test fix

* fix: revert v3 state migration changes, fix in upgrade test

Co-authored-by: technicallyty <48813565+tytech3@users.noreply.github.com>
Co-authored-by: Ryan Christoffersen <12519942+ryanchristo@users.noreply.github.com>
  • Loading branch information
3 people authored Sep 19, 2022
1 parent cb2b624 commit ea2dd1b
Show file tree
Hide file tree
Showing 9 changed files with 270 additions and 117 deletions.
46 changes: 44 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package app

import (
"encoding/json"
"fmt"
"io"
"math/big"
"net/http"
"os"

"github.com/cosmos/cosmos-sdk/x/auth/ante"
distrclient "github.com/cosmos/cosmos-sdk/x/distribution/client"
govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
paramsclient "github.com/cosmos/cosmos-sdk/x/params/client"
Expand Down Expand Up @@ -103,6 +105,8 @@ import (
ibchost "github.com/cosmos/ibc-go/v5/modules/core/24-host"
ibckeeper "github.com/cosmos/ibc-go/v5/modules/core/keeper"

regenupgrades "github.com/regen-network/regen-ledger/v4/app/upgrades"
v5 "github.com/regen-network/regen-ledger/v4/app/upgrades/v5"
"github.com/regen-network/regen-ledger/x/data"
datamodule "github.com/regen-network/regen-ledger/x/data/module"
"github.com/regen-network/regen-ledger/x/ecocredit"
Expand Down Expand Up @@ -176,6 +180,8 @@ var (

return perms
}()

upgrades = []regenupgrades.Upgrade{v5.Upgrade}
)

func init() {
Expand Down Expand Up @@ -317,7 +323,6 @@ func NewRegenApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest
// set the governance module account as the authority for conducting upgrades
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp,
authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.registerUpgradeHandlers()

// register the staking hooks
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
Expand Down Expand Up @@ -530,6 +535,9 @@ func NewRegenApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest
app.ModuleManager.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino)
app.ModuleManager.RegisterInvariants(&app.CrisisKeeper)

app.setUpgradeStoreLoaders()
app.setUpgradeHandlers()

// create the simulation manager and define the order of the modules for deterministic simulations
//
// NOTE: this is not required apps that don't use the simulator for fuzz testing
Expand Down Expand Up @@ -566,7 +574,15 @@ func NewRegenApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest
app.SetBeginBlocker(app.BeginBlocker)
app.SetEndBlocker(app.EndBlocker)

anteHandler, err := app.setCustomAnteHandler(encodingConfig.TxConfig)
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
FeegrantKeeper: app.FeeGrantKeeper,
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
)
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -708,6 +724,32 @@ func (app *RegenApp) RegisterTendermintService(clientCtx client.Context) {
)
}

func (app *RegenApp) setUpgradeStoreLoaders() {
upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk()
if err != nil {
panic(fmt.Sprintf("failed to read upgrade info from disk %s", err))
}

if app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
return
}

for _, u := range upgrades {
if upgradeInfo.Name == u.UpgradeName {
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &u.StoreUpgrades))
}
}
}

func (app *RegenApp) setUpgradeHandlers() {
for _, u := range upgrades {
app.UpgradeKeeper.SetUpgradeHandler(
u.UpgradeName,
u.CreateUpgradeHandler(app.ModuleManager, app.configurator),
)
}
}

// RegisterSwaggerAPI registers swagger route with API Server
func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router) {
statikFS, err := fs.New()
Expand Down
91 changes: 0 additions & 91 deletions app/appconfig.go

This file was deleted.

23 changes: 10 additions & 13 deletions app/app_test.go → app/testsuite/app_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package app
package testsuite

import (
"os"
Expand All @@ -8,36 +8,33 @@ import (
dbm "github.com/tendermint/tm-db"

"github.com/tendermint/tendermint/libs/log"

"github.com/regen-network/regen-ledger/v4/app"
)

func TestSimAppExportAndBlockedAddrs(t *testing.T) {
encCfg := MakeEncodingConfig()
encCfg := app.MakeEncodingConfig()
db := dbm.NewMemDB()
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
app := NewAppWithCustomOptions(t, false, SetupOptions{
regenApp := NewAppWithCustomOptions(t, false, SetupOptions{
Logger: logger,
DB: db,
InvCheckPeriod: 0,
EncConfig: encCfg,
HomePath: DefaultNodeHome,
HomePath: app.DefaultNodeHome,
SkipUpgradeHeights: map[int64]bool{},
AppOpts: EmptyAppOptions{},
})

for acc := range maccPerms {
require.Equal(t, true, app.BankKeeper.BlockedAddr(app.AccountKeeper.GetModuleAddress(acc)),
for acc := range app.GetMaccPerms() {
require.Equal(t, true, regenApp.BankKeeper.BlockedAddr(regenApp.AccountKeeper.GetModuleAddress(acc)),
"ensure that all module account addresses are properly blocked in bank keeper")
}

app.Commit()
regenApp.Commit()

// Making a new app object with the db, so that initchain hasn't been called
app2 := NewRegenApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{})
app2 := app.NewRegenApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, app.DefaultNodeHome, 0, encCfg, EmptyAppOptions{})
_, err := app2.ExportAppStateAndValidators(false, []string{})
require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
}

func TestGetMaccPerms(t *testing.T) {
dup := GetMaccPerms()
require.Equal(t, maccPerms, dup, "duplicated module account permissions differed from actual module account permissions")
}
47 changes: 37 additions & 10 deletions app/test_helpers.go → app/testsuite/helpers.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package app
package testsuite

import (
"testing"
Expand All @@ -7,6 +7,8 @@ import (
"github.com/stretchr/testify/require"
dbm "github.com/tendermint/tm-db"

"github.com/tendermint/tendermint/crypto/ed25519"

abci "github.com/tendermint/tendermint/abci/types"
tmjson "github.com/tendermint/tendermint/libs/json"
"github.com/tendermint/tendermint/libs/log"
Expand All @@ -22,6 +24,8 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

"github.com/regen-network/regen-ledger/v4/app"
)

// DefaultConsensusParams defines the default Tendermint consensus params used in
Expand Down Expand Up @@ -50,12 +54,24 @@ type SetupOptions struct {
InvCheckPeriod uint
HomePath string
SkipUpgradeHeights map[int64]bool
EncConfig EncodingConfig
EncConfig app.EncodingConfig
AppOpts types.AppOptions
}

func DefaultOptions() SetupOptions {
return SetupOptions{
Logger: log.NewNopLogger(),
DB: dbm.NewMemDB(),
InvCheckPeriod: 5,
HomePath: app.DefaultNodeHome,
SkipUpgradeHeights: map[int64]bool{},
EncConfig: app.MakeEncodingConfig(),
AppOpts: EmptyAppOptions{},
}
}

// NewAppWithCustomOptions initializes a new RegenApp with custom options.
func NewAppWithCustomOptions(t *testing.T, isCheckTx bool, options SetupOptions) *RegenApp {
func NewAppWithCustomOptions(t *testing.T, isCheckTx bool, options SetupOptions) *app.RegenApp {
t.Helper()

privVal := mock.NewPV()
Expand All @@ -73,17 +89,17 @@ func NewAppWithCustomOptions(t *testing.T, isCheckTx bool, options SetupOptions)
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))),
}

app := NewRegenApp(options.Logger, options.DB, nil, true, options.SkipUpgradeHeights, options.HomePath, options.InvCheckPeriod, options.EncConfig, options.AppOpts)
genesisState := NewDefaultGenesisState(app.appCodec)
genesisState = genesisStateWithValSet(t, app, genesisState, valSet, []authtypes.GenesisAccount{acc}, balance)
regenApp := app.NewRegenApp(options.Logger, options.DB, nil, true, options.SkipUpgradeHeights, options.HomePath, options.InvCheckPeriod, options.EncConfig, options.AppOpts)
genesisState := app.NewDefaultGenesisState(regenApp.AppCodec())
genesisState = genesisStateWithValSet(t, regenApp, genesisState, valSet, []authtypes.GenesisAccount{acc}, balance)

if !isCheckTx {
// init chain must be called to stop deliverState from being nil
stateBytes, err := tmjson.MarshalIndent(genesisState, "", " ")
require.NoError(t, err)

// Initialize the chain
app.InitChain(
regenApp.InitChain(
abci.RequestInitChain{
Validators: []abci.ValidatorUpdate{},
ConsensusParams: DefaultConsensusParams,
Expand All @@ -92,14 +108,14 @@ func NewAppWithCustomOptions(t *testing.T, isCheckTx bool, options SetupOptions)
)
}

return app
return regenApp
}

func genesisStateWithValSet(t *testing.T,
app *RegenApp, genesisState GenesisState,
app *app.RegenApp, genesisState app.GenesisState,
valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount,
balances ...banktypes.Balance,
) GenesisState {
) app.GenesisState {
// set genesis accounts
authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis)
Expand Down Expand Up @@ -166,3 +182,14 @@ type EmptyAppOptions struct{}
func (ao EmptyAppOptions) Get(o string) interface{} {
return nil
}

// CreateRandomAccounts is a function return a list of randomly generated AccAddresses
func CreateRandomAccounts(numAccts int) []sdk.AccAddress {
testAddrs := make([]sdk.AccAddress, numAccts)
for i := 0; i < numAccts; i++ {
pk := ed25519.GenPrivKey().PubKey()
testAddrs[i] = sdk.AccAddress(pk.Address())
}

return testAddrs
}
2 changes: 1 addition & 1 deletion app/testsuite/network_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func NewRegenAppConstructor(encCfg app.EncodingConfig) network.AppConstructor {
return app.NewRegenApp(
val.Ctx.Logger, dbm.NewMemDB(), nil, true, make(map[int64]bool), val.Ctx.Config.RootDir, 0,
encCfg,
app.EmptyAppOptions{},
EmptyAppOptions{},
baseapp.SetPruning(pruningtypes.NewPruningOptionsFromString(val.AppConfig.Pruning)),
baseapp.SetMinGasPrices(val.AppConfig.MinGasPrices),
)
Expand Down
34 changes: 34 additions & 0 deletions app/testsuite/suite.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package testsuite

import (
"time"

"github.com/stretchr/testify/suite"

"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
tmtypes "github.com/tendermint/tendermint/proto/tendermint/types"

"github.com/regen-network/regen-ledger/v4/app"
)

type UpgradeTestSuite struct {
suite.Suite

App *app.RegenApp
Ctx sdk.Context
QueryHelper *baseapp.QueryServiceTestHelper
TestAccs []sdk.AccAddress
}

// Setup sets up basic environment for suite (App, Ctx, and test accounts)
func (s *UpgradeTestSuite) Setup() {
s.App = NewAppWithCustomOptions(s.T(), false, DefaultOptions())
s.Ctx = s.App.BaseApp.NewContext(false, tmtypes.Header{Height: 1, ChainID: "regen-1", Time: time.Now().UTC()})
s.QueryHelper = &baseapp.QueryServiceTestHelper{
GRPCQueryRouter: s.App.GRPCQueryRouter(),
Ctx: s.Ctx,
}

s.TestAccs = CreateRandomAccounts(3)
}
Loading

0 comments on commit ea2dd1b

Please sign in to comment.