| 306 | } |
| 307 | |
| 308 | static bool LookupRange(CDBWrapper& db, const std::string& index_name, int start_height, |
| 309 | const CBlockIndex* stop_index, std::vector<DBVal>& results) |
| 310 | { |
| 311 | if (start_height < 0) { |
| 312 | LogError("start height (%d) is negative", start_height); |
| 313 | return false; |
| 314 | } |
| 315 | if (start_height > stop_index->nHeight) { |
| 316 | LogError("start height (%d) is greater than stop height (%d)", |
| 317 | start_height, stop_index->nHeight); |
| 318 | return false; |
| 319 | } |
| 320 | |
| 321 | size_t results_size = static_cast<size_t>(stop_index->nHeight - start_height + 1); |
| 322 | std::vector<std::pair<uint256, DBVal>> values(results_size); |
| 323 | |
| 324 | index_util::DBHeightKey key(start_height); |
| 325 | std::unique_ptr<CDBIterator> db_it(db.NewIterator()); |
| 326 | db_it->Seek(index_util::DBHeightKey(start_height)); |
| 327 | for (int height = start_height; height <= stop_index->nHeight; ++height) { |
| 328 | if (!db_it->Valid() || !db_it->GetKey(key) || key.height != height) { |
| 329 | return false; |
| 330 | } |
| 331 | |
| 332 | size_t i = static_cast<size_t>(height - start_height); |
| 333 | if (!db_it->GetValue(values[i])) { |
| 334 | LogError("unable to read value in %s at key (%c, %d)", |
| 335 | index_name, index_util::DB_BLOCK_HEIGHT, height); |
| 336 | return false; |
| 337 | } |
| 338 | |
| 339 | db_it->Next(); |
| 340 | } |
| 341 | |
| 342 | results.resize(results_size); |
| 343 | |
| 344 | // Iterate backwards through block indexes collecting results in order to access the block hash |
| 345 | // of each entry in case we need to look it up in the hash index. |
| 346 | for (const CBlockIndex* block_index = stop_index; |
| 347 | block_index && block_index->nHeight >= start_height; |
| 348 | block_index = block_index->pprev) { |
| 349 | uint256 block_hash = block_index->GetBlockHash(); |
| 350 | |
| 351 | size_t i = static_cast<size_t>(block_index->nHeight - start_height); |
| 352 | if (block_hash == values[i].first) { |
| 353 | results[i] = std::move(values[i].second); |
| 354 | continue; |
| 355 | } |
| 356 | |
| 357 | if (!db.Read(index_util::DBHashKey(block_hash), results[i])) { |
| 358 | LogError("unable to read value in %s at key (%c, %s)", |
| 359 | index_name, index_util::DB_BLOCK_HASH, block_hash.ToString()); |
| 360 | return false; |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | return true; |
| 365 | } |
no test coverage detected