ZcashLightClientKit/Tests/NetworkTests/BlockScanTests.swift

204 lines
7.4 KiB
Swift

//
// BlockScanTests.swift
// ZcashLightClientKitTests
//
// Created by Francisco Gindre on 10/17/19.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import XCTest
import SQLite
@testable import TestUtils
@testable import ZcashLightClientKit
// swiftlint:disable implicitly_unwrapped_optional force_try force_unwrapping print_function_usage
class BlockScanTests: XCTestCase {
let rustWelding = ZcashRustBackend.self
var cacheDbURL: URL!
var dataDbURL: URL!
var saplingExtendedKey = SaplingExtendedFullViewingKey(validatedEncoding: "zxviewtestsapling1qw88ayg8qqqqpqyhg7jnh9mlldejfqwu46pm40ruwstd8znq3v3l4hjf33qcu2a5e36katshcfhcxhzgyfugj2lkhmt40j45cv38rv3frnghzkxcx73k7m7afw9j7ujk7nm4dx5mv02r26umxqgar7v3x390w2h3crqqgjsjly7jy4vtwzrmustm5yudpgcydw7x78awca8wqjvkqj8p8e3ykt7lrgd7xf92fsfqjs5vegfsja4ekzpfh5vtccgvs5747xqm6qflmtqpr8s9u")
var walletBirthDay = Checkpoint.birthday(
with: 1386000,
network: ZcashNetworkBuilder.network(for: .testnet)
)
var network = ZcashNetworkBuilder.network(for: .testnet)
var blockRepository: BlockRepository!
override func setUp() {
// Put setup code here. This method is called before the invocation of each test method in the class.
super.setUp()
self.cacheDbURL = try! __cacheDbURL()
self.dataDbURL = try! __dataDbURL()
deleteDBs()
}
private func deleteDBs() {
try? FileManager.default.removeItem(at: cacheDbURL)
try? FileManager.default.removeItem(at: dataDbURL)
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
try? FileManager.default.removeItem(at: cacheDbURL)
try? FileManager.default.removeItem(at: dataDbURL)
}
func testSingleDownloadAndScan() async throws {
logger = SampleLogger(logLevel: .debug)
XCTAssertNoThrow(try rustWelding.initDataDb(dbData: dataDbURL, seed: nil, networkType: network.networkType))
let storage = try! TestDbBuilder.inMemoryCompactBlockStorage()
let service = LightWalletGRPCService(
endpoint: LightWalletEndpoint(
address: "lightwalletd.testnet.electriccoin.co",
port: 9067
)
)
let blockCount = 100
let range = network.constants.saplingActivationHeight ... network.constants.saplingActivationHeight + blockCount
let downloader = CompactBlockDownloader.sqlDownloader(
service: service,
at: cacheDbURL
)!
let processorConfig = CompactBlockProcessor.Configuration.standard(
for: network,
walletBirthday: network.constants.saplingActivationHeight
)
let compactBlockProcessor = CompactBlockProcessor(
service: service,
storage: storage,
backend: ZcashRustBackend.self,
config: processorConfig
)
let repository = BlockSQLDAO(dbProvider: SimpleConnectionProvider.init(path: self.dataDbURL.absoluteString, readonly: true))
var latestScannedheight = BlockHeight.empty()
do {
try await compactBlockProcessor.compactBlockDownload(
downloader: downloader,
range: range
)
XCTAssertFalse(Task.isCancelled)
try await compactBlockProcessor.compactBlockScanning(
rustWelding: rustWelding,
cacheDb: cacheDbURL,
dataDb: dataDbURL,
networkType: network.networkType
)
latestScannedheight = repository.lastScannedBlockHeight()
XCTAssertEqual(latestScannedheight, range.upperBound)
} catch {
XCTFail("Download failed with error: \(error)")
}
}
@objc func observeBenchmark(_ notification: Notification) {
guard let report = SDKMetrics.blockReportFromNotification(notification) else {
return
}
print("observed benchmark: \(report)")
}
func testScanValidateDownload() async throws {
let seed = "testreferencealicetestreferencealice"
logger = SampleLogger(logLevel: .debug)
NotificationCenter.default.addObserver(
self,
selector: #selector(observeBenchmark(_:)),
name: SDKMetrics.notificationName,
object: nil
)
guard try self.rustWelding.initDataDb(dbData: dataDbURL, seed: nil, networkType: network.networkType) == .success else {
XCTFail("Seed should not be required for this test")
return
}
let derivationTool = DerivationTool(networkType: .testnet)
let ufvk = try derivationTool
.deriveUnifiedSpendingKey(seed: Array(seed.utf8), accountIndex: 0)
.map { try derivationTool.deriveUnifiedFullViewingKey(from: $0) }
do {
try self.rustWelding.initAccountsTable(
dbData: self.dataDbURL,
ufvks: [ufvk],
networkType: network.networkType
)
} catch {
XCTFail("failed to init account table. error: \(self.rustWelding.getLastError() ?? "no error found")")
return
}
try self.rustWelding.initBlocksTable(
dbData: dataDbURL,
height: Int32(walletBirthDay.height),
hash: walletBirthDay.hash,
time: walletBirthDay.time,
saplingTree: walletBirthDay.saplingTree,
networkType: network.networkType
)
let service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet)
let storage = CompactBlockStorage(url: cacheDbURL, readonly: false)
try storage.createTable()
var processorConfig = CompactBlockProcessor.Configuration(
cacheDb: cacheDbURL,
dataDb: dataDbURL,
walletBirthday: network.constants.saplingActivationHeight,
network: network
)
processorConfig.scanningBatchSize = 1000
let compactBlockProcessor = CompactBlockProcessor(
service: service,
storage: storage,
backend: rustWelding,
config: processorConfig
)
let range = CompactBlockRange(
uncheckedBounds: (walletBirthDay.height, walletBirthDay.height + 10000)
)
do {
try await compactBlockProcessor.compactBlockStreamDownload(
blockBufferSize: 10,
startHeight: range.lowerBound,
targetHeight: range.upperBound
)
XCTAssertFalse(Task.isCancelled)
try await compactBlockProcessor.compactBlockValidation()
XCTAssertFalse(Task.isCancelled)
try await compactBlockProcessor.compactBlockBatchScanning(range: range)
XCTAssertFalse(Task.isCancelled)
} catch {
if let lwdError = error as? LightWalletServiceError {
switch lwdError {
case .timeOut:
XCTAssert(true)
default:
XCTFail("LWD Service error found, but should have been a timeLimit reached Error - \(lwdError)")
}
} else {
XCTFail("Error should have been a timeLimit reached Error - \(error)")
}
}
}
}