|
|
@ -1,6 +1,10 @@ |
|
|
|
package evidence |
|
|
|
|
|
|
|
import ( |
|
|
|
"fmt" |
|
|
|
"sync" |
|
|
|
|
|
|
|
dbm "github.com/tendermint/tmlibs/db" |
|
|
|
"github.com/tendermint/tmlibs/log" |
|
|
|
|
|
|
|
sm "github.com/tendermint/tendermint/state" |
|
|
@ -14,17 +18,21 @@ type EvidencePool struct { |
|
|
|
|
|
|
|
evidenceStore *EvidenceStore |
|
|
|
|
|
|
|
state sm.State |
|
|
|
params types.EvidenceParams |
|
|
|
// needed to load validators to verify evidence
|
|
|
|
stateDB dbm.DB |
|
|
|
|
|
|
|
// latest state
|
|
|
|
mtx sync.Mutex |
|
|
|
state sm.State |
|
|
|
|
|
|
|
// never close
|
|
|
|
evidenceChan chan types.Evidence |
|
|
|
} |
|
|
|
|
|
|
|
func NewEvidencePool(params types.EvidenceParams, evidenceStore *EvidenceStore, state sm.State) *EvidencePool { |
|
|
|
func NewEvidencePool(stateDB dbm.DB, evidenceStore *EvidenceStore) *EvidencePool { |
|
|
|
evpool := &EvidencePool{ |
|
|
|
state: state, |
|
|
|
params: params, |
|
|
|
stateDB: stateDB, |
|
|
|
state: sm.LoadState(stateDB), |
|
|
|
logger: log.NewNopLogger(), |
|
|
|
evidenceStore: evidenceStore, |
|
|
|
evidenceChan: make(chan types.Evidence), |
|
|
@ -52,31 +60,44 @@ func (evpool *EvidencePool) PendingEvidence() []types.Evidence { |
|
|
|
return evpool.evidenceStore.PendingEvidence() |
|
|
|
} |
|
|
|
|
|
|
|
// State returns the current state of the evpool.
|
|
|
|
func (evpool *EvidencePool) State() sm.State { |
|
|
|
evpool.mtx.Lock() |
|
|
|
defer evpool.mtx.Unlock() |
|
|
|
return evpool.state |
|
|
|
} |
|
|
|
|
|
|
|
// Update loads the latest
|
|
|
|
func (evpool *EvidencePool) Update(block *types.Block) { |
|
|
|
evpool.mtx.Lock() |
|
|
|
defer evpool.mtx.Unlock() |
|
|
|
|
|
|
|
state := sm.LoadState(evpool.stateDB) |
|
|
|
if state.LastBlockHeight != block.Height { |
|
|
|
panic(fmt.Sprintf("EvidencePool.Update: loaded state with height %d when block.Height=%d", state.LastBlockHeight, block.Height)) |
|
|
|
} |
|
|
|
evpool.state = state |
|
|
|
|
|
|
|
// NOTE: shouldn't need the mutex
|
|
|
|
evpool.MarkEvidenceAsCommitted(block.Evidence.Evidence) |
|
|
|
} |
|
|
|
|
|
|
|
// AddEvidence checks the evidence is valid and adds it to the pool.
|
|
|
|
// Blocks on the EvidenceChan.
|
|
|
|
func (evpool *EvidencePool) AddEvidence(evidence types.Evidence) (err error) { |
|
|
|
|
|
|
|
// TODO: check if we already have evidence for this
|
|
|
|
// validator at this height so we dont get spammed
|
|
|
|
|
|
|
|
if err := sm.VerifyEvidence(evpool.state, evidence); err != nil { |
|
|
|
if err := sm.VerifyEvidence(evpool.stateDB, evpool.State(), evidence); err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
var priority int64 |
|
|
|
/* // Needs a db ...
|
|
|
|
// TODO: if err is just that we cant find it cuz we pruned, ignore.
|
|
|
|
// TODO: if its actually bad evidence, punish peer
|
|
|
|
|
|
|
|
valset, err := LoadValidators(s.db, ev.Height()) |
|
|
|
if err != nil { |
|
|
|
// XXX/TODO: what do we do if we can't load the valset?
|
|
|
|
// eg. if we have pruned the state or height is too high?
|
|
|
|
return err |
|
|
|
} |
|
|
|
if err := VerifyEvidenceValidator(valSet, ev); err != nil { |
|
|
|
return types.NewEvidenceInvalidErr(ev, err) |
|
|
|
} |
|
|
|
*/ |
|
|
|
// fetch the validator and return its voting power as its priority
|
|
|
|
// TODO: something better ?
|
|
|
|
valset, _ := sm.LoadValidators(evpool.stateDB, evidence.Height()) |
|
|
|
_, val := valset.GetByAddress(evidence.Address()) |
|
|
|
priority := val.VotingPower |
|
|
|
|
|
|
|
added := evpool.evidenceStore.AddNewEvidence(evidence, priority) |
|
|
|
if !added { |
|
|
|