evidence: introduce time.Duration to evidence params (#4254)

* evidence: introduce time.Duration to evidence params

- add time.duration to evidence
- this pr is taking pr #2606 and updating it to use both time and height

- closes #2565

Signed-off-by: Marko Baricevic <marbar3778@yahoo.com>

* fix testing and genesis cfg in signer harness

* remove debugging fmt

* change maxageheight to maxagenumblocks, rename other things to block instead of height

* further check of duration

* check duration to not send peers outdated evidence

* change some lines, onward and upward

* refactor evidence package

* add a changelog pending entry

* make mockbadevidence have time and use it

* add what could possibly be called a test case

* remove mockbadevidence and mockgoodevidence in favor of mockevidence

* add a comment for err that is returned

* add a changelog for removal of good & bad evidence

* add a test for adding evidence

* fix test

* add ev to types in testcase

* Update evidence/pool_test.go

Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com>

* Update evidence/pool_test.go

Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com>

* fix tests

* fix linting

Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
This commit is contained in:
Marko
2020-01-08 10:46:37 +01:00
committed by GitHub
co-authored by Anton Kaliaev
parent d7f4ce30ca
commit 6d91c1faf4
26 changed files with 540 additions and 382 deletions
+4 -4
View File
@@ -40,7 +40,7 @@ func TestBlockAddEvidence(t *testing.T) {
commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals)
require.NoError(t, err)
ev := NewMockGoodEvidence(h, 0, valSet.Validators[0].Address)
ev := NewMockEvidence(h, time.Now(), 0, valSet.Validators[0].Address)
evList := []Evidence{ev}
block := MakeBlock(h, txs, commit, evList)
@@ -60,7 +60,7 @@ func TestBlockValidateBasic(t *testing.T) {
commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals)
require.NoError(t, err)
ev := NewMockGoodEvidence(h, 0, valSet.Validators[0].Address)
ev := NewMockEvidence(h, time.Now(), 0, valSet.Validators[0].Address)
evList := []Evidence{ev}
testCases := []struct {
@@ -123,7 +123,7 @@ func TestBlockMakePartSetWithEvidence(t *testing.T) {
commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals)
require.NoError(t, err)
ev := NewMockGoodEvidence(h, 0, valSet.Validators[0].Address)
ev := NewMockEvidence(h, time.Now(), 0, valSet.Validators[0].Address)
evList := []Evidence{ev}
partSet := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList).MakePartSet(512)
@@ -140,7 +140,7 @@ func TestBlockHashesTo(t *testing.T) {
commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals)
require.NoError(t, err)
ev := NewMockGoodEvidence(h, 0, valSet.Validators[0].Address)
ev := NewMockEvidence(h, time.Now(), 0, valSet.Validators[0].Address)
evList := []Evidence{ev}
block := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList)
+42 -44
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"strings"
"time"
"github.com/pkg/errors"
"github.com/tendermint/tendermint/crypto/tmhash"
@@ -56,6 +57,7 @@ func (err *ErrEvidenceOverflow) Error() string {
// Evidence represents any provable malicious activity by a validator
type Evidence interface {
Height() int64 // height of the equivocation
Time() time.Time // time of the equivocation
Address() []byte // address of the equivocating validator
Bytes() []byte // bytes which compromise the evidence
Hash() []byte // hash of the evidence
@@ -72,9 +74,8 @@ func RegisterEvidences(cdc *amino.Codec) {
}
func RegisterMockEvidences(cdc *amino.Codec) {
cdc.RegisterConcrete(MockGoodEvidence{}, "tendermint/MockGoodEvidence", nil)
cdc.RegisterConcrete(MockRandomGoodEvidence{}, "tendermint/MockRandomGoodEvidence", nil)
cdc.RegisterConcrete(MockBadEvidence{}, "tendermint/MockBadEvidence", nil)
cdc.RegisterConcrete(MockEvidence{}, "tendermint/MockEvidence", nil)
cdc.RegisterConcrete(MockRandomEvidence{}, "tendermint/MockRandomEvidence", nil)
}
const (
@@ -136,6 +137,11 @@ func (dve *DuplicateVoteEvidence) Height() int64 {
return dve.VoteA.Height
}
// Time return the time the evidence was created
func (dve *DuplicateVoteEvidence) Time() time.Time {
return dve.VoteA.Timestamp
}
// Address returns the address of the validator.
func (dve *DuplicateVoteEvidence) Address() []byte {
return dve.PubKey.Address()
@@ -241,72 +247,64 @@ func (dve *DuplicateVoteEvidence) ValidateBasic() error {
//-----------------------------------------------------------------
// UNSTABLE
type MockRandomGoodEvidence struct {
MockGoodEvidence
type MockRandomEvidence struct {
MockEvidence
randBytes []byte
}
var _ Evidence = &MockRandomGoodEvidence{}
var _ Evidence = &MockRandomEvidence{}
// UNSTABLE
func NewMockRandomGoodEvidence(height int64, address []byte, randBytes []byte) MockRandomGoodEvidence {
return MockRandomGoodEvidence{
MockGoodEvidence{height, address}, randBytes,
func NewMockRandomEvidence(height int64, eTime time.Time, address []byte, randBytes []byte) MockRandomEvidence {
return MockRandomEvidence{
MockEvidence{
EvidenceHeight: height,
EvidenceTime: eTime,
EvidenceAddress: address}, randBytes,
}
}
func (e MockRandomGoodEvidence) Hash() []byte {
func (e MockRandomEvidence) Hash() []byte {
return []byte(fmt.Sprintf("%d-%x", e.EvidenceHeight, e.randBytes))
}
// UNSTABLE
type MockGoodEvidence struct {
type MockEvidence struct {
EvidenceHeight int64
EvidenceTime time.Time
EvidenceAddress []byte
}
var _ Evidence = &MockGoodEvidence{}
var _ Evidence = &MockEvidence{}
// UNSTABLE
func NewMockGoodEvidence(height int64, idx int, address []byte) MockGoodEvidence {
return MockGoodEvidence{height, address}
func NewMockEvidence(height int64, eTime time.Time, idx int, address []byte) MockEvidence {
return MockEvidence{
EvidenceHeight: height,
EvidenceTime: eTime,
EvidenceAddress: address}
}
func (e MockGoodEvidence) Height() int64 { return e.EvidenceHeight }
func (e MockGoodEvidence) Address() []byte { return e.EvidenceAddress }
func (e MockGoodEvidence) Hash() []byte {
return []byte(fmt.Sprintf("%d-%x", e.EvidenceHeight, e.EvidenceAddress))
func (e MockEvidence) Height() int64 { return e.EvidenceHeight }
func (e MockEvidence) Time() time.Time { return e.EvidenceTime }
func (e MockEvidence) Address() []byte { return e.EvidenceAddress }
func (e MockEvidence) Hash() []byte {
return []byte(fmt.Sprintf("%d-%x-%s",
e.EvidenceHeight, e.EvidenceAddress, e.EvidenceTime))
}
func (e MockGoodEvidence) Bytes() []byte {
return []byte(fmt.Sprintf("%d-%x", e.EvidenceHeight, e.EvidenceAddress))
func (e MockEvidence) Bytes() []byte {
return []byte(fmt.Sprintf("%d-%x-%s",
e.EvidenceHeight, e.EvidenceAddress, e.EvidenceTime))
}
func (e MockGoodEvidence) Verify(chainID string, pubKey crypto.PubKey) error { return nil }
func (e MockGoodEvidence) Equal(ev Evidence) bool {
e2 := ev.(MockGoodEvidence)
func (e MockEvidence) Verify(chainID string, pubKey crypto.PubKey) error { return nil }
func (e MockEvidence) Equal(ev Evidence) bool {
e2 := ev.(MockEvidence)
return e.EvidenceHeight == e2.EvidenceHeight &&
bytes.Equal(e.EvidenceAddress, e2.EvidenceAddress)
}
func (e MockGoodEvidence) ValidateBasic() error { return nil }
func (e MockGoodEvidence) String() string {
return fmt.Sprintf("GoodEvidence: %d/%s", e.EvidenceHeight, e.EvidenceAddress)
}
// UNSTABLE
type MockBadEvidence struct {
MockGoodEvidence
}
func (e MockBadEvidence) Verify(chainID string, pubKey crypto.PubKey) error {
return fmt.Errorf("mockBadEvidence")
}
func (e MockBadEvidence) Equal(ev Evidence) bool {
e2 := ev.(MockBadEvidence)
return e.EvidenceHeight == e2.EvidenceHeight &&
bytes.Equal(e.EvidenceAddress, e2.EvidenceAddress)
}
func (e MockBadEvidence) ValidateBasic() error { return nil }
func (e MockBadEvidence) String() string {
return fmt.Sprintf("BadEvidence: %d/%s", e.EvidenceHeight, e.EvidenceAddress)
func (e MockEvidence) ValidateBasic() error { return nil }
func (e MockEvidence) String() string {
return fmt.Sprintf("Evidence: %d/%s/%s", e.EvidenceHeight, e.Time(), e.EvidenceAddress)
}
//-------------------------------------------
+3 -2
View File
@@ -3,6 +3,7 @@ package types
import (
"math"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -164,11 +165,11 @@ func TestDuplicateVoteEvidenceValidation(t *testing.T) {
}
func TestMockGoodEvidenceValidateBasic(t *testing.T) {
goodEvidence := NewMockGoodEvidence(int64(1), 1, []byte{1})
goodEvidence := NewMockEvidence(int64(1), time.Now(), 1, []byte{1})
assert.Nil(t, goodEvidence.ValidateBasic())
}
func TestMockBadEvidenceValidateBasic(t *testing.T) {
badEvidence := MockBadEvidence{MockGoodEvidence: NewMockGoodEvidence(int64(1), 1, []byte{1})}
badEvidence := NewMockEvidence(int64(1), time.Now(), 1, []byte{1})
assert.Nil(t, badEvidence.ValidateBasic())
}
+16 -6
View File
@@ -1,6 +1,8 @@
package types
import (
"time"
"github.com/pkg/errors"
abci "github.com/tendermint/tendermint/abci/types"
@@ -47,7 +49,8 @@ type BlockParams struct {
// EvidenceParams determine how we handle evidence of malfeasance.
type EvidenceParams struct {
MaxAge int64 `json:"max_age"` // only accept new evidence more recent than this
MaxAgeNumBlocks int64 `json:"max_age_num_blocks"` // only accept new evidence more recent than this
MaxAgeDuration time.Duration `json:"max_age_duration"`
}
// ValidatorParams restrict the public key types validators can use.
@@ -77,7 +80,8 @@ func DefaultBlockParams() BlockParams {
// DefaultEvidenceParams Params returns a default EvidenceParams.
func DefaultEvidenceParams() EvidenceParams {
return EvidenceParams{
MaxAge: 100000, // 27.8 hrs at 1block/s
MaxAgeNumBlocks: 100000, // 27.8 hrs at 1block/s
MaxAgeDuration: 48 * time.Hour,
}
}
@@ -118,9 +122,14 @@ func (params *ConsensusParams) Validate() error {
params.Block.TimeIotaMs)
}
if params.Evidence.MaxAge <= 0 {
return errors.Errorf("evidenceParams.MaxAge must be greater than 0. Got %d",
params.Evidence.MaxAge)
if params.Evidence.MaxAgeNumBlocks <= 0 {
return errors.Errorf("evidenceParams.MaxAgeNumBlocks must be greater than 0. Got %d",
params.Evidence.MaxAgeNumBlocks)
}
if params.Evidence.MaxAgeDuration <= 0 {
return errors.Errorf("evidenceParams.MaxAgeDuration must be grater than 0 if provided, Got %v",
params.Evidence.MaxAgeDuration)
}
if len(params.Validator.PubKeyTypes) == 0 {
@@ -177,7 +186,8 @@ func (params ConsensusParams) Update(params2 *abci.ConsensusParams) ConsensusPar
res.Block.MaxGas = params2.Block.MaxGas
}
if params2.Evidence != nil {
res.Evidence.MaxAge = params2.Evidence.MaxAge
res.Evidence.MaxAgeNumBlocks = params2.Evidence.MaxAgeNumBlocks
res.Evidence.MaxAgeDuration = params2.Evidence.MaxAgeDuration
}
if params2.Validator != nil {
// Copy params2.Validator.PubkeyTypes, and set result's value to the copy.
+5 -2
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"sort"
"testing"
"time"
"github.com/stretchr/testify/assert"
abci "github.com/tendermint/tendermint/abci/types"
@@ -59,7 +60,8 @@ func makeParams(
TimeIotaMs: blockTimeIotaMs,
},
Evidence: EvidenceParams{
MaxAge: evidenceAge,
MaxAgeNumBlocks: evidenceAge,
MaxAgeDuration: time.Duration(evidenceAge),
},
Validator: ValidatorParams{
PubKeyTypes: pubkeyTypes,
@@ -115,7 +117,8 @@ func TestConsensusParamsUpdate(t *testing.T) {
MaxGas: 200,
},
Evidence: &abci.EvidenceParams{
MaxAge: 300,
MaxAgeNumBlocks: 300,
MaxAgeDuration: time.Duration(300),
},
Validator: &abci.ValidatorParams{
PubKeyTypes: valSecp256k1,
+5 -4
View File
@@ -17,7 +17,7 @@ import (
const (
ABCIEvidenceTypeDuplicateVote = "duplicate/vote"
ABCIEvidenceTypeMockGood = "mock/good"
ABCIEvidenceTypeMock = "mock/evidence"
)
const (
@@ -136,7 +136,8 @@ func (tm2pb) ConsensusParams(params *ConsensusParams) *abci.ConsensusParams {
MaxGas: params.Block.MaxGas,
},
Evidence: &abci.EvidenceParams{
MaxAge: params.Evidence.MaxAge,
MaxAgeNumBlocks: params.Evidence.MaxAgeNumBlocks,
MaxAgeDuration: params.Evidence.MaxAgeDuration,
},
Validator: &abci.ValidatorParams{
PubKeyTypes: params.Validator.PubKeyTypes,
@@ -159,9 +160,9 @@ func (tm2pb) Evidence(ev Evidence, valSet *ValidatorSet, evTime time.Time) abci.
switch ev.(type) {
case *DuplicateVoteEvidence:
evType = ABCIEvidenceTypeDuplicateVote
case MockGoodEvidence:
case MockEvidence:
// XXX: not great to have test types in production paths ...
evType = ABCIEvidenceTypeMockGood
evType = ABCIEvidenceTypeMock
default:
panic(fmt.Sprintf("Unknown evidence type: %v %v", ev, reflect.TypeOf(ev)))
}