Skip to content

Commit

Permalink
feat: uibc unit tests (#2021)
Browse files Browse the repository at this point in the history
* rename dependencies

* add binary store helpers

* msg util starter

* refactore uibc quota tests

* update wiring

* lint

* rename KeeperBuilder

* changelog
  • Loading branch information
robert-zaremba authored May 5, 2023
1 parent 855fc06 commit 0c704b9
Show file tree
Hide file tree
Showing 30 changed files with 577 additions and 528 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
- [1989](https://github.com/umee-network/umee/pull/1989) Updated go version from 1.19 to 1.20
- [2009](https://github.com/umee-network/umee/pull/2009) Use DavidAnson/markdownlint action for Markdown linting.
- [2010](https://github.com/umee-network/umee/pull/2010) New `util/store` generic functions to load all values from a store.
- [2021](https://github.com/umee-network/umee/pull/2021) `quota/keeper` unit test refactor.

### Fixes

Expand Down
12 changes: 6 additions & 6 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ type UmeeApp struct {
IncentiveKeeper incentivekeeper.Keeper
OracleKeeper oraclekeeper.Keeper
bech32IbcKeeper bech32ibckeeper.Keeper
UIbcQuotaKeeper uibcquotakeeper.Keeper
UIbcQuotaKeeperB uibcquotakeeper.Builder

// make scoped keepers public for testing purposes
ScopedIBCKeeper capabilitykeeper.ScopedKeeper
Expand Down Expand Up @@ -531,7 +531,7 @@ func New(
)

// UIbcQuotaKeeper implements ibcporttypes.ICS4Wrapper
app.UIbcQuotaKeeper = uibcquotakeeper.NewKeeper(
app.UIbcQuotaKeeperB = uibcquotakeeper.NewKeeperBuilder(
appCodec,
keys[uibc.StoreKey],
app.IBCKeeper.ChannelKeeper, app.LeverageKeeper, uibcoracle.FromUmeeAvgPriceOracle(app.OracleKeeper),
Expand All @@ -544,7 +544,7 @@ func New(
appCodec,
keys[ibctransfertypes.StoreKey],
app.GetSubspace(ibctransfertypes.ModuleName),
app.UIbcQuotaKeeper, // ISC4 Wrapper: IBC Rate Limit middleware
app.UIbcQuotaKeeperB, // ISC4 Wrapper: IBC Rate Limit middleware
app.IBCKeeper.ChannelKeeper,
&app.IBCKeeper.PortKeeper,
app.AccountKeeper,
Expand Down Expand Up @@ -573,7 +573,7 @@ func New(
app.UIBCTransferKeeper,
)
// transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper)
transferStack = uibcquota.NewICS20Middleware(transferStack, app.UIbcQuotaKeeper, appCodec)
transferStack = uibcquota.NewICS20Middleware(transferStack, app.UIbcQuotaKeeperB, appCodec)

// Create Interchain Accounts Stack
// SendPacket, since it is originating from the application to core IBC:
Expand Down Expand Up @@ -686,7 +686,7 @@ func New(
incentivemodule.NewAppModule(appCodec, app.IncentiveKeeper, app.BankKeeper, app.LeverageKeeper),
oracle.NewAppModule(appCodec, app.OracleKeeper, app.AccountKeeper, app.BankKeeper),
bech32ibc.NewAppModule(appCodec, app.bech32IbcKeeper),
uibcmodule.NewAppModule(appCodec, app.UIbcQuotaKeeper),
uibcmodule.NewAppModule(appCodec, app.UIbcQuotaKeeperB),
}
if Experimental {
appModules = append(
Expand Down Expand Up @@ -1026,7 +1026,7 @@ func (app *UmeeApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APICo

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

// RegisterTendermintService implements the Application.RegisterTendermintService method.
Expand Down
24 changes: 24 additions & 0 deletions util/sdkutil/msg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package sdkutil

import (
"context"

sdk "github.com/cosmos/cosmos-sdk/types"
)

// StartMsg unpacks sdk.Context and validates msg.
func StartMsg(ctx context.Context, msg sdk.Msg) (sdk.Context, error) {
if err := msg.ValidateBasic(); err != nil {
return sdk.Context{}, err
}
sdkCtx := sdk.UnwrapSDKContext(ctx)
var err error
if fvmsg, ok := msg.(fullValidate); ok {
err = fvmsg.Validate(&sdkCtx)
}
return sdkCtx, err
}

type fullValidate interface {
Validate(*sdk.Context) error
}
26 changes: 25 additions & 1 deletion util/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"golang.org/x/exp/constraints"
)

// GetValue loads value from the store using default Unmarshaler
func GetValue[TPtr PtrMarshalable[T], T any](store sdk.KVStore, key []byte, errField string) TPtr {
if bz := store.Get(key); len(bz) > 0 {
var c TPtr = new(T)
Expand All @@ -40,13 +41,37 @@ func GetValue[TPtr PtrMarshalable[T], T any](store sdk.KVStore, key []byte, errF
return nil
}

// SetValue saves value in the store using default Marshaler
func SetValue[T Marshalable](store sdk.KVStore, key []byte, value T, errField string) error {
bz, err := value.Marshal()
if err != nil {
return fmt.Errorf("can't marshal %s: %s", errField, err)
}
store.Set(key, bz)
return nil
}

// GetBinValue is similar to GetValue (loads value in the store),
// but uses UnmarshalBinary interface instead of protobuf
func GetBinValue[TPtr PtrBinMarshalable[T], T any](store sdk.KVStore, key []byte, errField string) (TPtr, error) {
if bz := store.Get(key); len(bz) > 0 {
var c TPtr = new(T)
if err := c.UnmarshalBinary(bz); err != nil {
return nil, fmt.Errorf("error unmarshaling %s into %T: %s", errField, c, err)
}
return c, nil
}
return nil, nil
}

// SetBinValue is similar to SetValue (stores value in the store),
// but uses UnmarshalBinary interface instead of protobuf
func SetBinValue[T BinMarshalable](store sdk.KVStore, key []byte, value T, errField string) error {
bz, err := value.MarshalBinary()
if err != nil {
return fmt.Errorf("can't marshal %s: %s", errField, err)
}
store.Set(key, bz)
return nil
}

Expand Down Expand Up @@ -135,7 +160,6 @@ func SetDec(store sdk.KVStore, key []byte, val sdk.Dec, errField string) error {
if val.IsNegative() {
return fmt.Errorf("%s: cannot set negative %s", val, errField)
}

return SetValue(store, key, &val, errField)
}

Expand Down
10 changes: 10 additions & 0 deletions util/store/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,13 @@ type gogoInteger[T any, Num constraints.Integer] interface {
PtrMarshalable[T]
GetValue() Num
}

type BinMarshalable interface {
MarshalBinary() ([]byte, error)
UnmarshalBinary(data []byte) error
}

type PtrBinMarshalable[T any] interface {
BinMarshalable
*T
}
4 changes: 2 additions & 2 deletions x/uibc/client/tests/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/umee-network/umee/v4/x/uibc/client/cli"
)

func (s *IntegrationTests) TestQueryParams(t *testing.T) {
func (s *IntegrationTests) TestQueryParams(_ *testing.T) {
queries := []itestsuite.TestQuery{
{
Name: "Query params",
Expand All @@ -31,7 +31,7 @@ func (s *IntegrationTests) TestQueryParams(t *testing.T) {
s.RunTestQueries(queries...)
}

func (s *IntegrationTests) TestGetQuota(t *testing.T) {
func (s *IntegrationTests) TestGetQuota(_ *testing.T) {
queries := []itestsuite.TestQuery{
{
Name: "Get ibc-transfer quota of all denoms",
Expand Down
2 changes: 1 addition & 1 deletion x/uibc/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type BankKeeper interface {
IterateAllDenomMetaData(ctx sdk.Context, cb func(types.Metadata) bool)
}

type LeverageKeeper interface {
type Leverage interface {
GetTokenSettings(ctx sdk.Context, baseDenom string) (ltypes.Token, error)
ExchangeUToken(ctx sdk.Context, uToken sdk.Coin) (sdk.Coin, error)
DeriveExchangeRate(ctx sdk.Context, denom string) sdk.Dec
Expand Down
6 changes: 3 additions & 3 deletions x/uibc/ics20/ibc_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ import (
// IBCModule wraps ICS-20 IBC module to limit token transfer inflows.
type IBCModule struct {
// leverage keeper
lkeeper uibc.LeverageKeeper
lkeeper uibc.Leverage
// embed the ICS-20 transfer's AppModule: ibctransfer.IBCModule
ibcporttypes.IBCModule

keeper keeper.Keeper
}

func NewIBCModule(leverageKeeper uibc.LeverageKeeper, am ibctransfer.IBCModule, k keeper.Keeper) IBCModule {
func NewIBCModule(leverageKeeper uibc.Leverage, am ibctransfer.IBCModule, k keeper.Keeper) IBCModule {
return IBCModule{
lkeeper: leverageKeeper,
IBCModule: am,
Expand Down Expand Up @@ -67,7 +67,7 @@ func (am IBCModule) OnRecvPacket(

func CheckIBCInflow(ctx sdk.Context,
packet channeltypes.Packet,
lkeeper uibc.LeverageKeeper,
lkeeper uibc.Leverage,
dataDenom string, isSourceChain bool,
) ibcexported.Acknowledgement {
// if chain is recevier and sender chain is source then we need create ibc_denom (ibc/hash(channel,denom)) to
Expand Down
11 changes: 6 additions & 5 deletions x/uibc/module/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,23 @@ import (
)

// BeginBlock implements BeginBlock for the x/uibc module.
func BeginBlock(ctx sdk.Context, keeper keeper.Keeper) {
quotaExpires, err := keeper.GetExpire(ctx)
func BeginBlock(ctx sdk.Context, k keeper.Keeper) {
quotaExpires, err := k.GetExpire()
if err != nil {
// TODO, use logger as argument
ctx.Logger().Error("can't get quota exipre", "error", err)
return
}

// reset quotas
if quotaExpires == nil || quotaExpires.Before(ctx.BlockTime()) {
if err = keeper.ResetAllQuotas(ctx); err != nil {
if err = k.ResetAllQuotas(); err != nil {
ctx.Logger().Error("can't get quota exipre", "error", err)
}
}
}

// EndBlocker implements EndBlock for the x/leverage module.
func EndBlocker(_ sdk.Context, _ keeper.Keeper) []abci.ValidatorUpdate {
// EndBlocker implements EndBlock.
func EndBlocker() []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}
20 changes: 10 additions & 10 deletions x/uibc/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,27 +83,27 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingCo
// AppModule represents the AppModule for this module
type AppModule struct {
AppModuleBasic
keeper keeper.Keeper
kb keeper.Builder
}

func NewAppModule(cdc codec.Codec, keeper keeper.Keeper) AppModule {
func NewAppModule(cdc codec.Codec, kb keeper.Builder) AppModule {
return AppModule{
AppModuleBasic: NewAppModuleBasic(cdc),
keeper: keeper,
kb: kb,
}
}

// ExportGenesis implements module.AppModule
func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage {
genState := am.keeper.ExportGenesis(ctx)
genState := am.kb.ExportGenesis(ctx)
return cdc.MustMarshalJSON(genState)
}

// InitGenesis implements module.AppModule
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate {
var genState ibctransfer.GenesisState
cdc.MustUnmarshalJSON(data, &genState)
am.keeper.InitGenesis(ctx, genState)
am.kb.InitGenesis(ctx, genState)

return []abci.ValidatorUpdate{}
}
Expand All @@ -126,8 +126,8 @@ func (AppModule) RegisterInvariants(sdk.InvariantRegistry) {}

// RegisterServices implements module.AppModule
func (am AppModule) RegisterServices(cfg module.Configurator) {
ibctransfer.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
ibctransfer.RegisterQueryServer(cfg.QueryServer(), keeper.NewQuerier(am.keeper))
ibctransfer.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.kb))
ibctransfer.RegisterQueryServer(cfg.QueryServer(), keeper.NewQuerier(am.kb))
}

// Route implements module.AppModule
Expand All @@ -137,11 +137,11 @@ func (AppModule) Route() sdk.Route {

// BeginBlock executes all ABCI BeginBlock logic respective to the x/uibc module.
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
BeginBlock(ctx, am.keeper)
BeginBlock(ctx, am.kb.Keeper(&ctx))
}

// EndBlock executes all ABCI EndBlock logic respective to the x/uibc module.
// It returns no validator updates.
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return EndBlocker(ctx, am.keeper)
func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return EndBlocker()
}
12 changes: 6 additions & 6 deletions x/uibc/quota/ibc_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ var _ porttypes.Middleware = ICS20Middleware{}
// quota update on acknowledgement error or timeout.
type ICS20Middleware struct {
porttypes.IBCModule
keeper keeper.Keeper
cdc codec.JSONCodec
kb keeper.Builder
cdc codec.JSONCodec
}

// NewICS20Middleware is an IBCMiddlware constructor.
// `app` must be an ICS20 app.
func NewICS20Middleware(app porttypes.IBCModule, k keeper.Keeper, cdc codec.JSONCodec) ICS20Middleware {
func NewICS20Middleware(app porttypes.IBCModule, k keeper.Builder, cdc codec.JSONCodec) ICS20Middleware {
return ICS20Middleware{
IBCModule: app,
keeper: k,
kb: k,
cdc: cdc,
}
}
Expand All @@ -46,7 +46,7 @@ func (im ICS20Middleware) OnAcknowledgementPacket(ctx sdk.Context, packet channe
return errors.Wrap(err, "cannot unmarshal ICS-20 transfer packet acknowledgement")
}
if _, ok := ack.Response.(*channeltypes.Acknowledgement_Error); ok {
params := im.keeper.GetParams(ctx)
params := im.kb.Keeper(&ctx).GetParams()
if params.IbcStatus == uibc.IBCTransferStatus_IBC_TRANSFER_STATUS_QUOTA_ENABLED {
err := im.revertQuotaUpdate(ctx, packet.Data)
emitOnRevertQuota(&ctx, "acknowledgement", packet.Data, err)
Expand Down Expand Up @@ -80,7 +80,7 @@ func (im ICS20Middleware) revertQuotaUpdate(
return sdkerrors.ErrInvalidRequest.Wrapf("invalid transfer amount %s", data.Amount)
}

return im.keeper.UndoUpdateQuota(ctx, data.Denom, amount)
return im.kb.Keeper(&ctx).UndoUpdateQuota(data.Denom, amount)
}

func ValidateReceiverAddress(packet channeltypes.Packet) error {
Expand Down
6 changes: 3 additions & 3 deletions x/uibc/quota/ics4_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

// GetAppVersion implements types.Middleware
func (im ICS20Middleware) GetAppVersion(ctx sdk.Context, portID string, channelID string) (string, bool) {
return im.keeper.GetAppVersion(ctx, portID, channelID)
return im.kb.GetAppVersion(ctx, portID, channelID)
}

// SendPacket implements types.Middleware
Expand All @@ -22,12 +22,12 @@ func (im ICS20Middleware) SendPacket(
timeoutTimestamp uint64,
data []byte,
) (uint64, error) {
return im.keeper.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data)
return im.kb.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data)
}

// WriteAcknowledgement implements types.Middleware
func (im ICS20Middleware) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability,
packet exported.PacketI, ack exported.Acknowledgement,
) error {
return im.keeper.WriteAcknowledgement(ctx, chanCap, packet, ack)
return im.kb.WriteAcknowledgement(ctx, chanCap, packet, ack)
}
22 changes: 12 additions & 10 deletions x/uibc/quota/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,30 @@ import (

// InitGenesis initializes the x/uibc module's state from a provided genesis
// state.
func (k Keeper) InitGenesis(ctx sdk.Context, genState uibc.GenesisState) {
err := k.SetParams(ctx, genState.Params)
func (kb Builder) InitGenesis(ctx sdk.Context, genState uibc.GenesisState) {
k := kb.Keeper(&ctx)
err := k.SetParams(genState.Params)
util.Panic(err)

k.SetTokenOutflows(ctx, genState.Outflows)
k.SetTotalOutflowSum(ctx, genState.TotalOutflowSum)
k.SetTokenOutflows(genState.Outflows)
k.SetTotalOutflowSum(genState.TotalOutflowSum)

err = k.SetExpire(ctx, genState.QuotaExpires)
err = k.SetExpire(genState.QuotaExpires)
util.Panic(err)
}

// ExportGenesis returns the x/uibc module's exported genesis state.
func (k Keeper) ExportGenesis(ctx sdk.Context) *uibc.GenesisState {
outflows, err := k.GetAllOutflows(ctx)
func (kb Builder) ExportGenesis(ctx sdk.Context) *uibc.GenesisState {
k := kb.Keeper(&ctx)
outflows, err := k.GetAllOutflows()
util.Panic(err)
quotaExpires, err := k.GetExpire(ctx)
quotaExpires, err := k.GetExpire()
util.Panic(err)

return &uibc.GenesisState{
Params: k.GetParams(ctx),
Params: k.GetParams(),
Outflows: outflows,
TotalOutflowSum: k.GetTotalOutflow(ctx),
TotalOutflowSum: k.GetTotalOutflow(),
QuotaExpires: *quotaExpires,
}
}
Loading

0 comments on commit 0c704b9

Please sign in to comment.