github.com/evdatsion/aphelion-dpos-bft@v0.32.1/types/evidence.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "fmt" 6 7 "github.com/pkg/errors" 8 "github.com/evdatsion/aphelion-dpos-bft/crypto/tmhash" 9 10 amino "github.com/evdatsion/go-amino" 11 12 "github.com/evdatsion/aphelion-dpos-bft/crypto" 13 "github.com/evdatsion/aphelion-dpos-bft/crypto/merkle" 14 ) 15 16 const ( 17 // MaxEvidenceBytes is a maximum size of any evidence (including amino overhead). 18 MaxEvidenceBytes int64 = 484 19 ) 20 21 // ErrEvidenceInvalid wraps a piece of evidence and the error denoting how or why it is invalid. 22 type ErrEvidenceInvalid struct { 23 Evidence Evidence 24 ErrorValue error 25 } 26 27 // NewErrEvidenceInvalid returns a new EvidenceInvalid with the given err. 28 func NewErrEvidenceInvalid(ev Evidence, err error) *ErrEvidenceInvalid { 29 return &ErrEvidenceInvalid{ev, err} 30 } 31 32 // Error returns a string representation of the error. 33 func (err *ErrEvidenceInvalid) Error() string { 34 return fmt.Sprintf("Invalid evidence: %v. Evidence: %v", err.ErrorValue, err.Evidence) 35 } 36 37 // ErrEvidenceOverflow is for when there is too much evidence in a block. 38 type ErrEvidenceOverflow struct { 39 MaxNum int64 40 GotNum int64 41 } 42 43 // NewErrEvidenceOverflow returns a new ErrEvidenceOverflow where got > max. 44 func NewErrEvidenceOverflow(max, got int64) *ErrEvidenceOverflow { 45 return &ErrEvidenceOverflow{max, got} 46 } 47 48 // Error returns a string representation of the error. 49 func (err *ErrEvidenceOverflow) Error() string { 50 return fmt.Sprintf("Too much evidence: Max %d, got %d", err.MaxNum, err.GotNum) 51 } 52 53 //------------------------------------------- 54 55 // Evidence represents any provable malicious activity by a validator 56 type Evidence interface { 57 Height() int64 // height of the equivocation 58 Address() []byte // address of the equivocating validator 59 Bytes() []byte // bytes which compromise the evidence 60 Hash() []byte // hash of the evidence 61 Verify(chainID string, pubKey crypto.PubKey) error // verify the evidence 62 Equal(Evidence) bool // check equality of evidence 63 64 ValidateBasic() error 65 String() string 66 } 67 68 func RegisterEvidences(cdc *amino.Codec) { 69 cdc.RegisterInterface((*Evidence)(nil), nil) 70 cdc.RegisterConcrete(&DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence", nil) 71 } 72 73 func RegisterMockEvidences(cdc *amino.Codec) { 74 cdc.RegisterConcrete(MockGoodEvidence{}, "tendermint/MockGoodEvidence", nil) 75 cdc.RegisterConcrete(MockRandomGoodEvidence{}, "tendermint/MockRandomGoodEvidence", nil) 76 cdc.RegisterConcrete(MockBadEvidence{}, "tendermint/MockBadEvidence", nil) 77 } 78 79 const ( 80 MaxEvidenceBytesDenominator = 10 81 ) 82 83 // MaxEvidencePerBlock returns the maximum number of evidences 84 // allowed in the block and their maximum total size (limitted to 1/10th 85 // of the maximum block size). 86 // TODO: change to a constant, or to a fraction of the validator set size. 87 // See https://github.com/evdatsion/aphelion-dpos-bft/issues/2590 88 func MaxEvidencePerBlock(blockMaxBytes int64) (int64, int64) { 89 maxBytes := blockMaxBytes / MaxEvidenceBytesDenominator 90 maxNum := maxBytes / MaxEvidenceBytes 91 return maxNum, maxBytes 92 } 93 94 //------------------------------------------- 95 96 // DuplicateVoteEvidence contains evidence a validator signed two conflicting 97 // votes. 98 type DuplicateVoteEvidence struct { 99 PubKey crypto.PubKey 100 VoteA *Vote 101 VoteB *Vote 102 } 103 104 var _ Evidence = &DuplicateVoteEvidence{} 105 106 // String returns a string representation of the evidence. 107 func (dve *DuplicateVoteEvidence) String() string { 108 return fmt.Sprintf("VoteA: %v; VoteB: %v", dve.VoteA, dve.VoteB) 109 110 } 111 112 // Height returns the height this evidence refers to. 113 func (dve *DuplicateVoteEvidence) Height() int64 { 114 return dve.VoteA.Height 115 } 116 117 // Address returns the address of the validator. 118 func (dve *DuplicateVoteEvidence) Address() []byte { 119 return dve.PubKey.Address() 120 } 121 122 // Hash returns the hash of the evidence. 123 func (dve *DuplicateVoteEvidence) Bytes() []byte { 124 return cdcEncode(dve) 125 } 126 127 // Hash returns the hash of the evidence. 128 func (dve *DuplicateVoteEvidence) Hash() []byte { 129 return tmhash.Sum(cdcEncode(dve)) 130 } 131 132 // Verify returns an error if the two votes aren't conflicting. 133 // To be conflicting, they must be from the same validator, for the same H/R/S, but for different blocks. 134 func (dve *DuplicateVoteEvidence) Verify(chainID string, pubKey crypto.PubKey) error { 135 // H/R/S must be the same 136 if dve.VoteA.Height != dve.VoteB.Height || 137 dve.VoteA.Round != dve.VoteB.Round || 138 dve.VoteA.Type != dve.VoteB.Type { 139 return fmt.Errorf("DuplicateVoteEvidence Error: H/R/S does not match. Got %v and %v", dve.VoteA, dve.VoteB) 140 } 141 142 // Address must be the same 143 if !bytes.Equal(dve.VoteA.ValidatorAddress, dve.VoteB.ValidatorAddress) { 144 return fmt.Errorf("DuplicateVoteEvidence Error: Validator addresses do not match. Got %X and %X", dve.VoteA.ValidatorAddress, dve.VoteB.ValidatorAddress) 145 } 146 147 // Index must be the same 148 if dve.VoteA.ValidatorIndex != dve.VoteB.ValidatorIndex { 149 return fmt.Errorf("DuplicateVoteEvidence Error: Validator indices do not match. Got %d and %d", dve.VoteA.ValidatorIndex, dve.VoteB.ValidatorIndex) 150 } 151 152 // BlockIDs must be different 153 if dve.VoteA.BlockID.Equals(dve.VoteB.BlockID) { 154 return fmt.Errorf("DuplicateVoteEvidence Error: BlockIDs are the same (%v) - not a real duplicate vote", dve.VoteA.BlockID) 155 } 156 157 // pubkey must match address (this should already be true, sanity check) 158 addr := dve.VoteA.ValidatorAddress 159 if !bytes.Equal(pubKey.Address(), addr) { 160 return fmt.Errorf("DuplicateVoteEvidence FAILED SANITY CHECK - address (%X) doesn't match pubkey (%v - %X)", 161 addr, pubKey, pubKey.Address()) 162 } 163 164 // Signatures must be valid 165 if !pubKey.VerifyBytes(dve.VoteA.SignBytes(chainID), dve.VoteA.Signature) { 166 return fmt.Errorf("DuplicateVoteEvidence Error verifying VoteA: %v", ErrVoteInvalidSignature) 167 } 168 if !pubKey.VerifyBytes(dve.VoteB.SignBytes(chainID), dve.VoteB.Signature) { 169 return fmt.Errorf("DuplicateVoteEvidence Error verifying VoteB: %v", ErrVoteInvalidSignature) 170 } 171 172 return nil 173 } 174 175 // Equal checks if two pieces of evidence are equal. 176 func (dve *DuplicateVoteEvidence) Equal(ev Evidence) bool { 177 if _, ok := ev.(*DuplicateVoteEvidence); !ok { 178 return false 179 } 180 181 // just check their hashes 182 dveHash := tmhash.Sum(cdcEncode(dve)) 183 evHash := tmhash.Sum(cdcEncode(ev)) 184 return bytes.Equal(dveHash, evHash) 185 } 186 187 // ValidateBasic performs basic validation. 188 func (dve *DuplicateVoteEvidence) ValidateBasic() error { 189 if len(dve.PubKey.Bytes()) == 0 { 190 return errors.New("Empty PubKey") 191 } 192 if dve.VoteA == nil || dve.VoteB == nil { 193 return fmt.Errorf("One or both of the votes are empty %v, %v", dve.VoteA, dve.VoteB) 194 } 195 if err := dve.VoteA.ValidateBasic(); err != nil { 196 return fmt.Errorf("Invalid VoteA: %v", err) 197 } 198 if err := dve.VoteB.ValidateBasic(); err != nil { 199 return fmt.Errorf("Invalid VoteB: %v", err) 200 } 201 return nil 202 } 203 204 //----------------------------------------------------------------- 205 206 // UNSTABLE 207 type MockRandomGoodEvidence struct { 208 MockGoodEvidence 209 randBytes []byte 210 } 211 212 var _ Evidence = &MockRandomGoodEvidence{} 213 214 // UNSTABLE 215 func NewMockRandomGoodEvidence(height int64, address []byte, randBytes []byte) MockRandomGoodEvidence { 216 return MockRandomGoodEvidence{ 217 MockGoodEvidence{height, address}, randBytes, 218 } 219 } 220 221 func (e MockRandomGoodEvidence) Hash() []byte { 222 return []byte(fmt.Sprintf("%d-%x", e.Height_, e.randBytes)) 223 } 224 225 // UNSTABLE 226 type MockGoodEvidence struct { 227 Height_ int64 228 Address_ []byte 229 } 230 231 var _ Evidence = &MockGoodEvidence{} 232 233 // UNSTABLE 234 func NewMockGoodEvidence(height int64, idx int, address []byte) MockGoodEvidence { 235 return MockGoodEvidence{height, address} 236 } 237 238 func (e MockGoodEvidence) Height() int64 { return e.Height_ } 239 func (e MockGoodEvidence) Address() []byte { return e.Address_ } 240 func (e MockGoodEvidence) Hash() []byte { 241 return []byte(fmt.Sprintf("%d-%x", e.Height_, e.Address_)) 242 } 243 func (e MockGoodEvidence) Bytes() []byte { 244 return []byte(fmt.Sprintf("%d-%x", e.Height_, e.Address_)) 245 } 246 func (e MockGoodEvidence) Verify(chainID string, pubKey crypto.PubKey) error { return nil } 247 func (e MockGoodEvidence) Equal(ev Evidence) bool { 248 e2 := ev.(MockGoodEvidence) 249 return e.Height_ == e2.Height_ && 250 bytes.Equal(e.Address_, e2.Address_) 251 } 252 func (e MockGoodEvidence) ValidateBasic() error { return nil } 253 func (e MockGoodEvidence) String() string { 254 return fmt.Sprintf("GoodEvidence: %d/%s", e.Height_, e.Address_) 255 } 256 257 // UNSTABLE 258 type MockBadEvidence struct { 259 MockGoodEvidence 260 } 261 262 func (e MockBadEvidence) Verify(chainID string, pubKey crypto.PubKey) error { 263 return fmt.Errorf("MockBadEvidence") 264 } 265 func (e MockBadEvidence) Equal(ev Evidence) bool { 266 e2 := ev.(MockBadEvidence) 267 return e.Height_ == e2.Height_ && 268 bytes.Equal(e.Address_, e2.Address_) 269 } 270 func (e MockBadEvidence) ValidateBasic() error { return nil } 271 func (e MockBadEvidence) String() string { 272 return fmt.Sprintf("BadEvidence: %d/%s", e.Height_, e.Address_) 273 } 274 275 //------------------------------------------- 276 277 // EvidenceList is a list of Evidence. Evidences is not a word. 278 type EvidenceList []Evidence 279 280 // Hash returns the simple merkle root hash of the EvidenceList. 281 func (evl EvidenceList) Hash() []byte { 282 // These allocations are required because Evidence is not of type Bytes, and 283 // golang slices can't be typed cast. This shouldn't be a performance problem since 284 // the Evidence size is capped. 285 evidenceBzs := make([][]byte, len(evl)) 286 for i := 0; i < len(evl); i++ { 287 evidenceBzs[i] = evl[i].Bytes() 288 } 289 return merkle.SimpleHashFromByteSlices(evidenceBzs) 290 } 291 292 func (evl EvidenceList) String() string { 293 s := "" 294 for _, e := range evl { 295 s += fmt.Sprintf("%s\t\t", e) 296 } 297 return s 298 } 299 300 // Has returns true if the evidence is in the EvidenceList. 301 func (evl EvidenceList) Has(evidence Evidence) bool { 302 for _, ev := range evl { 303 if ev.Equal(evidence) { 304 return true 305 } 306 } 307 return false 308 }