[#1341] Add Support for GetSubTreeRoots in Advanced Re Org tests

closes #1341

Updates Proto files and compile new swift versions

Adds setSubTree darkside service
adds subtrees into buildFakeChain() methods
This commit is contained in:
Francisco Gindre 2024-01-04 18:58:03 -03:00
parent 6c9b7a91d6
commit 1908d70f7f
No known key found for this signature in database
GPG Key ID: 6B61CD8DAA2862B4
8 changed files with 1064 additions and 37 deletions

View File

@ -31,7 +31,7 @@ message TxFilter {
bytes hash = 3; // transaction ID (hash, txid)
}
// RawTransaction contains the complete transaction data. It also optionally includes
// RawTransaction contains the complete transaction data. It also optionally includes
// the block height in which the transaction was included, or, when returned
// by GetMempoolStream(), the latest block height.
message RawTransaction {
@ -170,7 +170,8 @@ service CompactTxStreamer {
// Submit the given transaction to the Zcash network
rpc SendTransaction(RawTransaction) returns (SendResponse) {}
// Return the txids corresponding to the given t-address within the given block range
// Return the transactions corresponding to the given t-address within the given block range
// NB - this method is misnamed, it returns transactions, not transaction IDs.
rpc GetTaddressTxids(TransparentAddressBlockFilter) returns (stream RawTransaction) {}
rpc GetTaddressBalance(AddressList) returns (Balance) {}
rpc GetTaddressBalanceStream(stream Address) returns (Balance) {}
@ -197,8 +198,8 @@ service CompactTxStreamer {
rpc GetTreeState(BlockID) returns (TreeState) {}
rpc GetLatestTreeState(Empty) returns (TreeState) {}
// Returns a stream of information about roots of subtrees of the Sapling and Orchard
// note commitment trees.
// Returns a stream of information about roots of subtrees of the note commitment tree
// for the specified shielded protocol (Sapling or Orchard).
rpc GetSubtreeRoots(GetSubtreeRootsArg) returns (stream SubtreeRoot) {}
rpc GetAddressUtxos(GetAddressUtxosArg) returns (GetAddressUtxosReplyList) {}

View File

@ -255,7 +255,8 @@ extension CompactTxStreamerClientProtocol {
)
}
/// Return the txids corresponding to the given t-address within the given block range
/// Return the transactions corresponding to the given t-address within the given block range
/// NB - this method is misnamed, it returns transactions, not transaction IDs.
///
/// - Parameters:
/// - request: Request to send to GetTaddressTxids.
@ -402,8 +403,8 @@ extension CompactTxStreamerClientProtocol {
)
}
/// Returns a stream of information about roots of subtrees of the Sapling and Orchard
/// note commitment trees.
/// Returns a stream of information about roots of subtrees of the note commitment tree
/// for the specified shielded protocol (Sapling or Orchard).
///
/// - Parameters:
/// - request: Request to send to GetSubtreeRoots.
@ -1358,3 +1359,818 @@ internal enum CompactTxStreamerClientMetadata {
}
}
/// To build a server, implement a class that conforms to this protocol.
internal protocol CompactTxStreamerProvider: CallHandlerProvider {
var interceptors: CompactTxStreamerServerInterceptorFactoryProtocol? { get }
/// Return the height of the tip of the best chain
func getLatestBlock(request: ChainSpec, context: StatusOnlyCallContext) -> EventLoopFuture<BlockID>
/// Return the compact block corresponding to the given block identifier
func getBlock(request: BlockID, context: StatusOnlyCallContext) -> EventLoopFuture<CompactBlock>
/// Same as GetBlock except actions contain only nullifiers
func getBlockNullifiers(request: BlockID, context: StatusOnlyCallContext) -> EventLoopFuture<CompactBlock>
/// Return a list of consecutive compact blocks
func getBlockRange(request: BlockRange, context: StreamingResponseCallContext<CompactBlock>) -> EventLoopFuture<GRPCStatus>
/// Same as GetBlockRange except actions contain only nullifiers
func getBlockRangeNullifiers(request: BlockRange, context: StreamingResponseCallContext<CompactBlock>) -> EventLoopFuture<GRPCStatus>
/// Return the requested full (not compact) transaction (as from zcashd)
func getTransaction(request: TxFilter, context: StatusOnlyCallContext) -> EventLoopFuture<RawTransaction>
/// Submit the given transaction to the Zcash network
func sendTransaction(request: RawTransaction, context: StatusOnlyCallContext) -> EventLoopFuture<SendResponse>
/// Return the transactions corresponding to the given t-address within the given block range
/// NB - this method is misnamed, it returns transactions, not transaction IDs.
func getTaddressTxids(request: TransparentAddressBlockFilter, context: StreamingResponseCallContext<RawTransaction>) -> EventLoopFuture<GRPCStatus>
func getTaddressBalance(request: AddressList, context: StatusOnlyCallContext) -> EventLoopFuture<Balance>
func getTaddressBalanceStream(context: UnaryResponseCallContext<Balance>) -> EventLoopFuture<(StreamEvent<Address>) -> Void>
/// Return the compact transactions currently in the mempool; the results
/// can be a few seconds out of date. If the Exclude list is empty, return
/// all transactions; otherwise return all *except* those in the Exclude list
/// (if any); this allows the client to avoid receiving transactions that it
/// already has (from an earlier call to this rpc). The transaction IDs in the
/// Exclude list can be shortened to any number of bytes to make the request
/// more bandwidth-efficient; if two or more transactions in the mempool
/// match a shortened txid, they are all sent (none is excluded). Transactions
/// in the exclude list that don't exist in the mempool are ignored.
func getMempoolTx(request: Exclude, context: StreamingResponseCallContext<CompactTx>) -> EventLoopFuture<GRPCStatus>
/// Return a stream of current Mempool transactions. This will keep the output stream open while
/// there are mempool transactions. It will close the returned stream when a new block is mined.
func getMempoolStream(request: Empty, context: StreamingResponseCallContext<RawTransaction>) -> EventLoopFuture<GRPCStatus>
/// GetTreeState returns the note commitment tree state corresponding to the given block.
/// See section 3.7 of the Zcash protocol specification. It returns several other useful
/// values also (even though they can be obtained using GetBlock).
/// The block can be specified by either height or hash.
func getTreeState(request: BlockID, context: StatusOnlyCallContext) -> EventLoopFuture<TreeState>
func getLatestTreeState(request: Empty, context: StatusOnlyCallContext) -> EventLoopFuture<TreeState>
/// Returns a stream of information about roots of subtrees of the note commitment tree
/// for the specified shielded protocol (Sapling or Orchard).
func getSubtreeRoots(request: GetSubtreeRootsArg, context: StreamingResponseCallContext<SubtreeRoot>) -> EventLoopFuture<GRPCStatus>
func getAddressUtxos(request: GetAddressUtxosArg, context: StatusOnlyCallContext) -> EventLoopFuture<GetAddressUtxosReplyList>
func getAddressUtxosStream(request: GetAddressUtxosArg, context: StreamingResponseCallContext<GetAddressUtxosReply>) -> EventLoopFuture<GRPCStatus>
/// Return information about this lightwalletd instance and the blockchain
func getLightdInfo(request: Empty, context: StatusOnlyCallContext) -> EventLoopFuture<LightdInfo>
/// Testing-only, requires lightwalletd --ping-very-insecure (do not enable in production)
func ping(request: Duration, context: StatusOnlyCallContext) -> EventLoopFuture<PingResponse>
}
extension CompactTxStreamerProvider {
internal var serviceName: Substring {
return CompactTxStreamerServerMetadata.serviceDescriptor.fullName[...]
}
/// Determines, calls and returns the appropriate request handler, depending on the request's method.
/// Returns nil for methods not handled by this service.
internal func handle(
method name: Substring,
context: CallHandlerContext
) -> GRPCServerHandlerProtocol? {
switch name {
case "GetLatestBlock":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<ChainSpec>(),
responseSerializer: ProtobufSerializer<BlockID>(),
interceptors: self.interceptors?.makeGetLatestBlockInterceptors() ?? [],
userFunction: self.getLatestBlock(request:context:)
)
case "GetBlock":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<BlockID>(),
responseSerializer: ProtobufSerializer<CompactBlock>(),
interceptors: self.interceptors?.makeGetBlockInterceptors() ?? [],
userFunction: self.getBlock(request:context:)
)
case "GetBlockNullifiers":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<BlockID>(),
responseSerializer: ProtobufSerializer<CompactBlock>(),
interceptors: self.interceptors?.makeGetBlockNullifiersInterceptors() ?? [],
userFunction: self.getBlockNullifiers(request:context:)
)
case "GetBlockRange":
return ServerStreamingServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<BlockRange>(),
responseSerializer: ProtobufSerializer<CompactBlock>(),
interceptors: self.interceptors?.makeGetBlockRangeInterceptors() ?? [],
userFunction: self.getBlockRange(request:context:)
)
case "GetBlockRangeNullifiers":
return ServerStreamingServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<BlockRange>(),
responseSerializer: ProtobufSerializer<CompactBlock>(),
interceptors: self.interceptors?.makeGetBlockRangeNullifiersInterceptors() ?? [],
userFunction: self.getBlockRangeNullifiers(request:context:)
)
case "GetTransaction":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<TxFilter>(),
responseSerializer: ProtobufSerializer<RawTransaction>(),
interceptors: self.interceptors?.makeGetTransactionInterceptors() ?? [],
userFunction: self.getTransaction(request:context:)
)
case "SendTransaction":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<RawTransaction>(),
responseSerializer: ProtobufSerializer<SendResponse>(),
interceptors: self.interceptors?.makeSendTransactionInterceptors() ?? [],
userFunction: self.sendTransaction(request:context:)
)
case "GetTaddressTxids":
return ServerStreamingServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<TransparentAddressBlockFilter>(),
responseSerializer: ProtobufSerializer<RawTransaction>(),
interceptors: self.interceptors?.makeGetTaddressTxidsInterceptors() ?? [],
userFunction: self.getTaddressTxids(request:context:)
)
case "GetTaddressBalance":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<AddressList>(),
responseSerializer: ProtobufSerializer<Balance>(),
interceptors: self.interceptors?.makeGetTaddressBalanceInterceptors() ?? [],
userFunction: self.getTaddressBalance(request:context:)
)
case "GetTaddressBalanceStream":
return ClientStreamingServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Address>(),
responseSerializer: ProtobufSerializer<Balance>(),
interceptors: self.interceptors?.makeGetTaddressBalanceStreamInterceptors() ?? [],
observerFactory: self.getTaddressBalanceStream(context:)
)
case "GetMempoolTx":
return ServerStreamingServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Exclude>(),
responseSerializer: ProtobufSerializer<CompactTx>(),
interceptors: self.interceptors?.makeGetMempoolTxInterceptors() ?? [],
userFunction: self.getMempoolTx(request:context:)
)
case "GetMempoolStream":
return ServerStreamingServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Empty>(),
responseSerializer: ProtobufSerializer<RawTransaction>(),
interceptors: self.interceptors?.makeGetMempoolStreamInterceptors() ?? [],
userFunction: self.getMempoolStream(request:context:)
)
case "GetTreeState":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<BlockID>(),
responseSerializer: ProtobufSerializer<TreeState>(),
interceptors: self.interceptors?.makeGetTreeStateInterceptors() ?? [],
userFunction: self.getTreeState(request:context:)
)
case "GetLatestTreeState":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Empty>(),
responseSerializer: ProtobufSerializer<TreeState>(),
interceptors: self.interceptors?.makeGetLatestTreeStateInterceptors() ?? [],
userFunction: self.getLatestTreeState(request:context:)
)
case "GetSubtreeRoots":
return ServerStreamingServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<GetSubtreeRootsArg>(),
responseSerializer: ProtobufSerializer<SubtreeRoot>(),
interceptors: self.interceptors?.makeGetSubtreeRootsInterceptors() ?? [],
userFunction: self.getSubtreeRoots(request:context:)
)
case "GetAddressUtxos":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<GetAddressUtxosArg>(),
responseSerializer: ProtobufSerializer<GetAddressUtxosReplyList>(),
interceptors: self.interceptors?.makeGetAddressUtxosInterceptors() ?? [],
userFunction: self.getAddressUtxos(request:context:)
)
case "GetAddressUtxosStream":
return ServerStreamingServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<GetAddressUtxosArg>(),
responseSerializer: ProtobufSerializer<GetAddressUtxosReply>(),
interceptors: self.interceptors?.makeGetAddressUtxosStreamInterceptors() ?? [],
userFunction: self.getAddressUtxosStream(request:context:)
)
case "GetLightdInfo":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Empty>(),
responseSerializer: ProtobufSerializer<LightdInfo>(),
interceptors: self.interceptors?.makeGetLightdInfoInterceptors() ?? [],
userFunction: self.getLightdInfo(request:context:)
)
case "Ping":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Duration>(),
responseSerializer: ProtobufSerializer<PingResponse>(),
interceptors: self.interceptors?.makePingInterceptors() ?? [],
userFunction: self.ping(request:context:)
)
default:
return nil
}
}
}
/// To implement a server, implement an object which conforms to this protocol.
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
internal protocol CompactTxStreamerAsyncProvider: CallHandlerProvider, Sendable {
static var serviceDescriptor: GRPCServiceDescriptor { get }
var interceptors: CompactTxStreamerServerInterceptorFactoryProtocol? { get }
/// Return the height of the tip of the best chain
func getLatestBlock(
request: ChainSpec,
context: GRPCAsyncServerCallContext
) async throws -> BlockID
/// Return the compact block corresponding to the given block identifier
func getBlock(
request: BlockID,
context: GRPCAsyncServerCallContext
) async throws -> CompactBlock
/// Same as GetBlock except actions contain only nullifiers
func getBlockNullifiers(
request: BlockID,
context: GRPCAsyncServerCallContext
) async throws -> CompactBlock
/// Return a list of consecutive compact blocks
func getBlockRange(
request: BlockRange,
responseStream: GRPCAsyncResponseStreamWriter<CompactBlock>,
context: GRPCAsyncServerCallContext
) async throws
/// Same as GetBlockRange except actions contain only nullifiers
func getBlockRangeNullifiers(
request: BlockRange,
responseStream: GRPCAsyncResponseStreamWriter<CompactBlock>,
context: GRPCAsyncServerCallContext
) async throws
/// Return the requested full (not compact) transaction (as from zcashd)
func getTransaction(
request: TxFilter,
context: GRPCAsyncServerCallContext
) async throws -> RawTransaction
/// Submit the given transaction to the Zcash network
func sendTransaction(
request: RawTransaction,
context: GRPCAsyncServerCallContext
) async throws -> SendResponse
/// Return the transactions corresponding to the given t-address within the given block range
/// NB - this method is misnamed, it returns transactions, not transaction IDs.
func getTaddressTxids(
request: TransparentAddressBlockFilter,
responseStream: GRPCAsyncResponseStreamWriter<RawTransaction>,
context: GRPCAsyncServerCallContext
) async throws
func getTaddressBalance(
request: AddressList,
context: GRPCAsyncServerCallContext
) async throws -> Balance
func getTaddressBalanceStream(
requestStream: GRPCAsyncRequestStream<Address>,
context: GRPCAsyncServerCallContext
) async throws -> Balance
/// Return the compact transactions currently in the mempool; the results
/// can be a few seconds out of date. If the Exclude list is empty, return
/// all transactions; otherwise return all *except* those in the Exclude list
/// (if any); this allows the client to avoid receiving transactions that it
/// already has (from an earlier call to this rpc). The transaction IDs in the
/// Exclude list can be shortened to any number of bytes to make the request
/// more bandwidth-efficient; if two or more transactions in the mempool
/// match a shortened txid, they are all sent (none is excluded). Transactions
/// in the exclude list that don't exist in the mempool are ignored.
func getMempoolTx(
request: Exclude,
responseStream: GRPCAsyncResponseStreamWriter<CompactTx>,
context: GRPCAsyncServerCallContext
) async throws
/// Return a stream of current Mempool transactions. This will keep the output stream open while
/// there are mempool transactions. It will close the returned stream when a new block is mined.
func getMempoolStream(
request: Empty,
responseStream: GRPCAsyncResponseStreamWriter<RawTransaction>,
context: GRPCAsyncServerCallContext
) async throws
/// GetTreeState returns the note commitment tree state corresponding to the given block.
/// See section 3.7 of the Zcash protocol specification. It returns several other useful
/// values also (even though they can be obtained using GetBlock).
/// The block can be specified by either height or hash.
func getTreeState(
request: BlockID,
context: GRPCAsyncServerCallContext
) async throws -> TreeState
func getLatestTreeState(
request: Empty,
context: GRPCAsyncServerCallContext
) async throws -> TreeState
/// Returns a stream of information about roots of subtrees of the note commitment tree
/// for the specified shielded protocol (Sapling or Orchard).
func getSubtreeRoots(
request: GetSubtreeRootsArg,
responseStream: GRPCAsyncResponseStreamWriter<SubtreeRoot>,
context: GRPCAsyncServerCallContext
) async throws
func getAddressUtxos(
request: GetAddressUtxosArg,
context: GRPCAsyncServerCallContext
) async throws -> GetAddressUtxosReplyList
func getAddressUtxosStream(
request: GetAddressUtxosArg,
responseStream: GRPCAsyncResponseStreamWriter<GetAddressUtxosReply>,
context: GRPCAsyncServerCallContext
) async throws
/// Return information about this lightwalletd instance and the blockchain
func getLightdInfo(
request: Empty,
context: GRPCAsyncServerCallContext
) async throws -> LightdInfo
/// Testing-only, requires lightwalletd --ping-very-insecure (do not enable in production)
func ping(
request: Duration,
context: GRPCAsyncServerCallContext
) async throws -> PingResponse
}
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
extension CompactTxStreamerAsyncProvider {
internal static var serviceDescriptor: GRPCServiceDescriptor {
return CompactTxStreamerServerMetadata.serviceDescriptor
}
internal var serviceName: Substring {
return CompactTxStreamerServerMetadata.serviceDescriptor.fullName[...]
}
internal var interceptors: CompactTxStreamerServerInterceptorFactoryProtocol? {
return nil
}
internal func handle(
method name: Substring,
context: CallHandlerContext
) -> GRPCServerHandlerProtocol? {
switch name {
case "GetLatestBlock":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<ChainSpec>(),
responseSerializer: ProtobufSerializer<BlockID>(),
interceptors: self.interceptors?.makeGetLatestBlockInterceptors() ?? [],
wrapping: { try await self.getLatestBlock(request: $0, context: $1) }
)
case "GetBlock":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<BlockID>(),
responseSerializer: ProtobufSerializer<CompactBlock>(),
interceptors: self.interceptors?.makeGetBlockInterceptors() ?? [],
wrapping: { try await self.getBlock(request: $0, context: $1) }
)
case "GetBlockNullifiers":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<BlockID>(),
responseSerializer: ProtobufSerializer<CompactBlock>(),
interceptors: self.interceptors?.makeGetBlockNullifiersInterceptors() ?? [],
wrapping: { try await self.getBlockNullifiers(request: $0, context: $1) }
)
case "GetBlockRange":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<BlockRange>(),
responseSerializer: ProtobufSerializer<CompactBlock>(),
interceptors: self.interceptors?.makeGetBlockRangeInterceptors() ?? [],
wrapping: { try await self.getBlockRange(request: $0, responseStream: $1, context: $2) }
)
case "GetBlockRangeNullifiers":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<BlockRange>(),
responseSerializer: ProtobufSerializer<CompactBlock>(),
interceptors: self.interceptors?.makeGetBlockRangeNullifiersInterceptors() ?? [],
wrapping: { try await self.getBlockRangeNullifiers(request: $0, responseStream: $1, context: $2) }
)
case "GetTransaction":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<TxFilter>(),
responseSerializer: ProtobufSerializer<RawTransaction>(),
interceptors: self.interceptors?.makeGetTransactionInterceptors() ?? [],
wrapping: { try await self.getTransaction(request: $0, context: $1) }
)
case "SendTransaction":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<RawTransaction>(),
responseSerializer: ProtobufSerializer<SendResponse>(),
interceptors: self.interceptors?.makeSendTransactionInterceptors() ?? [],
wrapping: { try await self.sendTransaction(request: $0, context: $1) }
)
case "GetTaddressTxids":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<TransparentAddressBlockFilter>(),
responseSerializer: ProtobufSerializer<RawTransaction>(),
interceptors: self.interceptors?.makeGetTaddressTxidsInterceptors() ?? [],
wrapping: { try await self.getTaddressTxids(request: $0, responseStream: $1, context: $2) }
)
case "GetTaddressBalance":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<AddressList>(),
responseSerializer: ProtobufSerializer<Balance>(),
interceptors: self.interceptors?.makeGetTaddressBalanceInterceptors() ?? [],
wrapping: { try await self.getTaddressBalance(request: $0, context: $1) }
)
case "GetTaddressBalanceStream":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Address>(),
responseSerializer: ProtobufSerializer<Balance>(),
interceptors: self.interceptors?.makeGetTaddressBalanceStreamInterceptors() ?? [],
wrapping: { try await self.getTaddressBalanceStream(requestStream: $0, context: $1) }
)
case "GetMempoolTx":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Exclude>(),
responseSerializer: ProtobufSerializer<CompactTx>(),
interceptors: self.interceptors?.makeGetMempoolTxInterceptors() ?? [],
wrapping: { try await self.getMempoolTx(request: $0, responseStream: $1, context: $2) }
)
case "GetMempoolStream":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Empty>(),
responseSerializer: ProtobufSerializer<RawTransaction>(),
interceptors: self.interceptors?.makeGetMempoolStreamInterceptors() ?? [],
wrapping: { try await self.getMempoolStream(request: $0, responseStream: $1, context: $2) }
)
case "GetTreeState":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<BlockID>(),
responseSerializer: ProtobufSerializer<TreeState>(),
interceptors: self.interceptors?.makeGetTreeStateInterceptors() ?? [],
wrapping: { try await self.getTreeState(request: $0, context: $1) }
)
case "GetLatestTreeState":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Empty>(),
responseSerializer: ProtobufSerializer<TreeState>(),
interceptors: self.interceptors?.makeGetLatestTreeStateInterceptors() ?? [],
wrapping: { try await self.getLatestTreeState(request: $0, context: $1) }
)
case "GetSubtreeRoots":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<GetSubtreeRootsArg>(),
responseSerializer: ProtobufSerializer<SubtreeRoot>(),
interceptors: self.interceptors?.makeGetSubtreeRootsInterceptors() ?? [],
wrapping: { try await self.getSubtreeRoots(request: $0, responseStream: $1, context: $2) }
)
case "GetAddressUtxos":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<GetAddressUtxosArg>(),
responseSerializer: ProtobufSerializer<GetAddressUtxosReplyList>(),
interceptors: self.interceptors?.makeGetAddressUtxosInterceptors() ?? [],
wrapping: { try await self.getAddressUtxos(request: $0, context: $1) }
)
case "GetAddressUtxosStream":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<GetAddressUtxosArg>(),
responseSerializer: ProtobufSerializer<GetAddressUtxosReply>(),
interceptors: self.interceptors?.makeGetAddressUtxosStreamInterceptors() ?? [],
wrapping: { try await self.getAddressUtxosStream(request: $0, responseStream: $1, context: $2) }
)
case "GetLightdInfo":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Empty>(),
responseSerializer: ProtobufSerializer<LightdInfo>(),
interceptors: self.interceptors?.makeGetLightdInfoInterceptors() ?? [],
wrapping: { try await self.getLightdInfo(request: $0, context: $1) }
)
case "Ping":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<Duration>(),
responseSerializer: ProtobufSerializer<PingResponse>(),
interceptors: self.interceptors?.makePingInterceptors() ?? [],
wrapping: { try await self.ping(request: $0, context: $1) }
)
default:
return nil
}
}
}
internal protocol CompactTxStreamerServerInterceptorFactoryProtocol: Sendable {
/// - Returns: Interceptors to use when handling 'getLatestBlock'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetLatestBlockInterceptors() -> [ServerInterceptor<ChainSpec, BlockID>]
/// - Returns: Interceptors to use when handling 'getBlock'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetBlockInterceptors() -> [ServerInterceptor<BlockID, CompactBlock>]
/// - Returns: Interceptors to use when handling 'getBlockNullifiers'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetBlockNullifiersInterceptors() -> [ServerInterceptor<BlockID, CompactBlock>]
/// - Returns: Interceptors to use when handling 'getBlockRange'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetBlockRangeInterceptors() -> [ServerInterceptor<BlockRange, CompactBlock>]
/// - Returns: Interceptors to use when handling 'getBlockRangeNullifiers'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetBlockRangeNullifiersInterceptors() -> [ServerInterceptor<BlockRange, CompactBlock>]
/// - Returns: Interceptors to use when handling 'getTransaction'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetTransactionInterceptors() -> [ServerInterceptor<TxFilter, RawTransaction>]
/// - Returns: Interceptors to use when handling 'sendTransaction'.
/// Defaults to calling `self.makeInterceptors()`.
func makeSendTransactionInterceptors() -> [ServerInterceptor<RawTransaction, SendResponse>]
/// - Returns: Interceptors to use when handling 'getTaddressTxids'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetTaddressTxidsInterceptors() -> [ServerInterceptor<TransparentAddressBlockFilter, RawTransaction>]
/// - Returns: Interceptors to use when handling 'getTaddressBalance'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetTaddressBalanceInterceptors() -> [ServerInterceptor<AddressList, Balance>]
/// - Returns: Interceptors to use when handling 'getTaddressBalanceStream'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetTaddressBalanceStreamInterceptors() -> [ServerInterceptor<Address, Balance>]
/// - Returns: Interceptors to use when handling 'getMempoolTx'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetMempoolTxInterceptors() -> [ServerInterceptor<Exclude, CompactTx>]
/// - Returns: Interceptors to use when handling 'getMempoolStream'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetMempoolStreamInterceptors() -> [ServerInterceptor<Empty, RawTransaction>]
/// - Returns: Interceptors to use when handling 'getTreeState'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetTreeStateInterceptors() -> [ServerInterceptor<BlockID, TreeState>]
/// - Returns: Interceptors to use when handling 'getLatestTreeState'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetLatestTreeStateInterceptors() -> [ServerInterceptor<Empty, TreeState>]
/// - Returns: Interceptors to use when handling 'getSubtreeRoots'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetSubtreeRootsInterceptors() -> [ServerInterceptor<GetSubtreeRootsArg, SubtreeRoot>]
/// - Returns: Interceptors to use when handling 'getAddressUtxos'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetAddressUtxosInterceptors() -> [ServerInterceptor<GetAddressUtxosArg, GetAddressUtxosReplyList>]
/// - Returns: Interceptors to use when handling 'getAddressUtxosStream'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetAddressUtxosStreamInterceptors() -> [ServerInterceptor<GetAddressUtxosArg, GetAddressUtxosReply>]
/// - Returns: Interceptors to use when handling 'getLightdInfo'.
/// Defaults to calling `self.makeInterceptors()`.
func makeGetLightdInfoInterceptors() -> [ServerInterceptor<Empty, LightdInfo>]
/// - Returns: Interceptors to use when handling 'ping'.
/// Defaults to calling `self.makeInterceptors()`.
func makePingInterceptors() -> [ServerInterceptor<Duration, PingResponse>]
}
internal enum CompactTxStreamerServerMetadata {
internal static let serviceDescriptor = GRPCServiceDescriptor(
name: "CompactTxStreamer",
fullName: "cash.z.wallet.sdk.rpc.CompactTxStreamer",
methods: [
CompactTxStreamerServerMetadata.Methods.getLatestBlock,
CompactTxStreamerServerMetadata.Methods.getBlock,
CompactTxStreamerServerMetadata.Methods.getBlockNullifiers,
CompactTxStreamerServerMetadata.Methods.getBlockRange,
CompactTxStreamerServerMetadata.Methods.getBlockRangeNullifiers,
CompactTxStreamerServerMetadata.Methods.getTransaction,
CompactTxStreamerServerMetadata.Methods.sendTransaction,
CompactTxStreamerServerMetadata.Methods.getTaddressTxids,
CompactTxStreamerServerMetadata.Methods.getTaddressBalance,
CompactTxStreamerServerMetadata.Methods.getTaddressBalanceStream,
CompactTxStreamerServerMetadata.Methods.getMempoolTx,
CompactTxStreamerServerMetadata.Methods.getMempoolStream,
CompactTxStreamerServerMetadata.Methods.getTreeState,
CompactTxStreamerServerMetadata.Methods.getLatestTreeState,
CompactTxStreamerServerMetadata.Methods.getSubtreeRoots,
CompactTxStreamerServerMetadata.Methods.getAddressUtxos,
CompactTxStreamerServerMetadata.Methods.getAddressUtxosStream,
CompactTxStreamerServerMetadata.Methods.getLightdInfo,
CompactTxStreamerServerMetadata.Methods.ping,
]
)
internal enum Methods {
internal static let getLatestBlock = GRPCMethodDescriptor(
name: "GetLatestBlock",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestBlock",
type: GRPCCallType.unary
)
internal static let getBlock = GRPCMethodDescriptor(
name: "GetBlock",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlock",
type: GRPCCallType.unary
)
internal static let getBlockNullifiers = GRPCMethodDescriptor(
name: "GetBlockNullifiers",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockNullifiers",
type: GRPCCallType.unary
)
internal static let getBlockRange = GRPCMethodDescriptor(
name: "GetBlockRange",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRange",
type: GRPCCallType.serverStreaming
)
internal static let getBlockRangeNullifiers = GRPCMethodDescriptor(
name: "GetBlockRangeNullifiers",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRangeNullifiers",
type: GRPCCallType.serverStreaming
)
internal static let getTransaction = GRPCMethodDescriptor(
name: "GetTransaction",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTransaction",
type: GRPCCallType.unary
)
internal static let sendTransaction = GRPCMethodDescriptor(
name: "SendTransaction",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/SendTransaction",
type: GRPCCallType.unary
)
internal static let getTaddressTxids = GRPCMethodDescriptor(
name: "GetTaddressTxids",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressTxids",
type: GRPCCallType.serverStreaming
)
internal static let getTaddressBalance = GRPCMethodDescriptor(
name: "GetTaddressBalance",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalance",
type: GRPCCallType.unary
)
internal static let getTaddressBalanceStream = GRPCMethodDescriptor(
name: "GetTaddressBalanceStream",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalanceStream",
type: GRPCCallType.clientStreaming
)
internal static let getMempoolTx = GRPCMethodDescriptor(
name: "GetMempoolTx",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolTx",
type: GRPCCallType.serverStreaming
)
internal static let getMempoolStream = GRPCMethodDescriptor(
name: "GetMempoolStream",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolStream",
type: GRPCCallType.serverStreaming
)
internal static let getTreeState = GRPCMethodDescriptor(
name: "GetTreeState",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTreeState",
type: GRPCCallType.unary
)
internal static let getLatestTreeState = GRPCMethodDescriptor(
name: "GetLatestTreeState",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestTreeState",
type: GRPCCallType.unary
)
internal static let getSubtreeRoots = GRPCMethodDescriptor(
name: "GetSubtreeRoots",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetSubtreeRoots",
type: GRPCCallType.serverStreaming
)
internal static let getAddressUtxos = GRPCMethodDescriptor(
name: "GetAddressUtxos",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxos",
type: GRPCCallType.unary
)
internal static let getAddressUtxosStream = GRPCMethodDescriptor(
name: "GetAddressUtxosStream",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxosStream",
type: GRPCCallType.serverStreaming
)
internal static let getLightdInfo = GRPCMethodDescriptor(
name: "GetLightdInfo",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo",
type: GRPCCallType.unary
)
internal static let ping = GRPCMethodDescriptor(
name: "Ping",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/Ping",
type: GRPCCallType.unary
)
}
}

