1
1
package evidence
2
2
3
3
import (
4
+ "errors"
4
5
"fmt"
5
6
"sync"
6
7
"time"
@@ -31,7 +32,7 @@ type Pool struct {
31
32
evidenceList * clist.CList // concurrent linked-list of evidence
32
33
33
34
// needed to load validators to verify evidence
34
- stateDB dbm. DB
35
+ stateDB StateStore
35
36
// needed to load headers to verify evidence
36
37
blockStore BlockStore
37
38
@@ -45,11 +46,11 @@ type Pool struct {
45
46
nextEvidenceTrialEndedHeight int64
46
47
}
47
48
48
- // Creates a new pool. If using an existing evidence store, it will add all pending evidence
49
- // to the concurrent list.
50
- func NewPool (stateDB , evidenceDB dbm.DB , blockStore BlockStore ) (* Pool , error ) {
49
+ // NewPool creates an evidence pool. If using an existing evidence store,
50
+ // it will add all pending evidence to the concurrent list.
51
+ func NewPool (evidenceDB dbm.DB , stateDB StateStore , blockStore BlockStore ) (* Pool , error ) {
51
52
var (
52
- state = sm .LoadState (stateDB )
53
+ state = stateDB .LoadState ()
53
54
)
54
55
55
56
pool := & Pool {
@@ -145,14 +146,11 @@ func (evpool *Pool) AddPOLC(polc *types.ProofOfLockChange) error {
145
146
// evidence is composite (ConflictingHeadersEvidence), it will be broken up
146
147
// into smaller pieces.
147
148
func (evpool * Pool ) AddEvidence (evidence types.Evidence ) error {
148
- var (
149
- state = evpool .State ()
150
- evList = []types.Evidence {evidence }
151
- )
149
+ var evList = []types.Evidence {evidence }
152
150
153
151
evpool .logger .Debug ("Attempting to add evidence" , "ev" , evidence )
154
152
155
- valSet , err := sm . LoadValidators ( evpool .stateDB , evidence .Height ())
153
+ valSet , err := evpool .stateDB . LoadValidators ( evidence .Height ())
156
154
if err != nil {
157
155
return fmt .Errorf ("can't load validators at height #%d: %w" , evidence .Height (), err )
158
156
}
@@ -177,36 +175,14 @@ func (evpool *Pool) AddEvidence(evidence types.Evidence) error {
177
175
178
176
if evpool .Has (ev ) {
179
177
// if it is an amnesia evidence we have but POLC is not absent then
180
- // we should still process it
178
+ // we should still process it else we loop to the next piece of evidence
181
179
if ae , ok := ev .(* types.AmnesiaEvidence ); ! ok || ae .Polc .IsAbsent () {
182
180
continue
183
181
}
184
182
}
185
183
186
- // A header needs to be fetched. For lunatic evidence this is so we can verify
187
- // that some of the fields are different to the ones we have. For all evidence it
188
- // it so we can verify that the time of the evidence is correct
189
-
190
- var header * types.Header
191
- // if the evidence is from the current height - this means the evidence is fresh from the consensus
192
- // and we won't have it in the block store. We thus check that the time isn't before the previous block
193
- if ev .Height () == evpool .State ().LastBlockHeight + 1 {
194
- if ev .Time ().Before (evpool .State ().LastBlockTime ) {
195
- return fmt .Errorf ("evidence is from an earlier time than the previous block: %v < %v" ,
196
- ev .Time (),
197
- evpool .State ().LastBlockTime )
198
- }
199
- header = & types.Header {Time : ev .Time ()}
200
- } else { // if the evidence is from a prior height
201
- header = evpool .Header (ev .Height ())
202
- if header == nil {
203
- return fmt .Errorf ("don't have header at height #%d" , ev .Height ())
204
- }
205
- }
206
-
207
184
// 1) Verify against state.
208
- if err := sm .VerifyEvidence (evpool .stateDB , state , ev , header ); err != nil {
209
- evpool .logger .Debug ("Inbound evidence is invalid" , "evidence" , ev , "err" , err )
185
+ if err := evpool .verify (ev ); err != nil {
210
186
return types .NewErrEvidenceInvalid (ev , err )
211
187
}
212
188
@@ -256,6 +232,37 @@ func (evpool *Pool) AddEvidence(evidence types.Evidence) error {
256
232
return nil
257
233
}
258
234
235
+ // Verify verifies the evidence against the node's (or evidence pool's) state. More specifically, to validate
236
+ // evidence against state is to validate it against the nodes own header and validator set for that height. This ensures
237
+ // as well as meeting the evidence's own validation rules, that the evidence hasn't expired, that the validator is still
238
+ // bonded and that the evidence can be committed to the chain.
239
+ func (evpool * Pool ) Verify (evidence types.Evidence ) error {
240
+ if evpool .IsCommitted (evidence ) {
241
+ return errors .New ("evidence was already committed" )
242
+ }
243
+ // We have already verified this piece of evidence - no need to do it again
244
+ if evpool .IsPending (evidence ) {
245
+ return nil
246
+ }
247
+
248
+ // if we don't already have amnesia evidence we need to add it to start our own trial period unless
249
+ // a) a valid polc has already been attached
250
+ // b) the accused node voted back on an earlier round
251
+ if ae , ok := evidence .(* types.AmnesiaEvidence ); ok && ae .Polc .IsAbsent () && ae .PotentialAmnesiaEvidence .VoteA .Round <
252
+ ae .PotentialAmnesiaEvidence .VoteB .Round {
253
+ if err := evpool .AddEvidence (ae .PotentialAmnesiaEvidence ); err != nil {
254
+ return fmt .Errorf ("unknown amnesia evidence, trying to add to evidence pool, err: %w" , err )
255
+ }
256
+ return errors .New ("amnesia evidence is new and hasn't undergone trial period yet" )
257
+ }
258
+
259
+ return evpool .verify (evidence )
260
+ }
261
+
262
+ func (evpool * Pool ) verify (evidence types.Evidence ) error {
263
+ return VerifyEvidence (evidence , evpool .State (), evpool .stateDB , evpool .blockStore )
264
+ }
265
+
259
266
// MarkEvidenceAsCommitted marks all the evidence as committed and removes it
260
267
// from the queue.
261
268
func (evpool * Pool ) MarkEvidenceAsCommitted (height int64 , evidence []types.Evidence ) {
@@ -543,7 +550,7 @@ func (evpool *Pool) pruneExpiredPOLC() {
543
550
evpool .logger .Error ("Unable to transition POLC from protobuf" , "err" , err )
544
551
continue
545
552
}
546
- if ! evpool .IsExpired (proof .Height ()- 1 , proof .Time ()) {
553
+ if ! evpool .IsExpired (proof .Height (), proof .Time ()) {
547
554
return
548
555
}
549
556
err = evpool .evidenceStore .Delete (iter .Key ())
0 commit comments