| 330 | } |
| 331 | |
| 332 | void CCoinsViewCache::SanityCheck() const |
| 333 | { |
| 334 | size_t recomputed_usage = 0; |
| 335 | size_t count_dirty = 0; |
| 336 | for (const auto& [_, entry] : cacheCoins) { |
| 337 | if (entry.coin.IsSpent()) { |
| 338 | assert(entry.IsDirty() && !entry.IsFresh()); // A spent coin must be dirty and cannot be fresh |
| 339 | } else { |
| 340 | assert(entry.IsDirty() || !entry.IsFresh()); // An unspent coin must not be fresh if not dirty |
| 341 | } |
| 342 | |
| 343 | // Recompute cachedCoinsUsage. |
| 344 | recomputed_usage += entry.coin.DynamicMemoryUsage(); |
| 345 | |
| 346 | // Count the number of entries we expect in the linked list. |
| 347 | if (entry.IsDirty()) ++count_dirty; |
| 348 | } |
| 349 | // Iterate over the linked list of flagged entries. |
| 350 | size_t count_linked = 0; |
| 351 | for (auto it = m_sentinel.second.Next(); it != &m_sentinel; it = it->second.Next()) { |
| 352 | // Verify linked list integrity. |
| 353 | assert(it->second.Next()->second.Prev() == it); |
| 354 | assert(it->second.Prev()->second.Next() == it); |
| 355 | // Verify they are actually flagged. |
| 356 | assert(it->second.IsDirty()); |
| 357 | // Count the number of entries actually in the list. |
| 358 | ++count_linked; |
| 359 | } |
| 360 | assert(count_dirty == count_linked && count_dirty == m_dirty_count); |
| 361 | assert(recomputed_usage == cachedCoinsUsage); |
| 362 | } |
| 363 | |
| 364 | static const uint64_t MIN_TRANSACTION_OUTPUT_WEIGHT{WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxOut())}; |
| 365 | static const uint64_t MAX_OUTPUTS_PER_BLOCK{MAX_BLOCK_WEIGHT / MIN_TRANSACTION_OUTPUT_WEIGHT}; |