195 static const PrecomputedData data;
198 CoinsViewBottom bottom;
200 std::vector<std::unique_ptr<CCoinsViewCache>> caches;
202 CacheLevel sim_caches[MAX_CACHES + 1];
204 uint32_t current_height = 1U;
207 sim_caches[0].Wipe();
210 auto lookup = [&](uint32_t outpointidx,
int sim_idx = -1) -> std::optional<std::pair<coinidx_type, uint32_t>> {
211 uint32_t cache_idx = sim_idx == -1 ? caches.size() : sim_idx;
213 const auto& entry = sim_caches[cache_idx].entry[outpointidx];
214 if (entry.entrytype == EntryType::UNSPENT) {
215 return {{entry.coinidx, entry.height}};
216 }
else if (entry.entrytype == EntryType::SPENT) {
219 if (cache_idx == 0)
break;
227 assert(caches.size() >= 1);
228 auto& cache = sim_caches[caches.size()];
229 auto& prev_cache = sim_caches[caches.size() - 1];
230 for (uint32_t outpointidx = 0; outpointidx < NUM_OUTPOINTS; ++outpointidx) {
231 if (cache.entry[outpointidx].entrytype != EntryType::NONE) {
232 prev_cache.entry[outpointidx] = cache.entry[outpointidx];
233 cache.entry[outpointidx].entrytype = EntryType::NONE;
246 if (caches.empty()) {
248 sim_caches[caches.size()].Wipe();
258 auto sim = lookup(outpointidx);
261 caches.back()->PeekCoin(data.outpoints[outpointidx]) :
262 caches.back()->GetCoin(data.outpoints[outpointidx]);
264 if (!sim.has_value()) {
267 assert(realcoin && !realcoin->IsSpent());
268 const auto& simcoin = data.coins[sim->first];
269 assert(realcoin->out == simcoin.out);
270 assert(realcoin->fCoinBase == simcoin.fCoinBase);
271 assert(realcoin->nHeight == sim->second);
278 auto sim = lookup(outpointidx);
280 auto real = caches.back()->HaveCoin(data.outpoints[outpointidx]);
282 assert(sim.has_value() == real);
288 (void)caches.back()->HaveCoinInCache(data.outpoints[outpointidx]);
294 auto sim = lookup(outpointidx);
296 const auto& realcoin = caches.back()->AccessCoin(data.outpoints[outpointidx]);
298 if (!sim.has_value()) {
299 assert(realcoin.IsSpent());
301 assert(!realcoin.IsSpent());
302 const auto& simcoin = data.coins[sim->first];
303 assert(simcoin.out == realcoin.out);
304 assert(simcoin.fCoinBase == realcoin.fCoinBase);
305 assert(realcoin.nHeight == sim->second);
313 auto sim = lookup(outpointidx);
315 Coin coin = data.coins[coinidx];
317 caches.back()->AddCoin(data.outpoints[outpointidx], std::move(coin), sim.has_value());
319 auto& entry = sim_caches[caches.size()].entry[outpointidx];
320 entry.entrytype = EntryType::UNSPENT;
321 entry.coinidx = coinidx;
322 entry.height = current_height;
329 Coin coin = data.coins[coinidx];
330 coin.nHeight = current_height;
331 caches.back()->AddCoin(data.outpoints[outpointidx], std::move(coin),
true);
333 auto& entry = sim_caches[caches.size()].entry[outpointidx];
334 entry.entrytype = EntryType::UNSPENT;
335 entry.coinidx = coinidx;
336 entry.height = current_height;
342 caches.back()->SpendCoin(data.outpoints[outpointidx],
nullptr);
344 sim_caches[caches.size()].entry[outpointidx].entrytype = EntryType::SPENT;
350 auto sim = lookup(outpointidx);
353 caches.back()->SpendCoin(data.outpoints[outpointidx], &realcoin);
355 sim_caches[caches.size()].entry[outpointidx].entrytype = EntryType::SPENT;
357 if (!sim.has_value()) {
361 const auto& simcoin = data.coins[sim->first];
371 caches.back()->Uncache(data.outpoints[outpointidx]);
375 if (caches.size() != MAX_CACHES) {
383 sim_caches[caches.size()].Wipe();
389 caches.back()->SanityCheck();
404 caches.back()->Sync();
408 sim_caches[caches.size()].Wipe();
411 const auto reset_guard{caches.back()->CreateResetGuard()};
416 (void)caches.back()->GetCacheSize();
420 (void)caches.back()->DynamicMemoryUsage();
430 for (
const auto& cache : caches) {
431 cache->SanityCheck();
436 for (
unsigned sim_idx = 1; sim_idx <= caches.size(); ++sim_idx) {
437 auto& cache = *caches[sim_idx - 1];
438 size_t cache_size = 0;
440 for (uint32_t outpointidx = 0; outpointidx < NUM_OUTPOINTS; ++outpointidx) {
441 cache_size += cache.HaveCoinInCache(data.outpoints[outpointidx]);
442 const auto& real = cache.AccessCoin(data.outpoints[outpointidx]);
443 auto sim = lookup(outpointidx, sim_idx);
444 if (!sim.has_value()) {
448 assert(real.out == data.coins[sim->first].out);
449 assert(real.fCoinBase == data.coins[sim->first].fCoinBase);
450 assert(real.nHeight == sim->second);
455 assert(cache.GetCacheSize() >= cache_size);
459 for (uint32_t outpointidx = 0; outpointidx < NUM_OUTPOINTS; ++outpointidx) {
460 auto realcoin = bottom.GetCoin(data.outpoints[outpointidx]);
461 auto sim = lookup(outpointidx, 0);
462 if (!sim.has_value()) {
465 assert(realcoin && !realcoin->IsSpent());
466 assert(realcoin->out == data.coins[sim->first].out);
467 assert(realcoin->fCoinBase == data.coins[sim->first].fCoinBase);
468 assert(realcoin->nHeight == sim->second);