Skip to content

Commit e8b9338

Browse files
MariusVanDerWijdenunclezoro
authored andcommitted
core/state/snapshot: fix race condition (ethereum#24685)
Fixes three race conditions found through fuzzing by David Theodore
1 parent 5a06ca3 commit e8b9338

File tree

2 files changed

+26
-14
lines changed

2 files changed

+26
-14
lines changed

core/state/snapshot/difflayer.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,9 @@ func (dl *diffLayer) CorrectAccounts(accounts map[common.Hash][]byte) {
297297

298298
// Parent returns the subsequent layer of a diff layer.
299299
func (dl *diffLayer) Parent() snapshot {
300+
dl.lock.RLock()
301+
defer dl.lock.RUnlock()
302+
300303
return dl.parent
301304
}
302305

eth/protocols/snap/sync.go

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@ type Syncer struct {
423423
storageSynced uint64 // Number of storage slots downloaded
424424
storageBytes common.StorageSize // Number of storage trie bytes persisted to disk
425425

426+
extProgress *SyncProgress // progress that can be exposed to external caller.
427+
426428
// Request tracking during healing phase
427429
trienodeHealIdlers map[string]struct{} // Peers that aren't serving trie node requests
428430
bytecodeHealIdlers map[string]struct{} // Peers that aren't serving bytecode requests
@@ -478,6 +480,8 @@ func NewSyncer(db ethdb.KeyValueStore) *Syncer {
478480
trienodeHealReqs: make(map[uint64]*trienodeHealRequest),
479481
bytecodeHealReqs: make(map[uint64]*bytecodeHealRequest),
480482
stateWriter: db.NewBatch(),
483+
484+
extProgress: new(SyncProgress),
481485
}
482486
}
483487

@@ -634,6 +638,21 @@ func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error {
634638
s.assignTrienodeHealTasks(trienodeHealResps, trienodeHealReqFails, cancel)
635639
s.assignBytecodeHealTasks(bytecodeHealResps, bytecodeHealReqFails, cancel)
636640
}
641+
// Update sync progress
642+
s.lock.Lock()
643+
s.extProgress = &SyncProgress{
644+
AccountSynced: s.accountSynced,
645+
AccountBytes: s.accountBytes,
646+
BytecodeSynced: s.bytecodeSynced,
647+
BytecodeBytes: s.bytecodeBytes,
648+
StorageSynced: s.storageSynced,
649+
StorageBytes: s.storageBytes,
650+
TrienodeHealSynced: s.trienodeHealSynced,
651+
TrienodeHealBytes: s.trienodeHealBytes,
652+
BytecodeHealSynced: s.bytecodeHealSynced,
653+
BytecodeHealBytes: s.bytecodeHealBytes,
654+
}
655+
s.lock.Unlock()
637656
// Wait for something to happen
638657
select {
639658
case <-s.update:
@@ -706,6 +725,9 @@ func (s *Syncer) loadSyncStatus() {
706725
}
707726
}
708727
}
728+
s.lock.Lock()
729+
defer s.lock.Unlock()
730+
709731
s.snapped = len(s.tasks) == 0
710732

711733
s.accountSynced = progress.AccountSynced
@@ -803,25 +825,12 @@ func (s *Syncer) saveSyncStatus() {
803825
func (s *Syncer) Progress() (*SyncProgress, *SyncPending) {
804826
s.lock.Lock()
805827
defer s.lock.Unlock()
806-
807-
progress := &SyncProgress{
808-
AccountSynced: s.accountSynced,
809-
AccountBytes: s.accountBytes,
810-
BytecodeSynced: s.bytecodeSynced,
811-
BytecodeBytes: s.bytecodeBytes,
812-
StorageSynced: s.storageSynced,
813-
StorageBytes: s.storageBytes,
814-
TrienodeHealSynced: s.trienodeHealSynced,
815-
TrienodeHealBytes: s.trienodeHealBytes,
816-
BytecodeHealSynced: s.bytecodeHealSynced,
817-
BytecodeHealBytes: s.bytecodeHealBytes,
818-
}
819828
pending := new(SyncPending)
820829
if s.healer != nil {
821830
pending.TrienodeHeal = uint64(len(s.healer.trieTasks))
822831
pending.BytecodeHeal = uint64(len(s.healer.codeTasks))
823832
}
824-
return progress, pending
833+
return s.extProgress, pending
825834
}
826835

827836
// cleanAccountTasks removes account range retrieval tasks that have already been

0 commit comments

Comments
 (0)