Merge pull request #1274 from LukasKorba/1273-SynchronizerState-not-always-up-to-date

[#1273] SynchronizerState not always up to date
This commit is contained in:
Kris Nuttycombe 2023-09-18 16:34:35 -06:00 committed by GitHub
commit ab7aedeea1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 49 additions and 14 deletions

View File

@ -11,12 +11,14 @@ final class ScanAction {
let configProvider: CompactBlockProcessor.ConfigProvider let configProvider: CompactBlockProcessor.ConfigProvider
let blockScanner: BlockScanner let blockScanner: BlockScanner
let rustBackend: ZcashRustBackendWelding let rustBackend: ZcashRustBackendWelding
let latestBlocksDataProvider: LatestBlocksDataProvider
let logger: Logger let logger: Logger
init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) { init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
self.configProvider = configProvider self.configProvider = configProvider
blockScanner = container.resolve(BlockScanner.self) blockScanner = container.resolve(BlockScanner.self)
rustBackend = container.resolve(ZcashRustBackendWelding.self) rustBackend = container.resolve(ZcashRustBackendWelding.self)
latestBlocksDataProvider = container.resolve(LatestBlocksDataProvider.self)
logger = container.resolve(Logger.self) logger = container.resolve(Logger.self)
} }
@ -54,7 +56,8 @@ extension ScanAction: Action {
let processedHeight = await context.processedHeight let processedHeight = await context.processedHeight
let incrementedprocessedHeight = processedHeight + BlockHeight(increment) let incrementedprocessedHeight = processedHeight + BlockHeight(increment)
await context.update(processedHeight: incrementedprocessedHeight) await context.update(processedHeight: incrementedprocessedHeight)
await self?.latestBlocksDataProvider.updateScannedData()
// report scan progress only if it's available // report scan progress only if it's available
if let scanProgress = try? await self?.rustBackend.getScanProgress() { if let scanProgress = try? await self?.rustBackend.getScanProgress() {
let progress = try scanProgress.progress() let progress = try scanProgress.progress()

View File

@ -11,12 +11,14 @@ final class UpdateChainTipAction {
let rustBackend: ZcashRustBackendWelding let rustBackend: ZcashRustBackendWelding
let downloader: BlockDownloader let downloader: BlockDownloader
let service: LightWalletService let service: LightWalletService
let latestBlocksDataProvider: LatestBlocksDataProvider
let logger: Logger let logger: Logger
init(container: DIContainer) { init(container: DIContainer) {
service = container.resolve(LightWalletService.self) service = container.resolve(LightWalletService.self)
downloader = container.resolve(BlockDownloader.self) downloader = container.resolve(BlockDownloader.self)
rustBackend = container.resolve(ZcashRustBackendWelding.self) rustBackend = container.resolve(ZcashRustBackendWelding.self)
latestBlocksDataProvider = container.resolve(LatestBlocksDataProvider.self)
logger = container.resolve(Logger.self) logger = container.resolve(Logger.self)
} }
@ -26,6 +28,7 @@ final class UpdateChainTipAction {
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))
await context.update(lastChainTipUpdateTime: time) await context.update(lastChainTipUpdateTime: time)
await latestBlocksDataProvider.update(latestBlockHeight)
} }
} }

View File

@ -16,6 +16,7 @@ protocol LatestBlocksDataProvider {
func updateScannedData() async func updateScannedData() async
func updateBlockData() async func updateBlockData() async
func updateWalletBirthday(_ walletBirthday: BlockHeight) async func updateWalletBirthday(_ walletBirthday: BlockHeight) async
func update(_ latestBlockHeight: BlockHeight) async
} }
actor LatestBlocksDataProviderImpl: LatestBlocksDataProvider { actor LatestBlocksDataProviderImpl: LatestBlocksDataProvider {
@ -41,13 +42,18 @@ actor LatestBlocksDataProviderImpl: LatestBlocksDataProvider {
} }
func updateBlockData() async { func updateBlockData() async {
if let newLatestBlockHeight = try? await service.latestBlockHeight(), if let newLatestBlockHeight = try? await service.latestBlockHeight() {
latestBlockHeight < newLatestBlockHeight { await update(newLatestBlockHeight)
latestBlockHeight = newLatestBlockHeight
} }
} }
func updateWalletBirthday(_ walletBirthday: BlockHeight) async { func updateWalletBirthday(_ walletBirthday: BlockHeight) async {
self.walletBirthday = walletBirthday self.walletBirthday = walletBirthday
} }
func update(_ newLatestBlockHeight: BlockHeight) async {
if latestBlockHeight < newLatestBlockHeight {
latestBlockHeight = newLatestBlockHeight
}
}
} }

