func ValidateMemo(stdTx types.StdTx, params Params) sdk.Error {
	memoLength := len(stdTx.GetMemo())
	if uint64(memoLength) > params.MaxMemoCharacters {
		return sdk.ErrMemoTooLarge(
			fmt.Sprintf(
				"maximum number of characters is %d but received %d characters",
				params.MaxMemoCharacters, memoLength,
			),
		)
	}
	return nil
}
ValidateMemo validates the memo size.
package auth
import (
	"encoding/hex"
	"fmt"
	posCrypto "github.com/pokt-network/pocket-core/crypto"
	sdk "github.com/pokt-network/pocket-core/types"
	"github.com/pokt-network/pocket-core/x/auth/keeper"
	"github.com/pokt-network/pocket-core/x/auth/types"
	"github.com/tendermint/tendermint/state/txindex"
	tmTypes "github.com/tendermint/tendermint/types"
	"os"
)
func NewAnteHandler(ak keeper.Keeper) sdk.AnteHandler {
	return func(ctx sdk.Ctx, tx sdk.Tx, txBz []byte, txIndexer txindex.TxIndexer, simulate bool) (newCtx sdk.Ctx, res sdk.Result, abort bool) {
		if addr := ak.GetModuleAddress(types.FeeCollectorName); addr == nil {
			ctx.Logger().Error(fmt.Sprintf("%s module account has not been set", types.FeeCollectorName))
			os.Exit(1)
		}
		if err := tx.ValidateBasic(); err != nil {
			return newCtx, err.Result(), true
		}
		stdTx, ok := tx.(types.StdTx)
		if !ok {
			return newCtx, sdk.ErrInternal("all transactions must be convertible to inteface: ProtoStdTx").Result(), true
		}
		err := ValidateTransaction(ctx, ak, stdTx, ak.GetParams(ctx), txIndexer, txBz, simulate)
		if err != nil {
			return newCtx, err.Result(), true
		}
		err = DeductFees(ak, ctx, stdTx)
		if err != nil {
			return newCtx, err.Result(), true
		}
		return ctx, sdk.Result{}, false  
	}
}
func ValidateTransaction(ctx sdk.Ctx, k Keeper, stdTx types.StdTx, params Params, txIndexer txindex.TxIndexer, txBz []byte, simulate bool) sdk.Error {
	if err := ValidateMemo(stdTx, params); err != nil {
		return types.ErrInvalidMemo(ModuleName, err)
	}
	var pk posCrypto.PublicKey
	if stdTx.GetSignature().GetPublicKey() != "" {
		var err error
		pk, err = posCrypto.NewPublicKey(stdTx.GetSignature().GetPublicKey())
		if err != nil {
			return sdk.ErrInvalidPubKey(err.Error())
		}
	} else {
		acc := k.GetAccount(ctx, stdTx.GetSigner())
		if acc == nil {
			return types.ErrAccountNotFound(ModuleName)
		}
		if pk = acc.GetPubKey(); pk == nil {
			return types.ErrEmptyPublicKey(ModuleName)
		}
	}
	txHash := tmTypes.Tx(txBz).Hash()
	if txIndexer == nil {
		ctx.Logger().Error(types.ErrNilTxIndexer(ModuleName).Error())
		return types.ErrNilTxIndexer(ModuleName)
	}
	res, err := (txIndexer).Get(txHash)
	if err != nil {
		ctx.Logger().Error(err.Error())
		return sdk.ErrInternal(err.Error())
	}
	if res != nil {
		return types.ErrDuplicateTx(ModuleName, hex.EncodeToString(txHash))
	}
	signBytes, err := GetSignBytes(ctx.ChainID(), stdTx)
	if err != nil {
		return sdk.ErrInternal(err.Error())
	}
	expectedFee := sdk.NewCoins(sdk.NewCoin(sdk.DefaultStakeDenom, k.GetParams(ctx).FeeMultiplier.GetFee(stdTx.GetMsg())))
	p, ok := pk.(posCrypto.PublicKeyMultiSig)
	if !ok {
		if !stdTx.GetFee().IsAllGTE(expectedFee) {
			return types.ErrInsufficientFee(ModuleName, expectedFee, stdTx.GetFee())
		}
		if !simulate && !pk.VerifyBytes(signBytes, stdTx.GetSignature().GetSignature()) {
			return sdk.ErrUnauthorized("signature verification failed for the transaction")
		}
		return nil
	}
	ok = ValidateSignatureDepth(params.TxSigLimit, p)
	if !ok {
		return types.ErrTooManySignatures(ModuleName, params.TxSigLimit)
	}
	if !simulate && !pk.VerifyBytes(signBytes, stdTx.GetSignature().GetSignature()) {
		return sdk.ErrUnauthorized("multisignature verification failed for the transaction")
	}
	return nil
}
func ValidateSignatureDepth(limit uint64, publicKey posCrypto.PublicKeyMultiSig) (ok bool) {
	_, ok = recSignDepth(1, limit, publicKey)
	return
}
func recSignDepth(count, limit uint64, publicKey posCrypto.PublicKeyMultiSig) (c uint64, ok bool) {
	for _, p := range publicKey.Keys() {
		count++
		if pk, ok := p.(posCrypto.PublicKeyMultiSig); ok {
			count, ok = recSignDepth(count, limit, pk)
			if !ok {
				return count, ok
			}
		}
		if count > limit {
			return count, false
		}
	}
	return count, true
}
func GetSignerAcc(ctx sdk.Ctx, ak keeper.Keeper, addr sdk.Address) (Account, sdk.Error) {
	if acc := ak.GetAccount(ctx, addr); acc != nil {
		return acc, nil
	}
	return nil, sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", addr))
}