mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-05 04:55:18 +00:00
abci++: add proto fields for enabling vote extensions (#8587)
This pull requests adds the protocol buffer field for the `ABCI.VoteExtensionsEnableHeight` parameter. This proto field is threaded throughout all of the relevant places where consensus params are used and referenced. This PR also adds validation of the consensus param updates. Previous consensus param changes didn't depend on _previous_ versions of the params, so this change adds a method for validating against the old params as well. closes: #8453
This commit is contained in:
@@ -330,6 +330,9 @@ func (params ConsensusParams) ValidateConsensusParams() error {
|
||||
if params.Timeout.Commit <= 0 {
|
||||
return fmt.Errorf("timeout.Commit must be greater than 0. Got: %d", params.Timeout.Commit)
|
||||
}
|
||||
if params.ABCI.VoteExtensionsEnableHeight < 0 {
|
||||
return fmt.Errorf("ABCI.VoteExtensionsEnableHeight cannot be negative. Got: %d", params.ABCI.VoteExtensionsEnableHeight)
|
||||
}
|
||||
|
||||
if len(params.Validator.PubKeyTypes) == 0 {
|
||||
return errors.New("len(Validator.PubKeyTypes) must be greater than 0")
|
||||
@@ -347,6 +350,30 @@ func (params ConsensusParams) ValidateConsensusParams() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (params ConsensusParams) ValidateUpdate(updated *tmproto.ConsensusParams, h int64) error {
|
||||
if updated.Abci == nil {
|
||||
return nil
|
||||
}
|
||||
if params.ABCI.VoteExtensionsEnableHeight == updated.Abci.VoteExtensionsEnableHeight {
|
||||
return nil
|
||||
}
|
||||
if params.ABCI.VoteExtensionsEnableHeight != 0 && updated.Abci.VoteExtensionsEnableHeight == 0 {
|
||||
return errors.New("vote extensions cannot be disabled once enabled")
|
||||
}
|
||||
if updated.Abci.VoteExtensionsEnableHeight <= h {
|
||||
return fmt.Errorf("VoteExtensionsEnableHeight cannot be updated to a past height, "+
|
||||
"initial height: %d, current height %d",
|
||||
params.ABCI.VoteExtensionsEnableHeight, h)
|
||||
}
|
||||
if params.ABCI.VoteExtensionsEnableHeight <= h {
|
||||
return fmt.Errorf("VoteExtensionsEnableHeight cannot be updated modified once"+
|
||||
"the initial height has occurred, "+
|
||||
"initial height: %d, current height %d",
|
||||
params.ABCI.VoteExtensionsEnableHeight, h)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Hash returns a hash of a subset of the parameters to store in the block header.
|
||||
// Only the Block.MaxBytes and Block.MaxGas are included in the hash.
|
||||
// This allows the ConsensusParams to evolve more without breaking the block
|
||||
@@ -373,6 +400,7 @@ func (params *ConsensusParams) Equals(params2 *ConsensusParams) bool {
|
||||
params.Version == params2.Version &&
|
||||
params.Synchrony == params2.Synchrony &&
|
||||
params.Timeout == params2.Timeout &&
|
||||
params.ABCI == params2.ABCI &&
|
||||
tmstrings.StringSliceEqual(params.Validator.PubKeyTypes, params2.Validator.PubKeyTypes)
|
||||
}
|
||||
|
||||
@@ -429,6 +457,9 @@ func (params ConsensusParams) UpdateConsensusParams(params2 *tmproto.ConsensusPa
|
||||
}
|
||||
res.Timeout.BypassCommitTimeout = params2.Timeout.GetBypassCommitTimeout()
|
||||
}
|
||||
if params2.Abci != nil {
|
||||
res.ABCI.VoteExtensionsEnableHeight = params2.Abci.GetVoteExtensionsEnableHeight()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -461,6 +492,9 @@ func (params *ConsensusParams) ToProto() tmproto.ConsensusParams {
|
||||
Commit: ¶ms.Timeout.Commit,
|
||||
BypassCommitTimeout: params.Timeout.BypassCommitTimeout,
|
||||
},
|
||||
Abci: &tmproto.ABCIParams{
|
||||
VoteExtensionsEnableHeight: params.ABCI.VoteExtensionsEnableHeight,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -508,5 +542,8 @@ func ConsensusParamsFromProto(pbParams tmproto.ConsensusParams) ConsensusParams
|
||||
}
|
||||
c.Timeout.BypassCommitTimeout = pbParams.Timeout.BypassCommitTimeout
|
||||
}
|
||||
if pbParams.Abci != nil {
|
||||
c.ABCI.VoteExtensionsEnableHeight = pbParams.Abci.GetVoteExtensionsEnableHeight()
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
)
|
||||
@@ -189,6 +190,8 @@ type makeParamsArgs struct {
|
||||
vote *time.Duration
|
||||
voteDelta *time.Duration
|
||||
commit *time.Duration
|
||||
|
||||
abciExtensionHeight int64
|
||||
}
|
||||
|
||||
func makeParams(args makeParamsArgs) ConsensusParams {
|
||||
@@ -235,6 +238,9 @@ func makeParams(args makeParamsArgs) ConsensusParams {
|
||||
Commit: *args.commit,
|
||||
BypassCommitTimeout: args.bypassCommitTimeout,
|
||||
},
|
||||
ABCI: ABCIParams{
|
||||
VoteExtensionsEnableHeight: args.abciExtensionHeight,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,19 +273,19 @@ func TestConsensusParamsHash(t *testing.T) {
|
||||
|
||||
func TestConsensusParamsUpdate(t *testing.T) {
|
||||
testCases := []struct {
|
||||
intialParams ConsensusParams
|
||||
initialParams ConsensusParams
|
||||
updates *tmproto.ConsensusParams
|
||||
updatedParams ConsensusParams
|
||||
}{
|
||||
// empty updates
|
||||
{
|
||||
intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}),
|
||||
initialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}),
|
||||
updates: &tmproto.ConsensusParams{},
|
||||
updatedParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}),
|
||||
},
|
||||
{
|
||||
// update synchrony params
|
||||
intialParams: makeParams(makeParamsArgs{evidenceAge: 3, precision: time.Second, messageDelay: 3 * time.Second}),
|
||||
initialParams: makeParams(makeParamsArgs{evidenceAge: 3, precision: time.Second, messageDelay: 3 * time.Second}),
|
||||
updates: &tmproto.ConsensusParams{
|
||||
Synchrony: &tmproto.SynchronyParams{
|
||||
Precision: durationPtr(time.Second * 2),
|
||||
@@ -290,7 +296,21 @@ func TestConsensusParamsUpdate(t *testing.T) {
|
||||
},
|
||||
{
|
||||
// update timeout params
|
||||
intialParams: makeParams(makeParamsArgs{
|
||||
initialParams: makeParams(makeParamsArgs{
|
||||
abciExtensionHeight: 1,
|
||||
}),
|
||||
updates: &tmproto.ConsensusParams{
|
||||
Abci: &tmproto.ABCIParams{
|
||||
VoteExtensionsEnableHeight: 10,
|
||||
},
|
||||
},
|
||||
updatedParams: makeParams(makeParamsArgs{
|
||||
abciExtensionHeight: 10,
|
||||
}),
|
||||
},
|
||||
{
|
||||
// update timeout params
|
||||
initialParams: makeParams(makeParamsArgs{
|
||||
propose: durationPtr(3 * time.Second),
|
||||
proposeDelta: durationPtr(500 * time.Millisecond),
|
||||
vote: durationPtr(time.Second),
|
||||
@@ -319,7 +339,7 @@ func TestConsensusParamsUpdate(t *testing.T) {
|
||||
},
|
||||
// fine updates
|
||||
{
|
||||
intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}),
|
||||
initialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}),
|
||||
updates: &tmproto.ConsensusParams{
|
||||
Block: &tmproto.BlockParams{
|
||||
MaxBytes: 100,
|
||||
@@ -341,7 +361,7 @@ func TestConsensusParamsUpdate(t *testing.T) {
|
||||
pubkeyTypes: valSecp256k1}),
|
||||
},
|
||||
{
|
||||
intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}),
|
||||
initialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}),
|
||||
updates: &tmproto.ConsensusParams{
|
||||
Block: &tmproto.BlockParams{
|
||||
MaxBytes: 100,
|
||||
@@ -366,7 +386,7 @@ func TestConsensusParamsUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
assert.Equal(t, tc.updatedParams, tc.intialParams.UpdateConsensusParams(tc.updates))
|
||||
assert.Equal(t, tc.updatedParams, tc.initialParams.UpdateConsensusParams(tc.updates))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,6 +401,78 @@ func TestConsensusParamsUpdate_AppVersion(t *testing.T) {
|
||||
assert.EqualValues(t, 1, updated.Version.AppVersion)
|
||||
}
|
||||
|
||||
func TestConsensusParamsUpdate_VoteExtensionsEnableHeight(t *testing.T) {
|
||||
t.Run("set to height but initial height already run", func(*testing.T) {
|
||||
initialParams := makeParams(makeParamsArgs{
|
||||
abciExtensionHeight: 1,
|
||||
})
|
||||
update := &tmproto.ConsensusParams{
|
||||
Abci: &tmproto.ABCIParams{
|
||||
VoteExtensionsEnableHeight: 10,
|
||||
},
|
||||
}
|
||||
require.Error(t, initialParams.ValidateUpdate(update, 1))
|
||||
require.Error(t, initialParams.ValidateUpdate(update, 5))
|
||||
})
|
||||
t.Run("reset to 0", func(t *testing.T) {
|
||||
initialParams := makeParams(makeParamsArgs{
|
||||
abciExtensionHeight: 1,
|
||||
})
|
||||
update := &tmproto.ConsensusParams{
|
||||
Abci: &tmproto.ABCIParams{
|
||||
VoteExtensionsEnableHeight: 0,
|
||||
},
|
||||
}
|
||||
require.Error(t, initialParams.ValidateUpdate(update, 1))
|
||||
})
|
||||
t.Run("set to height before current height run", func(*testing.T) {
|
||||
initialParams := makeParams(makeParamsArgs{
|
||||
abciExtensionHeight: 100,
|
||||
})
|
||||
update := &tmproto.ConsensusParams{
|
||||
Abci: &tmproto.ABCIParams{
|
||||
VoteExtensionsEnableHeight: 10,
|
||||
},
|
||||
}
|
||||
require.Error(t, initialParams.ValidateUpdate(update, 11))
|
||||
require.Error(t, initialParams.ValidateUpdate(update, 99))
|
||||
})
|
||||
t.Run("set to height after current height run", func(*testing.T) {
|
||||
initialParams := makeParams(makeParamsArgs{
|
||||
abciExtensionHeight: 300,
|
||||
})
|
||||
update := &tmproto.ConsensusParams{
|
||||
Abci: &tmproto.ABCIParams{
|
||||
VoteExtensionsEnableHeight: 99,
|
||||
},
|
||||
}
|
||||
require.NoError(t, initialParams.ValidateUpdate(update, 11))
|
||||
require.NoError(t, initialParams.ValidateUpdate(update, 98))
|
||||
})
|
||||
t.Run("no error when unchanged", func(*testing.T) {
|
||||
initialParams := makeParams(makeParamsArgs{
|
||||
abciExtensionHeight: 100,
|
||||
})
|
||||
update := &tmproto.ConsensusParams{
|
||||
Abci: &tmproto.ABCIParams{
|
||||
VoteExtensionsEnableHeight: 100,
|
||||
},
|
||||
}
|
||||
require.NoError(t, initialParams.ValidateUpdate(update, 500))
|
||||
})
|
||||
t.Run("updated from 0 to 0", func(t *testing.T) {
|
||||
initialParams := makeParams(makeParamsArgs{
|
||||
abciExtensionHeight: 0,
|
||||
})
|
||||
update := &tmproto.ConsensusParams{
|
||||
Abci: &tmproto.ABCIParams{
|
||||
VoteExtensionsEnableHeight: 0,
|
||||
},
|
||||
}
|
||||
require.NoError(t, initialParams.ValidateUpdate(update, 100))
|
||||
})
|
||||
}
|
||||
|
||||
func TestProto(t *testing.T) {
|
||||
params := []ConsensusParams{
|
||||
makeParams(makeParamsArgs{blockBytes: 4, blockGas: 2, evidenceAge: 3, maxEvidenceBytes: 1}),
|
||||
@@ -393,6 +485,16 @@ func TestProto(t *testing.T) {
|
||||
makeParams(makeParamsArgs{blockBytes: 4, blockGas: 6, evidenceAge: 5, maxEvidenceBytes: 1}),
|
||||
makeParams(makeParamsArgs{precision: time.Second, messageDelay: time.Minute}),
|
||||
makeParams(makeParamsArgs{precision: time.Nanosecond, messageDelay: time.Millisecond}),
|
||||
makeParams(makeParamsArgs{abciExtensionHeight: 100}),
|
||||
makeParams(makeParamsArgs{abciExtensionHeight: 100}),
|
||||
makeParams(makeParamsArgs{
|
||||
propose: durationPtr(2 * time.Second),
|
||||
proposeDelta: durationPtr(400 * time.Millisecond),
|
||||
vote: durationPtr(5 * time.Second),
|
||||
voteDelta: durationPtr(400 * time.Millisecond),
|
||||
commit: durationPtr(time.Minute),
|
||||
bypassCommitTimeout: true,
|
||||
}),
|
||||
}
|
||||
|
||||
for i := range params {
|
||||
|
||||
Reference in New Issue
Block a user