Skip to content

Commit

Permalink
Added fee grant interfaces to std
Browse files Browse the repository at this point in the history
  • Loading branch information
Sahith Reddy Narahari committed Mar 17, 2020
1 parent 1fe2ebb commit 59eef6c
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 58 deletions.
29 changes: 29 additions & 0 deletions codec/std/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
"github.com/cosmos/cosmos-sdk/x/evidence"
eviexported "github.com/cosmos/cosmos-sdk/x/evidence/exported"
"github.com/cosmos/cosmos-sdk/x/feegrant"
"github.com/cosmos/cosmos-sdk/x/feegrant/exported"
feegrantexported "github.com/cosmos/cosmos-sdk/x/feegrant/exported"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/supply"
supplyexported "github.com/cosmos/cosmos-sdk/x/supply/exported"
Expand All @@ -19,6 +22,7 @@ var (
_ supply.Codec = (*Codec)(nil)
_ evidence.Codec = (*Codec)(nil)
_ gov.Codec = (*Codec)(nil)
_ feegrant.Codec = (*Codec)(nil)
)

// Codec defines the application-level codec. This codec contains all the
Expand Down Expand Up @@ -180,6 +184,31 @@ func (c *Codec) UnmarshalProposal(bz []byte) (gov.Proposal, error) {
}, nil
}

func (c *Codec) MarshalFeeAllowanceGrant(feeAllowanceI exported.FeeAllowanceGrant) ([]byte, error) {
feeallowance := &FeeAllowance{}

if err := feeallowance.SetFeeAllowance(feeAllowanceI.GetFeeGrant()); err != nil {
return nil, err
}

grantFeeAllowance := &FeeAllowanceGrant{
Allowance: feeallowance,
FeeAllowanceGrantBase: feegrant.NewFeeAllowanceGrantBase(feeAllowanceI.GetGranter(), feeAllowanceI.GetGrantee()),
}

return c.Marshaler.MarshalBinaryBare(grantFeeAllowance)
}

func (c *Codec) UnmarshalFeeAllowanceGrant(bz []byte) (feegrantexported.FeeAllowanceGrant, error) {
feeallowance := &FeeAllowanceGrant{}

if err := c.Marshaler.UnmarshalBinaryBare(bz, feeallowance); err != nil {
return nil, err
}

return feeallowance, nil
}

// ----------------------------------------------------------------------------
// necessary types and interfaces registered. This codec is provided to all the
// modules the application depends on.
Expand Down
47 changes: 43 additions & 4 deletions codec/std/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/evidence"
eviexported "github.com/cosmos/cosmos-sdk/x/evidence/exported"
"github.com/cosmos/cosmos-sdk/x/feegrant/exported"
"github.com/cosmos/cosmos-sdk/x/feegrant"
feeexported "github.com/cosmos/cosmos-sdk/x/feegrant/exported"
"github.com/cosmos/cosmos-sdk/x/gov"
)

var (
_ eviexported.MsgSubmitEvidence = MsgSubmitEvidence{}
_ gov.MsgSubmitProposalI = MsgSubmitProposal{}
_ eviexported.MsgSubmitEvidence = MsgSubmitEvidence{}
_ gov.MsgSubmitProposalI = MsgSubmitProposal{}
_ feeexported.MsgGrantFeeAllowance = MsgGrantFeeAllowance{}
)

