From 1fdd02d41a2185daf8c7602efc9e1517342418c5 Mon Sep 17 00:00:00 2001 From: Tomas Tauber <2410580+tomtau@users.noreply.github.com> Date: Mon, 30 May 2022 10:23:03 +0800 Subject: [PATCH] tendermint-proto: Add a feature flag and generate gRPC server definitions - `proto-compiler` uses `tonic-build` - tendermint-proto can be compiled with std for the `grpc` feature (as required by the generated `tonic` code) - the primary motivation is the new gRPC-based PrivVal interface in Tendermint 0.35 (see https://github.com/informalsystems/tendermint-rs/issues/1134) --- .../unreleased/features/1134-proto-grpc.md | 2 + proto/Cargo.toml | 5 + proto/src/lib.rs | 2 +- proto/src/prost/tendermint.abci.rs | 688 ++++++++++++++++++ proto/src/prost/tendermint.privval.rs | 224 ++++++ proto/src/prost/tendermint.rpc.grpc.rs | 179 +++++ tools/proto-compiler/Cargo.toml | 1 + tools/proto-compiler/src/main.rs | 10 +- 8 files changed, 1109 insertions(+), 2 deletions(-) create mode 100644 .changelog/unreleased/features/1134-proto-grpc.md diff --git a/.changelog/unreleased/features/1134-proto-grpc.md b/.changelog/unreleased/features/1134-proto-grpc.md new file mode 100644 index 000000000..525f186ff --- /dev/null +++ b/.changelog/unreleased/features/1134-proto-grpc.md @@ -0,0 +1,2 @@ +- `[tendermint-proto]` Add a feature flag and generate gRPC server definitions + ([#1134](https://github.com/informalsystems/tendermint-rs/issues/1134)) diff --git a/proto/Cargo.toml b/proto/Cargo.toml index 7ad2d10dd..00a75f45c 100644 --- a/proto/Cargo.toml +++ b/proto/Cargo.toml @@ -16,6 +16,10 @@ description = """ [package.metadata.docs.rs] all-features = true +[features] +default = [] +grpc = ["tonic"] + [dependencies] prost = { version = "0.10", default-features = false } prost-types = { version = "0.10", default-features = false } @@ -27,6 +31,7 @@ num-traits = { version = "0.2", default-features = false } num-derive = { version = "0.3", default-features = false } time = { version = "0.3.5", default-features = false, features = ["macros", "parsing"] } flex-error = { version = "0.4.4", default-features = false } +tonic = { version = "0.7", optional = true } [dev-dependencies] serde_json = { version = "1.0", default-features = false, features = ["alloc"] } diff --git a/proto/src/lib.rs b/proto/src/lib.rs index 4a4a4ddf7..665b6f6b2 100644 --- a/proto/src/lib.rs +++ b/proto/src/lib.rs @@ -1,6 +1,6 @@ //! tendermint-proto library gives the developer access to the Tendermint proto-defined structs. -#![no_std] +#![cfg_attr(not(feature = "grpc"), no_std)] #![deny(warnings, trivial_casts, trivial_numeric_casts, unused_import_braces)] #![allow(clippy::large_enum_variant)] #![forbid(unsafe_code)] diff --git a/proto/src/prost/tendermint.abci.rs b/proto/src/prost/tendermint.abci.rs index 2a42bbd53..614488788 100644 --- a/proto/src/prost/tendermint.abci.rs +++ b/proto/src/prost/tendermint.abci.rs @@ -530,3 +530,691 @@ pub enum EvidenceType { DuplicateVote = 1, LightClientAttack = 2, } +/// Generated server implementations. +#[cfg(feature = "grpc")] +pub mod abci_application_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + ///Generated trait containing gRPC methods that should be implemented for use with AbciApplicationServer. + #[async_trait] + pub trait AbciApplication: Send + Sync + 'static { + async fn echo( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn flush( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn info( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn deliver_tx( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn check_tx( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn query( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn commit( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn init_chain( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn begin_block( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn end_block( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn list_snapshots( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn offer_snapshot( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn load_snapshot_chunk( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn apply_snapshot_chunk( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + } + #[derive(Debug)] + pub struct AbciApplicationServer { + inner: _Inner, + accept_compression_encodings: (), + send_compression_encodings: (), + } + struct _Inner(Arc); + impl AbciApplicationServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + } + impl tonic::codegen::Service> for AbciApplicationServer + where + T: AbciApplication, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/tendermint.abci.ABCIApplication/Echo" => { + #[allow(non_camel_case_types)] + struct EchoSvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService for EchoSvc { + type Response = super::ResponseEcho; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).echo(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = EchoSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.abci.ABCIApplication/Flush" => { + #[allow(non_camel_case_types)] + struct FlushSvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService for FlushSvc { + type Response = super::ResponseFlush; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).flush(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = FlushSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.abci.ABCIApplication/Info" => { + #[allow(non_camel_case_types)] + struct InfoSvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService for InfoSvc { + type Response = super::ResponseInfo; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).info(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = InfoSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.abci.ABCIApplication/DeliverTx" => { + #[allow(non_camel_case_types)] + struct DeliverTxSvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService + for DeliverTxSvc { + type Response = super::ResponseDeliverTx; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).deliver_tx(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = DeliverTxSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.abci.ABCIApplication/CheckTx" => { + #[allow(non_camel_case_types)] + struct CheckTxSvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService + for CheckTxSvc { + type Response = super::ResponseCheckTx; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).check_tx(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = CheckTxSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.abci.ABCIApplication/Query" => { + #[allow(non_camel_case_types)] + struct QuerySvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService for QuerySvc { + type Response = super::ResponseQuery; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).query(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = QuerySvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.abci.ABCIApplication/Commit" => { + #[allow(non_camel_case_types)] + struct CommitSvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService + for CommitSvc { + type Response = super::ResponseCommit; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).commit(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = CommitSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.abci.ABCIApplication/InitChain" => { + #[allow(non_camel_case_types)] + struct InitChainSvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService + for InitChainSvc { + type Response = super::ResponseInitChain; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).init_chain(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = InitChainSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.abci.ABCIApplication/BeginBlock" => { + #[allow(non_camel_case_types)] + struct BeginBlockSvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService + for BeginBlockSvc { + type Response = super::ResponseBeginBlock; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).begin_block(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = BeginBlockSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.abci.ABCIApplication/EndBlock" => { + #[allow(non_camel_case_types)] + struct EndBlockSvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService + for EndBlockSvc { + type Response = super::ResponseEndBlock; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).end_block(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = EndBlockSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.abci.ABCIApplication/ListSnapshots" => { + #[allow(non_camel_case_types)] + struct ListSnapshotsSvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService + for ListSnapshotsSvc { + type Response = super::ResponseListSnapshots; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).list_snapshots(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = ListSnapshotsSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.abci.ABCIApplication/OfferSnapshot" => { + #[allow(non_camel_case_types)] + struct OfferSnapshotSvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService + for OfferSnapshotSvc { + type Response = super::ResponseOfferSnapshot; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).offer_snapshot(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = OfferSnapshotSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.abci.ABCIApplication/LoadSnapshotChunk" => { + #[allow(non_camel_case_types)] + struct LoadSnapshotChunkSvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService + for LoadSnapshotChunkSvc { + type Response = super::ResponseLoadSnapshotChunk; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).load_snapshot_chunk(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = LoadSnapshotChunkSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.abci.ABCIApplication/ApplySnapshotChunk" => { + #[allow(non_camel_case_types)] + struct ApplySnapshotChunkSvc(pub Arc); + impl< + T: AbciApplication, + > tonic::server::UnaryService + for ApplySnapshotChunkSvc { + type Response = super::ResponseApplySnapshotChunk; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).apply_snapshot_chunk(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = ApplySnapshotChunkSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for AbciApplicationServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(self.0.clone()) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::transport::NamedService + for AbciApplicationServer { + const NAME: &'static str = "tendermint.abci.ABCIApplication"; + } +} diff --git a/proto/src/prost/tendermint.privval.rs b/proto/src/prost/tendermint.privval.rs index 04fac20e6..651f6d451 100644 --- a/proto/src/prost/tendermint.privval.rs +++ b/proto/src/prost/tendermint.privval.rs @@ -106,3 +106,227 @@ pub enum Errors { ReadTimeout = 4, WriteTimeout = 5, } +/// Generated server implementations. +#[cfg(feature = "grpc")] +pub mod priv_validator_api_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + ///Generated trait containing gRPC methods that should be implemented for use with PrivValidatorApiServer. + #[async_trait] + pub trait PrivValidatorApi: Send + Sync + 'static { + async fn get_pub_key( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn sign_vote( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn sign_proposal( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + } + #[derive(Debug)] + pub struct PrivValidatorApiServer { + inner: _Inner, + accept_compression_encodings: (), + send_compression_encodings: (), + } + struct _Inner(Arc); + impl PrivValidatorApiServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + } + impl tonic::codegen::Service> for PrivValidatorApiServer + where + T: PrivValidatorApi, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/tendermint.privval.PrivValidatorAPI/GetPubKey" => { + #[allow(non_camel_case_types)] + struct GetPubKeySvc(pub Arc); + impl< + T: PrivValidatorApi, + > tonic::server::UnaryService + for GetPubKeySvc { + type Response = super::PubKeyResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).get_pub_key(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetPubKeySvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.privval.PrivValidatorAPI/SignVote" => { + #[allow(non_camel_case_types)] + struct SignVoteSvc(pub Arc); + impl< + T: PrivValidatorApi, + > tonic::server::UnaryService + for SignVoteSvc { + type Response = super::SignedVoteResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).sign_vote(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = SignVoteSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.privval.PrivValidatorAPI/SignProposal" => { + #[allow(non_camel_case_types)] + struct SignProposalSvc(pub Arc); + impl< + T: PrivValidatorApi, + > tonic::server::UnaryService + for SignProposalSvc { + type Response = super::SignedProposalResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).sign_proposal(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = SignProposalSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for PrivValidatorApiServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(self.0.clone()) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::transport::NamedService + for PrivValidatorApiServer { + const NAME: &'static str = "tendermint.privval.PrivValidatorAPI"; + } +} diff --git a/proto/src/prost/tendermint.rpc.grpc.rs b/proto/src/prost/tendermint.rpc.grpc.rs index 97e339365..79f9715fd 100644 --- a/proto/src/prost/tendermint.rpc.grpc.rs +++ b/proto/src/prost/tendermint.rpc.grpc.rs @@ -22,3 +22,182 @@ pub struct ResponseBroadcastTx { #[prost(message, optional, tag="2")] pub deliver_tx: ::core::option::Option, } +/// Generated server implementations. +#[cfg(feature = "grpc")] +pub mod broadcast_api_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + ///Generated trait containing gRPC methods that should be implemented for use with BroadcastApiServer. + #[async_trait] + pub trait BroadcastApi: Send + Sync + 'static { + async fn ping( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + async fn broadcast_tx( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + } + #[derive(Debug)] + pub struct BroadcastApiServer { + inner: _Inner, + accept_compression_encodings: (), + send_compression_encodings: (), + } + struct _Inner(Arc); + impl BroadcastApiServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + } + impl tonic::codegen::Service> for BroadcastApiServer + where + T: BroadcastApi, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/tendermint.rpc.grpc.BroadcastAPI/Ping" => { + #[allow(non_camel_case_types)] + struct PingSvc(pub Arc); + impl tonic::server::UnaryService + for PingSvc { + type Response = super::ResponsePing; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).ping(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = PingSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/tendermint.rpc.grpc.BroadcastAPI/BroadcastTx" => { + #[allow(non_camel_case_types)] + struct BroadcastTxSvc(pub Arc); + impl< + T: BroadcastApi, + > tonic::server::UnaryService + for BroadcastTxSvc { + type Response = super::ResponseBroadcastTx; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).broadcast_tx(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = BroadcastTxSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for BroadcastApiServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(self.0.clone()) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::transport::NamedService for BroadcastApiServer { + const NAME: &'static str = "tendermint.rpc.grpc.BroadcastAPI"; + } +} diff --git a/tools/proto-compiler/Cargo.toml b/tools/proto-compiler/Cargo.toml index b8396b0af..81e39666f 100644 --- a/tools/proto-compiler/Cargo.toml +++ b/tools/proto-compiler/Cargo.toml @@ -11,3 +11,4 @@ prost-build = { version = "0.10" } git2 = { version = "0.13" } tempfile = { version = "3.2.0" } subtle-encoding = { version = "0.5" } +tonic-build = { version = "0.7" } \ No newline at end of file diff --git a/tools/proto-compiler/src/main.rs b/tools/proto-compiler/src/main.rs index 7de037997..38a7adf7c 100644 --- a/tools/proto-compiler/src/main.rs +++ b/tools/proto-compiler/src/main.rs @@ -81,7 +81,15 @@ fn main() { "super::super::google::protobuf::Timestamp", ); println!("[info] => Creating structs."); - pb.compile_protos(&protos, &proto_includes_paths).unwrap(); + tonic_build::configure() + .out_dir(&out_dir) + .build_client(false) + .build_server(true) + .server_mod_attribute("tendermint.abci", "#[cfg(feature = \"grpc\")]") + .server_mod_attribute("tendermint.privval", "#[cfg(feature = \"grpc\")]") + .server_mod_attribute("tendermint.rpc.grpc", "#[cfg(feature = \"grpc\")]") + .compile_with_config(pb, &protos, &proto_includes_paths) + .unwrap(); println!("[info] => Removing old structs and copying new structs."); copy_files(&out_dir, &target_dir); // This panics if it fails.