Skip to content

Commit

Permalink
review changes
Browse files Browse the repository at this point in the history
  • Loading branch information
atheeshp committed May 22, 2024
1 parent 7c4fab8 commit 62db0e7
Show file tree
Hide file tree
Showing 20 changed files with 1,471 additions and 1,235 deletions.
1,463 changes: 834 additions & 629 deletions api/cosmos/authz/v1beta1/authz.pulsar.go

Large diffs are not rendered by default.

274 changes: 175 additions & 99 deletions api/cosmos/authz/v1beta1/tx.pulsar.go

Large diffs are not rendered by default.

46 changes: 7 additions & 39 deletions proto/cosmos/authz/v1beta1/authz.proto
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ message Grant {
google.protobuf.Timestamp expiration = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = true];

// rules are conditions to execute the grant.
bytes rules = 3;
repeated Rule rules = 3;
}

// rules are conditions to execute the grant.
message Rule {
string key = 1;
repeated string values = 2;
}

// GrantAuthorization extends a grant with both the addresses of the grantee and granter.
Expand All @@ -50,41 +56,3 @@ message GrantQueueItem {
// msg_type_urls contains the list of TypeURL of a sdk.Msg.
repeated string msg_type_urls = 1;
}

// // AuthzRules defines the rules for authz messages.
// message AuthzRules {
// // Send authz rules
// SendAuthzRules send = 1 [(gogoproto.nullable) = false];

// // Stake authz rules
// StakeAuthzRules stake = 2 [(gogoproto.nullable) = false];

// // Generic authz rules
// GenericAuthzRules generic = 3 [(gogoproto.nullable) = false];
// }

// // Send authz rules
// message SendAuthzRules {
// repeated cosmos.base.v1beta1.Coin spend_limit = 1 [
// (gogoproto.nullable) = false,
// (amino.dont_omitempty) = true,
// (amino.encoding) = "legacy_coins",
// (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
// ];
// repeated string blocked_recipients = 2;
// }

// // Stake authz rules
// message StakeAuthzRules {
// repeated string blocked_validators = 1;
// }

// // Generic authz rules
// message GenericAuthzRules {
// repeated string blocked_messages = 1;
// }

// AuthzRuleKeys is app specific options to the keys
message AuthzRuleKeys {
bytes raw_json = 1;
}
2 changes: 1 addition & 1 deletion proto/cosmos/authz/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ message MsgGrant {
cosmos.authz.v1beta1.Grant grant = 3 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true];

// rules are conditions to execute the grant.
bytes rules = 4;
repeated cosmos.authz.v1beta1.Rule rules = 4;
}

// MsgGrantResponse defines the Msg/MsgGrant response type.
Expand Down
79 changes: 54 additions & 25 deletions x/auth/ante/authz_rules_ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ante
import (
"strings"

stakingv1beta1 "cosmossdk.io/api/cosmos/staking/v1beta1"
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
Expand All @@ -11,11 +12,6 @@ import (
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
)

const (
AllowedRecipients = "allowed_recipients"
MaxAmount = "max_amount"
)

type AuthzDecorator struct {
azk AuthzKeeper
ak AccountKeeper
Expand Down Expand Up @@ -59,7 +55,13 @@ func (azd AuthzDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool,
if isRulesBroken {
return ctx, err
}
case *stakingv1beta1.MsgDelegate:
isRulesBroken, err := azd.handleStakeAuthzRules(ctx, innerMsgConverted, grantee)
if isRulesBroken {
return ctx, err
}
}

}
}
}
Expand All @@ -77,12 +79,10 @@ func (azd AuthzDecorator) handleSendAuthzRules(ctx sdk.Context, msg *banktypes.M
}

