diff --git a/Sources/ZcashLightClientKit/Block/DatabaseStorage/CompactBlockStorage.swift b/Sources/ZcashLightClientKit/Block/DatabaseStorage/CompactBlockStorage.swift index 9a2166a9..5a9ccd9b 100644 --- a/Sources/ZcashLightClientKit/Block/DatabaseStorage/CompactBlockStorage.swift +++ b/Sources/ZcashLightClientKit/Block/DatabaseStorage/CompactBlockStorage.swift @@ -86,7 +86,7 @@ extension CompactBlockStorage: CompactBlockRepository { } func latestHeight(result: @escaping (Swift.Result) -> Void) { - DispatchQueue.global(qos: .userInitiated).async { + DispatchQueue.global(qos: .default).async { do { result(.success(try self.latestBlockHeight())) } catch { @@ -100,7 +100,7 @@ extension CompactBlockStorage: CompactBlockRepository { } func write(blocks: [ZcashCompactBlock], completion: ((Error?) -> Void)?) { - DispatchQueue.global(qos: .userInitiated).async { + DispatchQueue.global(qos: .default).async { do { try self.insert(blocks) completion?(nil) @@ -111,7 +111,7 @@ extension CompactBlockStorage: CompactBlockRepository { } func rewind(to height: BlockHeight, completion: ((Error?) -> Void)?) { - DispatchQueue.global(qos: .userInitiated).async { + DispatchQueue.global(qos: .default).async { do { try self.rewind(to: height) completion?(nil) diff --git a/Sources/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift b/Sources/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift index 3a84b9eb..44909277 100644 --- a/Sources/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift +++ b/Sources/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift @@ -322,9 +322,11 @@ public class CompactBlockProcessor { self.stop() } } + var maxAttemptsReached: Bool { self.retryAttempts >= self.config.retries } + var shouldStart: Bool { switch self.state { case .stopped, .synced, .error: @@ -335,7 +337,7 @@ public class CompactBlockProcessor { } private var service: LightWalletService - private var downloader: CompactBlockDownloading + private(set) var downloader: CompactBlockDownloading private var storage: CompactBlockStorage private var transactionRepository: TransactionRepository private var accountRepository: AccountRepository @@ -1130,7 +1132,8 @@ public class CompactBlockProcessor { case .downloading: NotificationCenter.default.post(name: Notification.Name.blockProcessorStartedDownloading, object: self) case .synced: - NotificationCenter.default.post(name: Notification.Name.blockProcessorFinished, object: self) + // transition to this state is handled by `processingFinished(height: BlockHeight)` + break case .error(let err): notifyError(err) case .scanning: @@ -1396,7 +1399,7 @@ extension CompactBlockProcessor { queue: DispatchQueue?, result: @escaping (Result) -> Void ) { - let dispatchQueue = queue ?? DispatchQueue.global(qos: .userInitiated) + let dispatchQueue = queue ?? DispatchQueue.global(qos: .default) dispatchQueue.async { do { diff --git a/Sources/ZcashLightClientKit/DAO/PagedTransactionDao.swift b/Sources/ZcashLightClientKit/DAO/PagedTransactionDao.swift index a7215722..e6655605 100644 --- a/Sources/ZcashLightClientKit/DAO/PagedTransactionDao.swift +++ b/Sources/ZcashLightClientKit/DAO/PagedTransactionDao.swift @@ -50,7 +50,7 @@ class PagedTransactionDAO: PaginatedTransactionRepository { } func page(_ number: Int, result: @escaping (Result<[TransactionEntity]?, Error>) -> Void) { - DispatchQueue.global(qos: .userInitiated).async { [weak self] in + DispatchQueue.global(qos: .default).async { [weak self] in guard let self = self else { return } do { result(.success(try self.page(number))) diff --git a/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift b/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift index 27c7ee7c..dd682704 100644 --- a/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift +++ b/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift @@ -77,6 +77,12 @@ public extension Notification.Name { /// Synchronizer implementation for UIKit and iOS 12+ // swiftlint:disable type_body_length public class SDKSynchronizer: Synchronizer { + public struct SynchronizerState { + public var shieldedBalance: WalletBalance + public var transparentBalance: WalletBalance + public var syncStatus: SyncStatus + public var latestScannedHeight: BlockHeight + } public enum NotificationKeys { public static let progress = "SDKSynchronizer.progress" @@ -89,6 +95,7 @@ public class SDKSynchronizer: Synchronizer { public static let nextStatus = "SDKSynchronizer.nextStatus" public static let currentConnectionState = "SDKSynchronizer.currentConnectionState" public static let previousConnectionState = "SDKSynchronizer.previousConnectionState" + public static let synchronizerState = "SDKSynchronizer.synchronizerState" } public private(set) var status: SyncStatus { @@ -435,16 +442,12 @@ public class SDKSynchronizer: Synchronizer { } @objc func processorFinished(_ notification: Notification) { - // FIX: Pending transaction updates fail if done from another thread. Improvement needed: explicitly define queues for sql repositories - - DispatchQueue.main.async { [weak self] in - guard let self = self else { return } - if let blockHeight = notification.userInfo?[CompactBlockProcessorNotificationKey.latestScannedBlockHeight] as? BlockHeight { - self.latestScannedHeight = blockHeight - } - self.refreshPendingTransactions() - self.status = .synced - } + // FIX: Pending transaction updates fail if done from another thread. Improvement needed: explicitly define queues for sql repositories see: https://github.com/zcash/ZcashLightClientKit/issues/450 + if let blockHeight = notification.userInfo?[CompactBlockProcessorNotificationKey.latestScannedBlockHeight] as? BlockHeight { + self.latestScannedHeight = blockHeight + } + self.refreshPendingTransactions() + self.status = .synced } @objc func processorTransitionUnknown(_ notification: Notification) { @@ -624,15 +627,15 @@ public class SDKSynchronizer: Synchronizer { } public func latestDownloadedHeight() throws -> BlockHeight { - try initializer.downloader.lastDownloadedBlockHeight() + try blockProcessor.downloader.lastDownloadedBlockHeight() } public func latestHeight(result: @escaping (Result) -> Void) { - initializer.downloader.latestBlockHeight(result: result) + blockProcessor.downloader.latestBlockHeight(result: result) } public func latestHeight() throws -> BlockHeight { - try initializer.downloader.latestBlockHeight() + try blockProcessor.downloader.latestBlockHeight() } public func latestUTXOs(address: String, result: @escaping (Result<[UnspentTransactionOutputEntity], Error>) -> Void) { @@ -770,7 +773,16 @@ public class SDKSynchronizer: Synchronizer { name: Notification.Name.synchronizerSynced, object: self, userInfo: [ - SDKSynchronizer.NotificationKeys.blockHeight: self.latestScannedHeight + SDKSynchronizer.NotificationKeys.blockHeight: self.latestScannedHeight, + SDKSynchronizer.NotificationKeys.synchronizerState: SynchronizerState( + shieldedBalance: WalletBalance( + verified: initializer.getVerifiedBalance(), + total: initializer.getBalance() + ), + transparentBalance: (try? self.getTransparentBalance(accountIndex: 0)) ?? WalletBalance.zero, + syncStatus: status, + latestScannedHeight: self.latestScannedHeight + ) ] ) case .unprepared: diff --git a/Sources/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift b/Sources/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift index c93db928..c5d81d6d 100644 --- a/Sources/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift +++ b/Sources/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift @@ -35,7 +35,7 @@ class PersistentTransactionManager: OutboundTransactionManager { self.encoder = encoder self.service = service self.network = networkType - self.queue = DispatchQueue.init(label: "PersistentTransactionManager.serial.queue", qos: .userInitiated) + self.queue = DispatchQueue.init(label: "PersistentTransactionManager.serial.queue", qos: .default) } func initSpend( diff --git a/Tests/TestUtils/FakeService.swift b/Tests/TestUtils/FakeService.swift index c7042ae2..fa252654 100644 --- a/Tests/TestUtils/FakeService.swift +++ b/Tests/TestUtils/FakeService.swift @@ -111,7 +111,7 @@ class MockLightWalletService: LightWalletService { } func submit(spendTransaction: Data, result: @escaping (Result) -> Void) { - DispatchQueue.global(qos: .userInitiated).asyncAfter(deadline: .now() + 1) { + DispatchQueue.global(qos: .default).asyncAfter(deadline: .now() + 1) { result(.success(LightWalletServiceMockResponse(errorCode: 0, errorMessage: "", unknownFields: UnknownStorage()))) } }