瀏覽代碼

core/state: fix resurrection state clearing and access

Péter Szilágyi 5 年之前
父節點
當前提交
328de180a7
共有 2 個文件被更改,包括 13 次插入1 次删除
  1. 9 0
      core/state/state_object.go
  2. 4 1
      core/state/statedb.go

+ 9 - 0
core/state/state_object.go

@@ -204,6 +204,15 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
 		if metrics.EnabledExpensive {
 			defer func(start time.Time) { s.db.SnapshotStorageReads += time.Since(start) }(time.Now())
 		}
+		// If the object was destructed in *this* block (and potentially resurrected),
+		// the storage has been cleared out, and we should *not* consult the previous
+		// snapshot about any storage values. The only possible alternatives are:
+		//   1) resurrect happened, and new slot values were set -- those should
+		//      have been handles via pendingStorage above.
+		//   2) we don't have new values, and can deliver empty response back
+		if _, destructed := s.db.snapDestructs[s.addrHash]; destructed {
+			return common.Hash{}
+		}
 		enc, err = s.db.snap.Storage(s.addrHash, crypto.Keccak256Hash(key[:]))
 	}
 	// If snapshot unavailable or reading from it failed, load from the database

+ 4 - 1
core/state/statedb.go

@@ -595,6 +595,9 @@ func (s *StateDB) CreateAccount(addr common.Address) {
 	if prev != nil {
 		newObj.setBalance(prev.data.Balance)
 	}
+	if s.snap != nil && prev != nil {
+		s.snapDestructs[prev.addrHash] = struct{}{}
+	}
 }
 
 func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error {
@@ -855,7 +858,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
 				log.Warn("Failed to cap snapshot tree", "root", root, "layers", 127, "err", err)
 			}
 		}
-		s.snap, s.snapAccounts, s.snapStorage = nil, nil, nil
+		s.snap, s.snapDestructs, s.snapAccounts, s.snapStorage = nil, nil, nil, nil
 	}
 	return root, err
 }