Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/evidence: StoreDecoder simulation #6035

Merged
merged 15 commits into from
Apr 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ functionality that requires an online connection.
* (client) [\#5895](https://github.com/cosmos/cosmos-sdk/issues/5895) show config options in the config command's help screen.
* (types/rest) [\#5900](https://github.com/cosmos/cosmos-sdk/pull/5900) Add Check*Error function family to spare developers from replicating tons of boilerplate code.
* (x/evidence) [\#5952](https://github.com/cosmos/cosmos-sdk/pull/5952) Tendermint Consensus parameters can now be changed via parameter change proposals through `x/gov`.
* (x/evidence) [\#5961](https://github.com/cosmos/cosmos-sdk/issues/5961) Add `StoreDecoder` simulation for evidence module.
* (x/auth/ante) [\#6040](https://github.com/cosmos/cosmos-sdk/pull/6040) `AccountKeeper` interface used for `NewAnteHandler` and handler's decorators to add support of using custom `AccountKeeper` implementations.
* (simulation) [\#6002](https://github.com/cosmos/cosmos-sdk/pull/6002) Add randomized consensus params into simulation.

Expand Down
3 changes: 2 additions & 1 deletion simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ func NewSimApp(
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
upgrade.NewAppModule(app.UpgradeKeeper),
evidence.NewAppModule(app.EvidenceKeeper),
evidence.NewAppModule(appCodec, app.EvidenceKeeper),
ibc.NewAppModule(app.IBCKeeper),
params.NewAppModule(app.ParamsKeeper),
transferModule,
Expand Down Expand Up @@ -313,6 +313,7 @@ func NewSimApp(
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
params.NewAppModule(app.ParamsKeeper),
evidence.NewAppModule(appCodec, app.EvidenceKeeper),
)

app.sm.RegisterStoreDecoders()
Expand Down
2 changes: 2 additions & 0 deletions simapp/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/evidence"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/mint"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
Expand Down Expand Up @@ -156,6 +157,7 @@ func TestAppImportExport(t *testing.T) {
{app.keys[bank.StoreKey], newApp.keys[bank.StoreKey], [][]byte{bank.BalancesPrefix}},
{app.keys[paramtypes.StoreKey], newApp.keys[paramtypes.StoreKey], [][]byte{}},
{app.keys[gov.StoreKey], newApp.keys[gov.StoreKey], [][]byte{}},
{app.keys[evidence.StoreKey], newApp.keys[evidence.StoreKey], [][]byte{}},
}

for _, skp := range storeKeysPrefixes {
Expand Down
47 changes: 40 additions & 7 deletions x/evidence/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,27 @@ package evidence
import (
"encoding/json"
"fmt"
"math/rand"

"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/evidence/client"
"github.com/cosmos/cosmos-sdk/x/evidence/client/cli"
"github.com/cosmos/cosmos-sdk/x/evidence/client/rest"
"github.com/cosmos/cosmos-sdk/x/evidence/simulation"

"github.com/gorilla/mux"
"github.com/spf13/cobra"
abci "github.com/tendermint/tendermint/abci/types"
)

var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}

// TODO: Enable simulation once concrete types are defined.
// _ module.AppModuleSimulation = AppModuleSimulation{}
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModule{}
)

// ----------------------------------------------------------------------------
Expand All @@ -31,9 +32,11 @@ var (

// AppModuleBasic implements the AppModuleBasic interface for the evidence module.
type AppModuleBasic struct {
cdc Codec
evidenceHandlers []client.EvidenceHandler // client evidence submission handlers
}

// NewAppModuleBasic crates a AppModuleBasic without the codec.
func NewAppModuleBasic(evidenceHandlers ...client.EvidenceHandler) AppModuleBasic {
return AppModuleBasic{
evidenceHandlers: evidenceHandlers,
Expand Down Expand Up @@ -103,9 +106,9 @@ type AppModule struct {
keeper Keeper
}

func NewAppModule(keeper Keeper) AppModule {
func NewAppModule(cdc Codec, keeper Keeper) AppModule {
return AppModule{
AppModuleBasic: NewAppModuleBasic(),
AppModuleBasic: AppModuleBasic{cdc: cdc},
keeper: keeper,
}
}
Expand Down Expand Up @@ -166,3 +169,33 @@ func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

//____________________________________________________________________________

// AppModuleSimulation functions

// GenerateGenesisState creates a randomized GenState of the evidence module.
func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}

// ProposalContents returns all the evidence content functions used to
// simulate governance proposals.
func (am AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
return nil
}

// RandomizedParams creates randomized evidence param changes for the simulator.
func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange {
return nil
}

// RegisterStoreDecoder registers a decoder for evidence module's types
func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.NewDecodeStore(am.cdc)
}

// WeightedOperations returns the all the gov module operations with their respective weights.
func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation {
return nil
}
32 changes: 32 additions & 0 deletions x/evidence/simulation/decoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package simulation

import (
"bytes"
"fmt"

tmkv "github.com/tendermint/tendermint/libs/kv"

"github.com/cosmos/cosmos-sdk/x/evidence/types"
)

// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's
// Value to the corresponding evidence type.
func NewDecodeStore(cdc types.Codec) func(kvA, kvB tmkv.Pair) string {
return func(kvA, kvB tmkv.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]))
}
}
}
64 changes: 64 additions & 0 deletions x/evidence/simulation/decoder_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package simulation_test

import (
"fmt"
"testing"
"time"

"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/ed25519"
tmkv "github.com/tendermint/tendermint/libs/kv"

codecstd "github.com/cosmos/cosmos-sdk/codec/std"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/evidence/simulation"
"github.com/cosmos/cosmos-sdk/x/evidence/types"
)

func TestDecodeStore(t *testing.T) {
cdc := codecstd.NewAppCodec(codecstd.MakeCodec(simapp.ModuleBasics))
dec := simulation.NewDecodeStore(cdc)

delPk1 := ed25519.GenPrivKey().PubKey()

ev := types.Equivocation{
Height: 10,
Time: time.Now().UTC(),
Power: 1000,
ConsensusAddress: sdk.ConsAddress(delPk1.Address()),
}

evBz, err := cdc.MarshalEvidence(&ev)
require.NoError(t, err)

kvPairs := tmkv.Pairs{
tmkv.Pair{
Key: types.KeyPrefixEvidence,
Value: evBz,
},
tmkv.Pair{
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[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, dec(kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}
37 changes: 37 additions & 0 deletions x/evidence/simulation/genesis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package simulation

// DONTCOVER

import (
"fmt"
"math/rand"

"github.com/cosmos/cosmos-sdk/codec"

"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/evidence/exported"
"github.com/cosmos/cosmos-sdk/x/evidence/types"
)

// Simulation parameter constants
const evidence = "evidence"

// GenEvidences returns an empty slice of evidences.
func GenEvidences(_ *rand.Rand, _ []simtypes.Account) []exported.Evidence {
return []exported.Evidence{}
}

// RandomizedGenState generates a random GenesisState for evidence
func RandomizedGenState(simState *module.SimulationState) {
var ev []exported.Evidence
simState.AppParams.GetOrGenerate(
simState.Cdc, evidence, &ev, simState.Rand,
func(r *rand.Rand) { ev = GenEvidences(r, simState.Accounts) },
)

evidenceGenesis := types.GenesisState{Evidence: ev}

fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, codec.MustMarshalJSONIndent(simState.Cdc, evidenceGenesis))
simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(evidenceGenesis)
}
7 changes: 6 additions & 1 deletion x/evidence/types/genesis.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package types

import (
"fmt"

"github.com/cosmos/cosmos-sdk/x/evidence/exported"
)

Expand All @@ -27,7 +29,10 @@ func DefaultGenesisState() GenesisState {
// Validate performs basic gensis state validation returning an error upon any
// failure.
func (gs GenesisState) Validate() error {
for _, e := range gs.Evidence {
for i, e := range gs.Evidence {
if e == nil {
return fmt.Errorf("evidence %d cannot be nil", i)
}
if err := e.ValidateBasic(); err != nil {
return err
}
Expand Down