2019-10-18 11:45:19 -07:00
|
|
|
//
|
|
|
|
// CompactBlockProcessorTests.swift
|
|
|
|
// ZcashLightClientKitTests
|
|
|
|
//
|
|
|
|
// Created by Francisco Gindre on 20/09/2019.
|
|
|
|
// Copyright © 2019 Electric Coin Company. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import XCTest
|
2022-02-28 09:03:20 -08:00
|
|
|
@testable import TestUtils
|
2019-10-18 11:45:19 -07:00
|
|
|
@testable import ZcashLightClientKit
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
|
|
// swiftlint:disable force_try implicitly_unwrapped_optional
|
2019-10-18 11:45:19 -07:00
|
|
|
class CompactBlockProcessorTests: XCTestCase {
|
2021-09-23 06:26:41 -07:00
|
|
|
let processorConfig = CompactBlockProcessor.Configuration.standard(
|
|
|
|
for: ZcashNetworkBuilder.network(for: .testnet),
|
|
|
|
walletBirthday: ZcashNetworkBuilder.network(for: .testnet).constants.saplingActivationHeight
|
|
|
|
)
|
2019-10-18 11:45:19 -07:00
|
|
|
var processor: CompactBlockProcessor!
|
2019-10-30 13:18:57 -07:00
|
|
|
var downloadStartedExpect: XCTestExpectation!
|
|
|
|
var updatedNotificationExpectation: XCTestExpectation!
|
|
|
|
var stopNotificationExpectation: XCTestExpectation!
|
|
|
|
var startedScanningNotificationExpectation: XCTestExpectation!
|
|
|
|
var startedValidatingNotificationExpectation: XCTestExpectation!
|
|
|
|
var idleNotificationExpectation: XCTestExpectation!
|
2021-07-28 09:59:10 -07:00
|
|
|
let network = ZcashNetworkBuilder.network(for: .testnet)
|
2021-09-15 05:21:29 -07:00
|
|
|
let mockLatestHeight = ZcashNetworkBuilder.network(for: .testnet).constants.saplingActivationHeight + 2000
|
2019-10-31 10:33:21 -07:00
|
|
|
|
2021-07-28 15:25:47 -07:00
|
|
|
override func setUpWithError() throws {
|
2021-09-23 06:26:41 -07:00
|
|
|
try super.setUpWithError()
|
2021-07-28 15:25:47 -07:00
|
|
|
logger = SampleLogger(logLevel: .debug)
|
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
let service = MockLightWalletService(
|
|
|
|
latestBlockHeight: mockLatestHeight,
|
|
|
|
service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet)
|
|
|
|
)
|
2021-07-28 15:25:47 -07:00
|
|
|
let branchID = try ZcashRustBackend.consensusBranchIdFor(height: Int32(mockLatestHeight), networkType: network.networkType)
|
|
|
|
service.mockLightDInfo = LightdInfo.with({ info in
|
|
|
|
info.blockHeight = UInt64(mockLatestHeight)
|
|
|
|
info.branch = "asdf"
|
|
|
|
info.buildDate = "today"
|
|
|
|
info.buildUser = "testUser"
|
|
|
|
info.chainName = "test"
|
|
|
|
info.consensusBranchID = branchID.toString()
|
|
|
|
info.estimatedHeight = UInt64(mockLatestHeight)
|
2021-09-15 05:21:29 -07:00
|
|
|
info.saplingActivationHeight = UInt64(network.constants.saplingActivationHeight)
|
2021-07-28 15:25:47 -07:00
|
|
|
})
|
2019-10-18 11:45:19 -07:00
|
|
|
|
2019-10-30 13:18:57 -07:00
|
|
|
let storage = CompactBlockStorage.init(connectionProvider: SimpleConnectionProvider(path: processorConfig.cacheDb.absoluteString))
|
|
|
|
try! storage.createTable()
|
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
processor = CompactBlockProcessor(
|
|
|
|
service: service,
|
|
|
|
storage: storage,
|
|
|
|
backend: ZcashRustBackend.self,
|
|
|
|
config: processorConfig
|
|
|
|
)
|
2022-08-24 08:38:42 -07:00
|
|
|
let dbInit = try ZcashRustBackend.initDataDb(dbData: processorConfig.dataDb, seed: nil, networkType: .testnet)
|
|
|
|
|
|
|
|
guard case .success = dbInit else {
|
|
|
|
XCTFail("Failed to initDataDb. Expected `.success` got: \(dbInit)")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
downloadStartedExpect = XCTestExpectation(description: "\(self.description) downloadStartedExpect")
|
|
|
|
stopNotificationExpectation = XCTestExpectation(description: "\(self.description) stopNotificationExpectation")
|
|
|
|
updatedNotificationExpectation = XCTestExpectation(description: "\(self.description) updatedNotificationExpectation")
|
|
|
|
startedValidatingNotificationExpectation = XCTestExpectation(
|
|
|
|
description: "\(self.description) startedValidatingNotificationExpectation"
|
|
|
|
)
|
|
|
|
startedScanningNotificationExpectation = XCTestExpectation(
|
|
|
|
description: "\(self.description) startedScanningNotificationExpectation"
|
|
|
|
)
|
|
|
|
idleNotificationExpectation = XCTestExpectation(description: "\(self.description) idleNotificationExpectation")
|
|
|
|
NotificationCenter.default.addObserver(
|
|
|
|
self,
|
|
|
|
selector: #selector(processorFailed(_:)),
|
|
|
|
name: Notification.Name.blockProcessorFailed,
|
|
|
|
object: processor
|
|
|
|
)
|
2019-10-18 11:45:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
override func tearDown() {
|
2021-09-23 06:26:41 -07:00
|
|
|
super.tearDown()
|
2019-10-30 13:18:57 -07:00
|
|
|
try! FileManager.default.removeItem(at: processorConfig.cacheDb)
|
2019-11-01 12:59:16 -07:00
|
|
|
try? FileManager.default.removeItem(at: processorConfig.dataDb)
|
2019-10-30 13:18:57 -07:00
|
|
|
downloadStartedExpect.unsubscribeFromNotifications()
|
|
|
|
stopNotificationExpectation.unsubscribeFromNotifications()
|
|
|
|
updatedNotificationExpectation.unsubscribeFromNotifications()
|
|
|
|
startedScanningNotificationExpectation.unsubscribeFromNotifications()
|
|
|
|
startedValidatingNotificationExpectation.unsubscribeFromNotifications()
|
|
|
|
idleNotificationExpectation.unsubscribeFromNotifications()
|
|
|
|
NotificationCenter.default.removeObserver(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
@objc func processorFailed(_ notification: Notification) {
|
|
|
|
XCTAssertNotNil(notification.userInfo)
|
|
|
|
if let error = notification.userInfo?["error"] {
|
|
|
|
XCTFail("CompactBlockProcessor failed with Error: \(error)")
|
|
|
|
} else {
|
|
|
|
XCTFail("CompactBlockProcessor failed")
|
2019-10-18 11:45:19 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-27 03:51:38 -07:00
|
|
|
private func startProcessing() async {
|
2019-10-18 11:45:19 -07:00
|
|
|
XCTAssertNotNil(processor)
|
|
|
|
|
2019-10-30 13:18:57 -07:00
|
|
|
// Subscribe to notifications
|
|
|
|
downloadStartedExpect.subscribe(to: Notification.Name.blockProcessorStartedDownloading, object: processor)
|
|
|
|
stopNotificationExpectation.subscribe(to: Notification.Name.blockProcessorStopped, object: processor)
|
|
|
|
updatedNotificationExpectation.subscribe(to: Notification.Name.blockProcessorUpdated, object: processor)
|
|
|
|
startedValidatingNotificationExpectation.subscribe(to: Notification.Name.blockProcessorStartedValidating, object: processor)
|
|
|
|
startedScanningNotificationExpectation.subscribe(to: Notification.Name.blockProcessorStartedScanning, object: processor)
|
2022-10-27 16:09:08 -07:00
|
|
|
idleNotificationExpectation.subscribe(to: Notification.Name.blockProcessorIdle, object: processor)
|
2019-10-18 11:45:19 -07:00
|
|
|
|
2022-10-27 03:51:38 -07:00
|
|
|
do {
|
|
|
|
try await processor.start()
|
|
|
|
} catch {
|
|
|
|
XCTFail("shouldn't fail")
|
|
|
|
}
|
2019-10-31 10:33:21 -07:00
|
|
|
}
|
2022-10-27 16:09:08 -07:00
|
|
|
|
|
|
|
// FIXME: disabled see https://github.com/zcash/ZcashLightClientKit/issues/590
|
2022-10-27 03:51:38 -07:00
|
|
|
func testStartNotifiesSuscriptors() async {
|
|
|
|
await startProcessing()
|
2019-10-30 13:18:57 -07:00
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
wait(
|
|
|
|
for: [
|
|
|
|
downloadStartedExpect,
|
|
|
|
startedValidatingNotificationExpectation,
|
|
|
|
startedScanningNotificationExpectation,
|
|
|
|
idleNotificationExpectation
|
|
|
|
],
|
|
|
|
timeout: 30,
|
2022-10-27 16:09:08 -07:00
|
|
|
enforceOrder: false
|
2021-09-23 06:26:41 -07:00
|
|
|
)
|
2019-10-18 11:45:19 -07:00
|
|
|
}
|
2022-10-27 16:09:08 -07:00
|
|
|
|
|
|
|
// FIXME: disabled see https://github.com/zcash/ZcashLightClientKit/issues/590
|
2022-10-27 03:51:38 -07:00
|
|
|
func testProgressNotifications() async {
|
2021-09-23 06:26:41 -07:00
|
|
|
let expectedUpdates = expectedBatches(
|
|
|
|
currentHeight: processorConfig.walletBirthday,
|
|
|
|
targetHeight: mockLatestHeight,
|
|
|
|
batchSize: processorConfig.downloadBatchSize
|
|
|
|
)
|
2019-10-31 10:33:21 -07:00
|
|
|
updatedNotificationExpectation.expectedFulfillmentCount = expectedUpdates
|
|
|
|
|
2022-10-27 03:51:38 -07:00
|
|
|
await startProcessing()
|
2019-12-03 09:11:24 -08:00
|
|
|
wait(for: [updatedNotificationExpectation], timeout: 300)
|
2019-10-31 10:33:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private func expectedBatches(currentHeight: BlockHeight, targetHeight: BlockHeight, batchSize: Int) -> Int {
|
2021-09-23 06:26:41 -07:00
|
|
|
(abs(currentHeight - targetHeight) / batchSize)
|
2019-10-31 10:33:21 -07:00
|
|
|
}
|
|
|
|
|
2019-10-30 13:18:57 -07:00
|
|
|
func testNextBatchBlockRange() {
|
|
|
|
// test first range
|
|
|
|
var latestDownloadedHeight = processorConfig.walletBirthday // this can be either this or Wallet Birthday.
|
2021-09-15 05:21:29 -07:00
|
|
|
var latestBlockchainHeight = BlockHeight(network.constants.saplingActivationHeight + 1000)
|
2019-10-30 13:18:57 -07:00
|
|
|
|
2021-06-17 14:03:42 -07:00
|
|
|
var expectedBatchRange = CompactBlockRange(uncheckedBounds: (lower: latestDownloadedHeight, upper:latestBlockchainHeight))
|
2019-10-30 13:18:57 -07:00
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
XCTAssertEqual(
|
|
|
|
expectedBatchRange,
|
|
|
|
CompactBlockProcessor.nextBatchBlockRange(
|
|
|
|
latestHeight: latestBlockchainHeight,
|
|
|
|
latestDownloadedHeight: latestDownloadedHeight,
|
|
|
|
walletBirthday: processorConfig.walletBirthday
|
|
|
|
)
|
|
|
|
)
|
2019-10-30 13:18:57 -07:00
|
|
|
|
|
|
|
// Test mid-range
|
2022-07-29 06:07:08 -07:00
|
|
|
latestDownloadedHeight = BlockHeight(network.constants.saplingActivationHeight + ZcashSDK.DefaultDownloadBatch)
|
2021-09-15 05:21:29 -07:00
|
|
|
latestBlockchainHeight = BlockHeight(network.constants.saplingActivationHeight + 1000)
|
2019-10-30 13:18:57 -07:00
|
|
|
|
2021-06-17 14:03:42 -07:00
|
|
|
expectedBatchRange = CompactBlockRange(uncheckedBounds: (lower: latestDownloadedHeight + 1, upper: latestBlockchainHeight))
|
2019-10-30 13:18:57 -07:00
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
XCTAssertEqual(
|
|
|
|
expectedBatchRange,
|
|
|
|
CompactBlockProcessor.nextBatchBlockRange(
|
|
|
|
latestHeight: latestBlockchainHeight,
|
|
|
|
latestDownloadedHeight: latestDownloadedHeight,
|
|
|
|
walletBirthday: processorConfig.walletBirthday
|
|
|
|
)
|
|
|
|
)
|
2019-10-30 13:18:57 -07:00
|
|
|
|
|
|
|
// Test last batch range
|
|
|
|
|
2021-09-15 05:21:29 -07:00
|
|
|
latestDownloadedHeight = BlockHeight(network.constants.saplingActivationHeight + 950)
|
|
|
|
latestBlockchainHeight = BlockHeight(network.constants.saplingActivationHeight + 1000)
|
2019-10-30 13:18:57 -07:00
|
|
|
|
|
|
|
expectedBatchRange = CompactBlockRange(uncheckedBounds: (lower: latestDownloadedHeight + 1, upper: latestBlockchainHeight))
|
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
XCTAssertEqual(
|
|
|
|
expectedBatchRange,
|
|
|
|
CompactBlockProcessor.nextBatchBlockRange(
|
|
|
|
latestHeight: latestBlockchainHeight,
|
|
|
|
latestDownloadedHeight: latestDownloadedHeight,
|
|
|
|
walletBirthday: processorConfig.walletBirthday
|
|
|
|
)
|
|
|
|
)
|
2019-10-30 13:18:57 -07:00
|
|
|
}
|
2020-01-29 19:11:40 -08:00
|
|
|
|
2022-10-27 03:51:38 -07:00
|
|
|
func testDetermineLowerBoundPastBirthday() async {
|
2020-01-29 19:11:40 -08:00
|
|
|
let errorHeight = 781_906
|
|
|
|
|
|
|
|
let walletBirthday = 781_900
|
|
|
|
|
2022-10-27 03:51:38 -07:00
|
|
|
let result = await processor.determineLowerBound(errorHeight: errorHeight, consecutiveErrors: 1, walletBirthday: walletBirthday)
|
2020-02-07 13:04:21 -08:00
|
|
|
let expected = 781_886
|
2020-01-29 19:11:40 -08:00
|
|
|
|
|
|
|
XCTAssertEqual(result, expected)
|
|
|
|
}
|
|
|
|
|
2022-10-27 03:51:38 -07:00
|
|
|
func testDetermineLowerBound() async {
|
2020-01-29 19:11:40 -08:00
|
|
|
let errorHeight = 781_906
|
|
|
|
|
|
|
|
let walletBirthday = 780_900
|
|
|
|
|
2022-10-27 03:51:38 -07:00
|
|
|
let result = await processor.determineLowerBound(errorHeight: errorHeight, consecutiveErrors: 0, walletBirthday: walletBirthday)
|
2020-01-29 19:11:40 -08:00
|
|
|
let expected = 781_896
|
|
|
|
|
|
|
|
XCTAssertEqual(result, expected)
|
|
|
|
}
|
2019-10-18 11:45:19 -07:00
|
|
|
}
|