From d40f3d36752946489eeb3cbf5b661a328771d49d Mon Sep 17 00:00:00 2001 From: Michal Fousek Date: Fri, 12 May 2023 11:49:15 +0200 Subject: [PATCH] [#1044] Implement EnhanceAction Closes #1044 --- .../Block/Actions/EnhanceAction.swift | 49 +++++++++++++++++-- .../Block/CompactBlockProcessorNG.swift | 7 ++- .../Constants/ZcashSDK.swift | 3 ++ 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/Sources/ZcashLightClientKit/Block/Actions/EnhanceAction.swift b/Sources/ZcashLightClientKit/Block/Actions/EnhanceAction.swift index 3385449b..444908f9 100644 --- a/Sources/ZcashLightClientKit/Block/Actions/EnhanceAction.swift +++ b/Sources/ZcashLightClientKit/Block/Actions/EnhanceAction.swift @@ -8,7 +8,33 @@ import Foundation class EnhanceAction { - init(container: DIContainer) { } + let blockEnhancer: BlockEnhancer + let config: CompactBlockProcessorNG.Configuration + let internalSyncProgress: InternalSyncProgress + let logger: Logger + let transactionRepository: TransactionRepository + init(container: DIContainer, config: CompactBlockProcessorNG.Configuration) { + blockEnhancer = container.resolve(BlockEnhancer.self) + self.config = config + internalSyncProgress = container.resolve(InternalSyncProgress.self) + logger = container.resolve(Logger.self) + transactionRepository = container.resolve(TransactionRepository.self) + } + + func decideWhatToDoNext(context: ActionContext, lastScannedHeight: BlockHeight) async -> ActionContext { + guard let downloadAndScanRange = await context.syncRanges.downloadAndScanRange else { + await context.update(state: .clearCache) + return context + } + + if lastScannedHeight >= downloadAndScanRange.upperBound { + await context.update(state: .clearCache) + } else { + await context.update(state: .download) + } + + return context + } } extension EnhanceAction: Action { @@ -23,8 +49,25 @@ extension EnhanceAction: Action { // If latestScannedHeight < context.scanRanges.downloadAndScanRange?.upperBound thne set state to `download` because there are blocks to // download and scan. - await context.update(state: .clearCache) - return context + let lastScannedHeight = try await transactionRepository.lastScannedHeight() + + guard let range = await context.syncRanges.enhanceRange else { + return await decideWhatToDoNext(context: context, lastScannedHeight: lastScannedHeight) + } + + let lastEnhancedHeight = await internalSyncProgress.load(.latestEnhancedHeight) + let enhanceRangeStart = max(range.lowerBound, lastEnhancedHeight) + let enhanceRangeEnd = min(range.upperBound, lastScannedHeight) + + if enhanceRangeStart <= enhanceRangeEnd && lastEnhancedHeight - lastScannedHeight >= config.enhanceBatchSize { + let enhanceRange = enhanceRangeStart...enhanceRangeEnd + let transactions = try await blockEnhancer.enhance(at: enhanceRange) { progress in + await didUpdate(.progressUpdated(.enhance(progress))) + } + await didUpdate(.foundTransactions(transactions, enhanceRange)) + } + + return await decideWhatToDoNext(context: context, lastScannedHeight: lastScannedHeight) } func stop() async { } diff --git a/Sources/ZcashLightClientKit/Block/CompactBlockProcessorNG.swift b/Sources/ZcashLightClientKit/Block/CompactBlockProcessorNG.swift index a49d8f2b..dacf35c9 100644 --- a/Sources/ZcashLightClientKit/Block/CompactBlockProcessorNG.swift +++ b/Sources/ZcashLightClientKit/Block/CompactBlockProcessorNG.swift @@ -49,6 +49,7 @@ actor CompactBlockProcessorNG { let dataDb: URL let spendParamsURL: URL let outputParamsURL: URL + let enhanceBatchSize: Int let batchSize: Int let retries: Int let maxBackoffInterval: TimeInterval @@ -72,6 +73,7 @@ actor CompactBlockProcessorNG { spendParamsURL: URL, outputParamsURL: URL, saplingParamsSourceURL: SaplingParamsSourceURL, + enhanceBatchSize: Int = ZcashSDK.DefaultEnhanceBatch, batchSize: Int = ZcashSDK.DefaultSyncBatch, retries: Int = ZcashSDK.defaultRetries, maxBackoffInterval: TimeInterval = ZcashSDK.defaultMaxBackOffInterval, @@ -87,6 +89,7 @@ actor CompactBlockProcessorNG { self.outputParamsURL = outputParamsURL self.saplingParamsSourceURL = saplingParamsSourceURL self.network = network + self.enhanceBatchSize = enhanceBatchSize self.batchSize = batchSize self.retries = retries self.maxBackoffInterval = maxBackoffInterval @@ -103,6 +106,7 @@ actor CompactBlockProcessorNG { spendParamsURL: URL, outputParamsURL: URL, saplingParamsSourceURL: SaplingParamsSourceURL, + enhanceBatchSize: Int = ZcashSDK.DefaultEnhanceBatch, batchSize: Int = ZcashSDK.DefaultSyncBatch, retries: Int = ZcashSDK.defaultRetries, maxBackoffInterval: TimeInterval = ZcashSDK.defaultMaxBackOffInterval, @@ -120,6 +124,7 @@ actor CompactBlockProcessorNG { self.saplingActivation = network.constants.saplingActivationHeight self.network = network self.cacheDbURL = nil + self.enhanceBatchSize = enhanceBatchSize self.batchSize = batchSize self.retries = retries self.maxBackoffInterval = maxBackoffInterval @@ -208,7 +213,7 @@ actor CompactBlockProcessorNG { case .clearAlreadyScannedBlocks: action = ClearAlreadyScannedBlocksAction(container: container) case .enhance: - action = EnhanceAction(container: container) + action = EnhanceAction(container: container, config: config) case .fetchUTXO: action = FetchUTXOsAction(container: container) case .handleSaplingParams: diff --git a/Sources/ZcashLightClientKit/Constants/ZcashSDK.swift b/Sources/ZcashLightClientKit/Constants/ZcashSDK.swift index ee63a57f..2b6f08a6 100644 --- a/Sources/ZcashLightClientKit/Constants/ZcashSDK.swift +++ b/Sources/ZcashLightClientKit/Constants/ZcashSDK.swift @@ -104,6 +104,9 @@ public enum ZcashSDK { /// times three is held in memory at some point of the sync process. public static let DefaultSyncBatch = 100 + /// Default batch size for enhancing transactions for the compact block processor + public static let DefaultEnhanceBatch = 1000 + /// Default amount of time, in in seconds, to poll for new blocks. Typically, this should be about half the average /// block time. public static let defaultPollInterval: TimeInterval = 20