swarm/network: fix chunk integrity checks (#3665)

* swarm/network: integrity on incoming known chunks
* swarm/network: fix integrity check for incoming chunks
* swarm/storage: imrpoved integrity checking on chunks
* dbstore panics on corrupt chunk entry an prompts user to run cleandb
* memstore adds logging for garbage collection
* dbstore refactor item delete. correct partial deletes in Get
* cmd/swarm: added cleandb subcommand
This commit is contained in:
Viktor Trón
2017-02-13 18:50:50 +06:30
committed by Felix Lange
parent 65ed6a9def
commit e23e86921b
6 changed files with 125 additions and 21 deletions

View File

@ -252,12 +252,7 @@ func (s *DbStore) collectGarbage(ratio float32) {
// actual gc
for i := 0; i < gcnt; i++ {
if s.gcArray[i].value <= cutval {
batch := new(leveldb.Batch)
batch.Delete(s.gcArray[i].idxKey)
batch.Delete(getDataKey(s.gcArray[i].idx))
s.entryCnt--
batch.Put(keyEntryCnt, U64ToBytes(s.entryCnt))
s.db.Write(batch)
s.delete(s.gcArray[i].idx, s.gcArray[i].idxKey)
}
}
@ -266,6 +261,52 @@ func (s *DbStore) collectGarbage(ratio float32) {
s.db.Put(keyGCPos, s.gcPos)
}
func (s *DbStore) Cleanup() {
//Iterates over the database and checks that there are no faulty chunks
it := s.db.NewIterator()
startPosition := []byte{kpIndex}
it.Seek(startPosition)
var key []byte
var errorsFound, total int
for it.Valid() {
key = it.Key()
if (key == nil) || (key[0] != kpIndex) {
break
}
total++
var index dpaDBIndex
decodeIndex(it.Value(), &index)
data, err := s.db.Get(getDataKey(index.Idx))
if err != nil {
glog.V(logger.Warn).Infof("Chunk %x found but could not be accessed: %v", key[:], err)
s.delete(index.Idx, getIndexKey(key[1:]))
errorsFound++
} else {
hasher := s.hashfunc()
hasher.Write(data)
hash := hasher.Sum(nil)
if !bytes.Equal(hash, key[1:]) {
glog.V(logger.Warn).Infof("Found invalid chunk. Hash mismatch. hash=%x, key=%x", hash, key[:])
s.delete(index.Idx, getIndexKey(key[1:]))
errorsFound++
}
}
it.Next()
}
it.Release()
glog.V(logger.Warn).Infof("Found %v errors out of %v entries", errorsFound, total)
}
func (s *DbStore) delete(idx uint64, idxKey []byte) {
batch := new(leveldb.Batch)
batch.Delete(idxKey)
batch.Delete(getDataKey(idx))
s.entryCnt--
batch.Put(keyEntryCnt, U64ToBytes(s.entryCnt))
s.db.Write(batch)
}
func (s *DbStore) Counter() uint64 {
s.lock.Lock()
defer s.lock.Unlock()
@ -283,6 +324,7 @@ func (s *DbStore) Put(chunk *Chunk) {
if chunk.dbStored != nil {
close(chunk.dbStored)
}
glog.V(logger.Detail).Infof("Storing to DB: chunk already exists, only update access")
return // already exists, only update access
}
@ -348,6 +390,8 @@ func (s *DbStore) Get(key Key) (chunk *Chunk, err error) {
var data []byte
data, err = s.db.Get(getDataKey(index.Idx))
if err != nil {
glog.V(logger.Detail).Infof("DBStore: Chunk %v found but could not be accessed: %v", key.Log(), err)
s.delete(index.Idx, getIndexKey(key))
return
}
@ -355,9 +399,8 @@ func (s *DbStore) Get(key Key) (chunk *Chunk, err error) {
hasher.Write(data)
hash := hasher.Sum(nil)
if !bytes.Equal(hash, key) {
s.db.Delete(getDataKey(index.Idx))
err = fmt.Errorf("invalid chunk. hash=%x, key=%v", hash, key[:])
return
s.delete(index.Idx, getIndexKey(key))
panic("Invalid Chunk in Database. Please repair with command: 'swarm cleandb'")
}
chunk = &Chunk{