From a97d05be4df72e17bc10168f49d4f61cad05e90d Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Wed, 8 Jul 2020 17:58:03 +0200 Subject: [PATCH] evidence: check lunatic vote matches header (#5093) --- state/validation_test.go | 8 ++++++- types/evidence.go | 11 ++++++++- types/evidence_test.go | 51 +++++++++++++++++++++++++++++++++------- 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/state/validation_test.go b/state/validation_test.go index 54bfc3723..087d8328c 100644 --- a/state/validation_test.go +++ b/state/validation_test.go @@ -587,7 +587,13 @@ func TestVerifyEvidenceWithLunaticValidatorEvidence(t *testing.T) { EvidenceHash: tmhash.Sum([]byte("evidence_hash")), ProposerAddress: crypto.AddressHash([]byte("proposer_address")), } - vote := makeVote(3, 1, 0, addr, blockID) + vote := makeVote(3, 1, 0, addr, types.BlockID{ + Hash: h.Hash(), + PartSetHeader: types.PartSetHeader{ + Total: 100, + Hash: crypto.CRandBytes(tmhash.Size), + }, + }) v := vote.ToProto() err := vals[val.Address.String()].SignVote(chainID, v) vote.Signature = v.Signature diff --git a/types/evidence.go b/types/evidence.go index 89b1ce38c..ea899dd49 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -941,10 +941,19 @@ func (e *LunaticValidatorEvidence) ValidateBasic() error { switch e.InvalidHeaderField { case "ValidatorsHash", "NextValidatorsHash", "ConsensusHash", "AppHash", "LastResultsHash": - return nil + break default: return errors.New("unknown invalid header field") } + + if !bytes.Equal(e.Header.Hash(), e.Vote.BlockID.Hash) { + return fmt.Errorf("vote was not for header: %X != %X", + e.Vote.BlockID.Hash, + e.Header.Hash(), + ) + } + + return nil } func (e *LunaticValidatorEvidence) String() string { diff --git a/types/evidence_test.go b/types/evidence_test.go index 28f7652f5..1e0047e52 100644 --- a/types/evidence_test.go +++ b/types/evidence_test.go @@ -208,32 +208,65 @@ func TestMockEvidenceValidateBasic(t *testing.T) { func TestLunaticValidatorEvidence(t *testing.T) { var ( - blockID = makeBlockIDRandom() - header = makeHeaderRandom() - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - val = NewMockPV() - vote = makeVote(t, val, header.ChainID, 0, header.Height, 0, 2, blockID, defaultVoteTime) + invalidBlockID = makeBlockIDRandom() + header = makeHeaderRandom() + altHeader = makeHeaderRandom() + bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") + val = NewMockPV() ) header.Time = bTime + blockID := BlockID{ + Hash: header.Hash(), + PartSetHeader: PartSetHeader{ + Total: 100, + Hash: crypto.CRandBytes(tmhash.Size), + }, + } + + vote := makeVote(t, val, header.ChainID, 0, header.Height, 0, 2, blockID, defaultVoteTime) + ev := NewLunaticValidatorEvidence(header, vote, "AppHash") + //happy path assert.Equal(t, header.Height, ev.Height()) assert.Equal(t, defaultVoteTime, ev.Time()) assert.EqualValues(t, vote.ValidatorAddress, ev.Address()) assert.NotEmpty(t, ev.Hash()) assert.NotEmpty(t, ev.Bytes()) + assert.True(t, ev.Equal(ev)) pubKey, err := val.GetPubKey() require.NoError(t, err) assert.NoError(t, ev.Verify(header.ChainID, pubKey)) + assert.NoError(t, ev.ValidateBasic()) + assert.NotEmpty(t, ev.String()) + assert.NoError(t, ev.VerifyHeader(altHeader)) + + // invalid evidence assert.Error(t, ev.Verify("other", pubKey)) privKey2 := ed25519.GenPrivKey() pubKey2 := privKey2.PubKey() - assert.Error(t, ev.Verify("other", pubKey2)) - assert.True(t, ev.Equal(ev)) - assert.NoError(t, ev.ValidateBasic()) - assert.NotEmpty(t, ev.String()) + assert.Error(t, ev.Verify(header.ChainID, pubKey2)) + assert.Error(t, ev.VerifyHeader(header)) + + invalidVote := makeVote(t, val, header.ChainID, 0, header.Height, 0, 2, invalidBlockID, defaultVoteTime) + invalidHeightVote := makeVote(t, val, header.ChainID, 0, header.Height+1, 0, 2, blockID, defaultVoteTime) + emptyBlockVote := makeVote(t, val, header.ChainID, 0, header.Height, 0, 2, BlockID{}, defaultVoteTime) + + invalidLunaticEvidence := []*LunaticValidatorEvidence{ + NewLunaticValidatorEvidence(header, invalidVote, "AppHash"), + NewLunaticValidatorEvidence(header, invalidHeightVote, "AppHash"), + NewLunaticValidatorEvidence(nil, vote, "AppHash"), + NewLunaticValidatorEvidence(header, nil, "AppHash"), + NewLunaticValidatorEvidence(header, vote, "other"), + NewLunaticValidatorEvidence(header, emptyBlockVote, "AppHash"), + } + + for idx, ev := range invalidLunaticEvidence { + assert.Error(t, ev.ValidateBasic(), "#%d", idx) + } + } func TestPhantomValidatorEvidence(t *testing.T) {