react-native-zcash 0.6.13 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/android/build.gradle +4 -4
  3. package/android/src/main/assets/co.electriccoin.zcash/checkpoint/mainnet/2470000.json +8 -0
  4. package/android/src/main/assets/co.electriccoin.zcash/checkpoint/mainnet/2480000.json +8 -0
  5. package/android/src/main/java/app/edge/rnzcash/RNZcashModule.kt +51 -9
  6. package/ios/RNZcash.m +8 -0
  7. package/ios/RNZcash.swift +66 -16
  8. package/ios/ZCashLightClientKit/Block/Actions/DownloadAction.swift +1 -1
  9. package/ios/ZCashLightClientKit/Block/Actions/EnhanceAction.swift +3 -1
  10. package/ios/ZCashLightClientKit/Block/Actions/FetchUTXOsAction.swift +1 -1
  11. package/ios/ZCashLightClientKit/Block/Actions/ProcessSuggestedScanRangesAction.swift +11 -2
  12. package/ios/ZCashLightClientKit/Block/Actions/RewindAction.swift +2 -2
  13. package/ios/ZCashLightClientKit/Block/Actions/ScanAction.swift +28 -11
  14. package/ios/ZCashLightClientKit/Block/Actions/UpdateChainTipAction.swift +4 -4
  15. package/ios/ZCashLightClientKit/Block/Actions/UpdateSubtreeRootsAction.swift +36 -7
  16. package/ios/ZCashLightClientKit/Block/Actions/ValidateServerAction.swift +1 -1
  17. package/ios/ZCashLightClientKit/Block/CompactBlockProcessor.swift +93 -51
  18. package/ios/ZCashLightClientKit/Block/Download/BlockDownloader.swift +0 -26
  19. package/ios/ZCashLightClientKit/Block/Enhance/BlockEnhancer.swift +5 -6
  20. package/ios/ZCashLightClientKit/Block/FetchUnspentTxOutputs/UTXOFetcher.swift +1 -11
  21. package/ios/ZCashLightClientKit/Block/SaplingParameters/SaplingParametersHandler.swift +6 -4
  22. package/ios/ZCashLightClientKit/Block/Scan/BlockScanner.swift +10 -12
  23. package/ios/ZCashLightClientKit/Checkpoint/BundleCheckpointSource.swift +38 -0
  24. package/ios/ZCashLightClientKit/Checkpoint/BundleCheckpointURLProvider.swift +40 -0
  25. package/ios/ZCashLightClientKit/{Constants/Checkpoint+Constants.swift → Checkpoint/Checkpoint+helpers.swift} +1 -33
  26. package/ios/ZCashLightClientKit/Checkpoint/CheckpointSource.swift +34 -0
  27. package/ios/ZCashLightClientKit/Checkpoint/CheckpointSourceFactory.swift +14 -0
  28. package/ios/ZCashLightClientKit/ClosureSynchronizer.swift +61 -6
  29. package/ios/ZCashLightClientKit/CombineSynchronizer.swift +63 -4
  30. package/ios/ZCashLightClientKit/Constants/ZcashSDK.swift +4 -0
  31. package/ios/ZCashLightClientKit/DAO/TransactionDao.swift +21 -33
  32. package/ios/ZCashLightClientKit/DAO/UnspentTransactionOutputDao.swift +0 -182
  33. package/ios/ZCashLightClientKit/Entity/AccountEntity.swift +0 -173
  34. package/ios/ZCashLightClientKit/Entity/TransactionEntity.swift +5 -2
  35. package/ios/ZCashLightClientKit/Error/Sourcery/generateErrorCode.sh +1 -1
  36. package/ios/ZCashLightClientKit/Error/ZcashError.swift +53 -1
  37. package/ios/ZCashLightClientKit/Error/ZcashErrorCode.swift +19 -1
  38. package/ios/ZCashLightClientKit/Error/ZcashErrorCodeDefinition.swift +32 -0
  39. package/ios/ZCashLightClientKit/Initializer.swift +8 -17
  40. package/ios/ZCashLightClientKit/Metrics/SDKMetrics.swift +103 -217
  41. package/ios/ZCashLightClientKit/Model/Proposal.swift +45 -0
  42. package/ios/ZCashLightClientKit/Model/ScanSummary.swift +14 -0
  43. package/ios/ZCashLightClientKit/Model/WalletSummary.swift +58 -0
  44. package/ios/ZCashLightClientKit/Model/WalletTypes.swift +0 -16
  45. package/ios/ZCashLightClientKit/Modules/Service/GRPC/LightWalletGRPCService.swift +5 -3
  46. package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/proposal.pb.swift +934 -0
  47. package/ios/ZCashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/proposal.proto +138 -0
  48. package/ios/ZCashLightClientKit/Modules/Service/LightWalletService.swift +2 -4
  49. package/ios/ZCashLightClientKit/Providers/LatestBlocksDataProvider.swift +9 -1
  50. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2272500.json +8 -0
  51. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2275000.json +8 -0
  52. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2277500.json +8 -0
  53. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2282500.json +8 -0
  54. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2285000.json +8 -0
  55. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2287500.json +8 -0
  56. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2292500.json +8 -0
  57. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2295000.json +8 -0
  58. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2297500.json +8 -0
  59. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2302500.json +8 -0
  60. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2305000.json +8 -0
  61. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2307500.json +8 -0
  62. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2312500.json +8 -0
  63. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2315000.json +8 -0
  64. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2317500.json +8 -0
  65. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2322500.json +8 -0
  66. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2325000.json +8 -0
  67. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2327500.json +8 -0
  68. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2332500.json +8 -0
  69. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2335000.json +8 -0
  70. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2337500.json +8 -0
  71. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2342500.json +8 -0
  72. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2345000.json +8 -0
  73. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2347500.json +8 -0
  74. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2352500.json +8 -0
  75. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2355000.json +8 -0
  76. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2357500.json +8 -0
  77. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2362500.json +8 -0
  78. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2365000.json +8 -0
  79. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2367500.json +8 -0
  80. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2372500.json +8 -0
  81. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2375000.json +8 -0
  82. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2377500.json +8 -0
  83. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2382500.json +8 -0
  84. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2385000.json +8 -0
  85. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2387500.json +8 -0
  86. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2392500.json +8 -0
  87. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2395000.json +8 -0
  88. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2397500.json +8 -0
  89. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2402500.json +8 -0
  90. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2405000.json +8 -0
  91. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2407500.json +8 -0
  92. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2412500.json +8 -0
  93. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2415000.json +8 -0
  94. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2417500.json +8 -0
  95. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2422500.json +8 -0
  96. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2425000.json +8 -0
  97. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2427500.json +8 -0
  98. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2432500.json +8 -0
  99. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2435000.json +8 -0
  100. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2437500.json +8 -0
  101. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2442500.json +8 -0
  102. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2445000.json +8 -0
  103. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2447500.json +8 -0
  104. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2452500.json +8 -0
  105. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2455000.json +8 -0
  106. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2457500.json +8 -0
  107. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2462500.json +8 -0
  108. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2465000.json +8 -0
  109. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2467500.json +8 -0
  110. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2470000.json +8 -0
  111. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2472500.json +8 -0
  112. package/ios/ZCashLightClientKit/Resources/checkpoints/mainnet/2480000.json +8 -0
  113. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2560000.json +8 -0
  114. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2570000.json +8 -0
  115. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2580000.json +8 -0
  116. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2590000.json +8 -0
  117. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2600000.json +8 -0
  118. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2610000.json +8 -0
  119. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2620000.json +8 -0
  120. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2630000.json +8 -0
  121. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2640000.json +8 -0
  122. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2650000.json +8 -0
  123. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2660000.json +8 -0
  124. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2670000.json +8 -0
  125. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2680000.json +8 -0
  126. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2690000.json +8 -0
  127. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2700000.json +8 -0
  128. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2710000.json +8 -0
  129. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2720000.json +8 -0
  130. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2730000.json +8 -0
  131. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2740000.json +8 -0
  132. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2750000.json +8 -0
  133. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2760000.json +8 -0
  134. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2770000.json +8 -0
  135. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2780000.json +8 -0
  136. package/ios/ZCashLightClientKit/Resources/checkpoints/testnet/2790000.json +8 -0
  137. package/ios/ZCashLightClientKit/Rust/ZcashKeyDerivationBackend.swift +1 -5
  138. package/ios/ZCashLightClientKit/Rust/ZcashRustBackend.swift +327 -153
  139. package/ios/ZCashLightClientKit/Rust/ZcashRustBackendWelding.swift +78 -36
  140. package/ios/ZCashLightClientKit/Rust/zcashlc.h +1441 -0
  141. package/ios/ZCashLightClientKit/Synchronizer/ClosureSDKSynchronizer.swift +43 -14
  142. package/ios/ZCashLightClientKit/Synchronizer/CombineSDKSynchronizer.swift +52 -14
  143. package/ios/ZCashLightClientKit/Synchronizer/Dependencies.swift +10 -6
  144. package/ios/ZCashLightClientKit/Synchronizer/SDKSynchronizer.swift +220 -70
  145. package/ios/ZCashLightClientKit/Synchronizer.swift +105 -29
  146. package/ios/ZCashLightClientKit/Transaction/TransactionEncoder.swift +61 -32
  147. package/ios/ZCashLightClientKit/Transaction/WalletTransactionEncoder.swift +52 -61
  148. package/ios/ZCashLightClientKit/Utils/DBActor.swift +21 -0
  149. package/ios/ZCashLightClientKit/Utils/LoggingProxy.swift +5 -0
  150. package/ios/ZCashLightClientKit/Utils/OSLogger.swift +71 -14
  151. package/ios/libzcashlc.xcframework/ios-arm64/libzcashlc.a +0 -0
  152. package/ios/libzcashlc.xcframework/ios-arm64_x86_64-simulator/libzcashlc.a +0 -0
  153. package/lib/rnzcash.rn.js +21 -6
  154. package/lib/rnzcash.rn.js.map +1 -1
  155. package/lib/src/react-native.d.ts +2 -1
  156. package/lib/src/types.d.ts +9 -1
  157. package/package.json +1 -1
  158. package/src/react-native.ts +23 -4
  159. package/src/types.ts +10 -1
  160. package/ios/ZCashLightClientKit/Model/ScanProgress.swift +0 -29
  161. package/ios/ZCashLightClientKit/Repository/UnspentTransactionOutputRepository.swift +0 -16
  162. /package/ios/ZCashLightClientKit/{Model → Checkpoint}/Checkpoint.swift +0 -0
