github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/evidence/internal/keeper/keeper.go (about)

     1  package keeper
     2  
     3  import (
     4  	"fmt"
     5  
     6  	tmbytes "github.com/fibonacci-chain/fbc/libs/tendermint/libs/bytes"
     7  	"github.com/fibonacci-chain/fbc/libs/tendermint/libs/log"
     8  
     9  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/prefix"
    11  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    12  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    13  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/evidence/exported"
    14  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/evidence/internal/types"
    15  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/params"
    16  )
    17  
    18  // Keeper defines the evidence module's keeper. The keeper is responsible for
    19  // managing persistence, state transitions and query handling for the evidence
    20  // module.
    21  type Keeper struct {
    22  	cdc            *codec.Codec
    23  	storeKey       sdk.StoreKey
    24  	paramSpace     params.Subspace
    25  	router         types.Router
    26  	stakingKeeper  types.StakingKeeper
    27  	slashingKeeper types.SlashingKeeper
    28  }
    29  
    30  func NewKeeper(
    31  	cdc *codec.Codec, storeKey sdk.StoreKey, paramSpace params.Subspace,
    32  	stakingKeeper types.StakingKeeper, slashingKeeper types.SlashingKeeper,
    33  ) *Keeper {
    34  
    35  	// set KeyTable if it has not already been set
    36  	if !paramSpace.HasKeyTable() {
    37  		paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
    38  	}
    39  
    40  	return &Keeper{
    41  		cdc:            cdc,
    42  		storeKey:       storeKey,
    43  		paramSpace:     paramSpace,
    44  		stakingKeeper:  stakingKeeper,
    45  		slashingKeeper: slashingKeeper,
    46  	}
    47  }
    48  
    49  // Logger returns a module-specific logger.
    50  func (k Keeper) Logger(ctx sdk.Context) log.Logger {
    51  	return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
    52  }
    53  
    54  // SetRouter sets the Evidence Handler router for the x/evidence module. Note,
    55  // we allow the ability to set the router after the Keeper is constructed as a
    56  // given Handler may need access the Keeper before being constructed. The router
    57  // may only be set once and will be sealed if it's not already sealed.
    58  func (k *Keeper) SetRouter(rtr types.Router) {
    59  	// It is vital to seal the Evidence Handler router as to not allow further
    60  	// handlers to be registered after the keeper is created since this
    61  	// could create invalid or non-deterministic behavior.
    62  	if !rtr.Sealed() {
    63  		rtr.Seal()
    64  	}
    65  	if k.router != nil {
    66  		panic(fmt.Sprintf("attempting to reset router on x/%s", types.ModuleName))
    67  	}
    68  
    69  	k.router = rtr
    70  }
    71  
    72  // GetEvidenceHandler returns a registered Handler for a given Evidence type. If
    73  // no handler exists, an error is returned.
    74  func (k Keeper) GetEvidenceHandler(evidenceRoute string) (types.Handler, error) {
    75  	if !k.router.HasRoute(evidenceRoute) {
    76  		return nil, sdkerrors.Wrap(types.ErrNoEvidenceHandlerExists, evidenceRoute)
    77  	}
    78  
    79  	return k.router.GetRoute(evidenceRoute), nil
    80  }
    81  
    82  // SubmitEvidence attempts to match evidence against the keepers router and execute
    83  // the corresponding registered Evidence Handler. An error is returned if no
    84  // registered Handler exists or if the Handler fails. Otherwise, the evidence is
    85  // persisted.
    86  func (k Keeper) SubmitEvidence(ctx sdk.Context, evidence exported.Evidence) error {
    87  	if _, ok := k.GetEvidence(ctx, evidence.Hash()); ok {
    88  		return sdkerrors.Wrap(types.ErrEvidenceExists, evidence.Hash().String())
    89  	}
    90  	if !k.router.HasRoute(evidence.Route()) {
    91  		return sdkerrors.Wrap(types.ErrNoEvidenceHandlerExists, evidence.Route())
    92  	}
    93  
    94  	handler := k.router.GetRoute(evidence.Route())
    95  	if err := handler(ctx, evidence); err != nil {
    96  		return sdkerrors.Wrap(types.ErrInvalidEvidence, err.Error())
    97  	}
    98  
    99  	ctx.EventManager().EmitEvent(
   100  		sdk.NewEvent(
   101  			types.EventTypeSubmitEvidence,
   102  			sdk.NewAttribute(types.AttributeKeyEvidenceHash, evidence.Hash().String()),
   103  		),
   104  	)
   105  
   106  	k.SetEvidence(ctx, evidence)
   107  	return nil
   108  }
   109  
   110  // SetEvidence sets Evidence by hash in the module's KVStore.
   111  func (k Keeper) SetEvidence(ctx sdk.Context, evidence exported.Evidence) {
   112  	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixEvidence)
   113  	bz := k.cdc.MustMarshalBinaryLengthPrefixed(evidence)
   114  	store.Set(evidence.Hash(), bz)
   115  }
   116  
   117  // GetEvidence retrieves Evidence by hash if it exists. If no Evidence exists for
   118  // the given hash, (nil, false) is returned.
   119  func (k Keeper) GetEvidence(ctx sdk.Context, hash tmbytes.HexBytes) (evidence exported.Evidence, found bool) {
   120  	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixEvidence)
   121  
   122  	bz := store.Get(hash)
   123  	if len(bz) == 0 {
   124  		return nil, false
   125  	}
   126  
   127  	k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &evidence)
   128  	return evidence, true
   129  }
   130  
   131  // IterateEvidence provides an interator over all stored Evidence objects. For
   132  // each Evidence object, cb will be called. If the cb returns true, the iterator
   133  // will close and stop.
   134  func (k Keeper) IterateEvidence(ctx sdk.Context, cb func(exported.Evidence) bool) {
   135  	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixEvidence)
   136  	iterator := sdk.KVStorePrefixIterator(store, nil)
   137  
   138  	defer iterator.Close()
   139  	for ; iterator.Valid(); iterator.Next() {
   140  		var evidence exported.Evidence
   141  		k.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &evidence)
   142  
   143  		if cb(evidence) {
   144  			break
   145  		}
   146  	}
   147  }
   148  
   149  // GetAllEvidence returns all stored Evidence objects.
   150  func (k Keeper) GetAllEvidence(ctx sdk.Context) (evidence []exported.Evidence) {
   151  	k.IterateEvidence(ctx, func(e exported.Evidence) bool {
   152  		evidence = append(evidence, e)
   153  		return false
   154  	})
   155  	return evidence
   156  }