mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 06:42:16 +00:00
Sec/bucky/35 commit duplicate evidence (#36)
Don't add committed evidence to evpool
This commit is contained in:
parent
cce4d21ccb
commit
90ba63948a
@ -28,7 +28,8 @@ type EvidencePool struct {
|
|||||||
state sm.State
|
state sm.State
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEvidencePool(stateDB dbm.DB, evidenceStore *EvidenceStore) *EvidencePool {
|
func NewEvidencePool(stateDB, evidenceDB dbm.DB) *EvidencePool {
|
||||||
|
evidenceStore := NewEvidenceStore(evidenceDB)
|
||||||
evpool := &EvidencePool{
|
evpool := &EvidencePool{
|
||||||
stateDB: stateDB,
|
stateDB: stateDB,
|
||||||
state: sm.LoadState(stateDB),
|
state: sm.LoadState(stateDB),
|
||||||
|
@ -56,8 +56,8 @@ func TestEvidencePool(t *testing.T) {
|
|||||||
valAddr := []byte("val1")
|
valAddr := []byte("val1")
|
||||||
height := int64(5)
|
height := int64(5)
|
||||||
stateDB := initializeValidatorState(valAddr, height)
|
stateDB := initializeValidatorState(valAddr, height)
|
||||||
store := NewEvidenceStore(dbm.NewMemDB())
|
evidenceDB := dbm.NewMemDB()
|
||||||
pool := NewEvidencePool(stateDB, store)
|
pool := NewEvidencePool(stateDB, evidenceDB)
|
||||||
|
|
||||||
goodEvidence := types.NewMockGoodEvidence(height, 0, valAddr)
|
goodEvidence := types.NewMockGoodEvidence(height, 0, valAddr)
|
||||||
badEvidence := types.MockBadEvidence{goodEvidence}
|
badEvidence := types.MockBadEvidence{goodEvidence}
|
||||||
|
@ -37,8 +37,8 @@ func makeAndConnectEvidenceReactors(config *cfg.Config, stateDBs []dbm.DB) []*Ev
|
|||||||
logger := evidenceLogger()
|
logger := evidenceLogger()
|
||||||
for i := 0; i < N; i++ {
|
for i := 0; i < N; i++ {
|
||||||
|
|
||||||
store := NewEvidenceStore(dbm.NewMemDB())
|
evidenceDB := dbm.NewMemDB()
|
||||||
pool := NewEvidencePool(stateDBs[i], store)
|
pool := NewEvidencePool(stateDBs[i], evidenceDB)
|
||||||
reactors[i] = NewEvidenceReactor(pool)
|
reactors[i] = NewEvidenceReactor(pool)
|
||||||
reactors[i].SetLogger(logger.With("validator", i))
|
reactors[i].SetLogger(logger.With("validator", i))
|
||||||
}
|
}
|
||||||
|
@ -117,32 +117,33 @@ func (store *EvidenceStore) listEvidence(prefixKey string, maxNum int64) (eviden
|
|||||||
return evidence
|
return evidence
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEvidence fetches the evidence with the given height and hash.
|
// GetEvidenceInfo fetches the EvidenceInfo with the given height and hash.
|
||||||
func (store *EvidenceStore) GetEvidence(height int64, hash []byte) *EvidenceInfo {
|
// If not found, ei.Evidence is nil.
|
||||||
|
func (store *EvidenceStore) GetEvidenceInfo(height int64, hash []byte) EvidenceInfo {
|
||||||
key := keyLookupFromHeightAndHash(height, hash)
|
key := keyLookupFromHeightAndHash(height, hash)
|
||||||
val := store.db.Get(key)
|
val := store.db.Get(key)
|
||||||
|
|
||||||
if len(val) == 0 {
|
if len(val) == 0 {
|
||||||
return nil
|
return EvidenceInfo{}
|
||||||
}
|
}
|
||||||
var ei EvidenceInfo
|
var ei EvidenceInfo
|
||||||
err := cdc.UnmarshalBinaryBare(val, &ei)
|
err := cdc.UnmarshalBinaryBare(val, &ei)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return &ei
|
return ei
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddNewEvidence adds the given evidence to the database.
|
// AddNewEvidence adds the given evidence to the database.
|
||||||
// It returns false if the evidence is already stored.
|
// It returns false if the evidence is already stored.
|
||||||
func (store *EvidenceStore) AddNewEvidence(evidence types.Evidence, priority int64) bool {
|
func (store *EvidenceStore) AddNewEvidence(evidence types.Evidence, priority int64) bool {
|
||||||
// check if we already have seen it
|
// check if we already have seen it
|
||||||
ei_ := store.GetEvidence(evidence.Height(), evidence.Hash())
|
ei := store.getEvidenceInfo(evidence)
|
||||||
if ei_ != nil && ei_.Evidence != nil {
|
if ei.Evidence != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
ei := EvidenceInfo{
|
ei = EvidenceInfo{
|
||||||
Committed: false,
|
Committed: false,
|
||||||
Priority: priority,
|
Priority: priority,
|
||||||
Evidence: evidence,
|
Evidence: evidence,
|
||||||
@ -165,6 +166,11 @@ func (store *EvidenceStore) AddNewEvidence(evidence types.Evidence, priority int
|
|||||||
// MarkEvidenceAsBroadcasted removes evidence from Outqueue.
|
// MarkEvidenceAsBroadcasted removes evidence from Outqueue.
|
||||||
func (store *EvidenceStore) MarkEvidenceAsBroadcasted(evidence types.Evidence) {
|
func (store *EvidenceStore) MarkEvidenceAsBroadcasted(evidence types.Evidence) {
|
||||||
ei := store.getEvidenceInfo(evidence)
|
ei := store.getEvidenceInfo(evidence)
|
||||||
|
if ei.Evidence == nil {
|
||||||
|
// nothin to do
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// remove from the outqueue
|
||||||
key := keyOutqueue(evidence, ei.Priority)
|
key := keyOutqueue(evidence, ei.Priority)
|
||||||
store.db.Delete(key)
|
store.db.Delete(key)
|
||||||
}
|
}
|
||||||
@ -177,8 +183,12 @@ func (store *EvidenceStore) MarkEvidenceAsCommitted(evidence types.Evidence) {
|
|||||||
pendingKey := keyPending(evidence)
|
pendingKey := keyPending(evidence)
|
||||||
store.db.Delete(pendingKey)
|
store.db.Delete(pendingKey)
|
||||||
|
|
||||||
ei := store.getEvidenceInfo(evidence)
|
// committed EvidenceInfo doens't need priority
|
||||||
ei.Committed = true
|
ei := EvidenceInfo{
|
||||||
|
Committed: true,
|
||||||
|
Evidence: evidence,
|
||||||
|
Priority: 0,
|
||||||
|
}
|
||||||
|
|
||||||
lookupKey := keyLookup(evidence)
|
lookupKey := keyLookup(evidence)
|
||||||
store.db.SetSync(lookupKey, cdc.MustMarshalBinaryBare(ei))
|
store.db.SetSync(lookupKey, cdc.MustMarshalBinaryBare(ei))
|
||||||
@ -187,13 +197,7 @@ func (store *EvidenceStore) MarkEvidenceAsCommitted(evidence types.Evidence) {
|
|||||||
//---------------------------------------------------
|
//---------------------------------------------------
|
||||||
// utils
|
// utils
|
||||||
|
|
||||||
|
// getEvidenceInfo is convenience for calling GetEvidenceInfo if we have the full evidence.
|
||||||
func (store *EvidenceStore) getEvidenceInfo(evidence types.Evidence) EvidenceInfo {
|
func (store *EvidenceStore) getEvidenceInfo(evidence types.Evidence) EvidenceInfo {
|
||||||
key := keyLookup(evidence)
|
return store.GetEvidenceInfo(evidence.Height(), evidence.Hash())
|
||||||
var ei EvidenceInfo
|
|
||||||
b := store.db.Get(key)
|
|
||||||
err := cdc.UnmarshalBinaryBare(b, &ei)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return ei
|
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,21 @@ func TestStoreAddDuplicate(t *testing.T) {
|
|||||||
assert.False(added)
|
assert.False(added)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStoreCommitDuplicate(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
db := dbm.NewMemDB()
|
||||||
|
store := NewEvidenceStore(db)
|
||||||
|
|
||||||
|
priority := int64(10)
|
||||||
|
ev := types.NewMockGoodEvidence(2, 1, []byte("val1"))
|
||||||
|
|
||||||
|
store.MarkEvidenceAsCommitted(ev)
|
||||||
|
|
||||||
|
added := store.AddNewEvidence(ev, priority)
|
||||||
|
assert.False(added)
|
||||||
|
}
|
||||||
|
|
||||||
func TestStoreMark(t *testing.T) {
|
func TestStoreMark(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
@ -46,7 +61,7 @@ func TestStoreMark(t *testing.T) {
|
|||||||
assert.True(added)
|
assert.True(added)
|
||||||
|
|
||||||
// get the evidence. verify. should be uncommitted
|
// get the evidence. verify. should be uncommitted
|
||||||
ei := store.GetEvidence(ev.Height(), ev.Hash())
|
ei := store.GetEvidenceInfo(ev.Height(), ev.Hash())
|
||||||
assert.Equal(ev, ei.Evidence)
|
assert.Equal(ev, ei.Evidence)
|
||||||
assert.Equal(priority, ei.Priority)
|
assert.Equal(priority, ei.Priority)
|
||||||
assert.False(ei.Committed)
|
assert.False(ei.Committed)
|
||||||
@ -72,9 +87,10 @@ func TestStoreMark(t *testing.T) {
|
|||||||
assert.Equal(0, len(pendingEv))
|
assert.Equal(0, len(pendingEv))
|
||||||
|
|
||||||
// evidence should show committed
|
// evidence should show committed
|
||||||
ei = store.GetEvidence(ev.Height(), ev.Hash())
|
newPriority := int64(0)
|
||||||
|
ei = store.GetEvidenceInfo(ev.Height(), ev.Hash())
|
||||||
assert.Equal(ev, ei.Evidence)
|
assert.Equal(ev, ei.Evidence)
|
||||||
assert.Equal(priority, ei.Priority)
|
assert.Equal(newPriority, ei.Priority)
|
||||||
assert.True(ei.Committed)
|
assert.True(ei.Committed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,8 +345,7 @@ func NewNode(config *cfg.Config,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
evidenceLogger := logger.With("module", "evidence")
|
evidenceLogger := logger.With("module", "evidence")
|
||||||
evidenceStore := evidence.NewEvidenceStore(evidenceDB)
|
evidencePool := evidence.NewEvidencePool(stateDB, evidenceDB)
|
||||||
evidencePool := evidence.NewEvidencePool(stateDB, evidenceStore)
|
|
||||||
evidencePool.SetLogger(evidenceLogger)
|
evidencePool.SetLogger(evidenceLogger)
|
||||||
evidenceReactor := evidence.NewEvidenceReactor(evidencePool)
|
evidenceReactor := evidence.NewEvidenceReactor(evidencePool)
|
||||||
evidenceReactor.SetLogger(evidenceLogger)
|
evidenceReactor.SetLogger(evidenceLogger)
|
||||||
|
@ -227,11 +227,10 @@ func TestCreateProposalBlock(t *testing.T) {
|
|||||||
mempool.SetLogger(logger)
|
mempool.SetLogger(logger)
|
||||||
|
|
||||||
// Make EvidencePool
|
// Make EvidencePool
|
||||||
types.RegisterMockEvidencesGlobal()
|
types.RegisterMockEvidencesGlobal() // XXX!
|
||||||
evidence.RegisterMockEvidences()
|
evidence.RegisterMockEvidences()
|
||||||
evidenceDB := dbm.NewMemDB()
|
evidenceDB := dbm.NewMemDB()
|
||||||
evidenceStore := evidence.NewEvidenceStore(evidenceDB)
|
evidencePool := evidence.NewEvidencePool(stateDB, evidenceDB)
|
||||||
evidencePool := evidence.NewEvidencePool(stateDB, evidenceStore)
|
|
||||||
evidencePool.SetLogger(logger)
|
evidencePool.SetLogger(logger)
|
||||||
|
|
||||||
// fill the evidence pool with more evidence
|
// fill the evidence pool with more evidence
|
||||||
@ -270,7 +269,6 @@ func TestCreateProposalBlock(t *testing.T) {
|
|||||||
|
|
||||||
err = blockExec.ValidateBlock(state, block)
|
err = blockExec.ValidateBlock(state, block)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func state(nVals int, height int64) (sm.State, dbm.DB) {
|
func state(nVals int, height int64) (sm.State, dbm.DB) {
|
||||||
|
@ -94,7 +94,6 @@ func (blockExec *BlockExecutor) CreateProposalBlock(
|
|||||||
txs := blockExec.mempool.ReapMaxBytesMaxGas(maxDataBytes, maxGas)
|
txs := blockExec.mempool.ReapMaxBytesMaxGas(maxDataBytes, maxGas)
|
||||||
|
|
||||||
return state.MakeBlock(height, txs, commit, evidence, proposerAddr)
|
return state.MakeBlock(height, txs, commit, evidence, proposerAddr)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateBlock validates the given block against the given state.
|
// ValidateBlock validates the given block against the given state.
|
||||||
|
@ -80,6 +80,7 @@ type BlockStore interface {
|
|||||||
// evidence pool
|
// evidence pool
|
||||||
|
|
||||||
// EvidencePool defines the EvidencePool interface used by the ConsensusState.
|
// EvidencePool defines the EvidencePool interface used by the ConsensusState.
|
||||||
|
// Get/Set/Commit
|
||||||
type EvidencePool interface {
|
type EvidencePool interface {
|
||||||
PendingEvidence(int64) []types.Evidence
|
PendingEvidence(int64) []types.Evidence
|
||||||
AddEvidence(types.Evidence) error
|
AddEvidence(types.Evidence) error
|
||||||
|
@ -185,6 +185,8 @@ func VerifyEvidence(stateDB dbm.DB, state State, evidence types.Evidence) error
|
|||||||
// The address must have been an active validator at the height.
|
// The address must have been an active validator at the height.
|
||||||
// NOTE: we will ignore evidence from H if the key was not a validator
|
// NOTE: we will ignore evidence from H if the key was not a validator
|
||||||
// at H, even if it is a validator at some nearby H'
|
// at H, even if it is a validator at some nearby H'
|
||||||
|
// XXX: this makes lite-client bisection as is unsafe
|
||||||
|
// See https://github.com/tendermint/tendermint/issues/3244
|
||||||
ev := evidence
|
ev := evidence
|
||||||
height, addr := ev.Height(), ev.Address()
|
height, addr := ev.Height(), ev.Address()
|
||||||
_, val := valset.GetByAddress(addr)
|
_, val := valset.GetByAddress(addr)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user