@@ -28,18 +28,18 @@ actor CompactBlockProcessor {
28
28
  private let configProvider: ConfigProvider
29
29
  private var afterSyncHooksManager = AfterSyncHooksManager()
30
30
 
31
- private let accountRepository: AccountRepository
32
- let blockDownloaderService: BlockDownloaderService
33
- private let latestBlocksDataProvider: LatestBlocksDataProvider
31
+ var blockDownloaderService: BlockDownloaderService
32
+ private var latestBlocksDataProvider: LatestBlocksDataProvider
34
33
  private let logger: Logger
35
34
  private let metrics: SDKMetrics
36
35
  private let rustBackend: ZcashRustBackendWelding
37
- let service: LightWalletService
36
+ var service: LightWalletService
38
37
  let storage: CompactBlockRepository
39
38
  private let transactionRepository: TransactionRepository
40
39
  private let fileManager: ZcashFileManager
41
40
 
42
41
  private var retryAttempts: Int = 0
42
+ private var serviceFailureRetryAttempts: Int = 0
43
43
  private var backoffTimer: Timer?
44
44
  private var consecutiveChainValidationErrors: Int = 0
45
45
 
@@ -141,20 +141,6 @@ actor CompactBlockProcessor {
141
141
  }
142
142
  }
143
143
 
