@@ -34,7 +34,9 @@ size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); }
34
34
CCoinsViewCache::CCoinsViewCache (CCoinsView* baseIn, bool deterministic) :
35
35
CCoinsViewBacked(baseIn), m_deterministic(deterministic),
36
36
cacheCoins(0 , SaltedOutpointHasher(/* deterministic=*/ deterministic), CCoinsMap::key_equal{}, &m_cache_coins_memory_resource)
37
- {}
37
+ {
38
+ m_sentinel.second .SelfRef (m_sentinel);
39
+ }
38
40
39
41
size_t CCoinsViewCache::DynamicMemoryUsage () const {
40
42
return memusage::DynamicUsage (cacheCoins) + cachedCoinsUsage;
@@ -51,7 +53,7 @@ CCoinsMap::iterator CCoinsViewCache::FetchCoin(const COutPoint &outpoint) const
51
53
if (ret->second .coin .IsSpent ()) {
52
54
// The parent only has an empty entry for this outpoint; we can consider our
53
55
// version as fresh.
54
- ret->second .AddFlags (CCoinsCacheEntry::FRESH);
56
+ ret->second .AddFlags (CCoinsCacheEntry::FRESH, *ret, m_sentinel );
55
57
}
56
58
cachedCoinsUsage += ret->second .coin .DynamicMemoryUsage ();
57
59
return ret;
@@ -96,7 +98,7 @@ void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possi
96
98
fresh = !it->second .IsDirty ();
97
99
}
98
100
it->second .coin = std::move (coin);
99
- it->second .AddFlags (CCoinsCacheEntry::DIRTY | (fresh ? CCoinsCacheEntry::FRESH : 0 ));
101
+ it->second .AddFlags (CCoinsCacheEntry::DIRTY | (fresh ? CCoinsCacheEntry::FRESH : 0 ), *it, m_sentinel );
100
102
cachedCoinsUsage += it->second .coin .DynamicMemoryUsage ();
101
103
TRACE5 (utxocache, add,
102
104
outpoint.hash .data (),
@@ -113,7 +115,7 @@ void CCoinsViewCache::EmplaceCoinInternalDANGER(COutPoint&& outpoint, Coin&& coi
113
115
std::forward_as_tuple (std::move (outpoint)),
114
116
std::forward_as_tuple (std::move (coin)));
115
117
if (inserted) {
116
- it->second .AddFlags (CCoinsCacheEntry::DIRTY);
118
+ it->second .AddFlags (CCoinsCacheEntry::DIRTY, *it, m_sentinel );
117
119
}
118
120
}
119
121
@@ -144,7 +146,7 @@ bool CCoinsViewCache::SpendCoin(const COutPoint &outpoint, Coin* moveout) {
144
146
if (it->second .IsFresh ()) {
145
147
cacheCoins.erase (it);
146
148
} else {
147
- it->second .AddFlags (CCoinsCacheEntry::DIRTY);
149
+ it->second .AddFlags (CCoinsCacheEntry::DIRTY, *it, m_sentinel );
148
150
it->second .coin .Clear ();
149
151
}
150
152
return true ;
@@ -196,7 +198,8 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
196
198
if (!(it->second .IsFresh () && it->second .coin .IsSpent ())) {
197
199
// Create the coin in the parent cache, move the data up
198
200
// and mark it as dirty.
199
- CCoinsCacheEntry& entry = cacheCoins[it->first ];
201
+ itUs = cacheCoins.try_emplace (it->first ).first ;
202
+ CCoinsCacheEntry& entry{itUs->second };
200
203
if (erase) {
201
204
// The `move` call here is purely an optimization; we rely on the
202
205
// `mapCoins.erase` call in the `for` expression to actually remove
@@ -206,12 +209,12 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
206
209
entry.coin = it->second .coin ;
207
210
}
208
211
cachedCoinsUsage += entry.coin .DynamicMemoryUsage ();
209
- entry.AddFlags (CCoinsCacheEntry::DIRTY);
212
+ entry.AddFlags (CCoinsCacheEntry::DIRTY, *itUs, m_sentinel );
210
213
// We can mark it FRESH in the parent if it was FRESH in the child
211
214
// Otherwise it might have just been flushed from the parent's cache
212
215
// and already exist in the grandparent
213
216
if (it->second .IsFresh ()) {
214
- entry.AddFlags (CCoinsCacheEntry::FRESH);
217
+ entry.AddFlags (CCoinsCacheEntry::FRESH, *itUs, m_sentinel );
215
218
}
216
219
}
217
220
} else {
@@ -241,7 +244,7 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
241
244
itUs->second .coin = it->second .coin ;
242
245
}
243
246
cachedCoinsUsage += itUs->second .coin .DynamicMemoryUsage ();
244
- itUs->second .AddFlags (CCoinsCacheEntry::DIRTY);
247
+ itUs->second .AddFlags (CCoinsCacheEntry::DIRTY, *itUs, m_sentinel );
245
248
// NOTE: It isn't safe to mark the coin as FRESH in the parent
246
249
// cache. If it already existed and was spent in the parent
247
250
// cache then marking it FRESH would prevent that spentness
0 commit comments