github.com/KiraCore/sekai@v0.3.43/app/ante/ante.go (about)

     1  package ante
     2  
     3  import (
     4  	"crypto/sha256"
     5  	"encoding/hex"
     6  	"fmt"
     7  	"time"
     8  
     9  	kiratypes "github.com/KiraCore/sekai/types"
    10  	custodykeeper "github.com/KiraCore/sekai/x/custody/keeper"
    11  	custodytypes "github.com/KiraCore/sekai/x/custody/types"
    12  	feeprocessingkeeper "github.com/KiraCore/sekai/x/feeprocessing/keeper"
    13  	feeprocessingtypes "github.com/KiraCore/sekai/x/feeprocessing/types"
    14  	customgovkeeper "github.com/KiraCore/sekai/x/gov/keeper"
    15  	customstakingkeeper "github.com/KiraCore/sekai/x/staking/keeper"
    16  	tokenskeeper "github.com/KiraCore/sekai/x/tokens/keeper"
    17  	sdk "github.com/cosmos/cosmos-sdk/types"
    18  	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
    19  	"github.com/cosmos/cosmos-sdk/x/auth/ante"
    20  	"github.com/cosmos/cosmos-sdk/x/auth/keeper"
    21  	"github.com/cosmos/cosmos-sdk/x/auth/signing"
    22  	"github.com/cosmos/cosmos-sdk/x/auth/types"
    23  	bank "github.com/cosmos/cosmos-sdk/x/bank/types"
    24  )
    25  
    26  // NewAnteHandler returns an AnteHandler that checks and increments sequence
    27  // numbers, checks signatures & account numbers, and deducts fees from the first
    28  // signer.
    29  func NewAnteHandler(
    30  	sk customstakingkeeper.Keeper,
    31  	cgk customgovkeeper.Keeper,
    32  	tk tokenskeeper.Keeper,
    33  	fk feeprocessingkeeper.Keeper,
    34  	ak keeper.AccountKeeper,
    35  	bk types.BankKeeper,
    36  	ck custodykeeper.Keeper,
    37  	feegrantKeeper ante.FeegrantKeeper,
    38  	extensionOptionChecker ante.ExtensionOptionChecker,
    39  	sigGasConsumer ante.SignatureVerificationGasConsumer,
    40  	signModeHandler signing.SignModeHandler,
    41  	txFeeChecker ante.TxFeeChecker,
    42  ) sdk.AnteHandler {
    43  	return sdk.ChainAnteDecorators(
    44  		ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
    45  		NewCustodyDecorator(ck, cgk),
    46  		NewZeroGasMeterDecorator(),
    47  		ante.NewExtensionOptionsDecorator(extensionOptionChecker),
    48  		ante.NewValidateBasicDecorator(),
    49  		ante.TxTimeoutHeightDecorator{},
    50  		ante.NewValidateMemoDecorator(ak),
    51  		ante.NewConsumeGasForTxSizeDecorator(ak),
    52  		// custom fee range validator
    53  		NewValidateFeeRangeDecorator(sk, cgk, tk, ak),
    54  		ante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators
    55  		ante.NewValidateSigCountDecorator(ak),
    56  		ante.NewDeductFeeDecorator(ak, bk, feegrantKeeper, txFeeChecker),
    57  		// poor network management decorator
    58  		NewPoorNetworkManagementDecorator(ak, cgk, sk),
    59  		NewBlackWhiteTokensCheckDecorator(cgk, sk, tk),
    60  		// custom execution fee consume decorator
    61  		NewExecutionFeeRegistrationDecorator(ak, cgk, fk),
    62  		ante.NewSigGasConsumeDecorator(ak, sigGasConsumer),
    63  		ante.NewSigVerificationDecorator(ak, signModeHandler),
    64  		ante.NewIncrementSequenceDecorator(ak),
    65  	)
    66  }
    67  
    68  type CustodyDecorator struct {
    69  	ck custodykeeper.Keeper
    70  	gk customgovkeeper.Keeper
    71  }
    72  
    73  func NewCustodyDecorator(ck custodykeeper.Keeper, gk customgovkeeper.Keeper) CustodyDecorator {
    74  	return CustodyDecorator{
    75  		ck: ck,
    76  		gk: gk,
    77  	}
    78  }
    79  
    80  func (cd CustodyDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
    81  	feeTx, ok := tx.(sdk.FeeTx)
    82  	if !ok {
    83  		return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
    84  	}
    85  
    86  	for _, msg := range feeTx.GetMsgs() {
    87  		settings := cd.ck.GetCustodyInfoByAddress(ctx, msg.GetSigners()[0])
    88  
    89  		if settings != nil && settings.CustodyEnabled {
    90  			switch kiratypes.MsgType(msg) {
    91  			case kiratypes.MsgTypeCreateCustody:
    92  				{
    93  					msg, ok := msg.(*custodytypes.MsgCreateCustodyRecord)
    94  					if !ok {
    95  						return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidType, "Not a MsgCreateCustodyRecord")
    96  					}
    97  
    98  					hash := sha256.Sum256([]byte(msg.OldKey))
    99  					hashString := hex.EncodeToString(hash[:])
   100  
   101  					if msg.TargetAddress != "" && msg.TargetAddress != settings.NextController {
   102  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongTargetAddr, "Custody module")
   103  					}
   104  
   105  					if hashString != settings.Key {
   106  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongKey, "Custody module")
   107  					}
   108  				}
   109  			case kiratypes.MsgTypeAddToCustodyWhiteList:
   110  				{
   111  					msg, ok := msg.(*custodytypes.MsgAddToCustodyWhiteList)
   112  					if !ok {
   113  						return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidType, "Not a MsgCreateCustodyRecord")
   114  					}
   115  
   116  					hash := sha256.Sum256([]byte(msg.OldKey))
   117  					hashString := hex.EncodeToString(hash[:])
   118  
   119  					if msg.TargetAddress != "" && msg.TargetAddress != settings.NextController {
   120  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongTargetAddr, "Custody module")
   121  					}
   122  
   123  					if hashString != settings.Key {
   124  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongKey, "Custody module")
   125  					}
   126  				}
   127  			case kiratypes.MsgTypeAddToCustodyCustodians:
   128  				{
   129  					msg, ok := msg.(*custodytypes.MsgAddToCustodyCustodians)
   130  					if !ok {
   131  						return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidType, "Not a MsgCreateCustodyRecord")
   132  					}
   133  
   134  					hash := sha256.Sum256([]byte(msg.OldKey))
   135  					hashString := hex.EncodeToString(hash[:])
   136  
   137  					if msg.TargetAddress != "" && msg.TargetAddress != settings.NextController {
   138  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongTargetAddr, "Custody module")
   139  					}
   140  
   141  					if hashString != settings.Key {
   142  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongKey, "Custody module")
   143  					}
   144  				}
   145  			case kiratypes.MsgTypeRemoveFromCustodyCustodians:
   146  				{
   147  					msg, ok := msg.(*custodytypes.MsgRemoveFromCustodyCustodians)
   148  					if !ok {
   149  						return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidType, "Not a MsgCreateCustodyRecord")
   150  					}
   151  
   152  					hash := sha256.Sum256([]byte(msg.OldKey))
   153  					hashString := hex.EncodeToString(hash[:])
   154  
   155  					if msg.TargetAddress != "" && msg.TargetAddress != settings.NextController {
   156  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongTargetAddr, "Custody module")
   157  					}
   158  
   159  					if hashString != settings.Key {
   160  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongKey, "Custody module")
   161  					}
   162  				}
   163  			case kiratypes.MsgTypeDropCustodyCustodians:
   164  				{
   165  					msg, ok := msg.(*custodytypes.MsgDropCustodyCustodians)
   166  					if !ok {
   167  						return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidType, "Not a MsgCreateCustodyRecord")
   168  					}
   169  
   170  					hash := sha256.Sum256([]byte(msg.OldKey))
   171  					hashString := hex.EncodeToString(hash[:])
   172  
   173  					if msg.TargetAddress != "" && msg.TargetAddress != settings.NextController {
   174  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongTargetAddr, "Custody module")
   175  					}
   176  
   177  					if hashString != settings.Key {
   178  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongKey, "Custody module")
   179  					}
   180  				}
   181  			case kiratypes.MsgTypeRemoveFromCustodyWhiteList:
   182  				{
   183  					msg, ok := msg.(*custodytypes.MsgRemoveFromCustodyWhiteList)
   184  					if !ok {
   185  						return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidType, "Not a MsgCreateCustodyRecord")
   186  					}
   187  
   188  					hash := sha256.Sum256([]byte(msg.OldKey))
   189  					hashString := hex.EncodeToString(hash[:])
   190  
   191  					if msg.TargetAddress != "" && msg.TargetAddress != settings.NextController {
   192  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongTargetAddr, "Custody module")
   193  					}
   194  
   195  					if hashString != settings.Key {
   196  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongKey, "Custody module")
   197  					}
   198  				}
   199  			case kiratypes.MsgTypeDropCustodyWhiteList:
   200  				{
   201  					msg, ok := msg.(*custodytypes.MsgDropCustodyWhiteList)
   202  					if !ok {
   203  						return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidType, "Not a MsgCreateCustodyRecord")
   204  					}
   205  
   206  					hash := sha256.Sum256([]byte(msg.OldKey))
   207  					hashString := hex.EncodeToString(hash[:])
   208  
   209  					if msg.TargetAddress != "" && msg.TargetAddress != settings.NextController {
   210  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongTargetAddr, "Custody module")
   211  					}
   212  
   213  					if hashString != settings.Key {
   214  						return ctx, sdkerrors.Wrap(custodytypes.ErrWrongKey, "Custody module")
   215  					}
   216  				}
   217  			case kiratypes.MsgTypeSend:
   218  				{
   219  					msg := msg.(*custodytypes.MsgSend)
   220  					properties := cd.gk.GetNetworkProperties(ctx)
   221  					custodians := cd.ck.GetCustodyCustodiansByAddress(ctx, msg.GetSigners()[0])
   222  					count := uint64(len(custodians.Addresses))
   223  
   224  					if len(msg.Reward) < 1 {
   225  						return ctx, sdkerrors.Wrap(custodytypes.ErrNotEnoughReward, "no reward")
   226  					}
   227  
   228  					if msg.Reward[0].Amount.Uint64() < properties.MinCustodyReward*count {
   229  						return ctx, sdkerrors.Wrap(custodytypes.ErrNotEnoughReward, "to small reward")
   230  					}
   231  
   232  					if msg.Reward[0].Denom != cd.ck.DefaultDenom(ctx) {
   233  						return ctx, sdkerrors.Wrap(custodytypes.ErrNotEnoughReward, "wrong reward denom")
   234  					}
   235  				}
   236  			}
   237  
   238  		}
   239  
   240  		if kiratypes.MsgType(msg) == bank.TypeMsgSend {
   241  			msg := msg.(*bank.MsgSend)
   242  
   243  			if settings != nil && settings.CustodyEnabled {
   244  				custodians := cd.ck.GetCustodyCustodiansByAddress(ctx, msg.GetSigners()[0])
   245  
   246  				if len(custodians.Addresses) > 0 {
   247  					return ctx, sdkerrors.Wrap(sdkerrors.ErrConflict, "Custody module is enabled. Please use custody send instead.")
   248  				}
   249  			}
   250  
   251  			if settings != nil && settings.UseWhiteList {
   252  				whiteList := cd.ck.GetCustodyWhiteListByAddress(ctx, msg.GetSigners()[0])
   253  
   254  				if whiteList != nil && !whiteList.Addresses[msg.ToAddress] {
   255  					return ctx, custodytypes.ErrNotInWhiteList
   256  				}
   257  			}
   258  
   259  			if settings != nil && settings.UseLimits {
   260  				limits := cd.ck.GetCustodyLimitsByAddress(ctx, msg.GetSigners()[0])
   261  
   262  				custodyLimitStatusRecord := custodytypes.CustodyLimitStatusRecord{
   263  					Address:         msg.GetSigners()[0],
   264  					CustodyStatuses: cd.ck.GetCustodyLimitsStatusByAddress(ctx, msg.GetSigners()[0]),
   265  				}
   266  
   267  				newAmount := msg.Amount.AmountOf(msg.Amount[0].Denom).Uint64()
   268  
   269  				if custodyLimitStatusRecord.CustodyStatuses != nil && custodyLimitStatusRecord.CustodyStatuses.Statuses[msg.Amount[0].Denom] != nil {
   270  					limit, _ := time.ParseDuration(limits.Limits[msg.Amount[0].Denom].Limit)
   271  					rate := limits.Limits[msg.Amount[0].Denom].Amount / (uint64(limit.Milliseconds()))
   272  					period := uint64(time.Now().Unix() - custodyLimitStatusRecord.CustodyStatuses.Statuses[msg.Amount[0].Denom].Time)
   273  					newAmount = custodyLimitStatusRecord.CustodyStatuses.Statuses[msg.Amount[0].Denom].Amount + msg.Amount.AmountOf(msg.Amount[0].Denom).Uint64() - (period * rate)
   274  
   275  					if newAmount <= 0 {
   276  						return ctx, custodytypes.ErrNotInLimits
   277  					}
   278  				}
   279  
   280  				custodyLimitStatusRecord.CustodyStatuses.Statuses[msg.Amount[0].Denom] = &custodytypes.CustodyStatus{
   281  					Amount: newAmount,
   282  				}
   283  
   284  				cd.ck.AddToCustodyLimitsStatus(ctx, custodyLimitStatusRecord)
   285  			}
   286  		}
   287  	}
   288  
   289  	return next(ctx, tx, simulate)
   290  }
   291  
   292  // ValidateFeeRangeDecorator check if fee is within range defined as network properties
   293  type ValidateFeeRangeDecorator struct {
   294  	sk  customstakingkeeper.Keeper
   295  	cgk customgovkeeper.Keeper
   296  	tk  tokenskeeper.Keeper
   297  	ak  keeper.AccountKeeper
   298  }
   299  
   300  // NewValidateFeeRangeDecorator check if fee is within range defined as network properties
   301  func NewValidateFeeRangeDecorator(
   302  	sk customstakingkeeper.Keeper,
   303  	cgk customgovkeeper.Keeper,
   304  	tk tokenskeeper.Keeper,
   305  	ak keeper.AccountKeeper,
   306  ) ValidateFeeRangeDecorator {
   307  	return ValidateFeeRangeDecorator{
   308  		sk:  sk,
   309  		cgk: cgk,
   310  		ak:  ak,
   311  		tk:  tk,
   312  	}
   313  }
   314  
   315  // AnteHandle is a handler for ValidateFeeRangeDecorator
   316  func (svd ValidateFeeRangeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
   317  	feeTx, ok := tx.(sdk.FeeTx)
   318  	if !ok {
   319  		return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
   320  	}
   321  
   322  	properties := svd.cgk.GetNetworkProperties(ctx)
   323  	defaultDenom := svd.sk.DefaultDenom(ctx)
   324  
   325  	feeAmount := sdk.NewDec(0)
   326  	feeCoins := feeTx.GetFee()
   327  	tokensBlackWhite := svd.tk.GetTokenBlackWhites(ctx)
   328  	for _, feeCoin := range feeCoins {
   329  		rate := svd.tk.GetTokenRate(ctx, feeCoin.Denom)
   330  		if !properties.EnableForeignFeePayments && feeCoin.Denom != defaultDenom {
   331  			return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("foreign fee payments is disabled by governance"))
   332  		}
   333  		if rate == nil || !rate.FeePayments {
   334  			return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("currency you are trying to use was not whitelisted as fee payment"))
   335  		}
   336  		if tokensBlackWhite.IsFrozen(feeCoin.Denom, defaultDenom, properties.EnableTokenBlacklist, properties.EnableTokenWhitelist) {
   337  			return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("currency you are trying to use as fee is frozen"))
   338  		}
   339  		feeAmount = feeAmount.Add(sdk.NewDecFromInt(feeCoin.Amount).Mul(rate.FeeRate))
   340  	}
   341  
   342  	// execution fee should be prepaid
   343  	executionMaxFee := uint64(0)
   344  	for _, msg := range feeTx.GetMsgs() {
   345  		fee := svd.cgk.GetExecutionFee(ctx, kiratypes.MsgType(msg))
   346  		if fee != nil { // execution fee exist
   347  			maxFee := fee.FailureFee
   348  			if fee.ExecutionFee > maxFee {
   349  				maxFee = fee.ExecutionFee
   350  			}
   351  			executionMaxFee += maxFee
   352  		}
   353  	}
   354  
   355  	if feeAmount.LT(sdk.NewDec(int64(properties.MinTxFee))) || feeAmount.GT(sdk.NewDec(int64(properties.MaxTxFee))) {
   356  		return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("fee %+v(%d) is out of range [%d, %d]%s", feeTx.GetFee(), feeAmount.RoundInt().Int64(), properties.MinTxFee, properties.MaxTxFee, defaultDenom))
   357  	}
   358  
   359  	if feeAmount.LT(sdk.NewDec(int64(executionMaxFee))) {
   360  		return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("fee %+v(%d) is less than max execution fee %d%s", feeTx.GetFee(), feeAmount.RoundInt().Int64(), executionMaxFee, defaultDenom))
   361  	}
   362  
   363  	return next(ctx, tx, simulate)
   364  }
   365  
   366  // ExecutionFeeRegistrationDecorator register paid execution fee
   367  type ExecutionFeeRegistrationDecorator struct {
   368  	ak  keeper.AccountKeeper
   369  	cgk customgovkeeper.Keeper
   370  	fk  feeprocessingkeeper.Keeper
   371  }
   372  
   373  // NewExecutionFeeRegistrationDecorator returns instance of CustomExecutionFeeConsumeDecorator
   374  func NewExecutionFeeRegistrationDecorator(ak keeper.AccountKeeper, cgk customgovkeeper.Keeper, fk feeprocessingkeeper.Keeper) ExecutionFeeRegistrationDecorator {
   375  	return ExecutionFeeRegistrationDecorator{
   376  		ak,
   377  		cgk,
   378  		fk,
   379  	}
   380  }
   381  
   382  // AnteHandle handle ExecutionFeeRegistrationDecorator
   383  func (sgcd ExecutionFeeRegistrationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
   384  	sigTx, ok := tx.(sdk.FeeTx)
   385  	if !ok {
   386  		return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
   387  	}
   388  
   389  	// execution fee consume gas
   390  	for _, msg := range sigTx.GetMsgs() {
   391  		fee := sgcd.cgk.GetExecutionFee(ctx, kiratypes.MsgType(msg))
   392  		if fee != nil { // execution fee exist
   393  			sgcd.fk.AddExecutionStart(ctx, msg)
   394  		}
   395  	}
   396  
   397  	return next(ctx, tx, simulate)
   398  }
   399  
   400  // PoorNetworkManagementDecorator register poor network manager
   401  type PoorNetworkManagementDecorator struct {
   402  	ak  keeper.AccountKeeper
   403  	cgk customgovkeeper.Keeper
   404  	csk customstakingkeeper.Keeper
   405  }
   406  
   407  // NewPoorNetworkManagementDecorator returns instance of PoorNetworkManagementDecorator
   408  func NewPoorNetworkManagementDecorator(ak keeper.AccountKeeper, cgk customgovkeeper.Keeper, csk customstakingkeeper.Keeper) PoorNetworkManagementDecorator {
   409  	return PoorNetworkManagementDecorator{
   410  		ak,
   411  		cgk,
   412  		csk,
   413  	}
   414  }
   415  
   416  func findString(a []string, x string) int {
   417  	for i, n := range a {
   418  		if x == n {
   419  			return i
   420  		}
   421  	}
   422  	return -1
   423  }
   424  
   425  // AnteHandle handle PoorNetworkManagementDecorator
   426  func (pnmd PoorNetworkManagementDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
   427  	sigTx, ok := tx.(sdk.FeeTx)
   428  	if !ok {
   429  		return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
   430  	}
   431  
   432  	// if not poor network, skip this process
   433  	if pnmd.csk.IsNetworkActive(ctx) {
   434  		return next(ctx, tx, simulate)
   435  	}
   436  	// handle messages on poor network
   437  	pnmsgs := pnmd.cgk.GetPoorNetworkMessages(ctx)
   438  	for _, msg := range sigTx.GetMsgs() {
   439  		if kiratypes.MsgType(msg) == bank.TypeMsgSend {
   440  			// on poor network, we introduce POOR_NETWORK_MAX_BANK_TX_SEND network property to limit transaction send amount
   441  			msg := msg.(*bank.MsgSend)
   442  			if len(msg.Amount) > 1 || msg.Amount[0].Denom != pnmd.csk.DefaultDenom(ctx) {
   443  				return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "only bond denom is allowed on poor network")
   444  			}
   445  			if msg.Amount[0].Amount.Uint64() > pnmd.cgk.GetNetworkProperties(ctx).PoorNetworkMaxBankSend {
   446  				return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "only restricted amount send is allowed on poor network")
   447  			}
   448  			// TODO: we could do restriction to send only when target account does not exist on chain yet for more restriction
   449  			return next(ctx, tx, simulate)
   450  		}
   451  		if findString(pnmsgs.Messages, kiratypes.MsgType(msg)) >= 0 {
   452  			return next(ctx, tx, simulate)
   453  		}
   454  		return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "invalid transaction type on poor network")
   455  	}
   456  
   457  	return next(ctx, tx, simulate)
   458  }
   459  
   460  // BlackWhiteTokensCheckDecorator register black white tokens check decorator
   461  type BlackWhiteTokensCheckDecorator struct {
   462  	cgk customgovkeeper.Keeper
   463  	csk customstakingkeeper.Keeper
   464  	tk  tokenskeeper.Keeper
   465  }
   466  
   467  // NewBlackWhiteTokensCheckDecorator returns instance of BlackWhiteTokensCheckDecorator
   468  func NewBlackWhiteTokensCheckDecorator(cgk customgovkeeper.Keeper, csk customstakingkeeper.Keeper, tk tokenskeeper.Keeper) BlackWhiteTokensCheckDecorator {
   469  	return BlackWhiteTokensCheckDecorator{
   470  		cgk,
   471  		csk,
   472  		tk,
   473  	}
   474  }
   475  
   476  // AnteHandle handle NewPoorNetworkManagementDecorator
   477  func (pnmd BlackWhiteTokensCheckDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
   478  	sigTx, ok := tx.(sdk.FeeTx)
   479  	if !ok {
   480  		return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
   481  	}
   482  
   483  	defaultDenom := pnmd.csk.DefaultDenom(ctx)
   484  	tokensBlackWhite := pnmd.tk.GetTokenBlackWhites(ctx)
   485  	properties := pnmd.cgk.GetNetworkProperties(ctx)
   486  	for _, msg := range sigTx.GetMsgs() {
   487  		if kiratypes.MsgType(msg) == bank.TypeMsgSend {
   488  			msg := msg.(*bank.MsgSend)
   489  			for _, amt := range msg.Amount {
   490  				if tokensBlackWhite.IsFrozen(amt.Denom, defaultDenom, properties.EnableTokenBlacklist, properties.EnableTokenWhitelist) {
   491  					return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "token is frozen")
   492  				}
   493  			}
   494  		}
   495  	}
   496  
   497  	return next(ctx, tx, simulate)
   498  }
   499  
   500  // ZeroGasMeterDecorator uses infinite gas decorator to avoid gas usage in the network
   501  type ZeroGasMeterDecorator struct{}
   502  
   503  // NewZeroGasMeterDecorator returns instance of ZeroGasMeterDecorator
   504  func NewZeroGasMeterDecorator() ZeroGasMeterDecorator {
   505  	return ZeroGasMeterDecorator{}
   506  }
   507  
   508  func (igm ZeroGasMeterDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
   509  	newCtx = ctx.WithGasMeter(feeprocessingtypes.NewZeroGasMeter())
   510  	return next(newCtx, tx, simulate)
   511  }