draft

[#1165] Step 1 - Download note commitment tree data from lightwalletd

- code cleanup after draft

[#1165] Step 1 - Download note commitment tree data from lightwalletd

- UpdateSubtreeRootsAction added, ensuring the roots are downloaded and stored in the DB

[#1165] Step 1 - Download note commitment tree data from lightwalletd

- added ZcashError for putSaplingSubtreeRoots failure
- cleaned up action

[#1165] Step 1 - Download note commitment tree data from lightwalletd

- demo app config temporarily updated to Nighthawk server

[#1165] Step 1 - Download note commitment tree data from lightwalletd

- file header updated

[#1165] Step 1 - Download note commitment tree data from lightwalletd (#1174)

- demo app config cleaned up

[#1165] Step 1 - Download note commitment tree data from lightwalletd (#1174)

- offline tests fixed
This commit is contained in:
Lukas Korba 2023-07-31 08:51:04 +02:00
parent d446c6d336
commit 7694b04d42
16 changed files with 263 additions and 47 deletions

View File

@ -18,14 +18,14 @@ enum DemoAppConfig {
let seed: [UInt8]
}
static let host = ZcashSDK.isMainnet ? "lightwalletd.electriccoin.co" : "lightwalletd.testnet.electriccoin.co"
static let host = ZcashSDK.isMainnet ? "mainnet.lightwalletd.com" : "testnet.lightwalletd.com"
static let port: Int = 9067
static let defaultBirthdayHeight: BlockHeight = ZcashSDK.isMainnet ? 935000 : 1386000
static let defaultSeed = try! Mnemonic.deterministicSeedBytes(from: """
live combine flight accident slow soda mind bright absent bid hen shy decade biology amazing mix enlist ensure biology rhythm snap duty soap armor
""")
static let otherSynchronizers: [SynchronizerInitData] = [
SynchronizerInitData(
alias: .custom("alt-sync-1"),

View File

@ -34,6 +34,7 @@ enum CBPState: CaseIterable {
case idle
case migrateLegacyCacheDB
case validateServer
case updateSubtreeRoots
case computeSyncControlData
case download
case scan

View File

@ -0,0 +1,68 @@
//
// UpdateSubtreeRootsAction.swift
//
//
// Created by Lukas Korba on 01.08.2023.
//
import Foundation
final class UpdateSubtreeRootsAction {
let rustBackend: ZcashRustBackendWelding
let service: LightWalletService
let logger: Logger
init(container: DIContainer) {
service = container.resolve(LightWalletService.self)
rustBackend = container.resolve(ZcashRustBackendWelding.self)
logger = container.resolve(Logger.self)
}
}
extension UpdateSubtreeRootsAction: Action {
var removeBlocksCacheWhenFailed: Bool { false }
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
var request = GetSubtreeRootsArg()
request.shieldedProtocol = .sapling
request.maxEntries = 65536
logger.info("Attempt to get subtree roots, this may fail because lightwalletd may not support DAG sync.")
let stream = service.getSubtreeRoots(request)
var roots: [SubtreeRoot] = []
var err: Error?
do {
for try await subtreeRoot in stream {
roots.append(subtreeRoot)
}
} catch {
logger.debug("getSubtreeRoots failed with error \(error.localizedDescription)")
err = error
}
// In case of error, the lightwalletd doesn't support DAG sync -> switching to linear sync.
// Likewise, no subtree roots results in switching to linear sync.
if err != nil || roots.isEmpty {
logger.info("DAG sync is not possible, switching to linear sync.")
await context.update(state: .computeSyncControlData)
} else {
logger.info("Sapling tree has \(roots.count) subtrees")
do {
try await rustBackend.putSaplingSubtreeRoots(startIndex: UInt64(request.startIndex), roots: roots)
// TODO: [#1167] Switching back to linear sync for now before step 3 & 4 are implemented
// https://github.com/zcash/ZcashLightClientKit/issues/1167
await context.update(state: .computeSyncControlData)
} catch {
logger.debug("putSaplingSubtreeRoots failed with error \(error.localizedDescription)")
throw ZcashError.compactBlockProcessorPutSaplingSubtreeRoots(error)
}
}
return context
}
func stop() async { }
}

View File

@ -52,7 +52,7 @@ extension ValidateServerAction: Action {
throw ZcashError.compactBlockProcessorWrongConsensusBranchId(localBranch, remoteBranchID)
}
await context.update(state: .computeSyncControlData)
await context.update(state: .updateSubtreeRoots)
return context
}

View File

@ -214,6 +214,8 @@ actor CompactBlockProcessor {
action = MigrateLegacyCacheDBAction(container: container, configProvider: configProvider)
case .validateServer:
action = ValidateServerAction(container: container, configProvider: configProvider)
case .updateSubtreeRoots:
action = UpdateSubtreeRootsAction(container: container)
case .computeSyncControlData:
action = ComputeSyncControlDataAction(container: container, configProvider: configProvider)
case .download:
@ -585,6 +587,8 @@ extension CompactBlockProcessor {
break
case .validateServer:
break
case .updateSubtreeRoots:
break
case .computeSyncControlData:
break
case .download:

View File

@ -58,6 +58,9 @@ public enum ZcashError: Equatable, Error {
/// LightWalletService.blockStream failed.
/// ZSRVC0000
case serviceBlockStreamFailed(_ error: LightWalletServiceError)
/// LightWalletService.getSubtreeRoots failed.
/// ZSRVC0009
case serviceSubtreeRootsStreamFailed(_ error: LightWalletServiceError)
/// SimpleConnectionProvider init of Connection failed.
/// ZSCPC0001
case simpleConnectionProvider(_ error: Error)
@ -277,18 +280,22 @@ public enum ZcashError: Equatable, Error {
/// ZRUST0045
case rustGetTransparentReceiverInvalidReceiver
/// Unable to allocate memory required to write blocks when calling ZcashRustBackend.putSaplingSubtreeRoots
/// sourcery: code="ZRUST0046"
/// ZRUST0046
case rustPutSaplingSubtreeRootsAllocationProblem
/// Error from rust layer when calling ZcashRustBackend.putSaplingSubtreeRoots
/// - `rustError` contains error generated by the rust layer.
/// sourcery: code="ZRUST0047"
/// ZRUST0047
case rustPutSaplingSubtreeRoots(_ rustError: String)
/// Error from rust layer when calling ZcashRustBackend.updateChainTip
/// - `rustError` contains error generated by the rust layer.
/// sourcery: code="ZRUST0048"
/// ZRUST0048
case rustUpdateChainTip(_ rustError: String)
/// Error from rust layer when calling ZcashRustBackend.suggestScanRanges
/// - `rustError` contains error generated by the rust layer.
/// sourcery: code="ZRUST0049"
/// ZRUST0049
case rustSuggestScanRanges(_ rustError: String)
/// Invalid transaction ID length when calling ZcashRustBackend.getMemo
@ -530,6 +537,9 @@ public enum ZcashError: Equatable, Error {
/// Rewind of DownloadBlockAction failed as no action is possible to unwrapp.
/// ZCBPEO0018
case compactBlockProcessorDownloadBlockActionRewind
/// Put sapling subtree roots to the DB failed.
/// ZCBPEO0019
case compactBlockProcessorPutSaplingSubtreeRoots(_ error: Error)
/// The synchronizer is unprepared.
/// ZSYNCO0001
case synchronizerNotPrepared
@ -566,6 +576,7 @@ public enum ZcashError: Equatable, Error {
case .serviceFetchTransactionFailed: return "LightWalletService.fetchTransaction failed."
case .serviceFetchUTXOsFailed: return "LightWalletService.fetchUTXOs failed."
case .serviceBlockStreamFailed: return "LightWalletService.blockStream failed."
case .serviceSubtreeRootsStreamFailed: return "LightWalletService.getSubtreeRoots failed."
case .simpleConnectionProvider: return "SimpleConnectionProvider init of Connection failed."
case .saplingParamsInvalidSpendParams: return "Downloaded file with sapling spending parameters isn't valid."
case .saplingParamsInvalidOutputParams: return "Downloaded file with sapling output parameters isn't valid."
@ -623,7 +634,7 @@ public enum ZcashError: Equatable, Error {
case .rustGetSaplingReceiverInvalidReceiver: return "Sapling receiver generated by rust layer is invalid when calling ZcashRustBackend.getSaplingReceiver"
case .rustGetTransparentReceiverInvalidAddress: return "Error from rust layer when calling ZcashRustBackend.getTransparentReceiver"
case .rustGetTransparentReceiverInvalidReceiver: return "Transparent receiver generated by rust layer is invalid when calling ZcashRustBackend.getTransparentReceiver"
case .rustPutSaplingSubtreeRootsAllocationProblem: return "Unable to allocate memory required to store subtree roots when calling ZcashRustBackend.putSaplingSubtreeRoots"
case .rustPutSaplingSubtreeRootsAllocationProblem: return "Unable to allocate memory required to write blocks when calling ZcashRustBackend.putSaplingSubtreeRoots"
case .rustPutSaplingSubtreeRoots: return "Error from rust layer when calling ZcashRustBackend.putSaplingSubtreeRoots"
case .rustUpdateChainTip: return "Error from rust layer when calling ZcashRustBackend.updateChainTip"
case .rustSuggestScanRanges: return "Error from rust layer when calling ZcashRustBackend.suggestScanRanges"
@ -703,6 +714,7 @@ public enum ZcashError: Equatable, Error {
case .compactBlockProcessorChainName: return "Chain name does not match. Expected either 'test' or 'main'. This is probably an API or programming error."
case .compactBlockProcessorConsensusBranchID: return "Consensus BranchIDs don't match this is probably an API or programming error."
case .compactBlockProcessorDownloadBlockActionRewind: return "Rewind of DownloadBlockAction failed as no action is possible to unwrapp."
case .compactBlockProcessorPutSaplingSubtreeRoots: return "Put sapling subtree roots to the DB failed."
case .synchronizerNotPrepared: return "The synchronizer is unprepared."
case .synchronizerSendMemoToTransparentAddress: return "Memos can't be sent to transparent addresses."
case .synchronizerShieldFundsInsuficientTransparentFunds: return "There is not enough transparent funds to cover fee for the shielding."
@ -729,6 +741,7 @@ public enum ZcashError: Equatable, Error {
case .serviceFetchTransactionFailed: return .serviceFetchTransactionFailed
case .serviceFetchUTXOsFailed: return .serviceFetchUTXOsFailed
case .serviceBlockStreamFailed: return .serviceBlockStreamFailed
case .serviceSubtreeRootsStreamFailed: return .serviceSubtreeRootsStreamFailed
case .simpleConnectionProvider: return .simpleConnectionProvider
case .saplingParamsInvalidSpendParams: return .saplingParamsInvalidSpendParams
case .saplingParamsInvalidOutputParams: return .saplingParamsInvalidOutputParams
@ -866,6 +879,7 @@ public enum ZcashError: Equatable, Error {
case .compactBlockProcessorChainName: return .compactBlockProcessorChainName
case .compactBlockProcessorConsensusBranchID: return .compactBlockProcessorConsensusBranchID
case .compactBlockProcessorDownloadBlockActionRewind: return .compactBlockProcessorDownloadBlockActionRewind
case .compactBlockProcessorPutSaplingSubtreeRoots: return .compactBlockProcessorPutSaplingSubtreeRoots
case .synchronizerNotPrepared: return .synchronizerNotPrepared
case .synchronizerSendMemoToTransparentAddress: return .synchronizerSendMemoToTransparentAddress
case .synchronizerShieldFundsInsuficientTransparentFunds: return .synchronizerShieldFundsInsuficientTransparentFunds

View File

@ -39,6 +39,8 @@ public enum ZcashErrorCode: String {
case serviceFetchUTXOsFailed = "ZSRVC0008"
/// LightWalletService.blockStream failed.
case serviceBlockStreamFailed = "ZSRVC0000"
/// LightWalletService.getSubtreeRoots failed.
case serviceSubtreeRootsStreamFailed = "ZSRVC0009"
/// SimpleConnectionProvider init of Connection failed.
case simpleConnectionProvider = "ZSCPC0001"
/// Downloaded file with sapling spending parameters isn't valid.
@ -313,6 +315,8 @@ public enum ZcashErrorCode: String {
case compactBlockProcessorConsensusBranchID = "ZCBPEO0017"
/// Rewind of DownloadBlockAction failed as no action is possible to unwrapp.
case compactBlockProcessorDownloadBlockActionRewind = "ZCBPEO0018"
/// Put sapling subtree roots to the DB failed.
case compactBlockProcessorPutSaplingSubtreeRoots = "ZCBPEO0019"
/// The synchronizer is unprepared.
case synchronizerNotPrepared = "ZSYNCO0001"
/// Memos can't be sent to transparent addresses.

View File

@ -77,6 +77,9 @@ enum ZcashErrorDefinition {
/// LightWalletService.blockStream failed.
// sourcery: code="ZSRVC0000"
case serviceBlockStreamFailed(_ error: LightWalletServiceError)
/// LightWalletService.getSubtreeRoots failed.
// sourcery: code="ZSRVC0009"
case serviceSubtreeRootsStreamFailed(_ error: LightWalletServiceError)
// MARK: SQLite connection
@ -307,6 +310,21 @@ enum ZcashErrorDefinition {
/// Transparent receiver generated by rust layer is invalid when calling ZcashRustBackend.getTransparentReceiver
// sourcery: code="ZRUST0045"
case rustGetTransparentReceiverInvalidReceiver
/// Unable to allocate memory required to write blocks when calling ZcashRustBackend.putSaplingSubtreeRoots
/// sourcery: code="ZRUST0046"
case rustPutSaplingSubtreeRootsAllocationProblem
/// Error from rust layer when calling ZcashRustBackend.putSaplingSubtreeRoots
/// - `rustError` contains error generated by the rust layer.
/// sourcery: code="ZRUST0047"
case rustPutSaplingSubtreeRoots(_ rustError: String)
/// Error from rust layer when calling ZcashRustBackend.updateChainTip
/// - `rustError` contains error generated by the rust layer.
/// sourcery: code="ZRUST0048"
case rustUpdateChainTip(_ rustError: String)
/// Error from rust layer when calling ZcashRustBackend.suggestScanRanges
/// - `rustError` contains error generated by the rust layer.
/// sourcery: code="ZRUST0049"
case rustSuggestScanRanges(_ rustError: String)
// MARK: - Account DAO
@ -592,6 +610,9 @@ enum ZcashErrorDefinition {
/// Rewind of DownloadBlockAction failed as no action is possible to unwrapp.
// sourcery: code="ZCBPEO0018"
case compactBlockProcessorDownloadBlockActionRewind
/// Put sapling subtree roots to the DB failed.
// sourcery: code="ZCBPEO0019"
case compactBlockProcessorPutSaplingSubtreeRoots(_ error: Error)
// MARK: - SDKSynchronizer

View File

@ -262,6 +262,21 @@ extension LightWalletGRPCService: LightWalletService {
}
}
}
func getSubtreeRoots(_ request: GetSubtreeRootsArg) -> AsyncThrowingStream<SubtreeRoot, Error> {
let stream = compactTxStreamer.getSubtreeRoots(request)
var iterator = stream.makeAsyncIterator()
return AsyncThrowingStream() {
do {
guard let subtreeRoot = try await iterator.next() else { return nil }
return subtreeRoot
} catch {
let serviceError = error.mapToServiceError()
throw ZcashError.serviceSubtreeRootsStreamFailed(serviceError)
}
}
}
func closeConnection() {
_ = channel.close()

View File

@ -193,4 +193,11 @@ protocol LightWalletService: AnyObject {
) -> AsyncThrowingStream<ZcashCompactBlock, Error>
func closeConnection()
/// Returns a stream of information about roots of subtrees of the Sapling and Orchard
/// note commitment trees.
///
/// - Parameters:
/// - request: Request to send to GetSubtreeRoots.
func getSubtreeRoots(_ request: GetSubtreeRootsArg) -> AsyncThrowingStream<SubtreeRoot, Error>
}

View File

@ -166,6 +166,10 @@ protocol ZcashRustBackendWelding {
/// - Throws: `rustRewindCacheToHeight` if rust layer returns error.
func rewindCacheToHeight(height: Int32) async throws
func putSaplingSubtreeRoots(startIndex: UInt64, roots: [SubtreeRoot]) async throws
func updateChainTip(height: Int32) async throws
/// Returns a list of suggested scan ranges based upon the current wallet state.
///
/// This method should only be used in cases where the `CompactBlock` data that will be

View File

@ -141,7 +141,7 @@ public class SDKSynchronizer: Synchronizer {
if case .seedRequired = try await self.initializer.initialize(with: seed, viewingKeys: viewingKeys, walletBirthday: walletBirthday) {
return .seedRequired
}
await latestBlocksDataProvider.updateWalletBirthday(initializer.walletBirthday)
await latestBlocksDataProvider.updateScannedData()

View File

@ -31,8 +31,8 @@ final class ValidateServerActionTests: ZcashTestCase {
let nextContext = try await validateServerAction.run(with: .init(state: .validateServer)) { _ in }
let nextState = await nextContext.state
XCTAssertTrue(
nextState == .computeSyncControlData,
"nextContext after .validateServer is expected to be .computeSyncControlData but received \(nextState)"
nextState == .updateSubtreeRoots,
"nextContext after .validateServer is expected to be .updateSubtreeRoots but received \(nextState)"
)
} catch {
XCTFail("testValidateServerAction_NextAction is not expected to fail. \(error)")

View File

@ -13,27 +13,27 @@ enum DarksideDataset: String {
case afterLargeReorg = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/basic-reorg/after-large-large.txt"
case afterSmallReorg = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/basic-reorg/after-small-reorg.txt"
case beforeReOrg = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/basic-reorg/before-reorg.txt"
/**
see
https://github.com/zcash-hackworks/darksidewalletd-test-data/tree/master/tx-index-reorg
*/
see
https://github.com/zcash-hackworks/darksidewalletd-test-data/tree/master/tx-index-reorg
*/
case txIndexChangeBefore = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/tx-index-reorg/before-reorg.txt"
case txIndexChangeAfter = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/tx-index-reorg/after-reorg.txt"
/**
See https://github.com/zcash-hackworks/darksidewalletd-test-data/tree/master/tx-height-reorg
*/
See https://github.com/zcash-hackworks/darksidewalletd-test-data/tree/master/tx-height-reorg
*/
case txHeightReOrgBefore = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/tx-height-reorg/before-reorg.txt"
case txHeightReOrgAfter = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/tx-height-reorg/after-reorg.txt"
/*
see: https://github.com/zcash-hackworks/darksidewalletd-test-data/tree/master/tx-remove-reorg
*/
see: https://github.com/zcash-hackworks/darksidewalletd-test-data/tree/master/tx-remove-reorg
*/
case txReOrgRemovesInboundTxBefore = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/tx-remove-reorg/before-reorg.txt"
case txReOrgRemovesInboundTxAfter = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/tx-remove-reorg/after-reorg.txt"
}
@ -45,34 +45,34 @@ class DarksideWalletService: LightWalletService {
var channel: Channel
var service: LightWalletService
var darksideService: DarksideStreamerNIOClient
init(endpoint: LightWalletEndpoint) {
self.channel = ChannelProvider().channel(endpoint: endpoint)
self.service = LightWalletServiceFactory(endpoint: endpoint).make()
self.darksideService = DarksideStreamerNIOClient(channel: channel)
}
init(endpoint: LightWalletEndpoint, service: LightWalletService) {
self.channel = ChannelProvider().channel(endpoint: endpoint)
self.darksideService = DarksideStreamerNIOClient(channel: channel)
self.service = service
}
convenience init() {
self.init(endpoint: LightWalletEndpointBuilder.default)
}
func blockStream(startHeight: BlockHeight, endHeight: BlockHeight) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
service.blockStream(startHeight: startHeight, endHeight: endHeight)
}
func latestBlock() async throws -> ZcashLightClientKit.BlockID {
throw "Not mocked"
}
func closeConnection() {
}
func fetchUTXOs(for tAddress: String, height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
service.fetchUTXOs(for: tAddress, height: height)
}
@ -80,40 +80,40 @@ class DarksideWalletService: LightWalletService {
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
service.fetchUTXOs(for: tAddresses, height: height)
}
func latestBlockHeight() async throws -> BlockHeight {
try await service.latestBlockHeight()
}
func useDataset(_ datasetUrl: String) throws {
try useDataset(from: datasetUrl)
}
func useDataset(from urlString: String) throws {
var blocksUrl = DarksideBlocksURL()
blocksUrl.url = urlString
_ = try darksideService.stageBlocks(blocksUrl, callOptions: nil).response.wait()
}
func applyStaged(nextLatestHeight: BlockHeight) throws {
var darksideHeight = DarksideHeight()
darksideHeight.height = Int32(nextLatestHeight)
_ = try darksideService.applyStaged(darksideHeight).response.wait()
}
func clearIncomingTransactions() throws {
_ = try darksideService.clearIncomingTransactions(Empty()).response.wait()
}
func getIncomingTransactions() throws -> [RawTransaction]? {
var txs: [RawTransaction] = []
let response = try darksideService.getIncomingTransactions(
Empty(),
handler: { txs.append($0) }
)
.status
.wait()
.status
.wait()
switch response.code {
case .ok:
return !txs.isEmpty ? txs : nil
@ -121,7 +121,7 @@ class DarksideWalletService: LightWalletService {
throw response
}
}
func reset(saplingActivation: BlockHeight, branchID: String = "d3adb33f", chainName: String = "test") throws {
var metaState = DarksideMetaState()
metaState.saplingActivation = Int32(saplingActivation)
@ -130,7 +130,7 @@ class DarksideWalletService: LightWalletService {
// TODO: [#718] complete meta state correctly, https://github.com/zcash/ZcashLightClientKit/issues/718
_ = try darksideService.reset(metaState).response.wait()
}
func stageBlocksCreate(from height: BlockHeight, count: Int = 1, nonce: Int = 0) throws {
var emptyBlocks = DarksideEmptyBlocks()
emptyBlocks.count = Int32(count)
@ -138,7 +138,7 @@ class DarksideWalletService: LightWalletService {
emptyBlocks.nonce = Int32(nonce)
_ = try darksideService.stageBlocksCreate(emptyBlocks).response.wait()
}
func stageTransaction(_ rawTransaction: RawTransaction, at height: BlockHeight) throws {
var transaction = rawTransaction
transaction.height = UInt64(height)
@ -146,18 +146,18 @@ class DarksideWalletService: LightWalletService {
.sendMessage(transaction)
.wait()
}
func stageTransaction(from url: String, at height: BlockHeight) throws {
var txUrl = DarksideTransactionsURL()
txUrl.height = Int32(height)
txUrl.url = url
_ = try darksideService.stageTransactions(txUrl, callOptions: nil).response.wait()
}
func addUTXO(_ utxo: GetAddressUtxosReply) throws {
_ = try darksideService.addAddressUtxo(utxo, callOptions: nil).response.wait()
}
func clearAddedUTXOs() throws {
_ = try darksideService.clearAddressUtxo(Empty(), callOptions: nil).response.wait()
}
@ -165,7 +165,7 @@ class DarksideWalletService: LightWalletService {
func getInfo() async throws -> LightWalletdInfo {
try await service.getInfo()
}
func blockRange(_ range: CompactBlockRange) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
service.blockRange(range)
}
@ -178,27 +178,31 @@ class DarksideWalletService: LightWalletService {
func fetchTransaction(txId: Data) async throws -> ZcashTransaction.Fetched {
try await service.fetchTransaction(txId: txId)
}
func getSubtreeRoots(_ request: ZcashLightClientKit.GetSubtreeRootsArg) -> AsyncThrowingStream<ZcashLightClientKit.SubtreeRoot, Error> {
service.getSubtreeRoots(request)
}
}
enum DarksideWalletDConstants: NetworkConstants {
static let defaultFsBlockDbRootName = "fs_cache"
static var saplingActivationHeight: BlockHeight {
663150
}
static var defaultDataDbName: String {
ZcashSDKMainnetConstants.defaultDataDbName
}
static var defaultCacheDbName: String {
ZcashSDKMainnetConstants.defaultCacheDbName
}
static var defaultDbNamePrefix: String {
ZcashSDKMainnetConstants.defaultDbNamePrefix
}
static var feeChangeHeight: BlockHeight {
ZcashSDKMainnetConstants.feeChangeHeight
}

View File

@ -78,4 +78,8 @@ class MockLightWalletService: LightWalletService {
func fetchTransaction(txId: Data) async throws -> ZcashTransaction.Fetched {
return ZcashTransaction.Fetched(rawID: Data(), minedHeight: -1, raw: Data())
}
func getSubtreeRoots(_ request: ZcashLightClientKit.GetSubtreeRootsArg) -> AsyncThrowingStream<ZcashLightClientKit.SubtreeRoot, Error> {
service.getSubtreeRoots(request)
}
}

View File

@ -820,6 +820,26 @@ class LightWalletServiceMock: LightWalletService {
closeConnectionClosure!()
}
// MARK: - getSubtreeRoots
var getSubtreeRootsCallsCount = 0
var getSubtreeRootsCalled: Bool {
return getSubtreeRootsCallsCount > 0
}
var getSubtreeRootsReceivedRequest: GetSubtreeRootsArg?
var getSubtreeRootsReturnValue: AsyncThrowingStream<SubtreeRoot, Error>!
var getSubtreeRootsClosure: ((GetSubtreeRootsArg) -> AsyncThrowingStream<SubtreeRoot, Error>)?
func getSubtreeRoots(_ request: GetSubtreeRootsArg) -> AsyncThrowingStream<SubtreeRoot, Error> {
getSubtreeRootsCallsCount += 1
getSubtreeRootsReceivedRequest = request
if let closure = getSubtreeRootsClosure {
return closure(request)
} else {
return getSubtreeRootsReturnValue
}
}
}
class LightWalletdInfoMock: LightWalletdInfo {
@ -2574,6 +2594,56 @@ actor ZcashRustBackendWeldingMock: ZcashRustBackendWelding {
try await rewindCacheToHeightHeightClosure!(height)
}
// MARK: - putSaplingSubtreeRoots
var putSaplingSubtreeRootsStartIndexRootsThrowableError: Error?
func setPutSaplingSubtreeRootsStartIndexRootsThrowableError(_ param: Error?) async {
putSaplingSubtreeRootsStartIndexRootsThrowableError = param
}
var putSaplingSubtreeRootsStartIndexRootsCallsCount = 0
var putSaplingSubtreeRootsStartIndexRootsCalled: Bool {
return putSaplingSubtreeRootsStartIndexRootsCallsCount > 0
}
var putSaplingSubtreeRootsStartIndexRootsReceivedArguments: (startIndex: UInt64, roots: [SubtreeRoot])?
var putSaplingSubtreeRootsStartIndexRootsClosure: ((UInt64, [SubtreeRoot]) async throws -> Void)?
func setPutSaplingSubtreeRootsStartIndexRootsClosure(_ param: ((UInt64, [SubtreeRoot]) async throws -> Void)?) async {
putSaplingSubtreeRootsStartIndexRootsClosure = param
}
func putSaplingSubtreeRoots(startIndex: UInt64, roots: [SubtreeRoot]) async throws {
if let error = putSaplingSubtreeRootsStartIndexRootsThrowableError {
throw error
}
putSaplingSubtreeRootsStartIndexRootsCallsCount += 1
putSaplingSubtreeRootsStartIndexRootsReceivedArguments = (startIndex: startIndex, roots: roots)
try await putSaplingSubtreeRootsStartIndexRootsClosure!(startIndex, roots)
}
// MARK: - updateChainTip
var updateChainTipHeightThrowableError: Error?
func setUpdateChainTipHeightThrowableError(_ param: Error?) async {
updateChainTipHeightThrowableError = param
}
var updateChainTipHeightCallsCount = 0
var updateChainTipHeightCalled: Bool {
return updateChainTipHeightCallsCount > 0
}
var updateChainTipHeightReceivedHeight: Int32?
var updateChainTipHeightClosure: ((Int32) async throws -> Void)?
func setUpdateChainTipHeightClosure(_ param: ((Int32) async throws -> Void)?) async {
updateChainTipHeightClosure = param
}
func updateChainTip(height: Int32) async throws {
if let error = updateChainTipHeightThrowableError {
throw error
}
updateChainTipHeightCallsCount += 1
updateChainTipHeightReceivedHeight = height
try await updateChainTipHeightClosure!(height)
}
// MARK: - suggestScanRanges
var suggestScanRangesThrowableError: Error?