From 3271634e7a1833c161d17c1c9c996f7743de27a5 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 19 Nov 2017 22:18:43 +0000 Subject: [PATCH] types: evidence cleanup --- state/execution.go | 2 +- state/state.go | 2 +- types/block.go | 13 +++---- types/evidence.go | 91 +++++++--------------------------------------- types/services.go | 4 +- 5 files changed, 24 insertions(+), 88 deletions(-) diff --git a/state/execution.go b/state/execution.go index 860c0caa..539d1cd3 100644 --- a/state/execution.go +++ b/state/execution.go @@ -309,7 +309,7 @@ func (s *State) validateBlock(b *types.Block) error { } } - for _, ev := range block.Evidence.Evidences { + for _, ev := range block.Evidence.Evidence { if _, err := s.VerifyEvidence(ev); err != nil { return types.NewEvidenceInvalidErr(ev, err) } diff --git a/state/state.go b/state/state.go index 78888152..871e2f70 100644 --- a/state/state.go +++ b/state/state.go @@ -386,7 +386,7 @@ func (s *State) GetValidators() (last *types.ValidatorSet, current *types.Valida // VerifyEvidence verifies the evidence fully by checking it is internally // consistent and corresponds to an existing or previous validator. // It returns the priority of this evidence, or an error. -// NOTE: return error may be ErrLoadValidators, in which case the validator set +// NOTE: return error may be ErrNoValSetForHeight, in which case the validator set // for the evidence height could not be loaded. func (s *State) VerifyEvidence(evidence types.Evidence) (priority int, err error) { if err := evidence.Verify(s.ChainID); err != nil { diff --git a/types/block.go b/types/block.go index 96bfbf9d..6aa97c2d 100644 --- a/types/block.go +++ b/types/block.go @@ -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.Evidences = append(b.Evidence.Evidences, evidence...) + b.Evidence.Evidence = append(b.Evidence.Evidence, evidence...) } // ValidateBasic performs basic validation that doesn't involve state data. @@ -437,8 +437,7 @@ func (data *Data) StringIndented(indent string) string { // EvidenceData contains any evidence of malicious wrong-doing by validators type EvidenceData struct { - // TODO: FIXME - Evidences evidences `json:"evidence"` + Evidence EvidenceList `json:"evidence"` // Volatile hash data.Bytes @@ -447,7 +446,7 @@ type EvidenceData struct { // Hash returns the hash of the data. func (data *EvidenceData) Hash() data.Bytes { if data.hash == nil { - data.hash = data.Evidences.Hash() + data.hash = data.Evidence.Hash() } return data.hash } @@ -457,10 +456,10 @@ func (data *EvidenceData) StringIndented(indent string) string { if data == nil { return "nil-Evidence" } - evStrings := make([]string, cmn.MinInt(len(data.Evidences), 21)) - for i, ev := range data.Evidences { + evStrings := make([]string, cmn.MinInt(len(data.Evidence), 21)) + for i, ev := range data.Evidence { if i == 20 { - evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidences)) + evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidence)) break } evStrings[i] = fmt.Sprintf("Evidence:%v", ev) diff --git a/types/evidence.go b/types/evidence.go index 42047faf..cb433ced 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -3,7 +3,6 @@ package types import ( "bytes" "fmt" - "sync" "github.com/tendermint/go-crypto" "github.com/tendermint/tmlibs/merkle" @@ -26,10 +25,6 @@ func (err *ErrEvidenceInvalid) Error() string { //------------------------------------------- -type HistoricalValidators interface { - LoadValidators(height int) (*ValidatorSet, error) -} - // Evidence represents any provable malicious activity by a validator type Evidence interface { Height() int // height of the equivocation @@ -44,96 +39,36 @@ type Evidence interface { //------------------------------------------- -//EvidenceSet is a thread-safe set of evidence. -type EvidenceSet struct { - sync.RWMutex - evidences evidences -} +// EvidenceList is a list of Evidence. Evidences is not a word. +type EvidenceList []Evidence -//Evidence returns a copy of all the evidence. -func (evset EvidenceSet) Evidence() []Evidence { - evset.RLock() - defer evset.RUnlock() - evCopy := make([]Evidence, len(evset.evidences)) - for i, ev := range evset.evidences { - evCopy[i] = ev - } - return evCopy -} - -// Size returns the number of pieces of evidence in the set. -func (evset EvidenceSet) Size() int { - evset.RLock() - defer evset.RUnlock() - return len(evset.evidences) -} - -// Hash returns a merkle hash of the evidence. -func (evset EvidenceSet) Hash() []byte { - evset.RLock() - defer evset.RUnlock() - return evset.evidences.Hash() -} - -// Has returns true if the given evidence is in the set. -func (evset EvidenceSet) Has(evidence Evidence) bool { - evset.RLock() - defer evset.RUnlock() - return evset.evidences.Has(evidence) -} - -// String returns a string representation of the evidence. -func (evset EvidenceSet) String() string { - evset.RLock() - defer evset.RUnlock() - return evset.evidences.String() -} - -// Add adds the given evidence to the set. -// TODO: and persists it to disk. -func (evset EvidenceSet) Add(evidence Evidence) { - evset.Lock() - defer evset.Unlock() - evset.evidences = append(evset.evidences, evidence) -} - -// Reset empties the evidence set. -func (evset EvidenceSet) Reset() { - evset.Lock() - defer evset.Unlock() - evset.evidences = make(evidences, 0) - -} - -//------------------------------------------- - -type evidences []Evidence - -func (evs evidences) Hash() []byte { +// Hash returns the simple merkle root hash of the EvidenceList. +func (evl EvidenceList) Hash() []byte { // Recursive impl. // Copied from tmlibs/merkle to avoid allocations - switch len(evs) { + switch len(evl) { case 0: return nil case 1: - return evs[0].Hash() + return evl[0].Hash() default: - left := evidences(evs[:(len(evs)+1)/2]).Hash() - right := evidences(evs[(len(evs)+1)/2:]).Hash() + left := EvidenceList(evl[:(len(evl)+1)/2]).Hash() + right := EvidenceList(evl[(len(evl)+1)/2:]).Hash() return merkle.SimpleHashFromTwoHashes(left, right) } } -func (evs evidences) String() string { +func (evl EvidenceList) String() string { s := "" - for _, e := range evs { + for _, e := range evl { s += fmt.Sprintf("%s\t\t", e) } return s } -func (evs evidences) Has(evidence Evidence) bool { - for _, ev := range evs { +// Has returns true if the evidence is in the EvidenceList. +func (evl EvidenceList) Has(evidence Evidence) bool { + for _, ev := range evl { if ev.Equal(evidence) { return true } diff --git a/types/services.go b/types/services.go index 25f77405..10014e66 100644 --- a/types/services.go +++ b/types/services.go @@ -4,7 +4,7 @@ import ( abci "github.com/tendermint/abci/types" ) -// NOTE: all types in this file are considered UNSTABLE +// NOTE/XXX: all type definitions in this file are considered UNSTABLE //------------------------------------------------------ // blockchain services types @@ -73,6 +73,8 @@ type BlockStore interface { //------------------------------------------------------ // state +// State defines the stateful interface used to verify evidence. +// UNSTABLE type State interface { VerifyEvidence(Evidence) (priority int, err error) }