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