ZcashLightClientKit/Sources/ZcashLightClientKit/Block/Scan/BlockScanner.swift

85 lines
2.8 KiB
Swift

//
// CompactBlockProcessing.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 10/15/19.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
struct BlockScannerConfig {
let networkType: NetworkType
let scanningBatchSize: Int
}
protocol BlockScanner {
@discardableResult
func scanBlocks(
at range: CompactBlockRange,
didScan: @escaping (BlockHeight, UInt32) async throws -> Void
) async throws -> BlockHeight
}
struct BlockScannerImpl {
let config: BlockScannerConfig
let rustBackend: ZcashRustBackendWelding
let transactionRepository: TransactionRepository
let metrics: SDKMetrics
let logger: Logger
}
extension BlockScannerImpl: BlockScanner {
@discardableResult
func scanBlocks(
at range: CompactBlockRange,
didScan: @escaping (BlockHeight, UInt32) async throws -> Void
) async throws -> BlockHeight {
logger.debug("Going to scan blocks in range: \(range)")
try Task.checkCancellation()
let scanStartHeight = range.lowerBound
let targetScanHeight = range.upperBound
var scannedNewBlocks = false
var lastScannedHeight = scanStartHeight
repeat {
try Task.checkCancellation()
let previousScannedHeight = lastScannedHeight
let startHeight = previousScannedHeight + 1
let batchSize = UInt32(config.scanningBatchSize)
// TODO: [#1355] Do more with ScanSummary
// https://github.com/Electric-Coin-Company/zcash-swift-wallet-sdk/issues/1355
let scanSummary: ScanSummary
let scanStartTime = Date()
do {
scanSummary = try await self.rustBackend.scanBlocks(fromHeight: Int32(startHeight), limit: batchSize)
} catch {
logger.debug("block scanning failed with error: \(String(describing: error))")
throw error
}
let scanFinishTime = Date()
lastScannedHeight = scanSummary.scannedRange.upperBound - 1
scannedNewBlocks = previousScannedHeight != lastScannedHeight
if scannedNewBlocks {
try await didScan(lastScannedHeight, batchSize)
let heightCount = lastScannedHeight - previousScannedHeight
let seconds = scanFinishTime.timeIntervalSinceReferenceDate - scanStartTime.timeIntervalSinceReferenceDate
logger.debug("Scanned \(heightCount) blocks in \(seconds) seconds")
logger.sync("Scanned \(heightCount) blocks in \(seconds) seconds")
}
await Task.yield()
} while !Task.isCancelled && scannedNewBlocks && lastScannedHeight < targetScanHeight
return lastScannedHeight
}
}