Skip to content

Commit

Permalink
Merge pull request #1309 from Pylons-tech/faisal/upgrade-handler
Browse files Browse the repository at this point in the history
Faisal/upgrade handler
  • Loading branch information
MikeSofaer authored Nov 11, 2022
2 parents 25c93c5 + 2edf59d commit b69e38b
Show file tree
Hide file tree
Showing 34 changed files with 3,985 additions and 236 deletions.
44 changes: 28 additions & 16 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (

evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper"

upgradev46 "github.com/Pylons-tech/pylons/app/upgrade"
"github.com/Pylons-tech/pylons/app/upgrades"
v3 "github.com/Pylons-tech/pylons/app/upgrades/v3"
v4 "github.com/Pylons-tech/pylons/app/upgrades/v4"

storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/version"
Expand Down Expand Up @@ -142,6 +144,8 @@ var (
Bech32PrefixConsAddr = AccountAddressPrefix + sdk.PrefixValidator + sdk.PrefixConsensus
// Bech32PrefixConsPub defines the Bech32 prefix of a consensus node public key.
Bech32PrefixConsPub = AccountAddressPrefix + sdk.PrefixValidator + sdk.PrefixConsensus + sdk.PrefixPublic
// List upgrades
Upgrades = []upgrades.Upgrade{v3.Upgrade, v4.Upgrade}
)

func init() {
Expand Down Expand Up @@ -455,8 +459,6 @@ func New(
app.TransferKeeper,
app.GetSubspace(pylonsmoduletypes.ModuleName),
)
// upgrade handlers
cfg := module.NewConfigurator(appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())

epochsKeeper := epochsmodulekeeper.NewKeeper(
appCodec,
Expand Down Expand Up @@ -624,7 +626,7 @@ func New(

// register upgrade
// if isUpgrade {
app.RegisterUpgradeHandlers(cfg)
app.setupUpgradeHandlers()
// }

// initialize stores
Expand Down Expand Up @@ -808,26 +810,36 @@ func (app *PylonsApp) RegisterTendermintService(clientCtx client.Context) {
)
}

// RegisterUpgradeHandlers returns upgrade handlers
func (app *PylonsApp) RegisterUpgradeHandlers(cfg module.Configurator) {
app.UpgradeKeeper.SetUpgradeHandler(upgradev46.UpgradeName, upgradev46.CreateUpgradeHandler(app.mm, app.configurator, &app.StakingKeeper, app.keys[pylonsmoduletypes.StoreKey], app.appCodec))
// setupUpgradeHandlers setup upgrade handlers
func (app *PylonsApp) setupUpgradeHandlers() {
// v3 upgrade handler
app.UpgradeKeeper.SetUpgradeHandler(
v3.UpgradeName,
v3.CreateUpgradeHandler(app.mm, app.configurator, &app.StakingKeeper, app.keys[pylonsmoduletypes.StoreKey], app.appCodec))
// v4 mainnet upgrade handler
app.UpgradeKeeper.SetUpgradeHandler(
v4.UpgradeName,
v4.CreateUpgradeHandler(app.mm, app.configurator, app.BankKeeper, &app.AccountKeeper, &app.StakingKeeper, &app.PylonsKeeper),
)
}

func (app *PylonsApp) setupUpgradeStoreLoaders() {
// When a planned update height is reached, the old binary will panic
// writing on disk the height and name of the update that triggered it
// This will read that value, and execute the preparations for the upgrade.
upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk()
if err != nil {
panic(fmt.Sprintf("failed to read upgrade info from disk %s", err))
panic(fmt.Errorf("failed to read upgrade info from disk: %w", err))
}

// TODO: add module name.
if upgradeInfo.Name == upgradev46.UpgradeName && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
storeUpgrades := storetypes.StoreUpgrades{
Added: []string{icacontrollertypes.StoreKey, icahosttypes.StoreKey},
Deleted: []string{"epoch"},
}
if app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
return
}

// configure store loader that checks if version == upgradeHeight and applies store upgrades
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades))
for _, upgrade := range Upgrades {
if upgradeInfo.Name == upgrade.UpgradeName {
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &upgrade.StoreUpgrades))
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions app/apptesting/test_suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ func (s *KeeperTestHelper) FundAcc(acc sdk.AccAddress, amounts sdk.Coins) {
s.Require().NoError(err)
}

func (s *KeeperTestHelper) FundModule(moduleName string, amounts sdk.Coins) {
err := testutil.FundModuleAccount(s.App.BankKeeper, s.Ctx, moduleName, amounts)
s.Require().NoError(err)
}

func (s *KeeperTestHelper) SetupValidator(bondStatus stakingtypes.BondStatus) sdk.ValAddress {
valPub := secp256k1.GenPrivKey().PubKey()
valAddr := sdk.ValAddress(valPub.Address())
Expand Down
9 changes: 6 additions & 3 deletions app/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"
"time"

"github.com/Pylons-tech/pylons/x/pylons/types"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
Expand Down Expand Up @@ -142,7 +143,9 @@ func genesisStateWithValSet(app *PylonsApp, genesisState GenesisState,

}
// set validators and delegations
stakingGenesis := stakingtypes.NewGenesisState(stakingtypes.DefaultParams(), validators, delegations)
stakingParams := stakingtypes.DefaultParams()
stakingParams.BondDenom = types.StakingCoinDenom
stakingGenesis := stakingtypes.NewGenesisState(stakingParams, validators, delegations)
genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis)

totalSupply := sdk.NewCoins()
Expand All @@ -153,13 +156,13 @@ func genesisStateWithValSet(app *PylonsApp, genesisState GenesisState,

for range delegations {
// add delegated tokens to total supply
totalSupply = totalSupply.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt))
totalSupply = totalSupply.Add(sdk.NewCoin(types.StakingCoinDenom, bondAmt))
}

// add bonded amount to bonded pool module account
balances = append(balances, banktypes.Balance{
Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(),
Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)},
Coins: sdk.Coins{sdk.NewCoin(types.StakingCoinDenom, bondAmt)},
})