View File

@ -13,7 +13,7 @@ final class ScanActionTests: ZcashTestCase {
func testScanAction_NextAction() async throws { func testScanAction_NextAction() async throws {
let blockScannerMock = BlockScannerMock() let blockScannerMock = BlockScannerMock()
let loggerMock = LoggerMock() let loggerMock = LoggerMock()
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in } loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
let scanAction = setupAction(blockScannerMock, loggerMock) let scanAction = setupAction(blockScannerMock, loggerMock)
@ -46,7 +46,7 @@ final class ScanActionTests: ZcashTestCase {
func testScanAction_EarlyOutForNoDownloadAndScanRangeSet() async throws { func testScanAction_EarlyOutForNoDownloadAndScanRangeSet() async throws {
let blockScannerMock = BlockScannerMock() let blockScannerMock = BlockScannerMock()
let loggerMock = LoggerMock() let loggerMock = LoggerMock()
let scanAction = setupAction(blockScannerMock, loggerMock) let scanAction = setupAction(blockScannerMock, loggerMock)
let syncContext = ActionContextMock.default() let syncContext = ActionContextMock.default()
@ -83,7 +83,7 @@ final class ScanActionTests: ZcashTestCase {
func testScanAction_EndRangeProperlySetLowerThanBatchSize() async throws { func testScanAction_EndRangeProperlySetLowerThanBatchSize() async throws {
let blockScannerMock = BlockScannerMock() let blockScannerMock = BlockScannerMock()
let loggerMock = LoggerMock() let loggerMock = LoggerMock()
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in } loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
let scanAction = setupAction(blockScannerMock, loggerMock) let scanAction = setupAction(blockScannerMock, loggerMock)
@ -107,7 +107,7 @@ final class ScanActionTests: ZcashTestCase {
func testScanAction_EndRangeProperlySetBatchSize() async throws { func testScanAction_EndRangeProperlySetBatchSize() async throws {
let blockScannerMock = BlockScannerMock() let blockScannerMock = BlockScannerMock()
let loggerMock = LoggerMock() let loggerMock = LoggerMock()
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in } loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
let scanAction = setupAction(blockScannerMock, loggerMock) let scanAction = setupAction(blockScannerMock, loggerMock)
@ -130,7 +130,8 @@ final class ScanActionTests: ZcashTestCase {
private func setupAction( private func setupAction(
_ blockScannerMock: BlockScannerMock, _ blockScannerMock: BlockScannerMock,
_ loggerMock: LoggerMock _ loggerMock: LoggerMock,
_ latestBlocksDataProvider: LatestBlocksDataProvider = LatestBlocksDataProviderMock()
) -> ScanAction { ) -> ScanAction {
let rustBackendMock = ZcashRustBackendWeldingMock( let rustBackendMock = ZcashRustBackendWeldingMock(
consensusBranchIdForHeightClosure: { height in consensusBranchIdForHeightClosure: { height in
@ -142,7 +143,8 @@ final class ScanActionTests: ZcashTestCase {
mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in rustBackendMock } mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in rustBackendMock }
mockContainer.mock(type: BlockScanner.self, isSingleton: true) { _ in blockScannerMock } mockContainer.mock(type: BlockScanner.self, isSingleton: true) { _ in blockScannerMock }
mockContainer.mock(type: Logger.self, isSingleton: true) { _ in loggerMock } mockContainer.mock(type: Logger.self, isSingleton: true) { _ in loggerMock }
mockContainer.mock(type: LatestBlocksDataProvider.self, isSingleton: true) { _ in latestBlocksDataProvider }
let config: CompactBlockProcessor.Configuration = .standard( let config: CompactBlockProcessor.Configuration = .standard(
for: ZcashNetworkBuilder.network(for: .testnet), walletBirthday: 0 for: ZcashNetworkBuilder.network(for: .testnet), walletBirthday: 0
) )

View File

@ -27,11 +27,13 @@ final class UpdateChainTipActionTests: ZcashTestCase {
func testUpdateChainTipAction_UpdateChainTipTimeTriggered() async throws { func testUpdateChainTipAction_UpdateChainTipTimeTriggered() async throws {
let loggerMock = LoggerMock() let loggerMock = LoggerMock()
let blockDownloaderMock = BlockDownloaderMock() let blockDownloaderMock = BlockDownloaderMock()
let latestBlocksDataProvider = LatestBlocksDataProviderMock()
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in } loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
blockDownloaderMock.stopDownloadClosure = { } blockDownloaderMock.stopDownloadClosure = { }
latestBlocksDataProvider.updateClosure = { _ in }
let updateChainTipAction = await setupAction(loggerMock, blockDownloaderMock)
let updateChainTipAction = await setupAction(loggerMock, blockDownloaderMock, latestBlocksDataProvider)
do { do {
let context = ActionContextMock.default() let context = ActionContextMock.default()
@ -53,11 +55,13 @@ final class UpdateChainTipActionTests: ZcashTestCase {
func testUpdateChainTipAction_UpdateChainTipPrevActionTriggered() async throws { func testUpdateChainTipAction_UpdateChainTipPrevActionTriggered() async throws {
let loggerMock = LoggerMock() let loggerMock = LoggerMock()
let blockDownloaderMock = BlockDownloaderMock() let blockDownloaderMock = BlockDownloaderMock()
let latestBlocksDataProvider = LatestBlocksDataProviderMock()
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in } loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
blockDownloaderMock.stopDownloadClosure = { } blockDownloaderMock.stopDownloadClosure = { }
latestBlocksDataProvider.updateClosure = { _ in }
let updateChainTipAction = await setupAction(loggerMock, blockDownloaderMock) let updateChainTipAction = await setupAction(loggerMock, blockDownloaderMock, latestBlocksDataProvider)
do { do {
let context = ActionContextMock.default() let context = ActionContextMock.default()
@ -104,7 +108,8 @@ final class UpdateChainTipActionTests: ZcashTestCase {
private func setupAction( private func setupAction(
_ loggerMock: LoggerMock = LoggerMock(), _ loggerMock: LoggerMock = LoggerMock(),
_ blockDownloaderMock: BlockDownloaderMock = BlockDownloaderMock() _ blockDownloaderMock: BlockDownloaderMock = BlockDownloaderMock(),
_ latestBlocksDataProvider: LatestBlocksDataProvider = LatestBlocksDataProviderMock()
) async -> UpdateChainTipAction { ) async -> UpdateChainTipAction {
let config: CompactBlockProcessor.Configuration = .standard( let config: CompactBlockProcessor.Configuration = .standard(
for: ZcashNetworkBuilder.network(for: underlyingNetworkType), walletBirthday: 0 for: ZcashNetworkBuilder.network(for: underlyingNetworkType), walletBirthday: 0
@ -133,6 +138,7 @@ final class UpdateChainTipActionTests: ZcashTestCase {
mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in serviceMock } mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in serviceMock }
mockContainer.mock(type: Logger.self, isSingleton: true) { _ in loggerMock } mockContainer.mock(type: Logger.self, isSingleton: true) { _ in loggerMock }
mockContainer.mock(type: BlockDownloader.self, isSingleton: true) { _ in blockDownloaderMock } mockContainer.mock(type: BlockDownloader.self, isSingleton: true) { _ in blockDownloaderMock }
mockContainer.mock(type: LatestBlocksDataProvider.self, isSingleton: true) { _ in latestBlocksDataProvider }
return UpdateChainTipAction(container: mockContainer) return UpdateChainTipAction(container: mockContainer)
} }

View File

@ -712,6 +712,21 @@ class LatestBlocksDataProviderMock: LatestBlocksDataProvider {
await updateWalletBirthdayClosure!(walletBirthday) await updateWalletBirthdayClosure!(walletBirthday)
} }
// MARK: - update
var updateCallsCount = 0
var updateCalled: Bool {
return updateCallsCount > 0
}
var updateReceivedLatestBlockHeight: BlockHeight?
var updateClosure: ((BlockHeight) async -> Void)?
func update(_ latestBlockHeight: BlockHeight) async {
updateCallsCount += 1
updateReceivedLatestBlockHeight = latestBlockHeight
await updateClosure!(latestBlockHeight)
}
} }
class LightWalletServiceMock: LightWalletService { class LightWalletServiceMock: LightWalletService {