refactor(x/feegrant): collection migration (#16535) BACKPORT (#24461)

This commit is contained in:
DuongNguyen | Decentrio 2025-05-05 21:22:09 +07:00 committed by GitHub
parent 672bb26954
commit a094cb0641
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 132 additions and 237 deletions

View File

@ -81,6 +81,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Improvements
* (x/feegrant) [24461](https://github.com/cosmos/cosmos-sdk/pull/24461) Use collections for `FeeAllowance`, `FeeAllowanceQueue`.
* (client) [#24561](https://github.com/cosmos/cosmos-sdk/pull/24561) TimeoutTimestamp flag has been changed to TimeoutDuration, which now sets the timeout timestamp of unordered transactions to the current time + duration passed.
* (telemetry) [#24541](https://github.com/cosmos/cosmos-sdk/pull/24541) Telemetry now includes a pre_blocker metric key. x/upgrade should migrate to this key in v0.54.0.
* (x/auth) [#24541](https://github.com/cosmos/cosmos-sdk/pull/24541) x/auth's PreBlocker now emits telemetry under the pre_blocker metric key.

View File

@ -1,18 +1,16 @@
package keeper
import (
"bytes"
"context"
"github.com/cosmos/gogoproto/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"cosmossdk.io/store/prefix"
"cosmossdk.io/collections"
"cosmossdk.io/x/feegrant"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/runtime"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
)
@ -72,23 +70,16 @@ func (q Keeper) Allowances(c context.Context, req *feegrant.QueryAllowancesReque
return nil, err
}
ctx := sdk.UnwrapSDKContext(c)
var grants []*feegrant.Grant
store := q.storeService.OpenKVStore(ctx)
grantsStore := prefix.NewStore(runtime.KVStoreAdapter(store), feegrant.FeeAllowancePrefixByGrantee(granteeAddr))
pageRes, err := query.Paginate(grantsStore, req.Pagination, func(key, value []byte) error {
var grant feegrant.Grant
if err := q.cdc.Unmarshal(value, &grant); err != nil {
return err
}
grants = append(grants, &grant)
return nil
})
_, pageRes, err := query.CollectionFilteredPaginate(c, q.FeeAllowance, req.Pagination,
func(key collections.Pair[sdk.AccAddress, sdk.AccAddress], grant feegrant.Grant) (include bool, err error) {
grants = append(grants, &grant)
return true, nil
}, func(_ collections.Pair[sdk.AccAddress, sdk.AccAddress], value feegrant.Grant) (*feegrant.Grant, error) {
return &value, nil
}, query.WithCollectionPaginationPairPrefix[sdk.AccAddress, sdk.AccAddress](granteeAddr),
)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
@ -107,21 +98,20 @@ func (q Keeper) AllowancesByGranter(c context.Context, req *feegrant.QueryAllowa
return nil, err
}
ctx := sdk.UnwrapSDKContext(c)
var grants []*feegrant.Grant
_, pageRes, err := query.CollectionFilteredPaginate(c, q.FeeAllowance, req.Pagination,
func(key collections.Pair[sdk.AccAddress, sdk.AccAddress], grant feegrant.Grant) (include bool, err error) {
if !sdk.AccAddress(granterAddr).Equals(key.K2()) {
return false, nil
}
store := q.storeService.OpenKVStore(ctx)
prefixStore := prefix.NewStore(runtime.KVStoreAdapter(store), feegrant.FeeAllowanceKeyPrefix)
grants, pageRes, err := query.GenericFilteredPaginate(q.cdc, prefixStore, req.Pagination, func(key []byte, grant *feegrant.Grant) (*feegrant.Grant, error) {
// ParseAddressesFromFeeAllowanceKey expects the full key including the prefix.
granter, _ := feegrant.ParseAddressesFromFeeAllowanceKey(append(feegrant.FeeAllowanceKeyPrefix, key...))
if !bytes.Equal(granter, granterAddr) {
return nil, nil
}
return grant, nil
}, func() *feegrant.Grant {
return &feegrant.Grant{}
})
grants = append(grants, &grant)
return true, nil
},
func(_ collections.Pair[sdk.AccAddress, sdk.AccAddress], grant feegrant.Grant) (*feegrant.Grant, error) {
return &grant, nil
},
)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

View File

@ -147,6 +147,25 @@ func (suite *KeeperTestSuite) TestFeeAllowances() {
suite.Require().Equal(resp.Allowances[0].Grantee, suite.addrs[1].String())
},
},
{
"valid query: expect multi grant",
&feegrant.QueryAllowancesRequest{
Grantee: suite.addrs[0].String(),
},
false,
func() {
suite.grantFeeAllowance(suite.addrs[1], suite.addrs[0])
suite.grantFeeAllowance(suite.addrs[2], suite.addrs[0])
suite.grantFeeAllowance(suite.addrs[3], suite.addrs[0])
},
func(resp *feegrant.QueryAllowancesResponse) {
suite.Require().Equal(len(resp.Allowances), 3)
for i, addr := range suite.addrs[1:4] {
resp.Allowances[i].Granter = suite.addrs[0].String()
resp.Allowances[i].Granter = addr.String()
}
},
},
}
for _, tc := range testCases {

View File

@ -2,9 +2,11 @@ package keeper
import (
"context"
"errors"
"fmt"
"time"
"cosmossdk.io/collections"
"cosmossdk.io/core/store"
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/log"
@ -21,20 +23,39 @@ import (
// Keeper manages state of all fee grants, as well as calculating approval.
// It must have a codec with all available allowances registered.
type Keeper struct {
cdc codec.BinaryCodec
storeService store.KVStoreService
authKeeper feegrant.AccountKeeper
bankKeeper feegrant.BankKeeper
cdc codec.BinaryCodec
storeService store.KVStoreService
authKeeper feegrant.AccountKeeper
bankKeeper feegrant.BankKeeper
Schema collections.Schema
FeeAllowance collections.Map[collections.Pair[sdk.AccAddress, sdk.AccAddress], feegrant.Grant]
FeeAllowanceQueue collections.Map[collections.Triple[time.Time, sdk.AccAddress, sdk.AccAddress], bool]
}
var _ ante.FeegrantKeeper = &Keeper{}
// NewKeeper creates a feegrant Keeper
func NewKeeper(cdc codec.BinaryCodec, storeService store.KVStoreService, ak feegrant.AccountKeeper) Keeper {
sb := collections.NewSchemaBuilder(storeService)
return Keeper{
cdc: cdc,
storeService: storeService,
authKeeper: ak,
FeeAllowance: collections.NewMap(
sb,
feegrant.FeeAllowanceKeyPrefix,
"allowances",
collections.PairKeyCodec(sdk.LengthPrefixedAddressKey(sdk.AccAddressKey), sdk.LengthPrefixedAddressKey(sdk.AccAddressKey)), // nolint: staticcheck // sdk.LengthPrefixedAddressKey is needed to retain state compatibility
codec.CollValue[feegrant.Grant](cdc),
),
FeeAllowanceQueue: collections.NewMap(
sb,
feegrant.FeeAllowanceQueueKeyPrefix,
"allowances_queue",
collections.TripleKeyCodec(sdk.TimeKey, sdk.LengthPrefixedAddressKey(sdk.AccAddressKey), sdk.LengthPrefixedAddressKey(sdk.AccAddressKey)), // nolint: staticcheck // sdk.LengthPrefixedAddressKey is needed to retain state compatibility
collections.BoolValue,
),
}
}
@ -68,9 +89,6 @@ func (k Keeper) GrantAllowance(ctx context.Context, granter, grantee sdk.AccAddr
k.authKeeper.SetAccount(ctx, granteeAcc)
}
store := k.storeService.OpenKVStore(ctx)
key := feegrant.FeeAllowanceKey(granter, grantee)
exp, err := feeAllowance.ExpiresAt()
if err != nil {
return err
@ -84,9 +102,7 @@ func (k Keeper) GrantAllowance(ctx context.Context, granter, grantee sdk.AccAddr
// if expiry is not nil, add the new key to pruning queue.
if exp != nil {
// `key` formed here with the prefix of `FeeAllowanceKeyPrefix` (which is `0x00`)
// remove the 1st byte and reuse the remaining key as it is
err = k.addToFeeAllowanceQueue(ctx, key[1:], exp)
err = k.FeeAllowanceQueue.Set(ctx, collections.Join3(*exp, grantee, granter), true)
if err != nil {
return err
}
@ -97,13 +113,7 @@ func (k Keeper) GrantAllowance(ctx context.Context, granter, grantee sdk.AccAddr
return err
}
bz, err := k.cdc.Marshal(&grant)
if err != nil {
return err
}
err = store.Set(key, bz)
if err != nil {
if err := k.FeeAllowance.Set(ctx, collections.Join(grantee, granter), grant); err != nil {
return err
}
@ -120,9 +130,6 @@ func (k Keeper) GrantAllowance(ctx context.Context, granter, grantee sdk.AccAddr
// UpdateAllowance updates the existing grant.
func (k Keeper) UpdateAllowance(ctx context.Context, granter, grantee sdk.AccAddress, feeAllowance feegrant.FeeAllowanceI) error {
store := k.storeService.OpenKVStore(ctx)
key := feegrant.FeeAllowanceKey(granter, grantee)
_, err := k.getGrant(ctx, granter, grantee)
if err != nil {
return err
@ -133,13 +140,7 @@ func (k Keeper) UpdateAllowance(ctx context.Context, granter, grantee sdk.AccAdd
return err
}
bz, err := k.cdc.Marshal(&grant)
if err != nil {
return err
}
err = store.Set(key, bz)
if err != nil {
if err := k.FeeAllowance.Set(ctx, collections.Join(grantee, granter), grant); err != nil {
return err
}
@ -161,9 +162,7 @@ func (k Keeper) revokeAllowance(ctx context.Context, granter, grantee sdk.AccAdd
return err
}
store := k.storeService.OpenKVStore(ctx)
key := feegrant.FeeAllowanceKey(granter, grantee)
err = store.Delete(key)
err = k.FeeAllowance.Remove(ctx, collections.Join(grantee, granter))
if err != nil {
return err
}
@ -174,7 +173,7 @@ func (k Keeper) revokeAllowance(ctx context.Context, granter, grantee sdk.AccAdd
}
if exp != nil {
if err := store.Delete(feegrant.FeeAllowancePrefixQueue(exp, feegrant.FeeAllowanceKey(grantee, granter)[1:])); err != nil {
if err := k.FeeAllowanceQueue.Remove(ctx, collections.Join3(*exp, grantee, granter)); err != nil {
return err
}
}
@ -193,7 +192,7 @@ func (k Keeper) revokeAllowance(ctx context.Context, granter, grantee sdk.AccAdd
// If there is none, it returns nil, nil.
// Returns an error on parsing issues
func (k Keeper) GetAllowance(ctx context.Context, granter, grantee sdk.AccAddress) (feegrant.FeeAllowanceI, error) {
grant, err := k.getGrant(ctx, granter, grantee)
grant, err := k.FeeAllowance.Get(ctx, collections.Join(grantee, granter))
if err != nil {
return nil, err
}
@ -203,22 +202,11 @@ func (k Keeper) GetAllowance(ctx context.Context, granter, grantee sdk.AccAddres
// getGrant returns entire grant between both accounts
func (k Keeper) getGrant(ctx context.Context, granter, grantee sdk.AccAddress) (*feegrant.Grant, error) {
store := k.storeService.OpenKVStore(ctx)
key := feegrant.FeeAllowanceKey(granter, grantee)
bz, err := store.Get(key)
feegrant, err := k.FeeAllowance.Get(ctx, collections.Join(grantee, granter))
if err != nil {
return nil, err
}
if len(bz) == 0 {
return nil, sdkerrors.ErrNotFound.Wrap("fee-grant not found")
}
var feegrant feegrant.Grant
if err := k.cdc.Unmarshal(bz, &feegrant); err != nil {
return nil, err
}
return &feegrant, nil
}
@ -230,14 +218,12 @@ func (k Keeper) IterateAllFeeAllowances(ctx context.Context, cb func(grant feegr
iter := storetypes.KVStorePrefixIterator(runtime.KVStoreAdapter(store), feegrant.FeeAllowanceKeyPrefix)
defer iter.Close()
stop := false
for ; iter.Valid() && !stop; iter.Next() {
bz := iter.Value()
var feeGrant feegrant.Grant
if err := k.cdc.Unmarshal(bz, &feeGrant); err != nil {
return err
}
stop = cb(feeGrant)
err := k.FeeAllowance.Walk(ctx, nil, func(key collections.Pair[sdk.AccAddress, sdk.AccAddress], grant feegrant.Grant) (stop bool, err error) {
return cb(grant), nil
})
if err != nil && !errors.Is(err, collections.ErrInvalidIterator) {
return err
}
return nil
@ -323,39 +309,39 @@ func (k Keeper) ExportGenesis(ctx context.Context) (*feegrant.GenesisState, erro
}, err
}
func (k Keeper) addToFeeAllowanceQueue(ctx context.Context, grantKey []byte, exp *time.Time) error {
store := k.storeService.OpenKVStore(ctx)
return store.Set(feegrant.FeeAllowancePrefixQueue(exp, grantKey), []byte{})
}
// RemoveExpiredAllowances iterates grantsByExpiryQueue and deletes the expired grants.
func (k Keeper) RemoveExpiredAllowances(ctx context.Context, limit int32) error {
exp := sdk.UnwrapSDKContext(ctx).BlockTime()
store := k.storeService.OpenKVStore(ctx)
iterator, err := store.Iterator(feegrant.FeeAllowanceQueueKeyPrefix, storetypes.InclusiveEndBytes(feegrant.AllowanceByExpTimeKey(&exp)))
var count int32
if err != nil {
return err
}
defer iterator.Close()
rng := collections.NewPrefixUntilTripleRange[time.Time, sdk.AccAddress, sdk.AccAddress](exp)
count := int32(0)
for ; iterator.Valid(); iterator.Next() {
err = store.Delete(iterator.Key())
if err != nil {
return err
keysToRemove := []collections.Triple[time.Time, sdk.AccAddress, sdk.AccAddress]{}
err := k.FeeAllowanceQueue.Walk(ctx, rng, func(key collections.Triple[time.Time, sdk.AccAddress, sdk.AccAddress], value bool) (stop bool, err error) {
grantee, granter := key.K2(), key.K3()
if err := k.FeeAllowance.Remove(ctx, collections.Join(grantee, granter)); err != nil {
return true, err
}
granter, grantee := feegrant.ParseAddressesFromFeeAllowanceQueueKey(iterator.Key())
err = store.Delete(feegrant.FeeAllowanceKey(granter, grantee))
if err != nil {
return err
}
keysToRemove = append(keysToRemove, key)
// limit the amount of iterations to avoid taking too much time
count++
if count == limit {
return nil
return true, nil
}
return false, nil
})
if err != nil && !errors.Is(err, collections.ErrInvalidIterator) {
return err
}
for _, key := range keysToRemove {
if err := k.FeeAllowanceQueue.Remove(ctx, key); err != nil {
return err
}
}
return nil
}

View File

@ -290,7 +290,7 @@ func (suite *KeeperTestSuite) TestUseGrantedFee() {
// verify: feegrant is revoked
_, err = suite.feegrantKeeper.GetAllowance(ctx, suite.addrs[0], suite.addrs[2])
suite.Error(err)
suite.Contains(err.Error(), "fee-grant not found")
suite.Contains(err.Error(), "not found")
}
func (suite *KeeperTestSuite) TestIterateGrants() {
@ -320,6 +320,7 @@ func (suite *KeeperTestSuite) TestIterateGrants() {
func (suite *KeeperTestSuite) TestPruneGrants() {
eth := sdk.NewCoins(sdk.NewInt64Coin("eth", 123))
now := suite.ctx.BlockTime()
oneDay := now.AddDate(0, 0, 1)
oneYearExpiry := now.AddDate(1, 0, 0)
testCases := []struct {
@ -333,24 +334,35 @@ func (suite *KeeperTestSuite) TestPruneGrants() {
postRun func()
}{
{
name: "grant not pruned from state",
ctx: suite.ctx,
granter: suite.addrs[0],
grantee: suite.addrs[1],
name: "grant pruned from state after a block: error",
ctx: suite.ctx,
granter: suite.addrs[0],
grantee: suite.addrs[1],
expErrMsg: "not found",
allowance: &feegrant.BasicAllowance{
SpendLimit: suite.atom,
Expiration: &now,
},
},
{
name: "grant pruned from state after a block: error",
name: "grant not pruned from state before expiration: no error",
ctx: suite.ctx,
granter: suite.addrs[2],
grantee: suite.addrs[1],
allowance: &feegrant.BasicAllowance{
SpendLimit: eth,
Expiration: &oneDay,
},
},
{
name: "grant pruned from state after a day: error",
ctx: suite.ctx.WithBlockTime(now.AddDate(0, 0, 1)),
granter: suite.addrs[2],
grantee: suite.addrs[1],
granter: suite.addrs[1],
grantee: suite.addrs[0],
expErrMsg: "not found",
allowance: &feegrant.BasicAllowance{
SpendLimit: eth,
Expiration: &now,
Expiration: &oneDay,
},
},
{
@ -365,7 +377,7 @@ func (suite *KeeperTestSuite) TestPruneGrants() {
},
{
name: "grant pruned from state after a year: error",
ctx: suite.ctx.WithBlockTime(now.AddDate(1, 0, 1)),
ctx: suite.ctx.WithBlockTime(now.AddDate(1, 0, 0)),
granter: suite.addrs[1],
grantee: suite.addrs[2],
expErrMsg: "not found",
@ -381,7 +393,6 @@ func (suite *KeeperTestSuite) TestPruneGrants() {
grantee: suite.addrs[2],
allowance: &feegrant.BasicAllowance{
SpendLimit: eth,
Expiration: &oneYearExpiry,
},
},
}
@ -401,6 +412,7 @@ func (suite *KeeperTestSuite) TestPruneGrants() {
suite.Error(err)
suite.Contains(err.Error(), tc.expErrMsg)
} else {
suite.NoError(err)
suite.NotNil(grant)
}
if tc.postRun != nil {

View File

@ -227,7 +227,7 @@ func (suite *KeeperTestSuite) TestRevokeAllowance() {
},
func() {},
true,
"fee-grant not found",
"not found",
},
{
"success: revoke fee allowance",
@ -269,7 +269,7 @@ func (suite *KeeperTestSuite) TestRevokeAllowance() {
},
func() {},
true,
"fee-grant not found",
"not found",
},
}

View File

@ -1,10 +1,7 @@
package feegrant
import (
time "time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
"cosmossdk.io/collections"
)
const (
@ -24,72 +21,9 @@ const (
var (
// FeeAllowanceKeyPrefix is the set of the kvstore for fee allowance data
// - 0x00<allowance_key_bytes>: allowance
FeeAllowanceKeyPrefix = []byte{0x00}
FeeAllowanceKeyPrefix = collections.NewPrefix(0)
// FeeAllowanceQueueKeyPrefix is the set of the kvstore for fee allowance keys data
// - 0x01<allowance_prefix_queue_key_bytes>: <empty value>
FeeAllowanceQueueKeyPrefix = []byte{0x01}
FeeAllowanceQueueKeyPrefix = collections.NewPrefix(1)
)
// FeeAllowanceKey is the canonical key to store a grant from granter to grantee
// We store by grantee first to allow searching by everyone who granted to you
//
// Key format:
// - <0x00><len(grantee_address_bytes)><grantee_address_bytes><len(granter_address_bytes)><granter_address_bytes>
func FeeAllowanceKey(granter, grantee sdk.AccAddress) []byte {
return append(FeeAllowancePrefixByGrantee(grantee), address.MustLengthPrefix(granter.Bytes())...)
}
// FeeAllowancePrefixByGrantee returns a prefix to scan for all grants to this given address.
//
// Key format:
// - <0x00><len(grantee_address_bytes)><grantee_address_bytes>
func FeeAllowancePrefixByGrantee(grantee sdk.AccAddress) []byte {
return append(FeeAllowanceKeyPrefix, address.MustLengthPrefix(grantee.Bytes())...)
}
// FeeAllowancePrefixQueue is the canonical key to store grant key.
//
// Key format:
// - <0x01><exp_bytes><len(grantee_address_bytes)><grantee_address_bytes><len(granter_address_bytes)><granter_address_bytes>
func FeeAllowancePrefixQueue(exp *time.Time, key []byte) []byte {
allowanceByExpTimeKey := AllowanceByExpTimeKey(exp)
return append(allowanceByExpTimeKey, key...)
}
// AllowanceByExpTimeKey returns a key with `FeeAllowanceQueueKeyPrefix`, expiry
//
// Key format:
// - <0x01><exp_bytes>
func AllowanceByExpTimeKey(exp *time.Time) []byte {
// no need of appending len(exp_bytes) here, `FormatTimeBytes` gives const length everytime.
return append(FeeAllowanceQueueKeyPrefix, sdk.FormatTimeBytes(*exp)...)
}
// ParseAddressesFromFeeAllowanceKey extracts and returns the granter, grantee from the given key.
func ParseAddressesFromFeeAllowanceKey(key []byte) (granter, grantee []byte) {
// key is of format:
// 0x00<granteeAddressLen (1 Byte)><granteeAddress_Bytes><granterAddressLen (1 Byte)><granterAddress_Bytes>
granterAddrLen, granterAddrLenEndIndex := sdk.ParseLengthPrefixedBytes(key, 1, 1) // ignore key[0] since it is a prefix key
grantee, granterAddrEndIndex := sdk.ParseLengthPrefixedBytes(key, granterAddrLenEndIndex+1, int(granterAddrLen[0]))
granteeAddrLen, granteeAddrLenEndIndex := sdk.ParseLengthPrefixedBytes(key, granterAddrEndIndex+1, 1)
granter, _ = sdk.ParseLengthPrefixedBytes(key, granteeAddrLenEndIndex+1, int(granteeAddrLen[0]))
return granter, grantee
}
// ParseAddressesFromFeeAllowanceQueueKey extracts and returns the granter, grantee from the given key.
func ParseAddressesFromFeeAllowanceQueueKey(key []byte) (granter, grantee []byte) {
lenTime := len(sdk.FormatTimeBytes(time.Now()))
// key is of format:
// <0x01><expiration_bytes(fixed length)><granteeAddressLen (1 Byte)><granteeAddress_Bytes><granterAddressLen (1 Byte)><granterAddress_Bytes>
granterAddrLen, granterAddrLenEndIndex := sdk.ParseLengthPrefixedBytes(key, 1+lenTime, 1) // ignore key[0] since it is a prefix key
grantee, granterAddrEndIndex := sdk.ParseLengthPrefixedBytes(key, granterAddrLenEndIndex+1, int(granterAddrLen[0]))
granteeAddrLen, granteeAddrLenEndIndex := sdk.ParseLengthPrefixedBytes(key, granterAddrEndIndex+1, 1)
granter, _ = sdk.ParseLengthPrefixedBytes(key, granteeAddrLenEndIndex+1, int(granteeAddrLen[0]))
return granter, grantee
}

View File

@ -1,47 +0,0 @@
package feegrant_test
import (
"testing"
"time"
"github.com/stretchr/testify/require"
"cosmossdk.io/x/feegrant"
codecaddress "github.com/cosmos/cosmos-sdk/codec/address"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func TestMarshalAndUnmarshalFeegrantKey(t *testing.T) {
addressCodec := codecaddress.NewBech32Codec("cosmos")
grantee, err := addressCodec.StringToBytes("cosmos1qk93t4j0yyzgqgt6k5qf8deh8fq6smpn3ntu3x")
require.NoError(t, err)
granter, err := addressCodec.StringToBytes("cosmos1p9qh4ldfd6n0qehujsal4k7g0e37kel90rc4ts")
require.NoError(t, err)
key := feegrant.FeeAllowanceKey(granter, grantee)
require.Len(t, key, len(grantee)+len(granter)+3)
require.Equal(t, feegrant.FeeAllowancePrefixByGrantee(grantee), key[:len(grantee)+2])
g1, g2 := feegrant.ParseAddressesFromFeeAllowanceKey(key)
require.Equal(t, granter, g1)
require.Equal(t, grantee, g2)
}
func TestMarshalAndUnmarshalFeegrantKeyQueueKey(t *testing.T) {
addressCodec := codecaddress.NewBech32Codec("cosmos")
grantee, err := addressCodec.StringToBytes("cosmos1qk93t4j0yyzgqgt6k5qf8deh8fq6smpn3ntu3x")
require.NoError(t, err)
granter, err := addressCodec.StringToBytes("cosmos1p9qh4ldfd6n0qehujsal4k7g0e37kel90rc4ts")
require.NoError(t, err)
exp := time.Now()
expBytes := sdk.FormatTimeBytes(exp)
key := feegrant.FeeAllowancePrefixQueue(&exp, feegrant.FeeAllowanceKey(granter, grantee)[1:])
require.Len(t, key, len(grantee)+len(granter)+3+len(expBytes))
granter1, grantee1 := feegrant.ParseAddressesFromFeeAllowanceQueueKey(key)
require.Equal(t, granter, granter1)
require.Equal(t, grantee, grantee1)
}

View File

@ -84,7 +84,7 @@ func TestFeegrantPruning(t *testing.T) {
})
require.NoError(t, err)
require.NotNil(t, res)
require.Len(t, res.Allowances, 3)
require.Len(t, res.Allowances, 2)
testCtx.Ctx = testCtx.Ctx.WithBlockTime(now.AddDate(0, 0, 2))
require.NoError(t, module.EndBlocker(testCtx.Ctx, feeGrantKeeper))