diff --git a/x/params/types/proposal/proposal.go b/x/params/types/proposal/proposal.go index ff10fd01d..e3d405c06 100644 --- a/x/params/types/proposal/proposal.go +++ b/x/params/types/proposal/proposal.go @@ -1,7 +1,9 @@ package proposal import ( + "encoding/json" "fmt" + "github.com/tendermint/tendermint/types" "strings" yaml "gopkg.in/yaml.v2" @@ -96,7 +98,37 @@ func ValidateChanges(changes []ParamChange) error { if len(pc.Value) == 0 { return ErrEmptyValue } + // We need to verify ConsensusParams since they are only validated once the proposal passes. + // If any of them are invalid at time of passing, this will cause a chain halt since validation is done during + // ApplyBlock: https://github.com/sei-protocol/sei-tendermint/blob/d426f1fe475eb0c406296770ff5e9f8869b3887e/internal/state/execution.go#L320 + // Therefore, we validate when we get a param-change msg for ConsensusParams + if pc.Subspace == "baseapp" { + if err := verifyConsensusParamsUsingDefault(changes); err != nil { + return err + } + } } return nil } + +func verifyConsensusParamsUsingDefault(changes []ParamChange) error { + // Start with a default (valid) set of parameters, and update based on proposal then check + defaultCP := types.DefaultConsensusParams() + for _, change := range changes { + // Note: BlockParams seems to be the only support ConsensusParams available for modifying with proposal + switch change.Key { + case "BlockParams": + blockParams := types.DefaultBlockParams() + err := json.Unmarshal([]byte(change.Value), &blockParams) + if err != nil { + return err + } + defaultCP.Block = blockParams + } + } + if err := defaultCP.ValidateConsensusParams(); err != nil { + return err + } + return nil +} diff --git a/x/params/types/proposal/proposal_test.go b/x/params/types/proposal/proposal_test.go index b7819abef..94a782b05 100644 --- a/x/params/types/proposal/proposal_test.go +++ b/x/params/types/proposal/proposal_test.go @@ -1,6 +1,8 @@ package proposal import ( + "fmt" + "github.com/tendermint/tendermint/types" "testing" "github.com/stretchr/testify/require" @@ -25,3 +27,14 @@ func TestParameterChangeProposal(t *testing.T) { pcp = NewParameterChangeProposal("test title", "test description", []ParamChange{pc4}, true) require.Error(t, pcp.ValidateBasic()) } + +func TestConsensusParameterChangeProposal(t *testing.T) { + // Valid block max_bytes ( + pc1 := NewParamChange("baseapp", "BlockParams", fmt.Sprintf("{\"max_bytes\":\"%d\"}", types.MaxBlockSizeBytes)) + pcp := NewParameterChangeProposal("test title", "test description", []ParamChange{pc1}, true) + require.Nil(t, pcp.ValidateBasic()) + + pc1 = NewParamChange("baseapp", "BlockParams", fmt.Sprintf("{\"max_bytes\":\"%d\"}", types.MaxBlockSizeBytes+1)) + pcp = NewParameterChangeProposal("test title", "test description", []ParamChange{pc1}, true) + require.Error(t, pcp.ValidateBasic()) +}