@@ -146,56 +146,58 @@ void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
146
146
}
147
147
148
148
bool CCoinsViewCache::BatchWrite (CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
149
- for (CCoinsMap::iterator it = mapCoins.begin (); it != mapCoins.end ();) {
150
- if (it->second .flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
151
- CCoinsMap::iterator itUs = cacheCoins.find (it->first );
152
- if (itUs == cacheCoins.end ()) {
153
- // The parent cache does not have an entry, while the child does
154
- // We can ignore it if it's both FRESH and pruned in the child
155
- if (!(it->second .flags & CCoinsCacheEntry::FRESH && it->second .coin .IsSpent ())) {
156
- // Otherwise we will need to create it in the parent
157
- // and move the data up and mark it as dirty
158
- CCoinsCacheEntry& entry = cacheCoins[it->first ];
159
- entry.coin = std::move (it->second .coin );
160
- cachedCoinsUsage += entry.coin .DynamicMemoryUsage ();
161
- entry.flags = CCoinsCacheEntry::DIRTY;
162
- // We can mark it FRESH in the parent if it was FRESH in the child
163
- // Otherwise it might have just been flushed from the parent's cache
164
- // and already exist in the grandparent
165
- if (it->second .flags & CCoinsCacheEntry::FRESH)
166
- entry.flags |= CCoinsCacheEntry::FRESH;
149
+ for (CCoinsMap::iterator it = mapCoins.begin (); it != mapCoins.end (); it = mapCoins.erase (it)) {
150
+ // Ignore non-dirty entries (optimization).
151
+ if (!(it->second .flags & CCoinsCacheEntry::DIRTY)) {
152
+ continue ;
153
+ }
154
+ CCoinsMap::iterator itUs = cacheCoins.find (it->first );
155
+ if (itUs == cacheCoins.end ()) {
156
+ // The parent cache does not have an entry, while the child does
157
+ // We can ignore it if it's both FRESH and pruned in the child
158
+ if (!(it->second .flags & CCoinsCacheEntry::FRESH && it->second .coin .IsSpent ())) {
159
+ // Otherwise we will need to create it in the parent
160
+ // and move the data up and mark it as dirty
161
+ CCoinsCacheEntry& entry = cacheCoins[it->first ];
162
+ entry.coin = std::move (it->second .coin );
163
+ cachedCoinsUsage += entry.coin .DynamicMemoryUsage ();
164
+ entry.flags = CCoinsCacheEntry::DIRTY;
165
+ // We can mark it FRESH in the parent if it was FRESH in the child
166
+ // Otherwise it might have just been flushed from the parent's cache
167
+ // and already exist in the grandparent
168
+ if (it->second .flags & CCoinsCacheEntry::FRESH) {
169
+ entry.flags |= CCoinsCacheEntry::FRESH;
167
170
}
168
- } else {
169
- // Assert that the child cache entry was not marked FRESH if the
170
- // parent cache entry has unspent outputs. If this ever happens,
171
- // it means the FRESH flag was misapplied and there is a logic
172
- // error in the calling code.
173
- if ((it->second .flags & CCoinsCacheEntry::FRESH) && !itUs->second .coin .IsSpent ())
174
- throw std::logic_error (" FRESH flag misapplied to cache entry for base transaction with spendable outputs" );
171
+ }
172
+ } else {
173
+ // Assert that the child cache entry was not marked FRESH if the
174
+ // parent cache entry has unspent outputs. If this ever happens,
175
+ // it means the FRESH flag was misapplied and there is a logic
176
+ // error in the calling code.
177
+ if ((it->second .flags & CCoinsCacheEntry::FRESH) && !itUs->second .coin .IsSpent ()) {
178
+ throw std::logic_error (" FRESH flag misapplied to cache entry for base transaction with spendable outputs" );
179
+ }
175
180
176
- // Found the entry in the parent cache
177
- if ((itUs->second .flags & CCoinsCacheEntry::FRESH) && it->second .coin .IsSpent ()) {
178
- // The grandparent does not have an entry, and the child is
179
- // modified and being pruned. This means we can just delete
180
- // it from the parent.
181
- cachedCoinsUsage -= itUs->second .coin .DynamicMemoryUsage ();
182
- cacheCoins.erase (itUs);
183
- } else {
184
- // A normal modification.
185
- cachedCoinsUsage -= itUs->second .coin .DynamicMemoryUsage ();
186
- itUs->second .coin = std::move (it->second .coin );
187
- cachedCoinsUsage += itUs->second .coin .DynamicMemoryUsage ();
188
- itUs->second .flags |= CCoinsCacheEntry::DIRTY;
189
- // NOTE: It is possible the child has a FRESH flag here in
190
- // the event the entry we found in the parent is pruned. But
191
- // we must not copy that FRESH flag to the parent as that
192
- // pruned state likely still needs to be communicated to the
193
- // grandparent.
194
- }
181
+ // Found the entry in the parent cache
182
+ if ((itUs->second .flags & CCoinsCacheEntry::FRESH) && it->second .coin .IsSpent ()) {
183
+ // The grandparent does not have an entry, and the child is
184
+ // modified and being pruned. This means we can just delete
185
+ // it from the parent.
186
+ cachedCoinsUsage -= itUs->second .coin .DynamicMemoryUsage ();
187
+ cacheCoins.erase (itUs);
188
+ } else {
189
+ // A normal modification.
190
+ cachedCoinsUsage -= itUs->second .coin .DynamicMemoryUsage ();
191
+ itUs->second .coin = std::move (it->second .coin );
192
+ cachedCoinsUsage += itUs->second .coin .DynamicMemoryUsage ();
193
+ itUs->second .flags |= CCoinsCacheEntry::DIRTY;
194
+ // NOTE: It is possible the child has a FRESH flag here in
195
+ // the event the entry we found in the parent is pruned. But
196
+ // we must not copy that FRESH flag to the parent as that
197
+ // pruned state likely still needs to be communicated to the
198
+ // grandparent.
195
199
}
196
200
}
197
- CCoinsMap::iterator itOld = it++;
198
- mapCoins.erase (itOld);
199
201
}
200
202
hashBlock = hashBlockIn;
201
203
return true ;
0 commit comments