// update total supply
Expand Down
3 changes: 0 additions & 3 deletions app/upgrade/const.go

This file was deleted.

16 changes: 16 additions & 0 deletions app/upgrades/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package upgrades

import (
storetypes "github.com/cosmos/cosmos-sdk/store/types"
)

// Upgrade defines a struct containing necessary fields that a SoftwareUpgradeProposal
// must have written, in order for the state migration to go smoothly.
// An upgrade must implement this struct, and then set it in the app.go.
// The app.go will then define the handler.
type Upgrade struct {
// Upgrade version name, for the upgrade handler, e.g. `v7`
UpgradeName string
// Store upgrades, should be used for any new modules introduced, new modules deleted, or store names renamed.
StoreUpgrades storetypes.StoreUpgrades
}
18 changes: 18 additions & 0 deletions app/upgrades/v3/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package v3

import (
"github.com/Pylons-tech/pylons/app/upgrades"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
icacontrollertypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types"
icahosttypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/host/types"
)

const UpgradeName = "sdk-46"

var Upgrade = upgrades.Upgrade{
UpgradeName: UpgradeName,
StoreUpgrades: storetypes.StoreUpgrades{
Added: []string{icacontrollertypes.StoreKey, icahosttypes.StoreKey},
Deleted: []string{"epoch"},
},
}
2 changes: 1 addition & 1 deletion app/upgrade/fork.go → app/upgrades/v3/fork.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package upgrade
package v3

