types: add new consensus params from proto (#7354)

This change adds the new TimingParams proto messages. These new messages were build using the wb/proposer-based-timestamps branch on the spec repo.
This change also adds validation that these values are positive when parsed and adds the new parameters into the existing tests.
This commit is contained in:
William Banfield
2021-12-05 19:20:37 -05:00
committed by GitHub
parent a9aab99b41
commit a9b2bbd70d
11 changed files with 658 additions and 136 deletions
+10 -5
View File
@@ -56,21 +56,26 @@ func TestGenesisBad(t *testing.T) {
}
}
func TestGenesisGood(t *testing.T) {
func TestBasicGenesisDoc(t *testing.T) {
// test a good one by raw json
genDocBytes := []byte(
`{
"genesis_time": "0001-01-01T00:00:00Z",
"chain_id": "test-chain-QDKdJr",
"initial_height": "1000",
"consensus_params": null,
"validators": [{
"pub_key":{"type":"tendermint/PubKeyEd25519","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="},
"power":"10",
"name":""
}],
"app_hash":"",
"app_state":{"account_owner": "Bob"}
"app_state":{"account_owner": "Bob"},
"consensus_params": {
"timing": {"precision": "1", "message_delay": "10"},
"validator": {"pub_key_types":["ed25519"]},
"block": {"max_bytes": "100"},
"evidence": {"max_age_num_blocks": "100", "max_age_duration": "10"}
}
}`,
)
_, err := GenesisDocFromJSON(genDocBytes)
@@ -97,12 +102,12 @@ func TestGenesisGood(t *testing.T) {
genDocBytes, err = tmjson.Marshal(genDoc)
assert.NoError(t, err, "error marshaling genDoc")
genDoc, err = GenesisDocFromJSON(genDocBytes)
assert.NoError(t, err, "expected no error for valid genDoc json")
require.NoError(t, err, "expected no error for valid genDoc json")
// test with invalid consensus params
genDoc.ConsensusParams.Block.MaxBytes = 0
genDocBytes, err = tmjson.Marshal(genDoc)
assert.NoError(t, err, "error marshaling genDoc")
require.NoError(t, err, "error marshaling genDoc")
_, err = GenesisDocFromJSON(genDocBytes)
assert.Error(t, err, "expected error for genDoc json with block size of 0")
+35 -10
View File
@@ -41,7 +41,7 @@ type ConsensusParams struct {
Evidence EvidenceParams `json:"evidence"`
Validator ValidatorParams `json:"validator"`
Version VersionParams `json:"version"`
Timestamp TimestampParams `json:"timestamp"`
Timing TimingParams `json:"timing"`
}
// HashedParams is a subset of ConsensusParams.
@@ -76,11 +76,11 @@ type VersionParams struct {
AppVersion uint64 `json:"app_version"`
}
// TimestampParams influence the validity of block timestamps.
// TimingParams influence the validity of block timestamps.
// TODO (@wbanfield): add link to proposer-based timestamp spec when completed.
type TimestampParams struct {
Precision time.Duration `json:"precision"`
MsgDelay time.Duration `json:"msg_delay"`
type TimingParams struct {
Precision time.Duration `json:"precision"`
MessageDelay time.Duration `json:"message_delay"`
}
// DefaultConsensusParams returns a default ConsensusParams.
@@ -90,6 +90,7 @@ func DefaultConsensusParams() *ConsensusParams {
Evidence: DefaultEvidenceParams(),
Validator: DefaultValidatorParams(),
Version: DefaultVersionParams(),
Timing: DefaultTimingParams(),
}
}
@@ -124,12 +125,12 @@ func DefaultVersionParams() VersionParams {
}
}
func DefaultTimestampParams() TimestampParams {
func DefaultTimingParams() TimingParams {
// TODO(@wbanfield): Determine experimental values for these defaults
// https://github.com/tendermint/tendermint/issues/7202
return TimestampParams{
Precision: 2 * time.Second,
MsgDelay: 3 * time.Second,
return TimingParams{
Precision: 1 * time.Nanosecond,
MessageDelay: 1 * time.Nanosecond,
}
}
@@ -165,7 +166,7 @@ func (params ConsensusParams) ValidateConsensusParams() error {
}
if params.Evidence.MaxAgeDuration <= 0 {
return fmt.Errorf("evidence.MaxAgeDuration must be grater than 0 if provided, Got %v",
return fmt.Errorf("evidence.MaxAgeDuration must be greater than 0 if provided, Got %v",
params.Evidence.MaxAgeDuration)
}
@@ -179,6 +180,16 @@ func (params ConsensusParams) ValidateConsensusParams() error {
params.Evidence.MaxBytes)
}
if params.Timing.MessageDelay <= 0 {
return fmt.Errorf("timing.MessageDelay must be greater than 0. Got: %d",
params.Timing.MessageDelay)
}
if params.Timing.Precision <= 0 {
return fmt.Errorf("timing.Precision must be greater than 0. Got: %d",
params.Timing.Precision)
}
if len(params.Validator.PubKeyTypes) == 0 {
return errors.New("len(Validator.PubKeyTypes) must be greater than 0")
}
@@ -222,6 +233,8 @@ func (params ConsensusParams) HashConsensusParams() []byte {
func (params *ConsensusParams) Equals(params2 *ConsensusParams) bool {
return params.Block == params2.Block &&
params.Evidence == params2.Evidence &&
params.Version == params2.Version &&
params.Timing == params2.Timing &&
tmstrings.StringSliceEqual(params.Validator.PubKeyTypes, params2.Validator.PubKeyTypes)
}
@@ -252,6 +265,10 @@ func (params ConsensusParams) UpdateConsensusParams(params2 *tmproto.ConsensusPa
if params2.Version != nil {
res.Version.AppVersion = params2.Version.AppVersion
}
if params2.Timing != nil {
res.Timing.Precision = params2.Timing.Precision
res.Timing.MessageDelay = params2.Timing.MessageDelay
}
return res
}
@@ -272,6 +289,10 @@ func (params *ConsensusParams) ToProto() tmproto.ConsensusParams {
Version: &tmproto.VersionParams{
AppVersion: params.Version.AppVersion,
},
Timing: &tmproto.TimingParams{
MessageDelay: params.Timing.MessageDelay,
Precision: params.Timing.Precision,
},
}
}
@@ -292,5 +313,9 @@ func ConsensusParamsFromProto(pbParams tmproto.ConsensusParams) ConsensusParams
Version: VersionParams{
AppVersion: pbParams.Version.AppVersion,
},
Timing: TimingParams{
MessageDelay: pbParams.Timing.MessageDelay,
Precision: pbParams.Timing.Precision,
},
}
}
+207 -54
View File
@@ -23,23 +23,140 @@ func TestConsensusParamsValidation(t *testing.T) {
valid bool
}{
// test block params
0: {makeParams(1, 0, 2, 0, valEd25519), true},
1: {makeParams(0, 0, 2, 0, valEd25519), false},
2: {makeParams(47*1024*1024, 0, 2, 0, valEd25519), true},
3: {makeParams(10, 0, 2, 0, valEd25519), true},
4: {makeParams(100*1024*1024, 0, 2, 0, valEd25519), true},
5: {makeParams(101*1024*1024, 0, 2, 0, valEd25519), false},
6: {makeParams(1024*1024*1024, 0, 2, 0, valEd25519), false},
7: {makeParams(1024*1024*1024, 0, -1, 0, valEd25519), false},
{
params: makeParams(makeParamsArgs{
blockBytes: 1,
evidenceAge: 2,
precision: 1,
messageDelay: 1}),
valid: true,
},
{
params: makeParams(makeParamsArgs{
blockBytes: 0,
evidenceAge: 2,
precision: 1,
messageDelay: 1}),
valid: false,
},
{
params: makeParams(makeParamsArgs{
blockBytes: 47 * 1024 * 1024,
evidenceAge: 2,
precision: 1,
messageDelay: 1}),
valid: true,
},
{
params: makeParams(makeParamsArgs{
blockBytes: 10,
evidenceAge: 2,
precision: 1,
messageDelay: 1}),
valid: true,
},
{
params: makeParams(makeParamsArgs{
blockBytes: 100 * 1024 * 1024,
evidenceAge: 2,
precision: 1,
messageDelay: 1}),
valid: true,
},
{
params: makeParams(makeParamsArgs{
blockBytes: 101 * 1024 * 1024,
evidenceAge: 2,
precision: 1,
messageDelay: 1}),
valid: false,
},
{
params: makeParams(makeParamsArgs{
blockBytes: 1024 * 1024 * 1024,
evidenceAge: 2,
precision: 1,
messageDelay: 1}),
valid: false,
},
{
params: makeParams(makeParamsArgs{
blockBytes: 1024 * 1024 * 1024,
evidenceAge: 2,
precision: 1,
messageDelay: 1}),
valid: false,
},
// test evidence params
8: {makeParams(1, 0, 0, 0, valEd25519), false},
9: {makeParams(1, 0, 2, 2, valEd25519), false},
10: {makeParams(1000, 0, 2, 1, valEd25519), true},
11: {makeParams(1, 0, -1, 0, valEd25519), false},
{
params: makeParams(makeParamsArgs{
blockBytes: 1,
evidenceAge: 0,
maxEvidenceBytes: 0,
precision: 1,
messageDelay: 1}),
valid: false,
},
{
params: makeParams(makeParamsArgs{
blockBytes: 1,
evidenceAge: 2,
maxEvidenceBytes: 2,
precision: 1,
messageDelay: 1}),
valid: false,
},
{
params: makeParams(makeParamsArgs{
blockBytes: 1000,
evidenceAge: 2,
maxEvidenceBytes: 1,
precision: 1,
messageDelay: 1}),
valid: true,
},
{
params: makeParams(makeParamsArgs{
blockBytes: 1,
evidenceAge: -1,
maxEvidenceBytes: 0,
precision: 1,
messageDelay: 1}),
valid: false,
},
// test no pubkey type provided
12: {makeParams(1, 0, 2, 0, []string{}), false},
{
params: makeParams(makeParamsArgs{
evidenceAge: 2,
pubkeyTypes: []string{},
precision: 1,
messageDelay: 1}),
valid: false,
},
// test invalid pubkey type provided
13: {makeParams(1, 0, 2, 0, []string{"potatoes make good pubkeys"}), false},
{
params: makeParams(makeParamsArgs{
evidenceAge: 2,
pubkeyTypes: []string{"potatoes make good pubkeys"},
precision: 1,
messageDelay: 1}),
valid: false,
},
// test invalid pubkey type provided
{
params: makeParams(makeParamsArgs{
evidenceAge: 2,
precision: 1,
messageDelay: -1}),
valid: false,
},
{
params: makeParams(makeParamsArgs{
evidenceAge: 2,
precision: -1,
messageDelay: 1}),
valid: false,
},
}
for i, tc := range testCases {
if tc.valid {
@@ -50,38 +167,51 @@ func TestConsensusParamsValidation(t *testing.T) {
}
}
func makeParams(
blockBytes, blockGas int64,
evidenceAge int64,
maxEvidenceBytes int64,
pubkeyTypes []string,
) ConsensusParams {
type makeParamsArgs struct {
blockBytes int64
blockGas int64
evidenceAge int64
maxEvidenceBytes int64
pubkeyTypes []string
precision time.Duration
messageDelay time.Duration
}
func makeParams(args makeParamsArgs) ConsensusParams {
if args.pubkeyTypes == nil {
args.pubkeyTypes = valEd25519
}
return ConsensusParams{
Block: BlockParams{
MaxBytes: blockBytes,
MaxGas: blockGas,
MaxBytes: args.blockBytes,
MaxGas: args.blockGas,
},
Evidence: EvidenceParams{
MaxAgeNumBlocks: evidenceAge,
MaxAgeDuration: time.Duration(evidenceAge),
MaxBytes: maxEvidenceBytes,
MaxAgeNumBlocks: args.evidenceAge,
MaxAgeDuration: time.Duration(args.evidenceAge),
MaxBytes: args.maxEvidenceBytes,
},
Validator: ValidatorParams{
PubKeyTypes: pubkeyTypes,
PubKeyTypes: args.pubkeyTypes,
},
Timing: TimingParams{
Precision: args.precision,
MessageDelay: args.messageDelay,
},
}
}
func TestConsensusParamsHash(t *testing.T) {
params := []ConsensusParams{
makeParams(4, 2, 3, 1, valEd25519),
makeParams(1, 4, 3, 1, valEd25519),
makeParams(1, 2, 4, 1, valEd25519),
makeParams(2, 5, 7, 1, valEd25519),
makeParams(1, 7, 6, 1, valEd25519),
makeParams(9, 5, 4, 1, valEd25519),
makeParams(7, 8, 9, 1, valEd25519),
makeParams(4, 6, 5, 1, valEd25519),
makeParams(makeParamsArgs{blockBytes: 4, blockGas: 2, evidenceAge: 3, maxEvidenceBytes: 1}),
makeParams(makeParamsArgs{blockBytes: 1, blockGas: 4, evidenceAge: 3, maxEvidenceBytes: 1}),
makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 4, maxEvidenceBytes: 1}),
makeParams(makeParamsArgs{blockBytes: 2, blockGas: 5, evidenceAge: 7, maxEvidenceBytes: 1}),
makeParams(makeParamsArgs{blockBytes: 1, blockGas: 7, evidenceAge: 6, maxEvidenceBytes: 1}),
makeParams(makeParamsArgs{blockBytes: 9, blockGas: 5, evidenceAge: 4, maxEvidenceBytes: 1}),
makeParams(makeParamsArgs{blockBytes: 7, blockGas: 8, evidenceAge: 9, maxEvidenceBytes: 1}),
makeParams(makeParamsArgs{blockBytes: 4, blockGas: 6, evidenceAge: 5, maxEvidenceBytes: 1}),
}
hashes := make([][]byte, len(params))
@@ -101,20 +231,31 @@ func TestConsensusParamsHash(t *testing.T) {
func TestConsensusParamsUpdate(t *testing.T) {
testCases := []struct {
params ConsensusParams
intialParams ConsensusParams
updates *tmproto.ConsensusParams
updatedParams ConsensusParams
}{
// empty updates
{
makeParams(1, 2, 3, 0, valEd25519),
&tmproto.ConsensusParams{},
makeParams(1, 2, 3, 0, valEd25519),
intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}),
updates: &tmproto.ConsensusParams{},
updatedParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}),
},
{
// update timing params
intialParams: makeParams(makeParamsArgs{evidenceAge: 3, precision: time.Second, messageDelay: 3 * time.Second}),
updates: &tmproto.ConsensusParams{
Timing: &tmproto.TimingParams{
Precision: time.Second * 2,
MessageDelay: time.Second * 4,
},
},
updatedParams: makeParams(makeParamsArgs{evidenceAge: 3, precision: 2 * time.Second, messageDelay: 4 * time.Second}),
},
// fine updates
{
makeParams(1, 2, 3, 0, valEd25519),
&tmproto.ConsensusParams{
intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}),
updates: &tmproto.ConsensusParams{
Block: &tmproto.BlockParams{
MaxBytes: 100,
MaxGas: 200,
@@ -128,11 +269,15 @@ func TestConsensusParamsUpdate(t *testing.T) {
PubKeyTypes: valSecp256k1,
},
},
makeParams(100, 200, 300, 50, valSecp256k1),
updatedParams: makeParams(makeParamsArgs{
blockBytes: 100, blockGas: 200,
evidenceAge: 300,
maxEvidenceBytes: 50,
pubkeyTypes: valSecp256k1}),
},
{
makeParams(1, 2, 3, 0, valEd25519),
&tmproto.ConsensusParams{
intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}),
updates: &tmproto.ConsensusParams{
Block: &tmproto.BlockParams{
MaxBytes: 100,
MaxGas: 200,
@@ -145,17 +290,23 @@ func TestConsensusParamsUpdate(t *testing.T) {
Validator: &tmproto.ValidatorParams{
PubKeyTypes: valSr25519,
},
}, makeParams(100, 200, 300, 50, valSr25519),
},
updatedParams: makeParams(makeParamsArgs{
blockBytes: 100,
blockGas: 200,
evidenceAge: 300,
maxEvidenceBytes: 50,
pubkeyTypes: valSr25519}),
},
}
for _, tc := range testCases {
assert.Equal(t, tc.updatedParams, tc.params.UpdateConsensusParams(tc.updates))
assert.Equal(t, tc.updatedParams, tc.intialParams.UpdateConsensusParams(tc.updates))
}
}
func TestConsensusParamsUpdate_AppVersion(t *testing.T) {
params := makeParams(1, 2, 3, 0, valEd25519)
params := makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3})
assert.EqualValues(t, 0, params.Version.AppVersion)
@@ -167,14 +318,16 @@ func TestConsensusParamsUpdate_AppVersion(t *testing.T) {
func TestProto(t *testing.T) {
params := []ConsensusParams{
makeParams(4, 2, 3, 1, valEd25519),
makeParams(1, 4, 3, 1, valEd25519),
makeParams(1, 2, 4, 1, valEd25519),
makeParams(2, 5, 7, 1, valEd25519),
makeParams(1, 7, 6, 1, valEd25519),
makeParams(9, 5, 4, 1, valEd25519),
makeParams(7, 8, 9, 1, valEd25519),
makeParams(4, 6, 5, 1, valEd25519),
makeParams(makeParamsArgs{blockBytes: 4, blockGas: 2, evidenceAge: 3, maxEvidenceBytes: 1}),
makeParams(makeParamsArgs{blockBytes: 1, blockGas: 4, evidenceAge: 3, maxEvidenceBytes: 1}),
makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 4, maxEvidenceBytes: 1}),
makeParams(makeParamsArgs{blockBytes: 2, blockGas: 5, evidenceAge: 7, maxEvidenceBytes: 1}),
makeParams(makeParamsArgs{blockBytes: 1, blockGas: 7, evidenceAge: 6, maxEvidenceBytes: 1}),
makeParams(makeParamsArgs{blockBytes: 9, blockGas: 5, evidenceAge: 4, maxEvidenceBytes: 1}),
makeParams(makeParamsArgs{blockBytes: 7, blockGas: 8, evidenceAge: 9, maxEvidenceBytes: 1}),
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}),
}
for i := range params {
+2 -2
View File
@@ -88,10 +88,10 @@ func (p *Proposal) ValidateBasic() error {
//
// For more information on the meaning of 'timely', see the proposer-based timestamp specification:
// https://github.com/tendermint/spec/tree/master/spec/consensus/proposer-based-timestamp
func (p *Proposal) IsTimely(clock tmtime.Source, tp TimestampParams) bool {
func (p *Proposal) IsTimely(clock tmtime.Source, tp TimingParams) bool {
lt := clock.Now()
lhs := lt.Add(-tp.Precision)
rhs := lt.Add(tp.Precision).Add(tp.MsgDelay)
rhs := lt.Add(tp.Precision).Add(tp.MessageDelay)
if lhs.Before(p.Timestamp) && rhs.After(p.Timestamp) {
return true
}
+3 -3
View File
@@ -241,9 +241,9 @@ func TestIsTimely(t *testing.T) {
Timestamp: testCase.proposalTime,
}
tp := TimestampParams{
Precision: testCase.precision,
MsgDelay: testCase.msgDelay,
tp := TimingParams{
Precision: testCase.precision,
MessageDelay: testCase.msgDelay,
}
mockSource := new(tmtimemocks.Source)