github.com/Finschia/finschia-sdk@v0.48.1/x/foundation/keeper/internal/censorship.go (about)

     1  package internal
     2  
     3  import (
     4  	sdk "github.com/Finschia/finschia-sdk/types"
     5  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
     6  	"github.com/Finschia/finschia-sdk/x/foundation"
     7  )
     8  
     9  func (k Keeper) GetCensorship(ctx sdk.Context, msgTypeURL string) (*foundation.Censorship, error) {
    10  	store := ctx.KVStore(k.storeKey)
    11  	key := censorshipKey(msgTypeURL)
    12  	bz := store.Get(key)
    13  	if bz == nil {
    14  		return nil, sdkerrors.ErrNotFound.Wrap("censorship not found")
    15  	}
    16  
    17  	var censorship foundation.Censorship
    18  	k.cdc.MustUnmarshal(bz, &censorship)
    19  
    20  	return &censorship, nil
    21  }
    22  
    23  func (k Keeper) UpdateCensorship(ctx sdk.Context, censorship foundation.Censorship) error {
    24  	url := censorship.MsgTypeUrl
    25  
    26  	oldCensorship, err := k.GetCensorship(ctx, url)
    27  	if err != nil {
    28  		return err
    29  	}
    30  
    31  	newAuthority := censorship.Authority
    32  	oldAuthority := oldCensorship.Authority
    33  	if newAuthority >= oldAuthority {
    34  		return sdkerrors.ErrInvalidRequest.Wrapf("bad transition; %s -> %s over %s", oldAuthority, newAuthority, url)
    35  	}
    36  
    37  	// clean up relevant authorizations
    38  	if newAuthority == foundation.CensorshipAuthorityUnspecified {
    39  		k.pruneAuthorizations(ctx, url)
    40  	}
    41  
    42  	k.SetCensorship(ctx, censorship)
    43  
    44  	return nil
    45  }
    46  
    47  func (k Keeper) SetCensorship(ctx sdk.Context, censorship foundation.Censorship) {
    48  	store := ctx.KVStore(k.storeKey)
    49  	key := censorshipKey(censorship.MsgTypeUrl)
    50  
    51  	if censorship.Authority == foundation.CensorshipAuthorityUnspecified {
    52  		store.Delete(key)
    53  		return
    54  	}
    55  
    56  	bz := k.cdc.MustMarshal(&censorship)
    57  	store.Set(key, bz)
    58  }
    59  
    60  func (k Keeper) iterateCensorships(ctx sdk.Context, fn func(censorship foundation.Censorship) (stop bool)) {
    61  	store := ctx.KVStore(k.storeKey)
    62  	iterator := sdk.KVStorePrefixIterator(store, censorshipKeyPrefix)
    63  	defer iterator.Close()
    64  
    65  	for ; iterator.Valid(); iterator.Next() {
    66  		var censorship foundation.Censorship
    67  		k.cdc.MustUnmarshal(iterator.Value(), &censorship)
    68  
    69  		if stop := fn(censorship); stop {
    70  			break
    71  		}
    72  	}
    73  }
    74  
    75  func (k Keeper) Grant(ctx sdk.Context, grantee sdk.AccAddress, authorization foundation.Authorization) error {
    76  	msgTypeURL := authorization.MsgTypeURL()
    77  	if !k.IsCensoredMessage(ctx, msgTypeURL) {
    78  		return sdkerrors.ErrInvalidRequest.Wrapf("%s is not being censored", msgTypeURL)
    79  	}
    80  
    81  	if _, err := k.GetAuthorization(ctx, grantee, msgTypeURL); err == nil {
    82  		return sdkerrors.ErrInvalidRequest.Wrapf("authorization for %s already exists", msgTypeURL)
    83  	}
    84  
    85  	k.setAuthorization(ctx, grantee, authorization)
    86  
    87  	any, err := foundation.SetAuthorization(authorization)
    88  	if err != nil {
    89  		return err
    90  	}
    91  
    92  	if err := ctx.EventManager().EmitTypedEvent(&foundation.EventGrant{
    93  		Grantee:       grantee.String(),
    94  		Authorization: any,
    95  	}); err != nil {
    96  		panic(err)
    97  	}
    98  
    99  	return nil
   100  }
   101  
   102  func (k Keeper) Revoke(ctx sdk.Context, grantee sdk.AccAddress, msgTypeURL string) error {
   103  	if _, err := k.GetAuthorization(ctx, grantee, msgTypeURL); err != nil {
   104  		return err
   105  	}
   106  	k.deleteAuthorization(ctx, grantee, msgTypeURL)
   107  
   108  	if err := ctx.EventManager().EmitTypedEvent(&foundation.EventRevoke{
   109  		Grantee:    grantee.String(),
   110  		MsgTypeUrl: msgTypeURL,
   111  	}); err != nil {
   112  		panic(err)
   113  	}
   114  
   115  	return nil
   116  }
   117  
   118  func (k Keeper) pruneAuthorizations(ctx sdk.Context, msgTypeURL string) {
   119  	var pruning []foundation.GrantAuthorization
   120  	k.iterateAuthorizations(ctx, func(grantee sdk.AccAddress, authorization foundation.Authorization) (stop bool) {
   121  		if authorization.MsgTypeURL() == msgTypeURL {
   122  			grant := foundation.GrantAuthorization{
   123  				Grantee: grantee.String(),
   124  			}.WithAuthorization(authorization)
   125  
   126  			pruning = append(pruning, *grant)
   127  		}
   128  		return false
   129  	})
   130  
   131  	for _, grant := range pruning {
   132  		k.deleteAuthorization(ctx, sdk.MustAccAddressFromBech32(grant.Grantee), grant.GetAuthorization().MsgTypeURL())
   133  	}
   134  }
   135  
   136  func (k Keeper) GetAuthorization(ctx sdk.Context, grantee sdk.AccAddress, msgTypeURL string) (foundation.Authorization, error) {
   137  	store := ctx.KVStore(k.storeKey)
   138  	key := grantKey(grantee, msgTypeURL)
   139  	bz := store.Get(key)
   140  	if bz == nil {
   141  		return nil, sdkerrors.ErrUnauthorized.Wrap("authorization not found")
   142  	}
   143  
   144  	var auth foundation.Authorization
   145  	if err := k.cdc.UnmarshalInterface(bz, &auth); err != nil {
   146  		panic(err)
   147  	}
   148  
   149  	return auth, nil
   150  }
   151  
   152  func (k Keeper) setAuthorization(ctx sdk.Context, grantee sdk.AccAddress, authorization foundation.Authorization) {
   153  	store := ctx.KVStore(k.storeKey)
   154  	key := grantKey(grantee, authorization.MsgTypeURL())
   155  
   156  	bz, err := k.cdc.MarshalInterface(authorization)
   157  	if err != nil {
   158  		panic(err)
   159  	}
   160  	store.Set(key, bz)
   161  }
   162  
   163  func (k Keeper) deleteAuthorization(ctx sdk.Context, grantee sdk.AccAddress, msgTypeURL string) {
   164  	store := ctx.KVStore(k.storeKey)
   165  	key := grantKey(grantee, msgTypeURL)
   166  	store.Delete(key)
   167  }
   168  
   169  func (k Keeper) Accept(ctx sdk.Context, grantee sdk.AccAddress, msg sdk.Msg) error {
   170  	msgTypeURL := sdk.MsgTypeURL(msg)
   171  
   172  	// check whether the msg is being censored
   173  	if !k.IsCensoredMessage(ctx, msgTypeURL) {
   174  		return nil
   175  	}
   176  
   177  	authorization, err := k.GetAuthorization(ctx, grantee, msgTypeURL)
   178  	if err != nil {
   179  		return err
   180  	}
   181  
   182  	resp, err := authorization.Accept(ctx, msg)
   183  	if err != nil {
   184  		return err
   185  	}
   186  
   187  	if resp.Delete {
   188  		k.deleteAuthorization(ctx, grantee, msgTypeURL)
   189  	} else if resp.Updated != nil {
   190  		k.setAuthorization(ctx, grantee, resp.Updated)
   191  	}
   192  
   193  	if !resp.Accept {
   194  		return sdkerrors.ErrUnauthorized
   195  	}
   196  
   197  	return nil
   198  }
   199  
   200  func (k Keeper) iterateAuthorizations(ctx sdk.Context, fn func(grantee sdk.AccAddress, authorization foundation.Authorization) (stop bool)) {
   201  	k.iterateAuthorizationsImpl(ctx, grantKeyPrefix, fn)
   202  }
   203  
   204  func (k Keeper) iterateAuthorizationsImpl(ctx sdk.Context, prefix []byte, fn func(grantee sdk.AccAddress, authorization foundation.Authorization) (stop bool)) {
   205  	store := ctx.KVStore(k.storeKey)
   206  	iterator := sdk.KVStorePrefixIterator(store, prefix)
   207  	defer iterator.Close()
   208  
   209  	for ; iterator.Valid(); iterator.Next() {
   210  		var authorization foundation.Authorization
   211  		if err := k.cdc.UnmarshalInterface(iterator.Value(), &authorization); err != nil {
   212  			panic(err)
   213  		}
   214  
   215  		grantee, _ := splitGrantKey(iterator.Key())
   216  		if stop := fn(grantee, authorization); stop {
   217  			break
   218  		}
   219  	}
   220  }