diff --git a/Example/ZcashLightClientSample/Podfile b/Example/ZcashLightClientSample/Podfile index 862581ce..3d1162c7 100644 --- a/Example/ZcashLightClientSample/Podfile +++ b/Example/ZcashLightClientSample/Podfile @@ -6,6 +6,7 @@ target 'ZcashLightClientSample' do pod "KRProgressHUD" # Pods for ZcashLightClientSample pod 'ZcashLightClientKit', :path => '../../', :testspecs => ['Tests'] + pod 'gRPC-Swift', '~> 1.0.0-alpha.11' pod 'PaginatedTableView' pod 'NotificationBubbles' target 'ZcashLightClientSampleTests' do diff --git a/Example/ZcashLightClientSample/Podfile.lock b/Example/ZcashLightClientSample/Podfile.lock index c6a9cc33..05ebb0ee 100644 --- a/Example/ZcashLightClientSample/Podfile.lock +++ b/Example/ZcashLightClientSample/Podfile.lock @@ -1,43 +1,77 @@ PODS: - - BoringSSL-GRPC (0.0.3): - - BoringSSL-GRPC/Implementation (= 0.0.3) - - BoringSSL-GRPC/Interface (= 0.0.3) - - BoringSSL-GRPC/Implementation (0.0.3): - - BoringSSL-GRPC/Interface (= 0.0.3) - - BoringSSL-GRPC/Interface (0.0.3) - - gRPC-Core (1.23.1): - - gRPC-Core/Implementation (= 1.23.1) - - gRPC-Core/Interface (= 1.23.1) - - gRPC-Core/Implementation (1.23.1): - - BoringSSL-GRPC (= 0.0.3) - - gRPC-Core/Interface (= 1.23.1) - - nanopb (~> 0.3) - - gRPC-Core/Interface (1.23.1) + - CGRPCZlib (1.0.0-alpha.11) + - CNIOAtomics (2.15.0) + - CNIOBoringSSL (2.7.1) + - CNIOBoringSSLShims (2.7.1): + - CNIOBoringSSL (= 2.7.1) + - CNIODarwin (2.15.0) + - CNIOHTTPParser (2.15.0) + - CNIOLinux (2.15.0) + - CNIOSHA1 (2.15.0) + - gRPC-Swift (1.0.0-alpha.11): + - CGRPCZlib (= 1.0.0-alpha.11) + - Logging (= 1.2.0) + - SwiftNIO (= 2.15.0) + - SwiftNIOHTTP2 (= 1.11.0) + - SwiftNIOSSL (= 2.7.1) + - SwiftNIOTransportServices (= 1.3.0) + - SwiftProtobuf (= 1.8.0) - KRActivityIndicatorView (3.0.4) - KRProgressHUD (3.4.4): - KRActivityIndicatorView (= 3.0.4) - - nanopb (0.3.9011): - - nanopb/decode (= 0.3.9011) - - nanopb/encode (= 0.3.9011) - - nanopb/decode (0.3.9011) - - nanopb/encode (0.3.9011) + - Logging (1.2.0) - NotificationBubbles (0.1.1) - - PaginatedTableView (0.1.0) + - PaginatedTableView (1.0.1) - SQLite.swift (0.12.2): - SQLite.swift/standard (= 0.12.2) - SQLite.swift/standard (0.12.2) - - SwiftGRPC (0.10.0): - - gRPC-Core (~> 1.23.0) - - SwiftProtobuf (~> 1.7.0) - - SwiftProtobuf (1.7.0) - - ZcashLightClientKit (0.3.2): + - SwiftNIO (2.15.0): + - CNIOAtomics (= 2.15.0) + - CNIODarwin (= 2.15.0) + - CNIOLinux (= 2.15.0) + - CNIOSHA1 (= 2.15.0) + - SwiftNIOConcurrencyHelpers (= 2.15.0) + - SwiftNIOConcurrencyHelpers (2.15.0): + - CNIOAtomics (= 2.15.0) + - SwiftNIOFoundationCompat (2.15.0): + - SwiftNIO (= 2.15.0) + - SwiftNIOHPACK (1.11.0): + - SwiftNIO (= 2.15.0) + - SwiftNIOConcurrencyHelpers (= 2.15.0) + - SwiftNIOHTTP1 (= 2.15.0) + - SwiftNIOHTTP1 (2.15.0): + - CNIOHTTPParser (= 2.15.0) + - SwiftNIO (= 2.15.0) + - SwiftNIOConcurrencyHelpers (= 2.15.0) + - SwiftNIOHTTP2 (1.11.0): + - SwiftNIO (= 2.15.0) + - SwiftNIOConcurrencyHelpers (= 2.15.0) + - SwiftNIOHPACK (= 1.11.0) + - SwiftNIOHTTP1 (= 2.15.0) + - SwiftNIOTLS (= 2.15.0) + - SwiftNIOSSL (2.7.1): + - CNIOBoringSSL (= 2.7.1) + - CNIOBoringSSLShims (= 2.7.1) + - SwiftNIO (= 2.15.0) + - SwiftNIOConcurrencyHelpers (= 2.15.0) + - SwiftNIOTLS (= 2.15.0) + - SwiftNIOTLS (2.15.0): + - SwiftNIO (= 2.15.0) + - SwiftNIOTransportServices (1.3.0): + - SwiftNIO (~> 2.0) + - SwiftNIOConcurrencyHelpers (~> 2.0) + - SwiftNIOFoundationCompat (~> 2.0) + - SwiftNIOTLS (~> 2.0) + - SwiftProtobuf (1.8.0) + - ZcashLightClientKit (0.4.0): + - gRPC-Swift (~> 1.0.0-alpha.11) - SQLite.swift (~> 0.12.2) - - SwiftGRPC (~> 0.10.0) - - ZcashLightClientKit/Tests (0.3.2): + - ZcashLightClientKit/Tests (0.4.0): + - gRPC-Swift (~> 1.0.0-alpha.11) - SQLite.swift (~> 0.12.2) - - SwiftGRPC (~> 0.10.0) DEPENDENCIES: + - gRPC-Swift (~> 1.0.0-alpha.11) - KRProgressHUD - NotificationBubbles - PaginatedTableView @@ -46,15 +80,30 @@ DEPENDENCIES: SPEC REPOS: trunk: - - BoringSSL-GRPC - - gRPC-Core + - CGRPCZlib + - CNIOAtomics + - CNIOBoringSSL + - CNIOBoringSSLShims + - CNIODarwin + - CNIOHTTPParser + - CNIOLinux + - CNIOSHA1 + - gRPC-Swift - KRActivityIndicatorView - KRProgressHUD - - nanopb + - Logging - NotificationBubbles - PaginatedTableView - SQLite.swift - - SwiftGRPC + - SwiftNIO + - SwiftNIOConcurrencyHelpers + - SwiftNIOFoundationCompat + - SwiftNIOHPACK + - SwiftNIOHTTP1 + - SwiftNIOHTTP2 + - SwiftNIOSSL + - SwiftNIOTLS + - SwiftNIOTransportServices - SwiftProtobuf EXTERNAL SOURCES: @@ -62,18 +111,33 @@ EXTERNAL SOURCES: :path: "../../" SPEC CHECKSUMS: - BoringSSL-GRPC: db8764df3204ccea016e1c8dd15d9a9ad63ff318 - gRPC-Core: 4b1148eb8596225178e5a154e40e35141a3cdf0f + CGRPCZlib: e595387378d0601be796e858dd30c505458c4b1f + CNIOAtomics: ba49b1c86f281e1ecfd84c9205fbc27a81826847 + CNIOBoringSSL: e4766830ab6d7c7fcd3618331f05fcb11638314d + CNIOBoringSSLShims: c3f3c6f05b7ce9b576521328a5b1b566d8f4665b + CNIODarwin: 2e341dd283fa3972706568b12925366145a8e2cd + CNIOHTTPParser: 25e1d1bc84c0612cbbbd6baedc4be05d77a17e01 + CNIOLinux: 61598a8e49510207acb74c87f8fc11f762f76b5a + CNIOSHA1: 7b1dcceef9682aef4c6578b9fc67f87a03f0c48e + gRPC-Swift: 79f04da038f9a62005271d5b638611ce1bb31304 KRActivityIndicatorView: 549db10b9578d58bac73db063d8b544e8970f7f2 KRProgressHUD: c3b9a48a0ee4824ea13212ac3f1efa50dca021e3 - nanopb: 18003b5e52dab79db540fe93fe9579f399bd1ccd + Logging: 7838d379d234d7e5ae1265fa02804a9084caf04c NotificationBubbles: 91ee10deee54f35b5d49a161e1cb3d788ab5d011 - PaginatedTableView: 14025b52a9f88bb1e9a87f31765eae7986ffb192 + PaginatedTableView: 294d9831d5ddf5c0dcfbb4a281d4fcfb8d12f55a SQLite.swift: d2b4642190917051ce6bd1d49aab565fe794eea3 - SwiftGRPC: f8fcfecb547c96cc6913de619f95fa3cd09838ee - SwiftProtobuf: 4fd9645e69b72cbae6ec8da5be0cdd20ca6565dd - ZcashLightClientKit: 28a8fd46d8c29486902a16f2fddc01a38c107300 + SwiftNIO: c9889dcd8aed2655af9163b42fc11ebd4ce94252 + SwiftNIOConcurrencyHelpers: 2357037a16e9c51880c01b896a5ac3cd41066044 + SwiftNIOFoundationCompat: f09ee499a8a9c636ec9007f73c5a1cedc23dcad3 + SwiftNIOHPACK: 906596511ff9d1e095b7a72a0011351591bcae03 + SwiftNIOHTTP1: b05f4061ba18482006a264a5aa087bbcd35d153c + SwiftNIOHTTP2: 3a52499594c6ec073af2a2801cf3c5d3d1c8700f + SwiftNIOSSL: 7c82b8393a6b69a3ef9b12fe74240e92c2bd7add + SwiftNIOTLS: 51580e51240d1a4d51efb2d317e92cf243181042 + SwiftNIOTransportServices: 26d40c589fc8fe667af51b06ef0aa49fbc9ae7f2 + SwiftProtobuf: 2cbd9409689b7df170d82a92a33443c8e3e14a70 + ZcashLightClientKit: 47e707be6657391d5d4fd7db1544b0d98ce45e42 -PODFILE CHECKSUM: 5a1fb98512fa179a4e83d67d14dd402f6d129a4d +PODFILE CHECKSUM: 4022861094cde8ab9d9c2f650b4a4adec279287f COCOAPODS: 1.9.1 diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/DemoAppConfig.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/DemoAppConfig.swift index b9935963..dfbd9bc3 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/DemoAppConfig.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/DemoAppConfig.swift @@ -11,7 +11,7 @@ import ZcashLightClientKit struct DemoAppConfig { static var host = ZcashSDK.isMainnet ? "lightwalletd.z.cash" : "lightwalletd.testnet.z.cash" - static var port = "9067" + static var port: Int = 9067 static var birthdayHeight: BlockHeight = ZcashSDK.isMainnet ? 643_500 : 620_000 static var network = ZcashSDK.isMainnet ? ZcashNetwork.mainNet : ZcashNetwork.testNet static var seed = ZcashSDK.isMainnet ? Array("testreferencealicetestreferencealice".utf8) : Array("testreferencealicetestreferencealice".utf8) diff --git a/ZcashLightClientKit.podspec b/ZcashLightClientKit.podspec index 5499a33b..9b4dd2fe 100644 --- a/ZcashLightClientKit.podspec +++ b/ZcashLightClientKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'ZcashLightClientKit' - s.version = '0.3.2' + s.version = '0.4.0' s.summary = 'Zcash Light Client wallet SDK for iOS' s.description = <<-DESC @@ -19,7 +19,7 @@ Pod::Spec.new do |s| s.module_map = 'ZcashLightClientKit.modulemap' s.swift_version = '5.1' s.ios.deployment_target = '12.0' - s.dependency 'SwiftGRPC', '~> 0.10.0' + s.dependency 'gRPC-Swift', '~> 1.0.0-alpha.11' s.dependency 'SQLite.swift', '~> 0.12.2' s.ios.vendored_libraries = 'lib/libzcashlc.a' s.preserve_paths = ['Scripts', 'rust','docs','Cargo.*','ZcashLightClientKit/Stencil'] @@ -40,7 +40,7 @@ Pod::Spec.new do |s| :script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_test_constants.sh && ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh --testing', :execution_position => :before_compile } - test_spec.dependency 'SwiftGRPC', '~> 0.10.0' + test_spec.dependency 'gRPC-Swift', '~> 1.0.0-alpha.11' test_spec.dependency 'SQLite.swift', '~> 0.12.2' end end diff --git a/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift b/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift index 1c1b901c..8113967d 100644 --- a/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift +++ b/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift @@ -7,7 +7,7 @@ // import Foundation -import SwiftGRPC +import GRPC /** Errors thrown by CompactBlock Processor @@ -17,6 +17,7 @@ public enum CompactBlockProcessorError: Error { case missingDbPath(path: String) case dataDbInitFailed(path: String) case connectionError(message: String) + case grpcError(statusCode: Int, message: String) case generalError(message: String) case maxAttemptsReached(attempts: Int) } @@ -613,14 +614,15 @@ public class CompactBlockProcessor { default: return CompactBlockProcessorError.generalError(message: "Error: \(lwdError)") } - } else if let rpcError = error as? SwiftGRPC.RPCError { + } else if let rpcError = error as? GRPC.GRPCStatus { switch rpcError { - case .invalidMessageReceived: - return CompactBlockProcessorError.connectionError(message: "invalid GRPC Message received") - case .timedOut: - return CompactBlockProcessorError.connectionError(message: "connection timeout") - case .callError(let callResult): - return CompactBlockProcessorError.connectionError(message: "GRPC Call error. Success: \(callResult.success) - StatusCode: \(callResult.statusCode)") + case .ok: + let msg = "Error Raised when status is OK" + LoggerProxy.warn(msg) + return CompactBlockProcessorError.grpcError(statusCode: rpcError.code.rawValue, message: rpcError.message ?? "Error Raised when status is OK") + default: + return CompactBlockProcessorError.grpcError(statusCode: rpcError.code.rawValue, message: rpcError.message ?? "No message") + } } return error diff --git a/ZcashLightClientKit/Initializer.swift b/ZcashLightClientKit/Initializer.swift index 5f8b400d..1bcb78e4 100644 --- a/ZcashLightClientKit/Initializer.swift +++ b/ZcashLightClientKit/Initializer.swift @@ -23,13 +23,11 @@ public enum InitializerError: Error { Represents a lightwallet instance endpoint to connect to */ public struct LightWalletEndpoint { - public var address: String - public var port: String + public var host: String + public var port: Int public var secure: Bool - public var host: String { - "\(address):\(port)" - } + /** initializes a LightWalletEndpoint - Parameters: @@ -37,8 +35,8 @@ public struct LightWalletEndpoint { - port: string with the port of the host address - secure: true if connecting through TLS. Default value is true */ - public init(address: String, port: String, secure: Bool = true) { - self.address = address + public init(address: String, port: Int, secure: Bool = true) { + self.host = address self.port = port self.secure = secure } diff --git a/ZcashLightClientKit/Service/LightWalletGRPCService.swift b/ZcashLightClientKit/Service/LightWalletGRPCService.swift index 1b0511a0..99189fbf 100644 --- a/ZcashLightClientKit/Service/LightWalletGRPCService.swift +++ b/ZcashLightClientKit/Service/LightWalletGRPCService.swift @@ -7,7 +7,9 @@ // import Foundation -import SwiftGRPC +import GRPC +import NIO +public typealias Channel = GRPC.GRPCChannel /** Swift GRPC implementation of Lightwalletd service */ @@ -16,62 +18,59 @@ public class LightWalletGRPCService { var queue = DispatchQueue.init(label: "LightWalletGRPCService") let channel: Channel - let compactTxStreamer: CompactTxStreamerServiceClient + let compactTxStreamer: CompactTxStreamerClient public init(channel: Channel) { self.channel = channel - compactTxStreamer = CompactTxStreamerServiceClient(channel: self.channel) + compactTxStreamer = CompactTxStreamerClient(channel: self.channel) } public convenience init(endpoint: LightWalletEndpoint) { - self.init(host: endpoint.host, secure: endpoint.secure) + self.init(host: endpoint.host, port: endpoint.port, secure: endpoint.secure) } - public convenience init(host: String, secure: Bool = true) { - let channel = Channel(address: host, secure: secure, arguments: []) + public convenience init(host: String, port: Int = 9067, secure: Bool = true) { + let configuration = ClientConnection.Configuration(target: .hostAndPort(host, port), eventLoopGroup: MultiThreadedEventLoopGroup(numberOfThreads: 1), tls: secure ? .init() : nil) + let channel = ClientConnection(configuration: configuration) self.init(channel: channel) } func stop() { - channel.shutdown() + _ = channel.close() } - func resume() -> Channel.ConnectivityState { - channel.connectivityState(tryToConnect: true) - } - - func blockRange(startHeight: BlockHeight, endHeight: BlockHeight? = nil, result: @escaping (CallResult) -> Void) throws -> CompactTxStreamerGetBlockRangeCall { - try compactTxStreamer.getBlockRange(BlockRange(startHeight: startHeight, endHeight: endHeight)) { result($0) } + func blockRange(startHeight: BlockHeight, endHeight: BlockHeight? = nil, result: @escaping (CompactBlock) -> Void) throws -> ServerStreamingCall { + compactTxStreamer.getBlockRange(BlockRange(startHeight: startHeight, endHeight: endHeight), handler: result) } func latestBlock() throws -> BlockID { - try compactTxStreamer.getLatestBlock(ChainSpec()) + try compactTxStreamer.getLatestBlock(ChainSpec()).response.wait() } func getTx(hash: String) throws -> RawTransaction { var filter = TxFilter() filter.hash = Data(hash.utf8) - return try compactTxStreamer.getTransaction(filter) - } - - func getAllBlocksSinceSaplingLaunch(_ result: @escaping (CallResult) -> Void) throws -> CompactTxStreamerGetBlockRangeCall { - try compactTxStreamer.getBlockRange(BlockRange.sinceSaplingActivation(), completion: result) + return try compactTxStreamer.getTransaction(filter).response.wait() } } extension LightWalletGRPCService: LightWalletService { public func submit(spendTransaction: Data, result: @escaping (Result) -> Void) { - DispatchQueue.global(qos: .userInitiated).async { [weak self] in + do { + let tx = try RawTransaction(serializedData: spendTransaction) + let response = self.compactTxStreamer.sendTransaction(tx).response - guard let self = self else { return } - - do { - let response = try self.compactTxStreamer.sendTransaction(RawTransaction(serializedData: spendTransaction)) - result(.success(response)) - } catch { - result(.failure(LightWalletServiceError.genericError(error: error))) + response.whenComplete { (responseResult) in + switch responseResult { + case .failure(let e): + result(.failure(LightWalletServiceError.genericError(error: e))) + case .success(let s): + result(.success(s)) + } } + } catch { + result(.failure(LightWalletServiceError.genericError(error: error))) } } @@ -80,89 +79,78 @@ extension LightWalletGRPCService: LightWalletService { let rawTx = RawTransaction.with { (raw) in raw.data = spendTransaction } - return try compactTxStreamer.sendTransaction(rawTx) + return try compactTxStreamer.sendTransaction(rawTx).response.wait() } public func blockRange(_ range: CompactBlockRange) throws -> [ZcashCompactBlock] { - var blocks = [ZcashCompactBlock]() + var blocks = [CompactBlock]() - let call = try compactTxStreamer.getBlockRange(range.blockRange(), completion: { statusCode in - LoggerProxy.debug("finished with statusCode: \(statusCode)") - }) + let response = compactTxStreamer.getBlockRange(range.blockRange(), handler: { + blocks.append($0) + }) - while let block = try call.receive() { - - if let compactBlock = ZcashCompactBlock(compactBlock: block) { - blocks.append(compactBlock) - } else { - throw LightWalletServiceError.invalidBlock - } + do { + _ = try response.status.wait() + } catch { + throw LightWalletServiceError.genericError(error: error) } - return blocks + do { + return try blocks.asZcashCompactBlocks() + } catch { + LoggerProxy.error("invalid block in range: \(range) - Error: \(error)") + throw LightWalletServiceError.genericError(error: error) + } } public func latestBlockHeight(result: @escaping (Result) -> Void) { - do { - try compactTxStreamer.getLatestBlock(ChainSpec()) { (blockID, callResult) in - guard let rawHeight = blockID?.height, let blockHeight = Int(exactly: rawHeight) else { - result(.failure(LightWalletServiceError.failed(statusCode: callResult.statusCode, message: callResult.statusMessage ?? "No message"))) - return - } - result(.success(blockHeight)) + let response = compactTxStreamer.getLatestBlock(ChainSpec()).response + + response.whenSuccess { (blockID) in + guard let blockHeight = Int(exactly: blockID.height) else { + result(.failure(LightWalletServiceError.generalError)) + return } - } catch { - // TODO: Handle Error - LoggerProxy.debug(error.localizedDescription) - result(.failure(LightWalletServiceError.generalError)) + result(.success(blockHeight)) } + + response.whenFailure { (error) in + result(.failure(LightWalletServiceError.genericError(error: error))) + } + } // TODO: Make cancellable public func blockRange(_ range: CompactBlockRange, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void) { + + queue.async { [weak self] in guard let self = self else { return } var blocks = [CompactBlock]() - var isSyncing = true - guard let response = try? self.compactTxStreamer.getBlockRange(range.blockRange(),completion: { (callResult) in - isSyncing = false - if callResult.success { - let code = callResult.statusCode - switch code{ - case .ok: - do { - result(.success(try blocks.asZcashCompactBlocks())) - } catch { - result(.failure(LightWalletServiceError.generalError)) - } - default: - result(.failure(LightWalletServiceError.failed(statusCode: code, message: callResult.statusMessage ?? "No Message"))) - } - - } else { - result(.failure(LightWalletServiceError.generalError)) - return - } - }) else { - result(.failure(LightWalletServiceError.generalError)) - return - } + + let response = self.compactTxStreamer.getBlockRange(range.blockRange(), handler: { blocks.append($0) }) + do { - - var element: CompactBlock? - repeat { - element = try response.receive() - if let e = element { - blocks.append(e) + let status = try response.status.wait() + switch status.code { + case .ok: + do { + result(.success(try blocks.asZcashCompactBlocks())) + } catch { + result(.failure(LightWalletServiceError.generalError)) } - } while isSyncing && element != nil + + default: + result(Result.failure(LightWalletServiceError.failed(statusCode: status.code.rawValue, message: status.message ?? "No Message"))) + } } catch { - result(.failure(LightWalletServiceError.generalError)) + result(.failure(LightWalletServiceError.genericError(error: error))) } + } } diff --git a/ZcashLightClientKit/Service/LightWalletService.swift b/ZcashLightClientKit/Service/LightWalletService.swift index c429589e..9501250b 100644 --- a/ZcashLightClientKit/Service/LightWalletService.swift +++ b/ZcashLightClientKit/Service/LightWalletService.swift @@ -7,7 +7,7 @@ // import Foundation -import SwiftGRPC +import GRPC import SwiftProtobuf /** @@ -15,7 +15,7 @@ import SwiftProtobuf */ public enum LightWalletServiceError: Error { case generalError - case failed(statusCode: StatusCode, message: String) + case failed(statusCode: Int, message: String) case invalidBlock case sentFailed(sendResponse: LightWalletServiceResponse) case genericError(error: Error) diff --git a/ZcashLightClientKit/Service/ProtoBuf/compact_formats.pb.swift b/ZcashLightClientKit/Service/ProtoBuf/compact_formats.pb.swift index dea79fe2..5027857b 100644 --- a/ZcashLightClientKit/Service/ProtoBuf/compact_formats.pb.swift +++ b/ZcashLightClientKit/Service/ProtoBuf/compact_formats.pb.swift @@ -3,7 +3,7 @@ // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: compact_formats.proto // -// For information on using the generated types, please see the documenation: +// For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ // Copyright (c) 2019-2020 The Zcash developers @@ -16,7 +16,7 @@ import SwiftProtobuf // If the compiler emits an error on this type, it is because this file // was generated by a version of the `protoc` Swift plug-in that is // incompatible with the version of SwiftProtobuf to which you are linking. -// Please ensure that your are building against the same version of the API +// Please ensure that you are building against the same version of the API // that was used to generate this file. fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} diff --git a/ZcashLightClientKit/Service/ProtoBuf/proto/compact_formats.proto b/ZcashLightClientKit/Service/ProtoBuf/proto/compact_formats.proto deleted file mode 100644 index 69a404ca..00000000 --- a/ZcashLightClientKit/Service/ProtoBuf/proto/compact_formats.proto +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2019-2020 The Zcash developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or https://www.opensource.org/licenses/mit-license.php . - -syntax = "proto3"; -package cash.z.wallet.sdk.rpc; -option go_package = "walletrpc"; -option swift_prefix = ""; -// Remember that proto3 fields are all optional. A field that is not present will be set to its zero value. -// bytes fields of hashes are in canonical little-endian format. - -// CompactBlock is a packaging of ONLY the data from a block that's needed to: -// 1. Detect a payment to your shielded Sapling address -// 2. Detect a spend of your shielded Sapling notes -// 3. Update your witnesses to generate new Sapling spend proofs. -message CompactBlock { - uint32 protoVersion = 1; // the version of this wire format, for storage - uint64 height = 2; // the height of this block - bytes hash = 3; - bytes prevHash = 4; - uint32 time = 5; - bytes header = 6; // (hash, prevHash, and time) OR (full header) - repeated CompactTx vtx = 7; // compact transactions from this block -} - -// Index and hash will allow the receiver to call out to chain -// explorers or other data structures to retrieve more information -// about this transaction. -message CompactTx { - uint64 index = 1; - bytes hash = 2; - - // The transaction fee: present if server can provide. In the case of a - // stateless server and a transaction with transparent inputs, this will be - // unset because the calculation requires reference to prior transactions. - // in a pure-Sapling context, the fee will be calculable as: - // valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut)) - uint32 fee = 3; - - repeated CompactSpend spends = 4; - repeated CompactOutput outputs = 5; -} - -message CompactSpend { - bytes nf = 1; -} - -message CompactOutput { - bytes cmu = 1; - bytes epk = 2; - bytes ciphertext = 3; -} diff --git a/ZcashLightClientKit/Service/ProtoBuf/proto/service.proto b/ZcashLightClientKit/Service/ProtoBuf/proto/service.proto deleted file mode 100644 index 6a77c844..00000000 --- a/ZcashLightClientKit/Service/ProtoBuf/proto/service.proto +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2019-2020 The Zcash developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or https://www.opensource.org/licenses/mit-license.php . - -syntax = "proto3"; -package cash.z.wallet.sdk.rpc; -option go_package = "walletrpc"; -option swift_prefix = ""; -import "compact_formats.proto"; - -// A BlockID message contains identifiers to select a block: a height or a -// hash. Specification by hash is not implemented, but may be in the future. -message BlockID { - uint64 height = 1; - bytes hash = 2; -} - -// BlockRange specifies a series of blocks from start to end inclusive. -// Both BlockIDs must be heights; specification by hash is not yet supported. -message BlockRange { - BlockID start = 1; - BlockID end = 2; -} - -// A TxFilter contains the information needed to identify a particular -// transaction: either a block and an index, or a direct transaction hash. -// Currently, only specification by hash is supported. -message TxFilter { - BlockID block = 1; - uint64 index = 2; - bytes hash = 3; -} - -// RawTransaction contains the complete transaction data. It also optionally includes -// the block height in which the transaction was included -message RawTransaction { - bytes data = 1; - uint64 height = 2; -} - -// A SendResponse encodes an error code and a string. It is currently used -// only by SendTransaction(). If error code is zero, the operation was -// successful; if non-zero, it and the message specify the failure. -message SendResponse { - int32 errorCode = 1; - string errorMessage = 2; -} - -// Chainspec is a placeholder to allow specification of a particular chain fork. -message ChainSpec {} - -// Empty is for gRPCs that take no arguments, currently only GetLightdInfo. -message Empty {} - -// LightdInfo returns various information about this lightwalletd instance -// and the state of the blockchain. -message LightdInfo { - string version = 1; - string vendor = 2; - bool taddrSupport = 3; - string chainName = 4; - uint64 saplingActivationHeight = 5; - string consensusBranchId = 6; - uint64 blockHeight = 7; -} - -// TransparentAddressBlockFilter restricts the results to the given address -// or block range. -message TransparentAddressBlockFilter { - string address = 1; - BlockRange range = 2; -} - -// Duration is currently used only for testing, so that the Ping rpc -// can simulate a delay, to create many simultaneous connections. Units -// are microseconds. -message Duration { - int64 intervalUs = 1; -} - -// PingResponse is used to indicate concurrency, how many Ping rpcs -// are executing upon entry and upon exit (after the delay). -message PingResponse { - int64 entry = 1; - int64 exit = 2; -} - -service CompactTxStreamer { - // Compact Blocks - rpc GetLatestBlock(ChainSpec) returns (BlockID) {} - rpc GetBlock(BlockID) returns (CompactBlock) {} - rpc GetBlockRange(BlockRange) returns (stream CompactBlock) {} - - // Transactions - rpc GetTransaction(TxFilter) returns (RawTransaction) {} - rpc SendTransaction(RawTransaction) returns (SendResponse) {} - - // t-Address support - rpc GetAddressTxids(TransparentAddressBlockFilter) returns (stream RawTransaction) {} - - // Misc - rpc GetLightdInfo(Empty) returns (LightdInfo) {} - rpc Ping(Duration) returns (PingResponse) {} -} diff --git a/ZcashLightClientKit/Service/ProtoBuf/service.grpc.swift b/ZcashLightClientKit/Service/ProtoBuf/service.grpc.swift index 269e8b03..1281d97c 100644 --- a/ZcashLightClientKit/Service/ProtoBuf/service.grpc.swift +++ b/ZcashLightClientKit/Service/ProtoBuf/service.grpc.swift @@ -20,291 +20,153 @@ // See the License for the specific language governing permissions and // limitations under the License. // -import Dispatch import Foundation -import SwiftGRPC +import GRPC +import NIO +import NIOHTTP1 import SwiftProtobuf -internal protocol CompactTxStreamerGetLatestBlockCall: ClientCallUnary {} -fileprivate final class CompactTxStreamerGetLatestBlockCallBase: ClientCallUnaryBase, CompactTxStreamerGetLatestBlockCall { - override class var method: String { return "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestBlock" } +/// Usage: instantiate CompactTxStreamerClient, then call methods of this protocol to make API calls. +internal protocol CompactTxStreamerClientProtocol { + func getLatestBlock(_ request: ChainSpec, callOptions: CallOptions?) -> UnaryCall + func getBlock(_ request: BlockID, callOptions: CallOptions?) -> UnaryCall + func getBlockRange(_ request: BlockRange, callOptions: CallOptions?, handler: @escaping (CompactBlock) -> Void) -> ServerStreamingCall + func getTransaction(_ request: TxFilter, callOptions: CallOptions?) -> UnaryCall + func sendTransaction(_ request: RawTransaction, callOptions: CallOptions?) -> UnaryCall + func getAddressTxids(_ request: TransparentAddressBlockFilter, callOptions: CallOptions?, handler: @escaping (RawTransaction) -> Void) -> ServerStreamingCall + func getLightdInfo(_ request: Empty, callOptions: CallOptions?) -> UnaryCall + func ping(_ request: Duration, callOptions: CallOptions?) -> UnaryCall } -internal protocol CompactTxStreamerGetBlockCall: ClientCallUnary {} +internal final class CompactTxStreamerClient: GRPCClient, CompactTxStreamerClientProtocol { + internal let channel: GRPCChannel + internal var defaultCallOptions: CallOptions -fileprivate final class CompactTxStreamerGetBlockCallBase: ClientCallUnaryBase, CompactTxStreamerGetBlockCall { - override class var method: String { return "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlock" } -} - -internal protocol CompactTxStreamerGetBlockRangeCall: ClientCallServerStreaming { - /// Do not call this directly, call `receive()` in the protocol extension below instead. - func _receive(timeout: DispatchTime) throws -> CompactBlock? - /// Call this to wait for a result. Nonblocking. - func receive(completion: @escaping (ResultOrRPCError) -> Void) throws -} - -internal extension CompactTxStreamerGetBlockRangeCall { - /// Call this to wait for a result. Blocking. - func receive(timeout: DispatchTime = .distantFuture) throws -> CompactBlock? { return try self._receive(timeout: timeout) } -} - -fileprivate final class CompactTxStreamerGetBlockRangeCallBase: ClientCallServerStreamingBase, CompactTxStreamerGetBlockRangeCall { - override class var method: String { return "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRange" } -} - -internal protocol CompactTxStreamerGetTransactionCall: ClientCallUnary {} - -fileprivate final class CompactTxStreamerGetTransactionCallBase: ClientCallUnaryBase, CompactTxStreamerGetTransactionCall { - override class var method: String { return "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTransaction" } -} - -internal protocol CompactTxStreamerSendTransactionCall: ClientCallUnary {} - -fileprivate final class CompactTxStreamerSendTransactionCallBase: ClientCallUnaryBase, CompactTxStreamerSendTransactionCall { - override class var method: String { return "/cash.z.wallet.sdk.rpc.CompactTxStreamer/SendTransaction" } -} - -internal protocol CompactTxStreamerGetAddressTxidsCall: ClientCallServerStreaming { - /// Do not call this directly, call `receive()` in the protocol extension below instead. - func _receive(timeout: DispatchTime) throws -> RawTransaction? - /// Call this to wait for a result. Nonblocking. - func receive(completion: @escaping (ResultOrRPCError) -> Void) throws -} - -internal extension CompactTxStreamerGetAddressTxidsCall { - /// Call this to wait for a result. Blocking. - func receive(timeout: DispatchTime = .distantFuture) throws -> RawTransaction? { return try self._receive(timeout: timeout) } -} - -fileprivate final class CompactTxStreamerGetAddressTxidsCallBase: ClientCallServerStreamingBase, CompactTxStreamerGetAddressTxidsCall { - override class var method: String { return "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressTxids" } -} - -internal protocol CompactTxStreamerGetLightdInfoCall: ClientCallUnary {} - -fileprivate final class CompactTxStreamerGetLightdInfoCallBase: ClientCallUnaryBase, CompactTxStreamerGetLightdInfoCall { - override class var method: String { return "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo" } -} - -internal protocol CompactTxStreamerPingCall: ClientCallUnary {} - -fileprivate final class CompactTxStreamerPingCallBase: ClientCallUnaryBase, CompactTxStreamerPingCall { - override class var method: String { return "/cash.z.wallet.sdk.rpc.CompactTxStreamer/Ping" } -} - - -/// Instantiate CompactTxStreamerServiceClient, then call methods of this protocol to make API calls. -internal protocol CompactTxStreamerService: ServiceClient { - /// Synchronous. Unary. - func getLatestBlock(_ request: ChainSpec, metadata customMetadata: Metadata) throws -> BlockID - /// Asynchronous. Unary. - @discardableResult - func getLatestBlock(_ request: ChainSpec, metadata customMetadata: Metadata, completion: @escaping (BlockID?, CallResult) -> Void) throws -> CompactTxStreamerGetLatestBlockCall - - /// Synchronous. Unary. - func getBlock(_ request: BlockID, metadata customMetadata: Metadata) throws -> CompactBlock - /// Asynchronous. Unary. - @discardableResult - func getBlock(_ request: BlockID, metadata customMetadata: Metadata, completion: @escaping (CompactBlock?, CallResult) -> Void) throws -> CompactTxStreamerGetBlockCall - - /// Asynchronous. Server-streaming. - /// Send the initial message. - /// Use methods on the returned object to get streamed responses. - func getBlockRange(_ request: BlockRange, metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> CompactTxStreamerGetBlockRangeCall - - /// Synchronous. Unary. - func getTransaction(_ request: TxFilter, metadata customMetadata: Metadata) throws -> RawTransaction - /// Asynchronous. Unary. - @discardableResult - func getTransaction(_ request: TxFilter, metadata customMetadata: Metadata, completion: @escaping (RawTransaction?, CallResult) -> Void) throws -> CompactTxStreamerGetTransactionCall - - /// Synchronous. Unary. - func sendTransaction(_ request: RawTransaction, metadata customMetadata: Metadata) throws -> SendResponse - /// Asynchronous. Unary. - @discardableResult - func sendTransaction(_ request: RawTransaction, metadata customMetadata: Metadata, completion: @escaping (SendResponse?, CallResult) -> Void) throws -> CompactTxStreamerSendTransactionCall - - /// Asynchronous. Server-streaming. - /// Send the initial message. - /// Use methods on the returned object to get streamed responses. - func getAddressTxids(_ request: TransparentAddressBlockFilter, metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> CompactTxStreamerGetAddressTxidsCall - - /// Synchronous. Unary. - func getLightdInfo(_ request: Empty, metadata customMetadata: Metadata) throws -> LightdInfo - /// Asynchronous. Unary. - @discardableResult - func getLightdInfo(_ request: Empty, metadata customMetadata: Metadata, completion: @escaping (LightdInfo?, CallResult) -> Void) throws -> CompactTxStreamerGetLightdInfoCall - - /// Synchronous. Unary. - func ping(_ request: Duration, metadata customMetadata: Metadata) throws -> PingResponse - /// Asynchronous. Unary. - @discardableResult - func ping(_ request: Duration, metadata customMetadata: Metadata, completion: @escaping (PingResponse?, CallResult) -> Void) throws -> CompactTxStreamerPingCall - -} - -internal extension CompactTxStreamerService { - /// Synchronous. Unary. - func getLatestBlock(_ request: ChainSpec) throws -> BlockID { - return try self.getLatestBlock(request, metadata: self.metadata) - } - /// Asynchronous. Unary. - @discardableResult - func getLatestBlock(_ request: ChainSpec, completion: @escaping (BlockID?, CallResult) -> Void) throws -> CompactTxStreamerGetLatestBlockCall { - return try self.getLatestBlock(request, metadata: self.metadata, completion: completion) + /// Creates a client for the cash.z.wallet.sdk.rpc.CompactTxStreamer service. + /// + /// - Parameters: + /// - channel: `GRPCChannel` to the service host. + /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. + internal init(channel: GRPCChannel, defaultCallOptions: CallOptions = CallOptions()) { + self.channel = channel + self.defaultCallOptions = defaultCallOptions } - /// Synchronous. Unary. - func getBlock(_ request: BlockID) throws -> CompactBlock { - return try self.getBlock(request, metadata: self.metadata) - } - /// Asynchronous. Unary. - @discardableResult - func getBlock(_ request: BlockID, completion: @escaping (CompactBlock?, CallResult) -> Void) throws -> CompactTxStreamerGetBlockCall { - return try self.getBlock(request, metadata: self.metadata, completion: completion) + /// Compact Blocks + /// + /// - Parameters: + /// - request: Request to send to GetLatestBlock. + /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + internal func getLatestBlock(_ request: ChainSpec, callOptions: CallOptions? = nil) -> UnaryCall { + return self.makeUnaryCall(path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestBlock", + request: request, + callOptions: callOptions ?? self.defaultCallOptions) } - /// Asynchronous. Server-streaming. - func getBlockRange(_ request: BlockRange, completion: ((CallResult) -> Void)?) throws -> CompactTxStreamerGetBlockRangeCall { - return try self.getBlockRange(request, metadata: self.metadata, completion: completion) + /// Unary call to GetBlock + /// + /// - Parameters: + /// - request: Request to send to GetBlock. + /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + internal func getBlock(_ request: BlockID, callOptions: CallOptions? = nil) -> UnaryCall { + return self.makeUnaryCall(path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlock", + request: request, + callOptions: callOptions ?? self.defaultCallOptions) } - /// Synchronous. Unary. - func getTransaction(_ request: TxFilter) throws -> RawTransaction { - return try self.getTransaction(request, metadata: self.metadata) - } - /// Asynchronous. Unary. - @discardableResult - func getTransaction(_ request: TxFilter, completion: @escaping (RawTransaction?, CallResult) -> Void) throws -> CompactTxStreamerGetTransactionCall { - return try self.getTransaction(request, metadata: self.metadata, completion: completion) + /// Server streaming call to GetBlockRange + /// + /// - Parameters: + /// - request: Request to send to GetBlockRange. + /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. + /// - handler: A closure called when each response is received from the server. + /// - Returns: A `ServerStreamingCall` with futures for the metadata and status. + internal func getBlockRange(_ request: BlockRange, callOptions: CallOptions? = nil, handler: @escaping (CompactBlock) -> Void) -> ServerStreamingCall { + return self.makeServerStreamingCall(path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRange", + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + handler: handler) } - /// Synchronous. Unary. - func sendTransaction(_ request: RawTransaction) throws -> SendResponse { - return try self.sendTransaction(request, metadata: self.metadata) - } - /// Asynchronous. Unary. - @discardableResult - func sendTransaction(_ request: RawTransaction, completion: @escaping (SendResponse?, CallResult) -> Void) throws -> CompactTxStreamerSendTransactionCall { - return try self.sendTransaction(request, metadata: self.metadata, completion: completion) + /// Transactions + /// + /// - Parameters: + /// - request: Request to send to GetTransaction. + /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + internal func getTransaction(_ request: TxFilter, callOptions: CallOptions? = nil) -> UnaryCall { + return self.makeUnaryCall(path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTransaction", + request: request, + callOptions: callOptions ?? self.defaultCallOptions) } - /// Asynchronous. Server-streaming. - func getAddressTxids(_ request: TransparentAddressBlockFilter, completion: ((CallResult) -> Void)?) throws -> CompactTxStreamerGetAddressTxidsCall { - return try self.getAddressTxids(request, metadata: self.metadata, completion: completion) + /// Unary call to SendTransaction + /// + /// - Parameters: + /// - request: Request to send to SendTransaction. + /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + internal func sendTransaction(_ request: RawTransaction, callOptions: CallOptions? = nil) -> UnaryCall { + return self.makeUnaryCall(path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/SendTransaction", + request: request, + callOptions: callOptions ?? self.defaultCallOptions) } - /// Synchronous. Unary. - func getLightdInfo(_ request: Empty) throws -> LightdInfo { - return try self.getLightdInfo(request, metadata: self.metadata) - } - /// Asynchronous. Unary. - @discardableResult - func getLightdInfo(_ request: Empty, completion: @escaping (LightdInfo?, CallResult) -> Void) throws -> CompactTxStreamerGetLightdInfoCall { - return try self.getLightdInfo(request, metadata: self.metadata, completion: completion) + /// t-Address support + /// + /// - Parameters: + /// - request: Request to send to GetAddressTxids. + /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. + /// - handler: A closure called when each response is received from the server. + /// - Returns: A `ServerStreamingCall` with futures for the metadata and status. + internal func getAddressTxids(_ request: TransparentAddressBlockFilter, callOptions: CallOptions? = nil, handler: @escaping (RawTransaction) -> Void) -> ServerStreamingCall { + return self.makeServerStreamingCall(path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressTxids", + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + handler: handler) } - /// Synchronous. Unary. - func ping(_ request: Duration) throws -> PingResponse { - return try self.ping(request, metadata: self.metadata) + /// Misc + /// + /// - Parameters: + /// - request: Request to send to GetLightdInfo. + /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + internal func getLightdInfo(_ request: Empty, callOptions: CallOptions? = nil) -> UnaryCall { + return self.makeUnaryCall(path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo", + request: request, + callOptions: callOptions ?? self.defaultCallOptions) } - /// Asynchronous. Unary. - @discardableResult - func ping(_ request: Duration, completion: @escaping (PingResponse?, CallResult) -> Void) throws -> CompactTxStreamerPingCall { - return try self.ping(request, metadata: self.metadata, completion: completion) + + /// Unary call to Ping + /// + /// - Parameters: + /// - request: Request to send to Ping. + /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + internal func ping(_ request: Duration, callOptions: CallOptions? = nil) -> UnaryCall { + return self.makeUnaryCall(path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/Ping", + request: request, + callOptions: callOptions ?? self.defaultCallOptions) } } -internal final class CompactTxStreamerServiceClient: ServiceClientBase, CompactTxStreamerService { - /// Synchronous. Unary. - internal func getLatestBlock(_ request: ChainSpec, metadata customMetadata: Metadata) throws -> BlockID { - return try CompactTxStreamerGetLatestBlockCallBase(channel) - .run(request: request, metadata: customMetadata) - } - /// Asynchronous. Unary. - @discardableResult - internal func getLatestBlock(_ request: ChainSpec, metadata customMetadata: Metadata, completion: @escaping (BlockID?, CallResult) -> Void) throws -> CompactTxStreamerGetLatestBlockCall { - return try CompactTxStreamerGetLatestBlockCallBase(channel) - .start(request: request, metadata: customMetadata, completion: completion) - } - /// Synchronous. Unary. - internal func getBlock(_ request: BlockID, metadata customMetadata: Metadata) throws -> CompactBlock { - return try CompactTxStreamerGetBlockCallBase(channel) - .run(request: request, metadata: customMetadata) - } - /// Asynchronous. Unary. - @discardableResult - internal func getBlock(_ request: BlockID, metadata customMetadata: Metadata, completion: @escaping (CompactBlock?, CallResult) -> Void) throws -> CompactTxStreamerGetBlockCall { - return try CompactTxStreamerGetBlockCallBase(channel) - .start(request: request, metadata: customMetadata, completion: completion) - } - - /// Asynchronous. Server-streaming. - /// Send the initial message. - /// Use methods on the returned object to get streamed responses. - internal func getBlockRange(_ request: BlockRange, metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> CompactTxStreamerGetBlockRangeCall { - return try CompactTxStreamerGetBlockRangeCallBase(channel) - .start(request: request, metadata: customMetadata, completion: completion) - } - - /// Synchronous. Unary. - internal func getTransaction(_ request: TxFilter, metadata customMetadata: Metadata) throws -> RawTransaction { - return try CompactTxStreamerGetTransactionCallBase(channel) - .run(request: request, metadata: customMetadata) - } - /// Asynchronous. Unary. - @discardableResult - internal func getTransaction(_ request: TxFilter, metadata customMetadata: Metadata, completion: @escaping (RawTransaction?, CallResult) -> Void) throws -> CompactTxStreamerGetTransactionCall { - return try CompactTxStreamerGetTransactionCallBase(channel) - .start(request: request, metadata: customMetadata, completion: completion) - } - - /// Synchronous. Unary. - internal func sendTransaction(_ request: RawTransaction, metadata customMetadata: Metadata) throws -> SendResponse { - return try CompactTxStreamerSendTransactionCallBase(channel) - .run(request: request, metadata: customMetadata) - } - /// Asynchronous. Unary. - @discardableResult - internal func sendTransaction(_ request: RawTransaction, metadata customMetadata: Metadata, completion: @escaping (SendResponse?, CallResult) -> Void) throws -> CompactTxStreamerSendTransactionCall { - return try CompactTxStreamerSendTransactionCallBase(channel) - .start(request: request, metadata: customMetadata, completion: completion) - } - - /// Asynchronous. Server-streaming. - /// Send the initial message. - /// Use methods on the returned object to get streamed responses. - internal func getAddressTxids(_ request: TransparentAddressBlockFilter, metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> CompactTxStreamerGetAddressTxidsCall { - return try CompactTxStreamerGetAddressTxidsCallBase(channel) - .start(request: request, metadata: customMetadata, completion: completion) - } - - /// Synchronous. Unary. - internal func getLightdInfo(_ request: Empty, metadata customMetadata: Metadata) throws -> LightdInfo { - return try CompactTxStreamerGetLightdInfoCallBase(channel) - .run(request: request, metadata: customMetadata) - } - /// Asynchronous. Unary. - @discardableResult - internal func getLightdInfo(_ request: Empty, metadata customMetadata: Metadata, completion: @escaping (LightdInfo?, CallResult) -> Void) throws -> CompactTxStreamerGetLightdInfoCall { - return try CompactTxStreamerGetLightdInfoCallBase(channel) - .start(request: request, metadata: customMetadata, completion: completion) - } - - /// Synchronous. Unary. - internal func ping(_ request: Duration, metadata customMetadata: Metadata) throws -> PingResponse { - return try CompactTxStreamerPingCallBase(channel) - .run(request: request, metadata: customMetadata) - } - /// Asynchronous. Unary. - @discardableResult - internal func ping(_ request: Duration, metadata customMetadata: Metadata, completion: @escaping (PingResponse?, CallResult) -> Void) throws -> CompactTxStreamerPingCall { - return try CompactTxStreamerPingCallBase(channel) - .start(request: request, metadata: customMetadata, completion: completion) - } - -} +// Provides conformance to `GRPCPayload` for request and response messages +extension ChainSpec: GRPCProtobufPayload {} +extension BlockID: GRPCProtobufPayload {} +extension CompactBlock: GRPCProtobufPayload {} +extension BlockRange: GRPCProtobufPayload {} +extension TxFilter: GRPCProtobufPayload {} +extension RawTransaction: GRPCProtobufPayload {} +extension SendResponse: GRPCProtobufPayload {} +extension TransparentAddressBlockFilter: GRPCProtobufPayload {} +extension Empty: GRPCProtobufPayload {} +extension LightdInfo: GRPCProtobufPayload {} +extension Duration: GRPCProtobufPayload {} +extension PingResponse: GRPCProtobufPayload {} diff --git a/ZcashLightClientKit/Service/ProtoBuf/service.pb.swift b/ZcashLightClientKit/Service/ProtoBuf/service.pb.swift index b67a1c6d..134234d6 100644 --- a/ZcashLightClientKit/Service/ProtoBuf/service.pb.swift +++ b/ZcashLightClientKit/Service/ProtoBuf/service.pb.swift @@ -3,7 +3,7 @@ // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: service.proto // -// For information on using the generated types, please see the documenation: +// For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ // Copyright (c) 2019-2020 The Zcash developers @@ -16,7 +16,7 @@ import SwiftProtobuf // If the compiler emits an error on this type, it is because this file // was generated by a version of the `protoc` Swift plug-in that is // incompatible with the version of SwiftProtobuf to which you are linking. -// Please ensure that your are building against the same version of the API +// Please ensure that you are building against the same version of the API // that was used to generate this file. fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} @@ -47,28 +47,29 @@ struct BlockRange { // methods supported on all messages. var start: BlockID { - get {return _storage._start ?? BlockID()} - set {_uniqueStorage()._start = newValue} + get {return _start ?? BlockID()} + set {_start = newValue} } /// Returns true if `start` has been explicitly set. - var hasStart: Bool {return _storage._start != nil} + var hasStart: Bool {return self._start != nil} /// Clears the value of `start`. Subsequent reads from it will return its default value. - mutating func clearStart() {_uniqueStorage()._start = nil} + mutating func clearStart() {self._start = nil} var end: BlockID { - get {return _storage._end ?? BlockID()} - set {_uniqueStorage()._end = newValue} + get {return _end ?? BlockID()} + set {_end = newValue} } /// Returns true if `end` has been explicitly set. - var hasEnd: Bool {return _storage._end != nil} + var hasEnd: Bool {return self._end != nil} /// Clears the value of `end`. Subsequent reads from it will return its default value. - mutating func clearEnd() {_uniqueStorage()._end = nil} + mutating func clearEnd() {self._end = nil} var unknownFields = SwiftProtobuf.UnknownStorage() init() {} - fileprivate var _storage = _StorageClass.defaultInstance + fileprivate var _start: BlockID? = nil + fileprivate var _end: BlockID? = nil } /// A TxFilter contains the information needed to identify a particular @@ -80,29 +81,23 @@ struct TxFilter { // methods supported on all messages. var block: BlockID { - get {return _storage._block ?? BlockID()} - set {_uniqueStorage()._block = newValue} + get {return _block ?? BlockID()} + set {_block = newValue} } /// Returns true if `block` has been explicitly set. - var hasBlock: Bool {return _storage._block != nil} + var hasBlock: Bool {return self._block != nil} /// Clears the value of `block`. Subsequent reads from it will return its default value. - mutating func clearBlock() {_uniqueStorage()._block = nil} + mutating func clearBlock() {self._block = nil} - var index: UInt64 { - get {return _storage._index} - set {_uniqueStorage()._index = newValue} - } + var index: UInt64 = 0 - var hash: Data { - get {return _storage._hash} - set {_uniqueStorage()._hash = newValue} - } + var hash: Data = SwiftProtobuf.Internal.emptyData var unknownFields = SwiftProtobuf.UnknownStorage() init() {} - fileprivate var _storage = _StorageClass.defaultInstance + fileprivate var _block: BlockID? = nil } /// RawTransaction contains the complete transaction data. It also optionally includes @@ -193,25 +188,22 @@ struct TransparentAddressBlockFilter { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. - var address: String { - get {return _storage._address} - set {_uniqueStorage()._address = newValue} - } + var address: String = String() var range: BlockRange { - get {return _storage._range ?? BlockRange()} - set {_uniqueStorage()._range = newValue} + get {return _range ?? BlockRange()} + set {_range = newValue} } /// Returns true if `range` has been explicitly set. - var hasRange: Bool {return _storage._range != nil} + var hasRange: Bool {return self._range != nil} /// Clears the value of `range`. Subsequent reads from it will return its default value. - mutating func clearRange() {_uniqueStorage()._range = nil} + mutating func clearRange() {self._range = nil} var unknownFields = SwiftProtobuf.UnknownStorage() init() {} - fileprivate var _storage = _StorageClass.defaultInstance + fileprivate var _range: BlockRange? = nil } /// Duration is currently used only for testing, so that the Ping rpc @@ -291,63 +283,29 @@ extension BlockRange: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio 2: .same(proto: "end"), ] - fileprivate class _StorageClass { - var _start: BlockID? = nil - var _end: BlockID? = nil - - static let defaultInstance = _StorageClass() - - private init() {} - - init(copying source: _StorageClass) { - _start = source._start - _end = source._end - } - } - - fileprivate mutating func _uniqueStorage() -> _StorageClass { - if !isKnownUniquelyReferenced(&_storage) { - _storage = _StorageClass(copying: _storage) - } - return _storage - } - mutating func decodeMessage(decoder: inout D) throws { - _ = _uniqueStorage() - try withExtendedLifetime(_storage) { (_storage: _StorageClass) in - while let fieldNumber = try decoder.nextFieldNumber() { - switch fieldNumber { - case 1: try decoder.decodeSingularMessageField(value: &_storage._start) - case 2: try decoder.decodeSingularMessageField(value: &_storage._end) - default: break - } + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularMessageField(value: &self._start) + case 2: try decoder.decodeSingularMessageField(value: &self._end) + default: break } } } func traverse(visitor: inout V) throws { - try withExtendedLifetime(_storage) { (_storage: _StorageClass) in - if let v = _storage._start { - try visitor.visitSingularMessageField(value: v, fieldNumber: 1) - } - if let v = _storage._end { - try visitor.visitSingularMessageField(value: v, fieldNumber: 2) - } + if let v = self._start { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } + if let v = self._end { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) } try unknownFields.traverse(visitor: &visitor) } static func ==(lhs: BlockRange, rhs: BlockRange) -> Bool { - if lhs._storage !== rhs._storage { - let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in - let _storage = _args.0 - let rhs_storage = _args.1 - if _storage._start != rhs_storage._start {return false} - if _storage._end != rhs_storage._end {return false} - return true - } - if !storagesAreEqual {return false} - } + if lhs._start != rhs._start {return false} + if lhs._end != rhs._end {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } @@ -361,70 +319,34 @@ extension TxFilter: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB 3: .same(proto: "hash"), ] - fileprivate class _StorageClass { - var _block: BlockID? = nil - var _index: UInt64 = 0 - var _hash: Data = SwiftProtobuf.Internal.emptyData - - static let defaultInstance = _StorageClass() - - private init() {} - - init(copying source: _StorageClass) { - _block = source._block - _index = source._index - _hash = source._hash - } - } - - fileprivate mutating func _uniqueStorage() -> _StorageClass { - if !isKnownUniquelyReferenced(&_storage) { - _storage = _StorageClass(copying: _storage) - } - return _storage - } - mutating func decodeMessage(decoder: inout D) throws { - _ = _uniqueStorage() - try withExtendedLifetime(_storage) { (_storage: _StorageClass) in - while let fieldNumber = try decoder.nextFieldNumber() { - switch fieldNumber { - case 1: try decoder.decodeSingularMessageField(value: &_storage._block) - case 2: try decoder.decodeSingularUInt64Field(value: &_storage._index) - case 3: try decoder.decodeSingularBytesField(value: &_storage._hash) - default: break - } + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularMessageField(value: &self._block) + case 2: try decoder.decodeSingularUInt64Field(value: &self.index) + case 3: try decoder.decodeSingularBytesField(value: &self.hash) + default: break } } } func traverse(visitor: inout V) throws { - try withExtendedLifetime(_storage) { (_storage: _StorageClass) in - if let v = _storage._block { - try visitor.visitSingularMessageField(value: v, fieldNumber: 1) - } - if _storage._index != 0 { - try visitor.visitSingularUInt64Field(value: _storage._index, fieldNumber: 2) - } - if !_storage._hash.isEmpty { - try visitor.visitSingularBytesField(value: _storage._hash, fieldNumber: 3) - } + if let v = self._block { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } + if self.index != 0 { + try visitor.visitSingularUInt64Field(value: self.index, fieldNumber: 2) + } + if !self.hash.isEmpty { + try visitor.visitSingularBytesField(value: self.hash, fieldNumber: 3) } try unknownFields.traverse(visitor: &visitor) } static func ==(lhs: TxFilter, rhs: TxFilter) -> Bool { - if lhs._storage !== rhs._storage { - let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in - let _storage = _args.0 - let rhs_storage = _args.1 - if _storage._block != rhs_storage._block {return false} - if _storage._index != rhs_storage._index {return false} - if _storage._hash != rhs_storage._hash {return false} - return true - } - if !storagesAreEqual {return false} - } + if lhs._block != rhs._block {return false} + if lhs.index != rhs.index {return false} + if lhs.hash != rhs.hash {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } @@ -610,63 +532,29 @@ extension TransparentAddressBlockFilter: SwiftProtobuf.Message, SwiftProtobuf._M 2: .same(proto: "range"), ] - fileprivate class _StorageClass { - var _address: String = String() - var _range: BlockRange? = nil - - static let defaultInstance = _StorageClass() - - private init() {} - - init(copying source: _StorageClass) { - _address = source._address - _range = source._range - } - } - - fileprivate mutating func _uniqueStorage() -> _StorageClass { - if !isKnownUniquelyReferenced(&_storage) { - _storage = _StorageClass(copying: _storage) - } - return _storage - } - mutating func decodeMessage(decoder: inout D) throws { - _ = _uniqueStorage() - try withExtendedLifetime(_storage) { (_storage: _StorageClass) in - while let fieldNumber = try decoder.nextFieldNumber() { - switch fieldNumber { - case 1: try decoder.decodeSingularStringField(value: &_storage._address) - case 2: try decoder.decodeSingularMessageField(value: &_storage._range) - default: break - } + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularStringField(value: &self.address) + case 2: try decoder.decodeSingularMessageField(value: &self._range) + default: break } } } func traverse(visitor: inout V) throws { - try withExtendedLifetime(_storage) { (_storage: _StorageClass) in - if !_storage._address.isEmpty { - try visitor.visitSingularStringField(value: _storage._address, fieldNumber: 1) - } - if let v = _storage._range { - try visitor.visitSingularMessageField(value: v, fieldNumber: 2) - } + if !self.address.isEmpty { + try visitor.visitSingularStringField(value: self.address, fieldNumber: 1) + } + if let v = self._range { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) } try unknownFields.traverse(visitor: &visitor) } static func ==(lhs: TransparentAddressBlockFilter, rhs: TransparentAddressBlockFilter) -> Bool { - if lhs._storage !== rhs._storage { - let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in - let _storage = _args.0 - let rhs_storage = _args.1 - if _storage._address != rhs_storage._address {return false} - if _storage._range != rhs_storage._range {return false} - return true - } - if !storagesAreEqual {return false} - } + if lhs.address != rhs.address {return false} + if lhs._range != rhs._range {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } diff --git a/ZcashLightClientKit/Synchronizer.swift b/ZcashLightClientKit/Synchronizer.swift index ccc24461..5f884f1d 100644 --- a/ZcashLightClientKit/Synchronizer.swift +++ b/ZcashLightClientKit/Synchronizer.swift @@ -17,6 +17,7 @@ public enum SynchronizerError: Error { case connectionFailed(message: String) case generalError(message: String) case maxRetryAttemptsReached(attempts: Int) + case connectionError(status: Int, message: String) } /** diff --git a/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift b/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift index 4ec25526..31958db8 100644 --- a/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift +++ b/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift @@ -117,8 +117,7 @@ public class SDKSynchronizer: Synchronizer { - Throws: CompactBlockProcessorError when failures occur */ public func start(retry: Bool = false) throws { - let connectivityState = initializer.lightWalletService.resume() - LoggerProxy.info("service started with connectivityState: \(connectivityState)") + guard let processor = initializer.blockProcessor() else { throw SynchronizerError.generalError(message: "compact block processor initialization failed") } @@ -529,6 +528,8 @@ public class SDKSynchronizer: Synchronizer { return SynchronizerError.generalError(message: message) case .maxAttemptsReached(attempts: let attempts): return SynchronizerError.maxRetryAttemptsReached(attempts: attempts) + case .grpcError(let statusCode, let message): + return SynchronizerError.connectionError(status: statusCode, message: message) } } return error diff --git a/ZcashLightClientKitTests/LightWalletServiceTests.swift b/ZcashLightClientKitTests/LightWalletServiceTests.swift index d592159f..5ca82cdf 100644 --- a/ZcashLightClientKitTests/LightWalletServiceTests.swift +++ b/ZcashLightClientKitTests/LightWalletServiceTests.swift @@ -8,7 +8,7 @@ import XCTest @testable import ZcashLightClientKit -import SwiftGRPC +import GRPC class LightWalletServiceTests: XCTestCase { var service: LightWalletService! @@ -21,8 +21,6 @@ class LightWalletServiceTests: XCTestCase { override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. - - channel.shutdown() } /// FIXME: check whether this test is stil valid on in memory lwd implementatiojn diff --git a/ZcashLightClientKitTests/ZcashLightClientKitTests.swift b/ZcashLightClientKitTests/ZcashLightClientKitTests.swift index 45e03627..192535b1 100644 --- a/ZcashLightClientKitTests/ZcashLightClientKitTests.swift +++ b/ZcashLightClientKitTests/ZcashLightClientKitTests.swift @@ -7,7 +7,7 @@ // import XCTest -import SwiftGRPC +import GRPC @testable import ZcashLightClientKit @@ -25,7 +25,6 @@ class ZcashLightClientKitTests: XCTestCase { override func tearDown() { super.tearDown() - service.channel.shutdown() service = nil latestBlockHeight = nil } @@ -44,48 +43,23 @@ class ZcashLightClientKitTests: XCTestCase { } -// /** -// LIGHTWALLETD KILLER TEST - DO NOT USE -// */ -// func testBlockRangeService() { -// -// let expect = XCTestExpectation(description: self.debugDescription) -// let _ = try? service.getAllBlocksSinceSaplingLaunch(){ result in -// LoggerProxy.debug(result) -// expect.fulfill() -// XCTAssert(result.success) -// XCTAssertNotNil(result.resultData) -// } -// wait(for: [expect], timeout: 10) -// } - func testBlockRangeServiceTilLastest() { let expectedCount: BlockHeight = 99 var count: BlockHeight = 0 let startHeight = latestBlockHeight - expectedCount let endHeight = latestBlockHeight! - - guard let call = try? service!.blockRange(startHeight: startHeight, endHeight: endHeight,result: { - result in - XCTAssert(result.success) - + var blocks = [CompactBlock]() + guard let call = try? service!.blockRange(startHeight: startHeight, endHeight: endHeight, result: { + blocks.append($0) + count += 1 + }) else { XCTFail("failed to create getBlockRange( \(startHeight) ..<= \(endHeight)") return } - var blocks = [CompactBlock]() - while true { - guard let block = try? call.receive() else { - - break - - } - blocks.append(block) - count += 1 - } - + _ = try! call.status.wait() XCTAssertEqual(expectedCount + 1, count) } diff --git a/ZcashLightClientKitTests/proto/darkside.grpc.swift b/ZcashLightClientKitTests/proto/darkside.grpc.swift index 350ab98d..1c82d6cb 100644 --- a/ZcashLightClientKitTests/proto/darkside.grpc.swift +++ b/ZcashLightClientKitTests/proto/darkside.grpc.swift @@ -20,87 +20,65 @@ // See the License for the specific language governing permissions and // limitations under the License. // -import Dispatch import Foundation -import SwiftGRPC +import GRPC +import NIO +import NIOHTTP1 import SwiftProtobuf -@testable import ZcashLightClientKit -internal protocol DarksideStreamerDarksideGetIncomingTransactionsCall: ClientCallServerStreaming { - /// Do not call this directly, call `receive()` in the protocol extension below instead. - func _receive(timeout: DispatchTime) throws -> RawTransaction? - /// Call this to wait for a result. Nonblocking. - func receive(completion: @escaping (ResultOrRPCError) -> Void) throws + + +/// Usage: instantiate DarksideStreamerClient, then call methods of this protocol to make API calls. +internal protocol DarksideStreamerClientProtocol { + func darksideGetIncomingTransactions(_ request: Empty, callOptions: CallOptions?, handler: @escaping (RawTransaction) -> Void) -> ServerStreamingCall + func darksideSetState(_ request: DarksideState, callOptions: CallOptions?) -> UnaryCall } -internal extension DarksideStreamerDarksideGetIncomingTransactionsCall { - /// Call this to wait for a result. Blocking. - func receive(timeout: DispatchTime = .distantFuture) throws -> RawTransaction? { return try self._receive(timeout: timeout) } -} +internal final class DarksideStreamerClient: GRPCClient, DarksideStreamerClientProtocol { + internal let channel: GRPCChannel + internal var defaultCallOptions: CallOptions -fileprivate final class DarksideStreamerDarksideGetIncomingTransactionsCallBase: ClientCallServerStreamingBase, DarksideStreamerDarksideGetIncomingTransactionsCall { - override class var method: String { return "/cash.z.wallet.sdk.rpc.DarksideStreamer/DarksideGetIncomingTransactions" } -} - -internal protocol DarksideStreamerDarksideSetStateCall: ClientCallUnary {} - -fileprivate final class DarksideStreamerDarksideSetStateCallBase: ClientCallUnaryBase, DarksideStreamerDarksideSetStateCall { - override class var method: String { return "/cash.z.wallet.sdk.rpc.DarksideStreamer/DarksideSetState" } -} - - -/// Instantiate DarksideStreamerServiceClient, then call methods of this protocol to make API calls. -internal protocol DarksideStreamerService: ServiceClient { - /// Asynchronous. Server-streaming. - /// Send the initial message. - /// Use methods on the returned object to get streamed responses. - func darksideGetIncomingTransactions(_ request: Empty, metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> DarksideStreamerDarksideGetIncomingTransactionsCall - - /// Synchronous. Unary. - func darksideSetState(_ request: DarksideState, metadata customMetadata: Metadata) throws -> Empty - /// Asynchronous. Unary. - @discardableResult - func darksideSetState(_ request: DarksideState, metadata customMetadata: Metadata, completion: @escaping (Empty?, CallResult) -> Void) throws -> DarksideStreamerDarksideSetStateCall - -} - -internal extension DarksideStreamerService { - /// Asynchronous. Server-streaming. - func darksideGetIncomingTransactions(_ request: Empty, completion: ((CallResult) -> Void)?) throws -> DarksideStreamerDarksideGetIncomingTransactionsCall { - return try self.darksideGetIncomingTransactions(request, metadata: self.metadata, completion: completion) + /// Creates a client for the cash.z.wallet.sdk.rpc.DarksideStreamer service. + /// + /// - Parameters: + /// - channel: `GRPCChannel` to the service host. + /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. + internal init(channel: GRPCChannel, defaultCallOptions: CallOptions = CallOptions()) { + self.channel = channel + self.defaultCallOptions = defaultCallOptions } - /// Synchronous. Unary. - func darksideSetState(_ request: DarksideState) throws -> Empty { - return try self.darksideSetState(request, metadata: self.metadata) + /// Return the list of transactions that have been submitted (via SendTransaction). + /// + /// - Parameters: + /// - request: Request to send to DarksideGetIncomingTransactions. + /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. + /// - handler: A closure called when each response is received from the server. + /// - Returns: A `ServerStreamingCall` with futures for the metadata and status. + internal func darksideGetIncomingTransactions(_ request: Empty, callOptions: CallOptions? = nil, handler: @escaping (RawTransaction) -> Void) -> ServerStreamingCall { + return self.makeServerStreamingCall(path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/DarksideGetIncomingTransactions", + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + handler: handler) } - /// Asynchronous. Unary. - @discardableResult - func darksideSetState(_ request: DarksideState, completion: @escaping (Empty?, CallResult) -> Void) throws -> DarksideStreamerDarksideSetStateCall { - return try self.darksideSetState(request, metadata: self.metadata, completion: completion) + + /// Set the information that GetLightdInfo returns, except that chainName specifies + /// a file of blocks within testdata/darkside that GetBlock will return. + /// + /// - Parameters: + /// - request: Request to send to DarksideSetState. + /// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + internal func darksideSetState(_ request: DarksideState, callOptions: CallOptions? = nil) -> UnaryCall { + return self.makeUnaryCall(path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/DarksideSetState", + request: request, + callOptions: callOptions ?? self.defaultCallOptions) } } -internal final class DarksideStreamerServiceClient: ServiceClientBase, DarksideStreamerService { - /// Asynchronous. Server-streaming. - /// Send the initial message. - /// Use methods on the returned object to get streamed responses. - internal func darksideGetIncomingTransactions(_ request: Empty, metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> DarksideStreamerDarksideGetIncomingTransactionsCall { - return try DarksideStreamerDarksideGetIncomingTransactionsCallBase(channel) - .start(request: request, metadata: customMetadata, completion: completion) - } - /// Synchronous. Unary. - internal func darksideSetState(_ request: DarksideState, metadata customMetadata: Metadata) throws -> Empty { - return try DarksideStreamerDarksideSetStateCallBase(channel) - .run(request: request, metadata: customMetadata) - } - /// Asynchronous. Unary. - @discardableResult - internal func darksideSetState(_ request: DarksideState, metadata customMetadata: Metadata, completion: @escaping (Empty?, CallResult) -> Void) throws -> DarksideStreamerDarksideSetStateCall { - return try DarksideStreamerDarksideSetStateCallBase(channel) - .start(request: request, metadata: customMetadata, completion: completion) - } - -} +// Provides conformance to `GRPCPayload` for request and response messages +extension Empty: GRPCProtobufPayload {} +extension RawTransaction: GRPCProtobufPayload {} +extension DarksideState: GRPCProtobufPayload {} diff --git a/ZcashLightClientKitTests/proto/darkside.pb.swift b/ZcashLightClientKitTests/proto/darkside.pb.swift index b3e04b9c..5af14aa9 100644 --- a/ZcashLightClientKitTests/proto/darkside.pb.swift +++ b/ZcashLightClientKitTests/proto/darkside.pb.swift @@ -3,7 +3,7 @@ // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: darkside.proto // -// For information on using the generated types, please see the documenation: +// For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ // Copyright (c) 2019-2020 The Zcash developers @@ -16,7 +16,7 @@ import SwiftProtobuf // If the compiler emits an error on this type, it is because this file // was generated by a version of the `protoc` Swift plug-in that is // incompatible with the version of SwiftProtobuf to which you are linking. -// Please ensure that your are building against the same version of the API +// Please ensure that you are building against the same version of the API // that was used to generate this file. fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} diff --git a/ZcashLightClientKitTests/proto/service.pb.swift b/ZcashLightClientKitTests/proto/service.pb.swift new file mode 100644 index 00000000..134234d6 --- /dev/null +++ b/ZcashLightClientKitTests/proto/service.pb.swift @@ -0,0 +1,625 @@ +// DO NOT EDIT. +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: service.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +// Copyright (c) 2019-2020 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +/// A BlockID message contains identifiers to select a block: a height or a +/// hash. Specification by hash is not implemented, but may be in the future. +struct BlockID { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var height: UInt64 = 0 + + var hash: Data = SwiftProtobuf.Internal.emptyData + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// BlockRange specifies a series of blocks from start to end inclusive. +/// Both BlockIDs must be heights; specification by hash is not yet supported. +struct BlockRange { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var start: BlockID { + get {return _start ?? BlockID()} + set {_start = newValue} + } + /// Returns true if `start` has been explicitly set. + var hasStart: Bool {return self._start != nil} + /// Clears the value of `start`. Subsequent reads from it will return its default value. + mutating func clearStart() {self._start = nil} + + var end: BlockID { + get {return _end ?? BlockID()} + set {_end = newValue} + } + /// Returns true if `end` has been explicitly set. + var hasEnd: Bool {return self._end != nil} + /// Clears the value of `end`. Subsequent reads from it will return its default value. + mutating func clearEnd() {self._end = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _start: BlockID? = nil + fileprivate var _end: BlockID? = nil +} + +/// A TxFilter contains the information needed to identify a particular +/// transaction: either a block and an index, or a direct transaction hash. +/// Currently, only specification by hash is supported. +struct TxFilter { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var block: BlockID { + get {return _block ?? BlockID()} + set {_block = newValue} + } + /// Returns true if `block` has been explicitly set. + var hasBlock: Bool {return self._block != nil} + /// Clears the value of `block`. Subsequent reads from it will return its default value. + mutating func clearBlock() {self._block = nil} + + var index: UInt64 = 0 + + var hash: Data = SwiftProtobuf.Internal.emptyData + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _block: BlockID? = nil +} + +/// RawTransaction contains the complete transaction data. It also optionally includes +/// the block height in which the transaction was included +struct RawTransaction { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var data: Data = SwiftProtobuf.Internal.emptyData + + var height: UInt64 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// A SendResponse encodes an error code and a string. It is currently used +/// only by SendTransaction(). If error code is zero, the operation was +/// successful; if non-zero, it and the message specify the failure. +struct SendResponse { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var errorCode: Int32 = 0 + + var errorMessage: String = String() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// Chainspec is a placeholder to allow specification of a particular chain fork. +struct ChainSpec { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// Empty is for gRPCs that take no arguments, currently only GetLightdInfo. +struct Empty { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// LightdInfo returns various information about this lightwalletd instance +/// and the state of the blockchain. +struct LightdInfo { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var version: String = String() + + var vendor: String = String() + + var taddrSupport: Bool = false + + var chainName: String = String() + + var saplingActivationHeight: UInt64 = 0 + + var consensusBranchID: String = String() + + var blockHeight: UInt64 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// TransparentAddressBlockFilter restricts the results to the given address +/// or block range. +struct TransparentAddressBlockFilter { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var address: String = String() + + var range: BlockRange { + get {return _range ?? BlockRange()} + set {_range = newValue} + } + /// Returns true if `range` has been explicitly set. + var hasRange: Bool {return self._range != nil} + /// Clears the value of `range`. Subsequent reads from it will return its default value. + mutating func clearRange() {self._range = nil} + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _range: BlockRange? = nil +} + +/// Duration is currently used only for testing, so that the Ping rpc +/// can simulate a delay, to create many simultaneous connections. Units +/// are microseconds. +struct Duration { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var intervalUs: Int64 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// PingResponse is used to indicate concurrency, how many Ping rpcs +/// are executing upon entry and upon exit (after the delay). +struct PingResponse { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var entry: Int64 = 0 + + var exit: Int64 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +fileprivate let _protobuf_package = "cash.z.wallet.sdk.rpc" + +extension BlockID: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".BlockID" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "height"), + 2: .same(proto: "hash"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularUInt64Field(value: &self.height) + case 2: try decoder.decodeSingularBytesField(value: &self.hash) + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.height != 0 { + try visitor.visitSingularUInt64Field(value: self.height, fieldNumber: 1) + } + if !self.hash.isEmpty { + try visitor.visitSingularBytesField(value: self.hash, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: BlockID, rhs: BlockID) -> Bool { + if lhs.height != rhs.height {return false} + if lhs.hash != rhs.hash {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension BlockRange: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".BlockRange" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "start"), + 2: .same(proto: "end"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularMessageField(value: &self._start) + case 2: try decoder.decodeSingularMessageField(value: &self._end) + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if let v = self._start { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } + if let v = self._end { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: BlockRange, rhs: BlockRange) -> Bool { + if lhs._start != rhs._start {return false} + if lhs._end != rhs._end {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension TxFilter: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".TxFilter" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "block"), + 2: .same(proto: "index"), + 3: .same(proto: "hash"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularMessageField(value: &self._block) + case 2: try decoder.decodeSingularUInt64Field(value: &self.index) + case 3: try decoder.decodeSingularBytesField(value: &self.hash) + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if let v = self._block { + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) + } + if self.index != 0 { + try visitor.visitSingularUInt64Field(value: self.index, fieldNumber: 2) + } + if !self.hash.isEmpty { + try visitor.visitSingularBytesField(value: self.hash, fieldNumber: 3) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: TxFilter, rhs: TxFilter) -> Bool { + if lhs._block != rhs._block {return false} + if lhs.index != rhs.index {return false} + if lhs.hash != rhs.hash {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension RawTransaction: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".RawTransaction" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "data"), + 2: .same(proto: "height"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularBytesField(value: &self.data) + case 2: try decoder.decodeSingularUInt64Field(value: &self.height) + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.data.isEmpty { + try visitor.visitSingularBytesField(value: self.data, fieldNumber: 1) + } + if self.height != 0 { + try visitor.visitSingularUInt64Field(value: self.height, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: RawTransaction, rhs: RawTransaction) -> Bool { + if lhs.data != rhs.data {return false} + if lhs.height != rhs.height {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension SendResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".SendResponse" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "errorCode"), + 2: .same(proto: "errorMessage"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularInt32Field(value: &self.errorCode) + case 2: try decoder.decodeSingularStringField(value: &self.errorMessage) + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.errorCode != 0 { + try visitor.visitSingularInt32Field(value: self.errorCode, fieldNumber: 1) + } + if !self.errorMessage.isEmpty { + try visitor.visitSingularStringField(value: self.errorMessage, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: SendResponse, rhs: SendResponse) -> Bool { + if lhs.errorCode != rhs.errorCode {return false} + if lhs.errorMessage != rhs.errorMessage {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ChainSpec: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".ChainSpec" + static let _protobuf_nameMap = SwiftProtobuf._NameMap() + + mutating func decodeMessage(decoder: inout D) throws { + while let _ = try decoder.nextFieldNumber() { + } + } + + func traverse(visitor: inout V) throws { + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ChainSpec, rhs: ChainSpec) -> Bool { + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Empty: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".Empty" + static let _protobuf_nameMap = SwiftProtobuf._NameMap() + + mutating func decodeMessage(decoder: inout D) throws { + while let _ = try decoder.nextFieldNumber() { + } + } + + func traverse(visitor: inout V) throws { + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Empty, rhs: Empty) -> Bool { + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension LightdInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".LightdInfo" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "version"), + 2: .same(proto: "vendor"), + 3: .same(proto: "taddrSupport"), + 4: .same(proto: "chainName"), + 5: .same(proto: "saplingActivationHeight"), + 6: .same(proto: "consensusBranchId"), + 7: .same(proto: "blockHeight"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularStringField(value: &self.version) + case 2: try decoder.decodeSingularStringField(value: &self.vendor) + case 3: try decoder.decodeSingularBoolField(value: &self.taddrSupport) + case 4: try decoder.decodeSingularStringField(value: &self.chainName) + case 5: try decoder.decodeSingularUInt64Field(value: &self.saplingActivationHeight) + case 6: try decoder.decodeSingularStringField(value: &self.consensusBranchID) + case 7: try decoder.decodeSingularUInt64Field(value: &self.blockHeight) + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.version.isEmpty { + try visitor.visitSingularStringField(value: self.version, fieldNumber: 1) + } + if !self.vendor.isEmpty { + try visitor.visitSingularStringField(value: self.vendor, fieldNumber: 2) + } + if self.taddrSupport != false { + try visitor.visitSingularBoolField(value: self.taddrSupport, fieldNumber: 3) + } + if !self.chainName.isEmpty { + try visitor.visitSingularStringField(value: self.chainName, fieldNumber: 4) + } + if self.saplingActivationHeight != 0 { + try visitor.visitSingularUInt64Field(value: self.saplingActivationHeight, fieldNumber: 5) + } + if !self.consensusBranchID.isEmpty { + try visitor.visitSingularStringField(value: self.consensusBranchID, fieldNumber: 6) + } + if self.blockHeight != 0 { + try visitor.visitSingularUInt64Field(value: self.blockHeight, fieldNumber: 7) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: LightdInfo, rhs: LightdInfo) -> Bool { + if lhs.version != rhs.version {return false} + if lhs.vendor != rhs.vendor {return false} + if lhs.taddrSupport != rhs.taddrSupport {return false} + if lhs.chainName != rhs.chainName {return false} + if lhs.saplingActivationHeight != rhs.saplingActivationHeight {return false} + if lhs.consensusBranchID != rhs.consensusBranchID {return false} + if lhs.blockHeight != rhs.blockHeight {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension TransparentAddressBlockFilter: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".TransparentAddressBlockFilter" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "address"), + 2: .same(proto: "range"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularStringField(value: &self.address) + case 2: try decoder.decodeSingularMessageField(value: &self._range) + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.address.isEmpty { + try visitor.visitSingularStringField(value: self.address, fieldNumber: 1) + } + if let v = self._range { + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: TransparentAddressBlockFilter, rhs: TransparentAddressBlockFilter) -> Bool { + if lhs.address != rhs.address {return false} + if lhs._range != rhs._range {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Duration: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".Duration" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "intervalUs"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularInt64Field(value: &self.intervalUs) + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.intervalUs != 0 { + try visitor.visitSingularInt64Field(value: self.intervalUs, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Duration, rhs: Duration) -> Bool { + if lhs.intervalUs != rhs.intervalUs {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension PingResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".PingResponse" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "entry"), + 2: .same(proto: "exit"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularInt64Field(value: &self.entry) + case 2: try decoder.decodeSingularInt64Field(value: &self.exit) + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.entry != 0 { + try visitor.visitSingularInt64Field(value: self.entry, fieldNumber: 1) + } + if self.exit != 0 { + try visitor.visitSingularInt64Field(value: self.exit, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: PingResponse, rhs: PingResponse) -> Bool { + if lhs.entry != rhs.entry {return false} + if lhs.exit != rhs.exit {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} diff --git a/ZcashLightClientKitTests/utils/DarkSideWalletService.swift b/ZcashLightClientKitTests/utils/DarkSideWalletService.swift index 78360c54..d0217cfe 100644 --- a/ZcashLightClientKitTests/utils/DarkSideWalletService.swift +++ b/ZcashLightClientKitTests/utils/DarkSideWalletService.swift @@ -7,17 +7,17 @@ import Foundation import ZcashLightClientKit -import SwiftGRPC +import GRPC class DarksideWalletService: LightWalletService { var channel: Channel init() { let channel = ChannelProvider().channel() self.channel = channel self.service = LightWalletGRPCService(channel: channel) - self.darksideService = DarksideStreamerServiceClient(channel: channel) + self.darksideService = DarksideStreamerClient(channel: channel) } var service: LightWalletGRPCService - var darksideService: DarksideStreamerServiceClient + var darksideService: DarksideStreamerClient func latestBlockHeight(result: @escaping (Result) -> Void) { service.latestBlockHeight(result: result) @@ -48,14 +48,14 @@ class DarksideWalletService: LightWalletService { darksideState.latestHeight = UInt64(latestHeight) darksideState.reorgHeight = UInt64(reOrgHeight) - _ = try darksideService.darksideSetState(darksideState, metadata: Metadata()) + _ = try darksideService.darksideSetState(darksideState).response.wait() } func setLatestHeight(_ latestHeight: BlockHeight) throws { - var state = DarksideState() - state.reorgHeight = 0 - state.latestHeight = UInt64(latestHeight) - _ = try darksideService.darksideSetState(state, metadata: Metadata()) + var darksideState = DarksideState() + darksideState.reorgHeight = 0 + darksideState.latestHeight = UInt64(latestHeight) + _ = try darksideService.darksideSetState(darksideState).response.wait() } diff --git a/ZcashLightClientKitTests/utils/Stubs.swift b/ZcashLightClientKitTests/utils/Stubs.swift index 00355ea0..34f769c8 100644 --- a/ZcashLightClientKitTests/utils/Stubs.swift +++ b/ZcashLightClientKitTests/utils/Stubs.swift @@ -7,7 +7,7 @@ // import Foundation -import SwiftGRPC +import GRPC import SwiftProtobuf @testable import ZcashLightClientKit diff --git a/ZcashLightClientKitTests/utils/Tests+Utils.swift b/ZcashLightClientKitTests/utils/Tests+Utils.swift index 7010c7d7..ede53d3c 100644 --- a/ZcashLightClientKitTests/utils/Tests+Utils.swift +++ b/ZcashLightClientKitTests/utils/Tests+Utils.swift @@ -7,19 +7,23 @@ // import Foundation -import SwiftGRPC +import GRPC import ZcashLightClientKit import XCTest - +import NIO class LightWalletEndpointBuilder { static var `default`: LightWalletEndpoint { - LightWalletEndpoint(address: "localhost", port: "9067", secure: false) + LightWalletEndpoint(address: Constants.address, port: 9067, secure: false) } } class ChannelProvider { - func channel(secure: Bool = false) -> SwiftGRPC.Channel { - Channel(address: Constants.address, secure: secure) + func channel(secure: Bool = false) -> GRPCChannel { + let endpoint = LightWalletEndpointBuilder.default + + let configuration = ClientConnection.Configuration(target: .hostAndPort(endpoint.host, endpoint.port), eventLoopGroup: MultiThreadedEventLoopGroup(numberOfThreads: 1), tls: secure ? .init() : nil) + return ClientConnection(configuration: configuration) + } }