[#492] Get rid of blocking API (#551)

- blocking API removed, only latestBlockHeight() stayed
- non-blocking closure based API removed
- unit tests updated to use async API

[#492] Get rid of blocking API (#551)

- forgotten commented code cleaned up
- some comments were still mentioning result (completion closure), removed
This commit is contained in:
Lukas Korba 2022-10-04 01:05:11 +02:00 committed by GitHub
parent fa5bbbb2bf
commit 9b6ff51b29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 141 additions and 879 deletions

View File

@ -91,12 +91,8 @@ extension CompactBlockStorage: CompactBlockRepository {
}
return try await task.value
}
func write(blocks: [ZcashCompactBlock]) throws {
try insert(blocks)
}
func writeAsync(blocks: [ZcashCompactBlock]) async throws {
func write(blocks: [ZcashCompactBlock]) async throws {
let task = Task(priority: .userInitiated) {
try insert(blocks)
}

View File

@ -16,18 +16,11 @@ enum CompactBlockDownloadError: Error {
Represents what a compact block downloaded should provide to its clients
*/
public protocol CompactBlockDownloading {
/**
Downloads and stores the given block range.
Blocking
*/
func downloadBlockRange(_ range: CompactBlockRange) throws
/**
Downloads and stores the given block range.
Non-Blocking
*/
func downloadBlockRangeAsync(_ heightRange: CompactBlockRange) async throws
func downloadBlockRange(_ heightRange: CompactBlockRange) async throws
/**
Restore the download progress up to the given height.
@ -69,36 +62,10 @@ public protocol CompactBlockDownloading {
/**
Gets the transaction for the Id given
- Parameter txId: Data representing the transaction Id
- Returns: a transaction entity with the requested transaction
- Throws: An error if the fetch failed
*/
func fetchTransaction(txId: Data) throws -> TransactionEntity
/**
Gets the transaction for the Id given
- Parameter txId: Data representing the transaction Id
*/
func fetchTransactionAsync(txId: Data) async throws -> TransactionEntity
func fetchUnspentTransactionOutputs(tAddress: String, startHeight: BlockHeight) throws -> [UnspentTransactionOutputEntity]
// TODO: will be removed with the issue 474
// https://github.com/zcash/ZcashLightClientKit/issues/474
// Use the new API fetchUnspentTransactionOutputs(...) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
func fetchUnspentTransactionOutputs(tAddress: String, startHeight: BlockHeight, result: @escaping (Result<[UnspentTransactionOutputEntity], Error>) -> Void)
func fetchTransaction(txId: Data) async throws -> TransactionEntity
func fetchUnspentTransactionOutputs(tAddress: String, startHeight: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
func fetchUnspentTransactionOutputs(tAddresses: [String], startHeight: BlockHeight) throws -> [UnspentTransactionOutputEntity]
// TODO: will be removed with the issue 474
// https://github.com/zcash/ZcashLightClientKit/issues/474
// Use the new API fetchUnspentTransactionOutputs(...) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
func fetchUnspentTransactionOutputs(
tAddresses: [String],
startHeight: BlockHeight,
result: @escaping (Result<[UnspentTransactionOutputEntity], Error>) -> Void
)
func fetchUnspentTransactionOutputs(tAddresses: [String], startHeight: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
@ -127,45 +94,11 @@ extension CompactBlockDownloader: CompactBlockDownloading {
func closeConnection() {
lightwalletService.closeConnection()
}
func fetchUnspentTransactionOutputs(tAddresses: [String], startHeight: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
try lightwalletService.fetchUTXOs(for: tAddresses, height: startHeight)
}
func fetchUnspentTransactionOutputs(
tAddresses: [String],
startHeight: BlockHeight,
result: @escaping (Result<[UnspentTransactionOutputEntity], Error>) -> Void
) {
lightwalletService.fetchUTXOs(for: tAddresses, height: startHeight) { fetchResult in
switch fetchResult {
case .success(let utxos):
result(.success(utxos))
case .failure(let error):
result(.failure(error))
}
}
}
func fetchUnspentTransactionOutputs(tAddresses: [String], startHeight: BlockHeight ) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
lightwalletService.fetchUTXOs(for: tAddresses, height: startHeight)
}
func fetchUnspentTransactionOutputs(tAddress: String, startHeight: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
try lightwalletService.fetchUTXOs(for: tAddress, height: startHeight)
}
func fetchUnspentTransactionOutputs(tAddress: String, startHeight: BlockHeight, result: @escaping (Result<[UnspentTransactionOutputEntity], Error>) -> Void) {
lightwalletService.fetchUTXOs(for: tAddress, height: startHeight) { fetchResult in
switch fetchResult {
case .success(let utxos):
result(.success(utxos))
case .failure(let error):
result(.failure(error))
}
}
}
func fetchUnspentTransactionOutputs(tAddress: String, startHeight: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
lightwalletService.fetchUTXOs(for: tAddress, height: startHeight)
}
@ -177,20 +110,15 @@ extension CompactBlockDownloader: CompactBlockDownloading {
func latestBlockHeight() throws -> BlockHeight {
try lightwalletService.latestBlockHeight()
}
func downloadBlockRange(_ range: CompactBlockRange) throws {
let blocks = try lightwalletService.blockRange(range)
try storage.write(blocks: blocks)
}
func downloadBlockRangeAsync( _ heightRange: CompactBlockRange) async throws {
func downloadBlockRange( _ heightRange: CompactBlockRange) async throws {
let stream: AsyncThrowingStream<ZcashCompactBlock, Error> = lightwalletService.blockRange(heightRange)
do {
var compactBlocks: [ZcashCompactBlock] = []
for try await compactBlock in stream {
compactBlocks.append(compactBlock)
}
try await self.storage.writeAsync(blocks: compactBlocks)
try await self.storage.write(blocks: compactBlocks)
} catch {
throw error
}
@ -213,7 +141,6 @@ extension CompactBlockDownloader: CompactBlockDownloading {
}
}
func rewind(to height: BlockHeight) throws {
try self.storage.rewind(to: height)
}
@ -222,11 +149,7 @@ extension CompactBlockDownloader: CompactBlockDownloading {
try self.storage.latestHeight()
}
func fetchTransaction(txId: Data) throws -> TransactionEntity {
try lightwalletService.fetchTransaction(txId: txId)
}
func fetchTransactionAsync(txId: Data) async throws -> TransactionEntity {
try await lightwalletService.fetchTransactionAsync(txId: txId)
func fetchTransaction(txId: Data) async throws -> TransactionEntity {
try await lightwalletService.fetchTransaction(txId: txId)
}
}

View File

@ -42,8 +42,7 @@ extension CompactBlockProcessor {
try Task.checkCancellation()
buffer.append(zcashCompactBlock)
if buffer.count >= blockBufferSize {
// TODO: writeAsync doesn't make sense here, awaiting it or calling blocking API have the same result and impact
try storage.write(blocks: buffer)
try await storage.write(blocks: buffer)
buffer.removeAll(keepingCapacity: true)
}
@ -54,8 +53,7 @@ extension CompactBlockProcessor {
)
notifyProgress(.download(progress))
}
// TODO: writeAsync doesn't make sense here, awaiting it or calling blocking API have the same result and impact
try storage.write(blocks: buffer)
try await storage.write(blocks: buffer)
buffer.removeAll(keepingCapacity: true)
} catch {
guard let err = error as? LightWalletServiceError, case .userCancelled = err else {
@ -73,7 +71,7 @@ extension CompactBlockProcessor {
try Task.checkCancellation()
do {
try await downloader.downloadBlockRangeAsync(range)
try await downloader.downloadBlockRange(range)
} catch {
throw error
}

View File

@ -18,7 +18,7 @@ extension CompactBlockProcessor {
private func enhance(transaction: TransactionEntity) async throws -> ConfirmedTransactionEntity {
LoggerProxy.debug("Zoom.... Enhance... Tx: \(transaction.transactionId.toHexStringTxId())")
let transaction = try await downloader.fetchTransactionAsync(txId: transaction.transactionId)
let transaction = try await downloader.fetchTransaction(txId: transaction.transactionId)
let transactionID = transaction.transactionId.toHexStringTxId()
let block = String(describing: transaction.minedHeight)

View File

@ -598,31 +598,23 @@ public class CompactBlockProcessor {
}
func validateServer(completionBlock: @escaping (() -> Void)) {
self.service.getInfo(result: { [weak self] result in
guard let self = self else { return }
switch result {
case .success(let info):
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
do {
try Self.validateServerInfo(
info,
saplingActivation: self.config.saplingActivation,
localNetwork: self.config.network,
rustBackend: self.rustBackend
)
completionBlock()
} catch {
self.severeFailure(error)
}
}
case .failure(let error):
Task { @MainActor in
do {
let info = try await self.service.getInfo()
try Self.validateServerInfo(
info,
saplingActivation: self.config.saplingActivation,
localNetwork: self.config.network,
rustBackend: self.rustBackend
)
completionBlock()
} catch let error as LightWalletServiceError {
self.severeFailure(error.mapToProcessorError())
} catch {
self.severeFailure(error)
}
})
}
}
/// Processes new blocks on the given range based on the configuration set for this instance
func processNewBlocks(range: CompactBlockRange) {
@ -1182,51 +1174,39 @@ extension CompactBlockProcessor {
rustBackend: ZcashRustBackendWelding.Type
) async throws -> NextState {
let task = Task(priority: .userInitiated) {
// TODO: refactor to async call, issue 463, PR 493
// https://github.com/zcash/ZcashLightClientKit/issues/463
try nextState(
service: service,
downloader: downloader,
config: config,
rustBackend: rustBackend
)
do {
let info = try await service.getInfo()
try CompactBlockProcessor.validateServerInfo(
info,
saplingActivation: config.saplingActivation,
localNetwork: config.network,
rustBackend: rustBackend
)
// get latest block height
let latestDownloadedBlockHeight: BlockHeight = max(config.walletBirthday, try downloader.lastDownloadedBlockHeight())
let latestBlockheight = try service.latestBlockHeight()
if latestDownloadedBlockHeight < latestBlockheight {
return NextState.processNewBlocks(
range: CompactBlockProcessor.nextBatchBlockRange(
latestHeight: latestBlockheight,
latestDownloadedHeight: latestDownloadedBlockHeight,
walletBirthday: config.walletBirthday
)
)
} else if latestBlockheight == latestDownloadedBlockHeight {
return .finishProcessing(height: latestBlockheight)
}
return .wait(latestHeight: latestBlockheight, latestDownloadHeight: latestBlockheight)
} catch {
throw error
}
}
return try await task.value
}
static func nextState(
service: LightWalletService,
downloader: CompactBlockDownloading,
config: Configuration,
rustBackend: ZcashRustBackendWelding.Type
) throws -> NextState {
let info = try service.getInfo()
try CompactBlockProcessor.validateServerInfo(
info,
saplingActivation: config.saplingActivation,
localNetwork: config.network,
rustBackend: rustBackend
)
// get latest block height
let latestDownloadedBlockHeight: BlockHeight = max(config.walletBirthday, try downloader.lastDownloadedBlockHeight())
let latestBlockheight = try service.latestBlockHeight()
if latestDownloadedBlockHeight < latestBlockheight {
return .processNewBlocks(
range: CompactBlockProcessor.nextBatchBlockRange(
latestHeight: latestBlockheight,
latestDownloadedHeight: latestDownloadedBlockHeight,
walletBirthday: config.walletBirthday
)
)
} else if latestBlockheight == latestDownloadedBlockHeight {
return .finishProcessing(height: latestBlockheight)
}
return .wait(latestHeight: latestBlockheight, latestDownloadHeight: latestBlockheight)
}
}
}

View File

@ -31,21 +31,14 @@ protocol CompactBlockRepository {
*/
func latestHeightAsync() async throws -> BlockHeight
/**
Write the given blocks to this store, which may be anything from an in-memory cache to a DB.
Blocking
- Parameter blocks: the compact blocks that will be written to storage
- Throws: an error when there's a failure
*/
func write(blocks: [ZcashCompactBlock]) throws
/**
Write the given blocks to this store, which may be anything from an in-memory cache to a DB.
Non-Blocking
- Parameters:
- Parameter blocks: array of blocks to be written to storage
- Throws: an error when there's a failure
*/
func writeAsync(blocks: [ZcashCompactBlock]) async throws
func write(blocks: [ZcashCompactBlock]) async throws
/**
Remove every block above and including the given height.

View File

@ -189,11 +189,11 @@ public class LightWalletGRPCService {
}
}
// MARK: - LightWalletServiceBlockingAPI
// MARK: - LightWalletService
extension LightWalletGRPCService: LightWalletServiceBlockingAPI {
public func getInfo() throws -> LightWalletdInfo {
try compactTxStreamer.getLightdInfo(Empty()).response.wait()
extension LightWalletGRPCService: LightWalletService {
public func getInfo() async throws -> LightWalletdInfo {
try await compactTxStreamerAsync.getLightdInfo(Empty())
}
public func latestBlockHeight() throws -> BlockHeight {
@ -202,161 +202,13 @@ extension LightWalletGRPCService: LightWalletServiceBlockingAPI {
}
return height
}
public func blockRange(_ range: CompactBlockRange) throws -> [ZcashCompactBlock] {
var blocks: [CompactBlock] = []
let response = compactTxStreamer.getBlockRange(
range.blockRange(),
handler: { blocks.append($0) }
)
let status = try response.status.wait()
switch status.code {
case .ok:
return blocks.asZcashCompactBlocks()
default:
throw LightWalletServiceError.mapCode(status)
}
}
public func submit(spendTransaction: Data) throws -> LightWalletServiceResponse {
let rawTx = RawTransaction.with { raw in
raw.data = spendTransaction
}
do {
return try compactTxStreamer.sendTransaction(rawTx).response.wait()
} catch {
throw error.mapToServiceError()
}
}
public func fetchTransaction(txId: Data) throws -> TransactionEntity {
var txFilter = TxFilter()
txFilter.hash = txId
do {
let rawTx = try compactTxStreamer.getTransaction(txFilter).response.wait()
return TransactionBuilder.createTransactionEntity(txId: txId, rawTransaction: rawTx)
} catch {
throw error.mapToServiceError()
}
}
public func fetchUTXOs(for tAddress: String, height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
let arg = GetAddressUtxosArg.with { utxoArgs in
utxoArgs.addresses = [tAddress]
utxoArgs.startHeight = UInt64(height)
}
do {
return try self.compactTxStreamer.getAddressUtxos(arg).response.wait().addressUtxos.map { reply in
UTXO(
id: nil,
address: tAddress,
prevoutTxId: reply.txid,
prevoutIndex: Int(reply.index),
script: reply.script,
valueZat: Int(reply.valueZat),
height: Int(reply.height),
spentInTx: nil
)
}
} catch {
throw error.mapToServiceError()
}
}
public func fetchUTXOs(for tAddresses: [String], height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
guard !tAddresses.isEmpty else {
return [] // FIXME: throw a real error
}
var utxos: [UnspentTransactionOutputEntity] = []
let arg = GetAddressUtxosArg.with { utxoArgs in
utxoArgs.addresses = tAddresses
utxoArgs.startHeight = UInt64(height)
}
utxos.append(
contentsOf:
try self.compactTxStreamer.getAddressUtxos(arg).response.wait().addressUtxos.map { reply in
UTXO(
id: nil,
address: reply.address,
prevoutTxId: reply.txid,
prevoutIndex: Int(reply.index),
script: reply.script,
valueZat: Int(reply.valueZat),
height: Int(reply.height),
spentInTx: nil
)
}
)
return utxos
}
}
// MARK: - LightWalletServiceNonBlockingAPI
extension LightWalletGRPCService: LightWalletServiceNonBlockingAPI {
public func getInfo(result: @escaping (Result<LightWalletdInfo, LightWalletServiceError>) -> Void) {
compactTxStreamer.getLightdInfo(Empty()).response.whenComplete { completionResult in
switch completionResult {
case .success(let info):
result(.success(info))
case .failure(let error):
result(.failure(error.mapToServiceError()))
}
}
}
public func getInfoAsync() async throws -> LightWalletdInfo {
try await compactTxStreamerAsync.getLightdInfo(Empty())
}
public func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void) {
let response = compactTxStreamer.getLatestBlock(ChainSpec()).response
response.whenSuccessBlocking(onto: queue) { blockID in
guard let blockHeight = Int(exactly: blockID.height) else {
result(.failure(LightWalletServiceError.generalError(message: "error creating blockheight from BlockID \(blockID)")))
return
}
result(.success(blockHeight))
}
response.whenFailureBlocking(onto: queue) { error in
result(.failure(error.mapToServiceError()))
}
}
public func latestBlockHeightAsync() async throws -> BlockHeight {
try await BlockHeight(compactTxStreamerAsync.getLatestBlock(ChainSpec()).height)
}
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] = []
let response = self.compactTxStreamer.getBlockRange(range.blockRange(), handler: { blocks.append($0) })
do {
let status = try response.status.wait()
switch status.code {
case .ok:
result(.success(blocks.asZcashCompactBlocks()))
default:
result(.failure(.mapCode(status)))
}
} catch {
result(.failure(error.mapToServiceError()))
}
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
}
public func blockRange(_ range: CompactBlockRange) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
@ -376,48 +228,16 @@ extension LightWalletGRPCService: LightWalletServiceNonBlockingAPI {
}
}
public func submit(spendTransaction: Data, result: @escaping (Result<LightWalletServiceResponse, LightWalletServiceError>) -> Void) {
public func submit(spendTransaction: Data) async throws -> LightWalletServiceResponse {
do {
let transaction = try RawTransaction(serializedData: spendTransaction)
let response = self.compactTxStreamer.sendTransaction(transaction).response
response.whenComplete { responseResult in
switch responseResult {
case .failure(let error):
result(.failure(LightWalletServiceError.sentFailed(error: error)))
case .success(let success):
result(.success(success))
}
}
} catch {
result(.failure(error.mapToServiceError()))
}
}
public func submitAsync(spendTransaction: Data) async throws -> LightWalletServiceResponse {
do {
let transaction = try RawTransaction(serializedData: spendTransaction)
let transaction = RawTransaction.with { $0.data = spendTransaction }
return try await compactTxStreamerAsync.sendTransaction(transaction)
} catch {
throw LightWalletServiceError.sentFailed(error: error)
}
}
public func fetchTransaction(txId: Data, result: @escaping (Result<TransactionEntity, LightWalletServiceError>) -> Void) {
var txFilter = TxFilter()
txFilter.hash = txId
compactTxStreamer.getTransaction(txFilter).response.whenComplete { response in
switch response {
case .failure(let error):
result(.failure(error.mapToServiceError()))
case .success(let rawTx):
result(.success(TransactionBuilder.createTransactionEntity(txId: txId, rawTransaction: rawTx)))
}
}
}
public func fetchTransactionAsync(txId: Data) async throws -> TransactionEntity {
public func fetchTransaction(txId: Data) async throws -> TransactionEntity {
var txFilter = TxFilter()
txFilter.hash = txId
@ -473,52 +293,6 @@ extension LightWalletGRPCService: LightWalletServiceNonBlockingAPI {
return fetchUTXOs(for: [tAddress], height: height)
}
public func fetchUTXOs(
for tAddresses: [String],
height: BlockHeight,
result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
) {
guard !tAddresses.isEmpty else {
return result(.success([])) // FIXME: throw a real error
}
var utxos: [UnspentTransactionOutputEntity] = []
self.queue.async { [weak self] in
guard let self = self else { return }
let args = GetAddressUtxosArg.with { utxoArgs in
utxoArgs.addresses = tAddresses
utxoArgs.startHeight = UInt64(height)
}
do {
let response = try self.compactTxStreamer.getAddressUtxosStream(args) { reply in
utxos.append(
UTXO(
id: nil,
address: reply.address,
prevoutTxId: reply.txid,
prevoutIndex: Int(reply.index),
script: reply.script,
valueZat: Int(reply.valueZat),
height: Int(reply.height),
spentInTx: nil
)
)
}
.status
.wait()
switch response.code {
case .ok:
result(.success(utxos))
default:
result(.failure(.mapCode(response)))
}
} catch {
result(.failure(error.mapToServiceError()))
}
}
}
public func fetchUTXOs(
for tAddresses: [String],
height: BlockHeight
@ -558,48 +332,6 @@ extension LightWalletGRPCService: LightWalletServiceNonBlockingAPI {
}
}
@discardableResult
public func blockStream(
startHeight: BlockHeight,
endHeight: BlockHeight,
result: @escaping (Result<GRPCResult, LightWalletServiceError>) -> Void,
handler: @escaping (ZcashCompactBlock) -> Void,
progress: @escaping (BlockProgress) -> Void
) -> CancellableCall {
let future = compactTxStreamer.getBlockRange(
BlockRange(
startHeight: startHeight,
endHeight: endHeight
),
callOptions: Self.callOptions(timeLimit: self.streamingCallTimeout),
handler: { compactBlock in
handler(ZcashCompactBlock(compactBlock: compactBlock))
progress(
BlockProgress(
startHeight: startHeight,
targetHeight: endHeight,
progressHeight: BlockHeight(compactBlock.height)
)
)
}
)
future.status.whenComplete { completionResult in
switch completionResult {
case .success(let status):
switch status.code {
case .ok:
result(.success(GRPCResult.success))
default:
result(.failure(LightWalletServiceError.mapCode(status)))
}
case .failure(let error):
result(.failure(LightWalletServiceError.genericError(error: error)))
}
}
return future
}
public func blockStream(
startHeight: BlockHeight,
endHeight: BlockHeight
@ -625,9 +357,7 @@ extension LightWalletGRPCService: LightWalletServiceNonBlockingAPI {
}
}
}
}
extension LightWalletGRPCService: LightWalletService {
public func closeConnection() {
_ = channel.close()
}

View File

@ -101,117 +101,40 @@ public protocol LightWalletServiceResponse {
extension SendResponse: LightWalletServiceResponse {}
/// Blocking API - used for the testing purposes
public protocol LightWalletServiceBlockingAPI {
/// Returns the info for this lightwalletd server (blocking)
func getInfo() throws -> LightWalletdInfo
public protocol LightWalletService {
/// Returns the info for this lightwalletd server
func getInfo() async throws -> LightWalletdInfo
///
/// Return the latest block height known to the service.
/// - Parameter result: a result containing the height or an Error
/// Blocking API
func latestBlockHeight() throws -> BlockHeight
/// Return the given range of blocks.
///
/// - Parameter range: the inclusive range to fetch.
/// For instance if 1..5 is given, then every block in that will be fetched, including 1 and 5.
func blockRange(_ range: CompactBlockRange) throws -> [ZcashCompactBlock]
/// Submits a raw transaction over lightwalletd. Blocking
/// - Parameter spendTransaction: data representing the transaction to be sent
/// - Throws: LightWalletServiceError
/// - Returns: LightWalletServiceResponse
func submit(spendTransaction: Data) throws -> LightWalletServiceResponse
/// Gets a transaction by id
/// - Parameter txId: data representing the transaction ID
/// - Throws: LightWalletServiceError
/// - Returns: LightWalletServiceResponse
func fetchTransaction(txId: Data) throws -> TransactionEntity
func fetchUTXOs(
for tAddress: String,
height: BlockHeight
) throws -> [UnspentTransactionOutputEntity]
func fetchUTXOs(
for tAddresses: [String],
height: BlockHeight
) throws -> [UnspentTransactionOutputEntity]
}
public protocol LightWalletServiceNonBlockingAPI {
/// Returns the info for this lightwalletd server
@available(*, deprecated, message: "This function will be removed soon. Use the `getInfoAsync()` instead.")
func getInfo(result: @escaping (Result<LightWalletdInfo, LightWalletServiceError>) -> Void)
func getInfoAsync() async throws -> LightWalletdInfo
///
/// Return the latest block height known to the service.
/// - Parameter result: a result containing the height or an Error
@available(*, deprecated, message: "This function will be removed soon. Use the `latestBlockHeightAsync()` instead.")
func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void)
func latestBlockHeightAsync() async throws -> BlockHeight
/// Return the given range of blocks.
/// - Parameter range: the inclusive range to fetch.
/// For instance if 1..5 is given, then every block in that will be fetched, including 1 and 5.
@available(*, deprecated, message: "This function will be removed soon. Use the `blockRange(...) -> AsyncThrowingStream<ZcashCompactBlock, Error>` instead.")
func blockRange(_ range: CompactBlockRange, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void)
func blockRange(_ range: CompactBlockRange) -> AsyncThrowingStream<ZcashCompactBlock, Error>
/// Submits a raw transaction over lightwalletd. Non-Blocking
/// - Parameter spendTransaction: data representing the transaction to be sent
/// - Parameter result: escaping closure that takes a result containing either LightWalletServiceResponse or LightWalletServiceError
@available(*, deprecated, message: "This function will be removed soon. Use the `submitAsync(spendTransaction: Data)` instead.")
func submit(spendTransaction: Data, result: @escaping(Result<LightWalletServiceResponse, LightWalletServiceError>) -> Void)
func submitAsync(spendTransaction: Data) async throws -> LightWalletServiceResponse
func submit(spendTransaction: Data) async throws -> LightWalletServiceResponse
/// Gets a transaction by id
/// - Parameter txId: data representing the transaction ID
/// - Parameter result: handler for the result
/// - Throws: LightWalletServiceError
/// - Returns: LightWalletServiceResponse
@available(*, deprecated, message: "This function will be removed soon. Use the `fetchTransactionAsync(txId: Data)` instead.")
func fetchTransaction(
txId: Data,
result: @escaping (Result<TransactionEntity, LightWalletServiceError>) -> Void
)
func fetchTransactionAsync(txId: Data) async throws -> TransactionEntity
func fetchTransaction(txId: Data) async throws -> TransactionEntity
@available(*, deprecated, message: "This function will be removed soon. Use the `fetchUTXOs(for tAddress:...) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>` instead.")
func fetchUTXOs(
for tAddress: String,
height: BlockHeight,
result: @escaping(Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
)
func fetchUTXOs(for tAddress: String, height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
@available(*, deprecated, message: "This function will be removed soon. Use the `fetchUTXOs(for tAddresses:...) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>` instead.")
func fetchUTXOs(
for tAddresses: [String],
height: BlockHeight,
result: @escaping(Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
)
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
@available(*, deprecated, message: "This function will be removed soon. Use the `blockStream(...) -> AsyncThrowingStream<ZcashCompactBlock, Error>` instead.")
@discardableResult
func blockStream(
startHeight: BlockHeight,
endHeight: BlockHeight,
result: @escaping (Result<GRPCResult, LightWalletServiceError>) -> Void,
handler: @escaping (ZcashCompactBlock) -> Void,
progress: @escaping (BlockProgress) -> Void
) -> CancellableCall
func blockStream(
startHeight: BlockHeight,
endHeight: BlockHeight
) -> AsyncThrowingStream<ZcashCompactBlock, Error>
}
public protocol LightWalletService: LightWalletServiceNonBlockingAPI, LightWalletServiceBlockingAPI {
func closeConnection()
}

View File

@ -585,26 +585,23 @@ public class SDKSynchronizer: Synchronizer {
try blockProcessor.downloader.latestBlockHeight()
}
public func latestUTXOs(address: String, result: @escaping (Result<[UnspentTransactionOutputEntity], Error>) -> Void) {
public func latestUTXOs(address: String) async throws -> [UnspentTransactionOutputEntity] {
guard initializer.isValidTransparentAddress(address) else {
result(.failure(SynchronizerError.generalError(message: "invalid t-address")))
return
throw SynchronizerError.generalError(message: "invalid t-address")
}
initializer.lightWalletService.fetchUTXOs(for: address, height: network.constants.saplingActivationHeight) { [weak self] fetchResult in
guard let self = self else { return }
switch fetchResult {
case .success(let utxos):
do {
try self.utxoRepository.clearAll(address: address)
try self.utxoRepository.store(utxos: utxos)
result(.success(utxos))
} catch {
result(.failure(SynchronizerError.generalError(message: "\(error)")))
}
case .failure(let error):
result(.failure(SynchronizerError.connectionFailed(message: error)))
let stream = initializer.lightWalletService.fetchUTXOs(for: address, height: network.constants.saplingActivationHeight)
do {
var utxos: [UnspentTransactionOutputEntity] = []
for try await transactionEntity in stream {
utxos.append(transactionEntity)
}
try self.utxoRepository.clearAll(address: address)
try self.utxoRepository.store(utxos: utxos)
return utxos
} catch {
throw SynchronizerError.generalError(message: "\(error)")
}
}

View File

@ -179,7 +179,7 @@ class PersistentTransactionManager: OutboundTransactionManager {
throw TransactionManagerError.internalInconsistency(storedTx)
}
let response = try self.service.submit(spendTransaction: raw)
let response = try await self.service.submit(spendTransaction: raw)
let transaction = try self.update(transaction: storedTx, on: response)
guard response.errorCode >= 0 else {

View File

@ -46,7 +46,7 @@ class BlockDownloaderTests: XCTestCase {
let range = CompactBlockRange(uncheckedBounds: (lowerRange, upperRange))
do {
try await downloader.downloadBlockRangeAsync(range)
try await downloader.downloadBlockRange(range)
// check what was 'stored'
let latestHeight = try await self.storage.latestHeightAsync()
@ -59,33 +59,6 @@ class BlockDownloaderTests: XCTestCase {
}
}
func testSmallDownload() {
let lowerRange: BlockHeight = self.network.constants.saplingActivationHeight
let upperRange: BlockHeight = self.network.constants.saplingActivationHeight + 99
let range = CompactBlockRange(uncheckedBounds: (lowerRange, upperRange))
var latest: BlockHeight = 0
do {
latest = try downloader.lastDownloadedBlockHeight()
} catch {
XCTFail(error.localizedDescription)
}
XCTAssertEqual(latest, BlockHeight.empty())
XCTAssertNoThrow(try downloader.downloadBlockRange(range))
var currentLatest: BlockHeight = 0
do {
currentLatest = try downloader.lastDownloadedBlockHeight()
} catch {
XCTFail("latest block failed")
return
}
XCTAssertEqual(currentLatest, upperRange )
}
func testFailure() async {
let awfulDownloader = CompactBlockDownloader(
service: AwfulLightWalletService(
@ -101,7 +74,7 @@ class BlockDownloaderTests: XCTestCase {
let range = CompactBlockRange(uncheckedBounds: (lowerRange, upperRange))
do {
try await awfulDownloader.downloadBlockRangeAsync(range)
try await awfulDownloader.downloadBlockRange(range)
} catch {
XCTAssertNotNil(error)
}

View File

@ -21,9 +21,7 @@ class BlockStreamingTest: XCTestCase {
try? FileManager.default.removeItem(at: __dataDbURL())
}
func testStream() throws {
let expectation = XCTestExpectation(description: "blockstream expectation")
func testStream() async throws {
let service = LightWalletGRPCService(
host: LightWalletEndpointBuilder.eccTestnet.host,
port: 9067,
@ -36,23 +34,19 @@ class BlockStreamingTest: XCTestCase {
let startHeight = latestHeight - 100_000
var blocks: [ZcashCompactBlock] = []
service.blockStream(startHeight: startHeight, endHeight: latestHeight) { result in
expectation.fulfill()
switch result {
case .success(let status):
XCTAssertEqual(GRPCResult.success, status)
case .failure(let error):
XCTFail("failed with error: \(error)")
let stream = service.blockStream(startHeight: startHeight, endHeight: latestHeight)
do {
for try await compactBlock in stream {
print("received block \(compactBlock.height)")
blocks.append(compactBlock)
print("progressHeight: \(compactBlock.height)")
print("startHeight: \(startHeight)")
print("targetHeight: \(latestHeight)")
}
} handler: { compactBlock in
print("received block \(compactBlock.height)")
blocks.append(compactBlock)
} progress: { progressReport in
print("progressHeight: \(progressReport.progressHeight)")
print("startHeight: \(progressReport.startHeight)")
print("targetHeight: \(progressReport.targetHeight)")
} catch {
XCTFail("failed with error: \(error)")
}
wait(for: [expectation], timeout: 1000)
}
func testStreamCancellation() async throws {

View File

@ -38,29 +38,6 @@ class LightWalletServiceTests: XCTestCase {
// wait(for: [expect], timeout: 20)
// }
func testHundredBlocks() {
let expect = XCTestExpectation(description: self.description)
let count = 99
let lowerRange: BlockHeight = network.constants.saplingActivationHeight
let upperRange: BlockHeight = network.constants.saplingActivationHeight + count
let blockRange = lowerRange ... upperRange
service.blockRange(blockRange) { result in
expect.fulfill()
switch result {
case .failure(let error):
XCTFail("failed with error \(error)")
case .success(let blocks):
XCTAssertEqual(blocks.count, blockRange.count)
XCTAssertEqual(blocks[0].height, lowerRange)
XCTAssertEqual(blocks.last!.height, upperRange)
}
}
wait(for: [expect], timeout: 10)
}
func testHundredBlocks() async throws {
let count = 99
let lowerRange: BlockHeight = network.constants.saplingActivationHeight
@ -76,19 +53,6 @@ class LightWalletServiceTests: XCTestCase {
XCTAssertEqual(blocks.last!.height, upperRange)
}
func testSyncBlockRange() {
let lowerRange: BlockHeight = network.constants.saplingActivationHeight
let upperRange: BlockHeight = network.constants.saplingActivationHeight + 99
let blockRange = lowerRange ... upperRange
do {
let blocks = try service.blockRange(blockRange)
XCTAssertEqual(blocks.count, blockRange.count)
} catch {
XCTFail("\(error)")
}
}
func testSyncBlockRange() async throws {
let lowerRange: BlockHeight = network.constants.saplingActivationHeight
let upperRange: BlockHeight = network.constants.saplingActivationHeight + 99
@ -101,21 +65,6 @@ class LightWalletServiceTests: XCTestCase {
XCTAssertEqual(blocks.count, blockRange.count)
}
func testLatestBlock() {
let expect = XCTestExpectation(description: self.description)
service.latestBlockHeight { result in
expect.fulfill()
switch result {
case .failure(let e):
XCTFail("error: \(e)")
case .success(let height):
XCTAssertTrue(height > self.network.constants.saplingActivationHeight)
}
}
wait(for: [expect], timeout: 10)
}
func testLatestBlock() async throws {
let height = try await service.latestBlockHeightAsync()
XCTAssertTrue(height > self.network.constants.saplingActivationHeight)

View File

@ -25,14 +25,14 @@ class CompactBlockStorageTests: XCTestCase {
XCTAssertEqual(latestHeight, BlockHeight.empty())
}
func testStoreThousandBlocks() {
func testStoreThousandBlocks() async {
let initialHeight = try! compactBlockDao.latestHeight()
let startHeight = self.network.constants.saplingActivationHeight
let blockCount = Int(1_000)
let finalHeight = startHeight + blockCount
do {
try TestDbBuilder.seed(db: compactBlockDao, with: startHeight...finalHeight)
try await TestDbBuilder.seed(db: compactBlockDao, with: startHeight...finalHeight)
} catch {
XCTFail("seed faild with error: \(error)")
return
@ -49,14 +49,14 @@ class CompactBlockStorageTests: XCTestCase {
let blockCount = Int(1_000)
let finalHeight = startHeight + blockCount
try TestDbBuilder.seed(db: compactBlockDao, with: startHeight...finalHeight)
try await TestDbBuilder.seed(db: compactBlockDao, with: startHeight...finalHeight)
let latestHeight = try await compactBlockDao.latestHeightAsync()
XCTAssertNotEqual(initialHeight, latestHeight)
XCTAssertEqual(latestHeight, finalHeight)
}
func testStoreOneBlockFromEmpty() {
func testStoreOneBlockFromEmpty() async {
let initialHeight = try! compactBlockDao.latestHeight()
guard initialHeight == BlockHeight.empty() else {
XCTFail("database not empty, latest height: \(initialHeight)")
@ -68,7 +68,11 @@ class CompactBlockStorageTests: XCTestCase {
XCTFail("could not create randem block with height: \(expectedHeight)")
return
}
XCTAssertNoThrow(try compactBlockDao.write(blocks: [block]))
do {
try await compactBlockDao.write(blocks: [block])
} catch {
XCTFail("unexpected testStoreOneBlockFromEmpty fail")
}
do {
let result = try compactBlockDao.latestHeight()
@ -91,27 +95,27 @@ class CompactBlockStorageTests: XCTestCase {
XCTFail("could not create randem block with height: \(expectedHeight)")
return
}
try await compactBlockDao.writeAsync(blocks: [block])
try await compactBlockDao.write(blocks: [block])
let result = try await compactBlockDao.latestHeightAsync()
XCTAssertEqual(result, expectedHeight)
}
func testRewindTo() {
func testRewindTo() async {
let startHeight = self.network.constants.saplingActivationHeight
let blockCount = Int(1_000)
let finalHeight = startHeight + blockCount
do {
try TestDbBuilder.seed(db: compactBlockDao, with: startHeight...finalHeight)
try await TestDbBuilder.seed(db: compactBlockDao, with: startHeight...finalHeight)
} catch {
XCTFail("seed faild with error: \(error)")
return
}
let rewindHeight = BlockHeight(finalHeight - 233)
XCTAssertNoThrow(try compactBlockDao.rewind(to: rewindHeight))
do {
try await compactBlockDao.rewindAsync(to: rewindHeight)
let latestHeight = try compactBlockDao.latestHeight()
XCTAssertEqual(latestHeight, rewindHeight - 1)
} catch {
@ -124,7 +128,7 @@ class CompactBlockStorageTests: XCTestCase {
let blockCount = Int(1_000)
let finalHeight = startHeight + blockCount
try TestDbBuilder.seed(db: compactBlockDao, with: startHeight...finalHeight)
try await TestDbBuilder.seed(db: compactBlockDao, with: startHeight...finalHeight)
let rewindHeight = BlockHeight(finalHeight - 233)
try await compactBlockDao.rewindAsync(to: rewindHeight)

View File

@ -58,105 +58,25 @@ class DarksideWalletService: LightWalletService {
self.init(endpoint: LightWalletEndpointBuilder.default)
}
@discardableResult
func blockStream(
startHeight: BlockHeight,
endHeight: BlockHeight,
result: @escaping (Result<GRPCResult, LightWalletServiceError>) -> Void,
handler: @escaping (ZcashCompactBlock) -> Void,
progress: @escaping (BlockProgress) -> Void
) -> CancellableCall {
return service.blockStream(
startHeight: startHeight,
endHeight: endHeight,
result: result,
handler: handler,
progress: progress
)
}
func blockStream(startHeight: BlockHeight, endHeight: BlockHeight) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
service.blockStream(startHeight: startHeight, endHeight: endHeight)
}
func getInfo() throws -> LightWalletdInfo {
try service.getInfo()
}
func getInfo(result: @escaping (Result<LightWalletdInfo, LightWalletServiceError>) -> Void) {
service.getInfo(result: result)
}
func closeConnection() {
}
func fetchUTXOs(for tAddress: String, height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
try service.fetchUTXOs(for: tAddress, height: height)
}
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
try service.fetchUTXOs(for: tAddresses, height: height)
}
func fetchUTXOs(
for tAddress: String,
height: BlockHeight,
result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
) {
service.fetchUTXOs(for: tAddress, height: height, result: result)
func closeConnection() {
}
func fetchUTXOs(for tAddress: String, height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
service.fetchUTXOs(for: tAddress, height: height)
}
func fetchUTXOs(
for tAddresses: [String],
height: BlockHeight,
result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
) {
service.fetchUTXOs(for: tAddresses, height: height, result: result)
}
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
service.fetchUTXOs(for: tAddresses, height: height)
}
func fetchTransaction(txId: Data) throws -> TransactionEntity {
try service.fetchTransaction(txId: txId)
}
func fetchTransaction(txId: Data, result: @escaping (Result<TransactionEntity, LightWalletServiceError>) -> Void) {
service.fetchTransaction(txId: txId, result: result)
}
func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void) {
service.latestBlockHeight(result: result)
}
func latestBlockHeight() throws -> BlockHeight {
try service.latestBlockHeight()
}
func blockRange(_ range: CompactBlockRange, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void) {
service.blockRange(range, result: result)
}
func blockRange(_ range: CompactBlockRange) throws -> [ZcashCompactBlock] {
try service.blockRange(range)
}
/**
Darskside lightwalletd should do a fake submission, by sending over the tx, retrieving it and including it in a new block
*/
func submit(spendTransaction: Data, result: @escaping (Result<LightWalletServiceResponse, LightWalletServiceError>) -> Void) {
service.submit(spendTransaction: spendTransaction, result: result)
}
func submit(spendTransaction: Data) throws -> LightWalletServiceResponse {
try service.submit(spendTransaction: spendTransaction)
}
func useDataset(_ datasetUrl: String) throws {
try useDataset(from: datasetUrl)
}
@ -234,10 +154,10 @@ class DarksideWalletService: LightWalletService {
_ = try darksideService.clearAddressUtxo(Empty(), callOptions: nil).response.wait()
}
func getInfoAsync() async throws -> LightWalletdInfo {
try service.getInfo()
func getInfo() async throws -> LightWalletdInfo {
try await service.getInfo()
}
func latestBlockHeightAsync() async throws -> BlockHeight {
try service.latestBlockHeight()
}
@ -246,12 +166,13 @@ class DarksideWalletService: LightWalletService {
service.blockRange(range)
}
func submitAsync(spendTransaction: Data) async throws -> LightWalletServiceResponse {
try service.submit(spendTransaction: spendTransaction)
/// Darskside lightwalletd should do a fake submission, by sending over the tx, retrieving it and including it in a new block
func submit(spendTransaction: Data) async throws -> LightWalletServiceResponse {
try await service.submit(spendTransaction: spendTransaction)
}
func fetchTransactionAsync(txId: Data) async throws -> TransactionEntity {
try service.fetchTransaction(txId: txId)
func fetchTransaction(txId: Data) async throws -> TransactionEntity {
try await service.fetchTransaction(txId: txId)
}
}

View File

@ -24,67 +24,17 @@ class MockLightWalletService: LightWalletService {
var mockLightDInfo: LightWalletdInfo?
var queue = DispatchQueue(label: "mock service queue")
@discardableResult
func blockStream(
startHeight: BlockHeight,
endHeight: BlockHeight,
result: @escaping (Result<GRPCResult, LightWalletServiceError>) -> Void,
handler: @escaping (ZcashCompactBlock) -> Void,
progress: @escaping (BlockProgress) -> Void
) -> CancellableCall {
return MockCancellable()
}
func blockStream(startHeight: BlockHeight, endHeight: BlockHeight) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
AsyncThrowingStream { _ in }
}
func getInfo() throws -> LightWalletdInfo {
guard let info = mockLightDInfo else {
throw LightWalletServiceError.generalError(message: "Not Implemented")
}
return info
}
func getInfo(result: @escaping (Result<LightWalletdInfo, LightWalletServiceError>) -> Void) {
queue.async { [weak self] in
guard let info = self?.mockLightDInfo else {
result(.failure(LightWalletServiceError.generalError(message: "Not Implemented")))
return
}
result(.success(info))
}
}
func closeConnection() {
}
func fetchUTXOs(for tAddress: String, height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
[]
}
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
[]
}
func fetchUTXOs(
for tAddress: String,
height: BlockHeight,
result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
) {
}
func fetchUTXOs(for tAddress: String, height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
AsyncThrowingStream { _ in }
}
func fetchUTXOs(
for tAddresses: [String],
height: BlockHeight,
result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
) {
}
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
AsyncThrowingStream { _ in }
}
@ -98,48 +48,17 @@ class MockLightWalletService: LightWalletService {
self.service = service
}
func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void) {
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
result(.success(self.latestHeight))
}
}
func latestBlockHeight() throws -> BlockHeight {
return self.latestHeight
}
func blockRange(_ range: CompactBlockRange, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void) {
self.service.blockRange(range, result: result)
}
func blockRange(_ range: CompactBlockRange) throws -> [ZcashCompactBlock] {
try self.service.blockRange(range)
}
func submit(spendTransaction: Data, result: @escaping (Result<LightWalletServiceResponse, LightWalletServiceError>) -> Void) {
DispatchQueue.global(qos: .default).asyncAfter(deadline: .now() + 1) {
result(.success(LightWalletServiceMockResponse(errorCode: 0, errorMessage: "", unknownFields: UnknownStorage())))
}
}
func submit(spendTransaction: Data) throws -> LightWalletServiceResponse {
return LightWalletServiceMockResponse(errorCode: 0, errorMessage: "", unknownFields: UnknownStorage())
}
func fetchTransaction(txId: Data) throws -> TransactionEntity {
Transaction(id: 1, transactionId: Data(), created: "Today", transactionIndex: 1, expiryHeight: -1, minedHeight: -1, raw: nil)
}
func fetchTransaction(txId: Data, result: @escaping (Result<TransactionEntity, LightWalletServiceError>) -> Void) {
}
func getInfoAsync() async throws -> LightWalletdInfo {
func getInfo() async throws -> LightWalletdInfo {
guard let info = mockLightDInfo else {
throw LightWalletServiceError.generalError(message: "Not Implemented")
}
return info
}
func latestBlockHeightAsync() async throws -> BlockHeight {
latestHeight
}
@ -148,19 +67,11 @@ class MockLightWalletService: LightWalletService {
service.blockRange(range)
}
func submitAsync(spendTransaction: Data) async throws -> LightWalletServiceResponse {
func submit(spendTransaction: Data) async throws -> LightWalletServiceResponse {
LightWalletServiceMockResponse(errorCode: 0, errorMessage: "", unknownFields: UnknownStorage())
}
func fetchTransactionAsync(txId: Data) async throws -> TransactionEntity {
func fetchTransaction(txId: Data) async throws -> TransactionEntity {
Transaction(id: 1, transactionId: Data(), created: "Today", transactionIndex: 1, expiryHeight: -1, minedHeight: -1, raw: nil)
}
func fetchUTXOsAsync(for tAddress: String, height: BlockHeight) async throws -> [UnspentTransactionOutputEntity] {
[]
}
func fetchUTXOsAsync(for tAddresses: [String], height: BlockHeight) async throws -> [UnspentTransactionOutputEntity] {
[]
}
}

View File

@ -14,7 +14,7 @@ class ZcashConsoleFakeStorage: CompactBlockRepository {
latestBlockHeight
}
func writeAsync(blocks: [ZcashCompactBlock]) async throws {
func write(blocks: [ZcashCompactBlock]) async throws {
fakeSave(blocks: blocks)
}
@ -26,10 +26,6 @@ class ZcashConsoleFakeStorage: CompactBlockRepository {
return self.latestBlockHeight
}
func write(blocks: [ZcashCompactBlock]) throws {
fakeSave(blocks: blocks)
}
func rewind(to height: BlockHeight) throws {
fakeRewind(to: height)
}

View File

@ -17,52 +17,26 @@ class AwfulLightWalletService: MockLightWalletService {
throw LightWalletServiceError.criticalError
}
override func blockRange(_ range: CompactBlockRange) throws -> [ZcashCompactBlock] {
override func latestBlockHeightAsync() async throws -> BlockHeight {
throw LightWalletServiceError.invalidBlock
}
override func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
result(.failure(LightWalletServiceError.invalidBlock))
}
}
override func blockRange(_ range: CompactBlockRange, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
result(.failure(LightWalletServiceError.invalidBlock))
}
}
override func blockRange(_ range: CompactBlockRange) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
AsyncThrowingStream { continuation in continuation.finish(throwing: LightWalletServiceError.invalidBlock) }
}
override func submit(spendTransaction: Data, result: @escaping(Result<LightWalletServiceResponse, LightWalletServiceError>) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
result(.failure(LightWalletServiceError.invalidBlock))
}
}
/**
Submits a raw transaction over lightwalletd. Blocking
*/
override func submit(spendTransaction: Data) throws -> LightWalletServiceResponse {
/// Submits a raw transaction over lightwalletd.
override func submit(spendTransaction: Data) async throws -> LightWalletServiceResponse {
throw LightWalletServiceError.invalidBlock
}
}
class SlightlyBadLightWalletService: MockLightWalletService {
override func submit(spendTransaction: Data, result: @escaping(Result<LightWalletServiceResponse, LightWalletServiceError>) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
result(.success(LightWalletServiceMockResponse.error))
}
}
extension LightWalletServiceMockResponse: Error { }
/**
Submits a raw transaction over lightwalletd. Blocking
*/
override func submit(spendTransaction: Data) throws -> LightWalletServiceResponse {
LightWalletServiceMockResponse.error
class SlightlyBadLightWalletService: MockLightWalletService {
/// Submits a raw transaction over lightwalletd.
override func submit(spendTransaction: Data) async throws -> LightWalletServiceResponse {
throw LightWalletServiceMockResponse.error
}
}

View File

@ -92,12 +92,12 @@ class TestDbBuilder {
return ReceivedNotesSQLDAO(dbProvider: provider)
}
static func seed(db: CompactBlockRepository, with blockRange: CompactBlockRange) throws {
static func seed(db: CompactBlockRepository, with blockRange: CompactBlockRange) async throws {
guard let blocks = StubBlockCreator.createBlockRange(blockRange) else {
throw TestBuilderError.generalError
}
try db.write(blocks: blocks)
try await db.write(blocks: blocks)
}
}