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: custom vesting module to check signer in allow list #387

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions proto/vesting/genesis.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
syntax = "proto3";
package rollapp.vesting.types;

import "gogoproto/gogo.proto";
import "vesting/params.proto";

option go_package = "github.com/dymensionxyz/dymension-rdk/x/vesting/types";

// GenesisState defines the test module's genesis state.
message GenesisState {
// params are all parameters for the module
Params params = 1 [ (gogoproto.nullable) = false ];
}
12 changes: 12 additions & 0 deletions proto/vesting/params.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
syntax = "proto3";
package rollapp.vesting.types;
import "gogoproto/gogo.proto";

option go_package = "github.com/dymensionxyz/dymension-rdk/x/vesting/types";

// Params defines the parameters for the module.
message Params {
// allowed_addresses defines the list of addresses authorized to use the module
repeated string allowed_addresses = 1
[ (gogoproto.moretags) = "yaml:\"allowed_addresses\"" ];
}
19 changes: 13 additions & 6 deletions testutil/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth/posthandler"
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
"github.com/cosmos/cosmos-sdk/x/auth/tx"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
"github.com/cosmos/cosmos-sdk/x/bank"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
Expand Down Expand Up @@ -85,6 +82,10 @@ import (
epochskeeper "github.com/dymensionxyz/dymension-rdk/x/epochs/keeper"
epochstypes "github.com/dymensionxyz/dymension-rdk/x/epochs/types"

"github.com/dymensionxyz/dymension-rdk/x/vesting"
vestingkeeper "github.com/dymensionxyz/dymension-rdk/x/vesting/keeper"
vestingtypes "github.com/dymensionxyz/dymension-rdk/x/vesting/types"

ibctransfer "github.com/cosmos/ibc-go/v6/modules/apps/transfer"
ibctransferkeeper "github.com/cosmos/ibc-go/v6/modules/apps/transfer/keeper"
ibctransfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types"
Expand Down Expand Up @@ -212,6 +213,7 @@ type App struct {
DistrKeeper distrkeeper.Keeper
GovKeeper govkeeper.Keeper
HubGenesisKeeper hubgenkeeper.Keeper
VestingKeeper vestingkeeper.Keeper
UpgradeKeeper upgradekeeper.Keeper
ParamsKeeper paramskeeper.Keeper
IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly
Expand Down Expand Up @@ -354,6 +356,10 @@ func NewRollapp(
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.StakingKeeper = *stakingKeeper.SetHooks(app.DistrKeeper.Hooks())

app.VestingKeeper = vestingkeeper.NewKeeper(
appCodec, app.GetSubspace(vestingtypes.ModuleName),
)

app.EpochsKeeper.SetHooks(
epochstypes.NewMultiEpochHooks(
// insert epoch hooks receivers here
Expand Down Expand Up @@ -451,7 +457,7 @@ func NewRollapp(
encodingConfig.TxConfig,
),
auth.NewAppModule(appCodec, app.AccountKeeper, nil),
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
vesting.NewAppModule(app.VestingKeeper, app.AccountKeeper, app.BankKeeper),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
Expand Down Expand Up @@ -746,7 +752,7 @@ func (app *App) SimulationManager() *module.SimulationManager {
func (app *App) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
clientCtx := apiSvr.ClientCtx
// Register new tx routes from grpc-gateway.
authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
tx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
// Register new tendermint queries routes from grpc-gateway.
tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

Expand All @@ -764,7 +770,7 @@ func (app *App) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig

// RegisterTxService implements the Application.RegisterTxService method.
func (app *App) RegisterTxService(clientCtx client.Context) {
authtx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry)
tx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry)
}

// RegisterTendermintService implements the Application.RegisterTendermintService method.
Expand Down Expand Up @@ -844,6 +850,7 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino
paramsKeeper.Subspace(seqtypes.ModuleName)
paramsKeeper.Subspace(minttypes.ModuleName)
paramsKeeper.Subspace(denommetadatatypes.ModuleName)
paramsKeeper.Subspace(vestingtypes.ModuleName)
paramsKeeper.Subspace(epochstypes.ModuleName)
paramsKeeper.Subspace(distrtypes.ModuleName)
paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govv1.ParamKeyTable())
Expand Down
7 changes: 7 additions & 0 deletions testutil/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
hubgenkeeper "github.com/dymensionxyz/dymension-rdk/x/hub-genesis/keeper"
mintkeeper "github.com/dymensionxyz/dymension-rdk/x/mint/keeper"
seqkeeper "github.com/dymensionxyz/dymension-rdk/x/sequencers/keeper"
vestingkeeper "github.com/dymensionxyz/dymension-rdk/x/vesting/keeper"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"

app "github.com/dymensionxyz/dymension-rdk/testutil/app"
Expand Down Expand Up @@ -44,3 +45,9 @@
ctx := app.BaseApp.NewContext(false, tmproto.Header{Height: 1, ChainID: "rollapp-1", Time: time.Now().UTC()})
return k, ctx
}

func NewTestVestingKeeperFromApp(app *app.App) (*vestingkeeper.Keeper, sdk.Context) {
k := &app.VestingKeeper
ctx := app.BaseApp.NewContext(false, tmproto.Header{Height: 1, ChainID: "rollapp-1", Time: time.Now().UTC()})
Dismissed Show dismissed Hide dismissed
return k, ctx
}
35 changes: 35 additions & 0 deletions x/vesting/genesis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package vesting

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

"github.com/dymensionxyz/dymension-rdk/x/vesting/keeper"
"github.com/dymensionxyz/dymension-rdk/x/vesting/types"
)

// DefaultGenesis returns the default Capability genesis state
func DefaultGenesis() *types.GenesisState {
return &types.GenesisState{
Params: types.DefaultParams(),
}
}

// InitGenesis import module genesis
func InitGenesis(
ctx sdk.Context,
k keeper.Keeper,
data types.GenesisState,
) {
k.SetParams(ctx, data.Params)
}

// ExportGenesis export module state
func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState {
return &types.GenesisState{
Params: k.GetParams(ctx),
}
}

func ValidateGenesis(gs types.GenesisState) error {
return gs.Params.Validate()
}
61 changes: 61 additions & 0 deletions x/vesting/keeper/keeper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package keeper

import (
"fmt"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/tendermint/tendermint/libs/log"

"github.com/dymensionxyz/dymension-rdk/x/vesting/types"
)

// Keeper of this module maintains distributing tokens to all stakers.
type Keeper struct {
cdc codec.BinaryCodec
ps paramtypes.Subspace
}

// NewKeeper creates new instances of the vesting Keeper
func NewKeeper(
cdc codec.BinaryCodec,
ps paramtypes.Subspace,
) Keeper {
// set KeyTable if it has not already been set
if !ps.HasKeyTable() {
ps = ps.WithKeyTable(types.ParamKeyTable())
}

return Keeper{
cdc: cdc,
ps: ps,
}
}

// Logger returns a module-specific logger.
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
}

