Skip to content

Commit

Permalink
chore: update grpc queries to handle multiple fees (#967)
Browse files Browse the repository at this point in the history
* adding new proto types and codegen

* refactoring ics29 fees for more efficient storage

* updating tests

* updating protos and existing queries

* updating grpc queries and refactoring tests

* format error correct in favour of proto string() method

* leveraging ParseKeyFeesInEscrow to obtain  packet id in query
  • Loading branch information
damiannolan authored Feb 24, 2022
1 parent f1ba06f commit fcea26d
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 153 deletions.
4 changes: 2 additions & 2 deletions docs/ibc/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ QueryIncentivizedPacketsResponse is the response type for the incentivized packe

| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `incentivized_packet` | [IdentifiedPacketFee](#ibc.applications.fee.v1.IdentifiedPacketFee) | | Incentivized_packet |
| `incentivized_packet` | [IdentifiedPacketFees](#ibc.applications.fee.v1.IdentifiedPacketFees) | | Incentivized_packet |



Expand Down Expand Up @@ -977,7 +977,7 @@ QueryIncentivizedPacketsResponse is the response type for the incentivized packe

| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `incentivized_packets` | [IdentifiedPacketFee](#ibc.applications.fee.v1.IdentifiedPacketFee) | repeated | Map of all incentivized_packets |
| `incentivized_packets` | [IdentifiedPacketFees](#ibc.applications.fee.v1.IdentifiedPacketFees) | repeated | Map of all incentivized_packets |



Expand Down
28 changes: 15 additions & 13 deletions modules/apps/29-fee/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,25 @@ func (k Keeper) IncentivizedPackets(c context.Context, req *types.QueryIncentivi

ctx := sdk.UnwrapSDKContext(c).WithBlockHeight(int64(req.QueryHeight))

var packets []*types.IdentifiedPacketFee
store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.FeeInEscrowPrefix))
_, err := query.Paginate(store, req.Pagination, func(_, value []byte) error {
result := k.MustUnmarshalFee(value)
packets = append(packets, &result)
var identifiedPackets []types.IdentifiedPacketFees
store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.FeesInEscrowPrefix))
_, err := query.Paginate(store, req.Pagination, func(key, value []byte) error {
packetID, err := types.ParseKeyFeesInEscrow(types.FeesInEscrowPrefix + string(key))
if err != nil {
return err
}

packetFees := k.MustUnmarshalFees(value)
identifiedPackets = append(identifiedPackets, types.NewIdentifiedPacketFees(packetID, packetFees.PacketFees))
return nil
})

if err != nil {
return nil, status.Error(
codes.NotFound, err.Error(),
)
return nil, status.Error(codes.NotFound, err.Error())
}

return &types.QueryIncentivizedPacketsResponse{
IncentivizedPackets: packets,
IncentivizedPackets: identifiedPackets,
}, nil
}

Expand All @@ -51,15 +54,14 @@ func (k Keeper) IncentivizedPacket(c context.Context, req *types.QueryIncentiviz

ctx := sdk.UnwrapSDKContext(c).WithBlockHeight(int64(req.QueryHeight))

fee, exists := k.GetFeeInEscrow(ctx, req.PacketId)
feesInEscrow, exists := k.GetFeesInEscrow(ctx, req.PacketId)
if !exists {
return nil, status.Error(
codes.NotFound,
sdkerrors.Wrap(types.ErrFeeNotFound, req.PacketId.String()).Error(),
)
sdkerrors.Wrapf(types.ErrFeeNotFound, "channel: %s, port: %s, sequence: %d", req.PacketId.ChannelId, req.PacketId.PortId, req.PacketId.Sequence).Error())
}

return &types.QueryIncentivizedPacketResponse{
IncentivizedPacket: &fee,
IncentivizedPacket: types.NewIdentifiedPacketFees(req.PacketId, feesInEscrow.PacketFees),
}, nil
}
138 changes: 60 additions & 78 deletions modules/apps/29-fee/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package keeper_test

import (
"fmt"

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

Expand All @@ -11,25 +9,10 @@ import (
ibctesting "github.com/cosmos/ibc-go/v3/testing"
)

func (suite *KeeperTestSuite) TestQueryIncentivizedPacketI() {

func (suite *KeeperTestSuite) TestQueryIncentivizedPackets() {
var (
req *types.QueryIncentivizedPacketRequest
)

// setup
suite.coordinator.Setup(suite.path) // setup channel
validPacketId := channeltypes.NewPacketId(suite.path.EndpointA.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, 1)
invalidPacketId := channeltypes.NewPacketId(ibctesting.FirstChannelID, ibctesting.MockFeePort, 2)
identifiedPacketFee := types.NewIdentifiedPacketFee(
validPacketId,
types.Fee{
AckFee: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))),
RecvFee: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))),
TimeoutFee: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))),
},
"", // leave empty here and then populate on each testcase since suite resets
[]string(nil),
req *types.QueryIncentivizedPacketsRequest
expectedPackets []types.IdentifiedPacketFees
)