View File

@ -56,7 +56,7 @@ enum ShieldedProtocol: SwiftProtobuf.Enum {
extension ShieldedProtocol: CaseIterable {
// The compiler won't synthesize support with the UNRECOGNIZED case.
static var allCases: [ShieldedProtocol] = [
static let allCases: [ShieldedProtocol] = [
.sapling,
.orchard,
]
@ -144,7 +144,7 @@ struct TxFilter {
fileprivate var _block: BlockID? = nil
}
/// RawTransaction contains the complete transaction data. It also optionally includes
/// RawTransaction contains the complete transaction data. It also optionally includes
/// the block height in which the transaction was included, or, when returned
/// by GetMempoolStream(), the latest block height.
struct RawTransaction {

View File

@ -190,6 +190,10 @@ class DarksideWalletService: LightWalletService {
func getSubtreeRoots(_ request: ZcashLightClientKit.GetSubtreeRootsArg) -> AsyncThrowingStream<ZcashLightClientKit.SubtreeRoot, Error> {
service.getSubtreeRoots(request)
}
func setSubtreeRoots(_ request: DarksideSubtreeRoots) {
_ = darksideService.setSubtreeRoots(request)
}
}
enum DarksideWalletDConstants: NetworkConstants {

View File

@ -15,14 +15,14 @@ enum FakeChainBuilderError: Error {
enum FakeChainBuilder {
static let someOtherTxUrl = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/transactions/t-shielded-spend.txt"
static let txMainnetBlockUrl = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/basic-reorg/663150.txt"
static let testnetCanopyUpdateUrl = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/testnet-canopy/1028400-1028600.txt"
static let testnetCanopyStartBlock = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/testnet-canopy/1013250.txt"
static let testnetPreCanopyTx = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/testnet-canopy/pre-activation-txs/61088726aaa7c25b0568dd7bf19955f4a57f7173034e720c924107ff05cd3649.txt"
static let testnetPostCanopyTx = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/testnet-canopy/post-activation-txs/ecaa6c03709d70aa25446a81690b18ddb11daac96a03fe4b5cfd0d89a49fb963.txt"
static func buildSingleNoteChain(darksideWallet: DarksideWalletService, branchID: String, chainName: String) throws {
try darksideWallet.reset(
saplingActivation: 663150,
@ -31,14 +31,14 @@ enum FakeChainBuilder {
branchID: branchID,
chainName: chainName
)
try darksideWallet.useDataset(from: txMainnetBlockUrl)
try darksideWallet.stageBlocksCreate(from: 663151, count: 100)
try darksideWallet.stageTransaction(from: txUrls[663174]!, at: 663174)
}
static func buildChain(darksideWallet: DarksideWalletService, branchID: String, chainName: String) throws {
try darksideWallet.reset(
saplingActivation: 663150,
@ -47,16 +47,18 @@ enum FakeChainBuilder {
branchID: branchID,
chainName: chainName
)
try darksideWallet.useDataset(from: txMainnetBlockUrl)
try darksideWallet.stageBlocksCreate(from: 663151, count: 100)
try darksideWallet.stageTransaction(from: txUrls[663174]!, at: 663174)
try darksideWallet.stageTransaction(from: txUrls[663188]!, at: 663188)
try setSubTreeRoots(service: darksideWallet)
}
static func buildChainWithTxsFarFromEachOther(darksideWallet: DarksideWalletService, branchID: String, chainName: String, length: Int) throws {
try darksideWallet.reset(
saplingActivation: 663150,
@ -65,16 +67,16 @@ enum FakeChainBuilder {
branchID: branchID,
chainName: chainName
)
try darksideWallet.useDataset(from: txMainnetBlockUrl)
try darksideWallet.stageBlocksCreate(from: 663151, count: length)
try darksideWallet.stageTransaction(from: txUrls[663188]!, at: 663188)
try darksideWallet.stageTransaction(from: txUrls[663974]!, at: 663974)
}
static func buildChain(darksideWallet: DarksideWalletService, branchID: String, chainName: String, length: Int) throws {
try darksideWallet.reset(
saplingActivation: 663150,
@ -83,20 +85,20 @@ enum FakeChainBuilder {
branchID: branchID,
chainName: chainName
)
try darksideWallet.useDataset(from: txMainnetBlockUrl)
try darksideWallet.stageBlocksCreate(from: 663151, count: length)
try darksideWallet.stageTransaction(from: txUrls[663174]!, at: 663174)
try darksideWallet.stageTransaction(from: txUrls[663188]!, at: 663188)
try darksideWallet.stageTransaction(from: txUrls[663202]!, at: 663202)
try darksideWallet.stageTransaction(from: txUrls[663218]!, at: 663218)
try darksideWallet.stageTransaction(from: txUrls[663229]!, at: 663229)
try darksideWallet.stageTransaction(from: txUrls[663953]!, at: 663953)
try darksideWallet.stageTransaction(from: txUrls[663974]!, at: 663974)
}
static func buildChain(
darksideWallet: DarksideWalletService,
birthday: BlockHeight,
@ -119,7 +121,7 @@ enum FakeChainBuilder {
try darksideWallet.stageBlocksCreate(from: birthday + 1, count: length)
try darksideWallet.stageTransaction(from: testnetPreCanopyTx, at: networkActivationHeight - ZcashSDK.expiryOffset)
}
static func buildChainPostActivationFunds(darksideWallet: DarksideWalletService, birthday: BlockHeight, startSaplingTreeSize: UInt32, startOrchardTreeSize: UInt32, networkActivationHeight: BlockHeight, length: Int) throws {
try darksideWallet.reset(
saplingActivation: birthday,
@ -133,7 +135,7 @@ enum FakeChainBuilder {
try darksideWallet.stageBlocksCreate(from: birthday + 1, count: length)
try darksideWallet.stageTransaction(from: testnetPostCanopyTx, at: networkActivationHeight + 1)
}
static func buildChainMixedFunds(
darksideWallet: DarksideWalletService,
birthday: BlockHeight,
@ -154,14 +156,14 @@ enum FakeChainBuilder {
chainName: chainName,
length: length
)
try darksideWallet.stageTransaction(from: testnetPostCanopyTx, at: networkActivationHeight + ZcashSDK.expiryOffset)
}
static func buildTxUrl(for id: String) -> String {
"https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/transactions/recv/\(id).txt"
}
static let txUrls = [
663174: buildTxUrl(for: "8f064d23c66dc36e32445e5f3b50e0f32ac3ddb78cff21fb521eb6c19c07c99a"),
663188: buildTxUrl(for: "15a677b6770c5505fb47439361d3d3a7c21238ee1a6874fdedad18ae96850590"),
@ -244,4 +246,34 @@ enum FakeChainBuilder {
822410: buildTxUrl(for: "f3f8684be8d77367d099a38f30e3652410cdebe35c006d0599d86d8ec640867f"),
828933: buildTxUrl(for: "1fd394257d1c10c8a70fb760cf73f6d0e96e61edcf1ffca6da12d733a59221a4")
]
static func setSubTreeRoots(service: DarksideWalletService) throws {
let subtreeRoots = try DarksideSubtreeRoots.with { subtreeRoots in
subtreeRoots.shieldedProtocol = .sapling
subtreeRoots.startIndex = 0
subtreeRoots.subtreeRoots = [
try .init(
jsonString:
"""
{
"rootHash": "dUu1k+pC0jGn3fNnZA8Ju/WdwA8sHSADzDQODAFrWxM=",
"completingBlockHash": "AAAAAACPmsBjbYHceVyw9Ulab9B06BWhnhmfDaSRUf4=",
"completingBlockHeight": "558822"
}
"""
),
try .init(
jsonString:
"""
{
"rootHash": "A2VMPqy7m5PhIs9td7YG6uKWEPTzikd5hTaBl/1o4C0=",
"completingBlockHash": "AAAAAAIFzQaAI1LPzYkhgVvQqdc+ta/D7AnzXHGARqk=",
"completingBlockHeight": "670209"
}
"""
)
]
}
service.setSubtreeRoots(subtreeRoots)
}
}

View File

@ -89,6 +89,11 @@ internal protocol DarksideStreamerClientProtocol: GRPCClient {
_ request: Empty,
callOptions: CallOptions?
) -> UnaryCall<Empty, Empty>
func setSubtreeRoots(
_ request: DarksideSubtreeRoots,
callOptions: CallOptions?
) -> UnaryCall<DarksideSubtreeRoots, Empty>
}
extension DarksideStreamerClientProtocol {
@ -391,6 +396,25 @@ extension DarksideStreamerClientProtocol {
interceptors: self.interceptors?.makeClearAllTreeStatesInterceptors() ?? []
)
}
/// Sets the subtree roots cache (for GetSubtreeRoots),
/// replacing any existing entries
///
/// - Parameters:
/// - request: Request to send to SetSubtreeRoots.
/// - callOptions: Call options.
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
internal func setSubtreeRoots(
_ request: DarksideSubtreeRoots,
callOptions: CallOptions? = nil
) -> UnaryCall<DarksideSubtreeRoots, Empty> {
return self.makeUnaryCall(
path: DarksideStreamerClientMetadata.Methods.setSubtreeRoots.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeSetSubtreeRootsInterceptors() ?? []
)
}
}
@available(*, deprecated)
@ -526,6 +550,11 @@ internal protocol DarksideStreamerAsyncClientProtocol: GRPCClient {
_ request: Empty,
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<Empty, Empty>
func makeSetSubtreeRootsCall(
_ request: DarksideSubtreeRoots,
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<DarksideSubtreeRoots, Empty>
}
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
@ -701,6 +730,18 @@ extension DarksideStreamerAsyncClientProtocol {
interceptors: self.interceptors?.makeClearAllTreeStatesInterceptors() ?? []
)
}
internal func makeSetSubtreeRootsCall(
_ request: DarksideSubtreeRoots,
callOptions: CallOptions? = nil
) -> GRPCAsyncUnaryCall<DarksideSubtreeRoots, Empty> {
return self.makeAsyncUnaryCall(
path: DarksideStreamerClientMetadata.Methods.setSubtreeRoots.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeSetSubtreeRootsInterceptors() ?? []
)
}
}
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
@ -896,6 +937,18 @@ extension DarksideStreamerAsyncClientProtocol {
interceptors: self.interceptors?.makeClearAllTreeStatesInterceptors() ?? []
)
}
internal func setSubtreeRoots(
_ request: DarksideSubtreeRoots,
callOptions: CallOptions? = nil
) async throws -> Empty {
return try await self.performAsyncUnaryCall(
path: DarksideStreamerClientMetadata.Methods.setSubtreeRoots.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeSetSubtreeRootsInterceptors() ?? []
)
}
}
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
@ -958,6 +1011,9 @@ internal protocol DarksideStreamerClientInterceptorFactoryProtocol: Sendable {
/// - Returns: Interceptors to use when invoking 'clearAllTreeStates'.
func makeClearAllTreeStatesInterceptors() -> [ClientInterceptor<Empty, Empty>]
/// - Returns: Interceptors to use when invoking 'setSubtreeRoots'.
func makeSetSubtreeRootsInterceptors() -> [ClientInterceptor<DarksideSubtreeRoots, Empty>]
}
internal enum DarksideStreamerClientMetadata {
@ -979,6 +1035,7 @@ internal enum DarksideStreamerClientMetadata {
DarksideStreamerClientMetadata.Methods.addTreeState,
DarksideStreamerClientMetadata.Methods.removeTreeState,
DarksideStreamerClientMetadata.Methods.clearAllTreeStates,
DarksideStreamerClientMetadata.Methods.setSubtreeRoots,
]
)
@ -1066,6 +1123,12 @@ internal enum DarksideStreamerClientMetadata {
path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/ClearAllTreeStates",
type: GRPCCallType.unary
)
internal static let setSubtreeRoots = GRPCMethodDescriptor(
name: "SetSubtreeRoots",
path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/SetSubtreeRoots",
type: GRPCCallType.unary
)
}
}
@ -1160,6 +1223,10 @@ internal protocol DarksideStreamerProvider: CallHandlerProvider {
/// Clear the list of GetTreeStates entries (can't fail)
func clearAllTreeStates(request: Empty, context: StatusOnlyCallContext) -> EventLoopFuture<Empty>
/// Sets the subtree roots cache (for GetSubtreeRoots),
/// replacing any existing entries
func setSubtreeRoots(request: DarksideSubtreeRoots, context: StatusOnlyCallContext) -> EventLoopFuture<Empty>
}
extension DarksideStreamerProvider {
@ -1300,6 +1367,15 @@ extension DarksideStreamerProvider {
userFunction: self.clearAllTreeStates(request:context:)
)
case "SetSubtreeRoots":
return UnaryServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<DarksideSubtreeRoots>(),
responseSerializer: ProtobufSerializer<Empty>(),
interceptors: self.interceptors?.makeSetSubtreeRootsInterceptors() ?? [],
userFunction: self.setSubtreeRoots(request:context:)
)
default:
return nil
}
@ -1442,6 +1518,13 @@ internal protocol DarksideStreamerAsyncProvider: CallHandlerProvider, Sendable {
request: Empty,
context: GRPCAsyncServerCallContext
) async throws -> Empty
/// Sets the subtree roots cache (for GetSubtreeRoots),
/// replacing any existing entries
func setSubtreeRoots(
request: DarksideSubtreeRoots,
context: GRPCAsyncServerCallContext
) async throws -> Empty
}
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
@ -1589,6 +1672,15 @@ extension DarksideStreamerAsyncProvider {
wrapping: { try await self.clearAllTreeStates(request: $0, context: $1) }
)
case "SetSubtreeRoots":
return GRPCAsyncServerHandler(
context: context,
requestDeserializer: ProtobufDeserializer<DarksideSubtreeRoots>(),
responseSerializer: ProtobufSerializer<Empty>(),
interceptors: self.interceptors?.makeSetSubtreeRootsInterceptors() ?? [],
wrapping: { try await self.setSubtreeRoots(request: $0, context: $1) }
)
default:
return nil
}
@ -1652,6 +1744,10 @@ internal protocol DarksideStreamerServerInterceptorFactoryProtocol: Sendable {
/// - Returns: Interceptors to use when handling 'clearAllTreeStates'.
/// Defaults to calling `self.makeInterceptors()`.
func makeClearAllTreeStatesInterceptors() -> [ServerInterceptor<Empty, Empty>]
/// - Returns: Interceptors to use when handling 'setSubtreeRoots'.
/// Defaults to calling `self.makeInterceptors()`.
func makeSetSubtreeRootsInterceptors() -> [ServerInterceptor<DarksideSubtreeRoots, Empty>]
}
internal enum DarksideStreamerServerMetadata {
@ -1673,6 +1769,7 @@ internal enum DarksideStreamerServerMetadata {
DarksideStreamerServerMetadata.Methods.addTreeState,
DarksideStreamerServerMetadata.Methods.removeTreeState,
DarksideStreamerServerMetadata.Methods.clearAllTreeStates,
DarksideStreamerServerMetadata.Methods.setSubtreeRoots,
]
)
@ -1760,5 +1857,11 @@ internal enum DarksideStreamerServerMetadata {
path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/ClearAllTreeStates",
type: GRPCCallType.unary
)
internal static let setSubtreeRoots = GRPCMethodDescriptor(
name: "SetSubtreeRoots",
path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/SetSubtreeRoots",
type: GRPCCallType.unary
)
}
}

View File

@ -13,7 +13,7 @@
import Foundation
import SwiftProtobuf
@testable import ZcashLightClientKit
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
@ -116,6 +116,22 @@ struct DarksideEmptyBlocks {
init() {}
}
struct DarksideSubtreeRoots {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var shieldedProtocol: ShieldedProtocol = .sapling
var startIndex: UInt32 = 0
var subtreeRoots: [SubtreeRoot] = []
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
#if swift(>=5.5) && canImport(_Concurrency)
extension DarksideMetaState: @unchecked Sendable {}
extension DarksideBlock: @unchecked Sendable {}
@ -123,6 +139,7 @@ extension DarksideBlocksURL: @unchecked Sendable {}
extension DarksideTransactionsURL: @unchecked Sendable {}
extension DarksideHeight: @unchecked Sendable {}
extension DarksideEmptyBlocks: @unchecked Sendable {}
extension DarksideSubtreeRoots: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
@ -362,3 +379,47 @@ extension DarksideEmptyBlocks: SwiftProtobuf.Message, SwiftProtobuf._MessageImpl
return true
}
}
extension DarksideSubtreeRoots: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".DarksideSubtreeRoots"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "shieldedProtocol"),
2: .same(proto: "startIndex"),
3: .same(proto: "subtreeRoots"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularEnumField(value: &self.shieldedProtocol) }()
case 2: try { try decoder.decodeSingularUInt32Field(value: &self.startIndex) }()
case 3: try { try decoder.decodeRepeatedMessageField(value: &self.subtreeRoots) }()
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.shieldedProtocol != .sapling {
try visitor.visitSingularEnumField(value: self.shieldedProtocol, fieldNumber: 1)
}
if self.startIndex != 0 {
try visitor.visitSingularUInt32Field(value: self.startIndex, fieldNumber: 2)
}
if !self.subtreeRoots.isEmpty {
try visitor.visitRepeatedMessageField(value: self.subtreeRoots, fieldNumber: 3)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: DarksideSubtreeRoots, rhs: DarksideSubtreeRoots) -> Bool {
if lhs.shieldedProtocol != rhs.shieldedProtocol {return false}
if lhs.startIndex != rhs.startIndex {return false}
if lhs.subtreeRoots != rhs.subtreeRoots {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -45,6 +45,12 @@ message DarksideEmptyBlocks {
int32 count = 3;
}
message DarksideSubtreeRoots {
ShieldedProtocol shieldedProtocol = 1;
uint32 startIndex = 2;
repeated SubtreeRoot subtreeRoots = 3;
}
// Darksidewalletd maintains two staging areas, blocks and transactions. The
// Stage*() gRPCs add items to the staging area; ApplyStaged() "applies" everything
// in the staging area to the working (operational) state that the mock zcashd
@ -132,4 +138,8 @@ service DarksideStreamer {
// Clear the list of GetTreeStates entries (can't fail)
rpc ClearAllTreeStates(Empty) returns (Empty) {}
// Sets the subtree roots cache (for GetSubtreeRoots),
// replacing any existing entries
rpc SetSubtreeRoots(DarksideSubtreeRoots) returns (Empty) {}
}