// NewMsgSubmitEvidence returns a new MsgSubmitEvidence.
Expand Down Expand Up @@ -84,11 +86,48 @@ func (msg MsgSubmitProposal) GetContent() gov.Content { return msg.Content.
func (msg MsgSubmitProposal) GetInitialDeposit() sdk.Coins { return msg.InitialDeposit }
func (msg MsgSubmitProposal) GetProposer() sdk.AccAddress { return msg.Proposer }

func (msg MsgGrantFeeAllowance) NewMsgGrantFeeAllowance(feeAllowanceI feeexported.FeeAllowance, granter, grantee sdk.AccAddress) (MsgGrantFeeAllowance, error) {
feeallowance := &FeeAllowance{}

if err := feeallowance.SetFeeAllowance(feeAllowanceI); err != nil {
return MsgGrantFeeAllowance{}, err
}

return MsgGrantFeeAllowance{
Allowance: feeallowance,
MsgGrantFeeAllowanceBase: feegrant.NewMsgGrantFeeAllowanceBase(granter, grantee),
}, nil
}

func (msg MsgGrantFeeAllowance) ValidateBasic() error {
//TODO
return nil
}

func (msg MsgGrantFeeAllowance) GetEvidence() exported.FeeAllowance {
func (msg MsgGrantFeeAllowance) GetFeeGrant() feeexported.FeeAllowance {
return msg.Allowance.GetFeeAllowance()
}

func (msg MsgGrantFeeAllowance) GetGrantee() sdk.AccAddress {
return msg.Grantee
}

func (msg MsgGrantFeeAllowance) GetGranter() sdk.AccAddress {
return msg.Granter
}

func (grant FeeAllowanceGrant) ValidateBasic() error {
return nil
}

func (grant FeeAllowanceGrant) GetFeeGrant() feeexported.FeeAllowance {
return grant.Allowance.GetFeeAllowance()
}

func (grant FeeAllowanceGrant) GetGrantee() sdk.AccAddress {
return grant.Grantee
}

func (grant FeeAllowanceGrant) GetGranter() sdk.AccAddress {
return grant.Granter
}
8 changes: 5 additions & 3 deletions x/feegrant/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ var (
BlockDuration = types.BlockDuration
FeeAllowanceKey = types.FeeAllowanceKey
FeeAllowancePrefixByGrantee = types.FeeAllowancePrefixByGrantee
NewMsgGrantFeeAllowance = types.NewMsgGrantFeeAllowance
NewMsgRevokeFeeAllowance = types.NewMsgRevokeFeeAllowance
NewFeeGrantTx = types.NewFeeGrantTx
NewMsgGrantFeeAllowanceBase = types.NewMsgGrantFeeAllowanceBase
NewFeeAllowanceGrantBase = types.NewFeeAllowanceGrantBase
CountSubKeys = types.CountSubKeys
NewGrantedFee = types.NewGrantedFee
StdSignBytes = types.StdSignBytes
Expand All @@ -54,12 +55,13 @@ type (
BasicFeeAllowance = types.BasicFeeAllowance
ExpiresAt = types.ExpiresAt
Duration = types.Duration
FeeAllowanceGrant = types.FeeAllowanceGrant
MsgGrantFeeAllowance = types.MsgGrantFeeAllowance
FeeAllowanceGrantBase = types.FeeAllowanceGrantBase
MsgGrantFeeAllowanceBase = types.MsgGrantFeeAllowanceBase
MsgRevokeFeeAllowance = types.MsgRevokeFeeAllowance
PeriodicFeeAllowance = types.PeriodicFeeAllowance
FeeGrantTx = types.FeeGrantTx
GrantedFee = types.GrantedFee
DelegatedSignDoc = types.DelegatedSignDoc
Keeper = keeper.Keeper
Codec = types.Codec
)
4 changes: 1 addition & 3 deletions x/feegrant/exported/external.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type AccountKeeper interface {
SetAccount(ctx sdk.Context, acc auth.Account)
}

type MsgGrantAuthorization interface {
type MsgGrantFeeAllowance interface {
sdk.Msg

GetFeeGrant() FeeAllowance
Expand All @@ -29,8 +29,6 @@ type MsgGrantAuthorization interface {
}

type FeeAllowanceGrant interface {
sdk.Msg

GetFeeGrant() FeeAllowance
GetGranter() sdk.AccAddress
GetGrantee() sdk.AccAddress
Expand Down
13 changes: 9 additions & 4 deletions x/feegrant/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,32 @@ package feegrant
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/feegrant/exported"
)

func NewHandler(k Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
ctx = ctx.WithEventManager(sdk.NewEventManager())

switch msg := msg.(type) {
case MsgGrantFeeAllowance:
return handleGrantFee(ctx, k, msg)
case MsgGrantFeeAllowanceBase:
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "%T must be extended to support feegrant", msg)

case MsgRevokeFeeAllowance:
return handleRevokeFee(ctx, k, msg)

default:
msgGrantFa, ok := msg.(exported.MsgGrantFeeAllowance)
if ok {
return handleGrantFee(ctx, k, msgGrantFa)
}
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg)
}
}
}

func handleGrantFee(ctx sdk.Context, k Keeper, msg MsgGrantFeeAllowance) (*sdk.Result, error) {
grant := FeeAllowanceGrant(msg)
func handleGrantFee(ctx sdk.Context, k Keeper, msg exported.MsgGrantFeeAllowance) (*sdk.Result, error) {
grant := exported.FeeAllowanceGrant(msg)
k.GrantFeeAllowance(ctx, grant)
return &sdk.Result{Events: ctx.EventManager().Events()}, nil
}
Expand Down
48 changes: 25 additions & 23 deletions x/feegrant/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ import (

"github.com/tendermint/tendermint/libs/log"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/feegrant/exported"
"github.com/cosmos/cosmos-sdk/x/feegrant/types"
)

// 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.Marshaler
cdc types.Codec
storeKey sdk.StoreKey
}

// NewKeeper creates a fee grant Keeper
func NewKeeper(cdc codec.Marshaler, storeKey sdk.StoreKey) Keeper {
func NewKeeper(cdc types.Codec, storeKey sdk.StoreKey) Keeper {
return Keeper{cdc: cdc, storeKey: storeKey}
}

Expand All @@ -29,18 +29,20 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger {
}

// GrantFeeAllowance creates a new grant
func (k Keeper) GrantFeeAllowance(ctx sdk.Context, grant types.FeeAllowanceGrant) {
func (k Keeper) GrantFeeAllowance(ctx sdk.Context, grant exported.FeeAllowanceGrant) {
store := ctx.KVStore(k.storeKey)
key := types.FeeAllowanceKey(grant.Granter, grant.Grantee)
bz := k.cdc.MustMarshalBinaryBare(&grant)

key := types.FeeAllowanceKey(grant.GetGranter(), grant.GetGrantee())
bz, err := k.cdc.MarshalFeeAllowanceGrant(grant)
if err != nil {
panic(fmt.Errorf("failed to encode fee allowance: %w", err))
}
store.Set(key, bz)

ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSetFeeGrant,
sdk.NewAttribute(types.AttributeKeyGranter, grant.Granter.String()),
sdk.NewAttribute(types.AttributeKeyGrantee, grant.Grantee.String()),
sdk.NewAttribute(types.AttributeKeyGranter, grant.GetGranter().String()),
sdk.NewAttribute(types.AttributeKeyGrantee, grant.GetGrantee().String()),
),
)
}
Expand All @@ -64,33 +66,35 @@ func (k Keeper) RevokeFeeAllowance(ctx sdk.Context, granter, grantee sdk.AccAddr
// GetFeeAllowance returns the allowance between the granter and grantee.
// If there is none, it returns nil, nil.
// Returns an error on parsing issues
func (k Keeper) GetFeeAllowance(ctx sdk.Context, granter, grantee sdk.AccAddress) *types.FeeAllowance {
func (k Keeper) GetFeeAllowance(ctx sdk.Context, granter, grantee sdk.AccAddress) exported.FeeAllowance {
grant, found := k.GetFeeGrant(ctx, granter, grantee)
if !found {
return nil
}

return grant.Allowance
return grant.GetFeeGrant()
}

// GetFeeGrant returns entire grant between both accounts
func (k Keeper) GetFeeGrant(ctx sdk.Context, granter sdk.AccAddress, grantee sdk.AccAddress) (types.FeeAllowanceGrant, bool) {
func (k Keeper) GetFeeGrant(ctx sdk.Context, granter sdk.AccAddress, grantee sdk.AccAddress) (exported.FeeAllowanceGrant, bool) {
store := ctx.KVStore(k.storeKey)
key := types.FeeAllowanceKey(granter, grantee)
bz := store.Get(key)
if len(bz) == 0 {
return types.FeeAllowanceGrant{}, false
return nil, false
}

var grant types.FeeAllowanceGrant
k.cdc.MustUnmarshalBinaryBare(bz, &grant)
grant, err := k.cdc.UnmarshalFeeAllowanceGrant(bz)
if err != nil {
return nil, false
}

return grant, true
}

// IterateAllGranteeFeeAllowances iterates over all the grants from anyone to the given grantee.
// Callback to get all data, returns true to stop, false to keep reading
func (k Keeper) IterateAllGranteeFeeAllowances(ctx sdk.Context, grantee sdk.AccAddress, cb func(types.FeeAllowanceGrant) bool) error {
func (k Keeper) IterateAllGranteeFeeAllowances(ctx sdk.Context, grantee sdk.AccAddress, cb func(exported.FeeAllowanceGrant) bool) error {
store := ctx.KVStore(k.storeKey)
prefix := types.FeeAllowancePrefixByGrantee(grantee)
iter := sdk.KVStorePrefixIterator(store, prefix)
Expand All @@ -99,9 +103,8 @@ func (k Keeper) IterateAllGranteeFeeAllowances(ctx sdk.Context, grantee sdk.AccA
stop := false
for ; iter.Valid() && !stop; iter.Next() {
bz := iter.Value()
var grant types.FeeAllowanceGrant

err := k.cdc.UnmarshalBinaryBare(bz, &grant)
grant, err := k.cdc.UnmarshalFeeAllowanceGrant(bz)
if err != nil {
return err
}
Expand All @@ -115,17 +118,16 @@ func (k Keeper) IterateAllGranteeFeeAllowances(ctx sdk.Context, grantee sdk.AccA
// IterateAllFeeAllowances iterates over all the grants in the store.
// Callback to get all data, returns true to stop, false to keep reading
// Calling this without pagination is very expensive and only designed for export genesis
func (k Keeper) IterateAllFeeAllowances(ctx sdk.Context, cb func(types.FeeAllowanceGrant) bool) error {
func (k Keeper) IterateAllFeeAllowances(ctx sdk.Context, cb func(exported.FeeAllowanceGrant) bool) error {
store := ctx.KVStore(k.storeKey)
iter := sdk.KVStorePrefixIterator(store, types.FeeAllowanceKeyPrefix)
defer iter.Close()

stop := false
for ; iter.Valid() && !stop; iter.Next() {
bz := iter.Value()
var grant types.FeeAllowanceGrant

err := k.cdc.UnmarshalBinaryBare(bz, &grant)
grant, err := k.cdc.UnmarshalFeeAllowanceGrant(bz)
if err != nil {
return err
}
Expand All @@ -139,11 +141,11 @@ func (k Keeper) IterateAllFeeAllowances(ctx sdk.Context, cb func(types.FeeAllowa
// UseGrantedFees will try to pay the given fee from the granter's account as requested by the grantee
func (k Keeper) UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress, fee sdk.Coins) error {
grant, found := k.GetFeeGrant(ctx, granter, grantee)
if !found || grant.Allowance == nil {
if !found || grant.GetFeeGrant() == nil {
return sdkerrors.Wrapf(types.ErrNoAllowance, "grant missing")
}

remove, err := grant.GetAllowance().GetFeeAllowance().Accept(fee, ctx.BlockTime(), ctx.BlockHeight())
remove, err := grant.GetFeeGrant().Accept(fee, ctx.BlockTime(), ctx.BlockHeight())
if err == nil {
ctx.EventManager().EmitEvent(
sdk.NewEvent(
Expand Down
18 changes: 7 additions & 11 deletions x/feegrant/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,21 +73,17 @@ func (suite *KeeperTestSuite) TestKeeperCrud() {
// some helpers
atom := sdk.NewCoins(sdk.NewInt64Coin("atom", 555))
eth := sdk.NewCoins(sdk.NewInt64Coin("eth", 123))
basic := types.FeeAllowance_BasicFeeAllowance{
BasicFeeAllowance: &types.BasicFeeAllowance{
SpendLimit: atom,
Expiration: types.ExpiresAtHeight(334455),
},
basic := &types.BasicFeeAllowance{
SpendLimit: atom,
Expiration: types.ExpiresAtHeight(334455),
}
basic2 := types.FeeAllowance_BasicFeeAllowance{
BasicFeeAllowance: &types.BasicFeeAllowance{
SpendLimit: eth,
Expiration: types.ExpiresAtHeight(172436),
},
basic2 := &types.BasicFeeAllowance{
SpendLimit: eth,
Expiration: types.ExpiresAtHeight(172436),
}

// let's set up some initial state here
k.GrantFeeAllowance(ctx, types.FeeAllowanceGrant{
k.GrantFeeAllowance(ctx, std.FeeAllowanceGrant{
Granter: suite.addr, Grantee: suite.addr2, Allowance: &types.FeeAllowance{Sum: &basic},
})
k.GrantFeeAllowance(ctx, types.FeeAllowanceGrant{
Expand Down
8 changes: 8 additions & 0 deletions x/feegrant/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ import (
"github.com/cosmos/cosmos-sdk/x/feegrant/exported"
)

// Codec defines the interface required to serialize custom x/gov types.
type Codec interface {
codec.Marshaler

MarshalFeeAllowanceGrant(exported.FeeAllowanceGrant) ([]byte, error)
UnmarshalFeeAllowanceGrant([]byte) (exported.FeeAllowanceGrant, error)
}

// RegisterCodec registers the account types and interface
func RegisterCodec(cdc *codec.Codec) {
cdc.RegisterInterface((*exported.FeeAllowance)(nil), nil)
Expand Down
Loading

0 comments on commit 59eef6c

Please sign in to comment.