208 static const PrecomputedData data;
211 CoinsViewBottom bottom;
213 std::vector<std::unique_ptr<CCoinsViewCache>> caches;
215 CacheLevel sim_caches[MAX_CACHES + 1];
217 uint32_t current_height = 1U;
220 sim_caches[0].Wipe();
223 auto lookup = [&](uint32_t outpointidx,
int sim_idx = -1) -> std::optional<std::pair<coinidx_type, uint32_t>> {
224 uint32_t cache_idx = sim_idx == -1 ? caches.size() : sim_idx;
226 const auto& entry = sim_caches[cache_idx].entry[outpointidx];
227 if (entry.entrytype == EntryType::UNSPENT) {
228 return {{entry.coinidx, entry.height}};
229 }
else if (entry.entrytype == EntryType::SPENT) {
232 if (cache_idx == 0)
break;
240 assert(caches.size() >= 1);
241 auto& cache = sim_caches[caches.size()];
242 auto& prev_cache = sim_caches[caches.size() - 1];
243 for (uint32_t outpointidx = 0; outpointidx < NUM_OUTPOINTS; ++outpointidx) {
244 if (cache.entry[outpointidx].entrytype != EntryType::NONE) {
245 prev_cache.entry[outpointidx] = cache.entry[outpointidx];
246 cache.entry[outpointidx].entrytype = EntryType::NONE;
259 if (caches.empty()) {
261 sim_caches[caches.size()].Wipe();
271 auto sim = lookup(outpointidx);
274 auto real = caches.back()->GetCoin(data.outpoints[outpointidx], realcoin);
276 if (!sim.has_value()) {
280 const auto& simcoin = data.coins[sim->first];
290 auto sim = lookup(outpointidx);
292 auto real = caches.back()->HaveCoin(data.outpoints[outpointidx]);
294 assert(sim.has_value() == real);
300 (void)caches.back()->HaveCoinInCache(data.outpoints[outpointidx]);
306 auto sim = lookup(outpointidx);
308 const auto& realcoin = caches.back()->AccessCoin(data.outpoints[outpointidx]);
310 if (!sim.has_value()) {
311 assert(realcoin.IsSpent());
313 assert(!realcoin.IsSpent());
314 const auto& simcoin = data.coins[sim->first];
315 assert(simcoin.out == realcoin.out);
316 assert(simcoin.fCoinBase == realcoin.fCoinBase);
317 assert(realcoin.nHeight == sim->second);
325 auto sim = lookup(outpointidx);
327 Coin coin = data.coins[coinidx];
329 caches.back()->AddCoin(data.outpoints[outpointidx], std::move(coin), sim.has_value());
331 auto& entry = sim_caches[caches.size()].entry[outpointidx];
332 entry.entrytype = EntryType::UNSPENT;
333 entry.coinidx = coinidx;
334 entry.height = current_height;
341 Coin coin = data.coins[coinidx];
343 caches.back()->AddCoin(data.outpoints[outpointidx], std::move(coin),
true);
345 auto& entry = sim_caches[caches.size()].entry[outpointidx];
346 entry.entrytype = EntryType::UNSPENT;
347 entry.coinidx = coinidx;
348 entry.height = current_height;
354 caches.back()->SpendCoin(data.outpoints[outpointidx],
nullptr);
356 sim_caches[caches.size()].entry[outpointidx].entrytype = EntryType::SPENT;
362 auto sim = lookup(outpointidx);
365 caches.back()->SpendCoin(data.outpoints[outpointidx], &realcoin);
367 sim_caches[caches.size()].entry[outpointidx].entrytype = EntryType::SPENT;
369 if (!sim.has_value()) {
373 const auto& simcoin = data.coins[sim->first];
383 caches.back()->Uncache(data.outpoints[outpointidx]);
387 if (caches.size() != MAX_CACHES) {
391 sim_caches[caches.size()].Wipe();
397 caches.back()->SanityCheck();
405 caches.back()->Flush();
412 caches.back()->Sync();
419 caches.back()->Flush();
420 caches.back()->ReallocateCache();
424 (void)caches.back()->GetCacheSize();
428 (void)caches.back()->DynamicMemoryUsage();
438 for (
const auto& cache : caches) {
439 cache->SanityCheck();
444 for (
unsigned sim_idx = 1; sim_idx <= caches.size(); ++sim_idx) {
445 auto& cache = *caches[sim_idx - 1];
446 size_t cache_size = 0;
448 for (uint32_t outpointidx = 0; outpointidx < NUM_OUTPOINTS; ++outpointidx) {
449 cache_size += cache.HaveCoinInCache(data.outpoints[outpointidx]);
450 const auto& real = cache.AccessCoin(data.outpoints[outpointidx]);
451 auto sim = lookup(outpointidx, sim_idx);
452 if (!sim.has_value()) {
456 assert(real.out == data.coins[sim->first].
out);
458 assert(real.nHeight == sim->second);
463 assert(cache.GetCacheSize() >= cache_size);
467 for (uint32_t outpointidx = 0; outpointidx < NUM_OUTPOINTS; ++outpointidx) {
469 bool real = bottom.GetCoin(data.outpoints[outpointidx], realcoin);
470 auto sim = lookup(outpointidx, 0);
471 if (!sim.has_value()) {