// GetParams returns the total set of denommetadata parameters.
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
k.ps.GetParamSet(ctx, &params)
return
}

// SetParams sets the total set of denommetadata parameters.
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
k.ps.SetParamSet(ctx, &params)
}

// IsAddressPermissioned checks if the given address is permissioned to create or update denom metadata
func (k Keeper) IsAddressPermissioned(ctx sdk.Context, address string) bool {
params := k.GetParams(ctx)
for _, PermissionedAddress := range params.AllowedAddresses {
if PermissionedAddress == address {
return true
}
}
return false
}
34 changes: 34 additions & 0 deletions x/vesting/keeper/keeper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package keeper_test

import (
"testing"

testkeepers "github.com/dymensionxyz/dymension-rdk/testutil/keepers"
"github.com/dymensionxyz/dymension-rdk/testutil/utils"
"github.com/dymensionxyz/dymension-rdk/x/vesting/types"
"github.com/stretchr/testify/require"
)

func TestParams(t *testing.T) {
// Setup the test environment
app := utils.Setup(t, false)
k, ctx := testkeepers.NewTestVestingKeeperFromApp(app)

// Set some initial parameters
initialParams := types.DefaultParams()
initialParams.AllowedAddresses = []string{"cosmos19crd4fwzm9qtf5ln5l3e2vmquhevjwprk8tgxp", "cosmos1gusne8eh37myphx09hgdsy85zpl2t0kzdvu3en"} // Example addresses
k.SetParams(ctx, initialParams)

// Retrieve the parameters
retrievedParams := k.GetParams(ctx)

// Assert that the retrieved parameters match the initial ones
require.Equal(t, initialParams, retrievedParams, "retrieved parameters should match the initial ones")

// Test setting and getting a different set of parameters
updatedParams := initialParams
updatedParams.AllowedAddresses = append(updatedParams.AllowedAddresses, "cosmos1s77x8wr2gzdhq8gt8c085vate0s23xu9u80wtx")
k.SetParams(ctx, updatedParams)
retrievedParams = k.GetParams(ctx)
require.Equal(t, updatedParams, retrievedParams, "retrieved parameters should match the updated ones")
}
46 changes: 46 additions & 0 deletions x/vesting/keeper/permissioned_decorator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package keeper

import (
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/dymensionxyz/dymension-rdk/x/vesting/types"
)

// PermissionedVestingDecorator prevents invalid msg types from being executed
type PermissionedVestingDecorator struct {
Copy link
Collaborator

Choose a reason for hiding this comment

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

not wired in app.go ante handler

Copy link
Contributor Author

@trinitys7 trinitys7 Apr 24, 2024

Choose a reason for hiding this comment

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

the dymension-rdk doesn't actually have antehandler. So I added it here then on rollapp-evm's app.go, we just need to call the Decorator from here

vestingKeeper Keeper
disabledMsgTypeURLs []string
}

func NewPermissionedVestingDecorator(vestingKeeper Keeper, msgTypeURLs []string) PermissionedVestingDecorator {
return PermissionedVestingDecorator{
vestingKeeper: vestingKeeper,
disabledMsgTypeURLs: msgTypeURLs,
}
}

// AnteHandle rejects vesting messages that signer does not have permissions
// to create vesting account.
func (pvd PermissionedVestingDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
for _, msg := range tx.GetMsgs() {
typeURL := sdk.MsgTypeURL(msg)
for _, disabledTypeURL := range pvd.disabledMsgTypeURLs {
if typeURL == disabledTypeURL {
// Check if vesting tx signer is 1
if len(msg.GetSigners()) != 1 {
Copy link
Contributor

Choose a reason for hiding this comment

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

why are we blocking multisigs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As I see, all vesting msgs on cosmos-sdk or evmos only contains 1 signer. WDYT

Copy link
Contributor

Choose a reason for hiding this comment

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

ok we can start with that

return ctx, errorsmod.Wrapf(types.ErrInvalidSigners, "invalid signers: %v", msg.GetSigners())
}

signer, err := sdk.Bech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), msg.GetSigners()[0])
if err != nil {
return ctx, err
}

if !pvd.vestingKeeper.IsAddressPermissioned(ctx, signer) {
return ctx, types.ErrNoPermission
}
}
}
}
return next(ctx, tx, simulate)
}
Loading
Loading