testCases := []struct {
Expand All @@ -40,117 +23,116 @@ func (suite *KeeperTestSuite) TestQueryIncentivizedPacketI() {
{
"success",
func() {
req = &types.QueryIncentivizedPacketRequest{
PacketId: validPacketId,
suite.chainA.GetSimApp().IBCFeeKeeper.SetFeeEnabled(suite.chainA.GetContext(), ibctesting.MockFeePort, ibctesting.FirstChannelID)

fee := types.NewFee(defaultReceiveFee, defaultAckFee, defaultTimeoutFee)
packetFee := types.NewPacketFee(fee, suite.chainA.SenderAccount.GetAddress().String(), []string(nil))

for i := 0; i < 3; i++ {
// escrow packet fees for three different packets
packetID := channeltypes.NewPacketId(ibctesting.FirstChannelID, ibctesting.MockFeePort, uint64(i+1))
suite.chainA.GetSimApp().IBCFeeKeeper.EscrowPacketFee(suite.chainA.GetContext(), packetID, packetFee)

expectedPackets = append(expectedPackets, types.NewIdentifiedPacketFees(packetID, []types.PacketFee{packetFee}))
}

req = &types.QueryIncentivizedPacketsRequest{
Pagination: &query.PageRequest{
Limit: 5,
CountTotal: false,
},
QueryHeight: 0,
}
},
true,
},
{
"packetId not found",
"empty pagination",
func() {
req = &types.QueryIncentivizedPacketRequest{
PacketId: invalidPacketId,
QueryHeight: 0,
}
expectedPackets = nil
req = &types.QueryIncentivizedPacketsRequest{}
},
false,
true,
},
}

for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest() // reset

refundAcc := suite.chainA.SenderAccount.GetAddress()
// populate RefundAddress field
identifiedPacketFee.RefundAddress = refundAcc.String()

tc.malleate()

suite.chainA.GetSimApp().IBCFeeKeeper.SetFeeEnabled(suite.chainA.GetContext(), validPacketId.PortId, validPacketId.ChannelId)
suite.chainA.GetSimApp().IBCFeeKeeper.SetFeeInEscrow(suite.chainA.GetContext(), identifiedPacketFee)
tc.malleate() // malleate mutates test data

ctx := sdk.WrapSDKContext(suite.chainA.GetContext())
res, err := suite.queryClient.IncentivizedPacket(ctx, req)
res, err := suite.queryClient.IncentivizedPackets(ctx, req)

if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(&identifiedPacketFee, res.IncentivizedPacket)
suite.Require().Equal(expectedPackets, res.IncentivizedPackets)
} else {
suite.Require().Error(err)
}
})
}
}