import (
"github.com/cosmos/cosmos-sdk/codec"
Expand Down
22 changes: 22 additions & 0 deletions app/upgrades/v4/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package v4

import (
storetypes "github.com/cosmos/cosmos-sdk/store/types"

"github.com/Pylons-tech/pylons/app/upgrades"
)

const (
// UpgradeName is the shared upgrade plan name for mainnet and testnet
UpgradeName = "mainnet"
)

// TODO: Update StoreUpgrades

var Upgrade = upgrades.Upgrade{
UpgradeName: UpgradeName,
StoreUpgrades: storetypes.StoreUpgrades{
Added: []string{},
Deleted: []string{},
},
}
51 changes: 51 additions & 0 deletions app/upgrades/v4/msg_restrict_ubedrock_ante.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package v4

import (
pylonskeeper "github.com/Pylons-tech/pylons/x/pylons/keeper"
pylonstypes "github.com/Pylons-tech/pylons/x/pylons/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
)

type MsgRestrictUbedrockDecorator struct {
pk pylonskeeper.Keeper
}

func NewMsgRestrictUbedrockDecorator(pk pylonskeeper.Keeper) MsgRestrictUbedrockDecorator {
return MsgRestrictUbedrockDecorator{
pk: pk,
}
}

// AnteDecorator for restrict ubedrock denom used by unallowed address
func (ad MsgRestrictUbedrockDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
if (ctx.IsCheckTx() || ctx.IsReCheckTx()) && !simulate {
sigTx, ok := tx.(authsigning.SigVerifiableTx)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
}

messages := sigTx.GetMsgs()
if len(messages) == 0 {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid messages")
}
for _, message := range messages {
msgSend, ok := message.(*banktypes.MsgSend)
if !ok {
continue
}

ok, _ = msgSend.Amount.Find(pylonstypes.StakingCoinDenom)
if !ok {
continue
}

if _, kycAccFound := ad.pk.GetPylonsKYC(ctx, msgSend.ToAddress); !kycAccFound {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "'ubedrock' should only be transferred among allowed address")
}
}
}
return next(ctx, tx, simulate)
}
74 changes: 74 additions & 0 deletions app/upgrades/v4/msg_restrict_ubedrock_ante_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package v4_test

import (
"testing"
"time"

"github.com/Pylons-tech/pylons/app"
v4 "github.com/Pylons-tech/pylons/app/upgrades/v4"
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/stretchr/testify/require"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)

func noOpAnteDecorator() sdk.AnteHandler {
return func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
return ctx, nil
}
}

func createTestContext() (sdk.Context, app.PylonsApp) {
pylonsApp := app.Setup(false)

ctx := pylonsApp.BaseApp.NewContext(true, tmproto.Header{Height: 1, ChainID: "pylons-1", Time: time.Now().UTC()})
return ctx, *pylonsApp
}

func TestMsgRestrictUbedrockDecorator(t *testing.T) {
ctx, pylonsApp := createTestContext()
handler := v4.NewMsgRestrictUbedrockDecorator(pylonsApp.PylonsKeeper)
txCfg := app.MakeEncodingConfig().TxConfig

addr1 := sdk.AccAddress([]byte("address1---------------"))
addr2 := sdk.AccAddress([]byte("address2---------------"))

testCases := []struct {
name string
ctx sdk.Context
msgs []sdk.Msg
expectErr bool
}{
{
name: "Valid account",
ctx: ctx,
msgs: []sdk.Msg{
banktypes.NewMsgSend(addr1, addr2, sdk.NewCoins(sdk.NewInt64Coin("foo", 5))),
},
expectErr: false,
},
{
name: "Invalid account",
ctx: ctx,
msgs: []sdk.Msg{
banktypes.NewMsgSend(addr1, addr2, sdk.NewCoins(sdk.NewInt64Coin("ubedrock", 1))),
},
expectErr: true,
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
txBuilder := txCfg.NewTxBuilder()
require.NoError(t, txBuilder.SetMsgs(tc.msgs...))

_, err := handler.AnteHandle(tc.ctx, txBuilder.GetTx(), false, noOpAnteDecorator())
if tc.expectErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}
Loading

0 comments on commit b69e38b

Please sign in to comment.