Merge PR #5952: Refactor Evidence Age Util + Governable Consensus Params

This commit is contained in:
Alexander Bezobchuk 2020-04-16 11:10:39 -04:00 committed by GitHub
parent b26109c5dc
commit 09a55f68b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 521 additions and 665 deletions

View File

@ -52,6 +52,7 @@ that parse log messages.
older clients.
* (x/auth) [\#5844](https://github.com/cosmos/cosmos-sdk/pull/5844) `tx sign` command now returns an error when signing is attempted with offline/multisig keys.
* (client/keys) [\#5889](https://github.com/cosmos/cosmos-sdk/pull/5889) Remove `keys update` command.
* (x/evidence) [\#5952](https://github.com/cosmos/cosmos-sdk/pull/5952) Remove CLI and REST handlers for querying `x/evidence` parameters.
* (server) [\#5982](https://github.com/cosmos/cosmos-sdk/pull/5982) `--pruning` now must be set to `custom` if you want to customise the granular options.
### API Breaking Changes
@ -87,6 +88,8 @@ constructor is provided [\#5889](https://github.com/cosmos/cosmos-sdk/pull/5889)
to new keyring backends. Plus, the package and the new keyring no longer depends on the sdk.Config singleton. Please consult the package documentation for more
information on how to implement the new `Keyring` interface.
* [\#5858](https://github.com/cosmos/cosmos-sdk/pull/5858) Make Keyring store keys by name and address's hexbytes representation.
* (x/evidence) [\#5952](https://github.com/cosmos/cosmos-sdk/pull/5952) Remove APIs for getting and setting `x/evidence` parameters. `BaseApp` now uses a `ParamStore` to manage Tendermint consensus parameters which is managed via the `x/params` `Substore` type.
* (export) [\#5952](https://github.com/cosmos/cosmos-sdk/pull/5952) `AppExporter` now returns ABCI consensus parameters to be included in marshaled exported state. These parameters must be returned from the application via the `BaseApp`.
### Features
@ -185,6 +188,7 @@ Buffers for state serialization instead of Amino.
* The module now accepts a `Codec` interface which extends the `codec.Marshaler` interface by
requiring a concrete codec to know how to serialize `Proposal` types.
* (codec) [\#5799](https://github.com/cosmos/cosmos-sdk/pull/5799) Now we favor the use of `(Un)MarshalBinaryBare` instead of `(Un)MarshalBinaryLengthPrefixed` in all cases that are not needed.
* (x/evidence) [\#5952](https://github.com/cosmos/cosmos-sdk/pull/5952) Remove parameters from `x/evidence` genesis and module state. The `x/evidence` module now solely uses Tendermint consensus parameters to determine of evidence is valid or not.
### Improvements
@ -207,6 +211,7 @@ functionality that requires an online connection.
* (client) [\#5856](https://github.com/cosmos/cosmos-sdk/pull/5856) Added the possibility to set `--offline` flag with config command.
* (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`.
## [v0.38.3] - 2020-04-09

View File

@ -17,18 +17,19 @@ import (
// InitChain implements the ABCI interface. It runs the initialization logic
// directly on the CommitMultiStore.
func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) {
// stash the consensus params in the cms main store and memoize
if req.ConsensusParams != nil {
app.setConsensusParams(req.ConsensusParams)
app.storeConsensusParams(req.ConsensusParams)
}
initHeader := abci.Header{ChainID: req.ChainId, Time: req.Time}
// initialize the deliver state and check state with a correct header
app.setDeliverState(initHeader)
app.setCheckState(initHeader)
// Store the consensus params in the BaseApp's paramstore. Note, this must be
// done after the deliver state and context have been set as it's persisted
// to state.
if req.ConsensusParams != nil {
app.storeConsensusParams(app.deliverState.ctx, req.ConsensusParams)
}
if app.initChainer == nil {
return
}
@ -124,7 +125,7 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg
// add block gas meter
var gasMeter sdk.GasMeter
if maxGas := app.getMaximumBlockGas(); maxGas > 0 {
if maxGas := app.getMaximumBlockGas(app.deliverState.ctx); maxGas > 0 {
gasMeter = sdk.NewGasMeter(maxGas)
} else {
gasMeter = sdk.NewInfiniteGasMeter()

View File

@ -1,13 +1,11 @@
package baseapp
import (
"errors"
"fmt"
"reflect"
"runtime/debug"
"strings"
"github.com/gogo/protobuf/proto"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/tmhash"
"github.com/tendermint/tendermint/libs/log"
@ -23,9 +21,6 @@ const (
runTxModeReCheck // Recheck a (pending) transaction after a commit
runTxModeSimulate // Simulate a transaction
runTxModeDeliver // Deliver a transaction
// MainStoreKey is the string representation of the main store
MainStoreKey = "main"
)
var (
@ -59,9 +54,6 @@ type BaseApp struct { // nolint: maligned
queryRouter sdk.QueryRouter // router for redirecting query calls
txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx
// set upon LoadVersion or LoadLatestVersion.
baseKey *sdk.KVStoreKey // Main KVStore in cms
anteHandler sdk.AnteHandler // ante handler for fee and auth
initChainer sdk.InitChainer // initialize state with validators and state blob
beginBlocker sdk.BeginBlocker // logic to run before any txs
@ -83,9 +75,9 @@ type BaseApp struct { // nolint: maligned
// absent validators from begin block
voteInfos []abci.VoteInfo
// consensus params
// TODO: Move this in the future to baseapp param store on main store.
consensusParams *abci.ConsensusParams
// paramStore is used to query for ABCI consensus parameters from an
// application parameter store.
paramStore ParamStore
// The minimum gas prices a validator is willing to accept for processing a
// transaction. This is mainly used for DoS and spam prevention.
@ -209,12 +201,13 @@ func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) {
// LoadLatestVersion loads the latest application version. It will panic if
// called more than once on a running BaseApp.
func (app *BaseApp) LoadLatestVersion(baseKey *sdk.KVStoreKey) error {
func (app *BaseApp) LoadLatestVersion() error {
err := app.storeLoader(app.cms)
if err != nil {
return err
return fmt.Errorf("failed to load latest version: %w", err)
}
return app.initFromMainStore(baseKey)
return app.init()
}
// DefaultStoreLoader will be used by default and loads the latest version
@ -224,12 +217,13 @@ func DefaultStoreLoader(ms sdk.CommitMultiStore) error {
// LoadVersion loads the BaseApp application version. It will panic if called
// more than once on a running baseapp.
func (app *BaseApp) LoadVersion(version int64, baseKey *sdk.KVStoreKey) error {
func (app *BaseApp) LoadVersion(version int64) error {
err := app.cms.LoadVersion(version)
if err != nil {
return err
return fmt.Errorf("failed to load version %d: %w", version, err)
}
return app.initFromMainStore(baseKey)
return app.init()
}
// LastCommitID returns the last CommitID of the multistore.
@ -242,33 +236,9 @@ func (app *BaseApp) LastBlockHeight() int64 {
return app.cms.LastCommitID().Version
}
// initializes the remaining logic from app.cms
func (app *BaseApp) initFromMainStore(baseKey *sdk.KVStoreKey) error {
mainStore := app.cms.GetKVStore(baseKey)
if mainStore == nil {
return errors.New("baseapp expects MultiStore with 'main' KVStore")
}
// memoize baseKey
if app.baseKey != nil {
panic("app.baseKey expected to be nil; duplicate init?")
}
app.baseKey = baseKey
// Load the consensus params from the main store. If the consensus params are
// nil, it will be saved later during InitChain.
//
// TODO: assert that InitChain hasn't yet been called.
consensusParamsBz := mainStore.Get(mainConsensusParamsKey)
if consensusParamsBz != nil {
var consensusParams = &abci.ConsensusParams{}
err := proto.Unmarshal(consensusParamsBz, consensusParams)
if err != nil {
panic(err)
}
app.setConsensusParams(consensusParams)
func (app *BaseApp) init() error {
if app.sealed {
panic("cannot call initFromMainStore: baseapp already sealed")
}
// needed for the export command which inits from store but never calls initchain
@ -337,30 +307,59 @@ func (app *BaseApp) setDeliverState(header abci.Header) {
}
}
// setConsensusParams memoizes the consensus params.
func (app *BaseApp) setConsensusParams(consensusParams *abci.ConsensusParams) {
app.consensusParams = consensusParams
// GetConsensusParams returns the current consensus parameters from the BaseApp's
// ParamStore. If the BaseApp has no ParamStore defined, nil is returned.
func (app *BaseApp) GetConsensusParams(ctx sdk.Context) *abci.ConsensusParams {
if app.paramStore == nil {
return nil
}
cp := new(abci.ConsensusParams)
if app.paramStore.Has(ctx, ParamStoreKeyBlockParams) {
var bp abci.BlockParams
app.paramStore.Get(ctx, ParamStoreKeyBlockParams, &bp)
cp.Block = &bp
}
if app.paramStore.Has(ctx, ParamStoreKeyEvidenceParams) {
var ep abci.EvidenceParams
app.paramStore.Get(ctx, ParamStoreKeyEvidenceParams, &ep)
cp.Evidence = &ep
}
if app.paramStore.Has(ctx, ParamStoreKeyValidatorParams) {
var vp abci.ValidatorParams
app.paramStore.Get(ctx, ParamStoreKeyValidatorParams, &vp)
cp.Validator = &vp
}
return cp
}
// setConsensusParams stores the consensus params to the main store.
func (app *BaseApp) storeConsensusParams(consensusParams *abci.ConsensusParams) {
consensusParamsBz, err := proto.Marshal(consensusParams)
if err != nil {
panic(err)
func (app *BaseApp) storeConsensusParams(ctx sdk.Context, cp *abci.ConsensusParams) {
if app.paramStore == nil {
panic("cannot store consensus params with no params store set")
}
mainStore := app.cms.GetKVStore(app.baseKey)
mainStore.Set(mainConsensusParamsKey, consensusParamsBz)
if cp == nil {
return
}
app.paramStore.Set(ctx, ParamStoreKeyBlockParams, cp.Block)
app.paramStore.Set(ctx, ParamStoreKeyEvidenceParams, cp.Evidence)
app.paramStore.Set(ctx, ParamStoreKeyValidatorParams, cp.Validator)
}
// getMaximumBlockGas gets the maximum gas from the consensus params. It panics
// if maximum block gas is less than negative one and returns zero if negative
// one.
func (app *BaseApp) getMaximumBlockGas() uint64 {
if app.consensusParams == nil || app.consensusParams.Block == nil {
func (app *BaseApp) getMaximumBlockGas(ctx sdk.Context) uint64 {
cp := app.GetConsensusParams(ctx)
if cp == nil || cp.Block == nil {
return 0
}
maxGas := app.consensusParams.Block.MaxGas
maxGas := cp.Block.MaxGas
switch {
case maxGas < -1:
panic(fmt.Sprintf("invalid maximum block gas: %d", maxGas))
@ -416,8 +415,9 @@ func (app *BaseApp) getState(mode runTxMode) *state {
func (app *BaseApp) getContextForTx(mode runTxMode, txBytes []byte) sdk.Context {
ctx := app.getState(mode).ctx.
WithTxBytes(txBytes).
WithVoteInfos(app.voteInfos).
WithConsensusParams(app.consensusParams)
WithVoteInfos(app.voteInfos)
ctx = ctx.WithConsensusParams(app.GetConsensusParams(ctx))
if mode == runTxModeReCheck {
ctx = ctx.WithIsReCheckTx(true)

View File

@ -3,6 +3,7 @@ package baseapp
import (
"bytes"
"encoding/binary"
"encoding/json"
"fmt"
"os"
"strings"
@ -12,7 +13,6 @@ import (
"github.com/gogo/protobuf/jsonpb"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
@ -29,6 +29,43 @@ var (
capKey2 = sdk.NewKVStoreKey("key2")
)
type paramStore struct {
db *dbm.MemDB
}
func (ps *paramStore) Set(_ sdk.Context, key []byte, value interface{}) {
bz, err := json.Marshal(value)
if err != nil {
panic(err)
}
ps.db.Set(key, bz)
}
func (ps *paramStore) Has(_ sdk.Context, key []byte) bool {
ok, err := ps.db.Has(key)
if err != nil {
panic(err)
}
return ok
}
func (ps *paramStore) Get(_ sdk.Context, key []byte, ptr interface{}) {
bz, err := ps.db.Get(key)
if err != nil {
panic(err)
}
if len(bz) == 0 {
return
}
if err := json.Unmarshal(bz, ptr); err != nil {
panic(err)
}
}
func defaultLogger() log.Logger {
return log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
}
@ -57,15 +94,11 @@ func setupBaseApp(t *testing.T, options ...func(*BaseApp)) *BaseApp {
app := newBaseApp(t.Name(), options...)
require.Equal(t, t.Name(), app.Name())
// no stores are mounted
require.Panics(t, func() {
app.LoadLatestVersion(capKey1)
})
app.MountStores(capKey1, capKey2)
app.SetParamStore(&paramStore{db: dbm.NewMemDB()})
// stores are mounted
err := app.LoadLatestVersion(capKey1)
err := app.LoadLatestVersion()
require.Nil(t, err)
return app
}
@ -90,9 +123,7 @@ func TestLoadVersion(t *testing.T) {
app := NewBaseApp(name, logger, db, nil, pruningOpt)
// make a cap key and mount the store
capKey := sdk.NewKVStoreKey(MainStoreKey)
app.MountStores(capKey)
err := app.LoadLatestVersion(capKey) // needed to make stores non-nil
err := app.LoadLatestVersion() // needed to make stores non-nil
require.Nil(t, err)
emptyCommitID := sdk.CommitID{}
@ -117,16 +148,15 @@ func TestLoadVersion(t *testing.T) {
// reload with LoadLatestVersion
app = NewBaseApp(name, logger, db, nil, pruningOpt)
app.MountStores(capKey)
err = app.LoadLatestVersion(capKey)
app.MountStores()
err = app.LoadLatestVersion()
require.Nil(t, err)
testLoadVersionHelper(t, app, int64(2), commitID2)
// reload with LoadVersion, see if you can commit the same block and get
// the same result
app = NewBaseApp(name, logger, db, nil, pruningOpt)
app.MountStores(capKey)
err = app.LoadVersion(1, capKey)
err = app.LoadVersion(1)
require.Nil(t, err)
testLoadVersionHelper(t, app, int64(1), commitID1)
app.BeginBlock(abci.RequestBeginBlock{Header: header})
@ -205,10 +235,8 @@ func TestSetLoader(t *testing.T) {
opts = append(opts, tc.setLoader)
}
app := NewBaseApp(t.Name(), defaultLogger(), db, nil, opts...)
capKey := sdk.NewKVStoreKey(MainStoreKey)
app.MountStores(capKey)
app.MountStores(sdk.NewKVStoreKey(tc.loadStoreKey))
err := app.LoadLatestVersion(capKey)
err := app.LoadLatestVersion()
require.Nil(t, err)
// "execute" one block
@ -250,13 +278,11 @@ func TestLoadVersionInvalid(t *testing.T) {
name := t.Name()
app := NewBaseApp(name, logger, db, nil, pruningOpt)
capKey := sdk.NewKVStoreKey(MainStoreKey)
app.MountStores(capKey)
err := app.LoadLatestVersion(capKey)
err := app.LoadLatestVersion()
require.Nil(t, err)
// require error when loading an invalid version
err = app.LoadVersion(-1, capKey)
err = app.LoadVersion(-1)
require.Error(t, err)
header := abci.Header{Height: 1}
@ -266,15 +292,14 @@ func TestLoadVersionInvalid(t *testing.T) {
// create a new app with the stores mounted under the same cap key
app = NewBaseApp(name, logger, db, nil, pruningOpt)
app.MountStores(capKey)
// require we can load the latest version
err = app.LoadVersion(1, capKey)
err = app.LoadVersion(1)
require.Nil(t, err)
testLoadVersionHelper(t, app, int64(1), commitID1)
// require error when loading an invalid version
err = app.LoadVersion(2, capKey)
err = app.LoadVersion(2)
require.Error(t, err)
}
@ -290,9 +315,10 @@ func TestLoadVersionPruning(t *testing.T) {
app := NewBaseApp(name, logger, db, nil, pruningOpt)
// make a cap key and mount the store
capKey := sdk.NewKVStoreKey(MainStoreKey)
capKey := sdk.NewKVStoreKey("key1")
app.MountStores(capKey)
err := app.LoadLatestVersion(capKey) // needed to make stores non-nil
err := app.LoadLatestVersion() // needed to make stores non-nil
require.Nil(t, err)
emptyCommitID := sdk.CommitID{}
@ -323,7 +349,8 @@ func TestLoadVersionPruning(t *testing.T) {
// reload with LoadLatestVersion, check it loads last flushed version
app = NewBaseApp(name, logger, db, nil, pruningOpt)
app.MountStores(capKey)
err = app.LoadLatestVersion(capKey)
err = app.LoadLatestVersion()
require.Nil(t, err)
testLoadVersionHelper(t, app, int64(2), commitID2)
@ -348,7 +375,7 @@ func TestLoadVersionPruning(t *testing.T) {
// reload with LoadLatestVersion, check it loads last flushed version
app = NewBaseApp(name, logger, db, nil, pruningOpt)
app.MountStores(capKey)
err = app.LoadLatestVersion(capKey)
err = app.LoadLatestVersion()
require.Nil(t, err)
testLoadVersionHelper(t, app, int64(4), commitID4)
@ -356,7 +383,7 @@ func TestLoadVersionPruning(t *testing.T) {
// and check it fails since previous flush should be pruned
app = NewBaseApp(name, logger, db, nil, pruningOpt)
app.MountStores(capKey)
err = app.LoadVersion(2, capKey)
err = app.LoadVersion(2)
require.NotNil(t, err)
}
@ -469,7 +496,7 @@ func TestInitChainer(t *testing.T) {
db := dbm.NewMemDB()
logger := defaultLogger()
app := NewBaseApp(name, logger, db, nil)
capKey := sdk.NewKVStoreKey(MainStoreKey)
capKey := sdk.NewKVStoreKey("main")
capKey2 := sdk.NewKVStoreKey("key2")
app.MountStores(capKey, capKey2)
@ -495,7 +522,7 @@ func TestInitChainer(t *testing.T) {
app.SetInitChainer(initChainer)
// stores are mounted and private members are set - sealing baseapp
err := app.LoadLatestVersion(capKey) // needed to make stores non-nil
err := app.LoadLatestVersion() // needed to make stores non-nil
require.Nil(t, err)
require.Equal(t, int64(0), app.LastBlockHeight())
@ -517,7 +544,7 @@ func TestInitChainer(t *testing.T) {
app = NewBaseApp(name, logger, db, nil)
app.SetInitChainer(initChainer)
app.MountStores(capKey, capKey2)
err = app.LoadLatestVersion(capKey) // needed to make stores non-nil
err = app.LoadLatestVersion() // needed to make stores non-nil
require.Nil(t, err)
require.Equal(t, int64(1), app.LastBlockHeight())
@ -1162,7 +1189,6 @@ func TestMaxBlockGasLimits(t *testing.T) {
return
})
}
routerOpt := func(bapp *BaseApp) {
@ -1472,18 +1498,20 @@ func TestP2PQuery(t *testing.T) {
func TestGetMaximumBlockGas(t *testing.T) {
app := setupBaseApp(t)
app.InitChain(abci.RequestInitChain{})
ctx := app.NewContext(true, abci.Header{})
app.setConsensusParams(&abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: 0}})
require.Equal(t, uint64(0), app.getMaximumBlockGas())
app.storeConsensusParams(ctx, &abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: 0}})
require.Equal(t, uint64(0), app.getMaximumBlockGas(ctx))
app.setConsensusParams(&abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: -1}})
require.Equal(t, uint64(0), app.getMaximumBlockGas())
app.storeConsensusParams(ctx, &abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: -1}})
require.Equal(t, uint64(0), app.getMaximumBlockGas(ctx))
app.setConsensusParams(&abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: 5000000}})
require.Equal(t, uint64(5000000), app.getMaximumBlockGas())
app.storeConsensusParams(ctx, &abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: 5000000}})
require.Equal(t, uint64(5000000), app.getMaximumBlockGas(ctx))
app.setConsensusParams(&abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: -5000000}})
require.Panics(t, func() { app.getMaximumBlockGas() })
app.storeConsensusParams(ctx, &abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: -5000000}})
require.Panics(t, func() { app.getMaximumBlockGas(ctx) })
}
// NOTE: represents a new custom router for testing purposes of WithRouter()

View File

@ -51,6 +51,14 @@ func (app *BaseApp) SetName(name string) {
app.name = name
}
// SetParamStore sets a parameter store on the BaseApp.
func (app *BaseApp) SetParamStore(ps ParamStore) {
if app.sealed {
panic("SetParamStore() on sealed BaseApp")
}
app.paramStore = ps
}
// SetAppVersion sets the application's version string.
func (app *BaseApp) SetAppVersion(v string) {
if app.sealed {

79
baseapp/params.go Normal file
View File

@ -0,0 +1,79 @@
package baseapp
import (
"errors"
"fmt"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Paramspace defines the parameter subspace to be used for the paramstore.
const Paramspace = "baseapp"
// Parameter store keys for all the consensus parameter types.
var (
ParamStoreKeyBlockParams = []byte("BlockParams")
ParamStoreKeyEvidenceParams = []byte("EvidenceParams")
ParamStoreKeyValidatorParams = []byte("ValidatorParams")
)
// ParamStore defines the interface the parameter store used by the BaseApp must
// fulfill.
type ParamStore interface {
Get(ctx sdk.Context, key []byte, ptr interface{})
Has(ctx sdk.Context, key []byte) bool
Set(ctx sdk.Context, key []byte, param interface{})
}
// ValidateBlockParams defines a stateless validation on BlockParams. This function
// is called whenever the parameters are updated or stored.
func ValidateBlockParams(i interface{}) error {
v, ok := i.(abci.BlockParams)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if v.MaxBytes <= 0 {
return fmt.Errorf("block maximum bytes must be positive: %d", v.MaxBytes)
}
if v.MaxGas < -1 {
return fmt.Errorf("block maximum gas must be greater than or equal to -1: %d", v.MaxGas)
}
return nil
}
// ValidateEvidenceParams defines a stateless validation on EvidenceParams. This
// function is called whenever the parameters are updated or stored.
func ValidateEvidenceParams(i interface{}) error {
v, ok := i.(abci.EvidenceParams)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if v.MaxAgeNumBlocks <= 0 {
return fmt.Errorf("evidence maximum age in blocks must be positive: %d", v.MaxAgeNumBlocks)
}
if v.MaxAgeDuration <= 0 {
return fmt.Errorf("evidence maximum age time duration must be positive: %v", v.MaxAgeDuration)
}
return nil
}
// ValidateValidatorParams defines a stateless validation on ValidatorParams. This
// function is called whenever the parameters are updated or stored.
func ValidateValidatorParams(i interface{}) error {
v, ok := i.(abci.ValidatorParams)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if len(v.PubKeyTypes) == 0 {
return errors.New("validator allowed pubkey types must not be empty")
}
return nil
}

63
baseapp/params_test.go Normal file
View File

@ -0,0 +1,63 @@
package baseapp_test
import (
"testing"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/cosmos/cosmos-sdk/baseapp"
)
func TestValidateBlockParams(t *testing.T) {
testCases := []struct {
arg interface{}
expectErr bool
}{
{nil, true},
{&abci.BlockParams{}, true},
{abci.BlockParams{}, true},
{abci.BlockParams{MaxBytes: -1, MaxGas: -1}, true},
{abci.BlockParams{MaxBytes: 2000000, MaxGas: -5}, true},
{abci.BlockParams{MaxBytes: 2000000, MaxGas: 300000}, false},
}
for _, tc := range testCases {
require.Equal(t, tc.expectErr, baseapp.ValidateBlockParams(tc.arg) != nil)
}
}
func TestValidateEvidenceParams(t *testing.T) {
testCases := []struct {
arg interface{}
expectErr bool
}{
{nil, true},
{&abci.EvidenceParams{}, true},
{abci.EvidenceParams{}, true},
{abci.EvidenceParams{MaxAgeNumBlocks: -1, MaxAgeDuration: 18004000}, true},
{abci.EvidenceParams{MaxAgeNumBlocks: 360000, MaxAgeDuration: -1}, true},
{abci.EvidenceParams{MaxAgeNumBlocks: 360000, MaxAgeDuration: 18004000}, false},
}
for _, tc := range testCases {
require.Equal(t, tc.expectErr, baseapp.ValidateEvidenceParams(tc.arg) != nil)
}
}
func TestValidateValidatorParams(t *testing.T) {
testCases := []struct {
arg interface{}
expectErr bool
}{
{nil, true},
{&abci.ValidatorParams{}, true},
{abci.ValidatorParams{}, true},
{abci.ValidatorParams{PubKeyTypes: []string{}}, true},
{abci.ValidatorParams{PubKeyTypes: []string{"secp256k1"}}, false},
}
for _, tc := range testCases {
require.Equal(t, tc.expectErr, baseapp.ValidateValidatorParams(tc.arg) != nil)
}
}

View File

@ -28,7 +28,7 @@ developers will create a custom type for their application, like so:
```go
type App struct {
// reference to a BaseApp
*bam.BaseApp
*baseapp.BaseApp
// list of application store keys
@ -45,7 +45,7 @@ management logic.
## Type Definition
The `BaseApp` type holds many important parameters for any Cosmos SDK based application.
The `BaseApp` type holds many important parameters for any Cosmos SDK based application.
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/baseapp/baseapp.go#L54-L108
@ -71,8 +71,7 @@ appropriate module for it to be processed. These `queries` are not ABCI messages
are relayed to the application from the underlying consensus engine via the ABCI message [`Query`](#query).
- [`TxDecoder`](https://godoc.org/github.com/cosmos/cosmos-sdk/types#TxDecoder): It is used to decode
raw transaction bytes relayed by the underlying Tendermint engine.
- `BaseKey`: This key is used to access the main store in the `CommitMultiStore`. The main store is
used to persist data related to the core of the application, like consensus parameters.
- [`ParamStore`](#paramstore): The parameter store used to get and set application consensus parameters.
- [`AnteHandler`](#antehandler): This handler is used to handle signature verification, fee payment,
and other pre-message execution checks when a transaction is received. It's executed during
[`CheckTx/RecheckTx`](#checktx) and [`DeliverTx`](#delivertx).
@ -122,7 +121,7 @@ the node's `min-gas-prices`.
Naturally, developers can add additional `options` based on their application's needs.
## State Updates
## State Updates
The `BaseApp` maintains two primary volatile states and a root or main state. The main state
is the canonical state of the application and the volatile states, `checkState` and `deliverState`,
@ -179,6 +178,14 @@ newly committed state and `deliverState` is set to `nil` to be reset on `BeginBl
![Commit](./baseapp_state-commit.png)
## ParamStore
During `InitChain`, the `RequestInitChain` provides `ConsensusParams` which contains parameters
related to block execution such as maximum gas and size in addition to evidence parameters. If these
parameters are non-nil, they are set in the BaseApp's `ParamStore`. Behind the scenes, the `ParamStore`
is actually managed by an `x/params` module `Subspace`. This allows the parameters to be tweaked via
on-chain governance.
## Routing
When messages and queries are received by the application, they must be routed to the appropriate module in order to be processed. Routing is done via `baseapp`, which holds a `router` for messages, and a `query router` for queries.
@ -199,7 +206,7 @@ Just like the `router`, the `query router` is initilalized with all the query ro
## Main ABCI Messages
The [Application-Blockchain Interface](https://tendermint.com/docs/spec/abci/) (ABCI) is a generic interface that connects a state-machine with a consensus engine to form a functional full-node. It can be wrapped in any language, and needs to be implemented by each application-specific blockchain built on top of an ABCI-compatible consensus engine like Tendermint.
The [Application-Blockchain Interface](https://tendermint.com/docs/spec/abci/) (ABCI) is a generic interface that connects a state-machine with a consensus engine to form a functional full-node. It can be wrapped in any language, and needs to be implemented by each application-specific blockchain built on top of an ABCI-compatible consensus engine like Tendermint.
The consensus engine handles two main tasks:
@ -376,17 +383,17 @@ Finally, `Commit` returns the hash of the commitment of `app.cms` back to the un
The [`Info` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.html#info) is a simple query from the underlying consensus engine, notably used to sync the latter with the application during a handshake that happens on startup. When called, the `Info(res abci.ResponseInfo)` function from `baseapp` will return the application's name, version and the hash of the last commit of `app.cms`.
### Query
### Query
The [`Query` ABCI message](https://tendermint.com/docs/app-dev/abci-spec.html#query) is used to serve queries received from the underlying consensus engine, including queries received via RPC like Tendermint RPC. It is the main entrypoint to build interfaces with the application. The application must respect a few rules when implementing the `Query` method, which are outlined [here](https://tendermint.com/docs/app-dev/abci-spec.html#query).
Each `query` comes with a `path`, which contains multiple `string`s. By convention, the first element of the `path` (`path[0]`) contains the category of `query` (`app`, `p2p`, `store` or `custom`). The `baseapp` implementation of the `Query(req abci.RequestQuery)` method is a simple dispatcher serving these 4 main categories of queries:
- Application-related queries like querying the application's version, which are served via the `handleQueryApp` method.
- Direct queries to the multistore, which are served by the `handlerQueryStore` method. These direct queryeis are different from custom queries which go through `app.queryRouter`, and are mainly used by third-party service provider like block explorers.
- Direct queries to the multistore, which are served by the `handlerQueryStore` method. These direct queryeis are different from custom queries which go through `app.queryRouter`, and are mainly used by third-party service provider like block explorers.
- P2P queries, which are served via the `handleQueryP2P` method. These queries return either `app.addrPeerFilter` or `app.ipPeerFilter` that contain the list of peers filtered by address or IP respectively. These lists are first initialized via `options` in `baseapp`'s [constructor](#constructor).
- Custom queries, which encompass most queries, are served via the `handleQueryCustom` method. The `handleQueryCustom` cache-wraps the multistore before using the `queryRoute` obtained from [`app.queryRouter`](#query-routing) to map the query to the appropriate module's `querier`.
## Next {hide}
Learn more about [transactions](./transactions.md) {hide}
Learn more about [transactions](./transactions.md) {hide}

View File

@ -12,7 +12,7 @@ A store is a data structure that holds the state of the application. {synopsis}
## Introduction to SDK Stores
The Cosmos SDK comes with a large set of stores to persist the state of applications. By default, the main store of SDK applications is a `multistore`, i.e. a store of stores. Developers can add any number of key-value stores to the multistore, depending on their application needs. The multistore exists to support the modularity of the Cosmos SDK, as it lets each module declare and manage their own subset of the state. Key-value stores in the multistore can only be accessed with a specific capability `key`, which is typically held in the [`keeper`](../building-modules/keeper.md) of the module that declared the store.
The Cosmos SDK comes with a large set of stores to persist the state of applications. By default, the main store of SDK applications is a `multistore`, i.e. a store of stores. Developers can add any number of key-value stores to the multistore, depending on their application needs. The multistore exists to support the modularity of the Cosmos SDK, as it lets each module declare and manage their own subset of the state. Key-value stores in the multistore can only be accessed with a specific capability `key`, which is typically held in the [`keeper`](../building-modules/keeper.md) of the module that declared the store.
```
+-----------------------------------------------------+
@ -64,7 +64,7 @@ The `GetStoreType` is a simple method that returns the type of store, whereas a
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L217-L238
Cache-wrapping is used ubiquitously in the Cosmos SDK and required to be implemented on every store type. A cache-wrapper creates a light snapshot of a store that can be passed around and updated without affecting the main underlying store. This is used to trigger temporary state-transitions that may be reverted later should an error occur. If a state-transition sequence is performed without issue, the cached store can be comitted to the underlying store at the end of the sequence.
Cache-wrapping is used ubiquitously in the Cosmos SDK and required to be implemented on every store type. A cache-wrapper creates a light snapshot of a store that can be passed around and updated without affecting the main underlying store. This is used to trigger temporary state-transitions that may be reverted later should an error occur. If a state-transition sequence is performed without issue, the cached store can be committed to the underlying store at the end of the sequence.
### Commit Store
@ -76,9 +76,9 @@ The `Committer` is an interface that defines methods to persist changes to disk:
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L17-L22
The `CommitID` is a deterministic commit of the state tree. Its hash is returned to the underlying consensus engine and stored in the block header. Note that commit store interfaces exist for various purposes, one of which is to make sure not every object can commit the store. As part of the [object-capabilities model](./ocap.md) of the Cosmos SDK, only `baseapp` should have the ability to commit stores. For example, this is the reason why the `ctx.KVStore()` method by which modules typically access stores returns a `KVStore` and not a `CommitKVStore`.
The `CommitID` is a deterministic commit of the state tree. Its hash is returned to the underlying consensus engine and stored in the block header. Note that commit store interfaces exist for various purposes, one of which is to make sure not every object can commit the store. As part of the [object-capabilities model](./ocap.md) of the Cosmos SDK, only `baseapp` should have the ability to commit stores. For example, this is the reason why the `ctx.KVStore()` method by which modules typically access stores returns a `KVStore` and not a `CommitKVStore`.
The Cosmos SDK comes with many types of stores, the most used being [`CommitMultiStore`](#multistore), [`KVStore`](#kvstore) and [`GasKv` store](#gaskv-store). [Other types of stores](#other-stores) include `Transient` and `TraceKV` stores.
The Cosmos SDK comes with many types of stores, the most used being [`CommitMultiStore`](#multistore), [`KVStore`](#kvstore) and [`GasKv` store](#gaskv-store). [Other types of stores](#other-stores) include `Transient` and `TraceKV` stores.
## Multistore
@ -100,7 +100,7 @@ As for concrete implementation, the [`rootMulti.Store`] is the go-to implementat
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/rootmulti/store.go#L27-L43
The `rootMulti.Store` is a base-layer multistore built around a `db` on top of which multiple `KVStores` can be mounted, and is the default multistore store used in [`baseapp`](./baseapp.md).
The `rootMulti.Store` is a base-layer multistore built around a `db` on top of which multiple `KVStores` can be mounted, and is the default multistore store used in [`baseapp`](./baseapp.md).
### CacheMultiStore
@ -114,11 +114,11 @@ Whenever the `rootMulti.Store` needs to be cached-wrapped, a [`cachemulti.Store`
### `KVStore` and `CommitKVStore` Interfaces
A `KVStore` is a simple key-value store used to store and retrieve data. A `CommitKVStore` is a `KVStore` that also implements a `Committer`. By default, stores mounted in `baseapp`'s main `CommitMultiStore` are `CommitKVStore`s. The `KVStore` interface is primarily used to restrict modules from accessing the committer.
A `KVStore` is a simple key-value store used to store and retrieve data. A `CommitKVStore` is a `KVStore` that also implements a `Committer`. By default, stores mounted in `baseapp`'s main `CommitMultiStore` are `CommitKVStore`s. The `KVStore` interface is primarily used to restrict modules from accessing the committer.
Individual `KVStore`s are used by modules to manage a subset of the global state. `KVStores` can be accessed by objects that hold a specific key. This `key` should only be exposed to the [`keeper`](../building-modules/keeper.md) of the module that defines the store.
Individual `KVStore`s are used by modules to manage a subset of the global state. `KVStores` can be accessed by objects that hold a specific key. This `key` should only be exposed to the [`keeper`](../building-modules/keeper.md) of the module that defines the store.
`CommitKVStore`s are declared by proxy of their respective `key` and mounted on the application's [multistore](#multistore) in the [main application file](../basics/app-anatomy.md#core-application-file). In the same file, the `key` is also passed to the module's `keeper` that is responsible for managing the store.
`CommitKVStore`s are declared by proxy of their respective `key` and mounted on the application's [multistore](#multistore) in the [main application file](../basics/app-anatomy.md#core-application-file). In the same file, the `key` is also passed to the module's `keeper` that is responsible for managing the store.
+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/store/types/store.go#L163-L193
@ -237,4 +237,4 @@ When `Store.Iterator()` is called, it does not simply prefix the `Store.prefix`,
## Next {hide}
Learn about [encoding](./encoding.md) {hide}
Learn about [encoding](./encoding.md) {hide}

View File

@ -21,7 +21,7 @@ type (
// AppExporter is a function that dumps all app state to
// JSON-serializable structure and returns the current validator set.
AppExporter func(log.Logger, dbm.DB, io.Writer, int64, bool, []string) (json.RawMessage, []tmtypes.GenesisValidator, error)
AppExporter func(log.Logger, dbm.DB, io.Writer, int64, bool, []string) (json.RawMessage, []tmtypes.GenesisValidator, *abci.ConsensusParams, error)
)
func openDB(rootDir string) (dbm.DB, error) {

View File

@ -61,7 +61,7 @@ func ExportCmd(ctx *Context, cdc codec.JSONMarshaler, appExporter AppExporter) *
forZeroHeight := viper.GetBool(flagForZeroHeight)
jailWhiteList := viper.GetStringSlice(flagJailWhitelist)
appState, validators, err := appExporter(ctx.Logger, db, traceWriter, height, forZeroHeight, jailWhiteList)
appState, validators, cp, err := appExporter(ctx.Logger, db, traceWriter, height, forZeroHeight, jailWhiteList)
if err != nil {
return fmt.Errorf("error exporting state: %v", err)
}
@ -73,6 +73,19 @@ func ExportCmd(ctx *Context, cdc codec.JSONMarshaler, appExporter AppExporter) *
doc.AppState = appState
doc.Validators = validators
doc.ConsensusParams = &tmtypes.ConsensusParams{
Block: tmtypes.BlockParams{
MaxBytes: cp.Block.MaxBytes,
MaxGas: cp.Block.MaxGas,
},
Evidence: tmtypes.EvidenceParams{
MaxAgeNumBlocks: cp.Evidence.MaxAgeNumBlocks,
MaxAgeDuration: cp.Evidence.MaxAgeDuration,
},
Validator: tmtypes.ValidatorParams{
PubKeyTypes: cp.Validator.PubKeyTypes,
},
}
encoded, err := codec.MarshalJSONIndent(cdc, doc)
if err != nil {

View File

@ -26,7 +26,7 @@ func NewApp(rootDir string, logger log.Logger) (abci.Application, error) {
}
// Capabilities key to access the main KVStore.
capKeyMainStore := sdk.NewKVStoreKey(bam.MainStoreKey)
capKeyMainStore := sdk.NewKVStoreKey("main")
// Create BaseApp.
baseApp := bam.NewBaseApp("kvstore", logger, db, decodeTx)
@ -40,7 +40,7 @@ func NewApp(rootDir string, logger log.Logger) (abci.Application, error) {
baseApp.Router().AddRoute("kvstore", KVStoreHandler(capKeyMainStore))
// Load latest version.
if err := baseApp.LoadLatestVersion(capKeyMainStore); err != nil {
if err := baseApp.LoadLatestVersion(); err != nil {
return nil, err
}

View File

@ -9,9 +9,10 @@ import (
tmos "github.com/tendermint/tendermint/libs/os"
dbm "github.com/tendermint/tm-db"
bam "github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
codecstd "github.com/cosmos/cosmos-sdk/codec/std"
"github.com/cosmos/cosmos-sdk/std"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/version"
@ -95,7 +96,7 @@ var _ App = (*SimApp)(nil)
// They are exported for convenience in creating helper functions, as object
// capabilities aren't needed for testing.
type SimApp struct {
*bam.BaseApp
*baseapp.BaseApp
cdc *codec.Codec
invCheckPeriod uint
@ -138,19 +139,19 @@ type SimApp struct {
// NewSimApp returns a reference to an initialized SimApp.
func NewSimApp(
logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, skipUpgradeHeights map[int64]bool,
homePath string, invCheckPeriod uint, baseAppOptions ...func(*bam.BaseApp),
homePath string, invCheckPeriod uint, baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
// TODO: Remove cdc in favor of appCodec once all modules are migrated.
cdc := codecstd.MakeCodec(ModuleBasics)
appCodec := codecstd.NewAppCodec(cdc)
bApp := bam.NewBaseApp(appName, logger, db, auth.DefaultTxDecoder(cdc), baseAppOptions...)
bApp := baseapp.NewBaseApp(appName, logger, db, auth.DefaultTxDecoder(cdc), baseAppOptions...)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetAppVersion(version.Version)
keys := sdk.NewKVStoreKeys(
bam.MainStoreKey, auth.StoreKey, bank.StoreKey, staking.StoreKey,
auth.StoreKey, bank.StoreKey, staking.StoreKey,
supply.StoreKey, mint.StoreKey, distr.StoreKey, slashing.StoreKey,
gov.StoreKey, params.StoreKey, ibc.StoreKey, upgrade.StoreKey,
evidence.StoreKey, transfer.StoreKey, capability.StoreKey,
@ -176,7 +177,9 @@ func NewSimApp(
app.subspaces[slashing.ModuleName] = app.ParamsKeeper.Subspace(slashing.DefaultParamspace)
app.subspaces[gov.ModuleName] = app.ParamsKeeper.Subspace(gov.DefaultParamspace).WithKeyTable(gov.ParamKeyTable())
app.subspaces[crisis.ModuleName] = app.ParamsKeeper.Subspace(crisis.DefaultParamspace)
app.subspaces[evidence.ModuleName] = app.ParamsKeeper.Subspace(evidence.DefaultParamspace)
// set the BaseApp's parameter store
bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(std.ConsensusParamsKeyTable()))
// add capability keeper and ScopeToModule for ibc module
app.CapabilityKeeper = capability.NewKeeper(appCodec, keys[capability.StoreKey])
@ -250,7 +253,7 @@ func NewSimApp(
// create evidence keeper with router
evidenceKeeper := evidence.NewKeeper(
appCodec, keys[evidence.StoreKey], app.subspaces[evidence.ModuleName], &app.StakingKeeper, app.SlashingKeeper,
appCodec, keys[evidence.StoreKey], &app.StakingKeeper, app.SlashingKeeper,
)
evidenceRouter := evidence.NewRouter().
AddRoute(ibcclient.RouterKey, ibcclient.HandlerClientMisbehaviour(app.IBCKeeper.ClientKeeper))
@ -330,8 +333,7 @@ func NewSimApp(
app.SetEndBlocker(app.EndBlocker)
if loadLatest {
err := app.LoadLatestVersion(app.keys[bam.MainStoreKey])
if err != nil {
if err := app.LoadLatestVersion(); err != nil {
tmos.Exit(err.Error())
}
}
@ -370,7 +372,7 @@ func (app *SimApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.
// LoadHeight loads a particular height
func (app *SimApp) LoadHeight(height int64) error {
return app.LoadVersion(height, app.keys[bam.MainStoreKey])
return app.LoadVersion(height)
}
// ModuleAccountAddrs returns all the app's module account addresses.

View File

@ -32,7 +32,7 @@ func TestSimAppExport(t *testing.T) {
// Making a new app object with the db, so that initchain hasn't been called
app2 := NewSimApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0)
_, _, err = app2.ExportAppStateAndValidators(false, []string{})
_, _, _, err = app2.ExportAppStateAndValidators(false, []string{})
require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
}

View File

@ -18,7 +18,7 @@ import (
// file.
func (app *SimApp) ExportAppStateAndValidators(
forZeroHeight bool, jailWhiteList []string,
) (appState json.RawMessage, validators []tmtypes.GenesisValidator, err error) {
) (appState json.RawMessage, validators []tmtypes.GenesisValidator, cp *abci.ConsensusParams, err error) {
// as if they could withdraw from the start of the next block
ctx := app.NewContext(true, abci.Header{Height: app.LastBlockHeight()})
@ -30,11 +30,11 @@ func (app *SimApp) ExportAppStateAndValidators(
genState := app.mm.ExportGenesis(ctx, app.cdc)
appState, err = codec.MarshalJSONIndent(app.cdc, genState)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
validators = staking.WriteValidators(ctx, app.StakingKeeper)
return appState, validators, nil
return appState, validators, app.BaseApp.GetConsensusParams(ctx), nil
}
// prepare for fresh start at zero height

View File

@ -116,7 +116,7 @@ func TestAppImportExport(t *testing.T) {
fmt.Printf("exporting genesis...\n")
appState, _, err := app.ExportAppStateAndValidators(false, []string{})
appState, _, _, err := app.ExportAppStateAndValidators(false, []string{})
require.NoError(t, err)
fmt.Printf("importing genesis...\n")
@ -143,7 +143,6 @@ func TestAppImportExport(t *testing.T) {
fmt.Printf("comparing stores...\n")
storeKeysPrefixes := []StoreKeysPrefixes{
{app.keys[baseapp.MainStoreKey], newApp.keys[baseapp.MainStoreKey], [][]byte{}},
{app.keys[auth.StoreKey], newApp.keys[auth.StoreKey], [][]byte{}},
{app.keys[staking.StoreKey], newApp.keys[staking.StoreKey],
[][]byte{
@ -208,7 +207,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
fmt.Printf("exporting genesis...\n")
appState, _, err := app.ExportAppStateAndValidators(true, []string{})
appState, _, _, err := app.ExportAppStateAndValidators(true, []string{})
require.NoError(t, err)
fmt.Printf("importing genesis...\n")

View File

@ -12,6 +12,7 @@ import (
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/libs/log"
tmtypes "github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tm-db"
bam "github.com/cosmos/cosmos-sdk/baseapp"
@ -24,10 +25,29 @@ import (
"github.com/cosmos/cosmos-sdk/x/supply"
)
// DefaultConsensusParams defines the default Tendermint consensus params used in
// SimApp testing.
var DefaultConsensusParams = &abci.ConsensusParams{
Block: &abci.BlockParams{
MaxBytes: 200000,
MaxGas: 2000000,
},
Evidence: &abci.EvidenceParams{
MaxAgeNumBlocks: 302400,
MaxAgeDuration: 1814400,
},
Validator: &abci.ValidatorParams{
PubKeyTypes: []string{
tmtypes.ABCIPubKeyTypeEd25519,
tmtypes.ABCIPubKeyTypeSecp256k1,
},
},
}
// Setup initializes a new SimApp. A Nop logger is set in SimApp.
func Setup(isCheckTx bool) *SimApp {
db := dbm.NewMemDB()
app := NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0)
app := NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 5)
if !isCheckTx {
// init chain must be called to stop deliverState from being nil
genesisState := NewDefaultGenesisState()
@ -39,8 +59,9 @@ func Setup(isCheckTx bool) *SimApp {
// Initialize the chain
app.InitChain(
abci.RequestInitChain{
Validators: []abci.ValidatorUpdate{},
AppStateBytes: stateBytes,
Validators: []abci.ValidatorUpdate{},
ConsensusParams: DefaultConsensusParams,
AppStateBytes: stateBytes,
},
)
}
@ -70,8 +91,9 @@ func SetupWithGenesisAccounts(genAccs []authexported.GenesisAccount, balances ..
app.InitChain(
abci.RequestInitChain{
Validators: []abci.ValidatorUpdate{},
AppStateBytes: stateBytes,
Validators: []abci.ValidatorUpdate{},
ConsensusParams: DefaultConsensusParams,
AppStateBytes: stateBytes,
},
)

View File

@ -36,7 +36,7 @@ type App interface {
// Exports the state of the application for a genesis file.
ExportAppStateAndValidators(
forZeroHeight bool, jailWhiteList []string,
) (json.RawMessage, []tmtypes.GenesisValidator, error)
) (json.RawMessage, []tmtypes.GenesisValidator, *abci.ConsensusParams, error)
// All the registered module account addreses.
ModuleAccountAddrs() map[string]bool

View File

@ -76,7 +76,7 @@ func CheckExportSimulation(
) error {
if config.ExportStatePath != "" {
fmt.Println("exporting app state...")
appState, _, err := app.ExportAppStateAndValidators(false, nil)
appState, _, _, err := app.ExportAppStateAndValidators(false, nil)
if err != nil {
return err
}

27
std/consensus_params.go Normal file
View File

@ -0,0 +1,27 @@
package std
import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/x/params"
)
// ConsensusParamsKeyTable returns an x/params module keyTable to be used in
// the BaseApp's ParamStore. The KeyTable registers the types along with the
// standard validation functions. Applications can choose to adopt this KeyTable
// or provider their own when the existing validation functions do not suite their
// needs.
func ConsensusParamsKeyTable() params.KeyTable {
return params.NewKeyTable(
params.NewParamSetPair(
baseapp.ParamStoreKeyBlockParams, abci.BlockParams{}, baseapp.ValidateBlockParams,
),
params.NewParamSetPair(
baseapp.ParamStoreKeyEvidenceParams, abci.EvidenceParams{}, baseapp.ValidateEvidenceParams,
),
params.NewParamSetPair(
baseapp.ParamStoreKeyValidatorParams, abci.ValidatorParams{}, baseapp.ValidateValidatorParams,
),
)
}

12
std/doc.go Normal file
View File

@ -0,0 +1,12 @@
/*
Package std defines all the common and standard inter-module Cosmos SDK types and definitions
modules and applications can depend on. These types and definitions serve as
convenient starting point and also to act as an example or template of how said
types and definitions can be overridden/redefined.
Typically these will be used in application-specific units of business logic. These
types and definitions are different from the types you may find in a "core" or "types"
package as those should be considered the defacto types to be used and are not
application-specific.
*/
package std

View File

@ -3,9 +3,8 @@ package transient
import (
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/store/dbadapter"
"github.com/cosmos/cosmos-sdk/store/types"
)
var _ types.Committer = (*Store)(nil)

View File

@ -1,33 +0,0 @@
package keeper_test
import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/simapp"
)
func createTestApp() *simapp.SimApp {
db := dbm.NewMemDB()
app := simapp.NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, simapp.DefaultNodeHome, 5)
// init chain must be called to stop deliverState from being nil
genesisState := simapp.NewDefaultGenesisState()
stateBytes, err := codec.MarshalJSONIndent(app.Codec(), genesisState)
if err != nil {
panic(err)
}
// Initialize the chain
app.InitChain(
abci.RequestInitChain{
Validators: []abci.ValidatorUpdate{},
AppStateBytes: stateBytes,
},
)
app.Commit()
app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: app.LastBlockHeight() + 1}})
return app
}

View File

@ -6,18 +6,22 @@ import (
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func TestLogger(t *testing.T) {
app := createTestApp()
app := simapp.Setup(false)
ctx := app.NewContext(true, abci.Header{})
require.Equal(t, ctx.Logger(), app.CrisisKeeper.Logger(ctx))
}
func TestInvariants(t *testing.T) {
app := createTestApp()
app := simapp.Setup(false)
app.Commit()
app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: app.LastBlockHeight() + 1}})
require.Equal(t, app.CrisisKeeper.InvCheckPeriod(), uint(5))
// SimApp has 11 registered invariants
@ -27,7 +31,10 @@ func TestInvariants(t *testing.T) {
}
func TestAssertInvariants(t *testing.T) {
app := createTestApp()
app := simapp.Setup(false)
app.Commit()
app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: app.LastBlockHeight() + 1}})
ctx := app.NewContext(true, abci.Header{})
app.CrisisKeeper.RegisterRoute("testModule", "testRoute1", func(sdk.Context) (string, bool) { return "", false })

View File

@ -12,15 +12,12 @@ const (
StoreKey = types.StoreKey
RouterKey = types.RouterKey
QuerierRoute = types.QuerierRoute
DefaultParamspace = types.DefaultParamspace
QueryEvidence = types.QueryEvidence
QueryAllEvidence = types.QueryAllEvidence
QueryParameters = types.QueryParameters
TypeMsgSubmitEvidence = types.TypeMsgSubmitEvidence
EventTypeSubmitEvidence = types.EventTypeSubmitEvidence
AttributeValueCategory = types.AttributeValueCategory
AttributeKeyEvidenceHash = types.AttributeKeyEvidenceHash
DefaultMaxEvidenceAge = types.DefaultMaxEvidenceAge
)
var (
@ -36,9 +33,7 @@ var (
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
ConvertDuplicateVoteEvidence = types.ConvertDuplicateVoteEvidence
KeyMaxEvidenceAge = types.KeyMaxEvidenceAge
DoubleSignJailEndTime = types.DoubleSignJailEndTime
ParamKeyTable = types.ParamKeyTable
ErrNoEvidenceHandlerExists = types.ErrNoEvidenceHandlerExists
ErrInvalidEvidence = types.ErrInvalidEvidence
ErrNoEvidenceExists = types.ErrNoEvidenceExists

View File

@ -42,40 +42,9 @@ $ %s query %s --page=2 --limit=50
cmd.Flags().Int(flags.FlagPage, 1, "pagination page of evidence to to query for")
cmd.Flags().Int(flags.FlagLimit, 100, "pagination limit of evidence to query for")
cmd.AddCommand(flags.GetCommands(QueryParamsCmd(cdc))...)
return flags.GetCommands(cmd)[0]
}
// QueryParamsCmd returns the command handler for evidence parameter querying.
func QueryParamsCmd(cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "params",
Short: "Query the current evidence parameters",
Args: cobra.NoArgs,
Long: strings.TrimSpace(`Query the current evidence parameters:
$ <appcli> query evidence params
`),
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryParameters)
res, _, err := cliCtx.QueryWithData(route, nil)
if err != nil {
return err
}
var params types.Params
if err := cdc.UnmarshalJSON(res, &params); err != nil {
return fmt.Errorf("failed to unmarshal params: %w", err)
}
return cliCtx.PrintOutput(params)
},
}
}
// QueryEvidenceCmd returns the command handler for evidence querying. Evidence
// can be queried for by hash or paginated evidence can be returned.
func QueryEvidenceCmd(cdc *codec.Codec) func(*cobra.Command, []string) error {

View File

@ -22,11 +22,6 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) {
"/evidence",
queryAllEvidenceHandler(cliCtx),
).Methods(MethodGet)
r.HandleFunc(
"/evidence/params",
queryParamsHandler(cliCtx),
).Methods(MethodGet)
}
func queryEvidenceHandler(cliCtx context.CLIContext) http.HandlerFunc {
@ -91,21 +86,3 @@ func queryAllEvidenceHandler(cliCtx context.CLIContext) http.HandlerFunc {
rest.PostProcessResponse(w, cliCtx, res)
}
}
func queryParamsHandler(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryParameters)
res, height, err := cliCtx.QueryWithData(route, nil)
if rest.CheckInternalServerError(w, err) {
return
}
cliCtx = cliCtx.WithHeight(height)
rest.PostProcessResponse(w, cliCtx, res)
}
}

View File

@ -20,14 +20,11 @@ func InitGenesis(ctx sdk.Context, k Keeper, gs GenesisState) {
k.SetEvidence(ctx, e)
}
k.SetParams(ctx, gs.Params)
}
// ExportGenesis returns the evidence module's exported genesis.
func ExportGenesis(ctx sdk.Context, k Keeper) GenesisState {
return GenesisState{
Params: k.GetParams(ctx),
Evidence: k.GetAllEvidence(ctx),
}
}

View File

@ -44,7 +44,7 @@ func (suite *GenesisTestSuite) TestInitGenesis_Valid() {
}
suite.NotPanics(func() {
evidence.InitGenesis(suite.ctx, suite.keeper, evidence.NewGenesisState(types.DefaultParams(), testEvidence))
evidence.InitGenesis(suite.ctx, suite.keeper, evidence.NewGenesisState(testEvidence))
})
for _, e := range testEvidence {
@ -66,7 +66,7 @@ func (suite *GenesisTestSuite) TestInitGenesis_Invalid() {
}
suite.Panics(func() {
evidence.InitGenesis(suite.ctx, suite.keeper, evidence.NewGenesisState(types.DefaultParams(), testEvidence))
evidence.InitGenesis(suite.ctx, suite.keeper, evidence.NewGenesisState(testEvidence))
})
suite.Empty(suite.keeper.GetAllEvidence(suite.ctx))

View File

@ -56,7 +56,7 @@ func (suite *HandlerTestSuite) SetupTest() {
// recreate keeper in order to use custom testing types
evidenceKeeper := evidence.NewKeeper(
codecstd.NewAppCodec(app.Codec()), app.GetKey(evidence.StoreKey),
app.GetSubspace(evidence.ModuleName), app.StakingKeeper, app.SlashingKeeper,
app.StakingKeeper, app.SlashingKeeper,
)
router := evidence.NewRouter()
router = router.AddRoute(types.RouteEquivocation, testEquivocationHandler(*evidenceKeeper))

View File

@ -25,11 +25,6 @@ import (
func (k Keeper) HandleDoubleSign(ctx sdk.Context, evidence types.Equivocation) {
logger := k.Logger(ctx)
consAddr := evidence.GetConsensusAddress()
infractionHeight := evidence.GetHeight()
// calculate the age of the evidence
blockTime := ctx.BlockHeader().Time
age := blockTime.Sub(evidence.GetTime())
if _, err := k.slashingKeeper.GetPubkey(ctx, consAddr.Bytes()); err != nil {
// Ignore evidence that cannot be handled.
@ -44,15 +39,28 @@ func (k Keeper) HandleDoubleSign(ctx sdk.Context, evidence types.Equivocation) {
return
}
// reject evidence if the double-sign is too old
if age > k.MaxEvidenceAge(ctx) {
logger.Info(
fmt.Sprintf(
"ignored double sign from %s at height %d, age of %d past max age of %d",
consAddr, infractionHeight, age, k.MaxEvidenceAge(ctx),
),
)
return
// calculate the age of the evidence
infractionHeight := evidence.GetHeight()
infractionTime := evidence.GetTime()
ageDuration := ctx.BlockHeader().Time.Sub(infractionTime)
ageBlocks := ctx.BlockHeader().Height - infractionHeight
// Reject evidence if the double-sign is too old. Evidence is considered stale
// if the difference in time and number of blocks is greater than the allowed
// parameters defined.
cp := ctx.ConsensusParams()
if cp != nil && cp.Evidence != nil {
if ageDuration > cp.Evidence.MaxAgeDuration && ageBlocks > cp.Evidence.MaxAgeNumBlocks {
logger.Info(
"ignored equivocation; evidence too old",
"validator", consAddr,
"infraction_height", infractionHeight,
"max_age_num_blocks", cp.Evidence.MaxAgeNumBlocks,
"infraction_time", infractionTime,
"max_age_duration", cp.Evidence.MaxAgeDuration,
)
return
}
}
validator := k.stakingKeeper.ValidatorByConsAddr(ctx, consAddr)
@ -69,15 +77,20 @@ func (k Keeper) HandleDoubleSign(ctx sdk.Context, evidence types.Equivocation) {
// ignore if the validator is already tombstoned
if k.slashingKeeper.IsTombstoned(ctx, consAddr) {
logger.Info(
fmt.Sprintf(
"ignored double sign from %s at height %d, validator already tombstoned",
consAddr, infractionHeight,
),
"ignored equivocation; validator already tombstoned",
"validator", consAddr,
"infraction_height", infractionHeight,
"infraction_time", infractionTime,
)
return
}
logger.Info(fmt.Sprintf("confirmed double sign from %s at height %d, age of %d", consAddr, infractionHeight, age))
logger.Info(
"confirmed equivocation",
"validator", consAddr,
"infraction_height", infractionHeight,
"infraction_time", infractionTime,
)
// We need to retrieve the stake distribution which signed the block, so we
// subtract ValidatorUpdateDelay from the evidence height.

View File

@ -112,7 +112,12 @@ func (suite *KeeperTestSuite) TestHandleDoubleSign_TooOld() {
Power: power,
ConsensusAddress: sdk.ConsAddress(val.Address()),
}
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(suite.app.EvidenceKeeper.MaxEvidenceAge(ctx) + 1))
cp := suite.app.BaseApp.GetConsensusParams(ctx)
ctx = ctx.WithConsensusParams(cp)
ctx = ctx.WithBlockTime(ctx.BlockTime().Add(cp.Evidence.MaxAgeDuration + 1))
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + cp.Evidence.MaxAgeNumBlocks + 1)
suite.app.EvidenceKeeper.HandleDoubleSign(ctx, evidence)
suite.False(suite.app.StakingKeeper.Validator(ctx, operatorAddr).IsJailed())

View File

@ -11,7 +11,6 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/evidence/exported"
"github.com/cosmos/cosmos-sdk/x/evidence/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
)
// Keeper defines the evidence module's keeper. The keeper is responsible for
@ -20,26 +19,19 @@ import (
type Keeper struct {
cdc types.Codec
storeKey sdk.StoreKey
paramSpace paramtypes.Subspace
router types.Router
stakingKeeper types.StakingKeeper
slashingKeeper types.SlashingKeeper
}
func NewKeeper(
cdc types.Codec, storeKey sdk.StoreKey, paramSpace paramtypes.Subspace,
stakingKeeper types.StakingKeeper, slashingKeeper types.SlashingKeeper,
cdc types.Codec, storeKey sdk.StoreKey, stakingKeeper types.StakingKeeper,
slashingKeeper types.SlashingKeeper,
) *Keeper {
// set KeyTable if it has not already been set
if !paramSpace.HasKeyTable() {
paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
}
return &Keeper{
cdc: cdc,
storeKey: storeKey,
paramSpace: paramSpace,
stakingKeeper: stakingKeeper,
slashingKeeper: slashingKeeper,
}

View File

@ -84,7 +84,7 @@ func (suite *KeeperTestSuite) SetupTest() {
// recreate keeper in order to use custom testing types
evidenceKeeper := evidence.NewKeeper(
codecstd.NewAppCodec(app.Codec()), app.GetKey(evidence.StoreKey),
app.GetSubspace(evidence.ModuleName), app.StakingKeeper, app.SlashingKeeper,
app.StakingKeeper, app.SlashingKeeper,
)
router := evidence.NewRouter()
router = router.AddRoute(types.RouteEquivocation, testEquivocationHandler(*evidenceKeeper))

View File

@ -1,25 +0,0 @@
package keeper
import (
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/evidence/types"
)
// MaxEvidenceAge returns the maximum age for submitted evidence.
func (k Keeper) MaxEvidenceAge(ctx sdk.Context) (res time.Duration) {
k.paramSpace.Get(ctx, types.KeyMaxEvidenceAge, &res)
return
}
// GetParams returns the total set of evidence parameters.
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
k.paramSpace.GetParamSet(ctx, &params)
return params
}
// SetParams sets the evidence parameters to the param space.
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
k.paramSpace.SetParamSet(ctx, &params)
}

View File

@ -1,11 +0,0 @@
package keeper_test
import (
"github.com/cosmos/cosmos-sdk/x/evidence/types"
)
func (suite *KeeperTestSuite) TestParams() {
ctx := suite.ctx.WithIsCheckTx(false)
suite.Equal(types.DefaultParams(), suite.app.EvidenceKeeper.GetParams(ctx))
suite.Equal(types.DefaultMaxEvidenceAge, suite.app.EvidenceKeeper.MaxEvidenceAge(ctx))
}

View File

@ -21,9 +21,6 @@ func NewQuerier(k Keeper) sdk.Querier {
)
switch path[0] {
case types.QueryParameters:
res, err = queryParams(ctx, k)
case types.QueryEvidence:
res, err = queryEvidence(ctx, req, k)
@ -38,17 +35,6 @@ func NewQuerier(k Keeper) sdk.Querier {
}
}
func queryParams(ctx sdk.Context, k Keeper) ([]byte, error) {
params := k.GetParams(ctx)
res, err := codec.MarshalJSONIndent(k.cdc, params)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return res, nil
}
func queryEvidence(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryEvidenceParams

View File

@ -89,12 +89,3 @@ func (suite *KeeperTestSuite) TestQueryAllEvidence_InvalidPagination() {
suite.Nil(cdc.UnmarshalJSON(bz, &e))
suite.Len(e, 0)
}
func (suite *KeeperTestSuite) TestQueryParams() {
ctx := suite.ctx.WithIsCheckTx(false)
bz, err := suite.querier(ctx, []string{types.QueryParameters}, abci.RequestQuery{})
suite.Nil(err)
suite.NotNil(bz)
suite.Equal("{\n \"max_evidence_age\": \"120000000000\"\n}", string(bz))
}

View File

@ -1,9 +1,6 @@
package types
import (
"fmt"
"time"
"github.com/cosmos/cosmos-sdk/x/evidence/exported"
)
@ -11,13 +8,11 @@ import (
// GenesisState defines the evidence module's genesis state.
type GenesisState struct {
Params Params `json:"params" yaml:"params"`
Evidence []exported.Evidence `json:"evidence" yaml:"evidence"`
}
func NewGenesisState(p Params, e []exported.Evidence) GenesisState {
func NewGenesisState(e []exported.Evidence) GenesisState {
return GenesisState{
Params: p,
Evidence: e,
}
}
@ -25,7 +20,6 @@ func NewGenesisState(p Params, e []exported.Evidence) GenesisState {
// DefaultGenesisState returns the evidence module's default genesis state.
func DefaultGenesisState() GenesisState {
return GenesisState{
Params: DefaultParams(),
Evidence: []exported.Evidence{},
}
}
@ -39,10 +33,5 @@ func (gs GenesisState) Validate() error {
}
}
maxEvidence := gs.Params.MaxEvidenceAge
if maxEvidence < 1*time.Minute {
return fmt.Errorf("max evidence age must be at least 1 minute, is %s", maxEvidence.String())
}
return nil
}

View File

@ -30,7 +30,7 @@ func TestGenesisStateValidate_Valid(t *testing.T) {
}
}
gs := types.NewGenesisState(types.DefaultParams(), evidence)
gs := types.NewGenesisState(evidence)
require.NoError(t, gs.Validate())
}
@ -47,6 +47,6 @@ func TestGenesisStateValidate_Invalid(t *testing.T) {
}
}
gs := types.NewGenesisState(types.DefaultParams(), evidence)
gs := types.NewGenesisState(evidence)
require.Error(t, gs.Validate())
}

View File

@ -1,64 +1,11 @@
package types
import (
"fmt"
"time"
"gopkg.in/yaml.v2"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
)
// DONTCOVER
// Default parameter values
const (
DefaultParamspace = ModuleName
DefaultMaxEvidenceAge = 60 * 2 * time.Second
)
// Parameter store keys
var (
KeyMaxEvidenceAge = []byte("MaxEvidenceAge")
// The Double Sign Jail period ends at Max Time supported by Amino
// (Dec 31, 9999 - 23:59:59 GMT).
DoubleSignJailEndTime = time.Unix(253402300799, 0)
)
// ParamKeyTable returns the parameter key table.
func ParamKeyTable() paramtypes.KeyTable {
return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
}
func (p Params) String() string {
out, _ := yaml.Marshal(p)
return string(out)
}
// ParamSetPairs returns the parameter set pairs.
func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
return paramtypes.ParamSetPairs{
paramtypes.NewParamSetPair(KeyMaxEvidenceAge, &p.MaxEvidenceAge, validateMaxEvidenceAge),
}
}
// DefaultParams returns the default parameters for the evidence module.
func DefaultParams() Params {
return Params{
MaxEvidenceAge: DefaultMaxEvidenceAge,
}
}
func validateMaxEvidenceAge(i interface{}) error {
v, ok := i.(time.Duration)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if v <= 0 {
return fmt.Errorf("max evidence age must be positive: %s", v)
}
return nil
}
// The Double Sign Jail period ends at Max Time supported by Amino
// (Dec 31, 9999 - 23:59:59 GMT).
var DoubleSignJailEndTime = time.Unix(253402300799, 0)

View File

@ -2,7 +2,6 @@ package types
// Querier routes for the evidence module
const (
QueryParameters = "parameters"
QueryEvidence = "evidence"
QueryAllEvidence = "all_evidence"
)

View File

@ -10,7 +10,6 @@ import (
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
_ "github.com/golang/protobuf/ptypes/duration"
_ "github.com/golang/protobuf/ptypes/timestamp"
io "io"
math "math"
@ -122,89 +121,40 @@ func (m *Equivocation) XXX_DiscardUnknown() {
var xxx_messageInfo_Equivocation proto.InternalMessageInfo
// Params defines the total set of parameters for the evidence module
type Params struct {
MaxEvidenceAge time.Duration `protobuf:"bytes,1,opt,name=max_evidence_age,json=maxEvidenceAge,proto3,stdduration" json:"max_evidence_age" yaml:"max_evidence_age"`
}
func (m *Params) Reset() { *m = Params{} }
func (*Params) ProtoMessage() {}
func (*Params) Descriptor() ([]byte, []int) {
return fileDescriptor_72113e6a7b2536ae, []int{2}
}
func (m *Params) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Params.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Params) XXX_Merge(src proto.Message) {
xxx_messageInfo_Params.Merge(m, src)
}
func (m *Params) XXX_Size() int {
return m.Size()
}
func (m *Params) XXX_DiscardUnknown() {
xxx_messageInfo_Params.DiscardUnknown(m)
}
var xxx_messageInfo_Params proto.InternalMessageInfo
func (m *Params) GetMaxEvidenceAge() time.Duration {
if m != nil {
return m.MaxEvidenceAge
}
return 0
}
func init() {
proto.RegisterType((*MsgSubmitEvidenceBase)(nil), "cosmos_sdk.x.evidence.v1.MsgSubmitEvidenceBase")
proto.RegisterType((*Equivocation)(nil), "cosmos_sdk.x.evidence.v1.Equivocation")
proto.RegisterType((*Params)(nil), "cosmos_sdk.x.evidence.v1.Params")
}
func init() { proto.RegisterFile("x/evidence/types/types.proto", fileDescriptor_72113e6a7b2536ae) }
var fileDescriptor_72113e6a7b2536ae = []byte{
// 455 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x3d, 0x6f, 0xd4, 0x30,
0x1c, 0xc6, 0x63, 0x7a, 0x9c, 0x8a, 0x5b, 0xa1, 0x12, 0xf1, 0x12, 0x4e, 0x28, 0xae, 0x82, 0x84,
0xba, 0xd4, 0x51, 0xcb, 0x82, 0x6e, 0xbb, 0x40, 0x27, 0xc4, 0x8b, 0x0e, 0x26, 0x96, 0xc8, 0x97,
0x18, 0x27, 0x6a, 0x1d, 0x07, 0xdb, 0x39, 0x72, 0xe2, 0x0b, 0x30, 0x76, 0xec, 0xd8, 0x91, 0x8f,
0xd2, 0xb1, 0x23, 0x53, 0x40, 0x77, 0xdf, 0xa0, 0x63, 0x25, 0x24, 0x74, 0x76, 0x42, 0xa5, 0xab,
0x84, 0xba, 0x24, 0xb1, 0xf3, 0xe4, 0xc9, 0xf3, 0xfb, 0x3f, 0x86, 0x4f, 0xea, 0x90, 0x4e, 0xf3,
0x94, 0x16, 0x09, 0x0d, 0xf5, 0xac, 0xa4, 0xca, 0x5e, 0x71, 0x29, 0x85, 0x16, 0xae, 0x97, 0x08,
0xc5, 0x85, 0x8a, 0x55, 0x7a, 0x88, 0x6b, 0xdc, 0x09, 0xf1, 0x74, 0x6f, 0xf0, 0x4c, 0x67, 0xb9,
0x4c, 0xe3, 0x92, 0x48, 0x3d, 0x0b, 0x8d, 0x38, 0x64, 0x82, 0x89, 0xab, 0x27, 0xeb, 0x30, 0x40,
0x4c, 0x08, 0x76, 0x44, 0xad, 0x64, 0x52, 0x7d, 0x0e, 0x75, 0xce, 0xa9, 0xd2, 0x84, 0x97, 0xad,
0xc0, 0x5f, 0x15, 0xa4, 0x95, 0x24, 0x3a, 0x17, 0x85, 0x7d, 0x1f, 0x64, 0xf0, 0xc1, 0x1b, 0xc5,
0x3e, 0x54, 0x13, 0x9e, 0xeb, 0x83, 0x36, 0x40, 0x44, 0x14, 0x75, 0xdf, 0xc1, 0x3b, 0xca, 0xec,
0x6a, 0x2a, 0x3d, 0xb0, 0x0d, 0x76, 0x36, 0xa3, 0xbd, 0xcb, 0x06, 0xed, 0xb2, 0x5c, 0x67, 0xd5,
0x04, 0x27, 0x82, 0x87, 0x36, 0x7d, 0x7b, 0xdb, 0x55, 0xe9, 0x61, 0x0b, 0x37, 0x4a, 0x92, 0x51,
0x9a, 0x4a, 0xaa, 0xd4, 0xf8, 0xca, 0x23, 0xf8, 0x03, 0xe0, 0xe6, 0xc1, 0x97, 0x2a, 0x9f, 0x8a,
0xc4, 0x04, 0x70, 0x1f, 0xc2, 0x7e, 0x46, 0x73, 0x96, 0x69, 0x63, 0xbf, 0x36, 0x6e, 0x57, 0xee,
0x0b, 0xd8, 0x5b, 0x52, 0x78, 0xb7, 0xb6, 0xc1, 0xce, 0xc6, 0xfe, 0x00, 0x5b, 0x02, 0xdc, 0x11,
0xe0, 0x8f, 0x1d, 0x62, 0xb4, 0x7e, 0xd6, 0x20, 0xe7, 0xf8, 0x17, 0x02, 0x63, 0xf3, 0x85, 0x7b,
0x1f, 0xde, 0x2e, 0xc5, 0x57, 0x2a, 0xbd, 0x35, 0x63, 0x68, 0x17, 0xee, 0x37, 0x78, 0x2f, 0x11,
0x85, 0xa2, 0x85, 0xaa, 0x54, 0x4c, 0x6c, 0x30, 0xaf, 0x67, 0x88, 0xde, 0x5e, 0x34, 0xc8, 0x9b,
0x11, 0x7e, 0x34, 0x0c, 0xae, 0x49, 0x82, 0xcb, 0x06, 0xe1, 0x1b, 0xd0, 0xbe, 0x14, 0x85, 0xea,
0x70, 0xb7, 0xfe, 0xb9, 0xb4, 0x3b, 0xc3, 0xf5, 0xef, 0xa7, 0xc8, 0x39, 0x39, 0x45, 0x4e, 0x50,
0xc3, 0xfe, 0x7b, 0x22, 0x09, 0x57, 0x6e, 0x06, 0xb7, 0x38, 0xa9, 0xe3, 0xae, 0xef, 0x98, 0x30,
0x6a, 0x46, 0xb0, 0xb1, 0xff, 0xf8, 0x1a, 0xec, 0xab, 0xb6, 0xae, 0xe8, 0xe9, 0x92, 0xf5, 0xa2,
0x41, 0x8f, 0x6c, 0xdc, 0x55, 0x83, 0xe0, 0x64, 0x39, 0x86, 0xbb, 0x9c, 0xd4, 0x5d, 0x8b, 0x23,
0x46, 0x87, 0xbd, 0xe5, 0x9f, 0xa3, 0xd7, 0x3f, 0xe6, 0x3e, 0x38, 0x9b, 0xfb, 0xe0, 0x7c, 0xee,
0x83, 0xdf, 0x73, 0x1f, 0x1c, 0x2f, 0x7c, 0xe7, 0x7c, 0xe1, 0x3b, 0x3f, 0x17, 0xbe, 0xf3, 0xe9,
0xff, 0x8d, 0xae, 0x9e, 0xdf, 0x49, 0xdf, 0x44, 0x7b, 0xfe, 0x37, 0x00, 0x00, 0xff, 0xff, 0x35,
0xfb, 0xe6, 0x44, 0xda, 0x02, 0x00, 0x00,
// 390 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xa9, 0xd0, 0x4f, 0x2d,
0xcb, 0x4c, 0x49, 0xcd, 0x4b, 0x4e, 0xd5, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0x86, 0x90, 0x7a, 0x05,
0x45, 0xf9, 0x25, 0xf9, 0x42, 0x12, 0xc9, 0xf9, 0xc5, 0xb9, 0xf9, 0xc5, 0xf1, 0xc5, 0x29, 0xd9,
0x7a, 0x15, 0x7a, 0x30, 0x85, 0x7a, 0x65, 0x86, 0x52, 0x6a, 0x25, 0x19, 0x99, 0x45, 0x29, 0xf1,
0x05, 0x89, 0x45, 0x25, 0x95, 0xfa, 0x60, 0xc5, 0xfa, 0xe9, 0xf9, 0xe9, 0xf9, 0x08, 0x16, 0xc4,
0x04, 0x29, 0xf9, 0xf4, 0xfc, 0xfc, 0xf4, 0x9c, 0x54, 0x88, 0x92, 0xa4, 0xd2, 0x34, 0xfd, 0x92,
0xcc, 0xdc, 0xd4, 0xe2, 0x92, 0xc4, 0xdc, 0x02, 0x88, 0x02, 0xa5, 0x0c, 0x2e, 0x51, 0xdf, 0xe2,
0xf4, 0xe0, 0xd2, 0xa4, 0xdc, 0xcc, 0x12, 0x57, 0xa8, 0x05, 0x4e, 0x89, 0xc5, 0xa9, 0x42, 0xfe,
0x5c, 0x9c, 0xc5, 0x60, 0xd1, 0x92, 0xd4, 0x22, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x1e, 0x27, 0xc3,
0x5f, 0xf7, 0xe4, 0x75, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0x21,
0xae, 0x83, 0x52, 0xba, 0xc5, 0x29, 0xd9, 0x50, 0xc7, 0x3b, 0x26, 0x27, 0x3b, 0xa6, 0xa4, 0x14,
0xa5, 0x16, 0x17, 0x07, 0x21, 0xcc, 0x50, 0xfa, 0xcb, 0xc8, 0xc5, 0xe3, 0x5a, 0x58, 0x9a, 0x59,
0x96, 0x9f, 0x9c, 0x58, 0x92, 0x99, 0x9f, 0x27, 0x24, 0xc6, 0xc5, 0x96, 0x91, 0x9a, 0x99, 0x9e,
0x51, 0x02, 0x36, 0x9e, 0x39, 0x08, 0xca, 0x13, 0xb2, 0xe0, 0x62, 0x01, 0xb9, 0x52, 0x82, 0x49,
0x81, 0x51, 0x83, 0xdb, 0x48, 0x4a, 0x0f, 0xe2, 0x05, 0x3d, 0x98, 0x17, 0xf4, 0x42, 0x60, 0x5e,
0x70, 0xe2, 0x38, 0x71, 0x4f, 0x9e, 0x61, 0xc2, 0x7d, 0x79, 0xc6, 0x20, 0xb0, 0x0e, 0x21, 0x11,
0x2e, 0xd6, 0x82, 0xfc, 0xf2, 0xd4, 0x22, 0x09, 0x66, 0xb0, 0x81, 0x10, 0x8e, 0x50, 0x35, 0x97,
0x60, 0x72, 0x7e, 0x5e, 0x71, 0x6a, 0x5e, 0x71, 0x69, 0x71, 0x7c, 0x22, 0xc4, 0x61, 0x12, 0x2c,
0x60, 0x1f, 0xf9, 0x7d, 0xba, 0x27, 0x2f, 0x51, 0x99, 0x98, 0x9b, 0x63, 0xa5, 0x84, 0xa1, 0x44,
0xe9, 0xd7, 0x3d, 0x79, 0x3d, 0x22, 0x7c, 0xeb, 0x9c, 0x9f, 0x57, 0x0c, 0xf3, 0xae, 0x00, 0xdc,
0x14, 0xa8, 0x88, 0x15, 0x47, 0xc7, 0x02, 0x79, 0x86, 0x19, 0x0b, 0xe4, 0x19, 0x9c, 0xbc, 0x57,
0x3c, 0x92, 0x63, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18,
0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xfc, 0xe1,
0x8a, 0x9e, 0x4a, 0x92, 0xd8, 0xc0, 0xa1, 0x61, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xce, 0x16,
0xee, 0xfa, 0x40, 0x02, 0x00, 0x00,
}
func (this *MsgSubmitEvidenceBase) Equal(that interface{}) bool {
@ -264,30 +214,6 @@ func (this *Equivocation) Equal(that interface{}) bool {
}
return true
}
func (this *Params) Equal(that interface{}) bool {
if that == nil {
return this == nil
}
that1, ok := that.(*Params)
if !ok {
that2, ok := that.(Params)
if ok {
that1 = &that2
} else {
return false
}
}
if that1 == nil {
return this == nil
} else if this == nil {
return false
}
if this.MaxEvidenceAge != that1.MaxEvidenceAge {
return false
}
return true
}
func (m *MsgSubmitEvidenceBase) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@ -366,37 +292,6 @@ func (m *Equivocation) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *Params) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Params) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
n2, err2 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.MaxEvidenceAge, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.MaxEvidenceAge):])
if err2 != nil {
return 0, err2
}
i -= n2
i = encodeVarintTypes(dAtA, i, uint64(n2))
i--
dAtA[i] = 0xa
return len(dAtA) - i, nil
}
func encodeVarintTypes(dAtA []byte, offset int, v uint64) int {
offset -= sovTypes(v)
base := offset
@ -442,17 +337,6 @@ func (m *Equivocation) Size() (n int) {
return n
}
func (m *Params) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.MaxEvidenceAge)
n += 1 + l + sovTypes(uint64(l))
return n
}
func sovTypes(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
@ -704,92 +588,6 @@ func (m *Equivocation) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *Params) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTypes
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Params: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field MaxEvidenceAge", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTypes
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthTypes
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthTypes
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.MaxEvidenceAge, dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTypes(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthTypes
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthTypes
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipTypes(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0

View File

@ -6,7 +6,6 @@ option (gogoproto.equal_all) = true;
import "third_party/proto/gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
// MsgSubmitEvidenceBase defines an sdk.Msg type that supports submitting arbitrary
// Evidence.
@ -33,14 +32,3 @@ message Equivocation {
(gogoproto.moretags) = "yaml:\"consensus_address\""
];
}
// Params defines the total set of parameters for the evidence module
message Params {
option (gogoproto.goproto_stringer) = false;
google.protobuf.Duration max_evidence_age = 1 [
(gogoproto.nullable) = false,
(gogoproto.stdduration) = true,
(gogoproto.moretags) = "yaml:\"max_evidence_age\""
];
}

View File

@ -66,8 +66,9 @@ func TestImportExportQueues(t *testing.T) {
app2.InitChain(
abci.RequestInitChain{
Validators: []abci.ValidatorUpdate{},
AppStateBytes: stateBytes,
Validators: []abci.ValidatorUpdate{},
ConsensusParams: simapp.DefaultConsensusParams,
AppStateBytes: stateBytes,
},
)

View File

@ -14,7 +14,9 @@ const (
var (
// functions aliases
NewKeeper = keeper.NewKeeper
NewKeeper = keeper.NewKeeper
NewParamSetPair = types.NewParamSetPair
NewKeyTable = types.NewKeyTable
)
type (

View File

@ -118,6 +118,8 @@ func (s Subspace) GetIfExists(ctx sdk.Context, key []byte, ptr interface{}) {
return
}
s.checkType(key, ptr)
if err := s.cdc.UnmarshalJSON(bz, ptr); err != nil {
panic(err)
}

View File

@ -65,12 +65,14 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k
return nil, err
}
if ctx.ConsensusParams() != nil {
cp := ctx.ConsensusParams()
if cp != nil && cp.Validator != nil {
tmPubKey := tmtypes.TM2PB.PubKey(pk)
if !tmstrings.StringInSlice(tmPubKey.Type, ctx.ConsensusParams().Validator.PubKeyTypes) {
if !tmstrings.StringInSlice(tmPubKey.Type, cp.Validator.PubKeyTypes) {
return nil, sdkerrors.Wrapf(
ErrValidatorPubKeyTypeNotSupported,
"got: %s, expected: %s", tmPubKey.Type, ctx.ConsensusParams().Validator.PubKeyTypes,
"got: %s, expected: %s", tmPubKey.Type, cp.Validator.PubKeyTypes,
)
}
}

View File

@ -125,10 +125,10 @@ func TestSetLoader(t *testing.T) {
}
app := baseapp.NewBaseApp(t.Name(), defaultLogger(), db, nil, opts...)
capKey := sdk.NewKVStoreKey(baseapp.MainStoreKey)
capKey := sdk.NewKVStoreKey("main")
app.MountStores(capKey)
app.MountStores(sdk.NewKVStoreKey(tc.loadStoreKey))
err := app.LoadLatestVersion(capKey)
err := app.LoadLatestVersion()
require.Nil(t, err)
// "execute" one block