func (suite *KeeperTestSuite) TestQueryIncentivizedPackets() {
func (suite *KeeperTestSuite) TestQueryIncentivizedPacket() {
var (
req *types.QueryIncentivizedPacketsRequest
expPackets []*types.IdentifiedPacketFee
req *types.QueryIncentivizedPacketRequest
)

fee := types.Fee{
AckFee: sdk.Coins{sdk.Coin{Denom: sdk.DefaultBondDenom, Amount: sdk.NewInt(100)}},
RecvFee: sdk.Coins{sdk.Coin{Denom: sdk.DefaultBondDenom, Amount: sdk.NewInt(100)}},
TimeoutFee: sdk.Coins{sdk.Coin{Denom: sdk.DefaultBondDenom, Amount: sdk.NewInt(100)}},
}

testCases := []struct {
msg string
name string
malleate func()
expPass bool
}{
{
"empty pagination",
func() {
req = &types.QueryIncentivizedPacketsRequest{}
},
"success",
func() {},
true,
},
{
"success",
"fees not found for packet id",
func() {
refundAcc := suite.chainA.SenderAccount.GetAddress()

fee1 := types.NewIdentifiedPacketFee(channeltypes.NewPacketId(ibctesting.FirstChannelID, ibctesting.MockFeePort, 1), fee, refundAcc.String(), []string(nil))
fee2 := types.NewIdentifiedPacketFee(channeltypes.NewPacketId(ibctesting.FirstChannelID, ibctesting.MockFeePort, 2), fee, refundAcc.String(), []string(nil))
fee3 := types.NewIdentifiedPacketFee(channeltypes.NewPacketId(ibctesting.FirstChannelID, ibctesting.MockFeePort, 3), fee, refundAcc.String(), []string(nil))

expPackets = []*types.IdentifiedPacketFee{}
expPackets = append(expPackets, &fee1, &fee2, &fee3)

suite.chainA.GetSimApp().IBCFeeKeeper.SetFeeEnabled(suite.chainA.GetContext(), ibctesting.MockFeePort, ibctesting.FirstChannelID)
for _, packetFee := range expPackets {
suite.chainA.GetSimApp().IBCFeeKeeper.SetFeeInEscrow(suite.chainA.GetContext(), *packetFee)
}

req = &types.QueryIncentivizedPacketsRequest{
Pagination: &query.PageRequest{
Limit: 5,
CountTotal: false,
},
req = &types.QueryIncentivizedPacketRequest{
PacketId: channeltypes.NewPacketId(ibctesting.FirstChannelID, ibctesting.MockFeePort, 100),
QueryHeight: 0,
}
},
true,
false,
},
}

for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.Run(tc.name, func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.chainA.GetContext())

res, err := suite.queryClient.IncentivizedPackets(ctx, req)
suite.chainA.GetSimApp().IBCFeeKeeper.SetFeeEnabled(suite.chainA.GetContext(), ibctesting.MockFeePort, ibctesting.FirstChannelID)

packetID := channeltypes.NewPacketId(ibctesting.FirstChannelID, ibctesting.MockFeePort, 1)
fee := types.NewFee(defaultReceiveFee, defaultAckFee, defaultTimeoutFee)
packetFee := types.NewPacketFee(fee, suite.chainA.SenderAccount.GetAddress().String(), []string(nil))

for i := 0; i < 3; i++ {
// escrow three packet fees for the same packet
err := suite.chainA.GetSimApp().IBCFeeKeeper.EscrowPacketFee(suite.chainA.GetContext(), packetID, packetFee)
suite.Require().NoError(err)
}

req = &types.QueryIncentivizedPacketRequest{
PacketId: packetID,
QueryHeight: 0,
}

tc.malleate() // malleate mutates test data

ctx := sdk.WrapSDKContext(suite.chainA.GetContext())
res, err := suite.queryClient.IncentivizedPacket(ctx, req)

if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expPackets, res.IncentivizedPackets)
suite.Require().Equal(types.NewIdentifiedPacketFees(packetID, []types.PacketFee{packetFee, packetFee, packetFee}), res.IncentivizedPacket)
} else {
suite.Require().Error(err)
}
Expand Down
9 changes: 9 additions & 0 deletions modules/apps/29-fee/types/fee.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types"
)

// NewPacketFee creates and returns a new PacketFee struct including the incentivization fees, refund addres and relayers
Expand Down Expand Up @@ -42,6 +43,14 @@ func NewPacketFees(packetFees []PacketFee) PacketFees {
}
}

// NewIdentifiedPacketFees creates and returns a new IdentifiedPacketFees struct containing a packet ID and packet fees
func NewIdentifiedPacketFees(packetID channeltypes.PacketId, packetFees []PacketFee) IdentifiedPacketFees {
return IdentifiedPacketFees{
PacketId: packetID,
PacketFees: packetFees,
}
}

// NewFee creates and returns a new Fee struct encapsulating the receive, acknowledgement and timeout fees as sdk.Coins
func NewFee(recvFee, ackFee, timeoutFee sdk.Coins) Fee {
return Fee{
Expand Down
Loading

0 comments on commit fcea26d

Please sign in to comment.