// Fetch start-base-stop|top+1(max 500) // This may generally execute 502 but as many as 531+ queries. void block_chain_impl::fetch_locator_block_hashes( const message::get_blocks& locator, const hash_digest& threshold, size_t limit, locator_block_hashes_fetch_handler handler) { // This is based on the idea that looking up by block hash to get heights // will be much faster than hashing each retrieved block to test for stop. const auto do_fetch = [this, locator, threshold, limit, handler]( size_t slock) { // Find the first block height. // If no start block is on our chain we start with block 0. size_t start = 0; for (const auto& hash: locator.start_hashes) { const auto result = database_.blocks.get(hash); if (result) { start = result.height(); break; } } // Find the stop block height. // The maximum stop block is 501 blocks after start (to return 500). size_t stop = start + limit + 1; if (locator.stop_hash != null_hash) { // If the stop block is not on chain we treat it as a null stop. const auto stop_result = database_.blocks.get(locator.stop_hash); if (stop_result) stop = std::min(stop_result.height(), stop); } // Find the threshold block height. // If the threshold is above the start it becomes the new start. if (threshold != null_hash) { const auto start_result = database_.blocks.get(threshold); if (start_result) start = std::max(start_result.height(), start); } // This largest portion can be parallelized. // Build the hash list until we hit last or the blockchain top. hash_list hashes; for (size_t index = start + 1; index < stop; ++index) { const auto result = database_.blocks.get(index); if (!result) { hashes.push_back(result.header().hash()); break; } } return finish_fetch(slock, handler, error::success, hashes); }; fetch_ordered(do_fetch); }
void block_chain_impl::fetch_stealth(const binary& filter, uint64_t from_height, stealth_fetch_handler handler) { const auto do_fetch = [this, filter, handler, from_height]( size_t slock) { const auto stealth = database_.stealth.scan(filter, from_height); return finish_fetch(slock, handler, error::success, stealth); }; fetch_parallel(do_fetch); }
void block_chain_impl::fetch_history(const wallet::payment_address& address, uint64_t limit, uint64_t from_height, history_fetch_handler handler) { const auto do_fetch = [this, address, handler, limit, from_height]( size_t slock) { const auto history = database_.history.get(address.hash(), limit, from_height); return finish_fetch(slock, handler, error::success, history); }; fetch_parallel(do_fetch); }
// This may execute up to 500 queries. void block_chain_impl::fetch_missing_block_hashes(const hash_list& hashes, missing_block_hashes_fetch_handler handler) { const auto do_fetch = [this, hashes, handler](size_t slock) { hash_list missing; for (const auto& hash: hashes) if (!database_.blocks.get(hash)) missing.push_back(hash); return finish_fetch(slock, handler, error::success, missing); }; fetch_ordered(do_fetch); }