Browse Source

evidence: check lunatic vote matches header (#5093)

pull/5103/head
Callum Waters 4 years ago
committed by GitHub
parent
commit
a97d05be4d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 59 additions and 11 deletions
  1. +7
    -1
      state/validation_test.go
  2. +10
    -1
      types/evidence.go
  3. +42
    -9
      types/evidence_test.go

+ 7
- 1
state/validation_test.go View File

@ -587,7 +587,13 @@ func TestVerifyEvidenceWithLunaticValidatorEvidence(t *testing.T) {
EvidenceHash: tmhash.Sum([]byte("evidence_hash")), EvidenceHash: tmhash.Sum([]byte("evidence_hash")),
ProposerAddress: crypto.AddressHash([]byte("proposer_address")), 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() v := vote.ToProto()
err := vals[val.Address.String()].SignVote(chainID, v) err := vals[val.Address.String()].SignVote(chainID, v)
vote.Signature = v.Signature vote.Signature = v.Signature


+ 10
- 1
types/evidence.go View File

@ -941,10 +941,19 @@ func (e *LunaticValidatorEvidence) ValidateBasic() error {
switch e.InvalidHeaderField { switch e.InvalidHeaderField {
case "ValidatorsHash", "NextValidatorsHash", "ConsensusHash", "AppHash", "LastResultsHash": case "ValidatorsHash", "NextValidatorsHash", "ConsensusHash", "AppHash", "LastResultsHash":
return nil
break
default: default:
return errors.New("unknown invalid header field") 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 { func (e *LunaticValidatorEvidence) String() string {


+ 42
- 9
types/evidence_test.go View File

@ -208,32 +208,65 @@ func TestMockEvidenceValidateBasic(t *testing.T) {
func TestLunaticValidatorEvidence(t *testing.T) { func TestLunaticValidatorEvidence(t *testing.T) {
var ( 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 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") ev := NewLunaticValidatorEvidence(header, vote, "AppHash")
//happy path
assert.Equal(t, header.Height, ev.Height()) assert.Equal(t, header.Height, ev.Height())
assert.Equal(t, defaultVoteTime, ev.Time()) assert.Equal(t, defaultVoteTime, ev.Time())
assert.EqualValues(t, vote.ValidatorAddress, ev.Address()) assert.EqualValues(t, vote.ValidatorAddress, ev.Address())
assert.NotEmpty(t, ev.Hash()) assert.NotEmpty(t, ev.Hash())
assert.NotEmpty(t, ev.Bytes()) assert.NotEmpty(t, ev.Bytes())
assert.True(t, ev.Equal(ev))
pubKey, err := val.GetPubKey() pubKey, err := val.GetPubKey()
require.NoError(t, err) require.NoError(t, err)
assert.NoError(t, ev.Verify(header.ChainID, pubKey)) 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)) assert.Error(t, ev.Verify("other", pubKey))
privKey2 := ed25519.GenPrivKey() privKey2 := ed25519.GenPrivKey()
pubKey2 := privKey2.PubKey() 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) { func TestPhantomValidatorEvidence(t *testing.T) {


Loading…
Cancel
Save