@@ -160,18 +160,23 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
160
160
if (it->second .flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
161
161
CCoinsMap::iterator itUs = cacheCoins.find (it->first );
162
162
if (itUs == cacheCoins.end ()) {
163
- if (!it->second .coins .IsPruned ()) {
164
- // The parent cache does not have an entry, while the child
165
- // cache does have (a non-pruned) one. Move the data up, and
166
- // mark it as fresh (if the grandparent did have it, we
167
- // would have pulled it in at first GetCoins).
168
- assert (it->second .flags & CCoinsCacheEntry::FRESH);
163
+ // The parent cache does not have an entry, while the child does
164
+ // We can ignore it if it's both FRESH and pruned in the child
165
+ if (!(it->second .flags & CCoinsCacheEntry::FRESH && it->second .coins .IsPruned ())) {
166
+ // Otherwise we will need to create it in the parent
167
+ // and move the data up and mark it as dirty
169
168
CCoinsCacheEntry& entry = cacheCoins[it->first ];
170
169
entry.coins .swap (it->second .coins );
171
170
cachedCoinsUsage += entry.coins .DynamicMemoryUsage ();
172
- entry.flags = CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH;
171
+ entry.flags = CCoinsCacheEntry::DIRTY;
172
+ // We can mark it FRESH in the parent if it was FRESH in the child
173
+ // Otherwise it might have just been flushed from the parent's cache
174
+ // and already exist in the grandparent
175
+ if (it->second .flags & CCoinsCacheEntry::FRESH)
176
+ entry.flags |= CCoinsCacheEntry::FRESH;
173
177
}
174
178
} else {
179
+ // Found the entry in the parent cache
175
180
if ((itUs->second .flags & CCoinsCacheEntry::FRESH) && it->second .coins .IsPruned ()) {
176
181
// The grandparent does not have an entry, and the child is
177
182
// modified and being pruned. This means we can just delete
0 commit comments