evidence: retrieve header at height of evidence for validation (#4870)

validation of lunatic evidence requires that the node retrieve the header at the height of the infringement from the block store for comparison
This commit is contained in:
Callum Waters
2020-06-03 06:44:06 +02:00
committed by GitHub
parent e538ea03d1
commit 26bea83694
6 changed files with 43 additions and 5 deletions

View File

@@ -236,6 +236,7 @@ func (m *mockEvidencePool) IsPending(evidence types.Evidence) bool {
return false
}
func (m *mockEvidencePool) AddPOLC(types.ProofOfLockChange) error { return nil }
func (m *mockEvidencePool) Header(int64) *types.Header { return nil }
//------------------------------------

View File

@@ -56,6 +56,7 @@ func (emptyEvidencePool) Update(*types.Block, sm.State) {}
func (emptyEvidencePool) IsCommitted(types.Evidence) bool { return false }
func (emptyEvidencePool) IsPending(types.Evidence) bool { return false }
func (emptyEvidencePool) AddPOLC(types.ProofOfLockChange) error { return nil }
func (emptyEvidencePool) Header(int64) *types.Header { return nil }
//-----------------------------------------------------------------------------
// mockProxyApp uses ABCIResponses to give the right results.

View File

@@ -181,11 +181,10 @@ func (evpool *Pool) AddEvidence(evidence types.Evidence) error {
// For lunatic validator evidence, a header needs to be fetched.
var header *types.Header
if _, ok := ev.(*types.LunaticValidatorEvidence); ok {
blockMeta := evpool.blockStore.LoadBlockMeta(ev.Height())
if blockMeta == nil {
header = evpool.Header(ev.Height())
if header == nil {
return fmt.Errorf("don't have block meta at height #%d", ev.Height())
}
header = &blockMeta.Header
}
// 1) Verify against state.
@@ -266,7 +265,7 @@ func (evpool *Pool) IsCommitted(evidence types.Evidence) bool {
return ok
}
// Checks whether the evidence is already pending. DB errors are passed to the logger.
// IsPending checks whether the evidence is already pending. DB errors are passed to the logger.
func (evpool *Pool) IsPending(evidence types.Evidence) bool {
key := keyPending(evidence)
ok, err := evpool.evidenceStore.Has(key)
@@ -306,6 +305,16 @@ func (evpool *Pool) SetLogger(l log.Logger) {
evpool.logger = l
}
// Header gets the header from the block store at a specified height.
// Is used for validation of LunaticValidatorEvidence
func (evpool *Pool) Header(height int64) *types.Header {
blockMeta := evpool.blockStore.LoadBlockMeta(height)
if blockMeta == nil {
return nil
}
return &blockMeta.Header
}
// ValidatorLastHeight returns the last height of the validator w/ the
// given address. 0 - if address never was a validator or was such a
// long time ago (> ConsensusParams.Evidence.MaxAgeDuration && >

View File

@@ -28,6 +28,22 @@ func (_m *EvidencePool) AddEvidence(_a0 types.Evidence) error {
return r0
}
// Header provides a mock function with given fields: _a0
func (_m *EvidencePool) Header(_a0 int64) *types.Header {
ret := _m.Called(_a0)
var r0 *types.Header
if rf, ok := ret.Get(0).(func(int64) *types.Header); ok {
r0 = rf(_a0)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.Header)
}
}
return r0
}
// IsCommitted provides a mock function with given fields: _a0
func (_m *EvidencePool) IsCommitted(_a0 types.Evidence) bool {
ret := _m.Called(_a0)

View File

@@ -45,6 +45,7 @@ type EvidencePool interface {
Update(*types.Block, State)
IsCommitted(types.Evidence) bool
IsPending(types.Evidence) bool
Header(int64) *types.Header
}
// MockEvidencePool is an empty implementation of EvidencePool, useful for testing.
@@ -55,3 +56,4 @@ func (me MockEvidencePool) AddEvidence(types.Evidence) error { return nil
func (me MockEvidencePool) Update(*types.Block, State) {}
func (me MockEvidencePool) IsCommitted(types.Evidence) bool { return false }
func (me MockEvidencePool) IsPending(types.Evidence) bool { return false }
func (me MockEvidencePool) Header(int64) *types.Header { return nil }

View File

@@ -142,7 +142,16 @@ func validateBlock(evidencePool EvidencePool, stateDB dbm.DB, state State, block
continue
}
}
if err := VerifyEvidence(stateDB, state, ev, &block.Header); err != nil {
var header *types.Header
if _, ok := ev.(*types.LunaticValidatorEvidence); ok {
header = evidencePool.Header(ev.Height())
if header == nil {
return fmt.Errorf("don't have block meta at height #%d", ev.Height())
}
}
if err := VerifyEvidence(stateDB, state, ev, header); err != nil {
return types.NewErrEvidenceInvalid(ev, err)
}
}