// // Stubs.swift // ZcashLightClientKitTests // // Created by Francisco Gindre on 18/09/2019. // Copyright © 2019 Electric Coin Company. All rights reserved. // import Foundation import GRPC import SwiftProtobuf @testable import ZcashLightClientKit extension String: Error { } class AwfulLightWalletService: MockLightWalletService { override func latestBlockHeight() async throws -> BlockHeight { throw ZcashError.serviceLatestBlockFailed(.criticalError) } override func blockRange(_ range: CompactBlockRange) -> AsyncThrowingStream { AsyncThrowingStream { continuation in continuation.finish(throwing: ZcashError.serviceSubmitFailed(.invalidBlock)) } } /// Submits a raw transaction over lightwalletd. override func submit(spendTransaction: Data) async throws -> LightWalletServiceResponse { throw ZcashError.serviceSubmitFailed(.invalidBlock) } } extension LightWalletServiceMockResponse: Error { } class SlightlyBadLightWalletService: MockLightWalletService { /// Submits a raw transaction over lightwalletd. override func submit(spendTransaction: Data) async throws -> LightWalletServiceResponse { throw LightWalletServiceMockResponse.error } } extension LightWalletServiceMockResponse { static var error: LightWalletServiceMockResponse { LightWalletServiceMockResponse( errorCode: -100, errorMessage: "Ohhh this is bad, really bad, you lost all your internet money", unknownFields: UnknownStorage() ) } static var success: LightWalletServiceMockResponse { LightWalletServiceMockResponse(errorCode: 0, errorMessage: "", unknownFields: UnknownStorage()) } } class RustBackendMockHelper { let rustBackendMock: ZcashRustBackendWeldingMock init( rustBackend: ZcashRustBackendWelding, consensusBranchID: Int32? = nil ) async { self.rustBackendMock = ZcashRustBackendWeldingMock( consensusBranchIdForHeightClosure: { height in if let consensusBranchID { return consensusBranchID } else { return try rustBackend.consensusBranchIdFor(height: height) } } ) await setupDefaultMock(rustBackend: rustBackend) } private func setupDefaultMock(rustBackend: ZcashRustBackendWelding) async { await rustBackendMock.setLatestCachedBlockHeightReturnValue(.empty()) await rustBackendMock.setInitBlockMetadataDbClosure() { } await rustBackendMock.setWriteBlocksMetadataBlocksClosure() { _ in } await rustBackendMock.setGetTransparentBalanceAccountReturnValue(0) await rustBackendMock.setListTransparentReceiversAccountReturnValue([]) await rustBackendMock.setGetCurrentAddressAccountThrowableError(ZcashError.rustGetCurrentAddress("mocked error")) await rustBackendMock.setGetNextAvailableAddressAccountThrowableError(ZcashError.rustGetNextAvailableAddress("mocked error")) await rustBackendMock.setCreateAccountSeedTreeStateRecoverUntilThrowableError(ZcashError.rustInitAccountsTableViewingKeyCotainsNullBytes) await rustBackendMock.setGetMemoTxIdOutputIndexReturnValue(nil) await rustBackendMock.setInitDataDbSeedReturnValue(.seedRequired) await rustBackendMock.setGetNearestRewindHeightHeightReturnValue(-1) await rustBackendMock.setPutUnspentTransparentOutputTxidIndexScriptValueHeightClosure() { _, _, _, _, _ in } await rustBackendMock.setProposeTransferAccountToValueMemoThrowableError(ZcashError.rustCreateToAddress("mocked error")) await rustBackendMock.setProposeShieldingAccountMemoShieldingThresholdThrowableError(ZcashError.rustShieldFunds("mocked error")) await rustBackendMock.setCreateProposedTransactionProposalUskThrowableError(ZcashError.rustCreateToAddress("mocked error")) await rustBackendMock.setDecryptAndStoreTransactionTxBytesMinedHeightThrowableError(ZcashError.rustDecryptAndStoreTransaction("mock fail")) await rustBackendMock.setInitDataDbSeedClosure() { seed in return try await rustBackend.initDataDb(seed: seed) } await rustBackendMock.setRewindToHeightHeightClosure() { height in try await rustBackend.rewindToHeight(height: height) } await rustBackendMock.setRewindCacheToHeightHeightClosure() { _ in } await rustBackendMock.setSuggestScanRangesClosure() { try await rustBackend.suggestScanRanges() } await rustBackendMock.setScanBlocksFromHeightLimitClosure() { fromHeight, limit in try await rustBackend.scanBlocks(fromHeight: fromHeight, limit: limit) } } private static func shouldSucceed(successRate: Float) -> Bool { let random = Float.random(in: 0.0...1.0) return random <= successRate } } extension SaplingParamsSourceURL { static let tests = SaplingParamsSourceURL( spendParamFileURL: Bundle.module.url(forResource: "sapling-spend", withExtension: "params")!, outputParamFileURL: Bundle.module.url(forResource: "sapling-output", withExtension: "params")! ) } extension CompactBlockProcessor.Configuration { /// Standard configuration for most compact block processors static func standard( alias: ZcashSynchronizerAlias = .default, for network: ZcashNetwork, walletBirthday: BlockHeight ) -> CompactBlockProcessor.Configuration { let pathProvider = DefaultResourceProvider(network: network) return CompactBlockProcessor.Configuration( alias: alias, fsBlockCacheRoot: pathProvider.fsCacheURL, dataDb: pathProvider.dataDbURL, spendParamsURL: pathProvider.spendParamsURL, outputParamsURL: pathProvider.outputParamsURL, saplingParamsSourceURL: SaplingParamsSourceURL.tests, walletBirthdayProvider: { walletBirthday }, network: network ) } } extension SynchronizerState { static var mock: SynchronizerState { SynchronizerState( syncSessionID: .nullID, accountBalance: AccountBalance(saplingBalance: .zero, unshielded: Zatoshi(200)), internalSyncStatus: .syncing(0), latestBlockHeight: 222222 ) } }