From d956e9940b1d4d6b2c6aa241704c122387b203d4 Mon Sep 17 00:00:00 2001 From: Lukas Korba Date: Thu, 7 Sep 2023 12:54:47 +0200 Subject: [PATCH] [#1230] Remove linear sync from the SDK - concept of linear syncing fully removed from the SDK, it's fully replaced with Spend-before-Sync - BlockDAO - table blocks is no longer used, removed from the SDK and all it's associated getLastBlocks/ScannedHeights as with it - concept of pending transactions removed from the SDK - unit tests refactored --- CHANGELOG.md | 3 + .../ZcashLightClientSample/AppDelegate.swift | 1 - .../TransactionsDataSource.swift | 15 -- .../ViewController.swift | 8 +- README.md | 2 - .../Block/Actions/Action.swift | 10 +- .../Block/Actions/ClearCacheAction.swift | 14 +- .../ComputeSyncControlDataAction.swift | 83 -------- .../Block/Actions/SaplingParamsAction.swift | 7 +- .../Actions/UpdateSubtreeRootsAction.swift | 29 +-- .../Block/CompactBlockProcessor.swift | 19 +- .../Block/Scan/BlockScanner.swift | 1 - .../ClosureSynchronizer.swift | 1 - .../CombineSynchronizer.swift | 3 - .../ZcashLightClientKit/DAO/BlockDao.swift | 195 ----------------- .../DAO/TransactionDao.swift | 18 -- Sources/ZcashLightClientKit/Initializer.swift | 5 - .../Providers/LatestBlocksDataProvider.swift | 41 +--- .../Repository/TransactionRepository.swift | 8 +- .../ZcashLightClientKit/Synchronizer.swift | 27 +-- .../Synchronizer/ClosureSDKSynchronizer.swift | 6 - .../Synchronizer/CombineSDKSynchronizer.swift | 12 -- .../Synchronizer/Dependencies.swift | 8 +- .../Synchronizer/SDKSynchronizer.swift | 23 +- .../ClosureSynchronizerOfflineTests.swift | 14 -- .../CombineSynchronizerOfflineTests.swift | 24 --- .../ActionContextStateTests.swift | 11 - ...ClearAlreadyScannedBlocksActionTests.swift | 1 - .../ClearCacheActionTests.swift | 84 -------- .../ComputeSyncControlDataActionTests.swift | 166 --------------- .../DownloadActionTests.swift | 5 - .../MigrateLegacyCacheDBActionTests.swift | 20 -- .../SaplingParamsActionTests.swift | 23 -- .../UpdateSubtreeRootsActionTests.swift | 115 +--------- .../SynchronizerOfflineTests.swift | 23 +- .../TransactionRepositoryTests.swift | 10 - .../TestUtils/MockTransactionRepository.swift | 8 - .../AutoMockable.generated.swift | 196 +----------------- Tests/TestUtils/Stubs.swift | 4 +- 39 files changed, 57 insertions(+), 1186 deletions(-) delete mode 100644 Sources/ZcashLightClientKit/Block/Actions/ComputeSyncControlDataAction.swift delete mode 100644 Sources/ZcashLightClientKit/DAO/BlockDao.swift delete mode 100644 Tests/OfflineTests/CompactBlockProcessorActions/ComputeSyncControlDataActionTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 5efe98a80..871437f95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,9 @@ system itself won't remove these data. of syncing the amount of data provided is reduced so it's consistent. Spend before Sync is done in non-linear order so both Height and Time don't make sense anymore. +### [#1230] Remove linear sync from the SDK +`latestScannedHeight` and `latestScannedTime` removed from the SynchronizerState. Concept of pending transaction changed, `func allPendingTransactions()` is no longer available. Use `public func allTransactions()` instead. + # 0.22.0-beta ## Checkpoints diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/AppDelegate.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/AppDelegate.swift index 4eb4793cc..60c652faf 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/AppDelegate.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/AppDelegate.swift @@ -53,7 +53,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { spendParamsURL: try! spendParamsURLHelper(), outputParamsURL: try! outputParamsURLHelper(), saplingParamsSourceURL: SaplingParamsSourceURL.default, - syncAlgorithm: .spendBeforeSync, enableBackendTracing: true ) diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/List Transactions/TransactionsDataSource.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/List Transactions/TransactionsDataSource.swift index 028ace01b..13f3d729c 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/List Transactions/TransactionsDataSource.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/List Transactions/TransactionsDataSource.swift @@ -12,7 +12,6 @@ import ZcashLightClientKit class TransactionsDataSource: NSObject { enum TransactionType { - case pending case sent case received case cleared @@ -32,17 +31,9 @@ class TransactionsDataSource: NSObject { self.synchronizer = synchronizer } - // swiftlint:disable:next cyclomatic_complexity func load() async throws { transactions = [] switch status { - case .pending: - let rawTransactions = await synchronizer.pendingTransactions - for pendingTransaction in rawTransactions { - let memos = try await synchronizer.getMemos(for: pendingTransaction) - transactions.append(TransactionDetailModel(pendingTransaction: pendingTransaction, memos: memos)) - } - case .cleared: let rawTransactions = await synchronizer.transactions for transaction in rawTransactions { @@ -62,12 +53,6 @@ class TransactionsDataSource: NSObject { transactions.append(TransactionDetailModel(sendTransaction: transaction, memos: memos)) } case .all: - let rawPendingTransactions = await synchronizer.pendingTransactions - for pendingTransaction in rawPendingTransactions { - let memos = try await synchronizer.getMemos(for: pendingTransaction) - transactions.append(TransactionDetailModel(pendingTransaction: pendingTransaction, memos: memos)) - } - let rawClearedTransactions = await synchronizer.transactions for transaction in rawClearedTransactions { let memos = try await synchronizer.getMemos(for: transaction) diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/ViewController.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/ViewController.swift index de997a057..b4f066255 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/ViewController.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/ViewController.swift @@ -82,13 +82,7 @@ class MainTableViewController: UITableViewController { override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let destination = segue.destination as? TransactionsTableViewController { - if let id = segue.identifier, id == "Pending" { - destination.datasource = TransactionsDataSource( - status: .pending, - synchronizer: AppDelegate.shared.sharedSynchronizer - ) - destination.title = "Pending Transactions" - } else if let id = segue.identifier, id == "Sent" { + if let id = segue.identifier, id == "Sent" { destination.datasource = TransactionsDataSource( status: .sent, synchronizer: AppDelegate.shared.sharedSynchronizer diff --git a/README.md b/README.md index 6d5654bf3..faea33a92 100644 --- a/README.md +++ b/README.md @@ -92,8 +92,6 @@ We don't like reinventing the wheel, so we gently borrowed swift lint rules from ## `Spend before Sync` synchronization algorithm The CompactBlockProcessor is responsible for downloading and processing blocks from the lightwalletd. Since the inception of the SDK the blocks were processed in a linear order up to the chain tip. Latests SDK has introduced brand new algorithm for syncing of the blocks. It's called `Spend before Sync` and processes blocks in non-linear order so the spendable funds are discovered as soon as possible - allowing users to create a transaction while still syncing. - -By default the syncing algorithm is set to `.linear` so users of the SDK are not affected by this new feature. To switch to the `Spend before Sync` synchronization, set `syncAlgorithm: .spendBeforeSync` in the Initializer's init. # Versioning diff --git a/Sources/ZcashLightClientKit/Block/Actions/Action.swift b/Sources/ZcashLightClientKit/Block/Actions/Action.swift index b6f077826..0eb17e5ca 100644 --- a/Sources/ZcashLightClientKit/Block/Actions/Action.swift +++ b/Sources/ZcashLightClientKit/Block/Actions/Action.swift @@ -11,8 +11,6 @@ protocol ActionContext { var state: CBPState { get async } var prevState: CBPState? { get async } var syncControlData: SyncControlData { get async } - var preferredSyncAlgorithm: SyncAlgorithm { get } - var supportedSyncAlgorithm: SyncAlgorithm? { get async } var requestedRewindHeight: BlockHeight? { get async } var totalProgressRange: CompactBlockRange { get async } var processedHeight: BlockHeight { get async } @@ -28,7 +26,6 @@ protocol ActionContext { func update(lastScannedHeight: BlockHeight) async func update(lastDownloadedHeight: BlockHeight) async func update(lastEnhancedHeight: BlockHeight?) async - func update(supportedSyncAlgorithm: SyncAlgorithm) async func update(requestedRewindHeight: BlockHeight) async } @@ -36,8 +33,6 @@ actor ActionContextImpl: ActionContext { var state: CBPState var prevState: CBPState? var syncControlData: SyncControlData - let preferredSyncAlgorithm: SyncAlgorithm - var supportedSyncAlgorithm: SyncAlgorithm? var requestedRewindHeight: BlockHeight? /// Represents the overall range of blocks that will be synced, `SyncAlgorithm` doesn't matter. var totalProgressRange: CompactBlockRange = 0...0 @@ -49,9 +44,8 @@ actor ActionContextImpl: ActionContext { var lastDownloadedHeight: BlockHeight? var lastEnhancedHeight: BlockHeight? - init(state: CBPState, preferredSyncAlgorithm: SyncAlgorithm = .linear) { + init(state: CBPState) { self.state = state - self.preferredSyncAlgorithm = preferredSyncAlgorithm syncControlData = SyncControlData.empty } @@ -69,7 +63,6 @@ actor ActionContextImpl: ActionContext { func update(lastScannedHeight: BlockHeight) async { self.lastScannedHeight = lastScannedHeight } func update(lastDownloadedHeight: BlockHeight) async { self.lastDownloadedHeight = lastDownloadedHeight } func update(lastEnhancedHeight: BlockHeight?) async { self.lastEnhancedHeight = lastEnhancedHeight } - func update(supportedSyncAlgorithm: SyncAlgorithm) async { self.supportedSyncAlgorithm = supportedSyncAlgorithm } func update(requestedRewindHeight: BlockHeight) async { self.requestedRewindHeight = requestedRewindHeight } } @@ -81,7 +74,6 @@ enum CBPState: CaseIterable { case updateChainTip case processSuggestedScanRanges case rewind - case computeSyncControlData case download case scan case clearAlreadyScannedBlocks diff --git a/Sources/ZcashLightClientKit/Block/Actions/ClearCacheAction.swift b/Sources/ZcashLightClientKit/Block/Actions/ClearCacheAction.swift index 98a45cafa..67eca48ea 100644 --- a/Sources/ZcashLightClientKit/Block/Actions/ClearCacheAction.swift +++ b/Sources/ZcashLightClientKit/Block/Actions/ClearCacheAction.swift @@ -24,19 +24,7 @@ extension ClearCacheAction: Action { if await context.prevState == .idle { await context.update(state: .migrateLegacyCacheDB) } else { - if context.preferredSyncAlgorithm == .linear { - await context.update(state: .finished) - } else { - if let supportedSyncAlgorithm = await context.supportedSyncAlgorithm { - if supportedSyncAlgorithm == .linear { - await context.update(state: .finished) - } else { - await context.update(state: .processSuggestedScanRanges) - } - } else { - throw ZcashError.compactBlockProcessorSupportedSyncAlgorithm - } - } + await context.update(state: .processSuggestedScanRanges) } return context diff --git a/Sources/ZcashLightClientKit/Block/Actions/ComputeSyncControlDataAction.swift b/Sources/ZcashLightClientKit/Block/Actions/ComputeSyncControlDataAction.swift deleted file mode 100644 index aa46a9f69..000000000 --- a/Sources/ZcashLightClientKit/Block/Actions/ComputeSyncControlDataAction.swift +++ /dev/null @@ -1,83 +0,0 @@ -// -// ComputeSyncControlDataAction.swift -// -// -// Created by Michal Fousek on 05.05.2023. -// - -import Foundation - -final class ComputeSyncControlDataAction { - let configProvider: CompactBlockProcessor.ConfigProvider - let downloaderService: BlockDownloaderService - let latestBlocksDataProvider: LatestBlocksDataProvider - let logger: Logger - - init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) { - self.configProvider = configProvider - downloaderService = container.resolve(BlockDownloaderService.self) - latestBlocksDataProvider = container.resolve(LatestBlocksDataProvider.self) - logger = container.resolve(Logger.self) - } -} - -extension ComputeSyncControlDataAction: Action { - var removeBlocksCacheWhenFailed: Bool { false } - - func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext { - let config = await configProvider.config - - await latestBlocksDataProvider.updateScannedData() - await latestBlocksDataProvider.updateBlockData() - await latestBlocksDataProvider.updateUnenhancedData() - - // Here we know: - // - latest scanned height from the DB, if none the wallet's birthday is automatically used - // - first unenhanced height from the DB, could be nil = up to latestScannedHeight nothing to enhance - // - latest downloaded height reported by downloaderService - // - latest block height on the blockchain - // - wallet birthday for the initial scan - - let latestBlockHeight = await latestBlocksDataProvider.latestBlockHeight - let latestScannedHeightDB = await latestBlocksDataProvider.latestScannedHeight - let latestScannedHeight = latestScannedHeightDB < config.walletBirthday ? config.walletBirthday : latestScannedHeightDB - let firstUnenhancedHeight = await latestBlocksDataProvider.firstUnenhancedHeight - let enhanceStart: BlockHeight - if let firstUnenhancedHeight { - enhanceStart = min(firstUnenhancedHeight, latestScannedHeight) - } else { - enhanceStart = latestScannedHeight - } - - logger.debug(""" - Init numbers: - latestBlockHeight [BC]: \(latestBlockHeight) - latestScannedHeight [DB]: \(latestScannedHeight) - firstUnenhancedHeight [DB]: \(firstUnenhancedHeight ?? -1) - enhanceStart: \(enhanceStart) - walletBirthday: \(config.walletBirthday) - """) - - let syncControlData = SyncControlData( - latestBlockHeight: latestBlockHeight, - latestScannedHeight: latestScannedHeight, - firstUnenhancedHeight: enhanceStart - ) - - await context.update(lastScannedHeight: latestScannedHeight) - await context.update(lastDownloadedHeight: latestScannedHeight) - await context.update(syncControlData: syncControlData) - await context.update(totalProgressRange: latestScannedHeight...latestBlockHeight) - - // if there is nothing sync just switch to finished state - if latestBlockHeight < latestScannedHeight || latestBlockHeight == latestScannedHeight { - await context.update(state: .finished) - } else { - await context.update(state: .download) - } - - return context - } - - func stop() async { } -} diff --git a/Sources/ZcashLightClientKit/Block/Actions/SaplingParamsAction.swift b/Sources/ZcashLightClientKit/Block/Actions/SaplingParamsAction.swift index 5c1c77bb6..f734e645f 100644 --- a/Sources/ZcashLightClientKit/Block/Actions/SaplingParamsAction.swift +++ b/Sources/ZcashLightClientKit/Block/Actions/SaplingParamsAction.swift @@ -24,11 +24,8 @@ extension SaplingParamsAction: Action { logger.debug("Fetching sapling parameters") try await saplingParametersHandler.handleIfNeeded() - if context.preferredSyncAlgorithm == .spendBeforeSync { - await context.update(state: .updateSubtreeRoots) - } else { - await context.update(state: .computeSyncControlData) - } + await context.update(state: .updateSubtreeRoots) + return context } diff --git a/Sources/ZcashLightClientKit/Block/Actions/UpdateSubtreeRootsAction.swift b/Sources/ZcashLightClientKit/Block/Actions/UpdateSubtreeRootsAction.swift index d61e43cee..d554e3fe4 100644 --- a/Sources/ZcashLightClientKit/Block/Actions/UpdateSubtreeRootsAction.swift +++ b/Sources/ZcashLightClientKit/Block/Actions/UpdateSubtreeRootsAction.swift @@ -33,7 +33,6 @@ extension UpdateSubtreeRootsAction: Action { let stream = service.getSubtreeRoots(request) var roots: [SubtreeRoot] = [] - var err: Error? do { for try await subtreeRoot in stream { @@ -41,28 +40,16 @@ extension UpdateSubtreeRootsAction: Action { } } catch ZcashError.serviceSubtreeRootsStreamFailed(LightWalletServiceError.timeOut) { throw ZcashError.serviceSubtreeRootsStreamFailed(LightWalletServiceError.timeOut) - } catch { - logger.debug("getSubtreeRoots failed with error \(error.localizedDescription)") - err = error } - // In case of error, the lightwalletd doesn't support Spend before Sync -> switching to linear sync. - // Likewise, no subtree roots results in switching to linear sync. - if err != nil || roots.isEmpty { - logger.info("Spend before Sync is not possible, switching to linear sync.") - await context.update(supportedSyncAlgorithm: .linear) - await context.update(state: .computeSyncControlData) - } else { - await context.update(supportedSyncAlgorithm: .spendBeforeSync) - logger.info("Sapling tree has \(roots.count) subtrees") - do { - try await rustBackend.putSaplingSubtreeRoots(startIndex: UInt64(request.startIndex), roots: roots) - - await context.update(state: .updateChainTip) - } catch { - logger.debug("putSaplingSubtreeRoots failed with error \(error.localizedDescription)") - throw ZcashError.compactBlockProcessorPutSaplingSubtreeRoots(error) - } + logger.info("Sapling tree has \(roots.count) subtrees") + do { + try await rustBackend.putSaplingSubtreeRoots(startIndex: UInt64(request.startIndex), roots: roots) + + await context.update(state: .updateChainTip) + } catch { + logger.debug("putSaplingSubtreeRoots failed with error \(error.localizedDescription)") + throw ZcashError.compactBlockProcessorPutSaplingSubtreeRoots(error) } return context diff --git a/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift b/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift index 5a36104c8..ff96da6ce 100644 --- a/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift +++ b/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift @@ -70,7 +70,6 @@ actor CompactBlockProcessor { let network: ZcashNetwork let saplingActivation: BlockHeight let cacheDbURL: URL? - let syncAlgorithm: SyncAlgorithm var blockPollInterval: TimeInterval { TimeInterval.random(in: ZcashSDK.defaultPollInterval / 2 ... ZcashSDK.defaultPollInterval * 1.5) } @@ -90,7 +89,6 @@ actor CompactBlockProcessor { rewindDistance: Int = ZcashSDK.defaultRewindDistance, walletBirthdayProvider: @escaping () -> BlockHeight, saplingActivation: BlockHeight, - syncAlgorithm: SyncAlgorithm = .linear, network: ZcashNetwork ) { self.alias = alias @@ -108,7 +106,6 @@ actor CompactBlockProcessor { self.walletBirthdayProvider = walletBirthdayProvider self.saplingActivation = saplingActivation self.cacheDbURL = cacheDbURL - self.syncAlgorithm = syncAlgorithm } init( @@ -124,7 +121,6 @@ actor CompactBlockProcessor { maxBackoffInterval: TimeInterval = ZcashSDK.defaultMaxBackOffInterval, rewindDistance: Int = ZcashSDK.defaultRewindDistance, walletBirthdayProvider: @escaping () -> BlockHeight, - syncAlgorithm: SyncAlgorithm = .linear, network: ZcashNetwork ) { self.alias = alias @@ -142,7 +138,6 @@ actor CompactBlockProcessor { self.retries = retries self.maxBackoffInterval = maxBackoffInterval self.rewindDistance = rewindDistance - self.syncAlgorithm = syncAlgorithm } } @@ -174,7 +169,6 @@ actor CompactBlockProcessor { outputParamsURL: initializer.outputParamsURL, saplingParamsSourceURL: initializer.saplingParamsSourceURL, walletBirthdayProvider: walletBirthdayProvider, - syncAlgorithm: initializer.syncAlgorithm, network: initializer.network ), accountRepository: initializer.accountRepository @@ -193,7 +187,7 @@ actor CompactBlockProcessor { ) let configProvider = ConfigProvider(config: config) - context = ActionContextImpl(state: .idle, preferredSyncAlgorithm: config.syncAlgorithm) + context = ActionContextImpl(state: .idle) actions = Self.makeActions(container: container, configProvider: configProvider) self.metrics = container.resolve(SDKMetrics.self) @@ -232,8 +226,6 @@ actor CompactBlockProcessor { action = ProcessSuggestedScanRangesAction(container: container) case .rewind: action = RewindAction(container: container) - case .computeSyncControlData: - action = ComputeSyncControlDataAction(container: container, configProvider: configProvider) case .download: action = DownloadAction(container: container, configProvider: configProvider) case .scan: @@ -325,7 +317,7 @@ extension CompactBlockProcessor { private func doRewind(context: AfterSyncHooksManager.RewindContext) async throws { logger.debug("Executing rewind.") - let lastDownloaded = await latestBlocksDataProvider.latestScannedHeight + let lastDownloaded = await latestBlocksDataProvider.maxScannedHeight let height = Int32(context.height ?? lastDownloaded) let nearestHeight: Int32 @@ -611,8 +603,6 @@ extension CompactBlockProcessor { break case .rewind: break - case .computeSyncControlData: - break case .download: break case .scan: @@ -638,7 +628,7 @@ extension CompactBlockProcessor { private func resetContext() async { let lastEnhancedheight = await context.lastEnhancedHeight - context = ActionContextImpl(state: .idle, preferredSyncAlgorithm: config.syncAlgorithm) + context = ActionContextImpl(state: .idle) await context.update(lastEnhancedHeight: lastEnhancedheight) await compactBlockProgress.reset() } @@ -660,7 +650,7 @@ extension CompactBlockProcessor { retryAttempts = 0 consecutiveChainValidationErrors = 0 - let lastScannedHeight = await latestBlocksDataProvider.latestScannedHeight + let lastScannedHeight = await latestBlocksDataProvider.maxScannedHeight // Some actions may not run. For example there are no transactions to enhance and therefore there is no enhance progress. And in // cases like this computation of final progress won't work properly. So let's fake 100% progress at the end of the sync process. await send(event: .progressUpdated(1)) @@ -746,7 +736,6 @@ extension CompactBlockProcessor { """ Timer triggered: Starting compact Block processor!. Processor State: \(await self.context.state) - latestHeight: \(try await self.transactionRepository.lastScannedHeight()) attempts: \(await self.retryAttempts) """ ) diff --git a/Sources/ZcashLightClientKit/Block/Scan/BlockScanner.swift b/Sources/ZcashLightClientKit/Block/Scan/BlockScanner.swift index 9cd43b5ed..8d9db4bb8 100644 --- a/Sources/ZcashLightClientKit/Block/Scan/BlockScanner.swift +++ b/Sources/ZcashLightClientKit/Block/Scan/BlockScanner.swift @@ -27,7 +27,6 @@ struct BlockScannerImpl { let transactionRepository: TransactionRepository let metrics: SDKMetrics let logger: Logger - let latestBlocksDataProvider: LatestBlocksDataProvider } extension BlockScannerImpl: BlockScanner { diff --git a/Sources/ZcashLightClientKit/ClosureSynchronizer.swift b/Sources/ZcashLightClientKit/ClosureSynchronizer.swift index 0ef93852b..610019efb 100644 --- a/Sources/ZcashLightClientKit/ClosureSynchronizer.swift +++ b/Sources/ZcashLightClientKit/ClosureSynchronizer.swift @@ -50,7 +50,6 @@ public protocol ClosureSynchronizer { completion: @escaping (Result) -> Void ) - func pendingTransactions(completion: @escaping ([ZcashTransaction.Overview]) -> Void) func clearedTransactions(completion: @escaping ([ZcashTransaction.Overview]) -> Void) func sentTranscations(completion: @escaping ([ZcashTransaction.Overview]) -> Void) func receivedTransactions(completion: @escaping ([ZcashTransaction.Overview]) -> Void) diff --git a/Sources/ZcashLightClientKit/CombineSynchronizer.swift b/Sources/ZcashLightClientKit/CombineSynchronizer.swift index 7db6f455a..fb9bb47cd 100644 --- a/Sources/ZcashLightClientKit/CombineSynchronizer.swift +++ b/Sources/ZcashLightClientKit/CombineSynchronizer.swift @@ -48,7 +48,6 @@ public protocol CombineSynchronizer { ) -> SinglePublisher var allTransactions: SinglePublisher<[ZcashTransaction.Overview], Never> { get } - var pendingTransactions: SinglePublisher<[ZcashTransaction.Overview], Never> { get } var sentTransactions: SinglePublisher<[ZcashTransaction.Overview], Never> { get } var receivedTransactions: SinglePublisher<[ZcashTransaction.Overview], Never> { get } @@ -58,8 +57,6 @@ public protocol CombineSynchronizer { func getRecipients(for transaction: ZcashTransaction.Overview) -> SinglePublisher<[TransactionRecipient], Never> - func allPendingTransactions() -> SinglePublisher<[ZcashTransaction.Overview], Error> - func allTransactions(from transaction: ZcashTransaction.Overview, limit: Int) -> SinglePublisher<[ZcashTransaction.Overview], Error> func latestHeight() -> SinglePublisher diff --git a/Sources/ZcashLightClientKit/DAO/BlockDao.swift b/Sources/ZcashLightClientKit/DAO/BlockDao.swift deleted file mode 100644 index 40ec196f5..000000000 --- a/Sources/ZcashLightClientKit/DAO/BlockDao.swift +++ /dev/null @@ -1,195 +0,0 @@ -// -// BlockDao.swift -// ZcashLightClientKit -// -// Created by Francisco Gindre on 10/16/19. -// Copyright © 2019 Electric Coin Company. All rights reserved. -// - -import Foundation -import SQLite - -protocol BlockDao { - func latestBlockHeight() throws -> BlockHeight - func latestBlock() throws -> Block? - func block(at height: BlockHeight) throws -> Block? -} - -struct Block: Codable { - enum CodingKeys: String, CodingKey { - case height - case hash - case time - case saplingTree = "sapling_tree" - } - - enum TableStructure { - static let height = Expression(Block.CodingKeys.height.rawValue) - static let hash = Expression(Block.CodingKeys.hash.rawValue) - static let time = Expression(Block.CodingKeys.time.rawValue) - static let saplingTree = Expression(Block.CodingKeys.saplingTree.rawValue) - } - - let height: BlockHeight - let hash: Data - let time: Int - let saplingTree: Data - - static let table = Table("blocks") -} - -struct VTransaction: Codable { - enum CodingKeys: String, CodingKey { - case accountId = "account_id" - case idTx = "id_tx" - case minedHeight = "mined_height" - case txIndex = "tx_index" - case txId = "txid" - case expiryHeight = "expiry_height" - case raw = "raw" - case accountBalanceDelta = "account_balance_delta" - case feePaid = "fee_paid" - case expiredUnmined = "expired_unmined" - case hasChange = "has_change" - case sentNoteCount = "sent_note_count" - case recievedNoteCount = "received_note_count" - case memoCount = "memo_count" - case blockTime = "block_time" - } - - enum TableStructure { - static let accountId = Expression(VTransaction.CodingKeys.accountId.rawValue) - static let idTx = Expression(VTransaction.CodingKeys.idTx.rawValue) - static let minedHeight = Expression(VTransaction.CodingKeys.minedHeight.rawValue) - static let txIndex = Expression(VTransaction.CodingKeys.txIndex.rawValue) - static let txId = Expression(VTransaction.CodingKeys.txId.rawValue) - static let expiryHeight = Expression(VTransaction.CodingKeys.expiryHeight.rawValue) - static let raw = Expression(VTransaction.CodingKeys.raw.rawValue) - static let accountBalanceDelta = Expression(VTransaction.CodingKeys.accountBalanceDelta.rawValue) - static let feePaid = Expression(VTransaction.CodingKeys.feePaid.rawValue) - static let expiredUnmined = Expression(VTransaction.CodingKeys.expiredUnmined.rawValue) - static let hasChange = Expression(VTransaction.CodingKeys.hasChange.rawValue) - static let sentNoteCount = Expression(VTransaction.CodingKeys.sentNoteCount.rawValue) - static let recievedNoteCount = Expression(VTransaction.CodingKeys.recievedNoteCount.rawValue) - static let memoCount = Expression(VTransaction.CodingKeys.memoCount.rawValue) - static let blockTime = Expression(VTransaction.CodingKeys.blockTime.rawValue) - } - - let accountId: Int - let idTx: Int - let minedHeight: Int - let txIndex: Int - let txId: Data - let expiryHeight: Int? - let raw: Data? - let accountBalanceDelta: Int - let feePaid: Int? - let expiredUnmined: Int - let hasChange: Bool - let sentNoteCount: Int - let recievedNoteCount: Int - let memoCount: Int - let blockTime: Int - - static let table = Table("v_transactions") -} - -class BlockSQLDAO: BlockDao { - let dbProvider: ConnectionProvider - let table: Table - let height = Expression("height") - - let minedHeight = Expression("mined_height") - let raw = Expression("raw") - - init(dbProvider: ConnectionProvider) { - self.dbProvider = dbProvider - self.table = Table("Blocks") - } - - /// - Throws: - /// - `blockDAOCantDecode` if block data loaded from DB can't be decoded to `Block` object. - /// - `blockDAOBlock` if sqlite query to load block metadata failed. - func block(at height: BlockHeight) throws -> Block? { - do { - return try dbProvider - .connection() - .prepare(Block.table.filter(Block.TableStructure.height == height).limit(1)) - .map { - do { - return try $0.decode() - } catch { - throw ZcashError.blockDAOCantDecode(error) - } - } - .first - } catch { - if let error = error as? ZcashError { - throw error - } else { - throw ZcashError.blockDAOBlock(error) - } - } - } - - /// - Throws: `blockDAOLatestBlockHeight` if sqlite to fetch height fails. - func latestBlockHeight() throws -> BlockHeight { - do { - return try dbProvider.connection().scalar(table.select(height.max)) ?? BlockHeight.empty() - } catch { - throw ZcashError.blockDAOLatestBlockHeight(error) - } - } - - func latestBlock() throws -> Block? { - do { - return try dbProvider - .connection() - .prepare(Block.table.order(height.desc).limit(1)) - .map { - do { - return try $0.decode() - } catch { - throw ZcashError.blockDAOLatestBlockCantDecode(error) - } - } - .first - } catch { - if let error = error as? ZcashError { - throw error - } else { - throw ZcashError.blockDAOLatestBlock(error) - } - } - } - - func firstUnenhancedHeight(in range: CompactBlockRange? = nil) throws -> BlockHeight? { - do { - return try dbProvider - .connection() - .prepare( - VTransaction.table - .order(minedHeight.asc) - .filter(raw == nil) - .limit(1) - ) - .map { - do { - let vTransaction: VTransaction = try $0.decode() - return vTransaction.minedHeight - } catch { - throw ZcashError.blockDAOFirstUnenhancedCantDecode(error) - } - } - .first - } catch { - throw ZcashError.blockDAOFirstUnenhancedHeight(error) - } - } -} - -extension BlockSQLDAO: BlockRepository { - func lastScannedBlockHeight() -> BlockHeight { - (try? self.latestBlockHeight()) ?? BlockHeight.empty() - } -} diff --git a/Sources/ZcashLightClientKit/DAO/TransactionDao.swift b/Sources/ZcashLightClientKit/DAO/TransactionDao.swift index 176d0a2aa..b3d7e74f4 100644 --- a/Sources/ZcashLightClientKit/DAO/TransactionDao.swift +++ b/Sources/ZcashLightClientKit/DAO/TransactionDao.swift @@ -16,14 +16,12 @@ class TransactionSQLDAO: TransactionRepository { let dbProvider: ConnectionProvider - private let blockDao: BlockSQLDAO private let transactionsView = View("v_transactions") private let txOutputsView = View("v_tx_outputs") private let traceClosure: ((String) -> Void)? init(dbProvider: ConnectionProvider, traceClosure: ((String) -> Void)? = nil) { self.dbProvider = dbProvider - self.blockDao = BlockSQLDAO(dbProvider: dbProvider) self.traceClosure = traceClosure } @@ -37,22 +35,6 @@ class TransactionSQLDAO: TransactionRepository { dbProvider.close() } - func blockForHeight(_ height: BlockHeight) async throws -> Block? { - try blockDao.block(at: height) - } - - func lastScannedHeight() async throws -> BlockHeight { - try blockDao.latestBlockHeight() - } - - func lastScannedBlock() async throws -> Block? { - try blockDao.latestBlock() - } - - func firstUnenhancedHeight() throws -> BlockHeight? { - try blockDao.firstUnenhancedHeight() - } - func isInitialized() async throws -> Bool { true } diff --git a/Sources/ZcashLightClientKit/Initializer.swift b/Sources/ZcashLightClientKit/Initializer.swift index 5fcef01ee..6c1fa9b3f 100644 --- a/Sources/ZcashLightClientKit/Initializer.swift +++ b/Sources/ZcashLightClientKit/Initializer.swift @@ -126,7 +126,6 @@ public class Initializer { let network: ZcashNetwork let logger: Logger let rustBackend: ZcashRustBackendWelding - let syncAlgorithm: SyncAlgorithm /// The effective birthday of the wallet based on the height provided when initializing and the checkpoints available on this SDK. /// @@ -166,7 +165,6 @@ public class Initializer { outputParamsURL: URL, saplingParamsSourceURL: SaplingParamsSourceURL, alias: ZcashSynchronizerAlias = .default, - syncAlgorithm: SyncAlgorithm = .linear, loggingPolicy: LoggingPolicy = .default(.debug), enableBackendTracing: Bool = false ) { @@ -199,7 +197,6 @@ public class Initializer { saplingParamsSourceURL: saplingParamsSourceURL, alias: alias, urlsParsingError: parsingError, - syncAlgorithm: syncAlgorithm, loggingPolicy: loggingPolicy ) } @@ -260,7 +257,6 @@ public class Initializer { saplingParamsSourceURL: SaplingParamsSourceURL, alias: ZcashSynchronizerAlias, urlsParsingError: ZcashError?, - syncAlgorithm: SyncAlgorithm = .linear, loggingPolicy: LoggingPolicy = .default(.debug) ) { self.container = container @@ -288,7 +284,6 @@ public class Initializer { self.walletBirthday = Checkpoint.birthday(with: 0, network: network).height self.urlsParsingError = urlsParsingError self.logger = container.resolve(Logger.self) - self.syncAlgorithm = syncAlgorithm } private static func makeLightWalletServiceFactory(endpoint: LightWalletEndpoint) -> LightWalletServiceFactory { diff --git a/Sources/ZcashLightClientKit/Providers/LatestBlocksDataProvider.swift b/Sources/ZcashLightClientKit/Providers/LatestBlocksDataProvider.swift index 1c0b15e84..e831b9355 100644 --- a/Sources/ZcashLightClientKit/Providers/LatestBlocksDataProvider.swift +++ b/Sources/ZcashLightClientKit/Providers/LatestBlocksDataProvider.swift @@ -8,47 +8,36 @@ import Foundation protocol LatestBlocksDataProvider { - var latestScannedHeight: BlockHeight { get async } - var latestScannedTime: TimeInterval { get async } + var fullyScannedHeight: BlockHeight { get async } + var maxScannedHeight: BlockHeight { get async } var latestBlockHeight: BlockHeight { get async } var walletBirthday: BlockHeight { get async } - var firstUnenhancedHeight: BlockHeight? { get async } func updateScannedData() async func updateBlockData() async - func updateUnenhancedData() async func updateWalletBirthday(_ walletBirthday: BlockHeight) async - func updateLatestScannedHeight(_ latestScannedHeight: BlockHeight) async - func updateLatestScannedTime(_ latestScannedTime: TimeInterval) async } actor LatestBlocksDataProviderImpl: LatestBlocksDataProvider { let service: LightWalletService - let transactionRepository: TransactionRepository + let rustBackend: ZcashRustBackendWelding // Valid values are stored here after Synchronizer's `prepare` is called. - private(set) var latestScannedHeight: BlockHeight = .zero - private(set) var latestScannedTime: TimeInterval = 0.0 - private(set) var firstUnenhancedHeight: BlockHeight? + private(set) var fullyScannedHeight: BlockHeight = .zero + private(set) var maxScannedHeight: BlockHeight = .zero // Valid value is stored here after block processor's `nextState` is called. private(set) var latestBlockHeight: BlockHeight = .zero // Valid values are stored here after Synchronizer's `prepare` is called. private(set) var walletBirthday: BlockHeight = .zero - init(service: LightWalletService, transactionRepository: TransactionRepository) { + init(service: LightWalletService, rustBackend: ZcashRustBackendWelding) { self.service = service - self.transactionRepository = transactionRepository + self.rustBackend = rustBackend } - /// Call of this function is potentially dangerous and can result in `database lock` errors. - /// Typical use is outside of a sync process. Example: Synchronizer's prepare function, call there is a safe one. - /// The update of `latestScannedHeight` and `latestScannedTime` during the syncing is done via - /// appropriate `updateX()` methods inside `BlockScanner` so `transactionRepository` is omitted. func updateScannedData() async { - latestScannedHeight = (try? await transactionRepository.lastScannedHeight()) ?? walletBirthday - if let time = try? await transactionRepository.blockForHeight(latestScannedHeight)?.time { - latestScannedTime = TimeInterval(time) - } + fullyScannedHeight = (try? await rustBackend.fullyScannedHeight()) ?? walletBirthday + maxScannedHeight = (try? await rustBackend.maxScannedHeight()) ?? walletBirthday } func updateBlockData() async { @@ -58,19 +47,7 @@ actor LatestBlocksDataProviderImpl: LatestBlocksDataProvider { } } - func updateUnenhancedData() async { - firstUnenhancedHeight = try? transactionRepository.firstUnenhancedHeight() - } - func updateWalletBirthday(_ walletBirthday: BlockHeight) async { self.walletBirthday = walletBirthday } - - func updateLatestScannedHeight(_ latestScannedHeight: BlockHeight) async { - self.latestScannedHeight = latestScannedHeight - } - - func updateLatestScannedTime(_ latestScannedTime: TimeInterval) async { - self.latestScannedTime = latestScannedTime - } } diff --git a/Sources/ZcashLightClientKit/Repository/TransactionRepository.swift b/Sources/ZcashLightClientKit/Repository/TransactionRepository.swift index bdfc41b47..0e18703b0 100644 --- a/Sources/ZcashLightClientKit/Repository/TransactionRepository.swift +++ b/Sources/ZcashLightClientKit/Repository/TransactionRepository.swift @@ -11,10 +11,10 @@ protocol TransactionRepository { func closeDBConnection() func countAll() async throws -> Int func countUnmined() async throws -> Int - func blockForHeight(_ height: BlockHeight) async throws -> Block? - func lastScannedHeight() async throws -> BlockHeight - func lastScannedBlock() async throws -> Block? - func firstUnenhancedHeight() throws -> BlockHeight? +// func blockForHeight(_ height: BlockHeight) async throws -> Block? +// func lastScannedHeight() async throws -> BlockHeight +// func lastScannedBlock() async throws -> Block? +// func firstUnenhancedHeight() throws -> BlockHeight? func isInitialized() async throws -> Bool func find(id: Int) async throws -> ZcashTransaction.Overview func find(rawID: Data) async throws -> ZcashTransaction.Overview diff --git a/Sources/ZcashLightClientKit/Synchronizer.swift b/Sources/ZcashLightClientKit/Synchronizer.swift index 0bc0108e7..c56151583 100644 --- a/Sources/ZcashLightClientKit/Synchronizer.swift +++ b/Sources/ZcashLightClientKit/Synchronizer.swift @@ -52,9 +52,7 @@ public struct SynchronizerState: Equatable { shieldedBalance: .zero, transparentBalance: .zero, internalSyncStatus: .unprepared, - latestScannedHeight: .zero, - latestBlockHeight: .zero, - latestScannedTime: 0 + latestBlockHeight: .zero ) } @@ -63,9 +61,7 @@ public struct SynchronizerState: Equatable { shieldedBalance: WalletBalance, transparentBalance: WalletBalance, internalSyncStatus: InternalSyncStatus, - latestScannedHeight: BlockHeight, - latestBlockHeight: BlockHeight, - latestScannedTime: TimeInterval + latestBlockHeight: BlockHeight ) { self.syncSessionID = syncSessionID self.shieldedBalance = shieldedBalance @@ -112,9 +108,6 @@ public protocol Synchronizer: AnyObject { /// An object that when enabled collects mertrics from the synchronizer var metrics: SDKMetrics { get } - - /// Default algorithm used to sync the stored wallet with the blockchain. - var syncAlgorithm: SyncAlgorithm { get } /// Initialize the wallet. The ZIP-32 seed bytes can optionally be passed to perform /// database migrations. most of the times the seed won't be needed. If they do and are @@ -193,9 +186,6 @@ public protocol Synchronizer: AnyObject { shieldingThreshold: Zatoshi ) async throws -> ZcashTransaction.Overview - /// all outbound pending transactions that have been sent but are awaiting confirmations - var pendingTransactions: [ZcashTransaction.Overview] { get async } - /// all the transactions that are on the blockchain var transactions: [ZcashTransaction.Overview] { get async } @@ -236,10 +226,6 @@ public protocol Synchronizer: AnyObject { /// - Returns: an array with the given Transactions or an empty array func allTransactions(from transaction: ZcashTransaction.Overview, limit: Int) async throws -> [ZcashTransaction.Overview] - /// Fetch all pending transactions - /// - Returns: an array of transactions which are considered pending confirmation. can be empty - func allPendingTransactions() async throws -> [ZcashTransaction.Overview] - /// Returns the latest block height from the provided Lightwallet endpoint func latestHeight() async throws -> BlockHeight @@ -421,15 +407,6 @@ enum InternalSyncStatus: Equatable { } } -/// Algorithm used to sync the sdk with the blockchain -public enum SyncAlgorithm: Equatable { - /// Linear sync processes the unsynced blocks in a linear way up to the chain tip - case linear - /// Spend before Sync processes the unsynced blocks non-lineary, in prioritised ranges relevant to the stored wallet. - /// Note: This feature is in development (alpha version) so use carefully. - case spendBeforeSync -} - /// Kind of transactions handled by a Synchronizer public enum TransactionKind { case sent diff --git a/Sources/ZcashLightClientKit/Synchronizer/ClosureSDKSynchronizer.swift b/Sources/ZcashLightClientKit/Synchronizer/ClosureSDKSynchronizer.swift index 2ac033083..72e368740 100644 --- a/Sources/ZcashLightClientKit/Synchronizer/ClosureSDKSynchronizer.swift +++ b/Sources/ZcashLightClientKit/Synchronizer/ClosureSDKSynchronizer.swift @@ -92,12 +92,6 @@ extension ClosureSDKSynchronizer: ClosureSynchronizer { } } - public func pendingTransactions(completion: @escaping ([ZcashTransaction.Overview]) -> Void) { - AsyncToClosureGateway.executeAction(completion) { - await self.synchronizer.pendingTransactions - } - } - public func clearedTransactions(completion: @escaping ([ZcashTransaction.Overview]) -> Void) { AsyncToClosureGateway.executeAction(completion) { await self.synchronizer.transactions diff --git a/Sources/ZcashLightClientKit/Synchronizer/CombineSDKSynchronizer.swift b/Sources/ZcashLightClientKit/Synchronizer/CombineSDKSynchronizer.swift index e9bcf4962..b17ab359a 100644 --- a/Sources/ZcashLightClientKit/Synchronizer/CombineSDKSynchronizer.swift +++ b/Sources/ZcashLightClientKit/Synchronizer/CombineSDKSynchronizer.swift @@ -89,12 +89,6 @@ extension CombineSDKSynchronizer: CombineSynchronizer { } } - public var pendingTransactions: AnyPublisher<[ZcashTransaction.Overview], Never> { - AsyncToCombineGateway.executeAction() { - await self.synchronizer.pendingTransactions - } - } - public var allTransactions: SinglePublisher<[ZcashTransaction.Overview], Never> { AsyncToCombineGateway.executeAction() { await self.synchronizer.transactions @@ -127,12 +121,6 @@ extension CombineSDKSynchronizer: CombineSynchronizer { } } - public func allPendingTransactions() -> AnyPublisher<[ZcashTransaction.Overview], Error> { - AsyncToCombineGateway.executeThrowingAction() { - try await self.synchronizer.allPendingTransactions() - } - } - public func allTransactions(from transaction: ZcashTransaction.Overview, limit: Int) -> SinglePublisher<[ZcashTransaction.Overview], Error> { AsyncToCombineGateway.executeThrowingAction() { try await self.synchronizer.allTransactions(from: transaction, limit: limit) diff --git a/Sources/ZcashLightClientKit/Synchronizer/Dependencies.swift b/Sources/ZcashLightClientKit/Synchronizer/Dependencies.swift index 9e3b40c2f..c7bd01b3c 100644 --- a/Sources/ZcashLightClientKit/Synchronizer/Dependencies.swift +++ b/Sources/ZcashLightClientKit/Synchronizer/Dependencies.swift @@ -80,9 +80,9 @@ enum Dependencies { container.register(type: LatestBlocksDataProvider.self, isSingleton: true) { di in let service = di.resolve(LightWalletService.self) - let transactionRepository = di.resolve(TransactionRepository.self) + let rustBackend = di.resolve(ZcashRustBackendWelding.self) - return LatestBlocksDataProviderImpl(service: service, transactionRepository: transactionRepository) + return LatestBlocksDataProviderImpl(service: service, rustBackend: rustBackend) } container.register(type: SyncSessionIDGenerator.self, isSingleton: false) { _ in @@ -120,7 +120,6 @@ enum Dependencies { let transactionRepository = di.resolve(TransactionRepository.self) let metrics = di.resolve(SDKMetrics.self) let logger = di.resolve(Logger.self) - let latestBlocksDataProvider = di.resolve(LatestBlocksDataProvider.self) let blockScannerConfig = BlockScannerConfig( networkType: config.network.networkType, @@ -132,8 +131,7 @@ enum Dependencies { rustBackend: rustBackend, transactionRepository: transactionRepository, metrics: metrics, - logger: logger, - latestBlocksDataProvider: latestBlocksDataProvider + logger: logger ) } diff --git a/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift b/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift index 03f3f4887..224941365 100644 --- a/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift +++ b/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift @@ -24,8 +24,6 @@ public class SDKSynchronizer: Synchronizer { public let metrics: SDKMetrics public let logger: Logger - public var syncAlgorithm: SyncAlgorithm = .linear - private var requestedSyncAlgorithm: SyncAlgorithm? // Don't read this variable directly. Use `status` instead. And don't update this variable directly use `updateStatus()` methods instead. private var underlyingStatus: GenericActor @@ -89,7 +87,6 @@ public class SDKSynchronizer: Synchronizer { self.syncSession = SyncSession(.nullID) self.syncSessionTicker = syncSessionTicker self.latestBlocksDataProvider = initializer.container.resolve(LatestBlocksDataProvider.self) - self.syncAlgorithm = initializer.syncAlgorithm initializer.lightWalletService.connectionStateChange = { [weak self] oldState, newState in self?.connectivityStateChanged(oldState: oldState, newState: newState) @@ -313,8 +310,8 @@ public class SDKSynchronizer: Synchronizer { let accountIndex = Int(spendingKey.account) let tBalance = try await self.getTransparentBalance(accountIndex: accountIndex) - // Verify that at least there are funds for the fee. Ideally this logic will be improved by the shielding wallet. - guard tBalance.verified >= self.network.constants.defaultFee(for: await self.latestBlocksDataProvider.latestScannedHeight) else { + // Verify that at least there are funds for the fee. Ideally this logic will be improved by the shielding wallet. + guard tBalance.verified >= self.network.constants.defaultFee(for: await self.latestBlocksDataProvider.maxScannedHeight) else { throw ZcashError.synchronizerShieldFundsInsuficientTransparentFunds } @@ -367,12 +364,6 @@ public class SDKSynchronizer: Synchronizer { try await transactionRepository.findReceived(offset: 0, limit: Int.max) } - public func allPendingTransactions() async throws -> [ZcashTransaction.Overview] { - let latestScannedHeight = try await transactionRepository.lastScannedHeight() - - return try await transactionRepository.findPendingTransactions(latestHeight: latestScannedHeight, offset: 0, limit: .max) - } - public func allTransactions() async throws -> [ZcashTransaction.Overview] { return try await transactionRepository.find(offset: 0, limit: Int.max, kind: .all) } @@ -556,9 +547,7 @@ public class SDKSynchronizer: Synchronizer { ), transparentBalance: (try? await blockProcessor.getTransparentBalance(accountIndex: 0)) ?? .zero, internalSyncStatus: status, - latestScannedHeight: latestBlocksDataProvider.latestScannedHeight, - latestBlockHeight: latestBlocksDataProvider.latestBlockHeight, - latestScannedTime: latestBlocksDataProvider.latestScannedTime + latestBlockHeight: latestBlocksDataProvider.latestBlockHeight ) } @@ -622,12 +611,6 @@ extension SDKSynchronizer { (try? await allReceivedTransactions()) ?? [] } } - - public var pendingTransactions: [ZcashTransaction.Overview] { - get async { - (try? await allPendingTransactions()) ?? [] - } - } } extension InternalSyncStatus { diff --git a/Tests/OfflineTests/ClosureSynchronizerOfflineTests.swift b/Tests/OfflineTests/ClosureSynchronizerOfflineTests.swift index ee4d1493f..cbec4762f 100644 --- a/Tests/OfflineTests/ClosureSynchronizerOfflineTests.swift +++ b/Tests/OfflineTests/ClosureSynchronizerOfflineTests.swift @@ -408,20 +408,6 @@ class ClosureSynchronizerOfflineTests: XCTestCase { wait(for: [expectation], timeout: 0.5) } - func testPendingTransactionsSucceed() { - synchronizerMock.underlyingPendingTransactions = [data.pendingTransactionEntity] - - let expectation = XCTestExpectation() - - synchronizer.pendingTransactions() { transactions in - XCTAssertEqual(transactions.count, 1) - XCTAssertEqual(transactions[0].id, self.data.pendingTransactionEntity.id) - expectation.fulfill() - } - - wait(for: [expectation], timeout: 0.5) - } - func testClearedTransactionsSucceed() { synchronizerMock.underlyingTransactions = [data.clearedTransaction] diff --git a/Tests/OfflineTests/CombineSynchronizerOfflineTests.swift b/Tests/OfflineTests/CombineSynchronizerOfflineTests.swift index 64038894f..e019798b1 100644 --- a/Tests/OfflineTests/CombineSynchronizerOfflineTests.swift +++ b/Tests/OfflineTests/CombineSynchronizerOfflineTests.swift @@ -430,30 +430,6 @@ class CombineSynchronizerOfflineTests: XCTestCase { wait(for: [expectation], timeout: 0.5) } - func testPendingTransactionsSucceed() { - synchronizerMock.underlyingPendingTransactions = [data.pendingTransactionEntity] - - let expectation = XCTestExpectation() - - synchronizer.pendingTransactions - .sink( - receiveCompletion: { result in - switch result { - case .finished: - expectation.fulfill() - case let .failure(error): - XCTFail("Unpected failure with error: \(error)") - } - }, - receiveValue: { value in - XCTAssertEqual(value.map { $0.id }, [self.data.pendingTransactionEntity.id]) - } - ) - .store(in: &cancellables) - - wait(for: [expectation], timeout: 0.5) - } - func testClearedTransactionsSucceed() { synchronizerMock.underlyingTransactions = [data.clearedTransaction] diff --git a/Tests/OfflineTests/CompactBlockProcessorActions/ActionContextStateTests.swift b/Tests/OfflineTests/CompactBlockProcessorActions/ActionContextStateTests.swift index 8e81e7ce3..83dfa35a5 100644 --- a/Tests/OfflineTests/CompactBlockProcessorActions/ActionContextStateTests.swift +++ b/Tests/OfflineTests/CompactBlockProcessorActions/ActionContextStateTests.swift @@ -32,15 +32,4 @@ final class ActionContextStateTests: XCTestCase { XCTFail("syncContext.prevState is not expected to be nil.") } } - - func testDefaultSyncAlgorith() async throws { - let syncContext = ActionContextImpl(state: .idle) - - let preferredSyncAlgorithm = await syncContext.preferredSyncAlgorithm - - XCTAssertTrue( - preferredSyncAlgorithm == .linear, - "ActionContext default preferredSyncAlgorithm is expected to be .linear but received \(preferredSyncAlgorithm)" - ) - } } diff --git a/Tests/OfflineTests/CompactBlockProcessorActions/ClearAlreadyScannedBlocksActionTests.swift b/Tests/OfflineTests/CompactBlockProcessorActions/ClearAlreadyScannedBlocksActionTests.swift index aee9ca505..fd3038ddc 100644 --- a/Tests/OfflineTests/CompactBlockProcessorActions/ClearAlreadyScannedBlocksActionTests.swift +++ b/Tests/OfflineTests/CompactBlockProcessorActions/ClearAlreadyScannedBlocksActionTests.swift @@ -57,7 +57,6 @@ final class ClearAlreadyScannedBlocksActionTests: ZcashTestCase { let transactionRepositoryMock = TransactionRepositoryMock() compactBlockRepositoryMock.clearUpToClosure = { _ in } - transactionRepositoryMock.lastScannedHeightReturnValue = 1 mockContainer.mock(type: CompactBlockRepository.self, isSingleton: true) { _ in compactBlockRepositoryMock } mockContainer.mock(type: TransactionRepository.self, isSingleton: true) { _ in transactionRepositoryMock } diff --git a/Tests/OfflineTests/CompactBlockProcessorActions/ClearCacheActionTests.swift b/Tests/OfflineTests/CompactBlockProcessorActions/ClearCacheActionTests.swift index b789cf30c..280bf49b3 100644 --- a/Tests/OfflineTests/CompactBlockProcessorActions/ClearCacheActionTests.swift +++ b/Tests/OfflineTests/CompactBlockProcessorActions/ClearCacheActionTests.swift @@ -30,90 +30,6 @@ final class ClearCacheActionTests: ZcashTestCase { } } - func testClearCacheAction_FinishedLinear() async throws { - let compactBlockRepositoryMock = CompactBlockRepositoryMock() - - let clearCacheAction = setupAction(compactBlockRepositoryMock) - - do { - let context = ActionContextMock.default() - context.underlyingPreferredSyncAlgorithm = .linear - - let nextContext = try await clearCacheAction.run(with: context) { _ in } - - XCTAssertTrue(compactBlockRepositoryMock.clearCalled, "storage.clear() is expected to be called.") - - let acResult = nextContext.checkStateIs(.finished) - XCTAssertTrue(acResult == .true, "Check of state failed with '\(acResult)'") - } catch { - XCTFail("testClearCacheAction_FinishedLinear is not expected to fail. \(error)") - } - } - - func testClearCacheAction_PreferredSbSNoSupportedSyncAlgorithm() async throws { - let compactBlockRepositoryMock = CompactBlockRepositoryMock() - - let clearCacheAction = setupAction(compactBlockRepositoryMock) - - do { - let context = ActionContextMock.default() - context.underlyingPreferredSyncAlgorithm = .spendBeforeSync - - _ = try await clearCacheAction.run(with: context) { _ in } - } catch ZcashError.compactBlockProcessorSupportedSyncAlgorithm { - XCTAssertTrue(compactBlockRepositoryMock.clearCalled, "storage.clear() is expected to be called.") - } catch { - XCTFail( - """ - testClearCacheAction_PredferedSbSNoSupportedSyncAlgorithm is expected to fail - with ZcashError.compactBlockProcessorSupportedSyncAlgorithm but received \(error) - """ - ) - } - } - - func testClearCacheAction_PreferredSbSSupportedSyncAlgorithmLinear() async throws { - let compactBlockRepositoryMock = CompactBlockRepositoryMock() - - let clearCacheAction = setupAction(compactBlockRepositoryMock) - - do { - let context = ActionContextMock.default() - context.underlyingPreferredSyncAlgorithm = .spendBeforeSync - context.supportedSyncAlgorithm = .linear - - let nextContext = try await clearCacheAction.run(with: context) { _ in } - - XCTAssertTrue(compactBlockRepositoryMock.clearCalled, "storage.clear() is expected to be called.") - - let acResult = nextContext.checkStateIs(.finished) - XCTAssertTrue(acResult == .true, "Check of state failed with '\(acResult)'") - } catch { - XCTFail("testClearCacheAction_FinishedLinear is not expected to fail. \(error)") - } - } - - func testClearCacheAction_PreferedSbSSupportedSyncAlgorithmSbS() async throws { - let compactBlockRepositoryMock = CompactBlockRepositoryMock() - - let clearCacheAction = setupAction(compactBlockRepositoryMock) - - do { - let context = ActionContextMock.default() - context.underlyingPreferredSyncAlgorithm = .spendBeforeSync - context.supportedSyncAlgorithm = .spendBeforeSync - - let nextContext = try await clearCacheAction.run(with: context) { _ in } - - XCTAssertTrue(compactBlockRepositoryMock.clearCalled, "storage.clear() is expected to be called.") - - let acResult = nextContext.checkStateIs(.processSuggestedScanRanges) - XCTAssertTrue(acResult == .true, "Check of state failed with '\(acResult)'") - } catch { - XCTFail("testClearCacheAction_FinishedLinear is not expected to fail. \(error)") - } - } - private func setupAction( _ compactBlockRepositoryMock: CompactBlockRepositoryMock = CompactBlockRepositoryMock() ) -> ClearCacheAction { diff --git a/Tests/OfflineTests/CompactBlockProcessorActions/ComputeSyncControlDataActionTests.swift b/Tests/OfflineTests/CompactBlockProcessorActions/ComputeSyncControlDataActionTests.swift deleted file mode 100644 index 40620ec5b..000000000 --- a/Tests/OfflineTests/CompactBlockProcessorActions/ComputeSyncControlDataActionTests.swift +++ /dev/null @@ -1,166 +0,0 @@ -// -// ComputeSyncControlDataActionTests.swift -// -// -// Created by Lukáš Korba on 22.05.2023. -// - -import XCTest -@testable import TestUtils -@testable import ZcashLightClientKit - -final class ComputeSyncControlDataActionTests: ZcashTestCase { - var underlyingDownloadRange: CompactBlockRange? - var underlyingScanRange: CompactBlockRange? - - override func setUp() { - super.setUp() - - underlyingDownloadRange = nil - underlyingScanRange = nil - } - - func testComputeSyncControlDataAction_finishProcessingCase() async throws { - let blockDownloaderServiceMock = BlockDownloaderServiceMock() - let latestBlocksDataProviderMock = LatestBlocksDataProviderMock() - let loggerMock = LoggerMock() - - let computeSyncControlDataAction = setupDefaultMocksAndReturnAction( - blockDownloaderServiceMock, - latestBlocksDataProviderMock, - loggerMock - ) - latestBlocksDataProviderMock.underlyingLatestBlockHeight = 123 - latestBlocksDataProviderMock.underlyingLatestScannedHeight = 123 - - let syncContext = await setupActionContext() - - do { - let nextContext = try await computeSyncControlDataAction.run(with: syncContext) { _ in } - - checkLatestBlocksDataProvider(latestBlocksDataProviderMock) - checkActionContext(nextContext, expectedNextState: .finished) - - XCTAssertTrue(loggerMock.debugFileFunctionLineCalled, "logger.debug() is expected to be called.") - } catch { - XCTFail("testComputeSyncControlDataAction_finishProcessingCase is not expected to fail. \(error)") - } - } - - func testComputeSyncControlDataAction_DownloadCase() async throws { - let blockDownloaderServiceMock = BlockDownloaderServiceMock() - let latestBlocksDataProviderMock = LatestBlocksDataProviderMock() - let loggerMock = LoggerMock() - - let computeSyncControlDataAction = setupDefaultMocksAndReturnAction( - blockDownloaderServiceMock, - latestBlocksDataProviderMock, - loggerMock - ) - latestBlocksDataProviderMock.underlyingLatestBlockHeight = 1234 - latestBlocksDataProviderMock.underlyingLatestScannedHeight = 123 - - let syncContext = await setupActionContext() - - do { - let nextContext = try await computeSyncControlDataAction.run(with: syncContext) { _ in } - - checkLatestBlocksDataProvider(latestBlocksDataProviderMock) - checkActionContext(nextContext, expectedNextState: .download) - - XCTAssertTrue(loggerMock.debugFileFunctionLineCalled, "logger.debug() is expected to be called.") - } catch { - XCTFail("testComputeSyncControlDataAction_checksBeforeSyncCase is not expected to fail. \(error)") - } - } - - private func setupActionContext() async -> ActionContextMock { - let syncContext = ActionContextMock() - - syncContext.updateLastScannedHeightClosure = { _ in } - syncContext.updateLastDownloadedHeightClosure = { _ in } - syncContext.updateSyncControlDataClosure = { _ in } - syncContext.updateTotalProgressRangeClosure = { _ in } - syncContext.updateStateClosure = { _ in } - syncContext.underlyingState = .idle - - return syncContext - } - - private func setupDefaultMocksAndReturnAction( - _ blockDownloaderServiceMock: BlockDownloaderServiceMock = BlockDownloaderServiceMock(), - _ latestBlocksDataProviderMock: LatestBlocksDataProviderMock = LatestBlocksDataProviderMock(), - _ loggerMock: LoggerMock = LoggerMock() - ) -> ComputeSyncControlDataAction { - latestBlocksDataProviderMock.updateScannedDataClosure = { } - latestBlocksDataProviderMock.updateBlockDataClosure = { } - latestBlocksDataProviderMock.updateUnenhancedDataClosure = { } - loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in } - - return setupAction( - blockDownloaderServiceMock, - latestBlocksDataProviderMock, - loggerMock - ) - } - - private func setupAction( - _ blockDownloaderServiceMock: BlockDownloaderServiceMock = BlockDownloaderServiceMock(), - _ latestBlocksDataProviderMock: LatestBlocksDataProviderMock = LatestBlocksDataProviderMock(), - _ loggerMock: LoggerMock = LoggerMock() - ) -> ComputeSyncControlDataAction { - mockContainer.mock(type: BlockDownloaderService.self, isSingleton: true) { _ in blockDownloaderServiceMock } - mockContainer.mock(type: LatestBlocksDataProvider.self, isSingleton: true) { _ in latestBlocksDataProviderMock } - mockContainer.mock(type: Logger.self, isSingleton: true) { _ in loggerMock } - - let config: CompactBlockProcessor.Configuration = .standard( - for: ZcashNetworkBuilder.network(for: .testnet), walletBirthday: 0 - ) - - return ComputeSyncControlDataAction( - container: mockContainer, - configProvider: CompactBlockProcessor.ConfigProvider(config: config) - ) - } - - private func checkLatestBlocksDataProvider(_ latestBlocksDataProviderMock: LatestBlocksDataProviderMock) { - XCTAssertTrue( - latestBlocksDataProviderMock.updateScannedDataCalled, - "latestBlocksDataProvider.updateScannedData() is expected to be called." - ) - XCTAssertTrue( - latestBlocksDataProviderMock.updateBlockDataCalled, - "latestBlocksDataProvider.updateBlockData() is expected to be called." - ) - XCTAssertTrue( - latestBlocksDataProviderMock.updateUnenhancedDataCalled, - "latestBlocksDataProvider.updateUnenhancedData() is expected to be called." - ) - } - - private func checkActionContext(_ actionContext: ActionContext, expectedNextState: CBPState) { - guard let nextContextMock = actionContext as? ActionContextMock else { - return XCTFail("Result of run(with:) is expected to be an ActionContextMock") - } - - XCTAssertTrue(nextContextMock.updateStateCallsCount == 1) - XCTAssertTrue(nextContextMock.updateStateReceivedState == expectedNextState) - - XCTAssertTrue( - nextContextMock.updateLastScannedHeightCallsCount == 1, - "actionContext.update(lastScannedHeight:) is expected to be called." - ) - XCTAssertTrue( - nextContextMock.updateLastDownloadedHeightCallsCount == 1, - "actionContext.update(lastDownloadedHeight:) is expected to be called." - ) - XCTAssertTrue( - nextContextMock.updateSyncControlDataCallsCount == 1, - "actionContext.update(syncControlData:) is expected to be called." - ) - XCTAssertTrue( - nextContextMock.updateTotalProgressRangeCallsCount == 1, - "actionContext.update(totalProgressRange:) is expected to be called." - ) - } -} diff --git a/Tests/OfflineTests/CompactBlockProcessorActions/DownloadActionTests.swift b/Tests/OfflineTests/CompactBlockProcessorActions/DownloadActionTests.swift index a18f6c7ae..1b2ab9700 100644 --- a/Tests/OfflineTests/CompactBlockProcessorActions/DownloadActionTests.swift +++ b/Tests/OfflineTests/CompactBlockProcessorActions/DownloadActionTests.swift @@ -17,7 +17,6 @@ final class DownloadActionTests: ZcashTestCase { let blockDownloaderMock = BlockDownloaderMock() let transactionRepositoryMock = TransactionRepositoryMock() - transactionRepositoryMock.lastScannedHeightReturnValue = 1000 blockDownloaderMock.setSyncRangeBatchSizeClosure = { _, _ in } blockDownloaderMock.setDownloadLimitClosure = { _ in } blockDownloaderMock.startDownloadMaxBlockBufferSizeClosure = { _ in } @@ -120,10 +119,6 @@ final class DownloadActionTests: ZcashTestCase { do { let nextContext = try await downloadAction.run(with: syncContext) { _ in } - XCTAssertFalse( - transactionRepositoryMock.lastScannedHeightCalled, - "transactionRepository.lastScannedHeight() is not expected to be called." - ) XCTAssertFalse(blockDownloaderMock.setSyncRangeBatchSizeCalled, "downloader.setSyncRange() is not expected to be called.") XCTAssertFalse(blockDownloaderMock.setDownloadLimitCalled, "downloader.setDownloadLimit() is not expected to be called.") XCTAssertFalse(blockDownloaderMock.startDownloadMaxBlockBufferSizeCalled, "downloader.startDownload() is not expected to be called.") diff --git a/Tests/OfflineTests/CompactBlockProcessorActions/MigrateLegacyCacheDBActionTests.swift b/Tests/OfflineTests/CompactBlockProcessorActions/MigrateLegacyCacheDBActionTests.swift index c2fd8d501..127e589a1 100644 --- a/Tests/OfflineTests/CompactBlockProcessorActions/MigrateLegacyCacheDBActionTests.swift +++ b/Tests/OfflineTests/CompactBlockProcessorActions/MigrateLegacyCacheDBActionTests.swift @@ -38,10 +38,6 @@ final class MigrateLegacyCacheDBActionTests: ZcashTestCase { let nextContext = try await migrateLegacyCacheDBAction.run(with: context) { _ in } XCTAssertFalse(compactBlockRepositoryMock.createCalled, "storage.create() is not expected to be called.") - XCTAssertFalse( - transactionRepositoryMock.lastScannedHeightCalled, - "transactionRepository.lastScannedHeight() is not expected to be called." - ) XCTAssertFalse(zcashFileManagerMock.isReadableFileAtPathCalled, "fileManager.isReadableFile() is not expected to be called.") XCTAssertFalse(zcashFileManagerMock.removeItemAtCalled, "fileManager.removeItem() is not expected to be called.") @@ -71,10 +67,6 @@ final class MigrateLegacyCacheDBActionTests: ZcashTestCase { XCTFail("testMigrateLegacyCacheDBAction_noFsBlockCacheRoot is expected to fail.") } catch ZcashError.compactBlockProcessorCacheDbMigrationFsCacheMigrationFailedSameURL { XCTAssertFalse(compactBlockRepositoryMock.createCalled, "storage.create() is not expected to be called.") - XCTAssertFalse( - transactionRepositoryMock.lastScannedHeightCalled, - "transactionRepository.lastScannedHeight() is not expected to be called." - ) XCTAssertFalse(zcashFileManagerMock.isReadableFileAtPathCalled, "fileManager.isReadableFile() is not expected to be called.") XCTAssertFalse(zcashFileManagerMock.removeItemAtCalled, "fileManager.removeItem() is not expected to be called.") } catch { @@ -107,10 +99,6 @@ final class MigrateLegacyCacheDBActionTests: ZcashTestCase { let nextContext = try await migrateLegacyCacheDBAction.run(with: context) { _ in } XCTAssertFalse(compactBlockRepositoryMock.createCalled, "storage.create() is not expected to be called.") - XCTAssertFalse( - transactionRepositoryMock.lastScannedHeightCalled, - "transactionRepository.lastScannedHeight() is not expected to be called." - ) XCTAssertFalse(zcashFileManagerMock.isReadableFileAtPathCalled, "fileManager.isReadableFile() is not expected to be called.") XCTAssertFalse(zcashFileManagerMock.removeItemAtCalled, "fileManager.removeItem() is not expected to be called.") @@ -143,10 +131,6 @@ final class MigrateLegacyCacheDBActionTests: ZcashTestCase { let nextContext = try await migrateLegacyCacheDBAction.run(with: context) { _ in } XCTAssertFalse(compactBlockRepositoryMock.createCalled, "storage.create() is not expected to be called.") - XCTAssertFalse( - transactionRepositoryMock.lastScannedHeightCalled, - "transactionRepository.lastScannedHeight() is not expected to be called." - ) XCTAssertTrue(zcashFileManagerMock.isReadableFileAtPathCalled, "fileManager.isReadableFile() is expected to be called.") XCTAssertFalse(zcashFileManagerMock.removeItemAtCalled, "fileManager.removeItem() is not expected to be called.") @@ -180,10 +164,6 @@ final class MigrateLegacyCacheDBActionTests: ZcashTestCase { _ = try await migrateLegacyCacheDBAction.run(with: context) { _ in } } catch ZcashError.compactBlockProcessorCacheDbMigrationFailedToDeleteLegacyDb { XCTAssertFalse(compactBlockRepositoryMock.createCalled, "storage.create() is not expected to be called.") - XCTAssertFalse( - transactionRepositoryMock.lastScannedHeightCalled, - "transactionRepository.lastScannedHeight() is not expected to be called." - ) XCTAssertTrue(zcashFileManagerMock.isReadableFileAtPathCalled, "fileManager.isReadableFile() is expected to be called.") XCTAssertTrue(zcashFileManagerMock.removeItemAtCalled, "fileManager.removeItem() is expected to be called.") } catch { diff --git a/Tests/OfflineTests/CompactBlockProcessorActions/SaplingParamsActionTests.swift b/Tests/OfflineTests/CompactBlockProcessorActions/SaplingParamsActionTests.swift index c0bdfb147..a1ba054fc 100644 --- a/Tests/OfflineTests/CompactBlockProcessorActions/SaplingParamsActionTests.swift +++ b/Tests/OfflineTests/CompactBlockProcessorActions/SaplingParamsActionTests.swift @@ -10,28 +10,6 @@ import XCTest @testable import ZcashLightClientKit final class SaplingParamsActionTests: ZcashTestCase { - func testSaplingParamsAction_NextAction_linearSync() async throws { - let loggerMock = LoggerMock() - let saplingParametersHandlerMock = SaplingParametersHandlerMock() - - let saplingParamsActionAction = setupAction(saplingParametersHandlerMock, loggerMock) - - do { - let context = ActionContextMock.default() - context.underlyingPreferredSyncAlgorithm = .linear - - let nextContext = try await saplingParamsActionAction.run(with: context) { _ in } - - XCTAssertTrue(loggerMock.debugFileFunctionLineCalled, "logger.debug(...) is expected to be called.") - XCTAssertTrue(saplingParametersHandlerMock.handleIfNeededCalled, "saplingParametersHandler.handleIfNeeded() is expected to be called.") - - let acResult = nextContext.checkStateIs(.computeSyncControlData) - XCTAssertTrue(acResult == .true, "Check of state failed with '\(acResult)'") - } catch { - XCTFail("testSaplingParamsAction_NextAction is not expected to fail. \(error)") - } - } - func testSaplingParamsAction_NextAction_SpendBeforeSync() async throws { let loggerMock = LoggerMock() let saplingParametersHandlerMock = SaplingParametersHandlerMock() @@ -40,7 +18,6 @@ final class SaplingParamsActionTests: ZcashTestCase { do { let context = ActionContextMock.default() - context.underlyingPreferredSyncAlgorithm = .spendBeforeSync let nextContext = try await saplingParamsActionAction.run(with: context) { _ in } diff --git a/Tests/OfflineTests/CompactBlockProcessorActions/UpdateSubtreeRootsActionTests.swift b/Tests/OfflineTests/CompactBlockProcessorActions/UpdateSubtreeRootsActionTests.swift index c6d124f05..e249c918b 100644 --- a/Tests/OfflineTests/CompactBlockProcessorActions/UpdateSubtreeRootsActionTests.swift +++ b/Tests/OfflineTests/CompactBlockProcessorActions/UpdateSubtreeRootsActionTests.swift @@ -23,55 +23,11 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase { underlyingSaplingActivationHeight = nil underlyingConsensusBranchID = "c2d6d0b4" } - - func testUpdateSubtreeRootsAction_getSubtreeRootsFailure() async throws { - let loggerMock = LoggerMock() - - loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in } - loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in } - - let tupple = setupAction(loggerMock) - let updateSubtreeRootsActionAction = tupple.action - tupple.serviceMock.getSubtreeRootsClosure = { _ in - AsyncThrowingStream { continuation in continuation.finish(throwing: ZcashError.serviceSubmitFailed(.invalidBlock)) } - } - - do { - let context = ActionContextMock.default() - context.updateSupportedSyncAlgorithmClosure = { _ in } - - let nextContext = try await updateSubtreeRootsActionAction.run(with: context) { _ in } - - if let nextContextMock = nextContext as? ActionContextMock { - if let supportedSyncAlgorithm = nextContextMock.updateSupportedSyncAlgorithmReceivedSupportedSyncAlgorithm { - XCTAssertTrue( - supportedSyncAlgorithm == .linear, - "supportedSyncAlgorithm is expected to be .linear but received \(supportedSyncAlgorithm)" - ) - } else { - XCTFail("`nextContextMock` supportedSyncAlgorithm not set") - } - } else { - XCTFail("`nextContext` is not the ActionContextMock") - } - - if let debugArguments = loggerMock.debugFileFunctionLineReceivedArguments { - XCTAssertTrue(debugArguments.message.contains("getSubtreeRoots failed with error")) - } else { - XCTFail("`debugArguments` unavailable.") - } - - let acResult = nextContext.checkStateIs(.computeSyncControlData) - XCTAssertTrue(acResult == .true, "Check of state failed with '\(acResult)'") - } catch { - XCTFail("testUpdateSubtreeRootsAction_getSubtreeRootsFailure is not expected to fail. \(error)") - } - } func testUpdateSubtreeRootsAction_getSubtreeRootsTimeout() async throws { let loggerMock = LoggerMock() - loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in } + loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in } let tupple = setupAction(loggerMock) let updateSubtreeRootsActionAction = tupple.action @@ -81,7 +37,6 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase { do { let context = ActionContextMock.default() - context.updateSupportedSyncAlgorithmClosure = { _ in } _ = try await updateSubtreeRootsActionAction.run(with: context) { _ in } XCTFail("The test is expected to fail but continued.") @@ -98,51 +53,11 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase { } } - func testUpdateSubtreeRootsAction_getSubtreeRootsEmpty() async throws { - let loggerMock = LoggerMock() - - loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in } - loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in } - - let tupple = setupAction(loggerMock) - let updateSubtreeRootsActionAction = tupple.action - tupple.serviceMock.getSubtreeRootsClosure = { _ in - AsyncThrowingStream { continuation in continuation.finish() } - } - - do { - let context = ActionContextMock.default() - context.updateSupportedSyncAlgorithmClosure = { _ in } - - let nextContext = try await updateSubtreeRootsActionAction.run(with: context) { _ in } - - if let nextContextMock = nextContext as? ActionContextMock { - if let supportedSyncAlgorithm = nextContextMock.updateSupportedSyncAlgorithmReceivedSupportedSyncAlgorithm { - XCTAssertTrue( - supportedSyncAlgorithm == .linear, - "supportedSyncAlgorithm is expected to be .linear but received \(supportedSyncAlgorithm)" - ) - } else { - XCTFail("`nextContextMock` supportedSyncAlgorithm not set") - } - } else { - XCTFail("`nextContext` is not the ActionContextMock") - } - - XCTAssertFalse(loggerMock.debugFileFunctionLineCalled, "logger.debug() is not expected to be called.") - - let acResult = nextContext.checkStateIs(.computeSyncControlData) - XCTAssertTrue(acResult == .true, "Check of state failed with '\(acResult)'") - } catch { - XCTFail("testUpdateSubtreeRootsAction_getSubtreeRootsEmpty is not expected to fail. \(error)") - } - } - func testUpdateSubtreeRootsAction_RootsAvailablePutRootsSuccess() async throws { let loggerMock = LoggerMock() - loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in } - loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in } + loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in } + loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in } let tupple = setupAction(loggerMock) let updateSubtreeRootsActionAction = tupple.action @@ -152,27 +67,13 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase { continuation.finish() } } - await tupple.rustBackendMock.setPutSaplingSubtreeRootsStartIndexRootsClosure( { _, _ in } ) + await tupple.rustBackendMock.setPutSaplingSubtreeRootsStartIndexRootsClosure({ _, _ in }) do { let context = ActionContextMock.default() - context.updateSupportedSyncAlgorithmClosure = { _ in } let nextContext = try await updateSubtreeRootsActionAction.run(with: context) { _ in } - if let nextContextMock = nextContext as? ActionContextMock { - if let supportedSyncAlgorithm = nextContextMock.updateSupportedSyncAlgorithmReceivedSupportedSyncAlgorithm { - XCTAssertTrue( - supportedSyncAlgorithm == .spendBeforeSync, - "supportedSyncAlgorithm is expected to be .linear but received \(supportedSyncAlgorithm)" - ) - } else { - XCTFail("`nextContextMock` supportedSyncAlgorithm not set") - } - } else { - XCTFail("`nextContext` is not the ActionContextMock") - } - XCTAssertFalse(loggerMock.debugFileFunctionLineCalled, "logger.debug() is not expected to be called.") let acResult = nextContext.checkStateIs(.updateChainTip) @@ -185,8 +86,8 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase { func testUpdateSubtreeRootsAction_RootsAvailablePutRootsFailure() async throws { let loggerMock = LoggerMock() - loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in } - loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in } + loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in } + loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in } let tupple = setupAction(loggerMock) let updateSubtreeRootsActionAction = tupple.action @@ -200,7 +101,6 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase { do { let context = ActionContextMock.default() - context.updateSupportedSyncAlgorithmClosure = { _ in } _ = try await updateSubtreeRootsActionAction.run(with: context) { _ in } @@ -247,7 +147,8 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase { action: UpdateSubtreeRootsAction( container: mockContainer, - configProvider: CompactBlockProcessor.ConfigProvider(config: config)), + configProvider: CompactBlockProcessor.ConfigProvider(config: config) + ), serviceMock: serviceMock, rustBackendMock: rustBackendMock ) diff --git a/Tests/OfflineTests/SynchronizerOfflineTests.swift b/Tests/OfflineTests/SynchronizerOfflineTests.swift index 7628dfe94..78c4e9091 100644 --- a/Tests/OfflineTests/SynchronizerOfflineTests.swift +++ b/Tests/OfflineTests/SynchronizerOfflineTests.swift @@ -468,25 +468,6 @@ class SynchronizerOfflineTests: ZcashTestCase { XCTFail("Syncing is expected to be 100% (1.0) but received \(data).") } } - - func testLinearIsSetAsDefault() async throws { - let databases = TemporaryDbBuilder.build() - let initializer = Initializer( - cacheDbURL: nil, - fsBlockDbRoot: databases.fsCacheDbRoot, - generalStorageURL: testGeneralStorageDirectory, - dataDbURL: databases.dataDB, - endpoint: LightWalletEndpoint(address: "lightwalletd.electriccoin.co", port: 9067, secure: true), - network: ZcashNetworkBuilder.network(for: .mainnet), - spendParamsURL: try __spendParamsURL(), - outputParamsURL: try __outputParamsURL(), - saplingParamsSourceURL: SaplingParamsSourceURL.tests, - alias: .default, - loggingPolicy: .default(.debug) - ) - - XCTAssertTrue(initializer.syncAlgorithm == .linear, "Spend before Sync is a beta feature so linear syncing is set to default.") - } func synchronizerState(for internalSyncStatus: InternalSyncStatus) -> SynchronizerState { SynchronizerState( @@ -494,9 +475,7 @@ class SynchronizerOfflineTests: ZcashTestCase { shieldedBalance: .zero, transparentBalance: .zero, internalSyncStatus: internalSyncStatus, - latestScannedHeight: .zero, - latestBlockHeight: .zero, - latestScannedTime: 0 + latestBlockHeight: .zero ) } } diff --git a/Tests/OfflineTests/TransactionRepositoryTests.swift b/Tests/OfflineTests/TransactionRepositoryTests.swift index 441884802..4167fa1f4 100644 --- a/Tests/OfflineTests/TransactionRepositoryTests.swift +++ b/Tests/OfflineTests/TransactionRepositoryTests.swift @@ -35,16 +35,6 @@ class TransactionRepositoryTests: XCTestCase { XCTAssertEqual(count, 0) } - func testBlockForHeight() async throws { - let block = try await self.transactionRepository.blockForHeight(663150) - XCTAssertEqual(block?.height, 663150) - } - - func testLastScannedHeight() async throws { - let height = try await self.transactionRepository.lastScannedHeight() - XCTAssertEqual(height, 665000) - } - func testFindInRange() async throws { let transactions = try await self.transactionRepository.find(in: 663218...663974, limit: 3, kind: .received) XCTAssertEqual(transactions.count, 3) diff --git a/Tests/TestUtils/MockTransactionRepository.swift b/Tests/TestUtils/MockTransactionRepository.swift index b5b5fe41e..3581144c6 100644 --- a/Tests/TestUtils/MockTransactionRepository.swift +++ b/Tests/TestUtils/MockTransactionRepository.swift @@ -95,10 +95,6 @@ extension MockTransactionRepository: TransactionRepository { unminedCount } - func blockForHeight(_ height: BlockHeight) throws -> Block? { - nil - } - func findBy(id: Int) throws -> ZcashTransaction.Overview? { transactions.first(where: { $0.id == id }) } @@ -111,10 +107,6 @@ extension MockTransactionRepository: TransactionRepository { scannedHeight } - func lastScannedBlock() throws -> Block? { - nil - } - func firstUnenhancedHeight() throws -> ZcashLightClientKit.BlockHeight? { nil } diff --git a/Tests/TestUtils/Sourcery/GeneratedMocks/AutoMockable.generated.swift b/Tests/TestUtils/Sourcery/GeneratedMocks/AutoMockable.generated.swift index e9fd77c1c..31840f18e 100644 --- a/Tests/TestUtils/Sourcery/GeneratedMocks/AutoMockable.generated.swift +++ b/Tests/TestUtils/Sourcery/GeneratedMocks/AutoMockable.generated.swift @@ -22,11 +22,6 @@ class ActionContextMock: ActionContext { get { return underlyingSyncControlData } } var underlyingSyncControlData: SyncControlData! - var preferredSyncAlgorithm: SyncAlgorithm { - get { return underlyingPreferredSyncAlgorithm } - } - var underlyingPreferredSyncAlgorithm: SyncAlgorithm! - var supportedSyncAlgorithm: SyncAlgorithm? var requestedRewindHeight: BlockHeight? var totalProgressRange: CompactBlockRange { get { return underlyingTotalProgressRange } @@ -165,21 +160,6 @@ class ActionContextMock: ActionContext { // MARK: - update - var updateSupportedSyncAlgorithmCallsCount = 0 - var updateSupportedSyncAlgorithmCalled: Bool { - return updateSupportedSyncAlgorithmCallsCount > 0 - } - var updateSupportedSyncAlgorithmReceivedSupportedSyncAlgorithm: SyncAlgorithm? - var updateSupportedSyncAlgorithmClosure: ((SyncAlgorithm) async -> Void)? - - func update(supportedSyncAlgorithm: SyncAlgorithm) async { - updateSupportedSyncAlgorithmCallsCount += 1 - updateSupportedSyncAlgorithmReceivedSupportedSyncAlgorithm = supportedSyncAlgorithm - await updateSupportedSyncAlgorithmClosure!(supportedSyncAlgorithm) - } - - // MARK: - update - var updateRequestedRewindHeightCallsCount = 0 var updateRequestedRewindHeightCalled: Bool { return updateRequestedRewindHeightCallsCount > 0 @@ -693,14 +673,14 @@ class LatestBlocksDataProviderMock: LatestBlocksDataProvider { init( ) { } - var latestScannedHeight: BlockHeight { - get { return underlyingLatestScannedHeight } + var fullyScannedHeight: BlockHeight { + get { return underlyingFullyScannedHeight } } - var underlyingLatestScannedHeight: BlockHeight! - var latestScannedTime: TimeInterval { - get { return underlyingLatestScannedTime } + var underlyingFullyScannedHeight: BlockHeight! + var maxScannedHeight: BlockHeight { + get { return underlyingMaxScannedHeight } } - var underlyingLatestScannedTime: TimeInterval! + var underlyingMaxScannedHeight: BlockHeight! var latestBlockHeight: BlockHeight { get { return underlyingLatestBlockHeight } } @@ -709,7 +689,6 @@ class LatestBlocksDataProviderMock: LatestBlocksDataProvider { get { return underlyingWalletBirthday } } var underlyingWalletBirthday: BlockHeight! - var firstUnenhancedHeight: BlockHeight? // MARK: - updateScannedData @@ -737,19 +716,6 @@ class LatestBlocksDataProviderMock: LatestBlocksDataProvider { await updateBlockDataClosure!() } - // MARK: - updateUnenhancedData - - var updateUnenhancedDataCallsCount = 0 - var updateUnenhancedDataCalled: Bool { - return updateUnenhancedDataCallsCount > 0 - } - var updateUnenhancedDataClosure: (() async -> Void)? - - func updateUnenhancedData() async { - updateUnenhancedDataCallsCount += 1 - await updateUnenhancedDataClosure!() - } - // MARK: - updateWalletBirthday var updateWalletBirthdayCallsCount = 0 @@ -765,36 +731,6 @@ class LatestBlocksDataProviderMock: LatestBlocksDataProvider { await updateWalletBirthdayClosure!(walletBirthday) } - // MARK: - updateLatestScannedHeight - - var updateLatestScannedHeightCallsCount = 0 - var updateLatestScannedHeightCalled: Bool { - return updateLatestScannedHeightCallsCount > 0 - } - var updateLatestScannedHeightReceivedLatestScannedHeight: BlockHeight? - var updateLatestScannedHeightClosure: ((BlockHeight) async -> Void)? - - func updateLatestScannedHeight(_ latestScannedHeight: BlockHeight) async { - updateLatestScannedHeightCallsCount += 1 - updateLatestScannedHeightReceivedLatestScannedHeight = latestScannedHeight - await updateLatestScannedHeightClosure!(latestScannedHeight) - } - - // MARK: - updateLatestScannedTime - - var updateLatestScannedTimeCallsCount = 0 - var updateLatestScannedTimeCalled: Bool { - return updateLatestScannedTimeCallsCount > 0 - } - var updateLatestScannedTimeReceivedLatestScannedTime: TimeInterval? - var updateLatestScannedTimeClosure: ((TimeInterval) async -> Void)? - - func updateLatestScannedTime(_ latestScannedTime: TimeInterval) async { - updateLatestScannedTimeCallsCount += 1 - updateLatestScannedTimeReceivedLatestScannedTime = latestScannedTime - await updateLatestScannedTimeClosure!(latestScannedTime) - } - } class LightWalletServiceMock: LightWalletService { @@ -1234,14 +1170,6 @@ class SynchronizerMock: Synchronizer { get { return underlyingMetrics } } var underlyingMetrics: SDKMetrics! - var syncAlgorithm: SyncAlgorithm { - get { return underlyingSyncAlgorithm } - } - var underlyingSyncAlgorithm: SyncAlgorithm! - var pendingTransactions: [ZcashTransaction.Overview] { - get async { return underlyingPendingTransactions } - } - var underlyingPendingTransactions: [ZcashTransaction.Overview] = [] var transactions: [ZcashTransaction.Overview] { get async { return underlyingTransactions } } @@ -1539,28 +1467,6 @@ class SynchronizerMock: Synchronizer { } } - // MARK: - allPendingTransactions - - var allPendingTransactionsThrowableError: Error? - var allPendingTransactionsCallsCount = 0 - var allPendingTransactionsCalled: Bool { - return allPendingTransactionsCallsCount > 0 - } - var allPendingTransactionsReturnValue: [ZcashTransaction.Overview]! - var allPendingTransactionsClosure: (() async throws -> [ZcashTransaction.Overview])? - - func allPendingTransactions() async throws -> [ZcashTransaction.Overview] { - if let error = allPendingTransactionsThrowableError { - throw error - } - allPendingTransactionsCallsCount += 1 - if let closure = allPendingTransactionsClosure { - return try await closure() - } else { - return allPendingTransactionsReturnValue - } - } - // MARK: - latestHeight var latestHeightThrowableError: Error? @@ -1782,96 +1688,6 @@ class TransactionRepositoryMock: TransactionRepository { } } - // MARK: - blockForHeight - - var blockForHeightThrowableError: Error? - var blockForHeightCallsCount = 0 - var blockForHeightCalled: Bool { - return blockForHeightCallsCount > 0 - } - var blockForHeightReceivedHeight: BlockHeight? - var blockForHeightReturnValue: Block? - var blockForHeightClosure: ((BlockHeight) async throws -> Block?)? - - func blockForHeight(_ height: BlockHeight) async throws -> Block? { - if let error = blockForHeightThrowableError { - throw error - } - blockForHeightCallsCount += 1 - blockForHeightReceivedHeight = height - if let closure = blockForHeightClosure { - return try await closure(height) - } else { - return blockForHeightReturnValue - } - } - - // MARK: - lastScannedHeight - - var lastScannedHeightThrowableError: Error? - var lastScannedHeightCallsCount = 0 - var lastScannedHeightCalled: Bool { - return lastScannedHeightCallsCount > 0 - } - var lastScannedHeightReturnValue: BlockHeight! - var lastScannedHeightClosure: (() async throws -> BlockHeight)? - - func lastScannedHeight() async throws -> BlockHeight { - if let error = lastScannedHeightThrowableError { - throw error - } - lastScannedHeightCallsCount += 1 - if let closure = lastScannedHeightClosure { - return try await closure() - } else { - return lastScannedHeightReturnValue - } - } - - // MARK: - lastScannedBlock - - var lastScannedBlockThrowableError: Error? - var lastScannedBlockCallsCount = 0 - var lastScannedBlockCalled: Bool { - return lastScannedBlockCallsCount > 0 - } - var lastScannedBlockReturnValue: Block? - var lastScannedBlockClosure: (() async throws -> Block?)? - - func lastScannedBlock() async throws -> Block? { - if let error = lastScannedBlockThrowableError { - throw error - } - lastScannedBlockCallsCount += 1 - if let closure = lastScannedBlockClosure { - return try await closure() - } else { - return lastScannedBlockReturnValue - } - } - - // MARK: - firstUnenhancedHeight - - var firstUnenhancedHeightThrowableError: Error? - var firstUnenhancedHeightCallsCount = 0 - var firstUnenhancedHeightCalled: Bool { - return firstUnenhancedHeightCallsCount > 0 - } - var firstUnenhancedHeightReturnValue: BlockHeight? - var firstUnenhancedHeightClosure: (() throws -> BlockHeight?)? - - func firstUnenhancedHeight() throws -> BlockHeight? { - if let error = firstUnenhancedHeightThrowableError { - throw error - } - firstUnenhancedHeightCallsCount += 1 - if let closure = firstUnenhancedHeightClosure { - return try closure() - } else { - return firstUnenhancedHeightReturnValue - } - } - // MARK: - isInitialized var isInitializedThrowableError: Error? diff --git a/Tests/TestUtils/Stubs.swift b/Tests/TestUtils/Stubs.swift index 4063dfd04..725259512 100644 --- a/Tests/TestUtils/Stubs.swift +++ b/Tests/TestUtils/Stubs.swift @@ -172,9 +172,7 @@ extension SynchronizerState { shieldedBalance: WalletBalance(verified: Zatoshi(100), total: Zatoshi(200)), transparentBalance: WalletBalance(verified: Zatoshi(200), total: Zatoshi(300)), internalSyncStatus: .syncing(0), - latestScannedHeight: 111111, - latestBlockHeight: 222222, - latestScannedTime: 12345678 + latestBlockHeight: 222222 ) } }