Browse Source

types: Evidences for merkle hashing; Evidence.String()

pull/592/head
Ethan Buchman 7 years ago
parent
commit
77e45756f2
3 changed files with 57 additions and 9 deletions
  1. +1
    -1
      state/execution.go
  2. +19
    -7
      types/block.go
  3. +37
    -1
      types/evidence.go

+ 1
- 1
state/execution.go View File

@ -309,7 +309,7 @@ func (s *State) validateBlock(b *types.Block) error {
}
}
for _, ev := range block.Evidence.Evidence {
for _, ev := range block.Evidence.Evidences {
if err := ev.Verify(s.ChainID); err != nil {
return types.NewEvidenceInvalidErr(ev, err)
}


+ 19
- 7
types/block.go View File

@ -43,7 +43,7 @@ func MakeBlock(height int64, txs []Tx, commit *Commit) *Block {
// AddEvidence appends the given evidence to the block
func (b *Block) AddEvidence(evidence []Evidence) {
b.Evidence.Evidence = append(b.Evidence.Evidence, evidence...)
b.Evidence.Evidences = append(b.Evidence.Evidences, evidence...)
}
// ValidateBasic performs basic validation that doesn't involve state data.
@ -438,26 +438,38 @@ func (data *Data) StringIndented(indent string) string {
// EvidenceData contains any evidence of malicious wrong-doing by validators
type EvidenceData struct {
Evidence []Evidence `json:"evidence"`
Evidences Evidences `json:"evidence"`
// Volatile
hash data.Bytes
}
// Hash returns the hash of the data
// Hash returns the hash of the data.
func (data *EvidenceData) Hash() data.Bytes {
if data.hash == nil {
// TODO
data.hash = data.Evidences.Hash()
}
return data.hash
}
// StringIndented returns a string representation of the transactions
// StringIndented returns a string representation of the evidence.
func (data *EvidenceData) StringIndented(indent string) string {
if data == nil {
return "nil-Data"
return "nil-Evidence"
}
// TODO
evStrings := make([]string, cmn.MinInt(len(data.Evidences), 21))
for i, ev := range data.Evidences {
if i == 20 {
evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidences))
break
}
evStrings[i] = fmt.Sprintf("Evidence:%v", ev)
}
return fmt.Sprintf(`Data{
%s %v
%s}#%v`,
indent, strings.Join(evStrings, "\n"+indent+" "),
indent, data.hash)
return ""
}


+ 37
- 1
types/evidence.go View File

@ -5,6 +5,7 @@ import (
"fmt"
"github.com/tendermint/go-crypto"
"github.com/tendermint/tmlibs/merkle"
)
// ErrEvidenceInvalid wraps a piece of evidence and the error denoting how or why it is invalid.
@ -22,10 +23,34 @@ func (err *ErrEvidenceInvalid) Error() string {
return fmt.Sprintf("Invalid evidence: %v. Evidence: %v", err.ErrorValue, err.Evidence)
}
//-------------------------------------------
// Evidence represents any provable malicious activity by a validator
type Evidence interface {
Verify(chainID string) error
Address() []byte
Hash() []byte
Verify(chainID string) error
String() string
}
//-------------------------------------------
type Evidences []Evidence
func (evs Evidences) Hash() []byte {
// Recursive impl.
// Copied from tmlibs/merkle to avoid allocations
switch len(evs) {
case 0:
return nil
case 1:
return evs[0].Hash()
default:
left := Evidences(evs[:(len(evs)+1)/2]).Hash()
right := Evidences(evs[(len(evs)+1)/2:]).Hash()
return merkle.SimpleHashFromTwoHashes(left, right)
}
}
//-------------------------------------------
@ -37,11 +62,22 @@ type DuplicateVoteEvidence struct {
VoteB *Vote
}
// String returns a string representation of the evidence.
func (dve *DuplicateVoteEvidence) String() string {
return fmt.Sprintf("VoteA: %v; VoteB: %v", dve.VoteA, dve.VoteB)
}
// Address returns the address of the validator.
func (dve *DuplicateVoteEvidence) Address() []byte {
return dve.PubKey.Address()
}
// Hash returns the hash of the evidence.
func (dve *DuplicateVoteEvidence) Hash() []byte {
return merkle.SimpleHashFromBinary(dve)
}
// Verify returns an error if the two votes aren't conflicting.
// To be conflicting, they must be from the same validator, for the same H/R/S, but for different blocks.
func (dve *DuplicateVoteEvidence) Verify(chainID string) error {


Loading…
Cancel
Save