[#1169] Step 5 -Get the suggested scan ranges from the wallet database
- initial action in place - verify loop WIP [#1169] Step 5 -Get the suggested scan ranges from the wallet database - firstUnenhancedHeight fix [#1169] Step 5 -Get the suggested scan ranges from the wallet database - first working version implemented - download, scan and enhance actions are dependent on the context values only
This commit is contained in:
parent
4a78b4bd16
commit
086827fa24
|
@ -12,6 +12,7 @@ actor ActionContext {
|
||||||
var prevState: CBPState?
|
var prevState: CBPState?
|
||||||
var syncControlData: SyncControlData
|
var syncControlData: SyncControlData
|
||||||
var totalProgressRange: CompactBlockRange = 0...0
|
var totalProgressRange: CompactBlockRange = 0...0
|
||||||
|
var lastScannedHeight: BlockHeight?
|
||||||
var lastDownloadedHeight: BlockHeight?
|
var lastDownloadedHeight: BlockHeight?
|
||||||
var lastEnhancedHeight: BlockHeight?
|
var lastEnhancedHeight: BlockHeight?
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ actor ActionContext {
|
||||||
}
|
}
|
||||||
func update(syncControlData: SyncControlData) async { self.syncControlData = syncControlData }
|
func update(syncControlData: SyncControlData) async { self.syncControlData = syncControlData }
|
||||||
func update(totalProgressRange: CompactBlockRange) async { self.totalProgressRange = totalProgressRange }
|
func update(totalProgressRange: CompactBlockRange) async { self.totalProgressRange = totalProgressRange }
|
||||||
|
func update(lastScannedHeight: BlockHeight) async { self.lastScannedHeight = lastScannedHeight }
|
||||||
func update(lastDownloadedHeight: BlockHeight) async { self.lastDownloadedHeight = lastDownloadedHeight }
|
func update(lastDownloadedHeight: BlockHeight) async { self.lastDownloadedHeight = lastDownloadedHeight }
|
||||||
func update(lastEnhancedHeight: BlockHeight?) async { self.lastEnhancedHeight = lastEnhancedHeight }
|
func update(lastEnhancedHeight: BlockHeight?) async { self.lastEnhancedHeight = lastEnhancedHeight }
|
||||||
}
|
}
|
||||||
|
@ -36,6 +38,7 @@ enum CBPState: CaseIterable {
|
||||||
case validateServer
|
case validateServer
|
||||||
case updateSubtreeRoots
|
case updateSubtreeRoots
|
||||||
case updateChainTip
|
case updateChainTip
|
||||||
|
case validatePreviousWalletSession
|
||||||
case computeSyncControlData
|
case computeSyncControlData
|
||||||
case download
|
case download
|
||||||
case scan
|
case scan
|
||||||
|
|
|
@ -21,7 +21,12 @@ extension ClearAlreadyScannedBlocksAction: Action {
|
||||||
var removeBlocksCacheWhenFailed: Bool { false }
|
var removeBlocksCacheWhenFailed: Bool { false }
|
||||||
|
|
||||||
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
||||||
let lastScannedHeight = try await transactionRepository.lastScannedHeight()
|
guard let lastScannedHeight = await context.lastScannedHeight else {
|
||||||
|
fatalError("it must be valid")
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
//let lastScannedHeight = //try await transactionRepository.lastScannedHeight()
|
||||||
try await storage.clear(upTo: lastScannedHeight)
|
try await storage.clear(upTo: lastScannedHeight)
|
||||||
|
|
||||||
await context.update(state: .enhance)
|
await context.update(state: .enhance)
|
||||||
|
|
|
@ -23,7 +23,8 @@ extension ClearCacheAction: Action {
|
||||||
if await context.prevState == .idle {
|
if await context.prevState == .idle {
|
||||||
await context.update(state: .migrateLegacyCacheDB)
|
await context.update(state: .migrateLegacyCacheDB)
|
||||||
} else {
|
} else {
|
||||||
await context.update(state: .finished)
|
//await context.update(state: .finished) // Linear
|
||||||
|
await context.update(state: .validatePreviousWalletSession)
|
||||||
}
|
}
|
||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ extension ComputeSyncControlDataAction: Action {
|
||||||
firstUnenhancedHeight: enhanceStart
|
firstUnenhancedHeight: enhanceStart
|
||||||
)
|
)
|
||||||
|
|
||||||
|
await context.update(lastScannedHeight: latestScannedHeight)
|
||||||
await context.update(lastDownloadedHeight: latestScannedHeight)
|
await context.update(lastDownloadedHeight: latestScannedHeight)
|
||||||
await context.update(syncControlData: syncControlData)
|
await context.update(syncControlData: syncControlData)
|
||||||
await context.update(totalProgressRange: latestScannedHeight...latestBlockHeight)
|
await context.update(totalProgressRange: latestScannedHeight...latestBlockHeight)
|
||||||
|
@ -72,7 +73,7 @@ extension ComputeSyncControlDataAction: Action {
|
||||||
if latestBlockHeight < latestScannedHeight || latestBlockHeight == latestScannedHeight {
|
if latestBlockHeight < latestScannedHeight || latestBlockHeight == latestScannedHeight {
|
||||||
await context.update(state: .finished)
|
await context.update(state: .finished)
|
||||||
} else {
|
} else {
|
||||||
await context.update(state: .fetchUTXO)
|
await context.update(state: .download)
|
||||||
}
|
}
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
|
@ -30,16 +30,16 @@ extension DownloadAction: Action {
|
||||||
var removeBlocksCacheWhenFailed: Bool { true }
|
var removeBlocksCacheWhenFailed: Bool { true }
|
||||||
|
|
||||||
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
||||||
guard let lastScannedHeight = await context.syncControlData.latestScannedHeight else {
|
guard let lastScannedHeight = await context.lastScannedHeight else {
|
||||||
return await update(context: context)
|
return await update(context: context)
|
||||||
}
|
}
|
||||||
|
|
||||||
let config = await configProvider.config
|
let config = await configProvider.config
|
||||||
let lastScannedHeightDB = try await transactionRepository.lastScannedHeight()
|
// let lastScannedHeightDB = try await transactionRepository.lastScannedHeight()
|
||||||
let latestBlockHeight = await context.syncControlData.latestBlockHeight
|
let latestBlockHeight = await context.syncControlData.latestBlockHeight
|
||||||
// This action is executed for each batch (batch size is 100 blocks by default) until all the blocks in whole `downloadRange` are downloaded.
|
// This action is executed for each batch (batch size is 100 blocks by default) until all the blocks in whole `downloadRange` are downloaded.
|
||||||
// So the right range for this batch must be computed.
|
// So the right range for this batch must be computed.
|
||||||
let batchRangeStart = max(lastScannedHeightDB, lastScannedHeight)
|
let batchRangeStart = lastScannedHeight//max(lastScannedHeightDB, lastScannedHeight)
|
||||||
let batchRangeEnd = min(latestBlockHeight, batchRangeStart + config.batchSize)
|
let batchRangeEnd = min(latestBlockHeight, batchRangeStart + config.batchSize)
|
||||||
|
|
||||||
guard batchRangeStart <= batchRangeEnd else {
|
guard batchRangeStart <= batchRangeEnd else {
|
||||||
|
@ -47,10 +47,11 @@ extension DownloadAction: Action {
|
||||||
}
|
}
|
||||||
|
|
||||||
let batchRange = batchRangeStart...batchRangeEnd
|
let batchRange = batchRangeStart...batchRangeEnd
|
||||||
let downloadLimit = batchRange.upperBound + (2 * config.batchSize)
|
let potentialDownloadLimit = batchRange.upperBound + (2 * config.batchSize)
|
||||||
|
let downloadLimit = await context.syncControlData.latestBlockHeight >= potentialDownloadLimit ? potentialDownloadLimit : batchRangeEnd
|
||||||
|
|
||||||
logger.debug("Starting download with range: \(batchRange.lowerBound)...\(batchRange.upperBound)")
|
logger.debug("Starting download with range: \(batchRange.lowerBound)...\(batchRange.upperBound)")
|
||||||
await downloader.update(latestDownloadedBlockHeight: batchRange.lowerBound)
|
await downloader.update(latestDownloadedBlockHeight: batchRange.lowerBound, force: true) // SbS
|
||||||
try await downloader.setSyncRange(lastScannedHeight...latestBlockHeight, batchSize: config.batchSize)
|
try await downloader.setSyncRange(lastScannedHeight...latestBlockHeight, batchSize: config.batchSize)
|
||||||
await downloader.setDownloadLimit(downloadLimit)
|
await downloader.setDownloadLimit(downloadLimit)
|
||||||
await downloader.startDownload(maxBlockBufferSize: config.downloadBufferSize)
|
await downloader.startDownload(maxBlockBufferSize: config.downloadBufferSize)
|
||||||
|
|
|
@ -22,15 +22,18 @@ final class EnhanceAction {
|
||||||
|
|
||||||
func decideWhatToDoNext(context: ActionContext, lastScannedHeight: BlockHeight) async -> ActionContext {
|
func decideWhatToDoNext(context: ActionContext, lastScannedHeight: BlockHeight) async -> ActionContext {
|
||||||
guard await context.syncControlData.latestScannedHeight != nil else {
|
guard await context.syncControlData.latestScannedHeight != nil else {
|
||||||
await context.update(state: .clearCache)
|
await context.update(state: .clearCache) // linear
|
||||||
|
// await context.update(state: .validatePreviousWalletSession) // SbS
|
||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
let latestBlockHeight = await context.syncControlData.latestBlockHeight
|
let latestBlockHeight = await context.syncControlData.latestBlockHeight
|
||||||
if lastScannedHeight >= latestBlockHeight {
|
if lastScannedHeight >= latestBlockHeight {
|
||||||
await context.update(state: .clearCache)
|
await context.update(state: .clearCache) // linear
|
||||||
|
// await context.update(state: .validatePreviousWalletSession) // SbS
|
||||||
} else {
|
} else {
|
||||||
await context.update(state: .download)
|
await context.update(state: .download) // Linear
|
||||||
|
// await context.update(state: .validatePreviousWalletSession) // SbS
|
||||||
}
|
}
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
@ -49,7 +52,11 @@ extension EnhanceAction: Action {
|
||||||
// download and scan.
|
// download and scan.
|
||||||
|
|
||||||
let config = await configProvider.config
|
let config = await configProvider.config
|
||||||
let lastScannedHeight = try await transactionRepository.lastScannedHeight()
|
//let lastScannedHeight = try await transactionRepository.lastScannedHeight()
|
||||||
|
guard let lastScannedHeight = await context.lastScannedHeight else {
|
||||||
|
await context.update(state: .validatePreviousWalletSession)
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
guard let firstUnenhancedHeight = await context.syncControlData.firstUnenhancedHeight else {
|
guard let firstUnenhancedHeight = await context.syncControlData.firstUnenhancedHeight else {
|
||||||
return await decideWhatToDoNext(context: context, lastScannedHeight: lastScannedHeight)
|
return await decideWhatToDoNext(context: context, lastScannedHeight: lastScannedHeight)
|
||||||
|
|
|
@ -23,7 +23,8 @@ extension SaplingParamsAction: Action {
|
||||||
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
||||||
logger.debug("Fetching sapling parameters")
|
logger.debug("Fetching sapling parameters")
|
||||||
try await saplingParametersHandler.handleIfNeeded()
|
try await saplingParametersHandler.handleIfNeeded()
|
||||||
await context.update(state: .download)
|
// await context.update(state: .computeSyncControlData) // Linear
|
||||||
|
await context.update(state: .updateSubtreeRoots) // SbS
|
||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,16 +30,16 @@ extension ScanAction: Action {
|
||||||
var removeBlocksCacheWhenFailed: Bool { true }
|
var removeBlocksCacheWhenFailed: Bool { true }
|
||||||
|
|
||||||
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
||||||
guard let lastScannedHeight = await context.syncControlData.latestScannedHeight else {
|
guard let lastScannedHeight = await context.lastScannedHeight else {
|
||||||
return await update(context: context)
|
return await update(context: context)
|
||||||
}
|
}
|
||||||
|
|
||||||
let config = await configProvider.config
|
let config = await configProvider.config
|
||||||
let lastScannedHeightDB = try await transactionRepository.lastScannedHeight()
|
//let lastScannedHeightDB = try await transactionRepository.lastScannedHeight()
|
||||||
let latestBlockHeight = await context.syncControlData.latestBlockHeight
|
let latestBlockHeight = await context.syncControlData.latestBlockHeight
|
||||||
// This action is executed for each batch (batch size is 100 blocks by default) until all the blocks in whole `scanRange` are scanned.
|
// This action is executed for each batch (batch size is 100 blocks by default) until all the blocks in whole `scanRange` are scanned.
|
||||||
// So the right range for this batch must be computed.
|
// So the right range for this batch must be computed.
|
||||||
let batchRangeStart = max(lastScannedHeightDB, lastScannedHeight)
|
let batchRangeStart = lastScannedHeight//max(lastScannedHeightDB, lastScannedHeight)
|
||||||
let batchRangeEnd = min(latestBlockHeight, batchRangeStart + config.batchSize)
|
let batchRangeEnd = min(latestBlockHeight, batchRangeStart + config.batchSize)
|
||||||
|
|
||||||
guard batchRangeStart <= batchRangeEnd else {
|
guard batchRangeStart <= batchRangeEnd else {
|
||||||
|
@ -58,6 +58,16 @@ extension ScanAction: Action {
|
||||||
)
|
)
|
||||||
self?.logger.debug("progress: \(progress)")
|
self?.logger.debug("progress: \(progress)")
|
||||||
await didUpdate(.progressPartialUpdate(.syncing(progress)))
|
await didUpdate(.progressPartialUpdate(.syncing(progress)))
|
||||||
|
|
||||||
|
// ScanAction is controlled locally so it must report back the updated scanned height
|
||||||
|
await context.update(lastScannedHeight: lastScannedHeight)
|
||||||
|
// let prevSyncControlData = await context.syncControlData
|
||||||
|
// let newSyncControlData = SyncControlData(
|
||||||
|
// latestBlockHeight: prevSyncControlData.latestBlockHeight,
|
||||||
|
// latestScannedHeight: lastScannedHeight,
|
||||||
|
// firstUnenhancedHeight: prevSyncControlData.firstUnenhancedHeight
|
||||||
|
// )
|
||||||
|
// await context.update(syncControlData: newSyncControlData)
|
||||||
}
|
}
|
||||||
|
|
||||||
return await update(context: context)
|
return await update(context: context)
|
||||||
|
|
|
@ -28,9 +28,7 @@ extension UpdateChainTipAction: Action {
|
||||||
logger.info("Latest block height is \(latestBlockHeight)")
|
logger.info("Latest block height is \(latestBlockHeight)")
|
||||||
try await rustBackend.updateChainTip(height: Int32(latestBlockHeight))
|
try await rustBackend.updateChainTip(height: Int32(latestBlockHeight))
|
||||||
|
|
||||||
// TODO: [#1169] Switching back to linear sync for now before step 5 & 6 are implemented
|
await context.update(state: .validatePreviousWalletSession)
|
||||||
// https://github.com/zcash/ZcashLightClientKit/issues/1169
|
|
||||||
await context.update(state: .computeSyncControlData)
|
|
||||||
|
|
||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ extension UpdateSubtreeRootsAction: Action {
|
||||||
request.shieldedProtocol = .sapling
|
request.shieldedProtocol = .sapling
|
||||||
request.maxEntries = 65536
|
request.maxEntries = 65536
|
||||||
|
|
||||||
logger.info("Attempt to get subtree roots, this may fail because lightwalletd may not support DAG sync.")
|
logger.info("Attempt to get subtree roots, this may fail because lightwalletd may not support Spend before Sync.")
|
||||||
let stream = service.getSubtreeRoots(request)
|
let stream = service.getSubtreeRoots(request)
|
||||||
|
|
||||||
var roots: [SubtreeRoot] = []
|
var roots: [SubtreeRoot] = []
|
||||||
|
@ -42,10 +42,10 @@ extension UpdateSubtreeRootsAction: Action {
|
||||||
err = error
|
err = error
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case of error, the lightwalletd doesn't support DAG sync -> switching to linear sync.
|
// 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.
|
// Likewise, no subtree roots results in switching to linear sync.
|
||||||
if err != nil || roots.isEmpty {
|
if err != nil || roots.isEmpty {
|
||||||
logger.info("DAG sync is not possible, switching to linear sync.")
|
logger.info("Spend before Sync is not possible, switching to linear sync.")
|
||||||
await context.update(state: .computeSyncControlData)
|
await context.update(state: .computeSyncControlData)
|
||||||
} else {
|
} else {
|
||||||
logger.info("Sapling tree has \(roots.count) subtrees")
|
logger.info("Sapling tree has \(roots.count) subtrees")
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
//
|
||||||
|
// ValidatePreviousWalletSessionAction.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 02.08.2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
final class ValidatePreviousWalletSessionAction {
|
||||||
|
let rustBackend: ZcashRustBackendWelding
|
||||||
|
let service: LightWalletService
|
||||||
|
let logger: Logger
|
||||||
|
|
||||||
|
init(container: DIContainer) {
|
||||||
|
service = container.resolve(LightWalletService.self)
|
||||||
|
rustBackend = container.resolve(ZcashRustBackendWelding.self)
|
||||||
|
logger = container.resolve(Logger.self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ValidatePreviousWalletSessionAction: Action {
|
||||||
|
var removeBlocksCacheWhenFailed: Bool { false }
|
||||||
|
|
||||||
|
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
|
||||||
|
logger.info("Getting the suggested scan ranges from the wallet database.")
|
||||||
|
let scanRanges = try await rustBackend.suggestScanRanges()
|
||||||
|
|
||||||
|
print("__LD count \(scanRanges.count) first range \(scanRanges.first)")
|
||||||
|
|
||||||
|
// Run the following loop until the wallet's view of the chain tip
|
||||||
|
// as of the previous wallet session is valid.
|
||||||
|
// while true {
|
||||||
|
// If there is a range of blocks that needs to be verified, it will always
|
||||||
|
// be returned as the first element of the vector of suggested ranges.
|
||||||
|
if let firstRange = scanRanges.first {
|
||||||
|
//if firstRange.priority == .verify {
|
||||||
|
let lowerBound = firstRange.range.lowerBound - 1
|
||||||
|
let upperBound = firstRange.range.upperBound - 1
|
||||||
|
|
||||||
|
let syncControlData = SyncControlData(
|
||||||
|
latestBlockHeight: upperBound,
|
||||||
|
latestScannedHeight: lowerBound,
|
||||||
|
firstUnenhancedHeight: lowerBound + 1
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.debug("""
|
||||||
|
Init numbers:
|
||||||
|
latestBlockHeight [BC]: \(upperBound)
|
||||||
|
latestScannedHeight [DB]: \(lowerBound)
|
||||||
|
firstUnenhancedHeight [DB]: \(lowerBound + 1)
|
||||||
|
""")
|
||||||
|
|
||||||
|
if scanRanges.count == 1 {
|
||||||
|
print("cool")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await context.update(lastScannedHeight: lowerBound)
|
||||||
|
await context.update(lastDownloadedHeight: lowerBound)
|
||||||
|
await context.update(syncControlData: syncControlData)
|
||||||
|
await context.update(totalProgressRange: lowerBound...upperBound)
|
||||||
|
|
||||||
|
await context.update(state: .download)
|
||||||
|
// } else {
|
||||||
|
// print("cool")
|
||||||
|
// }
|
||||||
|
} else {
|
||||||
|
await context.update(state: .finished)
|
||||||
|
}
|
||||||
|
// } else {
|
||||||
|
// // Nothing to verify; break out of the loop
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TODO: [#1171] Switching back to linear sync for now before step 7 are implemented
|
||||||
|
// https://github.com/zcash/ZcashLightClientKit/issues/1171
|
||||||
|
// await context.update(state: .computeSyncControlData)
|
||||||
|
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
func stop() async { }
|
||||||
|
}
|
|
@ -52,7 +52,7 @@ extension ValidateServerAction: Action {
|
||||||
throw ZcashError.compactBlockProcessorWrongConsensusBranchId(localBranch, remoteBranchID)
|
throw ZcashError.compactBlockProcessorWrongConsensusBranchId(localBranch, remoteBranchID)
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.update(state: .updateSubtreeRoots)
|
await context.update(state: .fetchUTXO)
|
||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -218,6 +218,8 @@ actor CompactBlockProcessor {
|
||||||
action = UpdateSubtreeRootsAction(container: container)
|
action = UpdateSubtreeRootsAction(container: container)
|
||||||
case .updateChainTip:
|
case .updateChainTip:
|
||||||
action = UpdateChainTipAction(container: container)
|
action = UpdateChainTipAction(container: container)
|
||||||
|
case .validatePreviousWalletSession:
|
||||||
|
action = ValidatePreviousWalletSessionAction(container: container)
|
||||||
case .computeSyncControlData:
|
case .computeSyncControlData:
|
||||||
action = ComputeSyncControlDataAction(container: container, configProvider: configProvider)
|
action = ComputeSyncControlDataAction(container: container, configProvider: configProvider)
|
||||||
case .download:
|
case .download:
|
||||||
|
@ -593,6 +595,8 @@ extension CompactBlockProcessor {
|
||||||
break
|
break
|
||||||
case .updateChainTip:
|
case .updateChainTip:
|
||||||
break
|
break
|
||||||
|
case .validatePreviousWalletSession:
|
||||||
|
break
|
||||||
case .computeSyncControlData:
|
case .computeSyncControlData:
|
||||||
break
|
break
|
||||||
case .download:
|
case .download:
|
||||||
|
|
|
@ -55,7 +55,7 @@ protocol BlockDownloader {
|
||||||
|
|
||||||
/// Updates the internal in memory value of latest downloaded block height. This way the `BlockDownloader` works with the current latest height and can
|
/// Updates the internal in memory value of latest downloaded block height. This way the `BlockDownloader` works with the current latest height and can
|
||||||
/// continue on parallel downloading of next batch.
|
/// continue on parallel downloading of next batch.
|
||||||
func update(latestDownloadedBlockHeight: BlockHeight) async
|
func update(latestDownloadedBlockHeight: BlockHeight, force: Bool) async
|
||||||
/// Provides the value of latest downloaded height.
|
/// Provides the value of latest downloaded height.
|
||||||
func latestDownloadedBlockHeight() async -> BlockHeight
|
func latestDownloadedBlockHeight() async -> BlockHeight
|
||||||
/// In case rewind is needed, the latestDownloadedBlockHeight is rewritten forcefully.
|
/// In case rewind is needed, the latestDownloadedBlockHeight is rewritten forcefully.
|
||||||
|
@ -253,8 +253,8 @@ extension BlockDownloaderImpl: BlockDownloader {
|
||||||
self.latestDownloadedBlockHeight = latestDownloadedBlockHeight ?? -1
|
self.latestDownloadedBlockHeight = latestDownloadedBlockHeight ?? -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(latestDownloadedBlockHeight: BlockHeight) async {
|
func update(latestDownloadedBlockHeight: BlockHeight, force: Bool = false) async {
|
||||||
if latestDownloadedBlockHeight >= self.latestDownloadedBlockHeight {
|
if latestDownloadedBlockHeight >= self.latestDownloadedBlockHeight || force {
|
||||||
self.latestDownloadedBlockHeight = latestDownloadedBlockHeight
|
self.latestDownloadedBlockHeight = latestDownloadedBlockHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ extension BlockScannerImpl: BlockScanner {
|
||||||
logger.debug("Going to scan blocks in range: \(range)")
|
logger.debug("Going to scan blocks in range: \(range)")
|
||||||
try Task.checkCancellation()
|
try Task.checkCancellation()
|
||||||
|
|
||||||
let scanStartHeight = try await transactionRepository.lastScannedHeight()
|
let scanStartHeight = range.lowerBound//try await transactionRepository.lastScannedHeight()
|
||||||
let targetScanHeight = range.upperBound
|
let targetScanHeight = range.upperBound
|
||||||
|
|
||||||
var scannedNewBlocks = false
|
var scannedNewBlocks = false
|
||||||
|
@ -65,11 +65,13 @@ extension BlockScannerImpl: BlockScanner {
|
||||||
|
|
||||||
let scanFinishTime = Date()
|
let scanFinishTime = Date()
|
||||||
|
|
||||||
if let lastScannedBlock = try await transactionRepository.lastScannedBlock() {
|
// if let lastScannedBlock = try await transactionRepository.lastScannedBlock() {
|
||||||
lastScannedHeight = lastScannedBlock.height
|
// lastScannedHeight = lastScannedBlock.height
|
||||||
|
lastScannedHeight = startHeight + Int(batchSize) - 1
|
||||||
await latestBlocksDataProvider.updateLatestScannedHeight(lastScannedHeight)
|
await latestBlocksDataProvider.updateLatestScannedHeight(lastScannedHeight)
|
||||||
await latestBlocksDataProvider.updateLatestScannedTime(TimeInterval(lastScannedBlock.time))
|
// await latestBlocksDataProvider.updateLatestScannedTime(TimeInterval(lastScannedBlock.time))
|
||||||
}
|
// }
|
||||||
|
// lastScannedHeight = targetScanHeight
|
||||||
|
|
||||||
scannedNewBlocks = previousScannedHeight != lastScannedHeight
|
scannedNewBlocks = previousScannedHeight != lastScannedHeight
|
||||||
if scannedNewBlocks {
|
if scannedNewBlocks {
|
||||||
|
|
|
@ -8,6 +8,20 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct ScanRange {
|
struct ScanRange {
|
||||||
|
enum Priority: UInt8 {
|
||||||
|
case unknown = 0
|
||||||
|
case scanned = 10
|
||||||
|
case historic = 20
|
||||||
|
case openAdjacent = 30
|
||||||
|
case foundNote = 40
|
||||||
|
case chainTip = 50
|
||||||
|
case verify = 60
|
||||||
|
|
||||||
|
init(_ value: UInt8) {
|
||||||
|
self = Priority(rawValue: value) ?? .unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let range: Range<BlockHeight>
|
let range: Range<BlockHeight>
|
||||||
let priority: UInt8
|
let priority: Priority
|
||||||
}
|
}
|
||||||
|
|
|
@ -585,7 +585,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
||||||
BlockHeight(scanRange.start),
|
BlockHeight(scanRange.start),
|
||||||
BlockHeight(scanRange.end)
|
BlockHeight(scanRange.end)
|
||||||
)),
|
)),
|
||||||
priority: scanRange.priority
|
priority: ScanRange.Priority(scanRange.priority)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,8 +81,8 @@ final class ComputeSyncControlDataActionTests: ZcashTestCase {
|
||||||
|
|
||||||
let nextState = await nextContext.state
|
let nextState = await nextContext.state
|
||||||
XCTAssertTrue(
|
XCTAssertTrue(
|
||||||
nextState == .fetchUTXO,
|
nextState == .download,
|
||||||
"nextContext after .computeSyncControlData is expected to be .fetchUTXO but received \(nextState)"
|
"nextContext after .computeSyncControlData is expected to be .download but received \(nextState)"
|
||||||
)
|
)
|
||||||
} catch {
|
} catch {
|
||||||
XCTFail("testComputeSyncControlDataAction_checksBeforeSyncCase is not expected to fail. \(error)")
|
XCTFail("testComputeSyncControlDataAction_checksBeforeSyncCase is not expected to fail. \(error)")
|
||||||
|
|
|
@ -28,8 +28,8 @@ final class SaplingParamsActionTests: ZcashTestCase {
|
||||||
XCTAssertTrue(saplingParametersHandlerMock.handleIfNeededCalled, "saplingParametersHandler.handleIfNeeded() is expected to be called.")
|
XCTAssertTrue(saplingParametersHandlerMock.handleIfNeededCalled, "saplingParametersHandler.handleIfNeeded() is expected to be called.")
|
||||||
let nextState = await nextContext.state
|
let nextState = await nextContext.state
|
||||||
XCTAssertTrue(
|
XCTAssertTrue(
|
||||||
nextState == .download,
|
nextState == .updateSubtreeRoots,
|
||||||
"nextContext after .handleSaplingParams is expected to be .download but received \(nextState)"
|
"nextContext after .handleSaplingParams is expected to be .updateSubtreeRoots but received \(nextState)"
|
||||||
)
|
)
|
||||||
} catch {
|
} catch {
|
||||||
XCTFail("testSaplingParamsAction_NextAction is not expected to fail. \(error)")
|
XCTFail("testSaplingParamsAction_NextAction is not expected to fail. \(error)")
|
||||||
|
|
|
@ -31,8 +31,8 @@ final class ValidateServerActionTests: ZcashTestCase {
|
||||||
let nextContext = try await validateServerAction.run(with: .init(state: .validateServer)) { _ in }
|
let nextContext = try await validateServerAction.run(with: .init(state: .validateServer)) { _ in }
|
||||||
let nextState = await nextContext.state
|
let nextState = await nextContext.state
|
||||||
XCTAssertTrue(
|
XCTAssertTrue(
|
||||||
nextState == .updateSubtreeRoots,
|
nextState == .fetchUTXO,
|
||||||
"nextContext after .validateServer is expected to be .updateSubtreeRoots but received \(nextState)"
|
"nextContext after .validateServer is expected to be .fetchUTXO but received \(nextState)"
|
||||||
)
|
)
|
||||||
} catch {
|
} catch {
|
||||||
XCTFail("testValidateServerAction_NextAction is not expected to fail. \(error)")
|
XCTFail("testValidateServerAction_NextAction is not expected to fail. \(error)")
|
||||||
|
|
|
@ -97,17 +97,17 @@ class BlockDownloaderMock: BlockDownloader {
|
||||||
|
|
||||||
// MARK: - update
|
// MARK: - update
|
||||||
|
|
||||||
var updateLatestDownloadedBlockHeightCallsCount = 0
|
var updateLatestDownloadedBlockHeightForceCallsCount = 0
|
||||||
var updateLatestDownloadedBlockHeightCalled: Bool {
|
var updateLatestDownloadedBlockHeightForceCalled: Bool {
|
||||||
return updateLatestDownloadedBlockHeightCallsCount > 0
|
return updateLatestDownloadedBlockHeightForceCallsCount > 0
|
||||||
}
|
}
|
||||||
var updateLatestDownloadedBlockHeightReceivedLatestDownloadedBlockHeight: BlockHeight?
|
var updateLatestDownloadedBlockHeightForceReceivedArguments: (latestDownloadedBlockHeight: BlockHeight, force: Bool)?
|
||||||
var updateLatestDownloadedBlockHeightClosure: ((BlockHeight) async -> Void)?
|
var updateLatestDownloadedBlockHeightForceClosure: ((BlockHeight, Bool) async -> Void)?
|
||||||
|
|
||||||
func update(latestDownloadedBlockHeight: BlockHeight) async {
|
func update(latestDownloadedBlockHeight: BlockHeight, force: Bool) async {
|
||||||
updateLatestDownloadedBlockHeightCallsCount += 1
|
updateLatestDownloadedBlockHeightForceCallsCount += 1
|
||||||
updateLatestDownloadedBlockHeightReceivedLatestDownloadedBlockHeight = latestDownloadedBlockHeight
|
updateLatestDownloadedBlockHeightForceReceivedArguments = (latestDownloadedBlockHeight: latestDownloadedBlockHeight, force: force)
|
||||||
await updateLatestDownloadedBlockHeightClosure!(latestDownloadedBlockHeight)
|
await updateLatestDownloadedBlockHeightForceClosure!(latestDownloadedBlockHeight, force)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - latestDownloadedBlockHeight
|
// MARK: - latestDownloadedBlockHeight
|
||||||
|
|
Loading…
Reference in New Issue