From 17a4830c703633506acd236d4de72d68c5610944 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 16 Sep 2022 17:24:14 +0000 Subject: [PATCH] zcash_client_backend: Add gRPC bindings behind feature flag The lightwalletd service file is sourced from: Git: https://github.com/zcash/lightwalletd Rev: ad5ecda5fbb5e12799f926b8cd785d54fdd250c8 Closes zcash/librustzcash#585. --- .gitattributes | 1 + zcash_client_backend/CHANGELOG.md | 2 + zcash_client_backend/Cargo.toml | 6 +- zcash_client_backend/build.rs | 62 ++- zcash_client_backend/proto/service.proto | 187 +++++++ zcash_client_backend/src/proto.rs | 4 + zcash_client_backend/src/proto/service.rs | 629 ++++++++++++++++++++++ 7 files changed, 875 insertions(+), 16 deletions(-) create mode 100644 zcash_client_backend/proto/service.proto create mode 100644 zcash_client_backend/src/proto/service.rs diff --git a/.gitattributes b/.gitattributes index ca9746e9a..e5a028af2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ zcash_client_backend/src/proto/compact_formats.rs linguist-generated=true +zcash_client_backend/src/proto/service.rs linguist-generated=true diff --git a/zcash_client_backend/CHANGELOG.md b/zcash_client_backend/CHANGELOG.md index b21a08975..463332316 100644 --- a/zcash_client_backend/CHANGELOG.md +++ b/zcash_client_backend/CHANGELOG.md @@ -47,6 +47,8 @@ and this library adheres to Rust's notion of - `zcash_client_backend::proto`: - `actions` field on `compact_formats::CompactTx` - `compact_formats::CompactOrchardAction` + - gRPC bindings for the `lightwalletd` server, behind a `lightwalletd-tonic` + feature flag. - `zcash_client_backend::zip321::TransactionRequest` methods: - `TransactionRequest::new` for constructing a request from `Vec`. - `TransactionRequest::payments` for accessing the `Payments` that make up a diff --git a/zcash_client_backend/Cargo.toml b/zcash_client_backend/Cargo.toml index f3c414260..3314c9498 100644 --- a/zcash_client_backend/Cargo.toml +++ b/zcash_client_backend/Cargo.toml @@ -42,8 +42,9 @@ hdwallet = { version = "0.3.1", optional = true } memuse = "0.2" tracing = "0.1" -# - Protobuf interfaces +# - Protobuf interfaces and gRPC bindings prost = "0.11" +tonic = { version = "0.8", optional = true } # - Secret management secrecy = "0.8" @@ -71,7 +72,7 @@ crossbeam-channel = "0.5" rayon = "1.5" [build-dependencies] -prost-build = "0.11" +tonic-build = "0.8" which = "4" [dev-dependencies] @@ -86,6 +87,7 @@ zcash_proofs = { version = "0.8", path = "../zcash_proofs" } zcash_address = { version = "0.2", path = "../components/zcash_address", features = ["test-dependencies"] } [features] +lightwalletd-tonic = ["tonic"] transparent-inputs = ["hdwallet", "zcash_primitives/transparent-inputs"] test-dependencies = [ "proptest", diff --git a/zcash_client_backend/build.rs b/zcash_client_backend/build.rs index c12d9dbac..271b0f781 100644 --- a/zcash_client_backend/build.rs +++ b/zcash_client_backend/build.rs @@ -5,22 +5,22 @@ use std::path::{Path, PathBuf}; const COMPACT_FORMATS_PROTO: &str = "proto/compact_formats.proto"; -fn main() -> io::Result<()> { - // We don't include the proto files in releases so that downstreams do not need to - // regenerate the bindings even if protoc is present. - if Path::new(COMPACT_FORMATS_PROTO).exists() { - println!("cargo:rerun-if-changed={}", COMPACT_FORMATS_PROTO); +#[cfg(feature = "lightwalletd-tonic")] +const SERVICE_PROTO: &str = "proto/service.proto"; - // We check for the existence of protoc in the same way as prost_build, so that people - // building from source do not need to have protoc installed. If they make changes to - // the proto files, the discrepancy will be caught by CI. - if env::var_os("PROTOC") +fn main() -> io::Result<()> { + // - We don't include the proto files in releases so that downstreams do not need to + // regenerate the bindings even if protoc is present. + // - We check for the existence of protoc in the same way as prost_build, so that + // people building from source do not need to have protoc installed. If they make + // changes to the proto files, the discrepancy will be caught by CI. + if Path::new(COMPACT_FORMATS_PROTO).exists() + && env::var_os("PROTOC") .map(PathBuf::from) .or_else(|| which::which("protoc").ok()) .is_some() - { - build()?; - } + { + build()?; } Ok(()) @@ -31,13 +31,47 @@ fn build() -> io::Result<()> { .expect("Cannot find OUT_DIR environment variable") .into(); - prost_build::compile_protos(&[COMPACT_FORMATS_PROTO], &["proto/"])?; + // Build the compact format types. + tonic_build::compile_protos(COMPACT_FORMATS_PROTO)?; - // Copy the generated files into the source tree so changes can be committed. + // Copy the generated types into the source tree so changes can be committed. fs::copy( out.join("cash.z.wallet.sdk.rpc.rs"), "src/proto/compact_formats.rs", )?; + #[cfg(feature = "lightwalletd-tonic")] + { + // Build the gRPC types and client. + tonic_build::configure() + .build_server(false) + .extern_path( + ".cash.z.wallet.sdk.rpc.CompactBlock", + "crate::proto::compact_formats::CompactBlock", + ) + .extern_path( + ".cash.z.wallet.sdk.rpc.CompactTx", + "crate::proto::compact_formats::CompactTx", + ) + .extern_path( + ".cash.z.wallet.sdk.rpc.CompactSaplingSpend", + "crate::proto::compact_formats::CompactSaplingSpend", + ) + .extern_path( + ".cash.z.wallet.sdk.rpc.CompactSaplingOutput", + "crate::proto::compact_formats::CompactSaplingOutput", + ) + .extern_path( + ".cash.z.wallet.sdk.rpc.CompactOrchardAction", + "crate::proto::compact_formats::CompactOrchardAction", + ) + .compile(&[SERVICE_PROTO], &["proto/"])?; + + // Copy the generated types into the source tree so changes can be committed. The + // file has the same name as for the compact format types because they have the + // same package, but we've set things up so this only contains the service types. + fs::copy(out.join("cash.z.wallet.sdk.rpc.rs"), "src/proto/service.rs")?; + } + Ok(()) } diff --git a/zcash_client_backend/proto/service.proto b/zcash_client_backend/proto/service.proto new file mode 100644 index 000000000..d7f11dcd6 --- /dev/null +++ b/zcash_client_backend/proto/service.proto @@ -0,0 +1,187 @@ +// Copyright (c) 2019-2020 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +syntax = "proto3"; +package cash.z.wallet.sdk.rpc; +option go_package = "lightwalletd/walletrpc"; +option swift_prefix = ""; +import "compact_formats.proto"; + +// 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. +message BlockID { + uint64 height = 1; + bytes hash = 2; +} + +// BlockRange specifies a series of blocks from start to end inclusive. +// Both BlockIDs must be heights; specification by hash is not yet supported. +message BlockRange { + BlockID start = 1; + BlockID end = 2; +} + +// A TxFilter contains the information needed to identify a particular +// transaction: either a block and an index, or a direct transaction hash. +// Currently, only specification by hash is supported. +message TxFilter { + BlockID block = 1; // block identifier, height or hash + uint64 index = 2; // index within the block + bytes hash = 3; // transaction ID (hash, txid) +} + +// 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 { + bytes data = 1; // exact data returned by Zcash 'getrawtransaction' + uint64 height = 2; // height that the transaction was mined (or -1) +} + +// A SendResponse encodes an error code and a string. It is currently used +// only by SendTransaction(). If error code is zero, the operation was +// successful; if non-zero, it and the message specify the failure. +message SendResponse { + int32 errorCode = 1; + string errorMessage = 2; +} + +// Chainspec is a placeholder to allow specification of a particular chain fork. +message ChainSpec {} + +// Empty is for gRPCs that take no arguments, currently only GetLightdInfo. +message Empty {} + +// LightdInfo returns various information about this lightwalletd instance +// and the state of the blockchain. +message LightdInfo { + string version = 1; + string vendor = 2; + bool taddrSupport = 3; // true + string chainName = 4; // either "main" or "test" + uint64 saplingActivationHeight = 5; // depends on mainnet or testnet + string consensusBranchId = 6; // protocol identifier, see consensus/upgrades.cpp + uint64 blockHeight = 7; // latest block on the best chain + string gitCommit = 8; + string branch = 9; + string buildDate = 10; + string buildUser = 11; + uint64 estimatedHeight = 12; // less than tip height if zcashd is syncing + string zcashdBuild = 13; // example: "v4.1.1-877212414" + string zcashdSubversion = 14; // example: "/MagicBean:4.1.1/" +} + +// TransparentAddressBlockFilter restricts the results to the given address +// or block range. +message TransparentAddressBlockFilter { + string address = 1; // t-address + BlockRange range = 2; // start, end heights +} + +// Duration is currently used only for testing, so that the Ping rpc +// can simulate a delay, to create many simultaneous connections. Units +// are microseconds. +message Duration { + int64 intervalUs = 1; +} + +// PingResponse is used to indicate concurrency, how many Ping rpcs +// are executing upon entry and upon exit (after the delay). +// This rpc is used for testing only. +message PingResponse { + int64 entry = 1; + int64 exit = 2; +} + +message Address { + string address = 1; +} +message AddressList { + repeated string addresses = 1; +} +message Balance { + int64 valueZat = 1; +} + +message Exclude { + repeated bytes txid = 1; +} + +// The TreeState is derived from the Zcash z_gettreestate rpc. +message TreeState { + 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 +} + +// Results are sorted by height, which makes it easy to issue another +// request that picks up from where the previous left off. +message GetAddressUtxosArg { + repeated string addresses = 1; + uint64 startHeight = 2; + uint32 maxEntries = 3; // zero means unlimited +} +message GetAddressUtxosReply { + string address = 6; + bytes txid = 1; + int32 index = 2; + bytes script = 3; + int64 valueZat = 4; + uint64 height = 5; +} +message GetAddressUtxosReplyList { + repeated GetAddressUtxosReply addressUtxos = 1; +} + +service CompactTxStreamer { + // Return the height of the tip of the best chain + rpc GetLatestBlock(ChainSpec) returns (BlockID) {} + // Return the compact block corresponding to the given block identifier + rpc GetBlock(BlockID) returns (CompactBlock) {} + // Return a list of consecutive compact blocks + rpc GetBlockRange(BlockRange) returns (stream CompactBlock) {} + + // Return the requested full (not compact) transaction (as from zcashd) + rpc GetTransaction(TxFilter) returns (RawTransaction) {} + // Submit the given transaction to the Zcash network + rpc SendTransaction(RawTransaction) returns (SendResponse) {} + + // Return the txids corresponding to the given t-address within the given block range + rpc GetTaddressTxids(TransparentAddressBlockFilter) returns (stream RawTransaction) {} + rpc GetTaddressBalance(AddressList) returns (Balance) {} + rpc GetTaddressBalanceStream(stream Address) returns (Balance) {} + + // Return the compact transactions currently in the mempool; the results + // can be a few seconds out of date. If the Exclude list is empty, return + // all transactions; otherwise return all *except* those in the Exclude list + // (if any); this allows the client to avoid receiving transactions that it + // already has (from an earlier call to this rpc). The transaction IDs in the + // Exclude list can be shortened to any number of bytes to make the request + // more bandwidth-efficient; if two or more transactions in the mempool + // match a shortened txid, they are all sent (none is excluded). Transactions + // in the exclude list that don't exist in the mempool are ignored. + rpc GetMempoolTx(Exclude) returns (stream CompactTx) {} + + // Return a stream of current Mempool transactions. This will keep the output stream open while + // there are mempool transactions. It will close the returned stream when a new block is mined. + rpc GetMempoolStream(Empty) returns (stream RawTransaction) {} + + // GetTreeState returns the note commitment tree state corresponding to the given block. + // See section 3.7 of the Zcash protocol specification. It returns several other useful + // values also (even though they can be obtained using GetBlock). + // The block can be specified by either height or hash. + rpc GetTreeState(BlockID) returns (TreeState) {} + rpc GetLatestTreeState(Empty) returns (TreeState) {} + + rpc GetAddressUtxos(GetAddressUtxosArg) returns (GetAddressUtxosReplyList) {} + rpc GetAddressUtxosStream(GetAddressUtxosArg) returns (stream GetAddressUtxosReply) {} + + // Return information about this lightwalletd instance and the blockchain + rpc GetLightdInfo(Empty) returns (LightdInfo) {} + // Testing-only, requires lightwalletd --ping-very-insecure (do not enable in production) + rpc Ping(Duration) returns (PingResponse) {} +} diff --git a/zcash_client_backend/src/proto.rs b/zcash_client_backend/src/proto.rs index aa129a099..713b93354 100644 --- a/zcash_client_backend/src/proto.rs +++ b/zcash_client_backend/src/proto.rs @@ -14,6 +14,10 @@ use zcash_note_encryption::{EphemeralKeyBytes, COMPACT_NOTE_SIZE}; #[rustfmt::skip] pub mod compact_formats; +#[cfg(feature = "lightwalletd-tonic")] +#[rustfmt::skip] +pub mod service; + impl compact_formats::CompactBlock { /// Returns the [`BlockHash`] for this block. /// diff --git a/zcash_client_backend/src/proto/service.rs b/zcash_client_backend/src/proto/service.rs new file mode 100644 index 000000000..d8680d658 --- /dev/null +++ b/zcash_client_backend/src/proto/service.rs @@ -0,0 +1,629 @@ +/// 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. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockId { + #[prost(uint64, tag="1")] + pub height: u64, + #[prost(bytes="vec", tag="2")] + pub hash: ::prost::alloc::vec::Vec, +} +/// BlockRange specifies a series of blocks from start to end inclusive. +/// Both BlockIDs must be heights; specification by hash is not yet supported. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockRange { + #[prost(message, optional, tag="1")] + pub start: ::core::option::Option, + #[prost(message, optional, tag="2")] + pub end: ::core::option::Option, +} +/// A TxFilter contains the information needed to identify a particular +/// transaction: either a block and an index, or a direct transaction hash. +/// Currently, only specification by hash is supported. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TxFilter { + /// block identifier, height or hash + #[prost(message, optional, tag="1")] + pub block: ::core::option::Option, + /// index within the block + #[prost(uint64, tag="2")] + pub index: u64, + /// transaction ID (hash, txid) + #[prost(bytes="vec", tag="3")] + pub hash: ::prost::alloc::vec::Vec, +} +/// 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. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RawTransaction { + /// exact data returned by Zcash 'getrawtransaction' + #[prost(bytes="vec", tag="1")] + pub data: ::prost::alloc::vec::Vec, + /// height that the transaction was mined (or -1) + #[prost(uint64, tag="2")] + pub height: u64, +} +/// A SendResponse encodes an error code and a string. It is currently used +/// only by SendTransaction(). If error code is zero, the operation was +/// successful; if non-zero, it and the message specify the failure. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SendResponse { + #[prost(int32, tag="1")] + pub error_code: i32, + #[prost(string, tag="2")] + pub error_message: ::prost::alloc::string::String, +} +/// Chainspec is a placeholder to allow specification of a particular chain fork. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ChainSpec { +} +/// Empty is for gRPCs that take no arguments, currently only GetLightdInfo. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Empty { +} +/// LightdInfo returns various information about this lightwalletd instance +/// and the state of the blockchain. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LightdInfo { + #[prost(string, tag="1")] + pub version: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub vendor: ::prost::alloc::string::String, + /// true + #[prost(bool, tag="3")] + pub taddr_support: bool, + /// either "main" or "test" + #[prost(string, tag="4")] + pub chain_name: ::prost::alloc::string::String, + /// depends on mainnet or testnet + #[prost(uint64, tag="5")] + pub sapling_activation_height: u64, + /// protocol identifier, see consensus/upgrades.cpp + #[prost(string, tag="6")] + pub consensus_branch_id: ::prost::alloc::string::String, + /// latest block on the best chain + #[prost(uint64, tag="7")] + pub block_height: u64, + #[prost(string, tag="8")] + pub git_commit: ::prost::alloc::string::String, + #[prost(string, tag="9")] + pub branch: ::prost::alloc::string::String, + #[prost(string, tag="10")] + pub build_date: ::prost::alloc::string::String, + #[prost(string, tag="11")] + pub build_user: ::prost::alloc::string::String, + /// less than tip height if zcashd is syncing + #[prost(uint64, tag="12")] + pub estimated_height: u64, + /// example: "v4.1.1-877212414" + #[prost(string, tag="13")] + pub zcashd_build: ::prost::alloc::string::String, + /// example: "/MagicBean:4.1.1/" + #[prost(string, tag="14")] + pub zcashd_subversion: ::prost::alloc::string::String, +} +/// TransparentAddressBlockFilter restricts the results to the given address +/// or block range. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransparentAddressBlockFilter { + /// t-address + #[prost(string, tag="1")] + pub address: ::prost::alloc::string::String, + /// start, end heights + #[prost(message, optional, tag="2")] + pub range: ::core::option::Option, +} +/// Duration is currently used only for testing, so that the Ping rpc +/// can simulate a delay, to create many simultaneous connections. Units +/// are microseconds. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Duration { + #[prost(int64, tag="1")] + pub interval_us: i64, +} +/// PingResponse is used to indicate concurrency, how many Ping rpcs +/// are executing upon entry and upon exit (after the delay). +/// This rpc is used for testing only. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PingResponse { + #[prost(int64, tag="1")] + pub entry: i64, + #[prost(int64, tag="2")] + pub exit: i64, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Address { + #[prost(string, tag="1")] + pub address: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AddressList { + #[prost(string, repeated, tag="1")] + pub addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Balance { + #[prost(int64, tag="1")] + pub value_zat: i64, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Exclude { + #[prost(bytes="vec", repeated, tag="1")] + pub txid: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, +} +/// The TreeState is derived from the Zcash z_gettreestate rpc. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TreeState { + /// "main" or "test" + #[prost(string, tag="1")] + pub network: ::prost::alloc::string::String, + /// block height + #[prost(uint64, tag="2")] + pub height: u64, + /// block id + #[prost(string, tag="3")] + pub hash: ::prost::alloc::string::String, + /// Unix epoch time when the block was mined + #[prost(uint32, tag="4")] + pub time: u32, + /// sapling commitment tree state + #[prost(string, tag="5")] + pub sapling_tree: ::prost::alloc::string::String, + /// orchard commitment tree state + #[prost(string, tag="6")] + pub orchard_tree: ::prost::alloc::string::String, +} +/// Results are sorted by height, which makes it easy to issue another +/// request that picks up from where the previous left off. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetAddressUtxosArg { + #[prost(string, repeated, tag="1")] + pub addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(uint64, tag="2")] + pub start_height: u64, + /// zero means unlimited + #[prost(uint32, tag="3")] + pub max_entries: u32, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetAddressUtxosReply { + #[prost(string, tag="6")] + pub address: ::prost::alloc::string::String, + #[prost(bytes="vec", tag="1")] + pub txid: ::prost::alloc::vec::Vec, + #[prost(int32, tag="2")] + pub index: i32, + #[prost(bytes="vec", tag="3")] + pub script: ::prost::alloc::vec::Vec, + #[prost(int64, tag="4")] + pub value_zat: i64, + #[prost(uint64, tag="5")] + pub height: u64, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetAddressUtxosReplyList { + #[prost(message, repeated, tag="1")] + pub address_utxos: ::prost::alloc::vec::Vec, +} +/// Generated client implementations. +pub mod compact_tx_streamer_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct CompactTxStreamerClient { + inner: tonic::client::Grpc, + } + impl CompactTxStreamerClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: std::convert::TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl CompactTxStreamerClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> CompactTxStreamerClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + CompactTxStreamerClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Return the height of the tip of the best chain + pub async fn get_latest_block( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestBlock", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// Return the compact block corresponding to the given block identifier + pub async fn get_block( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlock", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// Return a list of consecutive compact blocks + pub async fn get_block_range( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response< + tonic::codec::Streaming, + >, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRange", + ); + self.inner.server_streaming(request.into_request(), path, codec).await + } + /// Return the requested full (not compact) transaction (as from zcashd) + pub async fn get_transaction( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTransaction", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// Submit the given transaction to the Zcash network + pub async fn send_transaction( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/SendTransaction", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// Return the txids corresponding to the given t-address within the given block range + pub async fn get_taddress_txids( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressTxids", + ); + self.inner.server_streaming(request.into_request(), path, codec).await + } + pub async fn get_taddress_balance( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalance", + ); + self.inner.unary(request.into_request(), path, codec).await + } + pub async fn get_taddress_balance_stream( + &mut self, + request: impl tonic::IntoStreamingRequest, + ) -> Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalanceStream", + ); + self.inner + .client_streaming(request.into_streaming_request(), path, codec) + .await + } + /// Return the compact transactions currently in the mempool; the results + /// can be a few seconds out of date. If the Exclude list is empty, return + /// all transactions; otherwise return all *except* those in the Exclude list + /// (if any); this allows the client to avoid receiving transactions that it + /// already has (from an earlier call to this rpc). The transaction IDs in the + /// Exclude list can be shortened to any number of bytes to make the request + /// more bandwidth-efficient; if two or more transactions in the mempool + /// match a shortened txid, they are all sent (none is excluded). Transactions + /// in the exclude list that don't exist in the mempool are ignored. + pub async fn get_mempool_tx( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response< + tonic::codec::Streaming, + >, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolTx", + ); + self.inner.server_streaming(request.into_request(), path, codec).await + } + /// Return a stream of current Mempool transactions. This will keep the output stream open while + /// there are mempool transactions. It will close the returned stream when a new block is mined. + pub async fn get_mempool_stream( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolStream", + ); + self.inner.server_streaming(request.into_request(), path, codec).await + } + /// GetTreeState returns the note commitment tree state corresponding to the given block. + /// See section 3.7 of the Zcash protocol specification. It returns several other useful + /// values also (even though they can be obtained using GetBlock). + /// The block can be specified by either height or hash. + pub async fn get_tree_state( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTreeState", + ); + self.inner.unary(request.into_request(), path, codec).await + } + pub async fn get_latest_tree_state( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestTreeState", + ); + self.inner.unary(request.into_request(), path, codec).await + } + pub async fn get_address_utxos( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxos", + ); + self.inner.unary(request.into_request(), path, codec).await + } + pub async fn get_address_utxos_stream( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxosStream", + ); + self.inner.server_streaming(request.into_request(), path, codec).await + } + /// Return information about this lightwalletd instance and the blockchain + pub async fn get_lightd_info( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// Testing-only, requires lightwalletd --ping-very-insecure (do not enable in production) + pub async fn ping( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/cash.z.wallet.sdk.rpc.CompactTxStreamer/Ping", + ); + self.inner.unary(request.into_request(), path, codec).await + } + } +}