144
- /// Initializes a CompactBlockProcessor instance
145
- /// - Parameters:
146
- /// - service: concrete implementation of `LightWalletService` protocol
147
- /// - storage: concrete implementation of `CompactBlockRepository` protocol
148
- /// - backend: a class that complies to `ZcashRustBackendWelding`
149
- /// - config: `Configuration` struct for this processor
150
- init(container: DIContainer, config: Configuration) {
151
- self.init(
152
- container: container,
153
- config: config,
154
- accountRepository: AccountRepositoryBuilder.build(dataDbURL: config.dataDb, readOnly: true, logger: container.resolve(Logger.self))
155
- )
156
- }
157
-
158
144
  /// Initializes a CompactBlockProcessor instance from an Initialized object
159
145
  /// - Parameters:
160
146
  /// - initializer: an instance that complies to CompactBlockDownloading protocol
@@ -170,20 +156,23 @@ actor CompactBlockProcessor {
170
156
  saplingParamsSourceURL: initializer.saplingParamsSourceURL,
171
157
  walletBirthdayProvider: walletBirthdayProvider,
172
158
  network: initializer.network
173
- ),
174
- accountRepository: initializer.accountRepository
159
+ )
175
160
  )
176
161
  }
177
162
 
163
+ /// Initializes a CompactBlockProcessor instance
164
+ /// - Parameters:
165
+ /// - service: concrete implementation of `LightWalletService` protocol
166
+ /// - storage: concrete implementation of `CompactBlockRepository` protocol
167
+ /// - backend: a class that complies to `ZcashRustBackendWelding`
168
+ /// - config: `Configuration` struct for this processor
178
169
  init(
179
170
  container: DIContainer,
180
- config: Configuration,
181
- accountRepository: AccountRepository
171
+ config: Configuration
182
172
  ) {
183
173
  Dependencies.setupCompactBlockProcessor(
184
174
  in: container,
185
- config: config,
186
- accountRepository: accountRepository
175
+ config: config
187
176
  )
188
177
 
189
178
  let configProvider = ConfigProvider(config: config)
@@ -199,7 +188,6 @@ actor CompactBlockProcessor {
199
188
  self.storage = container.resolve(CompactBlockRepository.self)
200
189
  self.config = config
201
190
  self.transactionRepository = container.resolve(TransactionRepository.self)
202
- self.accountRepository = accountRepository
203
191
  self.fileManager = container.resolve(ZcashFileManager.self)
204
192
  self.configProvider = configProvider
205
193
  }
@@ -263,6 +251,7 @@ extension CompactBlockProcessor {
263
251
  func start(retry: Bool = false) async {
264
252
  if retry {
265
253
  self.retryAttempts = 0
254
+ self.serviceFailureRetryAttempts = 0
266
255
  self.backoffTimer?.invalidate()
267
256
  self.backoffTimer = nil
268
257
  }
@@ -289,6 +278,7 @@ extension CompactBlockProcessor {
289
278
  self.backoffTimer = nil
290
279
  await stopAllActions()
291
280
  retryAttempts = 0
281
+ serviceFailureRetryAttempts = 0
292
282
  }
293
283
 
294
284
  func latestHeight() async throws -> BlockHeight {
@@ -396,6 +386,8 @@ extension CompactBlockProcessor {
396
386
 
397
387
  try await rewindDownloadBlockAction(to: nil)
398
388
 
389
+ await latestBlocksDataProvider.reset()
390
+
399
391
  await context.completion(nil)
400
392
  } catch {
401
393
  await context.completion(error)
@@ -409,6 +401,52 @@ extension CompactBlockProcessor {
409
401
  }
410
402
  }
411
403
 
404
+ // MARK: - Switch server
405
+
406
+ extension CompactBlockProcessor {
407
+ func updateService(_ container: DIContainer) {
408
+ // LightWalletGRPCService
409
+ let updatedLWDService = container.resolve(LightWalletService.self)
410
+
411
+ (actions[.processSuggestedScanRanges] as? ProcessSuggestedScanRangesAction)?.service = updatedLWDService
412
+ (actions[.updateChainTip] as? UpdateChainTipAction)?.service = updatedLWDService
413
+ (actions[.updateSubtreeRoots] as? UpdateSubtreeRootsAction)?.service = updatedLWDService
414
+ (actions[.validateServer] as? ValidateServerAction)?.service = updatedLWDService
415
+ self.service = updatedLWDService
416
+
417
+ // BlockDownloaderService
418
+ let updatedDownloaderService = container.resolve(BlockDownloaderService.self)
419
+
420
+ (actions[.rewind] as? RewindAction)?.downloaderService = updatedDownloaderService
421
+ self.blockDownloaderService = updatedDownloaderService
422
+
423
+ // LatestBlocksDataProvider
424
+ let updatedLBDProvider = container.resolve(LatestBlocksDataProvider.self)
425
+
426
+ (actions[.scan] as? ScanAction)?.latestBlocksDataProvider = updatedLBDProvider
427
+ (actions[.updateChainTip] as? UpdateChainTipAction)?.latestBlocksDataProvider = updatedLBDProvider
428
+ self.latestBlocksDataProvider = updatedLBDProvider
429
+
430
+ // BlockDownloader
431
+ let updatedBlockDownloader = container.resolve(BlockDownloader.self)
432
+
433
+ (actions[.download] as? DownloadAction)?.downloader = updatedBlockDownloader
434
+ (actions[.updateChainTip] as? UpdateChainTipAction)?.downloader = updatedBlockDownloader
435
+ (actions[.rewind] as? RewindAction)?.downloader = updatedBlockDownloader
436
+ self.blockDownloaderService = updatedDownloaderService
437
+
438
+ // BlockEnhancer
439
+ let updatedEnhancer = container.resolve(BlockEnhancer.self)
440
+
441
+ (actions[.enhance] as? EnhanceAction)?.blockEnhancer = updatedEnhancer
442
+
443
+ // UTXOFetcher
444
+ let updatedUTXOFetcher = container.resolve(UTXOFetcher.self)
445
+
446
+ (actions[.fetchUTXO] as? FetchUTXOsAction)?.utxoFetcher = updatedUTXOFetcher
447
+ }
448
+ }
449
+
412
450
  // MARK: - Events
413
451
 
414
452
  extension CompactBlockProcessor {
@@ -478,6 +516,7 @@ extension CompactBlockProcessor {
478
516
  // swiftlint:disable:next cyclomatic_complexity
479
517
  private func run() async {
480
518
  logger.debug("Starting run")
519
+ metrics.cbpStart()
481
520
  await resetContext()
482
521
 
483
522
  while true {
@@ -513,6 +552,7 @@ extension CompactBlockProcessor {
513
552
  try Task.checkCancellation()
514
553
 
515
554
  // Execute action.
555
+ metrics.actionStart(state)
516
556
  context = try await action.run(with: context) { [weak self] event in
517
557
  await self?.send(event: event)
518
558
  if let progressChanged = await self?.compactBlockProgress.hasProgressUpdated(event), progressChanged {
@@ -528,7 +568,27 @@ extension CompactBlockProcessor {
528
568
  await stopAllActions()
529
569
  logger.error("Sync failed with error: \(error)")
530
570
 
531
- if Task.isCancelled {
571
+ // catching the service errors
572
+ let serviceError: Bool
573
+ switch error {
574
+ case ZcashError.serviceGetInfoFailed, ZcashError.serviceLatestBlockFailed,
575
+ ZcashError.serviceLatestBlockHeightFailed, ZcashError.serviceBlockRangeFailed,
576
+ ZcashError.serviceSubmitFailed, ZcashError.serviceFetchTransactionFailed,
577
+ ZcashError.serviceFetchUTXOsFailed, ZcashError.serviceBlockStreamFailed,
578
+ ZcashError.serviceSubtreeRootsStreamFailed: serviceError = true
579
+ default: serviceError = false
580
+ }
581
+
582
+ if serviceError && self.serviceFailureRetryAttempts < ZcashSDK.serviceFailureRetries {
583
+ // This may be false positive communication error that is usually resolved by retry.
584
+ // We will try to reset the sync and continue but this will we done at most `ZcashSDK.serviceFailureRetries` times.
585
+ logger.error("ServiceError: \(error), retry is available, starting the sync all over again.")
586
+
587
+ self.serviceFailureRetryAttempts += 1
588
+
589
+ // Start sync all over again
590
+ await resetContext()
591
+ } else if Task.isCancelled {
532
592
  logger.info("Processing cancelled.")
533
593
  do {
534
594
  if try await syncTaskWasCancelled() {
@@ -543,13 +603,8 @@ extension CompactBlockProcessor {
543
603
  break
544
604
  }
545
605
  } else {
546
- if await handleSyncFailure(action: action, error: error) {
547
- // Start sync all over again
548
- await resetContext()
549
- } else {
550
- // end the sync loop
551
- break
552
- }
606
+ await handleSyncFailure(action: action, error: error)
607
+ break
553
608
  }
554
609
  }
555
610
  }
@@ -565,15 +620,13 @@ extension CompactBlockProcessor {
565
620
  return try await handleAfterSyncHooks()
566
621
  }
567
622
 
568
- private func handleSyncFailure(action: Action, error: Error) async -> Bool {
623
+ private func handleSyncFailure(action: Action, error: Error) async {
569
624
  if action.removeBlocksCacheWhenFailed {
570
625
  await ifTaskIsNotCanceledClearCompactBlockCache()
571
626
  }
572
627
 
573
628
  logger.error("Sync failed with error: \(error)")
574
629
  await failure(error)
575
-
576
- return false
577
630
  }
578
631
 
579
632
  // swiftlint:disable:next cyclomatic_complexity
@@ -640,6 +693,7 @@ extension CompactBlockProcessor {
640
693
  latestBlockHeightWhenSyncing > 0 && latestBlockHeightWhenSyncing < latestBlockHeight
641
694
 
642
695
  retryAttempts = 0
696
+ serviceFailureRetryAttempts = 0
643
697
  consecutiveChainValidationErrors = 0
644
698
 
645
699
  let lastScannedHeight = await latestBlocksDataProvider.maxScannedHeight
@@ -649,6 +703,9 @@ extension CompactBlockProcessor {
649
703
  await send(event: .finished(lastScannedHeight))
650
704
  await context.update(state: .finished)
651
705
 
706
+ let walletSummary = try? await rustBackend.getWalletSummary()
707
+ await metrics.logCBPOverviewReport(logger, walletSummary: walletSummary)
708
+
652
709
  // If new blocks were mined during previous sync run the sync process again
653
710
  if newerBlocksWereMinedDuringSync {
654
711
  return true
@@ -777,21 +834,6 @@ extension CompactBlockProcessor {
777
834
  func getTransparentAddress(accountIndex: Int) async throws -> TransparentAddress {
778
835
  try await getUnifiedAddress(accountIndex: accountIndex).transparentReceiver()
779
836
  }
780
-
781
- func getTransparentBalance(accountIndex: Int) async throws -> WalletBalance {
782
- guard accountIndex >= 0 else {
783
- throw ZcashError.compactBlockProcessorInvalidAccount
784
- }
785
-
786
- return WalletBalance(
787
- verified: Zatoshi(
788
- try await rustBackend.getVerifiedTransparentBalance(account: Int32(accountIndex))
789
- ),
790
- total: Zatoshi(
791
- try await rustBackend.getTransparentBalance(account: Int32(accountIndex))
792
- )
793
- )
794
- }
795
837
  }
796
838
 
797
839
  extension CompactBlockProcessor {
@@ -195,44 +195,18 @@ actor BlockDownloaderImpl {
195
195
  var buffer: [ZcashCompactBlock] = []
196
196
  logger.debug("Downloading blocks in range: \(range.lowerBound)...\(range.upperBound)")
197
197
 
198
- var startTime = Date()
199
- var counter = 0
200
- var lastDownloadedBlockHeight = -1
201
-
202
- let pushMetrics: (BlockHeight, Date, Date) -> Void = { [metrics] _, startTime, finishTime in
203
- metrics.pushProgressReport(
204
- start: startTime,
205
- end: finishTime,
206
- batchSize: maxBlockBufferSize,
207
- operation: .downloadBlocks
208
- )
209
- }
210
-
211
198
  for _ in stride(from: range.lowerBound, to: range.upperBound + 1, by: 1) {
212
199
  try Task.checkCancellation()
213
200
  guard let block = try await stream.nextBlock() else { break }
214
201
 
215
- counter += 1
216
- lastDownloadedBlockHeight = block.height
217
-
218
202
  buffer.append(block)
219
203
  if buffer.count >= maxBlockBufferSize {
220
- let finishTime = Date()
221
204
  try await storage.write(blocks: buffer)
222
205
  try await blocksBufferWritten(buffer)
223
206
  buffer.removeAll(keepingCapacity: true)
224
-
225
- pushMetrics(block.height, startTime, finishTime)
226
-
227
- counter = 0
228
- startTime = finishTime
229
207
  }
230
208
  }
231
209
 
232
- if counter > 0 {
233
- pushMetrics(lastDownloadedBlockHeight, startTime, Date())
234
- }
235
-
236
210
  try await storage.write(blocks: buffer)
237
211
  try await blocksBufferWritten(buffer)
238
212
  }
@@ -96,6 +96,7 @@ extension BlockEnhancerImpl: BlockEnhancer {
96
96
 
97
97
  guard !transactions.isEmpty else {
98
98
  logger.debug("no transactions detected on range: \(range.lowerBound)...\(range.upperBound)")
99
+ logger.sync("No transactions detected on range: \(range.lowerBound)...\(range.upperBound)")
99
100
  return nil
100
101
  }
101
102
 
@@ -134,12 +135,10 @@ extension BlockEnhancerImpl: BlockEnhancer {
134
135
  }
135
136
  }
136
137
 
137
- metrics.pushProgressReport(
138
- start: startTime,
139
- end: Date(),
140
- batchSize: range.count,
141
- operation: .enhancement
142
- )
138
+ let endTime = Date()
139
+ let logMsg = "Enhanced \(transactions.count) transaction(s) in \(endTime.timeIntervalSince1970 - startTime.timeIntervalSince1970) for range \(range.lowerBound)...\(range.upperBound)"
140
+ logger.sync(logMsg)
141
+ metrics.actionDetail(logMsg, for: .enhance)
143
142
  } catch {
144
143
  logger.error("error enhancing transactions! \(error)")
145
144
  throw error
@@ -23,7 +23,6 @@ protocol UTXOFetcher {
23
23
  }
24
24
 
25
25
  struct UTXOFetcherImpl {
26
- let accountRepository: AccountRepository
27
26
  let blockDownloaderService: BlockDownloaderService
28
27
  let config: UTXOFetcherConfig
29
28
  let rustBackend: ZcashRustBackendWelding
@@ -37,8 +36,7 @@ extension UTXOFetcherImpl: UTXOFetcher {
37
36
  ) async throws -> (inserted: [UnspentTransactionOutputEntity], skipped: [UnspentTransactionOutputEntity]) {
38
37
  try Task.checkCancellation()
39
38
 
40
- let accounts = try accountRepository.getAll()
41
- .map { $0.account }
39
+ let accounts = try await rustBackend.listAccounts()
42
40
 
43
41
  var tAddresses: [TransparentAddress] = []
44
42
  for account in accounts {
@@ -62,7 +60,6 @@ extension UTXOFetcherImpl: UTXOFetcher {
62
60
  var refreshed: [UnspentTransactionOutputEntity] = []
63
61
  var skipped: [UnspentTransactionOutputEntity] = []
64
62
 
65
- let startTime = Date()
66
63
  let all = Float(utxos.count)
67
64
  var counter = Float(0)
68
65
  for utxo in utxos {
@@ -85,13 +82,6 @@ extension UTXOFetcherImpl: UTXOFetcher {
85
82
  }
86
83
  }
87
84
 
88
- metrics.pushProgressReport(
89
- start: startTime,
90
- end: Date(),
91
- batchSize: 1,
92
- operation: .fetchUTXOs
93
- )
94
-
95
85
  let result = (inserted: refreshed, skipped: skipped)
96
86
 
97
87
  if Task.isCancelled {
@@ -1,6 +1,6 @@
1
1
  //
2
- // HandleSaplingParametersIfNeeded.swift
3
- //
2
+ // SaplingParametersHandler.swift
3
+ //
4
4
  //
5
5
  // Created by Lukáš Korba on 23.11.2022.
6
6
  //
@@ -28,11 +28,13 @@ extension SaplingParametersHandlerImpl: SaplingParametersHandler {
28
28
  try Task.checkCancellation()
29
29
 
30
30
  do {
31
- let totalShieldedBalance = try await rustBackend.getBalance(account: Int32(0))
31
+ let totalSaplingBalance =
32
+ try await rustBackend.getWalletSummary()?.accountBalances[0]?.saplingBalance.total().amount
33
+ ?? 0
32
34
  let totalTransparentBalance = try await rustBackend.getTransparentBalance(account: Int32(0))
33
35
 
34
36
  // Download Sapling parameters only if sapling funds are detected.
35
- guard totalShieldedBalance > 0 || totalTransparentBalance > 0 else { return }
37
+ guard totalSaplingBalance > 0 || totalTransparentBalance > 0 else { return }
36
38
  } catch {
37
39
  // if sapling balance can't be detected of we fail to obtain the balance
38
40
  // for some reason we shall not proceed to download the parameters and
@@ -23,6 +23,7 @@ protocol BlockScanner {
23
23
  struct BlockScannerImpl {
24
24
  let config: BlockScannerConfig
25
25
  let rustBackend: ZcashRustBackendWelding
26
+ let service: LightWalletService
26
27
  let transactionRepository: TransactionRepository
27
28
  let metrics: SDKMetrics
28
29
  let logger: Logger
@@ -51,9 +52,14 @@ extension BlockScannerImpl: BlockScanner {
51
52
 
52
53
  let batchSize = UInt32(config.scanningBatchSize)
53
54
 
55
+ // TODO: [#1355] Do more with ScanSummary
56
+ // https://github.com/Electric-Coin-Company/zcash-swift-wallet-sdk/issues/1355
57
+ let scanSummary: ScanSummary
54
58
  let scanStartTime = Date()
55
59
  do {
56
- try await self.rustBackend.scanBlocks(fromHeight: Int32(startHeight), limit: batchSize)
60
+ let fromState = try await service.getTreeState(BlockID(height: startHeight - 1))
61
+
62
+ scanSummary = try await self.rustBackend.scanBlocks(fromHeight: Int32(startHeight), fromState: fromState, limit: batchSize)
57
63
  } catch {
58
64
  logger.debug("block scanning failed with error: \(String(describing: error))")
59
65
  throw error
@@ -61,24 +67,16 @@ extension BlockScannerImpl: BlockScanner {
61
67
 
62
68
  let scanFinishTime = Date()
63
69
 
64
- // TODO: [#1259] potential bug when rustBackend.scanBlocks scan less blocks than batchSize,
65
- // https://github.com/zcash/ZcashLightClientKit/issues/1259
66
- lastScannedHeight = startHeight + Int(batchSize) - 1
67
-
70
+ lastScannedHeight = scanSummary.scannedRange.upperBound - 1
71
+
68
72
  scannedNewBlocks = previousScannedHeight != lastScannedHeight
69
73
  if scannedNewBlocks {
70
74
  try await didScan(lastScannedHeight, batchSize)
71
75
 
72
- metrics.pushProgressReport(
73
- start: scanStartTime,
74
- end: scanFinishTime,
75
- batchSize: Int(batchSize),
76
- operation: .scanBlocks
77
- )
78
-
79
76
  let heightCount = lastScannedHeight - previousScannedHeight
80
77
  let seconds = scanFinishTime.timeIntervalSinceReferenceDate - scanStartTime.timeIntervalSinceReferenceDate
81
78
  logger.debug("Scanned \(heightCount) blocks in \(seconds) seconds")
79
+ logger.sync("Scanned \(heightCount) blocks in \(seconds) seconds")
82
80
  }
83
81
 
84
82
  await Task.yield()
@@ -0,0 +1,38 @@
1
+ //
2
+ // BundleCheckpointSource.swift
3
+ //
4
+ //
5
+ // Created by Francisco Gindre on 2023-10-30.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ struct BundleCheckpointSource: CheckpointSource {
11
+ var network: NetworkType
12
+
13
+ var saplingActivation: Checkpoint
14
+
15
+ init(network: NetworkType) {
16
+ self.network = network
17
+ self.saplingActivation = switch network {
18
+ case .mainnet:
19
+ Checkpoint.mainnetMin
20
+ case .testnet:
21
+ Checkpoint.testnetMin
22
+ }
23
+ }
24
+
25
+ func latestKnownCheckpoint() -> Checkpoint {
26
+ Checkpoint.birthday(
27
+ with: .max,
28
+ checkpointDirectory: BundleCheckpointURLProvider.default.url(self.network)
29
+ ) ?? saplingActivation
30
+ }
31
+
32
+ func birthday(for height: BlockHeight) -> Checkpoint {
33
+ Checkpoint.birthday(
34
+ with: height,
35
+ checkpointDirectory: BundleCheckpointURLProvider.default.url(self.network)
36
+ ) ?? saplingActivation
37
+ }
38
+ }
@@ -0,0 +1,40 @@
1
+ //
2
+ // BundleCheckpointURLProvider.swift
3
+ //
4
+ //
5
+ // Created by Francisco Gindre on 2023-10-30.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ struct BundleCheckpointURLProvider {
11
+ var url: (NetworkType) -> URL
12
+ }
13
+
14
+ extension BundleCheckpointURLProvider {
15
+ /// Attempts to resolve the platform. `#if os(macOS)` implies that the build is for a macOS
16
+ /// target, otherwise we assume the build is for an iOS target.
17
+ static let `default` = BundleCheckpointURLProvider { networkType in
18
+ #if os(macOS)
19
+ Self.macOS.url(networkType)
20
+ #else
21
+ Self.iOS.url(networkType)
22
+ #endif
23
+ }
24
+
25
+ static let iOS = BundleCheckpointURLProvider(url: { networkType in
26
+ switch networkType {
27
+ case .mainnet:
28
+ return Checkpoint.mainnetCheckpointDirectory
29
+ case .testnet:
30
+ return Checkpoint.testnetCheckpointDirectory
31
+ }
32
+ })
33
+
34
+ /// This variant attempts to retrieve the saplingActivation checkpoint for the given network
35
+ /// type using `Bundle.module.url(forResource:withExtension:subdirectory:localization)`.
36
+ /// If not found it will return `WalletBirthday.mainnetCheckpointDirectory` or
37
+ /// `WalletBirthday.testnetCheckpointDirectory`. This responds to tests failing on a macOS
38
+ /// target because the checkpoint resources would not be found.
39
+
40
+ }
@@ -1,5 +1,5 @@
1
1
  //
2
- // WalletBirthday+Constants.swift
2
+ // Checkpoint+helpers.swift
3
3
  // ZcashLightClientKit
4
4
  //
5
5
  // Created by Francisco Gindre on 7/28/21.
@@ -64,35 +64,3 @@ extension Checkpoint {
64
64
  }
65
65
  }
66
66
  }
67
-
68
- struct BundleCheckpointURLProvider {
69
- var url: (NetworkType) -> URL
70
- }
71
-
72
- extension BundleCheckpointURLProvider {
73
- /// Attempts to resolve the platform by checking `#if os(macOS)` build corresponds to a MacOS target
74
- /// `#else` branch of that condition will assume iOS is the target platform
75
- static let `default` = BundleCheckpointURLProvider { networkType in
76
- #if os(macOS)
77
- Self.macOS.url(networkType)
78
- #else
79
- Self.iOS.url(networkType)
80
- #endif
81
- }
82
-
83
- static let iOS = BundleCheckpointURLProvider(url: { networkType in
84
- switch networkType {
85
- case .mainnet:
86
- return Checkpoint.mainnetCheckpointDirectory
87
- case .testnet:
88
- return Checkpoint.testnetCheckpointDirectory
89
- }
90
- })
91
-
92
- /// This variant attempts to retrieve the saplingActivation checkpoint for the given network type
93
- /// using `Bundle.module.url(forResource:withExtension:subdirectory:localization)`
94
- /// if not found it will return `WalletBirthday.mainnetCheckpointDirectory` or
95
- /// `WalletBirthday.testnetCheckpointDirectory`. This responds to tests
96
- /// failing on MacOS target because the checkpoint resources would fail.
97
-
98
- }
@@ -0,0 +1,34 @@
1
+ //
2
+ // CheckpointSource.swift
3
+ //
4
+ //
5
+ // Created by Francisco Gindre on 2023-10-30.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ /// A protocol that abstracts the requirements around obtaining wallet checkpoints
11
+ /// (also known as TreeStates).
12
+ protocol CheckpointSource {
13
+ /// `NetworkType` of this Checkpoint source
14
+ var network: NetworkType { get }
15
+
16
+ /// The `Checkpoint` that represents the block in which Sapling was activated
17
+ var saplingActivation: Checkpoint { get }
18
+
19
+ /// Obtain the latest `Checkpoint` in terms of block height known by
20
+ /// this `CheckpointSource`. It is possible that the returned checkpoint
21
+ /// is not the latest checkpoint that exists in the blockchain.
22
+ /// - Returns a `Checkpoint` with the highest height known by this source
23
+ func latestKnownCheckpoint() -> Checkpoint
24
+
25
+ /// Obtain a `Checkpoint` in terms of a "wallet birthday". Wallet birthday
26
+ /// is estimated to be the latest height of the Zcash blockchain at the moment when the wallet was
27
+ /// created.
28
+ /// - Parameter height: Estimated or effective height known for the wallet birthday
29
+ /// - Returns: a `Checkpoint` that will allow the wallet to manage funds from the given `height`
30
+ /// onwards.
31
+ /// - Note: When the user knows the exact height of the first received funds for a wallet,
32
+ /// the effective birthday of that wallet is `transaction.height - 1`.
33
+ func birthday(for height: BlockHeight) -> Checkpoint
34
+ }
@@ -0,0 +1,14 @@
1
+ //
2
+ // CheckpointSourceFactory.swift
3
+ //
4
+ //
5
+ // Created by Francisco Gindre on 2023-10-30.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ struct CheckpointSourceFactory {
11
+ static func fromBundle(for network: NetworkType) -> CheckpointSource {
12
+ BundleCheckpointSource(network: network)
13
+ }
14
+ }