refactor(evidence)!: use collections for state management (#16336)
Co-authored-by: unknown unknown <unknown@unknown>
This commit is contained in:
parent
46c8ec8fc9
commit
28178f7ca6
@ -140,10 +140,10 @@ func initFixture(t testing.TB) *fixture {
|
||||
evidencetypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), keeper.NewMsgServerImpl(*evidenceKeeper))
|
||||
evidencetypes.RegisterQueryServer(integrationApp.QueryHelper(), keeper.NewQuerier(evidenceKeeper))
|
||||
|
||||
slashingKeeper.SetParams(sdkCtx, testutil.TestParams())
|
||||
assert.NilError(t, slashingKeeper.SetParams(sdkCtx, testutil.TestParams()))
|
||||
|
||||
// set default staking params
|
||||
stakingKeeper.SetParams(sdkCtx, stakingtypes.DefaultParams())
|
||||
assert.NilError(t, stakingKeeper.SetParams(sdkCtx, stakingtypes.DefaultParams()))
|
||||
|
||||
return &fixture{
|
||||
app: integrationApp,
|
||||
@ -171,14 +171,15 @@ func TestHandleDoubleSign(t *testing.T) {
|
||||
selfDelegation := tstaking.CreateValidatorWithValPower(operatorAddr, val, power, true)
|
||||
|
||||
// execute end-blocker and verify validator attributes
|
||||
f.stakingKeeper.EndBlocker(f.sdkCtx)
|
||||
_, err := f.stakingKeeper.EndBlocker(f.sdkCtx)
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t,
|
||||
f.bankKeeper.GetAllBalances(ctx, sdk.AccAddress(operatorAddr)).String(),
|
||||
sdk.NewCoins(sdk.NewCoin(stakingParams.BondDenom, initAmt.Sub(selfDelegation))).String(),
|
||||
)
|
||||
assert.DeepEqual(t, selfDelegation, f.stakingKeeper.Validator(ctx, operatorAddr).GetBondedTokens())
|
||||
|
||||
f.slashingKeeper.AddPubkey(f.sdkCtx, val)
|
||||
assert.NilError(t, f.slashingKeeper.AddPubkey(f.sdkCtx, val))
|
||||
|
||||
info := slashingtypes.NewValidatorSigningInfo(sdk.ConsAddress(val.Address()), f.sdkCtx.BlockHeight(), int64(0), time.Unix(0, 0), false, int64(0))
|
||||
f.slashingKeeper.SetValidatorSigningInfo(f.sdkCtx, sdk.ConsAddress(val.Address()), info)
|
||||
@ -199,7 +200,7 @@ func TestHandleDoubleSign(t *testing.T) {
|
||||
})
|
||||
|
||||
ctx = ctx.WithCometInfo(nci)
|
||||
f.evidenceKeeper.BeginBlocker(ctx.WithCometInfo(nci))
|
||||
assert.NilError(t, f.evidenceKeeper.BeginBlocker(ctx.WithCometInfo(nci)))
|
||||
|
||||
// should be jailed and tombstoned
|
||||
assert.Assert(t, f.stakingKeeper.Validator(ctx, operatorAddr).IsJailed())
|
||||
@ -210,7 +211,7 @@ func TestHandleDoubleSign(t *testing.T) {
|
||||
assert.Assert(t, newTokens.LT(oldTokens))
|
||||
|
||||
// submit duplicate evidence
|
||||
f.evidenceKeeper.BeginBlocker(ctx)
|
||||
assert.NilError(t, f.evidenceKeeper.BeginBlocker(ctx))
|
||||
|
||||
// tokens should be the same (capped slash)
|
||||
assert.Assert(t, f.stakingKeeper.Validator(ctx, operatorAddr).GetTokens().Equal(newTokens))
|
||||
@ -231,9 +232,11 @@ func TestHandleDoubleSign(t *testing.T) {
|
||||
tstaking.Undelegate(sdk.AccAddress(operatorAddr), operatorAddr, totalBond, true)
|
||||
|
||||
// query evidence from store
|
||||
evidences, err := f.evidenceKeeper.GetAllEvidence(ctx)
|
||||
iter, err := f.evidenceKeeper.Evidences.Iterate(ctx, nil)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, len(evidences) == 1)
|
||||
values, err := iter.Values()
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, len(values) == 1)
|
||||
}
|
||||
|
||||
func TestHandleDoubleSign_TooOld(t *testing.T) {
|
||||
@ -252,7 +255,8 @@ func TestHandleDoubleSign_TooOld(t *testing.T) {
|
||||
amt := tstaking.CreateValidatorWithValPower(operatorAddr, val, power, true)
|
||||
|
||||
// execute end-blocker and verify validator attributes
|
||||
f.stakingKeeper.EndBlocker(f.sdkCtx)
|
||||
_, err := f.stakingKeeper.EndBlocker(f.sdkCtx)
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t,
|
||||
f.bankKeeper.GetAllBalances(ctx, sdk.AccAddress(operatorAddr)),
|
||||
sdk.NewCoins(sdk.NewCoin(stakingParams.BondDenom, initAmt.Sub(amt))),
|
||||
@ -268,7 +272,7 @@ func TestHandleDoubleSign_TooOld(t *testing.T) {
|
||||
}},
|
||||
})
|
||||
|
||||
f.app.BaseApp.StoreConsensusParams(ctx, *simtestutil.DefaultConsensusParams)
|
||||
assert.NilError(t, f.app.BaseApp.StoreConsensusParams(ctx, *simtestutil.DefaultConsensusParams))
|
||||
cp := f.app.BaseApp.GetConsensusParams(ctx)
|
||||
|
||||
ctx = ctx.WithCometInfo(nci)
|
||||
@ -276,7 +280,7 @@ func TestHandleDoubleSign_TooOld(t *testing.T) {
|
||||
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(cp.Evidence.MaxAgeDuration + 1))
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + cp.Evidence.MaxAgeNumBlocks + 1)
|
||||
|
||||
f.evidenceKeeper.BeginBlocker(ctx)
|
||||
assert.NilError(t, f.evidenceKeeper.BeginBlocker(ctx))
|
||||
|
||||
assert.Assert(t, f.stakingKeeper.Validator(ctx, operatorAddr).IsJailed() == false)
|
||||
assert.Assert(t, f.slashingKeeper.IsTombstoned(ctx, sdk.ConsAddress(val.Address())) == false)
|
||||
|
||||
@ -34,3 +34,5 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
* [#16008](https://github.com/cosmos/cosmos-sdk/pull/16008) NewKeeper now takes in a KVStoreService instead of KVStoreKey, most functions use context.Context instead of sdk.Context and `IterateEvidence` callback function now returns an error to stop interation (`errors.ErrStopIterating`).
|
||||
* (keeper) [#15825](https://github.com/cosmos/cosmos-sdk/pull/15825) Evidence constructor now requires an `address.Codec` (`import "cosmossdk.io/core/address"`)
|
||||
* [#16336](https://github.com/cosmos/cosmos-sdk/pull/16336) Use collections for state management:
|
||||
* Removed: keeper `SetEvidence`, `GetEvidence`, `IterateEvidences`, `GetAllEvidences`, `MustMarshalEvidence`, `MustUnmarshalEvidence`, `MarshalEvidence`, `UnmarshalEvidence`
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
package evidence
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
"cosmossdk.io/x/evidence/exported"
|
||||
"cosmossdk.io/x/evidence/keeper"
|
||||
"cosmossdk.io/x/evidence/types"
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
@ -24,33 +24,29 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, gs *types.GenesisState) {
|
||||
if !ok {
|
||||
panic("expected evidence")
|
||||
}
|
||||
if _, err := k.GetEvidence(ctx, evi.Hash()); err == nil {
|
||||
if _, err := k.Evidences.Get(ctx, evi.Hash()); err == nil {
|
||||
panic(fmt.Sprintf("evidence with hash %s already exists", evi.Hash()))
|
||||
}
|
||||
|
||||
k.SetEvidence(ctx, evi)
|
||||
if err := k.Evidences.Set(ctx, evi.Hash(), evi); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ExportGenesis returns the evidence module's exported genesis.
|
||||
func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState {
|
||||
e, err := k.GetAllEvidence(ctx)
|
||||
if err != nil {
|
||||
gs := new(types.GenesisState)
|
||||
err := k.Evidences.Walk(ctx, nil, func(_ []byte, value exported.Evidence) (stop bool, err error) {
|
||||
anyEvi, err := codectypes.NewAnyWithValue(value)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
gs.Evidence = append(gs.Evidence, anyEvi)
|
||||
return false, nil
|
||||
})
|
||||
if err != nil && !errors.Is(err, collections.ErrInvalidIterator) {
|
||||
panic(err)
|
||||
}
|
||||
evidence := make([]*codectypes.Any, len(e))
|
||||
for i, evi := range e {
|
||||
msg, ok := evi.(proto.Message)
|
||||
if !ok {
|
||||
panic(fmt.Errorf("cannot proto marshal %T", evi))
|
||||
}
|
||||
any, err := codectypes.NewAnyWithValue(msg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
evidence[i] = any
|
||||
}
|
||||
return &types.GenesisState{
|
||||
Evidence: evidence,
|
||||
}
|
||||
return gs
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/x/evidence"
|
||||
@ -73,7 +74,7 @@ func (suite *GenesisTestSuite) TestInitGenesis() {
|
||||
true,
|
||||
func() {
|
||||
for _, e := range testEvidence {
|
||||
_, err := suite.keeper.GetEvidence(suite.ctx, e.Hash())
|
||||
_, err := suite.keeper.Evidences.Get(suite.ctx, e.Hash())
|
||||
suite.NoError(err)
|
||||
}
|
||||
},
|
||||
@ -93,9 +94,8 @@ func (suite *GenesisTestSuite) TestInitGenesis() {
|
||||
},
|
||||
false,
|
||||
func() {
|
||||
ev, err := suite.keeper.GetAllEvidence(suite.ctx)
|
||||
suite.Empty(ev)
|
||||
suite.NoError(err)
|
||||
_, err := suite.keeper.Evidences.Iterate(suite.ctx, nil)
|
||||
suite.Require().ErrorIs(err, collections.ErrInvalidIterator)
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -133,12 +133,13 @@ func (suite *GenesisTestSuite) TestExportGenesis() {
|
||||
{
|
||||
"success",
|
||||
func() {
|
||||
suite.keeper.SetEvidence(suite.ctx, &types.Equivocation{
|
||||
ev := &types.Equivocation{
|
||||
Height: 1,
|
||||
Power: 100,
|
||||
Time: time.Now().UTC(),
|
||||
ConsensusAddress: pk.PubKey().Address().String(),
|
||||
})
|
||||
}
|
||||
suite.Require().NoError(suite.keeper.Evidences.Set(suite.ctx, ev.Hash(), ev))
|
||||
},
|
||||
true,
|
||||
func() {},
|
||||
|
||||
@ -5,14 +5,13 @@ import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/store/prefix"
|
||||
"cosmossdk.io/x/evidence/exported"
|
||||
"cosmossdk.io/x/evidence/types"
|
||||
proto "github.com/cosmos/gogoproto/proto"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/query"
|
||||
)
|
||||
@ -20,15 +19,15 @@ import (
|
||||
var _ types.QueryServer = Querier{}
|
||||
|
||||
type Querier struct {
|
||||
*Keeper
|
||||
k *Keeper
|
||||
}
|
||||
|
||||
func NewQuerier(keeper *Keeper) Querier {
|
||||
return Querier{Keeper: keeper}
|
||||
return Querier{k: keeper}
|
||||
}
|
||||
|
||||
// Evidence implements the Query/Evidence gRPC method
|
||||
func (k Keeper) Evidence(c context.Context, req *types.QueryEvidenceRequest) (*types.QueryEvidenceResponse, error) {
|
||||
func (k Querier) Evidence(c context.Context, req *types.QueryEvidenceRequest) (*types.QueryEvidenceResponse, error) {
|
||||
if req == nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
@ -44,7 +43,7 @@ func (k Keeper) Evidence(c context.Context, req *types.QueryEvidenceRequest) (*t
|
||||
return nil, fmt.Errorf("invalid evidence hash: %w", err)
|
||||
}
|
||||
|
||||
evidence, _ := k.GetEvidence(ctx, decodedHash)
|
||||
evidence, _ := k.k.Evidences.Get(ctx, decodedHash)
|
||||
if evidence == nil {
|
||||
return nil, status.Errorf(codes.NotFound, "evidence %s not found", req.Hash)
|
||||
}
|
||||
@ -63,35 +62,22 @@ func (k Keeper) Evidence(c context.Context, req *types.QueryEvidenceRequest) (*t
|
||||
}
|
||||
|
||||
// AllEvidence implements the Query/AllEvidence gRPC method
|
||||
func (k Keeper) AllEvidence(c context.Context, req *types.QueryAllEvidenceRequest) (*types.QueryAllEvidenceResponse, error) {
|
||||
func (k Querier) AllEvidence(ctx context.Context, req *types.QueryAllEvidenceRequest) (*types.QueryAllEvidenceResponse, error) {
|
||||
if req == nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
var evidence []*codectypes.Any
|
||||
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(c))
|
||||
evidenceStore := prefix.NewStore(store, types.KeyPrefixEvidence)
|
||||
|
||||
pageRes, err := query.Paginate(evidenceStore, req.Pagination, func(key, value []byte) error {
|
||||
result, err := k.UnmarshalEvidence(value)
|
||||
_, pageRes, err := query.CollectionFilteredPaginate(ctx, k.k.Evidences, req.Pagination, func(_ []byte, value exported.Evidence) (include bool, err error) {
|
||||
evidenceAny, err := codectypes.NewAnyWithValue(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg, ok := result.(proto.Message)
|
||||
if !ok {
|
||||
return status.Errorf(codes.Internal, "can't protomarshal %T", msg)
|
||||
}
|
||||
|
||||
evidenceAny, err := codectypes.NewAnyWithValue(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
evidence = append(evidence, evidenceAny)
|
||||
return nil
|
||||
return false, nil // we don't include results because we're appending them
|
||||
})
|
||||
if err != nil {
|
||||
return &types.QueryAllEvidenceResponse{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.QueryAllEvidenceResponse{Evidence: evidence, Pagination: pageRes}, nil
|
||||
|
||||
@ -144,5 +144,5 @@ func (k Keeper) handleEquivocationEvidence(ctx context.Context, evidence *types.
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return k.SetEvidence(ctx, evidence)
|
||||
return k.Evidences.Set(ctx, evidence.Hash(), evidence)
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
"cosmossdk.io/core/address"
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/log"
|
||||
@ -14,11 +15,7 @@ import (
|
||||
|
||||
"cosmossdk.io/core/comet"
|
||||
"cosmossdk.io/errors"
|
||||
"cosmossdk.io/store/prefix"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
@ -34,6 +31,9 @@ type Keeper struct {
|
||||
addressCodec address.Codec
|
||||
|
||||
cometInfo comet.BlockInfoService
|
||||
|
||||
Schema collections.Schema
|
||||
Evidences collections.Map[[]byte, exported.Evidence]
|
||||
}
|
||||
|
||||
// NewKeeper creates a new Keeper object.
|
||||
@ -41,14 +41,22 @@ func NewKeeper(
|
||||
cdc codec.BinaryCodec, storeService store.KVStoreService, stakingKeeper types.StakingKeeper,
|
||||
slashingKeeper types.SlashingKeeper, ac address.Codec, ci comet.BlockInfoService,
|
||||
) *Keeper {
|
||||
return &Keeper{
|
||||
sb := collections.NewSchemaBuilder(storeService)
|
||||
k := &Keeper{
|
||||
cdc: cdc,
|
||||
storeService: storeService,
|
||||
stakingKeeper: stakingKeeper,
|
||||
slashingKeeper: slashingKeeper,
|
||||
addressCodec: ac,
|
||||
cometInfo: ci,
|
||||
Evidences: collections.NewMap(sb, types.KeyPrefixEvidence, "evidences", collections.BytesKey, codec.CollInterfaceValue[exported.Evidence](cdc)),
|
||||
}
|
||||
schema, err := sb.Build()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
k.Schema = schema
|
||||
return k
|
||||
}
|
||||
|
||||
// Logger returns a module-specific logger.
|
||||
@ -90,7 +98,7 @@ func (k Keeper) GetEvidenceHandler(evidenceRoute string) (types.Handler, error)
|
||||
// registered Handler exists or if the Handler fails. Otherwise, the evidence is
|
||||
// persisted.
|
||||
func (k Keeper) SubmitEvidence(ctx context.Context, evidence exported.Evidence) error {
|
||||
if _, err := k.GetEvidence(ctx, evidence.Hash()); err == nil {
|
||||
if _, err := k.Evidences.Get(ctx, evidence.Hash()); err == nil {
|
||||
return errors.Wrap(types.ErrEvidenceExists, strings.ToUpper(hex.EncodeToString(evidence.Hash())))
|
||||
}
|
||||
if !k.router.HasRoute(evidence.Route()) {
|
||||
@ -110,100 +118,5 @@ func (k Keeper) SubmitEvidence(ctx context.Context, evidence exported.Evidence)
|
||||
),
|
||||
)
|
||||
|
||||
return k.SetEvidence(ctx, evidence)
|
||||
}
|
||||
|
||||
// SetEvidence sets Evidence by hash in the module's KVStore.
|
||||
func (k Keeper) SetEvidence(ctx context.Context, evidence exported.Evidence) error {
|
||||
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
|
||||
prefixStore := prefix.NewStore(store, types.KeyPrefixEvidence)
|
||||
prefixStore.Set(evidence.Hash(), k.MustMarshalEvidence(evidence))
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetEvidence retrieves Evidence by hash if it exists. If no Evidence exists for
|
||||
// the given hash, (nil, types.ErrNoEvidenceExists) is returned.
|
||||
func (k Keeper) GetEvidence(ctx context.Context, hash []byte) (exported.Evidence, error) {
|
||||
store := k.storeService.OpenKVStore(ctx)
|
||||
bz, err := store.Get(types.EvidenceKey(hash))
|
||||
if len(bz) == 0 {
|
||||
return nil, types.ErrNoEvidenceExists
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return k.UnmarshalEvidence(bz)
|
||||
}
|
||||
|
||||
// IterateEvidence provides an interator over all stored Evidence objects. For
|
||||
// each Evidence object, cb will be called. If the cb returns true, the iterator
|
||||
// will close and stop.
|
||||
func (k Keeper) IterateEvidence(ctx context.Context, cb func(exported.Evidence) error) error {
|
||||
store := k.storeService.OpenKVStore(ctx)
|
||||
iterator, err := store.Iterator(types.KeyPrefixEvidence, storetypes.PrefixEndBytes(types.KeyPrefixEvidence))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer iterator.Close()
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
evidence, err := k.UnmarshalEvidence(iterator.Value())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cb(evidence)
|
||||
if errors.IsOf(err, errors.ErrStopIterating) {
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAllEvidence returns all stored Evidence objects.
|
||||
func (k Keeper) GetAllEvidence(ctx context.Context) (evidence []exported.Evidence, err error) {
|
||||
err = k.IterateEvidence(ctx, func(e exported.Evidence) error {
|
||||
evidence = append(evidence, e)
|
||||
return nil
|
||||
})
|
||||
|
||||
return evidence, err
|
||||
}
|
||||
|
||||
// MustUnmarshalEvidence attempts to decode and return an Evidence object from
|
||||
// raw encoded bytes. It panics on error.
|
||||
func (k Keeper) MustUnmarshalEvidence(bz []byte) exported.Evidence {
|
||||
evidence, err := k.UnmarshalEvidence(bz)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to decode evidence: %w", err))
|
||||
}
|
||||
|
||||
return evidence
|
||||
}
|
||||
|
||||
// MustMarshalEvidence attempts to encode an Evidence object and returns the
|
||||
// raw encoded bytes. It panics on error.
|
||||
func (k Keeper) MustMarshalEvidence(evidence exported.Evidence) []byte {
|
||||
bz, err := k.MarshalEvidence(evidence)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to encode evidence: %w", err))
|
||||
}
|
||||
|
||||
return bz
|
||||
}
|
||||
|
||||
// MarshalEvidence protobuf serializes an Evidence interface
|
||||
func (k Keeper) MarshalEvidence(evidenceI exported.Evidence) ([]byte, error) {
|
||||
return k.cdc.MarshalInterface(evidenceI)
|
||||
}
|
||||
|
||||
// UnmarshalEvidence returns an Evidence interface from raw encoded evidence
|
||||
// bytes of a Proto-based Evidence type
|
||||
func (k Keeper) UnmarshalEvidence(bz []byte) (exported.Evidence, error) {
|
||||
var evi exported.Evidence
|
||||
return evi, k.cdc.UnmarshalInterface(bz, &evi)
|
||||
return k.Evidences.Set(ctx, evidence.Hash(), evidence)
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
"cosmossdk.io/x/evidence"
|
||||
"cosmossdk.io/x/evidence/exported"
|
||||
"cosmossdk.io/x/evidence/keeper"
|
||||
@ -125,7 +126,7 @@ func (suite *KeeperTestSuite) SetupTest() {
|
||||
suite.accountKeeper = accountKeeper
|
||||
|
||||
queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.encCfg.InterfaceRegistry)
|
||||
types.RegisterQueryServer(queryHelper, evidenceKeeper)
|
||||
types.RegisterQueryServer(queryHelper, keeper.NewQuerier(evidenceKeeper))
|
||||
suite.queryClient = types.NewQueryClient(queryHelper)
|
||||
suite.evidenceKeeper = *evidenceKeeper
|
||||
|
||||
@ -167,7 +168,7 @@ func (suite *KeeperTestSuite) TestSubmitValidEvidence() {
|
||||
|
||||
suite.Nil(suite.evidenceKeeper.SubmitEvidence(ctx, e))
|
||||
|
||||
res, err := suite.evidenceKeeper.GetEvidence(ctx, e.Hash())
|
||||
res, err := suite.evidenceKeeper.Evidences.Get(ctx, e.Hash())
|
||||
suite.NoError(err)
|
||||
suite.Equal(e, res)
|
||||
}
|
||||
@ -186,7 +187,7 @@ func (suite *KeeperTestSuite) TestSubmitValidEvidence_Duplicate() {
|
||||
suite.Nil(suite.evidenceKeeper.SubmitEvidence(ctx, e))
|
||||
suite.Error(suite.evidenceKeeper.SubmitEvidence(ctx, e))
|
||||
|
||||
res, err := suite.evidenceKeeper.GetEvidence(ctx, e.Hash())
|
||||
res, err := suite.evidenceKeeper.Evidences.Get(ctx, e.Hash())
|
||||
suite.NoError(err)
|
||||
suite.Equal(e, res)
|
||||
}
|
||||
@ -204,8 +205,8 @@ func (suite *KeeperTestSuite) TestSubmitInvalidEvidence() {
|
||||
err := suite.evidenceKeeper.SubmitEvidence(ctx, e)
|
||||
suite.ErrorIs(err, types.ErrInvalidEvidence)
|
||||
|
||||
res, err := suite.evidenceKeeper.GetEvidence(ctx, e.Hash())
|
||||
suite.ErrorIs(err, types.ErrNoEvidenceExists)
|
||||
res, err := suite.evidenceKeeper.Evidences.Get(ctx, e.Hash())
|
||||
suite.ErrorIs(err, collections.ErrNotFound)
|
||||
suite.Nil(res)
|
||||
}
|
||||
|
||||
@ -214,9 +215,12 @@ func (suite *KeeperTestSuite) TestIterateEvidence() {
|
||||
numEvidence := 100
|
||||
suite.populateEvidence(ctx, numEvidence)
|
||||
|
||||
evidence, err := suite.evidenceKeeper.GetAllEvidence(ctx)
|
||||
suite.Len(evidence, numEvidence)
|
||||
suite.NoError(err)
|
||||
var evidences []exported.Evidence
|
||||
suite.Require().NoError(suite.evidenceKeeper.Evidences.Walk(ctx, nil, func(key []byte, value exported.Evidence) (stop bool, err error) {
|
||||
evidences = append(evidences, value)
|
||||
return false, nil
|
||||
}))
|
||||
suite.Len(evidences, numEvidence)
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGetEvidenceHandler() {
|
||||
|
||||
@ -144,7 +144,7 @@ func (am AppModule) Name() string {
|
||||
// RegisterServices registers module services.
|
||||
func (am AppModule) RegisterServices(registrar grpc.ServiceRegistrar) error {
|
||||
types.RegisterMsgServer(registrar, keeper.NewMsgServerImpl(am.keeper))
|
||||
types.RegisterQueryServer(registrar, am.keeper)
|
||||
types.RegisterQueryServer(registrar, keeper.NewQuerier(&am.keeper))
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -183,7 +183,7 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
|
||||
|
||||
// RegisterStoreDecoder registers a decoder for evidence module's types
|
||||
func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
|
||||
sdr[types.StoreKey] = simulation.NewDecodeStore(am.keeper)
|
||||
sdr[types.StoreKey] = simtypes.NewStoreDecoderFuncFromCollectionsSchema(am.keeper.Schema)
|
||||
}
|
||||
|
||||
// WeightedOperations returns the all the gov module operations with their respective weights.
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
package simulation
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/x/evidence/exported"
|
||||
"cosmossdk.io/x/evidence/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/kv"
|
||||
)
|
||||
|
||||
type EvidenceUnmarshaler interface {
|
||||
UnmarshalEvidence([]byte) (exported.Evidence, error)
|
||||
}
|
||||
|
||||
// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's
|
||||
// Value to the corresponding evidence type.
|
||||
func NewDecodeStore(cdc EvidenceUnmarshaler) func(kvA, kvB kv.Pair) string {
|
||||
return func(kvA, kvB kv.Pair) string {
|
||||
switch {
|
||||
case bytes.Equal(kvA.Key[:1], types.KeyPrefixEvidence):
|
||||
evidenceA, err := cdc.UnmarshalEvidence(kvA.Value)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot unmarshal evidence: %s", err.Error()))
|
||||
}
|
||||
|
||||
evidenceB, err := cdc.UnmarshalEvidence(kvB.Value)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot unmarshal evidence: %s", err.Error()))
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v\n%v", evidenceA, evidenceB)
|
||||
default:
|
||||
panic(fmt.Sprintf("invalid %s key prefix %X", types.ModuleName, kvA.Key[:1]))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,74 +0,0 @@
|
||||
package simulation_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/x/evidence/keeper"
|
||||
"cosmossdk.io/x/evidence/simulation"
|
||||
"cosmossdk.io/x/evidence/testutil"
|
||||
"cosmossdk.io/x/evidence/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/kv"
|
||||
)
|
||||
|
||||
func TestDecodeStore(t *testing.T) {
|
||||
var evidenceKeeper keeper.Keeper
|
||||
err := depinject.Inject(depinject.Configs(
|
||||
testutil.AppConfig,
|
||||
depinject.Supply(log.NewNopLogger()),
|
||||
), &evidenceKeeper)
|
||||
require.NoError(t, err)
|
||||
|
||||
dec := simulation.NewDecodeStore(evidenceKeeper)
|
||||
|
||||
delPk1 := ed25519.GenPrivKey().PubKey()
|
||||
|
||||
ev := &types.Equivocation{
|
||||
Height: 10,
|
||||
Time: time.Now().UTC(),
|
||||
Power: 1000,
|
||||
ConsensusAddress: sdk.ConsAddress(delPk1.Address()).String(),
|
||||
}
|
||||
|
||||
evBz, err := evidenceKeeper.MarshalEvidence(ev)
|
||||
require.NoError(t, err)
|
||||
|
||||
kvPairs := kv.Pairs{
|
||||
Pairs: []kv.Pair{
|
||||
{
|
||||
Key: types.KeyPrefixEvidence,
|
||||
Value: evBz,
|
||||
},
|
||||
{
|
||||
Key: []byte{0x99},
|
||||
Value: []byte{0x99},
|
||||
},
|
||||
},
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
expectedLog string
|
||||
}{
|
||||
{"Evidence", fmt.Sprintf("%v\n%v", ev, ev)},
|
||||
{"other", ""},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
i, tt := i, tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
switch i {
|
||||
case len(tests) - 1:
|
||||
require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name)
|
||||
default:
|
||||
require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,5 @@ import "cosmossdk.io/errors"
|
||||
var (
|
||||
ErrNoEvidenceHandlerExists = errors.Register(ModuleName, 2, "unregistered handler for evidence type")
|
||||
ErrInvalidEvidence = errors.Register(ModuleName, 3, "invalid evidence")
|
||||
ErrNoEvidenceExists = errors.Register(ModuleName, 4, "evidence does not exist")
|
||||
ErrEvidenceExists = errors.Register(ModuleName, 5, "evidence already exists")
|
||||
)
|
||||
|
||||
@ -1,24 +1,16 @@
|
||||
package types
|
||||
|
||||
import "cosmossdk.io/collections"
|
||||
|
||||
const (
|
||||
// ModuleName defines the module name
|
||||
ModuleName = "evidence"
|
||||
|
||||
// StoreKey defines the primary module store key
|
||||
StoreKey = ModuleName
|
||||
|
||||
// RouterKey defines the module's message routing key
|
||||
RouterKey = ModuleName
|
||||
)
|
||||
|
||||
// KVStore key prefixes
|
||||
var (
|
||||
KeyPrefixEvidence = []byte{0x00}
|
||||
KeyPrefixEvidence = collections.NewPrefix(0)
|
||||
)
|
||||
|
||||
func EvidenceKey(hash []byte) (key []byte) {
|
||||
key = make([]byte, len(KeyPrefixEvidence)+len(hash))
|
||||
copy(key, KeyPrefixEvidence)
|
||||
copy(key[len(KeyPrefixEvidence):], hash)
|
||||
return
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user