Browse Source

types: evidence cleanup

pull/592/head
Ethan Buchman 7 years ago
parent
commit
3271634e7a
5 changed files with 24 additions and 88 deletions
  1. +1
    -1
      state/execution.go
  2. +1
    -1
      state/state.go
  3. +6
    -7
      types/block.go
  4. +13
    -78
      types/evidence.go
  5. +3
    -1
      types/services.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.Evidences {
for _, ev := range block.Evidence.Evidence {
if _, err := s.VerifyEvidence(ev); err != nil {
return types.NewEvidenceInvalidErr(ev, err)
}


+ 1
- 1
state/state.go View File

@ -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 {


+ 6
- 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.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)


+ 13
- 78
types/evidence.go View File

@ -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
}
//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
// EvidenceList is a list of Evidence. Evidences is not a word.
type EvidenceList []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
}


+ 3
- 1
types/services.go View File

@ -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)
}


Loading…
Cancel
Save