Fetch and store Orchard subtree roots
This commit is contained in:
parent
d8f389b8da
commit
006861595d
|
@ -6,6 +6,9 @@ and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
# Unreleased
|
# Unreleased
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- Orchard subtree roots are now fetched alongside Sapling subtree roots.
|
||||||
|
|
||||||
# 2.1.2 - 2024-03-27
|
# 2.1.2 - 2024-03-27
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
|
@ -176,8 +176,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/zcash-hackworks/zcash-light-client-ffi",
|
"location" : "https://github.com/zcash-hackworks/zcash-light-client-ffi",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "8838b4f0ee4193349fed09f0248220d4ada271fc",
|
"revision" : "e2d8763f3a963fb0026b6160af2d211b527453cd",
|
||||||
"version" : "0.7.3"
|
"version" : "0.7.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -122,8 +122,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/zcash-hackworks/zcash-light-client-ffi",
|
"location" : "https://github.com/zcash-hackworks/zcash-light-client-ffi",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "c7e5158edf5e62af15492d30237163b78af35ce9",
|
"revision" : "e2d8763f3a963fb0026b6160af2d211b527453cd",
|
||||||
"version" : "0.7.1"
|
"version" : "0.7.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -16,7 +16,7 @@ let package = Package(
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.19.1"),
|
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.19.1"),
|
||||||
.package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1"),
|
.package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1"),
|
||||||
.package(url: "https://github.com/zcash-hackworks/zcash-light-client-ffi", exact: "0.7.3")
|
.package(url: "https://github.com/zcash-hackworks/zcash-light-client-ffi", exact: "0.7.4")
|
||||||
],
|
],
|
||||||
targets: [
|
targets: [
|
||||||
.target(
|
.target(
|
||||||
|
|
|
@ -31,19 +31,19 @@ extension UpdateSubtreeRootsAction: Action {
|
||||||
logger.debug("Attempt to get subtree roots, this may fail because lightwalletd may not support Spend before Sync.")
|
logger.debug("Attempt to get subtree roots, this may fail because lightwalletd may not support Spend before Sync.")
|
||||||
let stream = service.getSubtreeRoots(request)
|
let stream = service.getSubtreeRoots(request)
|
||||||
|
|
||||||
var roots: [SubtreeRoot] = []
|
var saplingRoots: [SubtreeRoot] = []
|
||||||
|
|
||||||
do {
|
do {
|
||||||
for try await subtreeRoot in stream {
|
for try await subtreeRoot in stream {
|
||||||
roots.append(subtreeRoot)
|
saplingRoots.append(subtreeRoot)
|
||||||
}
|
}
|
||||||
} catch ZcashError.serviceSubtreeRootsStreamFailed(LightWalletServiceError.timeOut) {
|
} catch ZcashError.serviceSubtreeRootsStreamFailed(LightWalletServiceError.timeOut) {
|
||||||
throw ZcashError.serviceSubtreeRootsStreamFailed(LightWalletServiceError.timeOut)
|
throw ZcashError.serviceSubtreeRootsStreamFailed(LightWalletServiceError.timeOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("Sapling tree has \(roots.count) subtrees")
|
logger.debug("Sapling tree has \(saplingRoots.count) subtrees")
|
||||||
do {
|
do {
|
||||||
try await rustBackend.putSaplingSubtreeRoots(startIndex: UInt64(request.startIndex), roots: roots)
|
try await rustBackend.putSaplingSubtreeRoots(startIndex: UInt64(request.startIndex), roots: saplingRoots)
|
||||||
|
|
||||||
await context.update(state: .updateChainTip)
|
await context.update(state: .updateChainTip)
|
||||||
} catch {
|
} catch {
|
||||||
|
@ -51,6 +51,35 @@ extension UpdateSubtreeRootsAction: Action {
|
||||||
throw ZcashError.compactBlockProcessorPutSaplingSubtreeRoots(error)
|
throw ZcashError.compactBlockProcessorPutSaplingSubtreeRoots(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !saplingRoots.isEmpty {
|
||||||
|
logger.debug("Found Sapling subtree roots, SbS supported, fetching Orchard subtree roots")
|
||||||
|
|
||||||
|
var orchardRequest = GetSubtreeRootsArg()
|
||||||
|
orchardRequest.shieldedProtocol = .orchard
|
||||||
|
|
||||||
|
let stream = service.getSubtreeRoots(orchardRequest)
|
||||||
|
|
||||||
|
var orchardRoots: [SubtreeRoot] = []
|
||||||
|
|
||||||
|
do {
|
||||||
|
for try await subtreeRoot in stream {
|
||||||
|
orchardRoots.append(subtreeRoot)
|
||||||
|
}
|
||||||
|
} catch ZcashError.serviceSubtreeRootsStreamFailed(LightWalletServiceError.timeOut) {
|
||||||
|
throw ZcashError.serviceSubtreeRootsStreamFailed(LightWalletServiceError.timeOut)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("Orchard tree has \(orchardRoots.count) subtrees")
|
||||||
|
do {
|
||||||
|
try await rustBackend.putOrchardSubtreeRoots(startIndex: UInt64(orchardRequest.startIndex), roots: orchardRoots)
|
||||||
|
|
||||||
|
await context.update(state: .updateChainTip)
|
||||||
|
} catch {
|
||||||
|
logger.debug("putOrchardSubtreeRoots failed with error \(error.localizedDescription)")
|
||||||
|
throw ZcashError.compactBlockProcessorPutOrchardSubtreeRoots(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -333,6 +333,15 @@ public enum ZcashError: Equatable, Error {
|
||||||
/// - `rustError` contains error generated by the rust layer.
|
/// - `rustError` contains error generated by the rust layer.
|
||||||
/// ZRUST0059
|
/// ZRUST0059
|
||||||
case rustIsSeedRelevantToAnyDerivedAccount(_ rustError: String)
|
case rustIsSeedRelevantToAnyDerivedAccount(_ rustError: String)
|
||||||
|
/// Unable to allocate memory required to write blocks when calling ZcashRustBackend.putOrchardSubtreeRoots
|
||||||
|
/// sourcery: code="ZRUST0060"
|
||||||
|
/// ZRUST0060
|
||||||
|
case rustPutOrchardSubtreeRootsAllocationProblem
|
||||||
|
/// Error from rust layer when calling ZcashRustBackend.putOrchardSubtreeRoots
|
||||||
|
/// - `rustError` contains error generated by the rust layer.
|
||||||
|
/// sourcery: code="ZRUST0061"
|
||||||
|
/// ZRUST0061
|
||||||
|
case rustPutOrchardSubtreeRoots(_ rustError: String)
|
||||||
/// SQLite query failed when fetching all accounts from the database.
|
/// SQLite query failed when fetching all accounts from the database.
|
||||||
/// - `sqliteError` is error produced by SQLite library.
|
/// - `sqliteError` is error produced by SQLite library.
|
||||||
/// ZADAO0001
|
/// ZADAO0001
|
||||||
|
@ -578,6 +587,9 @@ public enum ZcashError: Equatable, Error {
|
||||||
/// Getting the `supportedSyncAlgorithm` failed but it's supposed to always provide some value.
|
/// Getting the `supportedSyncAlgorithm` failed but it's supposed to always provide some value.
|
||||||
/// ZCBPEO0021
|
/// ZCBPEO0021
|
||||||
case compactBlockProcessorSupportedSyncAlgorithm
|
case compactBlockProcessorSupportedSyncAlgorithm
|
||||||
|
/// Put Orchard subtree roots to the DB failed.
|
||||||
|
/// ZCBPEO0022
|
||||||
|
case compactBlockProcessorPutOrchardSubtreeRoots(_ error: Error)
|
||||||
/// The synchronizer is unprepared.
|
/// The synchronizer is unprepared.
|
||||||
/// ZSYNCO0001
|
/// ZSYNCO0001
|
||||||
case synchronizerNotPrepared
|
case synchronizerNotPrepared
|
||||||
|
@ -691,6 +703,8 @@ public enum ZcashError: Equatable, Error {
|
||||||
case .rustProposeTransferFromURI: return "Error from rust layer when calling ZcashRustBackend."
|
case .rustProposeTransferFromURI: return "Error from rust layer when calling ZcashRustBackend."
|
||||||
case .rustListAccounts: return "Error from rust layer when calling ZcashRustBackend."
|
case .rustListAccounts: return "Error from rust layer when calling ZcashRustBackend."
|
||||||
case .rustIsSeedRelevantToAnyDerivedAccount: return "Error from rust layer when calling ZcashRustBackend.rustIsSeedRelevantToAnyDerivedAccount"
|
case .rustIsSeedRelevantToAnyDerivedAccount: return "Error from rust layer when calling ZcashRustBackend.rustIsSeedRelevantToAnyDerivedAccount"
|
||||||
|
case .rustPutOrchardSubtreeRootsAllocationProblem: return "Unable to allocate memory required to write blocks when calling ZcashRustBackend.putOrchardSubtreeRoots"
|
||||||
|
case .rustPutOrchardSubtreeRoots: return "Error from rust layer when calling ZcashRustBackend.putOrchardSubtreeRoots"
|
||||||
case .accountDAOGetAll: return "SQLite query failed when fetching all accounts from the database."
|
case .accountDAOGetAll: return "SQLite query failed when fetching all accounts from the database."
|
||||||
case .accountDAOGetAllCantDecode: return "Fetched accounts from SQLite but can't decode them."
|
case .accountDAOGetAllCantDecode: return "Fetched accounts from SQLite but can't decode them."
|
||||||
case .accountDAOFindBy: return "SQLite query failed when seaching for accounts in the database."
|
case .accountDAOFindBy: return "SQLite query failed when seaching for accounts in the database."
|
||||||
|
@ -769,6 +783,7 @@ public enum ZcashError: Equatable, Error {
|
||||||
case .compactBlockProcessorPutSaplingSubtreeRoots: return "Put sapling subtree roots to the DB failed."
|
case .compactBlockProcessorPutSaplingSubtreeRoots: return "Put sapling subtree roots to the DB failed."
|
||||||
case .compactBlockProcessorLastScannedHeight: return "Getting the `lastScannedHeight` failed but it's supposed to always provide some value."
|
case .compactBlockProcessorLastScannedHeight: return "Getting the `lastScannedHeight` failed but it's supposed to always provide some value."
|
||||||
case .compactBlockProcessorSupportedSyncAlgorithm: return "Getting the `supportedSyncAlgorithm` failed but it's supposed to always provide some value."
|
case .compactBlockProcessorSupportedSyncAlgorithm: return "Getting the `supportedSyncAlgorithm` failed but it's supposed to always provide some value."
|
||||||
|
case .compactBlockProcessorPutOrchardSubtreeRoots: return "Put Orchard subtree roots to the DB failed."
|
||||||
case .synchronizerNotPrepared: return "The synchronizer is unprepared."
|
case .synchronizerNotPrepared: return "The synchronizer is unprepared."
|
||||||
case .synchronizerSendMemoToTransparentAddress: return "Memos can't be sent to transparent addresses."
|
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."
|
case .synchronizerShieldFundsInsuficientTransparentFunds: return "There is not enough transparent funds to cover fee for the shielding."
|
||||||
|
@ -868,6 +883,8 @@ public enum ZcashError: Equatable, Error {
|
||||||
case .rustProposeTransferFromURI: return .rustProposeTransferFromURI
|
case .rustProposeTransferFromURI: return .rustProposeTransferFromURI
|
||||||
case .rustListAccounts: return .rustListAccounts
|
case .rustListAccounts: return .rustListAccounts
|
||||||
case .rustIsSeedRelevantToAnyDerivedAccount: return .rustIsSeedRelevantToAnyDerivedAccount
|
case .rustIsSeedRelevantToAnyDerivedAccount: return .rustIsSeedRelevantToAnyDerivedAccount
|
||||||
|
case .rustPutOrchardSubtreeRootsAllocationProblem: return .rustPutOrchardSubtreeRootsAllocationProblem
|
||||||
|
case .rustPutOrchardSubtreeRoots: return .rustPutOrchardSubtreeRoots
|
||||||
case .accountDAOGetAll: return .accountDAOGetAll
|
case .accountDAOGetAll: return .accountDAOGetAll
|
||||||
case .accountDAOGetAllCantDecode: return .accountDAOGetAllCantDecode
|
case .accountDAOGetAllCantDecode: return .accountDAOGetAllCantDecode
|
||||||
case .accountDAOFindBy: return .accountDAOFindBy
|
case .accountDAOFindBy: return .accountDAOFindBy
|
||||||
|
@ -946,6 +963,7 @@ public enum ZcashError: Equatable, Error {
|
||||||
case .compactBlockProcessorPutSaplingSubtreeRoots: return .compactBlockProcessorPutSaplingSubtreeRoots
|
case .compactBlockProcessorPutSaplingSubtreeRoots: return .compactBlockProcessorPutSaplingSubtreeRoots
|
||||||
case .compactBlockProcessorLastScannedHeight: return .compactBlockProcessorLastScannedHeight
|
case .compactBlockProcessorLastScannedHeight: return .compactBlockProcessorLastScannedHeight
|
||||||
case .compactBlockProcessorSupportedSyncAlgorithm: return .compactBlockProcessorSupportedSyncAlgorithm
|
case .compactBlockProcessorSupportedSyncAlgorithm: return .compactBlockProcessorSupportedSyncAlgorithm
|
||||||
|
case .compactBlockProcessorPutOrchardSubtreeRoots: return .compactBlockProcessorPutOrchardSubtreeRoots
|
||||||
case .synchronizerNotPrepared: return .synchronizerNotPrepared
|
case .synchronizerNotPrepared: return .synchronizerNotPrepared
|
||||||
case .synchronizerSendMemoToTransparentAddress: return .synchronizerSendMemoToTransparentAddress
|
case .synchronizerSendMemoToTransparentAddress: return .synchronizerSendMemoToTransparentAddress
|
||||||
case .synchronizerShieldFundsInsuficientTransparentFunds: return .synchronizerShieldFundsInsuficientTransparentFunds
|
case .synchronizerShieldFundsInsuficientTransparentFunds: return .synchronizerShieldFundsInsuficientTransparentFunds
|
||||||
|
|
|
@ -181,6 +181,10 @@ public enum ZcashErrorCode: String {
|
||||||
case rustListAccounts = "ZRUST0058"
|
case rustListAccounts = "ZRUST0058"
|
||||||
/// Error from rust layer when calling ZcashRustBackend.rustIsSeedRelevantToAnyDerivedAccount
|
/// Error from rust layer when calling ZcashRustBackend.rustIsSeedRelevantToAnyDerivedAccount
|
||||||
case rustIsSeedRelevantToAnyDerivedAccount = "ZRUST0059"
|
case rustIsSeedRelevantToAnyDerivedAccount = "ZRUST0059"
|
||||||
|
/// Unable to allocate memory required to write blocks when calling ZcashRustBackend.putOrchardSubtreeRoots
|
||||||
|
case rustPutOrchardSubtreeRootsAllocationProblem = "ZRUST0060"
|
||||||
|
/// Error from rust layer when calling ZcashRustBackend.putOrchardSubtreeRoots
|
||||||
|
case rustPutOrchardSubtreeRoots = "ZRUST0061"
|
||||||
/// SQLite query failed when fetching all accounts from the database.
|
/// SQLite query failed when fetching all accounts from the database.
|
||||||
case accountDAOGetAll = "ZADAO0001"
|
case accountDAOGetAll = "ZADAO0001"
|
||||||
/// Fetched accounts from SQLite but can't decode them.
|
/// Fetched accounts from SQLite but can't decode them.
|
||||||
|
@ -337,6 +341,8 @@ public enum ZcashErrorCode: String {
|
||||||
case compactBlockProcessorLastScannedHeight = "ZCBPEO0020"
|
case compactBlockProcessorLastScannedHeight = "ZCBPEO0020"
|
||||||
/// Getting the `supportedSyncAlgorithm` failed but it's supposed to always provide some value.
|
/// Getting the `supportedSyncAlgorithm` failed but it's supposed to always provide some value.
|
||||||
case compactBlockProcessorSupportedSyncAlgorithm = "ZCBPEO0021"
|
case compactBlockProcessorSupportedSyncAlgorithm = "ZCBPEO0021"
|
||||||
|
/// Put Orchard subtree roots to the DB failed.
|
||||||
|
case compactBlockProcessorPutOrchardSubtreeRoots = "ZCBPEO0022"
|
||||||
/// The synchronizer is unprepared.
|
/// The synchronizer is unprepared.
|
||||||
case synchronizerNotPrepared = "ZSYNCO0001"
|
case synchronizerNotPrepared = "ZSYNCO0001"
|
||||||
/// Memos can't be sent to transparent addresses.
|
/// Memos can't be sent to transparent addresses.
|
||||||
|
|
|
@ -360,6 +360,13 @@ enum ZcashErrorDefinition {
|
||||||
/// - `rustError` contains error generated by the rust layer.
|
/// - `rustError` contains error generated by the rust layer.
|
||||||
// sourcery: code="ZRUST0059"
|
// sourcery: code="ZRUST0059"
|
||||||
case rustIsSeedRelevantToAnyDerivedAccount(_ rustError: String)
|
case rustIsSeedRelevantToAnyDerivedAccount(_ rustError: String)
|
||||||
|
/// Unable to allocate memory required to write blocks when calling ZcashRustBackend.putOrchardSubtreeRoots
|
||||||
|
/// sourcery: code="ZRUST0060"
|
||||||
|
case rustPutOrchardSubtreeRootsAllocationProblem
|
||||||
|
/// Error from rust layer when calling ZcashRustBackend.putOrchardSubtreeRoots
|
||||||
|
/// - `rustError` contains error generated by the rust layer.
|
||||||
|
/// sourcery: code="ZRUST0061"
|
||||||
|
case rustPutOrchardSubtreeRoots(_ rustError: String)
|
||||||
|
|
||||||
// MARK: - Account DAO
|
// MARK: - Account DAO
|
||||||
|
|
||||||
|
@ -654,6 +661,9 @@ enum ZcashErrorDefinition {
|
||||||
/// Getting the `supportedSyncAlgorithm` failed but it's supposed to always provide some value.
|
/// Getting the `supportedSyncAlgorithm` failed but it's supposed to always provide some value.
|
||||||
// sourcery: code="ZCBPEO0021"
|
// sourcery: code="ZCBPEO0021"
|
||||||
case compactBlockProcessorSupportedSyncAlgorithm
|
case compactBlockProcessorSupportedSyncAlgorithm
|
||||||
|
/// Put Orchard subtree roots to the DB failed.
|
||||||
|
// sourcery: code="ZCBPEO0022"
|
||||||
|
case compactBlockProcessorPutOrchardSubtreeRoots(_ error: Error)
|
||||||
|
|
||||||
// MARK: - SDKSynchronizer
|
// MARK: - SDKSynchronizer
|
||||||
|
|
||||||
|
|
|
@ -571,6 +571,64 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func putOrchardSubtreeRoots(startIndex: UInt64, roots: [SubtreeRoot]) async throws {
|
||||||
|
var ffiSubtreeRootsVec: [FfiSubtreeRoot] = []
|
||||||
|
|
||||||
|
for root in roots {
|
||||||
|
let hashPtr = UnsafeMutablePointer<UInt8>.allocate(capacity: root.rootHash.count)
|
||||||
|
|
||||||
|
let contiguousHashBytes = ContiguousArray(root.rootHash.bytes)
|
||||||
|
|
||||||
|
let result: Void? = contiguousHashBytes.withContiguousStorageIfAvailable { hashBytesPtr in
|
||||||
|
// swiftlint:disable:next force_unwrapping
|
||||||
|
hashPtr.initialize(from: hashBytesPtr.baseAddress!, count: hashBytesPtr.count)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard result != nil else {
|
||||||
|
defer {
|
||||||
|
hashPtr.deallocate()
|
||||||
|
ffiSubtreeRootsVec.deallocateElements()
|
||||||
|
}
|
||||||
|
throw ZcashError.rustPutOrchardSubtreeRootsAllocationProblem
|
||||||
|
}
|
||||||
|
|
||||||
|
ffiSubtreeRootsVec.append(
|
||||||
|
FfiSubtreeRoot(
|
||||||
|
root_hash_ptr: hashPtr,
|
||||||
|
root_hash_ptr_len: UInt(contiguousHashBytes.count),
|
||||||
|
completing_block_height: UInt32(root.completingBlockHeight)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var contiguousFfiRoots = ContiguousArray(ffiSubtreeRootsVec)
|
||||||
|
|
||||||
|
let len = UInt(contiguousFfiRoots.count)
|
||||||
|
|
||||||
|
let rootsPtr = UnsafeMutablePointer<FfiSubtreeRoots>.allocate(capacity: 1)
|
||||||
|
|
||||||
|
defer {
|
||||||
|
ffiSubtreeRootsVec.deallocateElements()
|
||||||
|
rootsPtr.deallocate()
|
||||||
|
}
|
||||||
|
|
||||||
|
try contiguousFfiRoots.withContiguousMutableStorageIfAvailable { ptr in
|
||||||
|
var roots = FfiSubtreeRoots()
|
||||||
|
roots.ptr = ptr.baseAddress
|
||||||
|
roots.len = len
|
||||||
|
|
||||||
|
rootsPtr.initialize(to: roots)
|
||||||
|
|
||||||
|
globalDBLock.lock()
|
||||||
|
let res = zcashlc_put_orchard_subtree_roots(dbData.0, dbData.1, startIndex, rootsPtr, networkType.networkId)
|
||||||
|
globalDBLock.unlock()
|
||||||
|
|
||||||
|
guard res else {
|
||||||
|
throw ZcashError.rustPutOrchardSubtreeRoots(lastErrorMessage(fallback: "`putOrchardSubtreeRoots` failed with unknown error"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func updateChainTip(height: Int32) async throws {
|
func updateChainTip(height: Int32) async throws {
|
||||||
globalDBLock.lock()
|
globalDBLock.lock()
|
||||||
let result = zcashlc_update_chain_tip(dbData.0, dbData.1, height, networkType.networkId)
|
let result = zcashlc_update_chain_tip(dbData.0, dbData.1, height, networkType.networkId)
|
||||||
|
|
|
@ -133,6 +133,8 @@ protocol ZcashRustBackendWelding {
|
||||||
|
|
||||||
func putSaplingSubtreeRoots(startIndex: UInt64, roots: [SubtreeRoot]) async throws
|
func putSaplingSubtreeRoots(startIndex: UInt64, roots: [SubtreeRoot]) async throws
|
||||||
|
|
||||||
|
func putOrchardSubtreeRoots(startIndex: UInt64, roots: [SubtreeRoot]) async throws
|
||||||
|
|
||||||
/// Updates the wallet's view of the blockchain.
|
/// Updates the wallet's view of the blockchain.
|
||||||
///
|
///
|
||||||
/// This method is used to provide the wallet with information about the state of the blockchain,
|
/// This method is used to provide the wallet with information about the state of the blockchain,
|
||||||
|
|
|
@ -70,6 +70,7 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await tupple.rustBackendMock.setPutSaplingSubtreeRootsStartIndexRootsClosure({ _, _ in })
|
await tupple.rustBackendMock.setPutSaplingSubtreeRootsStartIndexRootsClosure({ _, _ in })
|
||||||
|
await tupple.rustBackendMock.setPutOrchardSubtreeRootsStartIndexRootsClosure({ _, _ in })
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let context = ActionContextMock.default()
|
let context = ActionContextMock.default()
|
||||||
|
@ -83,7 +84,7 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testUpdateSubtreeRootsAction_RootsAvailablePutRootsFailure() async throws {
|
func testUpdateSubtreeRootsAction_RootsAvailablePutSaplingRootsFailure() async throws {
|
||||||
let loggerMock = LoggerMock()
|
let loggerMock = LoggerMock()
|
||||||
|
|
||||||
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
|
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
|
||||||
|
@ -98,6 +99,7 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await tupple.rustBackendMock.setPutSaplingSubtreeRootsStartIndexRootsThrowableError("putSaplingFailed")
|
await tupple.rustBackendMock.setPutSaplingSubtreeRootsStartIndexRootsThrowableError("putSaplingFailed")
|
||||||
|
await tupple.rustBackendMock.setPutOrchardSubtreeRootsStartIndexRootsClosure({ _, _ in })
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let context = ActionContextMock.default()
|
let context = ActionContextMock.default()
|
||||||
|
@ -112,6 +114,36 @@ final class UpdateSubtreeRootsActionTests: ZcashTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testUpdateSubtreeRootsAction_RootsAvailablePutOrchardRootsFailure() async throws {
|
||||||
|
let loggerMock = LoggerMock()
|
||||||
|
|
||||||
|
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
|
||||||
|
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
|
||||||
|
|
||||||
|
let tupple = setupAction(loggerMock)
|
||||||
|
let updateSubtreeRootsActionAction = tupple.action
|
||||||
|
tupple.serviceMock.getSubtreeRootsClosure = { _ in
|
||||||
|
AsyncThrowingStream { continuation in
|
||||||
|
continuation.yield(SubtreeRoot())
|
||||||
|
continuation.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await tupple.rustBackendMock.setPutSaplingSubtreeRootsStartIndexRootsClosure({ _, _ in })
|
||||||
|
await tupple.rustBackendMock.setPutOrchardSubtreeRootsStartIndexRootsThrowableError("putOrchardFailed")
|
||||||
|
|
||||||
|
do {
|
||||||
|
let context = ActionContextMock.default()
|
||||||
|
|
||||||
|
_ = try await updateSubtreeRootsActionAction.run(with: context) { _ in }
|
||||||
|
|
||||||
|
XCTFail("updateSubtreeRootsActionAction.run(with:) is excpected to fail but didn't.")
|
||||||
|
} catch ZcashError.compactBlockProcessorPutOrchardSubtreeRoots {
|
||||||
|
// this is expected result of this test
|
||||||
|
} catch {
|
||||||
|
XCTFail("testUpdateSubtreeRootsAction_RootsAvailablePutRootsFailure is not expected to fail. \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// swiftlint:disable large_tuple
|
// swiftlint:disable large_tuple
|
||||||
private func setupAction(
|
private func setupAction(
|
||||||
_ loggerMock: LoggerMock = LoggerMock()
|
_ loggerMock: LoggerMock = LoggerMock()
|
||||||
|
|
|
@ -2722,6 +2722,31 @@ actor ZcashRustBackendWeldingMock: ZcashRustBackendWelding {
|
||||||
try await putSaplingSubtreeRootsStartIndexRootsClosure!(startIndex, roots)
|
try await putSaplingSubtreeRootsStartIndexRootsClosure!(startIndex, roots)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - putOrchardSubtreeRoots
|
||||||
|
|
||||||
|
var putOrchardSubtreeRootsStartIndexRootsThrowableError: Error?
|
||||||
|
func setPutOrchardSubtreeRootsStartIndexRootsThrowableError(_ param: Error?) async {
|
||||||
|
putOrchardSubtreeRootsStartIndexRootsThrowableError = param
|
||||||
|
}
|
||||||
|
var putOrchardSubtreeRootsStartIndexRootsCallsCount = 0
|
||||||
|
var putOrchardSubtreeRootsStartIndexRootsCalled: Bool {
|
||||||
|
return putOrchardSubtreeRootsStartIndexRootsCallsCount > 0
|
||||||
|
}
|
||||||
|
var putOrchardSubtreeRootsStartIndexRootsReceivedArguments: (startIndex: UInt64, roots: [SubtreeRoot])?
|
||||||
|
var putOrchardSubtreeRootsStartIndexRootsClosure: ((UInt64, [SubtreeRoot]) async throws -> Void)?
|
||||||
|
func setPutOrchardSubtreeRootsStartIndexRootsClosure(_ param: ((UInt64, [SubtreeRoot]) async throws -> Void)?) async {
|
||||||
|
putOrchardSubtreeRootsStartIndexRootsClosure = param
|
||||||
|
}
|
||||||
|
|
||||||
|
func putOrchardSubtreeRoots(startIndex: UInt64, roots: [SubtreeRoot]) async throws {
|
||||||
|
if let error = putOrchardSubtreeRootsStartIndexRootsThrowableError {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
putOrchardSubtreeRootsStartIndexRootsCallsCount += 1
|
||||||
|
putOrchardSubtreeRootsStartIndexRootsReceivedArguments = (startIndex: startIndex, roots: roots)
|
||||||
|
try await putOrchardSubtreeRootsStartIndexRootsClosure!(startIndex, roots)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - updateChainTip
|
// MARK: - updateChainTip
|
||||||
|
|
||||||
var updateChainTipHeightThrowableError: Error?
|
var updateChainTipHeightThrowableError: Error?
|
||||||
|
|
Loading…
Reference in New Issue