_, rules := azd.azk.GetAuthzWithRules(ctx, grantee, granter, sdk.MsgTypeURL(&banktypes.MsgSend{}))
if rules != nil {
if allowedAddrs, ok := rules[AllowedRecipients]; ok {
allowedAddrsValue := allowedAddrs.(string)
allowedAddrs := strings.Split(allowedAddrsValue, ",")
for _, rule := range rules {
if rule.Key == authztypes.AllowedRecipients {
isAllowed := false
for _, allowedRecipient := range allowedAddrs {
for _, allowedRecipient := range rule.Values {
if msg.ToAddress == allowedRecipient {
isAllowed = true
break
Expand All @@ -94,30 +94,59 @@ func (azd AuthzDecorator) handleSendAuthzRules(ctx sdk.Context, msg *banktypes.M
}
}

if spendLimitInterface, ok := rules[MaxAmount]; ok {
spendLimit := spendLimitInterface.(string)
limit, err := sdk.ParseCoinsNormalized(spendLimit)
if rule.Key == authztypes.MaxAmount {
limit, err := sdk.ParseCoinsNormalized(strings.Join(rule.Values, ","))
if err != nil {
return true, err
}
if !limit.IsAllGTE(msg.Amount) {
return true, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Amount exceeds the max_amount limit set by the granter")
}
}

}

return false, nil
}

// func checkGenericAuthzRules(_ *authztypes.MsgGrant, authz *authztypes.GenericAuthorization, genericRules map[string]string) bool {
// if msgsStr, ok := genericRules["blockedMessages"]; ok {
// msgs := strings.Split(msgsStr, ",")
// for _, v := range msgs {
// if v == authz.Msg {
// return true
// }
// }
// }

// return false
// }
func (azd AuthzDecorator) handleStakeAuthzRules(ctx sdk.Context, msg *stakingv1beta1.MsgDelegate, grantee []byte) (bool, error) {
granter, err := azd.ak.AddressCodec().StringToBytes(msg.DelegatorAddress)
if err != nil {
return true, err
}

_, rules := azd.azk.GetAuthzWithRules(ctx, grantee, granter, sdk.MsgTypeURL(&banktypes.MsgSend{}))

for _, rule := range rules {
if rule.Key == authztypes.AllowedStakeValidators {
isAllowed := false
for _, allowedValidator := range rule.Values {
if msg.ValidatorAddress == allowedValidator {
isAllowed = true
break
}
}

if !isAllowed {
return true, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Validator is not in the allowed validators of the grant")
}
}

if rule.Key == authztypes.AllowedMaxStakeAmount {
limit, err := sdk.ParseCoinsNormalized(strings.Join(rule.Values, ","))
if err != nil {
return true, err
}
amount, err := sdk.ParseCoinNormalized(msg.Amount.String())
if err != nil {
return true, err
}

if !limit.IsAllGTE(sdk.NewCoins(amount)) {
return true, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Amount exceeds the max_amount limit set by the granter")
}
}
}

return false, nil
}
4 changes: 1 addition & 3 deletions x/auth/ante/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,5 @@ type FeegrantKeeper interface {
}

type AuthzKeeper interface {
GetAuthzOptions() map[string]map[string]string
GetAuthzRulesKeys(ctx context.Context) (map[string]interface{}, error)
GetAuthzWithRules(ctx context.Context, grantee, granter sdk.AccAddress, msgType string) (authz.Authorization, map[string]interface{})
GetAuthzWithRules(ctx context.Context, grantee, granter sdk.AccAddress, msgType string) (authz.Authorization, []*authz.Rule)
}
21 changes: 1 addition & 20 deletions x/authz/authorization_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,7 @@ import (
// NewGrant returns new Grant. Expiration is optional and noop if null.
// It returns an error if the expiration is before the current block time,
// which is passed into the `blockTime` arg.
func NewGrant(blockTime time.Time, a Authorization, expiration *time.Time) (Grant, error) {
if expiration != nil && !expiration.After(blockTime) {
return Grant{}, errorsmod.Wrapf(ErrInvalidExpirationTime, "expiration must be after the current block time (%v), got %v", blockTime.Format(time.RFC3339), expiration.Format(time.RFC3339))
}
msg, ok := a.(proto.Message)
if !ok {
return Grant{}, sdkerrors.ErrPackAny.Wrapf("cannot proto marshal %T", a)
}
any, err := cdctypes.NewAnyWithValue(msg)
if err != nil {
return Grant{}, err
}
return Grant{
Expiration: expiration,
Authorization: any,
}, nil
}

// NewGrantWithRules does the same as NewGrant but takes rules as extra arg.
func NewGrantWithRules(blockTime time.Time, a Authorization, expiration *time.Time, rules []byte) (Grant, error) {
func NewGrant(blockTime time.Time, a Authorization, expiration *time.Time, rules []*Rule) (Grant, error) {
if expiration != nil && !expiration.After(blockTime) {
return Grant{}, errorsmod.Wrapf(ErrInvalidExpirationTime, "expiration must be after the current block time (%v), got %v", blockTime.Format(time.RFC3339), expiration.Format(time.RFC3339))
}
Expand Down
4 changes: 0 additions & 4 deletions x/authz/authorizations.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package authz

import (
context "context"
"encoding/json"

"github.com/cosmos/gogoproto/proto"

Expand All @@ -25,9 +24,6 @@ type Authorization interface {
// ValidateBasic does a simple validation check that
// doesn't require access to any other information.
ValidateBasic() error

// GetOptions are, rules defined if any.
GetOptions() json.RawMessage
}

// AcceptResponse instruments the controller of an authz message if the request is accepted
Expand Down
Loading

0 comments on commit 62db0e7

Please sign in to comment.