From 0bc33addf0a9aabb59aa81ad09d315008c499613 Mon Sep 17 00:00:00 2001 From: Lukas Korba Date: Wed, 19 Jul 2023 08:15:26 +0200 Subject: [PATCH] [#1157] Update proto files - compact_formats, service and Darkside proto files updated - swift files generated --- .../GRPC/ProtoBuf/compact_formats.pb.swift | 196 ++++- .../GRPC/ProtoBuf/proto/compact_formats.proto | 46 +- .../Service/GRPC/ProtoBuf/proto/service.proto | 38 +- .../Service/GRPC/ProtoBuf/service.grpc.swift | 281 +++++- .../Service/GRPC/ProtoBuf/service.pb.swift | 200 ++++- Tests/TestUtils/DarkSideWalletService.swift | 6 +- Tests/TestUtils/proto/darkside.grpc.swift | 819 +++++++++++++++++- Tests/TestUtils/proto/darkside.pb.swift | 49 +- Tests/TestUtils/proto/darkside.proto | 9 + 9 files changed, 1492 insertions(+), 152 deletions(-) diff --git a/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/compact_formats.pb.swift b/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/compact_formats.pb.swift index 86bb2b07..6e6876ea 100644 --- a/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/compact_formats.pb.swift +++ b/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/compact_formats.pb.swift @@ -7,7 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ -// Copyright (c) 2019-2020 The Zcash developers +// Copyright (c) 2019-2021 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -24,6 +24,23 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP typealias Version = _2 } +/// ChainMetadata represents information about the state of the chain as of a given block. +struct ChainMetadata { + // 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. + + /// the size of the Sapling note commitment tree as of the end of this block + var saplingCommitmentTreeSize: UInt32 = 0 + + /// the size of the Orchard note commitment tree as of the end of this block + var orchardCommitmentTreeSize: UInt32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + /// CompactBlock is a packaging of ONLY the data from a block that's needed to: /// 1. Detect a payment to your shielded Sapling address /// 2. Detect a spend of your shielded Sapling notes @@ -40,23 +57,35 @@ struct CompactBlock { var height: UInt64 = 0 /// the ID (hash) of this block, same as in block explorers - var hash: Data = SwiftProtobuf.Internal.emptyData + var hash: Data = Data() /// the ID (hash) of this block's predecessor - var prevHash: Data = SwiftProtobuf.Internal.emptyData + var prevHash: Data = Data() /// Unix epoch time when the block was mined var time: UInt32 = 0 /// (hash, prevHash, and time) OR (full header) - var header: Data = SwiftProtobuf.Internal.emptyData + var header: Data = Data() /// zero or more compact transactions from this block var vtx: [CompactTx] = [] + /// information about the state of the chain as of this block + var chainMetadata: ChainMetadata { + get {return _chainMetadata ?? ChainMetadata()} + set {_chainMetadata = newValue} + } + /// Returns true if `chainMetadata` has been explicitly set. + var hasChainMetadata: Bool {return self._chainMetadata != nil} + /// Clears the value of `chainMetadata`. Subsequent reads from it will return its default value. + mutating func clearChainMetadata() {self._chainMetadata = nil} + var unknownFields = SwiftProtobuf.UnknownStorage() init() {} + + fileprivate var _chainMetadata: ChainMetadata? = nil } /// CompactTx contains the minimum information for a wallet to know if this transaction @@ -67,23 +96,23 @@ struct CompactTx { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. - /// the index within the full block + /// Index and hash will allow the receiver to call out to chain + /// explorers or other data structures to retrieve more information + /// about this transaction. var index: UInt64 = 0 /// the ID (hash) of this transaction, same as in block explorers - var hash: Data = SwiftProtobuf.Internal.emptyData + var hash: Data = Data() /// The transaction fee: present if server can provide. In the case of a /// stateless server and a transaction with transparent inputs, this will be /// unset because the calculation requires reference to prior transactions. - /// in a pure-Sapling context, the fee will be calculable as: - /// valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut)) + /// If there are no transparent inputs, the fee will be calculable as: + /// valueBalanceSapling + valueBalanceOrchard + sum(vPubNew) - sum(vPubOld) - sum(tOut) var fee: UInt32 = 0 - /// inputs var spends: [CompactSaplingSpend] = [] - /// outputs var outputs: [CompactSaplingOutput] = [] var actions: [CompactOrchardAction] = [] @@ -101,28 +130,31 @@ struct CompactSaplingSpend { // methods supported on all messages. /// nullifier (see the Zcash protocol specification) - var nf: Data = SwiftProtobuf.Internal.emptyData + var nf: Data = Data() var unknownFields = SwiftProtobuf.UnknownStorage() init() {} } -/// output is a Sapling Output Description as described in section 7.4 of the -/// Zcash protocol spec. Total size is 948. +/// output encodes the `cmu` field, `ephemeralKey` field, and a 52-byte prefix of the +/// `encCiphertext` field of a Sapling Output Description. These fields are described in +/// section 7.4 of the Zcash protocol spec: +/// https://zips.z.cash/protocol/protocol.pdf#outputencodingandconsensus +/// Total size is 116 bytes. struct CompactSaplingOutput { // 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. /// note commitment u-coordinate - var cmu: Data = SwiftProtobuf.Internal.emptyData + var cmu: Data = Data() /// ephemeral public key - var epk: Data = SwiftProtobuf.Internal.emptyData + var ephemeralKey: Data = Data() /// first 52 bytes of ciphertext - var ciphertext: Data = SwiftProtobuf.Internal.emptyData + var ciphertext: Data = Data() var unknownFields = SwiftProtobuf.UnknownStorage() @@ -137,26 +169,73 @@ struct CompactOrchardAction { // methods supported on all messages. /// [32] The nullifier of the input note - var nullifier: Data = SwiftProtobuf.Internal.emptyData + var nullifier: Data = Data() /// [32] The x-coordinate of the note commitment for the output note - var cmx: Data = SwiftProtobuf.Internal.emptyData + var cmx: Data = Data() /// [32] An encoding of an ephemeral Pallas public key - var ephemeralKey: Data = SwiftProtobuf.Internal.emptyData + var ephemeralKey: Data = Data() - /// [52] The note plaintext component of the encCiphertext field - var ciphertext: Data = SwiftProtobuf.Internal.emptyData + /// [52] The first 52 bytes of the encCiphertext field + var ciphertext: Data = Data() var unknownFields = SwiftProtobuf.UnknownStorage() init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension ChainMetadata: @unchecked Sendable {} +extension CompactBlock: @unchecked Sendable {} +extension CompactTx: @unchecked Sendable {} +extension CompactSaplingSpend: @unchecked Sendable {} +extension CompactSaplingOutput: @unchecked Sendable {} +extension CompactOrchardAction: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "cash.z.wallet.sdk.rpc" +extension ChainMetadata: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".ChainMetadata" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "saplingCommitmentTreeSize"), + 2: .same(proto: "orchardCommitmentTreeSize"), + ] + + mutating func decodeMessage(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.decodeSingularUInt32Field(value: &self.saplingCommitmentTreeSize) }() + case 2: try { try decoder.decodeSingularUInt32Field(value: &self.orchardCommitmentTreeSize) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.saplingCommitmentTreeSize != 0 { + try visitor.visitSingularUInt32Field(value: self.saplingCommitmentTreeSize, fieldNumber: 1) + } + if self.orchardCommitmentTreeSize != 0 { + try visitor.visitSingularUInt32Field(value: self.orchardCommitmentTreeSize, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ChainMetadata, rhs: ChainMetadata) -> Bool { + if lhs.saplingCommitmentTreeSize != rhs.saplingCommitmentTreeSize {return false} + if lhs.orchardCommitmentTreeSize != rhs.orchardCommitmentTreeSize {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + extension CompactBlock: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { static let protoMessageName: String = _protobuf_package + ".CompactBlock" static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ @@ -167,24 +246,33 @@ extension CompactBlock: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat 5: .same(proto: "time"), 6: .same(proto: "header"), 7: .same(proto: "vtx"), + 8: .same(proto: "chainMetadata"), ] mutating func decodeMessage(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 decoder.decodeSingularUInt32Field(value: &self.protoVersion) - case 2: try decoder.decodeSingularUInt64Field(value: &self.height) - case 3: try decoder.decodeSingularBytesField(value: &self.hash) - case 4: try decoder.decodeSingularBytesField(value: &self.prevHash) - case 5: try decoder.decodeSingularUInt32Field(value: &self.time) - case 6: try decoder.decodeSingularBytesField(value: &self.header) - case 7: try decoder.decodeRepeatedMessageField(value: &self.vtx) + case 1: try { try decoder.decodeSingularUInt32Field(value: &self.protoVersion) }() + case 2: try { try decoder.decodeSingularUInt64Field(value: &self.height) }() + case 3: try { try decoder.decodeSingularBytesField(value: &self.hash) }() + case 4: try { try decoder.decodeSingularBytesField(value: &self.prevHash) }() + case 5: try { try decoder.decodeSingularUInt32Field(value: &self.time) }() + case 6: try { try decoder.decodeSingularBytesField(value: &self.header) }() + case 7: try { try decoder.decodeRepeatedMessageField(value: &self.vtx) }() + case 8: try { try decoder.decodeSingularMessageField(value: &self._chainMetadata) }() default: break } } } func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 if self.protoVersion != 0 { try visitor.visitSingularUInt32Field(value: self.protoVersion, fieldNumber: 1) } @@ -206,6 +294,9 @@ extension CompactBlock: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat if !self.vtx.isEmpty { try visitor.visitRepeatedMessageField(value: self.vtx, fieldNumber: 7) } + try { if let v = self._chainMetadata { + try visitor.visitSingularMessageField(value: v, fieldNumber: 8) + } }() try unknownFields.traverse(visitor: &visitor) } @@ -217,6 +308,7 @@ extension CompactBlock: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat if lhs.time != rhs.time {return false} if lhs.header != rhs.header {return false} if lhs.vtx != rhs.vtx {return false} + if lhs._chainMetadata != rhs._chainMetadata {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } @@ -235,13 +327,16 @@ extension CompactTx: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation mutating func decodeMessage(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 decoder.decodeSingularUInt64Field(value: &self.index) - case 2: try decoder.decodeSingularBytesField(value: &self.hash) - case 3: try decoder.decodeSingularUInt32Field(value: &self.fee) - case 4: try decoder.decodeRepeatedMessageField(value: &self.spends) - case 5: try decoder.decodeRepeatedMessageField(value: &self.outputs) - case 6: try decoder.decodeRepeatedMessageField(value: &self.actions) + case 1: try { try decoder.decodeSingularUInt64Field(value: &self.index) }() + case 2: try { try decoder.decodeSingularBytesField(value: &self.hash) }() + case 3: try { try decoder.decodeSingularUInt32Field(value: &self.fee) }() + case 4: try { try decoder.decodeRepeatedMessageField(value: &self.spends) }() + case 5: try { try decoder.decodeRepeatedMessageField(value: &self.outputs) }() + case 6: try { try decoder.decodeRepeatedMessageField(value: &self.actions) }() default: break } } @@ -289,8 +384,11 @@ extension CompactSaplingSpend: SwiftProtobuf.Message, SwiftProtobuf._MessageImpl mutating func decodeMessage(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 decoder.decodeSingularBytesField(value: &self.nf) + case 1: try { try decoder.decodeSingularBytesField(value: &self.nf) }() default: break } } @@ -314,16 +412,19 @@ extension CompactSaplingOutput: SwiftProtobuf.Message, SwiftProtobuf._MessageImp static let protoMessageName: String = _protobuf_package + ".CompactSaplingOutput" static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 1: .same(proto: "cmu"), - 2: .same(proto: "epk"), + 2: .same(proto: "ephemeralKey"), 3: .same(proto: "ciphertext"), ] mutating func decodeMessage(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 decoder.decodeSingularBytesField(value: &self.cmu) - case 2: try decoder.decodeSingularBytesField(value: &self.epk) - case 3: try decoder.decodeSingularBytesField(value: &self.ciphertext) + case 1: try { try decoder.decodeSingularBytesField(value: &self.cmu) }() + case 2: try { try decoder.decodeSingularBytesField(value: &self.ephemeralKey) }() + case 3: try { try decoder.decodeSingularBytesField(value: &self.ciphertext) }() default: break } } @@ -333,8 +434,8 @@ extension CompactSaplingOutput: SwiftProtobuf.Message, SwiftProtobuf._MessageImp if !self.cmu.isEmpty { try visitor.visitSingularBytesField(value: self.cmu, fieldNumber: 1) } - if !self.epk.isEmpty { - try visitor.visitSingularBytesField(value: self.epk, fieldNumber: 2) + if !self.ephemeralKey.isEmpty { + try visitor.visitSingularBytesField(value: self.ephemeralKey, fieldNumber: 2) } if !self.ciphertext.isEmpty { try visitor.visitSingularBytesField(value: self.ciphertext, fieldNumber: 3) @@ -344,7 +445,7 @@ extension CompactSaplingOutput: SwiftProtobuf.Message, SwiftProtobuf._MessageImp static func ==(lhs: CompactSaplingOutput, rhs: CompactSaplingOutput) -> Bool { if lhs.cmu != rhs.cmu {return false} - if lhs.epk != rhs.epk {return false} + if lhs.ephemeralKey != rhs.ephemeralKey {return false} if lhs.ciphertext != rhs.ciphertext {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true @@ -362,11 +463,14 @@ extension CompactOrchardAction: SwiftProtobuf.Message, SwiftProtobuf._MessageImp mutating func decodeMessage(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 decoder.decodeSingularBytesField(value: &self.nullifier) - case 2: try decoder.decodeSingularBytesField(value: &self.cmx) - case 3: try decoder.decodeSingularBytesField(value: &self.ephemeralKey) - case 4: try decoder.decodeSingularBytesField(value: &self.ciphertext) + case 1: try { try decoder.decodeSingularBytesField(value: &self.nullifier) }() + case 2: try { try decoder.decodeSingularBytesField(value: &self.cmx) }() + case 3: try { try decoder.decodeSingularBytesField(value: &self.ephemeralKey) }() + case 4: try { try decoder.decodeSingularBytesField(value: &self.ciphertext) }() default: break } } diff --git a/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/compact_formats.proto b/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/compact_formats.proto index f2129f2c..09df06d4 100644 --- a/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/compact_formats.proto +++ b/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/compact_formats.proto @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2020 The Zcash developers +// Copyright (c) 2019-2021 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -6,39 +6,50 @@ syntax = "proto3"; package cash.z.wallet.sdk.rpc; option go_package = "lightwalletd/walletrpc"; option swift_prefix = ""; + // Remember that proto3 fields are all optional. A field that is not present will be set to its zero value. // bytes fields of hashes are in canonical little-endian format. +// ChainMetadata represents information about the state of the chain as of a given block. +message ChainMetadata { + uint32 saplingCommitmentTreeSize = 1; // the size of the Sapling note commitment tree as of the end of this block + uint32 orchardCommitmentTreeSize = 2; // the size of the Orchard note commitment tree as of the end of this block +} + // CompactBlock is a packaging of ONLY the data from a block that's needed to: // 1. Detect a payment to your shielded Sapling address // 2. Detect a spend of your shielded Sapling notes // 3. Update your witnesses to generate new Sapling spend proofs. message CompactBlock { - uint32 protoVersion = 1; // the version of this wire format, for storage - uint64 height = 2; // the height of this block - bytes hash = 3; // the ID (hash) of this block, same as in block explorers - bytes prevHash = 4; // the ID (hash) of this block's predecessor - uint32 time = 5; // Unix epoch time when the block was mined - bytes header = 6; // (hash, prevHash, and time) OR (full header) - repeated CompactTx vtx = 7; // zero or more compact transactions from this block + uint32 protoVersion = 1; // the version of this wire format, for storage + uint64 height = 2; // the height of this block + bytes hash = 3; // the ID (hash) of this block, same as in block explorers + bytes prevHash = 4; // the ID (hash) of this block's predecessor + uint32 time = 5; // Unix epoch time when the block was mined + bytes header = 6; // (hash, prevHash, and time) OR (full header) + repeated CompactTx vtx = 7; // zero or more compact transactions from this block + ChainMetadata chainMetadata = 8; // information about the state of the chain as of this block } // CompactTx contains the minimum information for a wallet to know if this transaction // is relevant to it (either pays to it or spends from it) via shielded elements // only. This message will not encode a transparent-to-transparent transaction. message CompactTx { + // Index and hash will allow the receiver to call out to chain + // explorers or other data structures to retrieve more information + // about this transaction. uint64 index = 1; // the index within the full block bytes hash = 2; // the ID (hash) of this transaction, same as in block explorers // The transaction fee: present if server can provide. In the case of a // stateless server and a transaction with transparent inputs, this will be // unset because the calculation requires reference to prior transactions. - // in a pure-Sapling context, the fee will be calculable as: - // valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut)) + // If there are no transparent inputs, the fee will be calculable as: + // valueBalanceSapling + valueBalanceOrchard + sum(vPubNew) - sum(vPubOld) - sum(tOut) uint32 fee = 3; - repeated CompactSaplingSpend spends = 4; // inputs - repeated CompactSaplingOutput outputs = 5; // outputs + repeated CompactSaplingSpend spends = 4; + repeated CompactSaplingOutput outputs = 5; repeated CompactOrchardAction actions = 6; } @@ -48,11 +59,14 @@ message CompactSaplingSpend { bytes nf = 1; // nullifier (see the Zcash protocol specification) } -// output is a Sapling Output Description as described in section 7.4 of the -// Zcash protocol spec. Total size is 948. +// output encodes the `cmu` field, `ephemeralKey` field, and a 52-byte prefix of the +// `encCiphertext` field of a Sapling Output Description. These fields are described in +// section 7.4 of the Zcash protocol spec: +// https://zips.z.cash/protocol/protocol.pdf#outputencodingandconsensus +// Total size is 116 bytes. message CompactSaplingOutput { bytes cmu = 1; // note commitment u-coordinate - bytes epk = 2; // ephemeral public key + bytes ephemeralKey = 2; // ephemeral public key bytes ciphertext = 3; // first 52 bytes of ciphertext } @@ -62,5 +76,5 @@ message CompactOrchardAction { bytes nullifier = 1; // [32] The nullifier of the input note bytes cmx = 2; // [32] The x-coordinate of the note commitment for the output note bytes ephemeralKey = 3; // [32] An encoding of an ephemeral Pallas public key - bytes ciphertext = 4; // [52] The note plaintext component of the encCiphertext field + bytes ciphertext = 4; // [52] The first 52 bytes of the encCiphertext field } diff --git a/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/service.proto b/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/service.proto index 91d0ada1..c15a3ec9 100644 --- a/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/service.proto +++ b/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/proto/service.proto @@ -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 { @@ -110,11 +110,28 @@ message Exclude { // The TreeState is derived from the Zcash z_gettreestate rpc. message TreeState { - string network = 1; // "main" or "test" - uint64 height = 2; - string hash = 3; // block id - uint32 time = 4; // Unix epoch time when the block was mined - string tree = 5; // sapling commitment tree state + string network = 1; // "main" or "test" + uint64 height = 2; // block height + string hash = 3; // block id + uint32 time = 4; // Unix epoch time when the block was mined + string saplingTree = 5; // sapling commitment tree state + string orchardTree = 6; // orchard commitment tree state +} + +enum ShieldedProtocol { + sapling = 0; + orchard = 1; +} + +message GetSubtreeRootsArg { + uint32 startIndex = 1; // Index identifying where to start returning subtree roots + ShieldedProtocol shieldedProtocol = 2; // Shielded protocol to return subtree roots for + uint32 maxEntries = 3; // Maximum number of entries to return, or 0 for all entries. +} +message SubtreeRoot { + bytes rootHash = 2; // The 32-byte Merkle root of the subtree. + bytes completingBlockHash = 3; // The hash of the block that completed this subtree. + uint64 completingBlockHeight = 4; // The height of the block that completed this subtree in the main chain. } // Results are sorted by height, which makes it easy to issue another @@ -141,8 +158,12 @@ service CompactTxStreamer { rpc GetLatestBlock(ChainSpec) returns (BlockID) {} // Return the compact block corresponding to the given block identifier rpc GetBlock(BlockID) returns (CompactBlock) {} + // Same as GetBlock except actions contain only nullifiers + rpc GetBlockNullifiers(BlockID) returns (CompactBlock) {} // Return a list of consecutive compact blocks rpc GetBlockRange(BlockRange) returns (stream CompactBlock) {} + // Same as GetBlockRange except actions contain only nullifiers + rpc GetBlockRangeNullifiers(BlockRange) returns (stream CompactBlock) {} // Return the requested full (not compact) transaction (as from zcashd) rpc GetTransaction(TxFilter) returns (RawTransaction) {} @@ -174,6 +195,11 @@ service CompactTxStreamer { // values also (even though they can be obtained using GetBlock). // The block can be specified by either height or hash. 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. + rpc GetSubtreeRoots(GetSubtreeRootsArg) returns (stream SubtreeRoot) {} rpc GetAddressUtxos(GetAddressUtxosArg) returns (GetAddressUtxosReplyList) {} rpc GetAddressUtxosStream(GetAddressUtxosArg) returns (stream GetAddressUtxosReply) {} diff --git a/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.grpc.swift b/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.grpc.swift index d61e0bfe..1e18c03e 100644 --- a/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.grpc.swift +++ b/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.grpc.swift @@ -1,25 +1,10 @@ // // DO NOT EDIT. +// swift-format-ignore-file // // Generated by the protocol buffer compiler. // Source: service.proto // - -// -// Copyright 2018, gRPC Authors All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// import GRPC import NIO import NIOConcurrencyHelpers @@ -41,12 +26,23 @@ internal protocol CompactTxStreamerClientProtocol: GRPCClient { callOptions: CallOptions? ) -> UnaryCall + func getBlockNullifiers( + _ request: BlockID, + callOptions: CallOptions? + ) -> UnaryCall + func getBlockRange( _ request: BlockRange, callOptions: CallOptions?, handler: @escaping (CompactBlock) -> Void ) -> ServerStreamingCall + func getBlockRangeNullifiers( + _ request: BlockRange, + callOptions: CallOptions?, + handler: @escaping (CompactBlock) -> Void + ) -> ServerStreamingCall + func getTransaction( _ request: TxFilter, callOptions: CallOptions? @@ -89,6 +85,17 @@ internal protocol CompactTxStreamerClientProtocol: GRPCClient { callOptions: CallOptions? ) -> UnaryCall + func getLatestTreeState( + _ request: Empty, + callOptions: CallOptions? + ) -> UnaryCall + + func getSubtreeRoots( + _ request: GetSubtreeRootsArg, + callOptions: CallOptions?, + handler: @escaping (SubtreeRoot) -> Void + ) -> ServerStreamingCall + func getAddressUtxos( _ request: GetAddressUtxosArg, callOptions: CallOptions? @@ -152,6 +159,24 @@ extension CompactTxStreamerClientProtocol { ) } + /// Same as GetBlock except actions contain only nullifiers + /// + /// - Parameters: + /// - request: Request to send to GetBlockNullifiers. + /// - callOptions: Call options. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + internal func getBlockNullifiers( + _ request: BlockID, + callOptions: CallOptions? = nil + ) -> UnaryCall { + return self.makeUnaryCall( + path: CompactTxStreamerClientMetadata.Methods.getBlockNullifiers.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetBlockNullifiersInterceptors() ?? [] + ) + } + /// Return a list of consecutive compact blocks /// /// - Parameters: @@ -173,6 +198,27 @@ extension CompactTxStreamerClientProtocol { ) } + /// Same as GetBlockRange except actions contain only nullifiers + /// + /// - Parameters: + /// - request: Request to send to GetBlockRangeNullifiers. + /// - callOptions: Call options. + /// - handler: A closure called when each response is received from the server. + /// - Returns: A `ServerStreamingCall` with futures for the metadata and status. + internal func getBlockRangeNullifiers( + _ request: BlockRange, + callOptions: CallOptions? = nil, + handler: @escaping (CompactBlock) -> Void + ) -> ServerStreamingCall { + return self.makeServerStreamingCall( + path: CompactTxStreamerClientMetadata.Methods.getBlockRangeNullifiers.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetBlockRangeNullifiersInterceptors() ?? [], + handler: handler + ) + } + /// Return the requested full (not compact) transaction (as from zcashd) /// /// - Parameters: @@ -338,6 +384,46 @@ extension CompactTxStreamerClientProtocol { ) } + /// Unary call to GetLatestTreeState + /// + /// - Parameters: + /// - request: Request to send to GetLatestTreeState. + /// - callOptions: Call options. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + internal func getLatestTreeState( + _ request: Empty, + callOptions: CallOptions? = nil + ) -> UnaryCall { + return self.makeUnaryCall( + path: CompactTxStreamerClientMetadata.Methods.getLatestTreeState.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetLatestTreeStateInterceptors() ?? [] + ) + } + + /// Returns a stream of information about roots of subtrees of the Sapling and Orchard + /// note commitment trees. + /// + /// - Parameters: + /// - request: Request to send to GetSubtreeRoots. + /// - callOptions: Call options. + /// - handler: A closure called when each response is received from the server. + /// - Returns: A `ServerStreamingCall` with futures for the metadata and status. + internal func getSubtreeRoots( + _ request: GetSubtreeRootsArg, + callOptions: CallOptions? = nil, + handler: @escaping (SubtreeRoot) -> Void + ) -> ServerStreamingCall { + return self.makeServerStreamingCall( + path: CompactTxStreamerClientMetadata.Methods.getSubtreeRoots.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetSubtreeRootsInterceptors() ?? [], + handler: handler + ) + } + /// Unary call to GetAddressUtxos /// /// - Parameters: @@ -414,10 +500,8 @@ extension CompactTxStreamerClientProtocol { } } -#if compiler(>=5.6) @available(*, deprecated) extension CompactTxStreamerClient: @unchecked Sendable {} -#endif // compiler(>=5.6) @available(*, deprecated, renamed: "CompactTxStreamerNIOClient") internal final class CompactTxStreamerClient: CompactTxStreamerClientProtocol { @@ -473,7 +557,6 @@ internal struct CompactTxStreamerNIOClient: CompactTxStreamerClientProtocol { } } -#if compiler(>=5.6) @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) internal protocol CompactTxStreamerAsyncClientProtocol: GRPCClient { static var serviceDescriptor: GRPCServiceDescriptor { get } @@ -489,11 +572,21 @@ internal protocol CompactTxStreamerAsyncClientProtocol: GRPCClient { callOptions: CallOptions? ) -> GRPCAsyncUnaryCall + func makeGetBlockNullifiersCall( + _ request: BlockID, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall + func makeGetBlockRangeCall( _ request: BlockRange, callOptions: CallOptions? ) -> GRPCAsyncServerStreamingCall + func makeGetBlockRangeNullifiersCall( + _ request: BlockRange, + callOptions: CallOptions? + ) -> GRPCAsyncServerStreamingCall + func makeGetTransactionCall( _ request: TxFilter, callOptions: CallOptions? @@ -533,6 +626,16 @@ internal protocol CompactTxStreamerAsyncClientProtocol: GRPCClient { callOptions: CallOptions? ) -> GRPCAsyncUnaryCall + func makeGetLatestTreeStateCall( + _ request: Empty, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall + + func makeGetSubtreeRootsCall( + _ request: GetSubtreeRootsArg, + callOptions: CallOptions? + ) -> GRPCAsyncServerStreamingCall + func makeGetAddressUtxosCall( _ request: GetAddressUtxosArg, callOptions: CallOptions? @@ -588,6 +691,18 @@ extension CompactTxStreamerAsyncClientProtocol { ) } + internal func makeGetBlockNullifiersCall( + _ request: BlockID, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: CompactTxStreamerClientMetadata.Methods.getBlockNullifiers.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetBlockNullifiersInterceptors() ?? [] + ) + } + internal func makeGetBlockRangeCall( _ request: BlockRange, callOptions: CallOptions? = nil @@ -600,6 +715,18 @@ extension CompactTxStreamerAsyncClientProtocol { ) } + internal func makeGetBlockRangeNullifiersCall( + _ request: BlockRange, + callOptions: CallOptions? = nil + ) -> GRPCAsyncServerStreamingCall { + return self.makeAsyncServerStreamingCall( + path: CompactTxStreamerClientMetadata.Methods.getBlockRangeNullifiers.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetBlockRangeNullifiersInterceptors() ?? [] + ) + } + internal func makeGetTransactionCall( _ request: TxFilter, callOptions: CallOptions? = nil @@ -694,6 +821,30 @@ extension CompactTxStreamerAsyncClientProtocol { ) } + internal func makeGetLatestTreeStateCall( + _ request: Empty, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: CompactTxStreamerClientMetadata.Methods.getLatestTreeState.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetLatestTreeStateInterceptors() ?? [] + ) + } + + internal func makeGetSubtreeRootsCall( + _ request: GetSubtreeRootsArg, + callOptions: CallOptions? = nil + ) -> GRPCAsyncServerStreamingCall { + return self.makeAsyncServerStreamingCall( + path: CompactTxStreamerClientMetadata.Methods.getSubtreeRoots.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetSubtreeRootsInterceptors() ?? [] + ) + } + internal func makeGetAddressUtxosCall( _ request: GetAddressUtxosArg, callOptions: CallOptions? = nil @@ -769,6 +920,18 @@ extension CompactTxStreamerAsyncClientProtocol { ) } + internal func getBlockNullifiers( + _ request: BlockID, + callOptions: CallOptions? = nil + ) async throws -> CompactBlock { + return try await self.performAsyncUnaryCall( + path: CompactTxStreamerClientMetadata.Methods.getBlockNullifiers.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetBlockNullifiersInterceptors() ?? [] + ) + } + internal func getBlockRange( _ request: BlockRange, callOptions: CallOptions? = nil @@ -781,6 +944,18 @@ extension CompactTxStreamerAsyncClientProtocol { ) } + internal func getBlockRangeNullifiers( + _ request: BlockRange, + callOptions: CallOptions? = nil + ) -> GRPCAsyncResponseStream { + return self.performAsyncServerStreamingCall( + path: CompactTxStreamerClientMetadata.Methods.getBlockRangeNullifiers.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetBlockRangeNullifiersInterceptors() ?? [] + ) + } + internal func getTransaction( _ request: TxFilter, callOptions: CallOptions? = nil @@ -889,6 +1064,30 @@ extension CompactTxStreamerAsyncClientProtocol { ) } + internal func getLatestTreeState( + _ request: Empty, + callOptions: CallOptions? = nil + ) async throws -> TreeState { + return try await self.performAsyncUnaryCall( + path: CompactTxStreamerClientMetadata.Methods.getLatestTreeState.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetLatestTreeStateInterceptors() ?? [] + ) + } + + internal func getSubtreeRoots( + _ request: GetSubtreeRootsArg, + callOptions: CallOptions? = nil + ) -> GRPCAsyncResponseStream { + return self.performAsyncServerStreamingCall( + path: CompactTxStreamerClientMetadata.Methods.getSubtreeRoots.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetSubtreeRootsInterceptors() ?? [] + ) + } + internal func getAddressUtxos( _ request: GetAddressUtxosArg, callOptions: CallOptions? = nil @@ -955,9 +1154,7 @@ internal struct CompactTxStreamerAsyncClient: CompactTxStreamerAsyncClientProtoc } } -#endif // compiler(>=5.6) - -internal protocol CompactTxStreamerClientInterceptorFactoryProtocol: GRPCSendable { +internal protocol CompactTxStreamerClientInterceptorFactoryProtocol: Sendable { /// - Returns: Interceptors to use when invoking 'getLatestBlock'. func makeGetLatestBlockInterceptors() -> [ClientInterceptor] @@ -965,9 +1162,15 @@ internal protocol CompactTxStreamerClientInterceptorFactoryProtocol: GRPCSendabl /// - Returns: Interceptors to use when invoking 'getBlock'. func makeGetBlockInterceptors() -> [ClientInterceptor] + /// - Returns: Interceptors to use when invoking 'getBlockNullifiers'. + func makeGetBlockNullifiersInterceptors() -> [ClientInterceptor] + /// - Returns: Interceptors to use when invoking 'getBlockRange'. func makeGetBlockRangeInterceptors() -> [ClientInterceptor] + /// - Returns: Interceptors to use when invoking 'getBlockRangeNullifiers'. + func makeGetBlockRangeNullifiersInterceptors() -> [ClientInterceptor] + /// - Returns: Interceptors to use when invoking 'getTransaction'. func makeGetTransactionInterceptors() -> [ClientInterceptor] @@ -992,6 +1195,12 @@ internal protocol CompactTxStreamerClientInterceptorFactoryProtocol: GRPCSendabl /// - Returns: Interceptors to use when invoking 'getTreeState'. func makeGetTreeStateInterceptors() -> [ClientInterceptor] + /// - Returns: Interceptors to use when invoking 'getLatestTreeState'. + func makeGetLatestTreeStateInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'getSubtreeRoots'. + func makeGetSubtreeRootsInterceptors() -> [ClientInterceptor] + /// - Returns: Interceptors to use when invoking 'getAddressUtxos'. func makeGetAddressUtxosInterceptors() -> [ClientInterceptor] @@ -1012,7 +1221,9 @@ internal enum CompactTxStreamerClientMetadata { methods: [ CompactTxStreamerClientMetadata.Methods.getLatestBlock, CompactTxStreamerClientMetadata.Methods.getBlock, + CompactTxStreamerClientMetadata.Methods.getBlockNullifiers, CompactTxStreamerClientMetadata.Methods.getBlockRange, + CompactTxStreamerClientMetadata.Methods.getBlockRangeNullifiers, CompactTxStreamerClientMetadata.Methods.getTransaction, CompactTxStreamerClientMetadata.Methods.sendTransaction, CompactTxStreamerClientMetadata.Methods.getTaddressTxids, @@ -1021,6 +1232,8 @@ internal enum CompactTxStreamerClientMetadata { CompactTxStreamerClientMetadata.Methods.getMempoolTx, CompactTxStreamerClientMetadata.Methods.getMempoolStream, CompactTxStreamerClientMetadata.Methods.getTreeState, + CompactTxStreamerClientMetadata.Methods.getLatestTreeState, + CompactTxStreamerClientMetadata.Methods.getSubtreeRoots, CompactTxStreamerClientMetadata.Methods.getAddressUtxos, CompactTxStreamerClientMetadata.Methods.getAddressUtxosStream, CompactTxStreamerClientMetadata.Methods.getLightdInfo, @@ -1041,12 +1254,24 @@ internal enum CompactTxStreamerClientMetadata { 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", @@ -1095,6 +1320,18 @@ internal enum CompactTxStreamerClientMetadata { 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", diff --git a/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.pb.swift b/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.pb.swift index c5bc4caf..d54ba917 100644 --- a/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.pb.swift +++ b/Sources/ZcashLightClientKit/Modules/Service/GRPC/ProtoBuf/service.pb.swift @@ -24,6 +24,46 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP typealias Version = _2 } +enum ShieldedProtocol: SwiftProtobuf.Enum { + typealias RawValue = Int + case sapling // = 0 + case orchard // = 1 + case UNRECOGNIZED(Int) + + init() { + self = .sapling + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .sapling + case 1: self = .orchard + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .sapling: return 0 + case .orchard: return 1 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension ShieldedProtocol: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + static var allCases: [ShieldedProtocol] = [ + .sapling, + .orchard, + ] +} + +#endif // swift(>=4.2) + /// A BlockID message contains identifiers to select a block: a height or a /// hash. Specification by hash is not implemented, but may be in the future. struct BlockID { @@ -104,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 { @@ -326,6 +366,7 @@ struct TreeState { /// "main" or "test" var network: String = String() + /// block height var height: UInt64 = 0 /// block id @@ -335,7 +376,48 @@ struct TreeState { var time: UInt32 = 0 /// sapling commitment tree state - var tree: String = String() + var saplingTree: String = String() + + /// orchard commitment tree state + var orchardTree: String = String() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct GetSubtreeRootsArg { + // 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. + + /// Index identifying where to start returning subtree roots + var startIndex: UInt32 = 0 + + /// Shielded protocol to return subtree roots for + var shieldedProtocol: ShieldedProtocol = .sapling + + /// Maximum number of entries to return, or 0 for all entries. + var maxEntries: UInt32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct SubtreeRoot { + // 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. + + /// The 32-byte Merkle root of the subtree. + var rootHash: Data = Data() + + /// The hash of the block that completed this subtree. + var completingBlockHash: Data = Data() + + /// The height of the block that completed this subtree in the main chain. + var completingBlockHeight: UInt64 = 0 var unknownFields = SwiftProtobuf.UnknownStorage() @@ -396,6 +478,7 @@ struct GetAddressUtxosReplyList { } #if swift(>=5.5) && canImport(_Concurrency) +extension ShieldedProtocol: @unchecked Sendable {} extension BlockID: @unchecked Sendable {} extension BlockRange: @unchecked Sendable {} extension TxFilter: @unchecked Sendable {} @@ -412,6 +495,8 @@ extension AddressList: @unchecked Sendable {} extension Balance: @unchecked Sendable {} extension Exclude: @unchecked Sendable {} extension TreeState: @unchecked Sendable {} +extension GetSubtreeRootsArg: @unchecked Sendable {} +extension SubtreeRoot: @unchecked Sendable {} extension GetAddressUtxosArg: @unchecked Sendable {} extension GetAddressUtxosReply: @unchecked Sendable {} extension GetAddressUtxosReplyList: @unchecked Sendable {} @@ -421,6 +506,13 @@ extension GetAddressUtxosReplyList: @unchecked Sendable {} fileprivate let _protobuf_package = "cash.z.wallet.sdk.rpc" +extension ShieldedProtocol: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "sapling"), + 1: .same(proto: "orchard"), + ] +} + extension BlockID: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { static let protoMessageName: String = _protobuf_package + ".BlockID" static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ @@ -1020,7 +1112,8 @@ extension TreeState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation 2: .same(proto: "height"), 3: .same(proto: "hash"), 4: .same(proto: "time"), - 5: .same(proto: "tree"), + 5: .same(proto: "saplingTree"), + 6: .same(proto: "orchardTree"), ] mutating func decodeMessage(decoder: inout D) throws { @@ -1033,7 +1126,8 @@ extension TreeState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation case 2: try { try decoder.decodeSingularUInt64Field(value: &self.height) }() case 3: try { try decoder.decodeSingularStringField(value: &self.hash) }() case 4: try { try decoder.decodeSingularUInt32Field(value: &self.time) }() - case 5: try { try decoder.decodeSingularStringField(value: &self.tree) }() + case 5: try { try decoder.decodeSingularStringField(value: &self.saplingTree) }() + case 6: try { try decoder.decodeSingularStringField(value: &self.orchardTree) }() default: break } } @@ -1052,8 +1146,11 @@ extension TreeState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation if self.time != 0 { try visitor.visitSingularUInt32Field(value: self.time, fieldNumber: 4) } - if !self.tree.isEmpty { - try visitor.visitSingularStringField(value: self.tree, fieldNumber: 5) + if !self.saplingTree.isEmpty { + try visitor.visitSingularStringField(value: self.saplingTree, fieldNumber: 5) + } + if !self.orchardTree.isEmpty { + try visitor.visitSingularStringField(value: self.orchardTree, fieldNumber: 6) } try unknownFields.traverse(visitor: &visitor) } @@ -1063,7 +1160,96 @@ extension TreeState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation if lhs.height != rhs.height {return false} if lhs.hash != rhs.hash {return false} if lhs.time != rhs.time {return false} - if lhs.tree != rhs.tree {return false} + if lhs.saplingTree != rhs.saplingTree {return false} + if lhs.orchardTree != rhs.orchardTree {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension GetSubtreeRootsArg: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".GetSubtreeRootsArg" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "startIndex"), + 2: .same(proto: "shieldedProtocol"), + 3: .same(proto: "maxEntries"), + ] + + mutating func decodeMessage(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.decodeSingularUInt32Field(value: &self.startIndex) }() + case 2: try { try decoder.decodeSingularEnumField(value: &self.shieldedProtocol) }() + case 3: try { try decoder.decodeSingularUInt32Field(value: &self.maxEntries) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.startIndex != 0 { + try visitor.visitSingularUInt32Field(value: self.startIndex, fieldNumber: 1) + } + if self.shieldedProtocol != .sapling { + try visitor.visitSingularEnumField(value: self.shieldedProtocol, fieldNumber: 2) + } + if self.maxEntries != 0 { + try visitor.visitSingularUInt32Field(value: self.maxEntries, fieldNumber: 3) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: GetSubtreeRootsArg, rhs: GetSubtreeRootsArg) -> Bool { + if lhs.startIndex != rhs.startIndex {return false} + if lhs.shieldedProtocol != rhs.shieldedProtocol {return false} + if lhs.maxEntries != rhs.maxEntries {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension SubtreeRoot: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".SubtreeRoot" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 2: .same(proto: "rootHash"), + 3: .same(proto: "completingBlockHash"), + 4: .same(proto: "completingBlockHeight"), + ] + + mutating func decodeMessage(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 2: try { try decoder.decodeSingularBytesField(value: &self.rootHash) }() + case 3: try { try decoder.decodeSingularBytesField(value: &self.completingBlockHash) }() + case 4: try { try decoder.decodeSingularUInt64Field(value: &self.completingBlockHeight) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.rootHash.isEmpty { + try visitor.visitSingularBytesField(value: self.rootHash, fieldNumber: 2) + } + if !self.completingBlockHash.isEmpty { + try visitor.visitSingularBytesField(value: self.completingBlockHash, fieldNumber: 3) + } + if self.completingBlockHeight != 0 { + try visitor.visitSingularUInt64Field(value: self.completingBlockHeight, fieldNumber: 4) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: SubtreeRoot, rhs: SubtreeRoot) -> Bool { + if lhs.rootHash != rhs.rootHash {return false} + if lhs.completingBlockHash != rhs.completingBlockHash {return false} + if lhs.completingBlockHeight != rhs.completingBlockHeight {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } diff --git a/Tests/TestUtils/DarkSideWalletService.swift b/Tests/TestUtils/DarkSideWalletService.swift index 3730cbe4..8b655939 100644 --- a/Tests/TestUtils/DarkSideWalletService.swift +++ b/Tests/TestUtils/DarkSideWalletService.swift @@ -44,17 +44,17 @@ class DarksideWalletService: LightWalletService { } var channel: Channel var service: LightWalletService - var darksideService: DarksideStreamerClient + var darksideService: DarksideStreamerNIOClient init(endpoint: LightWalletEndpoint) { self.channel = ChannelProvider().channel(endpoint: endpoint) self.service = LightWalletServiceFactory(endpoint: endpoint).make() - self.darksideService = DarksideStreamerClient(channel: channel) + self.darksideService = DarksideStreamerNIOClient(channel: channel) } init(endpoint: LightWalletEndpoint, service: LightWalletService) { self.channel = ChannelProvider().channel(endpoint: endpoint) - self.darksideService = DarksideStreamerClient(channel: channel) + self.darksideService = DarksideStreamerNIOClient(channel: channel) self.service = service } diff --git a/Tests/TestUtils/proto/darkside.grpc.swift b/Tests/TestUtils/proto/darkside.grpc.swift index 266382d8..91d17962 100644 --- a/Tests/TestUtils/proto/darkside.grpc.swift +++ b/Tests/TestUtils/proto/darkside.grpc.swift @@ -1,32 +1,26 @@ // // DO NOT EDIT. +// swift-format-ignore-file // // Generated by the protocol buffer compiler. // Source: darkside.proto // - -// -// Copyright 2018, gRPC Authors All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// import GRPC import NIO +import NIOConcurrencyHelpers import SwiftProtobuf @testable import ZcashLightClientKit -/// Usage: instantiate DarksideStreamerClient, then call methods of this protocol to make API calls. +/// 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 +/// serves; transactions are placed into their corresponding blocks (by height). +/// +/// Usage: instantiate `DarksideStreamerClient`, then call methods of this protocol to make API calls. internal protocol DarksideStreamerClientProtocol: GRPCClient { + var serviceName: String { get } + var interceptors: DarksideStreamerClientInterceptorFactoryProtocol? { get } + func reset( _ request: DarksideMetaState, callOptions: CallOptions? @@ -81,9 +75,26 @@ internal protocol DarksideStreamerClientProtocol: GRPCClient { callOptions: CallOptions? ) -> UnaryCall + func addTreeState( + _ request: TreeState, + callOptions: CallOptions? + ) -> UnaryCall + + func removeTreeState( + _ request: BlockID, + callOptions: CallOptions? + ) -> UnaryCall + + func clearAllTreeStates( + _ request: Empty, + callOptions: CallOptions? + ) -> UnaryCall } extension DarksideStreamerClientProtocol { + internal var serviceName: String { + return "cash.z.wallet.sdk.rpc.DarksideStreamer" + } /// Reset reverts all darksidewalletd state (active block range, latest height, /// staged blocks and transactions) and lightwalletd state (cache) to empty, @@ -102,9 +113,10 @@ extension DarksideStreamerClientProtocol { callOptions: CallOptions? = nil ) -> UnaryCall { return self.makeUnaryCall( - path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/Reset", + path: DarksideStreamerClientMetadata.Methods.reset.path, request: request, - callOptions: callOptions ?? self.defaultCallOptions + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeResetInterceptors() ?? [] ) } @@ -122,8 +134,9 @@ extension DarksideStreamerClientProtocol { callOptions: CallOptions? = nil ) -> ClientStreamingCall { return self.makeClientStreamingCall( - path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocksStream", - callOptions: callOptions ?? self.defaultCallOptions + path: DarksideStreamerClientMetadata.Methods.stageBlocksStream.path, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageBlocksStreamInterceptors() ?? [] ) } @@ -139,9 +152,10 @@ extension DarksideStreamerClientProtocol { callOptions: CallOptions? = nil ) -> UnaryCall { return self.makeUnaryCall( - path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocks", + path: DarksideStreamerClientMetadata.Methods.stageBlocks.path, request: request, - callOptions: callOptions ?? self.defaultCallOptions + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageBlocksInterceptors() ?? [] ) } @@ -160,9 +174,10 @@ extension DarksideStreamerClientProtocol { callOptions: CallOptions? = nil ) -> UnaryCall { return self.makeUnaryCall( - path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocksCreate", + path: DarksideStreamerClientMetadata.Methods.stageBlocksCreate.path, request: request, - callOptions: callOptions ?? self.defaultCallOptions + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageBlocksCreateInterceptors() ?? [] ) } @@ -182,8 +197,9 @@ extension DarksideStreamerClientProtocol { callOptions: CallOptions? = nil ) -> ClientStreamingCall { return self.makeClientStreamingCall( - path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageTransactionsStream", - callOptions: callOptions ?? self.defaultCallOptions + path: DarksideStreamerClientMetadata.Methods.stageTransactionsStream.path, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageTransactionsStreamInterceptors() ?? [] ) } @@ -200,9 +216,10 @@ extension DarksideStreamerClientProtocol { callOptions: CallOptions? = nil ) -> UnaryCall { return self.makeUnaryCall( - path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageTransactions", + path: DarksideStreamerClientMetadata.Methods.stageTransactions.path, request: request, - callOptions: callOptions ?? self.defaultCallOptions + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageTransactionsInterceptors() ?? [] ) } @@ -232,9 +249,10 @@ extension DarksideStreamerClientProtocol { callOptions: CallOptions? = nil ) -> UnaryCall { return self.makeUnaryCall( - path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/ApplyStaged", + path: DarksideStreamerClientMetadata.Methods.applyStaged.path, request: request, - callOptions: callOptions ?? self.defaultCallOptions + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeApplyStagedInterceptors() ?? [] ) } @@ -257,9 +275,10 @@ extension DarksideStreamerClientProtocol { handler: @escaping (RawTransaction) -> Void ) -> ServerStreamingCall { return self.makeServerStreamingCall( - path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/GetIncomingTransactions", + path: DarksideStreamerClientMetadata.Methods.getIncomingTransactions.path, request: request, callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetIncomingTransactionsInterceptors() ?? [], handler: handler ) } @@ -275,9 +294,10 @@ extension DarksideStreamerClientProtocol { callOptions: CallOptions? = nil ) -> UnaryCall { return self.makeUnaryCall( - path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/ClearIncomingTransactions", + path: DarksideStreamerClientMetadata.Methods.clearIncomingTransactions.path, request: request, - callOptions: callOptions ?? self.defaultCallOptions + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeClearIncomingTransactionsInterceptors() ?? [] ) } @@ -293,9 +313,10 @@ extension DarksideStreamerClientProtocol { callOptions: CallOptions? = nil ) -> UnaryCall { return self.makeUnaryCall( - path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/AddAddressUtxo", + path: DarksideStreamerClientMetadata.Methods.addAddressUtxo.path, request: request, - callOptions: callOptions ?? self.defaultCallOptions + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeAddAddressUtxoInterceptors() ?? [] ) } @@ -310,25 +331,741 @@ extension DarksideStreamerClientProtocol { callOptions: CallOptions? = nil ) -> UnaryCall { return self.makeUnaryCall( - path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/ClearAddressUtxo", + path: DarksideStreamerClientMetadata.Methods.clearAddressUtxo.path, request: request, - callOptions: callOptions ?? self.defaultCallOptions + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeClearAddressUtxoInterceptors() ?? [] + ) + } + + /// Adds a GetTreeState to the tree state cache + /// + /// - Parameters: + /// - request: Request to send to AddTreeState. + /// - callOptions: Call options. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + internal func addTreeState( + _ request: TreeState, + callOptions: CallOptions? = nil + ) -> UnaryCall { + return self.makeUnaryCall( + path: DarksideStreamerClientMetadata.Methods.addTreeState.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeAddTreeStateInterceptors() ?? [] + ) + } + + /// Removes a GetTreeState for the given height from cache if present (can't fail) + /// + /// - Parameters: + /// - request: Request to send to RemoveTreeState. + /// - callOptions: Call options. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + internal func removeTreeState( + _ request: BlockID, + callOptions: CallOptions? = nil + ) -> UnaryCall { + return self.makeUnaryCall( + path: DarksideStreamerClientMetadata.Methods.removeTreeState.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeRemoveTreeStateInterceptors() ?? [] + ) + } + + /// Clear the list of GetTreeStates entries (can't fail) + /// + /// - Parameters: + /// - request: Request to send to ClearAllTreeStates. + /// - callOptions: Call options. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + internal func clearAllTreeStates( + _ request: Empty, + callOptions: CallOptions? = nil + ) -> UnaryCall { + return self.makeUnaryCall( + path: DarksideStreamerClientMetadata.Methods.clearAllTreeStates.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeClearAllTreeStatesInterceptors() ?? [] ) } } +@available(*, deprecated) +extension DarksideStreamerClient: @unchecked Sendable {} + +@available(*, deprecated, renamed: "DarksideStreamerNIOClient") internal final class DarksideStreamerClient: DarksideStreamerClientProtocol { + private let lock = Lock() + private var _defaultCallOptions: CallOptions + private var _interceptors: DarksideStreamerClientInterceptorFactoryProtocol? internal let channel: GRPCChannel - internal var defaultCallOptions: CallOptions + internal var defaultCallOptions: CallOptions { + get { self.lock.withLock { return self._defaultCallOptions } } + set { self.lock.withLockVoid { self._defaultCallOptions = newValue } } + } + internal var interceptors: DarksideStreamerClientInterceptorFactoryProtocol? { + get { self.lock.withLock { return self._interceptors } } + set { self.lock.withLockVoid { self._interceptors = newValue } } + } /// Creates a client for the cash.z.wallet.sdk.rpc.DarksideStreamer service. /// /// - Parameters: /// - channel: `GRPCChannel` to the service host. /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. - internal init(channel: GRPCChannel, defaultCallOptions: CallOptions = CallOptions()) { + /// - interceptors: A factory providing interceptors for each RPC. + internal init( + channel: GRPCChannel, + defaultCallOptions: CallOptions = CallOptions(), + interceptors: DarksideStreamerClientInterceptorFactoryProtocol? = nil + ) { self.channel = channel - self.defaultCallOptions = defaultCallOptions + self._defaultCallOptions = defaultCallOptions + self._interceptors = interceptors + } +} + +internal struct DarksideStreamerNIOClient: DarksideStreamerClientProtocol { + internal var channel: GRPCChannel + internal var defaultCallOptions: CallOptions + internal var interceptors: DarksideStreamerClientInterceptorFactoryProtocol? + + /// Creates a client for the cash.z.wallet.sdk.rpc.DarksideStreamer service. + /// + /// - Parameters: + /// - channel: `GRPCChannel` to the service host. + /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. + /// - interceptors: A factory providing interceptors for each RPC. + internal init( + channel: GRPCChannel, + defaultCallOptions: CallOptions = CallOptions(), + interceptors: DarksideStreamerClientInterceptorFactoryProtocol? = nil + ) { + self.channel = channel + self.defaultCallOptions = defaultCallOptions + self.interceptors = interceptors + } +} + +/// 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 +/// serves; transactions are placed into their corresponding blocks (by height). +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +internal protocol DarksideStreamerAsyncClientProtocol: GRPCClient { + static var serviceDescriptor: GRPCServiceDescriptor { get } + var interceptors: DarksideStreamerClientInterceptorFactoryProtocol? { get } + + func makeResetCall( + _ request: DarksideMetaState, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall + + func makeStageBlocksStreamCall( + callOptions: CallOptions? + ) -> GRPCAsyncClientStreamingCall + + func makeStageBlocksCall( + _ request: DarksideBlocksURL, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall + + func makeStageBlocksCreateCall( + _ request: DarksideEmptyBlocks, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall + + func makeStageTransactionsStreamCall( + callOptions: CallOptions? + ) -> GRPCAsyncClientStreamingCall + + func makeStageTransactionsCall( + _ request: DarksideTransactionsURL, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall + + func makeApplyStagedCall( + _ request: DarksideHeight, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall + + func makeGetIncomingTransactionsCall( + _ request: Empty, + callOptions: CallOptions? + ) -> GRPCAsyncServerStreamingCall + + func makeClearIncomingTransactionsCall( + _ request: Empty, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall + + func makeAddAddressUtxoCall( + _ request: GetAddressUtxosReply, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall + + func makeClearAddressUtxoCall( + _ request: Empty, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall + + func makeAddTreeStateCall( + _ request: TreeState, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall + + func makeRemoveTreeStateCall( + _ request: BlockID, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall + + func makeClearAllTreeStatesCall( + _ request: Empty, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall +} + +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +extension DarksideStreamerAsyncClientProtocol { + internal static var serviceDescriptor: GRPCServiceDescriptor { + return DarksideStreamerClientMetadata.serviceDescriptor + } + + internal var interceptors: DarksideStreamerClientInterceptorFactoryProtocol? { + return nil + } + + internal func makeResetCall( + _ request: DarksideMetaState, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.reset.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeResetInterceptors() ?? [] + ) + } + + internal func makeStageBlocksStreamCall( + callOptions: CallOptions? = nil + ) -> GRPCAsyncClientStreamingCall { + return self.makeAsyncClientStreamingCall( + path: DarksideStreamerClientMetadata.Methods.stageBlocksStream.path, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageBlocksStreamInterceptors() ?? [] + ) + } + + internal func makeStageBlocksCall( + _ request: DarksideBlocksURL, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.stageBlocks.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageBlocksInterceptors() ?? [] + ) + } + + internal func makeStageBlocksCreateCall( + _ request: DarksideEmptyBlocks, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.stageBlocksCreate.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageBlocksCreateInterceptors() ?? [] + ) + } + + internal func makeStageTransactionsStreamCall( + callOptions: CallOptions? = nil + ) -> GRPCAsyncClientStreamingCall { + return self.makeAsyncClientStreamingCall( + path: DarksideStreamerClientMetadata.Methods.stageTransactionsStream.path, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageTransactionsStreamInterceptors() ?? [] + ) + } + + internal func makeStageTransactionsCall( + _ request: DarksideTransactionsURL, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.stageTransactions.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageTransactionsInterceptors() ?? [] + ) + } + + internal func makeApplyStagedCall( + _ request: DarksideHeight, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.applyStaged.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeApplyStagedInterceptors() ?? [] + ) + } + + internal func makeGetIncomingTransactionsCall( + _ request: Empty, + callOptions: CallOptions? = nil + ) -> GRPCAsyncServerStreamingCall { + return self.makeAsyncServerStreamingCall( + path: DarksideStreamerClientMetadata.Methods.getIncomingTransactions.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetIncomingTransactionsInterceptors() ?? [] + ) + } + + internal func makeClearIncomingTransactionsCall( + _ request: Empty, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.clearIncomingTransactions.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeClearIncomingTransactionsInterceptors() ?? [] + ) + } + + internal func makeAddAddressUtxoCall( + _ request: GetAddressUtxosReply, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.addAddressUtxo.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeAddAddressUtxoInterceptors() ?? [] + ) + } + + internal func makeClearAddressUtxoCall( + _ request: Empty, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.clearAddressUtxo.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeClearAddressUtxoInterceptors() ?? [] + ) + } + + internal func makeAddTreeStateCall( + _ request: TreeState, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.addTreeState.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeAddTreeStateInterceptors() ?? [] + ) + } + + internal func makeRemoveTreeStateCall( + _ request: BlockID, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.removeTreeState.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeRemoveTreeStateInterceptors() ?? [] + ) + } + + internal func makeClearAllTreeStatesCall( + _ request: Empty, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.clearAllTreeStates.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeClearAllTreeStatesInterceptors() ?? [] + ) + } +} + +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +extension DarksideStreamerAsyncClientProtocol { + internal func reset( + _ request: DarksideMetaState, + callOptions: CallOptions? = nil + ) async throws -> Empty { + return try await self.performAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.reset.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeResetInterceptors() ?? [] + ) + } + + internal func stageBlocksStream( + _ requests: RequestStream, + callOptions: CallOptions? = nil + ) async throws -> Empty where RequestStream: Sequence, RequestStream.Element == DarksideBlock { + return try await self.performAsyncClientStreamingCall( + path: DarksideStreamerClientMetadata.Methods.stageBlocksStream.path, + requests: requests, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageBlocksStreamInterceptors() ?? [] + ) + } + + internal func stageBlocksStream( + _ requests: RequestStream, + callOptions: CallOptions? = nil + ) async throws -> Empty where RequestStream: AsyncSequence & Sendable, RequestStream.Element == DarksideBlock { + return try await self.performAsyncClientStreamingCall( + path: DarksideStreamerClientMetadata.Methods.stageBlocksStream.path, + requests: requests, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageBlocksStreamInterceptors() ?? [] + ) + } + + internal func stageBlocks( + _ request: DarksideBlocksURL, + callOptions: CallOptions? = nil + ) async throws -> Empty { + return try await self.performAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.stageBlocks.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageBlocksInterceptors() ?? [] + ) + } + + internal func stageBlocksCreate( + _ request: DarksideEmptyBlocks, + callOptions: CallOptions? = nil + ) async throws -> Empty { + return try await self.performAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.stageBlocksCreate.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageBlocksCreateInterceptors() ?? [] + ) + } + + internal func stageTransactionsStream( + _ requests: RequestStream, + callOptions: CallOptions? = nil + ) async throws -> Empty where RequestStream: Sequence, RequestStream.Element == RawTransaction { + return try await self.performAsyncClientStreamingCall( + path: DarksideStreamerClientMetadata.Methods.stageTransactionsStream.path, + requests: requests, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageTransactionsStreamInterceptors() ?? [] + ) + } + + internal func stageTransactionsStream( + _ requests: RequestStream, + callOptions: CallOptions? = nil + ) async throws -> Empty where RequestStream: AsyncSequence & Sendable, RequestStream.Element == RawTransaction { + return try await self.performAsyncClientStreamingCall( + path: DarksideStreamerClientMetadata.Methods.stageTransactionsStream.path, + requests: requests, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageTransactionsStreamInterceptors() ?? [] + ) + } + + internal func stageTransactions( + _ request: DarksideTransactionsURL, + callOptions: CallOptions? = nil + ) async throws -> Empty { + return try await self.performAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.stageTransactions.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeStageTransactionsInterceptors() ?? [] + ) + } + + internal func applyStaged( + _ request: DarksideHeight, + callOptions: CallOptions? = nil + ) async throws -> Empty { + return try await self.performAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.applyStaged.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeApplyStagedInterceptors() ?? [] + ) + } + + internal func getIncomingTransactions( + _ request: Empty, + callOptions: CallOptions? = nil + ) -> GRPCAsyncResponseStream { + return self.performAsyncServerStreamingCall( + path: DarksideStreamerClientMetadata.Methods.getIncomingTransactions.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeGetIncomingTransactionsInterceptors() ?? [] + ) + } + + internal func clearIncomingTransactions( + _ request: Empty, + callOptions: CallOptions? = nil + ) async throws -> Empty { + return try await self.performAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.clearIncomingTransactions.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeClearIncomingTransactionsInterceptors() ?? [] + ) + } + + internal func addAddressUtxo( + _ request: GetAddressUtxosReply, + callOptions: CallOptions? = nil + ) async throws -> Empty { + return try await self.performAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.addAddressUtxo.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeAddAddressUtxoInterceptors() ?? [] + ) + } + + internal func clearAddressUtxo( + _ request: Empty, + callOptions: CallOptions? = nil + ) async throws -> Empty { + return try await self.performAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.clearAddressUtxo.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeClearAddressUtxoInterceptors() ?? [] + ) + } + + internal func addTreeState( + _ request: TreeState, + callOptions: CallOptions? = nil + ) async throws -> Empty { + return try await self.performAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.addTreeState.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeAddTreeStateInterceptors() ?? [] + ) + } + + internal func removeTreeState( + _ request: BlockID, + callOptions: CallOptions? = nil + ) async throws -> Empty { + return try await self.performAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.removeTreeState.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeRemoveTreeStateInterceptors() ?? [] + ) + } + + internal func clearAllTreeStates( + _ request: Empty, + callOptions: CallOptions? = nil + ) async throws -> Empty { + return try await self.performAsyncUnaryCall( + path: DarksideStreamerClientMetadata.Methods.clearAllTreeStates.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeClearAllTreeStatesInterceptors() ?? [] + ) + } +} + +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +internal struct DarksideStreamerAsyncClient: DarksideStreamerAsyncClientProtocol { + internal var channel: GRPCChannel + internal var defaultCallOptions: CallOptions + internal var interceptors: DarksideStreamerClientInterceptorFactoryProtocol? + + internal init( + channel: GRPCChannel, + defaultCallOptions: CallOptions = CallOptions(), + interceptors: DarksideStreamerClientInterceptorFactoryProtocol? = nil + ) { + self.channel = channel + self.defaultCallOptions = defaultCallOptions + self.interceptors = interceptors + } +} + +internal protocol DarksideStreamerClientInterceptorFactoryProtocol: Sendable { + + /// - Returns: Interceptors to use when invoking 'reset'. + func makeResetInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'stageBlocksStream'. + func makeStageBlocksStreamInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'stageBlocks'. + func makeStageBlocksInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'stageBlocksCreate'. + func makeStageBlocksCreateInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'stageTransactionsStream'. + func makeStageTransactionsStreamInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'stageTransactions'. + func makeStageTransactionsInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'applyStaged'. + func makeApplyStagedInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'getIncomingTransactions'. + func makeGetIncomingTransactionsInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'clearIncomingTransactions'. + func makeClearIncomingTransactionsInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'addAddressUtxo'. + func makeAddAddressUtxoInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'clearAddressUtxo'. + func makeClearAddressUtxoInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'addTreeState'. + func makeAddTreeStateInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'removeTreeState'. + func makeRemoveTreeStateInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'clearAllTreeStates'. + func makeClearAllTreeStatesInterceptors() -> [ClientInterceptor] +} + +internal enum DarksideStreamerClientMetadata { + internal static let serviceDescriptor = GRPCServiceDescriptor( + name: "DarksideStreamer", + fullName: "cash.z.wallet.sdk.rpc.DarksideStreamer", + methods: [ + DarksideStreamerClientMetadata.Methods.reset, + DarksideStreamerClientMetadata.Methods.stageBlocksStream, + DarksideStreamerClientMetadata.Methods.stageBlocks, + DarksideStreamerClientMetadata.Methods.stageBlocksCreate, + DarksideStreamerClientMetadata.Methods.stageTransactionsStream, + DarksideStreamerClientMetadata.Methods.stageTransactions, + DarksideStreamerClientMetadata.Methods.applyStaged, + DarksideStreamerClientMetadata.Methods.getIncomingTransactions, + DarksideStreamerClientMetadata.Methods.clearIncomingTransactions, + DarksideStreamerClientMetadata.Methods.addAddressUtxo, + DarksideStreamerClientMetadata.Methods.clearAddressUtxo, + DarksideStreamerClientMetadata.Methods.addTreeState, + DarksideStreamerClientMetadata.Methods.removeTreeState, + DarksideStreamerClientMetadata.Methods.clearAllTreeStates, + ] + ) + + internal enum Methods { + internal static let reset = GRPCMethodDescriptor( + name: "Reset", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/Reset", + type: GRPCCallType.unary + ) + + internal static let stageBlocksStream = GRPCMethodDescriptor( + name: "StageBlocksStream", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocksStream", + type: GRPCCallType.clientStreaming + ) + + internal static let stageBlocks = GRPCMethodDescriptor( + name: "StageBlocks", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocks", + type: GRPCCallType.unary + ) + + internal static let stageBlocksCreate = GRPCMethodDescriptor( + name: "StageBlocksCreate", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocksCreate", + type: GRPCCallType.unary + ) + + internal static let stageTransactionsStream = GRPCMethodDescriptor( + name: "StageTransactionsStream", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageTransactionsStream", + type: GRPCCallType.clientStreaming + ) + + internal static let stageTransactions = GRPCMethodDescriptor( + name: "StageTransactions", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageTransactions", + type: GRPCCallType.unary + ) + + internal static let applyStaged = GRPCMethodDescriptor( + name: "ApplyStaged", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/ApplyStaged", + type: GRPCCallType.unary + ) + + internal static let getIncomingTransactions = GRPCMethodDescriptor( + name: "GetIncomingTransactions", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/GetIncomingTransactions", + type: GRPCCallType.serverStreaming + ) + + internal static let clearIncomingTransactions = GRPCMethodDescriptor( + name: "ClearIncomingTransactions", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/ClearIncomingTransactions", + type: GRPCCallType.unary + ) + + internal static let addAddressUtxo = GRPCMethodDescriptor( + name: "AddAddressUtxo", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/AddAddressUtxo", + type: GRPCCallType.unary + ) + + internal static let clearAddressUtxo = GRPCMethodDescriptor( + name: "ClearAddressUtxo", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/ClearAddressUtxo", + type: GRPCCallType.unary + ) + + internal static let addTreeState = GRPCMethodDescriptor( + name: "AddTreeState", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/AddTreeState", + type: GRPCCallType.unary + ) + + internal static let removeTreeState = GRPCMethodDescriptor( + name: "RemoveTreeState", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/RemoveTreeState", + type: GRPCCallType.unary + ) + + internal static let clearAllTreeStates = GRPCMethodDescriptor( + name: "ClearAllTreeStates", + path: "/cash.z.wallet.sdk.rpc.DarksideStreamer/ClearAllTreeStates", + type: GRPCCallType.unary + ) } } diff --git a/Tests/TestUtils/proto/darkside.pb.swift b/Tests/TestUtils/proto/darkside.pb.swift index 89e317d4..20479ebe 100644 --- a/Tests/TestUtils/proto/darkside.pb.swift +++ b/Tests/TestUtils/proto/darkside.pb.swift @@ -112,6 +112,15 @@ struct DarksideEmptyBlocks { init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension DarksideMetaState: @unchecked Sendable {} +extension DarksideBlock: @unchecked Sendable {} +extension DarksideBlocksURL: @unchecked Sendable {} +extension DarksideTransactionsURL: @unchecked Sendable {} +extension DarksideHeight: @unchecked Sendable {} +extension DarksideEmptyBlocks: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "cash.z.wallet.sdk.rpc" @@ -126,10 +135,13 @@ extension DarksideMetaState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem mutating func decodeMessage(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 decoder.decodeSingularInt32Field(value: &self.saplingActivation) - case 2: try decoder.decodeSingularStringField(value: &self.branchID) - case 3: try decoder.decodeSingularStringField(value: &self.chainName) + case 1: try { try decoder.decodeSingularInt32Field(value: &self.saplingActivation) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.branchID) }() + case 3: try { try decoder.decodeSingularStringField(value: &self.chainName) }() default: break } } @@ -165,8 +177,11 @@ extension DarksideBlock: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementa mutating func decodeMessage(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 decoder.decodeSingularStringField(value: &self.block) + case 1: try { try decoder.decodeSingularStringField(value: &self.block) }() default: break } } @@ -194,8 +209,11 @@ extension DarksideBlocksURL: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem mutating func decodeMessage(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 decoder.decodeSingularStringField(value: &self.url) + case 1: try { try decoder.decodeSingularStringField(value: &self.url) }() default: break } } @@ -224,9 +242,12 @@ extension DarksideTransactionsURL: SwiftProtobuf.Message, SwiftProtobuf._Message mutating func decodeMessage(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 decoder.decodeSingularInt32Field(value: &self.height) - case 2: try decoder.decodeSingularStringField(value: &self.url) + case 1: try { try decoder.decodeSingularInt32Field(value: &self.height) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.url) }() default: break } } @@ -258,8 +279,11 @@ extension DarksideHeight: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement mutating func decodeMessage(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 decoder.decodeSingularInt32Field(value: &self.height) + case 1: try { try decoder.decodeSingularInt32Field(value: &self.height) }() default: break } } @@ -289,10 +313,13 @@ extension DarksideEmptyBlocks: SwiftProtobuf.Message, SwiftProtobuf._MessageImpl mutating func decodeMessage(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 decoder.decodeSingularInt32Field(value: &self.height) - case 2: try decoder.decodeSingularInt32Field(value: &self.nonce) - case 3: try decoder.decodeSingularInt32Field(value: &self.count) + case 1: try { try decoder.decodeSingularInt32Field(value: &self.height) }() + case 2: try { try decoder.decodeSingularInt32Field(value: &self.nonce) }() + case 3: try { try decoder.decodeSingularInt32Field(value: &self.count) }() default: break } } diff --git a/Tests/TestUtils/proto/darkside.proto b/Tests/TestUtils/proto/darkside.proto index f84e615b..9cb94439 100644 --- a/Tests/TestUtils/proto/darkside.proto +++ b/Tests/TestUtils/proto/darkside.proto @@ -121,4 +121,13 @@ service DarksideStreamer { // Clear the list of GetAddressUtxos entries (can't fail) rpc ClearAddressUtxo(Empty) returns (Empty) {} + + // Adds a GetTreeState to the tree state cache + rpc AddTreeState(TreeState) returns (Empty) {} + + // Removes a GetTreeState for the given height from cache if present (can't fail) + rpc RemoveTreeState(BlockID) returns (Empty) {} + + // Clear the list of GetTreeStates entries (can't fail) + rpc ClearAllTreeStates(Empty) returns (Empty) {} }