[#746] Modularize GRPC related code
Closes #746 - `LightWalletGRPCService` is no longer public. `LightWalletService` is no longer public. - `LightWalletGRPCService` shouldn't be used dicrectly. Use `LightWalletServiceFactory` to create instance of the service. - Moved sending of `blockProcessorConnectivityStateChanged` notification to `Initilizer`. - All the errors from GRPC are mapped to `LightWalletServiceError`. Handling of `GRPCStatus` in the SDK is no longer required. - `Service` directory (that contains GRPC code) is moved to `Modules/Service`. We can put more code to `Modules/` if we decide to modularize more code.
This commit is contained in:
parent
62437c5c7d
commit
385c0a7195
|
@ -2,15 +2,16 @@
|
|||
# https://github.com/raywenderlich/swift-style-guide
|
||||
|
||||
included:
|
||||
- Sources/ZcashLightClientKit/
|
||||
- Tests/
|
||||
- Example/ZcashLightClientSample/ZcashLightClientSample
|
||||
- Example/ZcashLightClientSample/ZcashLightClientSampleTests
|
||||
- Sources/ZcashLightClientKit/
|
||||
- Tests/
|
||||
- Example/ZcashLightClientSample/ZcashLightClientSample
|
||||
- Example/ZcashLightClientSample/ZcashLightClientSampleTests
|
||||
|
||||
excluded:
|
||||
- xctemplates/
|
||||
- Sources/ZcashLightClientKit/Service/ProtoBuf/compact_formats.pb.swift
|
||||
- Sources/ZcashLightClientKit/Service/ProtoBuf/service.pb.swift
|
||||
- Sources/ZcashLightClientKit/Service/ProtoBuf/service.grpc.swift
|
||||
- Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/compact_formats.pb.swift
|
||||
- Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.pb.swift
|
||||
- Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.grpc.swift
|
||||
- Tests/TestUtils/proto
|
||||
- Tests/TestUtils/TestVector.swift
|
||||
- Tests/OfflineTests/BirthdayTests.swift
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# Unreleased
|
||||
|
||||
- [#726] Modularize GRPC layer
|
||||
This is mostly internal change. `LightWalletService` is no longer public. If it
|
||||
is used in your code replace it by using `SDKSynchronizer` API.
|
||||
|
||||
## File system backed block cache
|
||||
|
||||
File system based block cache. Compact blocks will now be stored
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
// Created by Francisco Gindre on 06/09/2019.
|
||||
// Copyright © 2019 Electric Coin Company. All rights reserved.
|
||||
//
|
||||
// swiftlint:disable force_cast force_try force_unwrapping
|
||||
import UIKit
|
||||
import ZcashLightClientKit
|
||||
import NotificationBubbles
|
||||
|
|
|
@ -11,8 +11,8 @@ import ZcashLightClientKit
|
|||
|
||||
class LatestHeightViewController: UIViewController {
|
||||
@IBOutlet weak var blockHeightLabel: UILabel!
|
||||
|
||||
var service: LightWalletService = LightWalletGRPCService(endpoint: DemoAppConfig.endpoint)
|
||||
|
||||
let synchronizer = AppDelegate.shared.sharedSynchronizer
|
||||
var model: BlockHeight? {
|
||||
didSet {
|
||||
if viewIfLoaded != nil {
|
||||
|
@ -32,9 +32,9 @@ class LatestHeightViewController: UIViewController {
|
|||
/// Note: It's safe to modify model or call fail() because all methods of a UIViewController are MainActor methods by default.
|
||||
Task {
|
||||
do {
|
||||
model = try await service.latestBlockHeightAsync()
|
||||
model = try await synchronizer.latestHeight()
|
||||
} catch {
|
||||
fail(error as? LightWalletServiceError ?? .unknown)
|
||||
fail(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ class LatestHeightViewController: UIViewController {
|
|||
blockHeightLabel.text = String(model)
|
||||
}
|
||||
|
||||
func fail(_ error: LightWalletServiceError) {
|
||||
func fail(_ error: Error) {
|
||||
self.blockHeightLabel.text = "Error"
|
||||
|
||||
let alert = UIAlertController(title: "Error", message: String(describing: error), preferredStyle: .alert)
|
||||
|
|
|
@ -27,8 +27,8 @@ let package = Package(
|
|||
.product(name: "libzcashlc", package: "zcash-light-client-ffi")
|
||||
],
|
||||
exclude: [
|
||||
"Service/ProtoBuf/proto/compact_formats.proto",
|
||||
"Service/ProtoBuf/proto/service.proto"
|
||||
"Modules/Service/GRPC/ProtoBuf/proto/compact_formats.proto",
|
||||
"Modules/Service/GRPC/ProtoBuf/proto/service.proto"
|
||||
],
|
||||
resources: [
|
||||
.copy("Resources/checkpoints")
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
// swiftlint:disable file_length type_body_length
|
||||
|
||||
import Foundation
|
||||
import GRPC
|
||||
|
||||
public typealias RefreshedUTXOs = (inserted: [UnspentTransactionOutputEntity], skipped: [UnspentTransactionOutputEntity])
|
||||
|
||||
|
@ -831,13 +830,13 @@ actor CompactBlockProcessor {
|
|||
)
|
||||
}
|
||||
|
||||
func notifyTransactions(_ txs: [ZcashTransaction.Overview], in range: BlockRange) {
|
||||
func notifyTransactions(_ txs: [ZcashTransaction.Overview], in range: CompactBlockRange) {
|
||||
NotificationSender.default.post(
|
||||
name: .blockProcessorFoundTransactions,
|
||||
object: self,
|
||||
userInfo: [
|
||||
CompactBlockProcessorNotificationKey.foundTransactions: txs,
|
||||
CompactBlockProcessorNotificationKey.foundTransactionsRange: ClosedRange(uncheckedBounds: (range.start.height, range.end.height))
|
||||
CompactBlockProcessorNotificationKey.foundTransactionsRange: range
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -885,17 +884,6 @@ actor CompactBlockProcessor {
|
|||
}
|
||||
if let lwdError = error as? LightWalletServiceError {
|
||||
return lwdError.mapToProcessorError()
|
||||
} else if let rpcError = error as? GRPC.GRPCStatus {
|
||||
switch rpcError {
|
||||
case .ok:
|
||||
LoggerProxy.warn("Error Raised when status is OK")
|
||||
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 .unspecifiedError(underlyingError: error)
|
||||
}
|
||||
|
|
|
@ -57,18 +57,17 @@ extension CompactBlockProcessor {
|
|||
LoggerProxy.debug("Started Enhancing range: \(range)")
|
||||
state = .enhancing
|
||||
|
||||
let blockRange = range.blockRange()
|
||||
var retries = 0
|
||||
let maxRetries = 5
|
||||
|
||||
// fetch transactions
|
||||
do {
|
||||
let startTime = Date()
|
||||
let transactions = try transactionRepository.find(in: blockRange, limit: Int.max, kind: .all)
|
||||
let transactions = try transactionRepository.find(in: range, limit: Int.max, kind: .all)
|
||||
|
||||
guard !transactions.isEmpty else {
|
||||
await internalSyncProgress.set(range.upperBound, .latestEnhancedHeight)
|
||||
LoggerProxy.debug("no transactions detected on range: \(blockRange.printRange)")
|
||||
LoggerProxy.debug("no transactions detected on range: \(range.lowerBound)...\(range.upperBound)")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -121,8 +120,8 @@ extension CompactBlockProcessor {
|
|||
throw error
|
||||
}
|
||||
|
||||
if let foundTxs = try? transactionRepository.find(in: blockRange, limit: Int.max, kind: .all) {
|
||||
notifyTransactions(foundTxs, in: blockRange)
|
||||
if let foundTxs = try? transactionRepository.find(in: range, limit: Int.max, kind: .all) {
|
||||
notifyTransactions(foundTxs, in: range)
|
||||
}
|
||||
|
||||
await internalSyncProgress.set(range.upperBound, .latestEnhancedHeight)
|
||||
|
@ -132,9 +131,3 @@ extension CompactBlockProcessor {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension BlockRange {
|
||||
var printRange: String {
|
||||
"\(self.start.height) ... \(self.end.height)"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,12 +78,12 @@ class TransactionSQLDAO: TransactionRepository {
|
|||
return try execute(query) { try ZcashTransaction.Overview(row: $0) }
|
||||
}
|
||||
|
||||
func find(in range: BlockRange, limit: Int, kind: TransactionKind) throws -> [ZcashTransaction.Overview] {
|
||||
func find(in range: CompactBlockRange, limit: Int, kind: TransactionKind) throws -> [ZcashTransaction.Overview] {
|
||||
let query = transactionsView
|
||||
.order((ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc, ZcashTransaction.Overview.Column.id.desc)
|
||||
.filter(
|
||||
ZcashTransaction.Overview.Column.minedHeight >= BlockHeight(range.start.height) &&
|
||||
ZcashTransaction.Overview.Column.minedHeight <= BlockHeight(range.end.height)
|
||||
ZcashTransaction.Overview.Column.minedHeight >= BlockHeight(range.lowerBound) &&
|
||||
ZcashTransaction.Overview.Column.minedHeight <= BlockHeight(range.upperBound)
|
||||
)
|
||||
.filterQueryFor(kind: kind)
|
||||
.limit(limit)
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// BlockProgress.swift
|
||||
//
|
||||
//
|
||||
// Created by Michal Fousek on 03.02.2023.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct BlockProgress: Equatable {
|
||||
public var startHeight: BlockHeight
|
||||
public var targetHeight: BlockHeight
|
||||
public var progressHeight: BlockHeight
|
||||
|
||||
public var progress: Float {
|
||||
let overall = self.targetHeight - self.startHeight
|
||||
|
||||
return overall > 0 ? Float((self.progressHeight - self.startHeight)) / Float(overall) : 0
|
||||
}
|
||||
}
|
||||
|
||||
public extension BlockProgress {
|
||||
static let nullProgress = BlockProgress(startHeight: 0, targetHeight: 0, progressHeight: 0)
|
||||
}
|
|
@ -55,7 +55,8 @@ public enum ZcashTransaction {
|
|||
public let value: Zatoshi
|
||||
}
|
||||
|
||||
public struct Fetched {
|
||||
/// Used when fetching blocks from the lightwalletd
|
||||
struct Fetched {
|
||||
public let rawID: Data
|
||||
public let minedHeight: BlockHeight
|
||||
public let raw: Data
|
||||
|
|
|
@ -21,6 +21,37 @@ extension BlockHeight {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
A Zcash compact block to store on cache DB
|
||||
*/
|
||||
public struct ZcashCompactBlock {
|
||||
struct Meta {
|
||||
var hash: Data
|
||||
var time: UInt32
|
||||
var saplingOutputs: UInt32
|
||||
var orchardOutputs: UInt32
|
||||
}
|
||||
|
||||
public var height: BlockHeight
|
||||
public var data: Data
|
||||
|
||||
var meta: Meta
|
||||
}
|
||||
|
||||
extension ZcashCompactBlock: Encodable {
|
||||
enum CodingKeys: CodingKey {
|
||||
case height
|
||||
case data
|
||||
case meta
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(data, forKey: .data)
|
||||
try container.encode(height, forKey: .height)
|
||||
}
|
||||
}
|
||||
|
||||
extension ZcashCompactBlock {
|
||||
init(compactBlock: CompactBlock) {
|
||||
self.height = Int(compactBlock.height)
|
|
@ -53,12 +53,17 @@ public struct LightWalletEndpoint {
|
|||
}
|
||||
}
|
||||
|
||||
extension Notification.Name {
|
||||
static let connectionStatusChanged = Notification.Name("LightWalletServiceConnectivityStatusChanged")
|
||||
}
|
||||
|
||||
/**
|
||||
Wrapper for all the Rust backend functionality that does not involve processing blocks. This
|
||||
class initializes the Rust backend and the supporting data required to exercise those abilities.
|
||||
The [cash.z.wallet.sdk.block.CompactBlockProcessor] handles all the remaining Rust backend
|
||||
functionality, related to processing blocks.
|
||||
*/
|
||||
// swiftlint:disable:next type_body_length
|
||||
public class Initializer {
|
||||
public enum InitializationResult {
|
||||
case success
|
||||
|
@ -119,7 +124,7 @@ public class Initializer {
|
|||
dataDbURL: dataDbURL,
|
||||
pendingDbURL: pendingDbURL,
|
||||
endpoint: endpoint,
|
||||
service: LightWalletGRPCService(endpoint: endpoint),
|
||||
service: Self.makeLightWalletServiceFactory(endpoint: endpoint).make(),
|
||||
repository: TransactionRepositoryBuilder.build(dataDbURL: dataDbURL),
|
||||
accountRepository: AccountRepositoryBuilder.build(
|
||||
dataDbURL: dataDbURL,
|
||||
|
@ -171,8 +176,6 @@ public class Initializer {
|
|||
alias: String = "",
|
||||
loggerProxy: Logger? = nil
|
||||
) {
|
||||
let lwdService = LightWalletGRPCService(endpoint: endpoint)
|
||||
|
||||
self.init(
|
||||
rustBackend: ZcashRustBackend.self,
|
||||
lowerBoundHeight: walletBirthday,
|
||||
|
@ -182,7 +185,7 @@ public class Initializer {
|
|||
dataDbURL: dataDbURL,
|
||||
pendingDbURL: pendingDbURL,
|
||||
endpoint: endpoint,
|
||||
service: lwdService,
|
||||
service: Self.makeLightWalletServiceFactory(endpoint: endpoint).make(),
|
||||
repository: TransactionRepositoryBuilder.build(dataDbURL: dataDbURL),
|
||||
accountRepository: AccountRepositoryBuilder.build(
|
||||
dataDbURL: dataDbURL,
|
||||
|
@ -251,6 +254,22 @@ public class Initializer {
|
|||
self.network = network
|
||||
}
|
||||
|
||||
private static func makeLightWalletServiceFactory(endpoint: LightWalletEndpoint) -> LightWalletServiceFactory {
|
||||
return LightWalletServiceFactory(
|
||||
endpoint: endpoint,
|
||||
connectionStateChange: { oldState, newState in
|
||||
NotificationSender.default.post(
|
||||
name: .blockProcessorConnectivityStateChanged,
|
||||
object: nil,
|
||||
userInfo: [
|
||||
CompactBlockProcessorNotificationKey.currentConnectivityStatus: newState,
|
||||
CompactBlockProcessorNotificationKey.previousConnectivityStatus: oldState
|
||||
]
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/// Initialize the wallet. The ZIP-32 seed bytes can optionally be passed to perform
|
||||
/// database migrations. most of the times the seed won't be needed. If they do and are
|
||||
/// not provided this will fail with `InitializationResult.seedRequired`. It could
|
||||
|
|
|
@ -12,96 +12,47 @@ import NIO
|
|||
import NIOHPACK
|
||||
import NIOTransportServices
|
||||
|
||||
public typealias Channel = GRPC.GRPCChannel
|
||||
|
||||
public protocol LightWalletdInfo {
|
||||
var version: String { get }
|
||||
|
||||
var vendor: String { get }
|
||||
|
||||
/// true
|
||||
var taddrSupport: Bool { get }
|
||||
|
||||
/// either "main" or "test"
|
||||
var chainName: String { get }
|
||||
|
||||
/// depends on mainnet or testnet
|
||||
var saplingActivationHeight: UInt64 { get }
|
||||
|
||||
/// protocol identifier, see consensus/upgrades.cpp
|
||||
var consensusBranchID: String { get }
|
||||
|
||||
/// latest block on the best chain
|
||||
var blockHeight: UInt64 { get }
|
||||
|
||||
var gitCommit: String { get }
|
||||
|
||||
var branch: String { get }
|
||||
|
||||
var buildDate: String { get }
|
||||
|
||||
var buildUser: String { get }
|
||||
|
||||
/// less than tip height if zcashd is syncing
|
||||
var estimatedHeight: UInt64 { get }
|
||||
|
||||
/// example: "v4.1.1-877212414"
|
||||
var zcashdBuild: String { get }
|
||||
|
||||
/// example: "/MagicBean:4.1.1/"
|
||||
var zcashdSubversion: String { get }
|
||||
}
|
||||
typealias Channel = GRPC.GRPCChannel
|
||||
|
||||
extension LightdInfo: LightWalletdInfo {}
|
||||
extension SendResponse: LightWalletServiceResponse {}
|
||||
|
||||
/**
|
||||
Swift GRPC implementation of Lightwalletd service
|
||||
*/
|
||||
public enum GRPCResult: Equatable {
|
||||
enum GRPCResult: Equatable {
|
||||
case success
|
||||
case error(_ error: LightWalletServiceError)
|
||||
}
|
||||
|
||||
public protocol CancellableCall {
|
||||
protocol CancellableCall {
|
||||
func cancel()
|
||||
}
|
||||
|
||||
extension ServerStreamingCall: CancellableCall {
|
||||
public func cancel() {
|
||||
func cancel() {
|
||||
self.cancel(promise: self.eventLoop.makePromise(of: Void.self))
|
||||
}
|
||||
}
|
||||
|
||||
public struct BlockProgress: Equatable {
|
||||
public var startHeight: BlockHeight
|
||||
public var targetHeight: BlockHeight
|
||||
public var progressHeight: BlockHeight
|
||||
|
||||
public var progress: Float {
|
||||
let overall = self.targetHeight - self.startHeight
|
||||
|
||||
return overall > 0 ? Float((self.progressHeight - self.startHeight)) / Float(overall) : 0
|
||||
}
|
||||
}
|
||||
|
||||
public extension BlockProgress {
|
||||
static let nullProgress = BlockProgress(startHeight: 0, targetHeight: 0, progressHeight: 0)
|
||||
}
|
||||
|
||||
protocol LatestBlockHeightProvider {
|
||||
func latestBlockHeight(streamer: CompactTxStreamerNIOClient?) throws -> BlockHeight
|
||||
}
|
||||
|
||||
class LiveLatestBlockHeightProvider: LatestBlockHeightProvider {
|
||||
func latestBlockHeight(streamer: CompactTxStreamerNIOClient?) throws -> BlockHeight {
|
||||
guard let height = try? streamer?.getLatestBlock(ChainSpec()).response.wait().compactBlockHeight() else {
|
||||
throw LightWalletServiceError.timeOut
|
||||
do {
|
||||
guard let height = try? streamer?.getLatestBlock(ChainSpec()).response.wait().compactBlockHeight() else {
|
||||
throw LightWalletServiceError.timeOut
|
||||
}
|
||||
return height
|
||||
} catch {
|
||||
throw error.mapToServiceError()
|
||||
}
|
||||
return height
|
||||
}
|
||||
}
|
||||
|
||||
public class LightWalletGRPCService {
|
||||
class LightWalletGRPCService {
|
||||
let channel: Channel
|
||||
let connectionManager: ConnectionStatusManager
|
||||
let compactTxStreamer: CompactTxStreamerNIOClient
|
||||
|
@ -112,13 +63,14 @@ public class LightWalletGRPCService {
|
|||
|
||||
var queue: DispatchQueue
|
||||
|
||||
public convenience init(endpoint: LightWalletEndpoint) {
|
||||
convenience init(endpoint: LightWalletEndpoint, connectionStateChange: @escaping (_ from: ConnectionState, _ to: ConnectionState) -> Void) {
|
||||
self.init(
|
||||
host: endpoint.host,
|
||||
port: endpoint.port,
|
||||
secure: endpoint.secure,
|
||||
singleCallTimeout: endpoint.singleCallTimeoutInMillis,
|
||||
streamingCallTimeout: endpoint.streamingCallTimeoutInMillis
|
||||
streamingCallTimeout: endpoint.streamingCallTimeoutInMillis,
|
||||
connectionStateChange: connectionStateChange
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -129,14 +81,15 @@ public class LightWalletGRPCService {
|
|||
/// - secure: whether this server is TLS or plaintext. default True (TLS)
|
||||
/// - singleCallTimeout: Timeout for unary calls in milliseconds.
|
||||
/// - streamingCallTimeout: Timeout for streaming calls in milliseconds.
|
||||
public init(
|
||||
init(
|
||||
host: String,
|
||||
port: Int = 9067,
|
||||
secure: Bool = true,
|
||||
singleCallTimeout: Int64,
|
||||
streamingCallTimeout: Int64
|
||||
streamingCallTimeout: Int64,
|
||||
connectionStateChange: @escaping (_ from: ConnectionState, _ to: ConnectionState) -> Void
|
||||
) {
|
||||
self.connectionManager = ConnectionStatusManager()
|
||||
self.connectionManager = ConnectionStatusManager(connectionStateChange: connectionStateChange)
|
||||
self.queue = DispatchQueue.init(label: "LightWalletGRPCService")
|
||||
self.streamingCallTimeout = TimeLimit.timeout(.milliseconds(streamingCallTimeout))
|
||||
self.singleCallTimeout = TimeLimit.timeout(.milliseconds(singleCallTimeout))
|
||||
|
@ -176,19 +129,27 @@ public class LightWalletGRPCService {
|
|||
_ = channel.close()
|
||||
}
|
||||
|
||||
func blockRange(startHeight: BlockHeight, endHeight: BlockHeight? = nil, result: @escaping (CompactBlock) -> Void) throws -> ServerStreamingCall<BlockRange, CompactBlock> {
|
||||
func blockRange(startHeight: BlockHeight, endHeight: BlockHeight? = nil, result: @escaping (CompactBlock) -> Void) -> ServerStreamingCall<BlockRange, CompactBlock> {
|
||||
compactTxStreamer.getBlockRange(BlockRange(startHeight: startHeight, endHeight: endHeight), handler: result)
|
||||
}
|
||||
|
||||
func latestBlock() throws -> BlockID {
|
||||
try compactTxStreamer.getLatestBlock(ChainSpec()).response.wait()
|
||||
do {
|
||||
return try compactTxStreamer.getLatestBlock(ChainSpec()).response.wait()
|
||||
} catch {
|
||||
throw error.mapToServiceError()
|
||||
}
|
||||
}
|
||||
|
||||
func getTx(hash: String) throws -> RawTransaction {
|
||||
var filter = TxFilter()
|
||||
filter.hash = Data(hash.utf8)
|
||||
|
||||
return try compactTxStreamer.getTransaction(filter).response.wait()
|
||||
do {
|
||||
return try compactTxStreamer.getTransaction(filter).response.wait()
|
||||
} catch {
|
||||
throw error.mapToServiceError()
|
||||
}
|
||||
}
|
||||
|
||||
static func callOptions(timeLimit: TimeLimit) -> CallOptions {
|
||||
|
@ -206,23 +167,35 @@ public class LightWalletGRPCService {
|
|||
// MARK: - LightWalletService
|
||||
|
||||
extension LightWalletGRPCService: LightWalletService {
|
||||
public func getInfo() async throws -> LightWalletdInfo {
|
||||
try await compactTxStreamerAsync.getLightdInfo(Empty())
|
||||
func getInfo() async throws -> LightWalletdInfo {
|
||||
do {
|
||||
return try await compactTxStreamerAsync.getLightdInfo(Empty())
|
||||
} catch {
|
||||
throw error.mapToServiceError()
|
||||
}
|
||||
}
|
||||
|
||||
public func latestBlockHeight() throws -> BlockHeight {
|
||||
try latestBlockHeightProvider.latestBlockHeight(streamer: compactTxStreamer)
|
||||
func latestBlockHeight() throws -> BlockHeight {
|
||||
do {
|
||||
return try latestBlockHeightProvider.latestBlockHeight(streamer: compactTxStreamer)
|
||||
} catch {
|
||||
throw error.mapToServiceError()
|
||||
}
|
||||
}
|
||||
|
||||
public func latestBlockHeightAsync() async throws -> BlockHeight {
|
||||
let blockID = try await compactTxStreamerAsync.getLatestBlock(ChainSpec())
|
||||
guard let blockHeight = Int(exactly: blockID.height) else {
|
||||
throw LightWalletServiceError.generalError(message: "error creating blockheight from BlockID \(blockID)")
|
||||
func latestBlockHeightAsync() async throws -> BlockHeight {
|
||||
do {
|
||||
let blockID = try await compactTxStreamerAsync.getLatestBlock(ChainSpec())
|
||||
guard let blockHeight = Int(exactly: blockID.height) else {
|
||||
throw LightWalletServiceError.generalError(message: "error creating blockheight from BlockID \(blockID)")
|
||||
}
|
||||
return blockHeight
|
||||
} catch {
|
||||
throw error.mapToServiceError()
|
||||
}
|
||||
return blockHeight
|
||||
}
|
||||
|
||||
public func blockRange(_ range: CompactBlockRange) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
|
||||
func blockRange(_ range: CompactBlockRange) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
|
||||
let stream = compactTxStreamerAsync.getBlockRange(range.blockRange())
|
||||
|
||||
return AsyncThrowingStream { continuation in
|
||||
|
@ -239,7 +212,7 @@ extension LightWalletGRPCService: LightWalletService {
|
|||
}
|
||||
}
|
||||
|
||||
public func submit(spendTransaction: Data) async throws -> LightWalletServiceResponse {
|
||||
func submit(spendTransaction: Data) async throws -> LightWalletServiceResponse {
|
||||
do {
|
||||
let transaction = RawTransaction.with { $0.data = spendTransaction }
|
||||
return try await compactTxStreamerAsync.sendTransaction(transaction)
|
||||
|
@ -248,15 +221,19 @@ extension LightWalletGRPCService: LightWalletService {
|
|||
}
|
||||
}
|
||||
|
||||
public func fetchTransaction(txId: Data) async throws -> ZcashTransaction.Fetched {
|
||||
func fetchTransaction(txId: Data) async throws -> ZcashTransaction.Fetched {
|
||||
var txFilter = TxFilter()
|
||||
txFilter.hash = txId
|
||||
|
||||
let rawTx = try await compactTxStreamerAsync.getTransaction(txFilter)
|
||||
return ZcashTransaction.Fetched(rawID: txId, minedHeight: BlockHeight(rawTx.height), raw: rawTx.data)
|
||||
do {
|
||||
let rawTx = try await compactTxStreamerAsync.getTransaction(txFilter)
|
||||
return ZcashTransaction.Fetched(rawID: txId, minedHeight: BlockHeight(rawTx.height), raw: rawTx.data)
|
||||
} catch {
|
||||
throw error.mapToServiceError()
|
||||
}
|
||||
}
|
||||
|
||||
public func fetchUTXOs(
|
||||
func fetchUTXOs(
|
||||
for tAddress: String,
|
||||
height: BlockHeight,
|
||||
result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>
|
||||
|
@ -298,14 +275,14 @@ extension LightWalletGRPCService: LightWalletService {
|
|||
}
|
||||
}
|
||||
|
||||
public func fetchUTXOs(
|
||||
func fetchUTXOs(
|
||||
for tAddress: String,
|
||||
height: BlockHeight
|
||||
) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
|
||||
return fetchUTXOs(for: [tAddress], height: height)
|
||||
}
|
||||
|
||||
public func fetchUTXOs(
|
||||
func fetchUTXOs(
|
||||
for tAddresses: [String],
|
||||
height: BlockHeight
|
||||
) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
|
||||
|
@ -344,7 +321,7 @@ extension LightWalletGRPCService: LightWalletService {
|
|||
}
|
||||
}
|
||||
|
||||
public func blockStream(
|
||||
func blockStream(
|
||||
startHeight: BlockHeight,
|
||||
endHeight: BlockHeight
|
||||
) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
|
||||
|
@ -370,15 +347,28 @@ extension LightWalletGRPCService: LightWalletService {
|
|||
}
|
||||
}
|
||||
|
||||
public func closeConnection() {
|
||||
func closeConnection() {
|
||||
_ = channel.close()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Extensions
|
||||
|
||||
extension Notification.Name {
|
||||
static let connectionStatusChanged = Notification.Name("LightWalletServiceConnectivityStatusChanged")
|
||||
extension ConnectivityState {
|
||||
func toConnectionState() -> ConnectionState {
|
||||
switch self {
|
||||
case .connecting:
|
||||
return .connecting
|
||||
case .idle:
|
||||
return .idle
|
||||
case .ready:
|
||||
return .online
|
||||
case .shutdown:
|
||||
return .shutdown
|
||||
case .transientFailure:
|
||||
return .reconnecting
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension TimeAmount {
|
||||
|
@ -427,15 +417,12 @@ extension LightWalletServiceError {
|
|||
}
|
||||
|
||||
class ConnectionStatusManager: ConnectivityStateDelegate {
|
||||
let connectionStateChange: (_ from: ConnectionState, _ to: ConnectionState) -> Void
|
||||
init(connectionStateChange: @escaping (_ from: ConnectionState, _ to: ConnectionState) -> Void) {
|
||||
self.connectionStateChange = connectionStateChange
|
||||
}
|
||||
|
||||
func connectivityStateDidChange(from oldState: ConnectivityState, to newState: ConnectivityState) {
|
||||
LoggerProxy.event("Connection Changed from \(oldState) to \(newState)")
|
||||
NotificationSender.default.post(
|
||||
name: .blockProcessorConnectivityStateChanged,
|
||||
object: self,
|
||||
userInfo: [
|
||||
CompactBlockProcessorNotificationKey.currentConnectivityStatus: newState,
|
||||
CompactBlockProcessorNotificationKey.previousConnectivityStatus: oldState
|
||||
]
|
||||
)
|
||||
connectionStateChange(oldState.toConnectionState(), newState.toConnectionState())
|
||||
}
|
||||
}
|
|
@ -7,13 +7,11 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import GRPC
|
||||
import SwiftProtobuf
|
||||
|
||||
/**
|
||||
Wrapper for errors received from a Lightwalletd endpoint
|
||||
*/
|
||||
public enum LightWalletServiceError: Error {
|
||||
enum LightWalletServiceError: Error {
|
||||
case generalError(message: String)
|
||||
case failed(statusCode: Int, message: String)
|
||||
case invalidBlock
|
||||
|
@ -27,7 +25,7 @@ public enum LightWalletServiceError: Error {
|
|||
|
||||
extension LightWalletServiceError: Equatable {
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
public static func == (lhs: Self, rhs: Self) -> Bool {
|
||||
static func == (lhs: Self, rhs: Self) -> Bool {
|
||||
switch lhs {
|
||||
case .generalError(let message):
|
||||
switch rhs {
|
||||
|
@ -93,15 +91,64 @@ extension LightWalletServiceError: Equatable {
|
|||
}
|
||||
}
|
||||
|
||||
public protocol LightWalletServiceResponse {
|
||||
var errorCode: Int32 { get }
|
||||
var errorMessage: String { get }
|
||||
var unknownFields: SwiftProtobuf.UnknownStorage { get }
|
||||
protocol LightWalletdInfo {
|
||||
var version: String { get }
|
||||
|
||||
var vendor: String { get }
|
||||
|
||||
/// true
|
||||
var taddrSupport: Bool { get }
|
||||
|
||||
/// either "main" or "test"
|
||||
var chainName: String { get }
|
||||
|
||||
/// depends on mainnet or testnet
|
||||
var saplingActivationHeight: UInt64 { get }
|
||||
|
||||
/// protocol identifier, see consensus/upgrades.cpp
|
||||
var consensusBranchID: String { get }
|
||||
|
||||
/// latest block on the best chain
|
||||
var blockHeight: UInt64 { get }
|
||||
|
||||
var gitCommit: String { get }
|
||||
|
||||
var branch: String { get }
|
||||
|
||||
var buildDate: String { get }
|
||||
|
||||
var buildUser: String { get }
|
||||
|
||||
/// less than tip height if zcashd is syncing
|
||||
var estimatedHeight: UInt64 { get }
|
||||
|
||||
/// example: "v4.1.1-877212414"
|
||||
var zcashdBuild: String { get }
|
||||
|
||||
/// example: "/MagicBean:4.1.1/"
|
||||
var zcashdSubversion: String { get }
|
||||
}
|
||||
|
||||
extension SendResponse: LightWalletServiceResponse {}
|
||||
protocol LightWalletServiceResponse {
|
||||
var errorCode: Int32 { get }
|
||||
var errorMessage: String { get }
|
||||
}
|
||||
|
||||
public protocol LightWalletService {
|
||||
struct LightWalletServiceFactory {
|
||||
let endpoint: LightWalletEndpoint
|
||||
let connectionStateChange: (_ from: ConnectionState, _ to: ConnectionState) -> Void
|
||||
|
||||
init(endpoint: LightWalletEndpoint, connectionStateChange: @escaping (_ from: ConnectionState, _ to: ConnectionState) -> Void) {
|
||||
self.endpoint = endpoint
|
||||
self.connectionStateChange = connectionStateChange
|
||||
}
|
||||
|
||||
func make() -> LightWalletService {
|
||||
return LightWalletGRPCService(endpoint: endpoint, connectionStateChange: connectionStateChange)
|
||||
}
|
||||
}
|
||||
|
||||
protocol LightWalletService {
|
||||
/// Returns the info for this lightwalletd server
|
||||
func getInfo() async throws -> LightWalletdInfo
|
||||
|
|
@ -8,37 +8,6 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
A Zcash compact block to store on cache DB
|
||||
*/
|
||||
public struct ZcashCompactBlock {
|
||||
struct Meta {
|
||||
var hash: Data
|
||||
var time: UInt32
|
||||
var saplingOutputs: UInt32
|
||||
var orchardOutputs: UInt32
|
||||
}
|
||||
|
||||
public var height: BlockHeight
|
||||
public var data: Data
|
||||
|
||||
var meta: Meta
|
||||
}
|
||||
|
||||
extension ZcashCompactBlock: Encodable {
|
||||
enum CodingKeys: CodingKey {
|
||||
case height
|
||||
case data
|
||||
case meta
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(data, forKey: .data)
|
||||
try container.encode(height, forKey: .height)
|
||||
}
|
||||
}
|
||||
|
||||
enum CompactBlockRepositoryError: Error, Equatable {
|
||||
/// cache is empty
|
||||
case cacheEmpty
|
||||
|
|
|
@ -23,7 +23,7 @@ protocol TransactionRepository {
|
|||
func find(id: Int) throws -> ZcashTransaction.Overview
|
||||
func find(rawID: Data) throws -> ZcashTransaction.Overview
|
||||
func find(offset: Int, limit: Int, kind: TransactionKind) throws -> [ZcashTransaction.Overview]
|
||||
func find(in range: BlockRange, limit: Int, kind: TransactionKind) throws -> [ZcashTransaction.Overview]
|
||||
func find(in range: CompactBlockRange, limit: Int, kind: TransactionKind) throws -> [ZcashTransaction.Overview]
|
||||
func find(from: ZcashTransaction.Overview, limit: Int, kind: TransactionKind) throws -> [ZcashTransaction.Overview]
|
||||
func findReceived(offset: Int, limit: Int) throws -> [ZcashTransaction.Received]
|
||||
func findSent(offset: Int, limit: Int) throws -> [ZcashTransaction.Sent]
|
||||
|
|
|
@ -305,8 +305,8 @@ public class SDKSynchronizer: Synchronizer {
|
|||
@objc func connectivityStateChanged(_ notification: Notification) {
|
||||
guard
|
||||
let userInfo = notification.userInfo,
|
||||
let previous = userInfo[CompactBlockProcessorNotificationKey.previousConnectivityStatus] as? ConnectivityState,
|
||||
let current = userInfo[CompactBlockProcessorNotificationKey.currentConnectivityStatus] as? ConnectivityState
|
||||
let previous = userInfo[CompactBlockProcessorNotificationKey.previousConnectivityStatus] as? ConnectionState,
|
||||
let current = userInfo[CompactBlockProcessorNotificationKey.currentConnectivityStatus] as? ConnectionState
|
||||
else {
|
||||
LoggerProxy.error(
|
||||
"Found \(Notification.Name.blockProcessorConnectivityStateChanged) but lacks dictionary information." +
|
||||
|
@ -315,17 +315,16 @@ public class SDKSynchronizer: Synchronizer {
|
|||
return
|
||||
}
|
||||
|
||||
let currentState = ConnectionState(current)
|
||||
NotificationSender.default.post(
|
||||
name: .synchronizerConnectionStateChanged,
|
||||
object: self,
|
||||
userInfo: [
|
||||
NotificationKeys.previousConnectionState: ConnectionState(previous),
|
||||
NotificationKeys.currentConnectionState: currentState
|
||||
NotificationKeys.previousConnectionState: previous,
|
||||
NotificationKeys.currentConnectionState: current
|
||||
]
|
||||
)
|
||||
|
||||
connectionState = currentState
|
||||
connectionState = current
|
||||
}
|
||||
|
||||
@objc func transactionsFound(_ notification: Notification) {
|
||||
|
@ -890,24 +889,6 @@ extension SDKSynchronizer {
|
|||
}
|
||||
}
|
||||
|
||||
import GRPC
|
||||
extension ConnectionState {
|
||||
init(_ connectivityState: ConnectivityState) {
|
||||
switch connectivityState {
|
||||
case .connecting:
|
||||
self = .connecting
|
||||
case .idle:
|
||||
self = .idle
|
||||
case .ready:
|
||||
self = .online
|
||||
case .shutdown:
|
||||
self = .shutdown
|
||||
case .transientFailure:
|
||||
self = .reconnecting
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct NullEnhancementProgress: EnhancementProgress {
|
||||
var totalTransactions: Int { 0 }
|
||||
var enhancedTransactions: Int { 0 }
|
||||
|
|
|
@ -36,7 +36,6 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
self.coordinator = try TestCoordinator(
|
||||
seed: seedPhrase,
|
||||
walletBirthday: birthday + 50, // don't use an exact birthday, users never do.
|
||||
channelProvider: ChannelProvider(),
|
||||
network: network
|
||||
)
|
||||
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
|
||||
|
|
|
@ -33,7 +33,6 @@ class BalanceTests: XCTestCase {
|
|||
self.coordinator = try TestCoordinator(
|
||||
seed: self.seedPhrase,
|
||||
walletBirthday: self.birthday,
|
||||
channelProvider: ChannelProvider(),
|
||||
network: self.network
|
||||
)
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class BlockDownloaderTests: XCTestCase {
|
|||
|
||||
override func setUpWithError() throws {
|
||||
try super.setUpWithError()
|
||||
service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
|
||||
service = LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default, connectionStateChange: { _, _ in }).make()
|
||||
try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false)
|
||||
storage = FSCompactBlockRepository(
|
||||
cacheDirectory: testTempDirectory,
|
||||
|
|
|
@ -36,7 +36,6 @@ class DarksideSanityCheckTests: XCTestCase {
|
|||
self.coordinator = try TestCoordinator(
|
||||
seed: self.seedPhrase,
|
||||
walletBirthday: self.birthday,
|
||||
channelProvider: ChannelProvider(),
|
||||
network: self.network
|
||||
)
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ final class InternalStateConsistencyTests: XCTestCase {
|
|||
self.coordinator = try TestCoordinator(
|
||||
seed: seedPhrase,
|
||||
walletBirthday: birthday + 50, // don't use an exact birthday, users never do.
|
||||
channelProvider: ChannelProvider(),
|
||||
network: network
|
||||
)
|
||||
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
|
||||
|
|
|
@ -34,7 +34,6 @@ class PendingTransactionUpdatesTest: XCTestCase {
|
|||
self.coordinator = try TestCoordinator(
|
||||
seed: self.seedPhrase,
|
||||
walletBirthday: self.birthday,
|
||||
channelProvider: ChannelProvider(),
|
||||
network: self.network
|
||||
)
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ class ReOrgTests: XCTestCase {
|
|||
self.coordinator = try TestCoordinator(
|
||||
seed: self.seedPhrase,
|
||||
walletBirthday: self.birthday,
|
||||
channelProvider: ChannelProvider(),
|
||||
network: self.network
|
||||
)
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ class RewindRescanTests: XCTestCase {
|
|||
self.coordinator = try TestCoordinator(
|
||||
seed: self.seedPhrase,
|
||||
walletBirthday: self.birthday,
|
||||
channelProvider: ChannelProvider(),
|
||||
network: self.network
|
||||
)
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ class ShieldFundsTests: XCTestCase {
|
|||
self.coordinator = try TestCoordinator(
|
||||
seed: seedPhrase,
|
||||
walletBirthday: birthday,
|
||||
channelProvider: ChannelProvider(),
|
||||
network: network
|
||||
)
|
||||
try coordinator.reset(saplingActivation: birthday, branchID: self.branchID, chainName: self.chainName)
|
||||
|
|
|
@ -38,7 +38,6 @@ class SychronizerDarksideTests: XCTestCase {
|
|||
self.coordinator = try TestCoordinator(
|
||||
seed: self.seedPhrase,
|
||||
walletBirthday: self.birthday,
|
||||
channelProvider: ChannelProvider(),
|
||||
network: self.network
|
||||
)
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ final class SynchronizerTests: XCTestCase {
|
|||
self.coordinator = try TestCoordinator(
|
||||
seed: self.seedPhrase,
|
||||
walletBirthday: self.birthday + 50, // don't use an exact birthday, users never do.
|
||||
channelProvider: ChannelProvider(),
|
||||
network: self.network
|
||||
)
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ class Z2TReceiveTests: XCTestCase {
|
|||
self.coordinator = try TestCoordinator(
|
||||
seed: self.seedPhrase,
|
||||
walletBirthday: self.birthday,
|
||||
channelProvider: ChannelProvider(),
|
||||
network: self.network
|
||||
)
|
||||
|
||||
|
|
|
@ -67,12 +67,8 @@ class BlockScanTests: XCTestCase {
|
|||
|
||||
XCTAssertNoThrow(try rustWelding.initDataDb(dbData: dataDbURL, seed: nil, networkType: network.networkType))
|
||||
|
||||
let service = LightWalletGRPCService(
|
||||
endpoint: LightWalletEndpoint(
|
||||
address: "lightwalletd.testnet.electriccoin.co",
|
||||
port: 9067
|
||||
)
|
||||
)
|
||||
let endpoint = LightWalletEndpoint(address: "lightwalletd.testnet.electriccoin.co", port: 9067)
|
||||
let service = LightWalletServiceFactory(endpoint: endpoint, connectionStateChange: { _, _ in }).make()
|
||||
let blockCount = 100
|
||||
let range = network.constants.saplingActivationHeight ... network.constants.saplingActivationHeight + blockCount
|
||||
|
||||
|
@ -90,6 +86,7 @@ class BlockScanTests: XCTestCase {
|
|||
)
|
||||
|
||||
try fsBlockRepository.create()
|
||||
|
||||
let processorConfig = CompactBlockProcessor.Configuration(
|
||||
fsBlockCacheRoot: fsDbRootURL,
|
||||
dataDb: dataDbURL,
|
||||
|
@ -169,7 +166,7 @@ class BlockScanTests: XCTestCase {
|
|||
networkType: network.networkType
|
||||
)
|
||||
|
||||
let service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet)
|
||||
let service = LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.eccTestnet, connectionStateChange: { _, _ in }).make()
|
||||
|
||||
let fsDbRootURL = self.testTempDirectory
|
||||
|
||||
|
|
|
@ -31,14 +31,15 @@ class BlockStreamingTest: XCTestCase {
|
|||
}
|
||||
|
||||
func testStream() async throws {
|
||||
let service = LightWalletGRPCService(
|
||||
host: LightWalletEndpointBuilder.eccTestnet.host,
|
||||
let endpoint = LightWalletEndpoint(
|
||||
address: LightWalletEndpointBuilder.eccTestnet.host,
|
||||
port: 9067,
|
||||
secure: true,
|
||||
singleCallTimeout: 1000,
|
||||
streamingCallTimeout: 100000
|
||||
singleCallTimeoutInMillis: 1000,
|
||||
streamingCallTimeoutInMillis: 100000
|
||||
)
|
||||
|
||||
let service = LightWalletServiceFactory(endpoint: endpoint, connectionStateChange: { _, _ in }).make()
|
||||
|
||||
let latestHeight = try service.latestBlockHeight()
|
||||
|
||||
let startHeight = latestHeight - 100_000
|
||||
|
@ -59,13 +60,14 @@ class BlockStreamingTest: XCTestCase {
|
|||
}
|
||||
|
||||
func testStreamCancellation() async throws {
|
||||
let service = LightWalletGRPCService(
|
||||
host: LightWalletEndpointBuilder.eccTestnet.host,
|
||||
let endpoint = LightWalletEndpoint(
|
||||
address: LightWalletEndpointBuilder.eccTestnet.host,
|
||||
port: 9067,
|
||||
secure: true,
|
||||
singleCallTimeout: 10000,
|
||||
streamingCallTimeout: 10000
|
||||
singleCallTimeoutInMillis: 10000,
|
||||
streamingCallTimeoutInMillis: 10000
|
||||
)
|
||||
let service = LightWalletServiceFactory(endpoint: endpoint, connectionStateChange: { _, _ in }).make()
|
||||
|
||||
let realRustBackend = ZcashRustBackend.self
|
||||
|
||||
|
@ -118,13 +120,14 @@ class BlockStreamingTest: XCTestCase {
|
|||
}
|
||||
|
||||
func testStreamTimeout() async throws {
|
||||
let service = LightWalletGRPCService(
|
||||
host: LightWalletEndpointBuilder.eccTestnet.host,
|
||||
let endpoint = LightWalletEndpoint(
|
||||
address: LightWalletEndpointBuilder.eccTestnet.host,
|
||||
port: 9067,
|
||||
secure: true,
|
||||
singleCallTimeout: 1000,
|
||||
streamingCallTimeout: 1000
|
||||
singleCallTimeoutInMillis: 1000,
|
||||
streamingCallTimeoutInMillis: 1000
|
||||
)
|
||||
let service = LightWalletServiceFactory(endpoint: endpoint, connectionStateChange: { _, _ in }).make()
|
||||
|
||||
let realRustBackend = ZcashRustBackend.self
|
||||
|
||||
|
|
|
@ -34,9 +34,10 @@ class CompactBlockProcessorTests: XCTestCase {
|
|||
try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false)
|
||||
logger = OSLogger(logLevel: .debug)
|
||||
|
||||
let liveService = LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.eccTestnet, connectionStateChange: { _, _ in }).make()
|
||||
let service = MockLightWalletService(
|
||||
latestBlockHeight: mockLatestHeight,
|
||||
service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet)
|
||||
service: liveService
|
||||
)
|
||||
let branchID = try ZcashRustBackend.consensusBranchIdFor(height: Int32(mockLatestHeight), networkType: network.networkType)
|
||||
service.mockLightDInfo = LightdInfo.with({ info in
|
||||
|
|
|
@ -37,10 +37,12 @@ class CompactBlockReorgTests: XCTestCase {
|
|||
try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false)
|
||||
logger = OSLogger(logLevel: .debug)
|
||||
|
||||
let liveService = LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.eccTestnet, connectionStateChange: { _, _ in }).make()
|
||||
let service = MockLightWalletService(
|
||||
latestBlockHeight: mockLatestHeight,
|
||||
service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet)
|
||||
service: liveService
|
||||
)
|
||||
|
||||
let branchID = try ZcashRustBackend.consensusBranchIdFor(height: Int32(mockLatestHeight), networkType: network.networkType)
|
||||
service.mockLightDInfo = LightdInfo.with { info in
|
||||
info.blockHeight = UInt64(mockLatestHeight)
|
||||
|
|
|
@ -33,7 +33,7 @@ class DownloadTests: XCTestCase {
|
|||
}
|
||||
|
||||
func testSingleDownload() async throws {
|
||||
let service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet)
|
||||
let service = LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.eccTestnet, connectionStateChange: { _, _ in }).make()
|
||||
|
||||
let realRustBackend = ZcashRustBackend.self
|
||||
|
||||
|
|
|
@ -16,13 +16,11 @@ class LightWalletServiceTests: XCTestCase {
|
|||
let network: ZcashNetwork = ZcashNetworkBuilder.network(for: .testnet)
|
||||
|
||||
var service: LightWalletService!
|
||||
var channel: Channel!
|
||||
|
||||
override func setUp() {
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
super.setUp()
|
||||
channel = ChannelProvider().channel()
|
||||
service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet)
|
||||
service = LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.eccTestnet, connectionStateChange: { _, _ in }).make()
|
||||
}
|
||||
|
||||
// FIXME: [#721] check whether this test is still valid on in memory lwd implementation, https://github.com/zcash/ZcashLightClientKit/issues/721
|
||||
|
|
|
@ -32,7 +32,7 @@ class BlockBatchValidationTests: XCTestCase {
|
|||
let network = ZcashNetworkBuilder.network(for: .mainnet)
|
||||
let service = MockLightWalletService(
|
||||
latestBlockHeight: 1210000,
|
||||
service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
|
||||
service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default, connectionStateChange: { _, _ in }).make()
|
||||
)
|
||||
|
||||
let realRustBackend = ZcashRustBackend.self
|
||||
|
@ -101,7 +101,7 @@ class BlockBatchValidationTests: XCTestCase {
|
|||
let network = ZcashNetworkBuilder.network(for: .mainnet)
|
||||
let service = MockLightWalletService(
|
||||
latestBlockHeight: 1210000,
|
||||
service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
|
||||
service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default, connectionStateChange: { _, _ in }).make()
|
||||
)
|
||||
|
||||
let realRustBackend = ZcashRustBackend.self
|
||||
|
@ -170,7 +170,7 @@ class BlockBatchValidationTests: XCTestCase {
|
|||
let network = ZcashNetworkBuilder.network(for: .testnet)
|
||||
let service = MockLightWalletService(
|
||||
latestBlockHeight: 1210000,
|
||||
service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
|
||||
service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default, connectionStateChange: { _, _ in }).make()
|
||||
)
|
||||
|
||||
let realRustBackend = ZcashRustBackend.self
|
||||
|
@ -239,7 +239,7 @@ class BlockBatchValidationTests: XCTestCase {
|
|||
let network = ZcashNetworkBuilder.network(for: .mainnet)
|
||||
let service = MockLightWalletService(
|
||||
latestBlockHeight: 1210000,
|
||||
service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
|
||||
service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default, connectionStateChange: { _, _ in }).make()
|
||||
)
|
||||
|
||||
let realRustBackend = ZcashRustBackend.self
|
||||
|
@ -314,7 +314,7 @@ class BlockBatchValidationTests: XCTestCase {
|
|||
let expectedLatestHeight = BlockHeight(1210000)
|
||||
let service = MockLightWalletService(
|
||||
latestBlockHeight: expectedLatestHeight,
|
||||
service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
|
||||
service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default, connectionStateChange: { _, _ in }).make()
|
||||
)
|
||||
let expectedStoredLatestHeight = BlockHeight(1220000)
|
||||
let expectedResult = CompactBlockProcessor.NextState.wait(
|
||||
|
@ -398,7 +398,7 @@ class BlockBatchValidationTests: XCTestCase {
|
|||
let expectedLatestHeight = BlockHeight(1230000)
|
||||
let service = MockLightWalletService(
|
||||
latestBlockHeight: expectedLatestHeight,
|
||||
service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
|
||||
service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default, connectionStateChange: { _, _ in }).make()
|
||||
)
|
||||
let expectedStoreLatestHeight = BlockHeight(1220000)
|
||||
let walletBirthday = BlockHeight(1210000)
|
||||
|
@ -487,7 +487,7 @@ class BlockBatchValidationTests: XCTestCase {
|
|||
let expectedLatestHeight = BlockHeight(1230000)
|
||||
let service = MockLightWalletService(
|
||||
latestBlockHeight: expectedLatestHeight,
|
||||
service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
|
||||
service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default, connectionStateChange: { _, _ in }).make()
|
||||
)
|
||||
let expectedStoreLatestHeight = BlockHeight(1230000)
|
||||
let walletBirthday = BlockHeight(1210000)
|
||||
|
|
|
@ -37,7 +37,7 @@ class CompactBlockProcessorOfflineTests: XCTestCase {
|
|||
|
||||
let service = MockLightWalletService(
|
||||
latestBlockHeight: 690000,
|
||||
service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet)
|
||||
service: LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.eccTestnet, connectionStateChange: { _, _ in }).make()
|
||||
)
|
||||
|
||||
let storage = FSCompactBlockRepository(
|
||||
|
|
|
@ -54,7 +54,7 @@ class TransactionRepositoryTests: XCTestCase {
|
|||
var transactions: [ZcashTransaction.Overview]!
|
||||
XCTAssertNoThrow(
|
||||
try {
|
||||
transactions = try self.transactionRepository.find(in: BlockRange(startHeight: 663218, endHeight: 663974), limit: 3, kind: .received)
|
||||
transactions = try self.transactionRepository.find(in: 663218...663974, limit: 3, kind: .received)
|
||||
}()
|
||||
)
|
||||
|
||||
|
|
|
@ -39,16 +39,16 @@ enum DarksideDataset: String {
|
|||
|
||||
class DarksideWalletService: LightWalletService {
|
||||
var channel: Channel
|
||||
var service: LightWalletGRPCService
|
||||
var service: LightWalletService
|
||||
var darksideService: DarksideStreamerClient
|
||||
|
||||
init(endpoint: LightWalletEndpoint) {
|
||||
self.channel = ChannelProvider().channel()
|
||||
self.service = LightWalletGRPCService(endpoint: endpoint)
|
||||
self.service = LightWalletServiceFactory(endpoint: endpoint, connectionStateChange: { _, _ in }).make()
|
||||
self.darksideService = DarksideStreamerClient(channel: channel)
|
||||
}
|
||||
|
||||
init(service: LightWalletGRPCService) {
|
||||
init(service: LightWalletService) {
|
||||
self.channel = ChannelProvider().channel()
|
||||
self.darksideService = DarksideStreamerClient(channel: channel)
|
||||
self.service = service
|
||||
|
|
|
@ -67,7 +67,6 @@ class ZcashConsoleFakeStorage: CompactBlockRepository {
|
|||
}
|
||||
}
|
||||
|
||||
import GRPC
|
||||
struct SandblastSimulator {
|
||||
/// Creates an array of Zcash CompactBlock from a mainnet sandblasted block of 500K bytes
|
||||
/// this is not good for syncing but for performance benchmarking of block storage.
|
||||
|
|
|
@ -185,7 +185,7 @@ extension MockTransactionRepository: TransactionRepository {
|
|||
throw MockTransactionRepositoryError.notImplemented
|
||||
}
|
||||
|
||||
func find(in range: BlockRange, limit: Int, kind: TransactionKind) throws -> [ZcashTransaction.Overview] {
|
||||
func find(in range: CompactBlockRange, limit: Int, kind: TransactionKind) throws -> [ZcashTransaction.Overview] {
|
||||
throw MockTransactionRepositoryError.notImplemented
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import GRPC
|
|||
import SwiftProtobuf
|
||||
@testable import ZcashLightClientKit
|
||||
|
||||
// swiftlint:disable function_parameter_count identifier_name type_body_length
|
||||
// swiftlint:disable function_parameter_count identifier_name
|
||||
class AwfulLightWalletService: MockLightWalletService {
|
||||
override func latestBlockHeight() throws -> BlockHeight {
|
||||
throw LightWalletServiceError.criticalError
|
||||
|
|
|
@ -39,7 +39,6 @@ class TestCoordinator {
|
|||
var errorHandler: ((Error?) -> Void)?
|
||||
var spendingKey: UnifiedSpendingKey
|
||||
var birthday: BlockHeight
|
||||
var channelProvider: ChannelProvider
|
||||
var synchronizer: SDKSynchronizer
|
||||
var service: DarksideWalletService
|
||||
var spendingKeys: [UnifiedSpendingKey]?
|
||||
|
@ -48,7 +47,6 @@ class TestCoordinator {
|
|||
convenience init(
|
||||
seed: String,
|
||||
walletBirthday: BlockHeight,
|
||||
channelProvider: ChannelProvider,
|
||||
network: ZcashNetwork
|
||||
) throws {
|
||||
let derivationTool = DerivationTool(networkType: network.networkType)
|
||||
|
@ -64,7 +62,6 @@ class TestCoordinator {
|
|||
spendingKey: spendingKey,
|
||||
unifiedFullViewingKey: ufvk,
|
||||
walletBirthday: walletBirthday,
|
||||
channelProvider: channelProvider,
|
||||
network: network
|
||||
)
|
||||
}
|
||||
|
@ -73,25 +70,24 @@ class TestCoordinator {
|
|||
spendingKey: UnifiedSpendingKey,
|
||||
unifiedFullViewingKey: UnifiedFullViewingKey,
|
||||
walletBirthday: BlockHeight,
|
||||
channelProvider: ChannelProvider,
|
||||
network: ZcashNetwork
|
||||
) throws {
|
||||
XCTestCase.wait { await InternalSyncProgress(storage: UserDefaults.standard).rewind(to: 0) }
|
||||
|
||||
self.spendingKey = spendingKey
|
||||
self.birthday = walletBirthday
|
||||
self.channelProvider = channelProvider
|
||||
self.databases = TemporaryDbBuilder.build()
|
||||
self.network = network
|
||||
self.service = DarksideWalletService(
|
||||
service: LightWalletGRPCService(
|
||||
host: Constants.address,
|
||||
port: 9067,
|
||||
secure: false,
|
||||
singleCallTimeout: 10000,
|
||||
streamingCallTimeout: 1000000
|
||||
)
|
||||
|
||||
let endpoint = LightWalletEndpoint(
|
||||
address: Constants.address,
|
||||
port: 9067,
|
||||
secure: false,
|
||||
singleCallTimeoutInMillis: 10000,
|
||||
streamingCallTimeoutInMillis: 1000000
|
||||
)
|
||||
let liveService = LightWalletServiceFactory(endpoint: endpoint, connectionStateChange: { _, _ in }).make()
|
||||
self.service = DarksideWalletService(service: liveService)
|
||||
|
||||
let realRustBackend = ZcashRustBackend.self
|
||||
|
||||
|
|
Loading…
Reference in New Issue