Skip to content

Commit

Permalink
pd: 📬 create tonic router in penumbra-app
Browse files Browse the repository at this point in the history
  • Loading branch information
cratelyn committed Jan 26, 2024
1 parent 3e6c620 commit e8ab3aa
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 92 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

93 changes: 11 additions & 82 deletions crates/bin/pd/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ use metrics_util::layers::Stack;
use anyhow::Context;
use cnidarium::{StateDelta, Storage};
use futures::stream::TryStreamExt;
use ibc_proto::ibc::core::channel::v1::query_server::QueryServer as ChannelQueryServer;
use ibc_proto::ibc::core::client::v1::query_server::QueryServer as ClientQueryServer;
use ibc_proto::ibc::core::connection::v1::query_server::QueryServer as ConnectionQueryServer;
use metrics_exporter_prometheus::PrometheusBuilder;
use pd::{
cli::{Opt, RootCommand, TestnetCommand},
Expand All @@ -25,8 +22,6 @@ use pd::{
},
};
use penumbra_app::{PenumbraHost, SUBSTORE_PREFIXES};
use penumbra_proto::core::component::dex::v1alpha1::simulation_service_server::SimulationServiceServer;
use penumbra_proto::util::tendermint_proxy::v1alpha1::tendermint_proxy_service_server::TendermintProxyServiceServer;
use penumbra_tendermint_proxy::TendermintProxy;
use penumbra_tower_trace::remote_addr;
use rand::Rng;
Expand Down Expand Up @@ -153,7 +148,6 @@ async fn main() -> anyhow::Result<()> {
async move { pd::Mempool::new(storage.clone(), queue).await?.run().await }
}));
let info = pd::Info::new(storage.clone());
let tm_proxy = TendermintProxy::new(cometbft_addr);
let snapshot = pd::Snapshot {};

let abci_server = tokio::task::Builder::new()
Expand All @@ -172,46 +166,21 @@ async fn main() -> anyhow::Result<()> {

let ibc = penumbra_ibc::component::rpc::IbcQuery::<PenumbraHost>::new(storage.clone());

// TODO: Once we migrate to Tonic 0.10.0, we'll be able to use the
// `Routes` structure to have each component define a method that
// returns a `Routes` with all of its query services bundled inside.
//
// This means we won't have to import all this shit and recite every
// single service -- we can e.g., have the app crate assemble all of
// its components' query services into a single `Routes` and then
// just add that to the gRPC server.

use cnidarium::rpc::proto::v1alpha1::query_service_server::QueryServiceServer as StorageQueryServiceServer;
use penumbra_proto::core::{
app::v1alpha1::query_service_server::QueryServiceServer as AppQueryServiceServer,
component::{
chain::v1alpha1::query_service_server::QueryServiceServer as ChainQueryServiceServer,
compact_block::v1alpha1::query_service_server::QueryServiceServer as CompactBlockQueryServiceServer,
dex::v1alpha1::query_service_server::QueryServiceServer as DexQueryServiceServer,
governance::v1alpha1::query_service_server::QueryServiceServer as GovernanceQueryServiceServer,
sct::v1alpha1::query_service_server::QueryServiceServer as SctQueryServiceServer,
shielded_pool::v1alpha1::query_service_server::QueryServiceServer as ShieldedPoolQueryServiceServer,
stake::v1alpha1::query_service_server::QueryServiceServer as StakeQueryServiceServer,
},
};
use tonic_web::enable as we;

use cnidarium::rpc::Server as StorageServer;
use penumbra_app::rpc::Server as AppServer;
use penumbra_chain::component::rpc::Server as ChainServer;
use penumbra_compact_block::component::rpc::Server as CompactBlockServer;
use penumbra_dex::component::rpc::Server as DexServer;
use penumbra_governance::component::rpc::Server as GovernanceServer;
use penumbra_sct::component::rpc::Server as SctServer;
use penumbra_shielded_pool::component::rpc::Server as ShieldedPoolServer;
use penumbra_stake::component::rpc::Server as StakeServer;

// Set rather permissive CORS headers for pd's gRPC: the service
// should be accessible from arbitrary web contexts, such as localhost,
// or any FQDN that wants to reference its data.
let cors_layer = CorsLayer::permissive();

let mut grpc_server = Server::builder()
// --------------------------------------------------------------------------------
let tendermint_proxy = TendermintProxy::new(cometbft_addr);
let routes = penumbra_app::rpc::Routes {
storage,
ibc,
tendermint_proxy,
enable_expensive_rpc,
}
.build()?;
let grpc_server = Server::builder()
.trace_fn(|req| match remote_addr(req) {
Some(remote_addr) => {
tracing::error_span!("grpc", ?remote_addr)
Expand All @@ -234,47 +203,7 @@ async fn main() -> anyhow::Result<()> {
// new blocks.
// .timeout(std::time::Duration::from_secs(7))
// Wrap each of the gRPC services in a tonic-web proxy:
.add_service(we(StorageQueryServiceServer::new(StorageServer::new(
storage.clone(),
))))
.add_service(we(AppQueryServiceServer::new(AppServer::new(
storage.clone(),
))))
.add_service(we(ChainQueryServiceServer::new(ChainServer::new(
storage.clone(),
))))
.add_service(we(CompactBlockQueryServiceServer::new(
CompactBlockServer::new(storage.clone()),
)))
.add_service(we(DexQueryServiceServer::new(DexServer::new(
storage.clone(),
))))
.add_service(we(GovernanceQueryServiceServer::new(
GovernanceServer::new(storage.clone()),
)))
.add_service(we(SctQueryServiceServer::new(SctServer::new(
storage.clone(),
))))
.add_service(we(ShieldedPoolQueryServiceServer::new(
ShieldedPoolServer::new(storage.clone()),
)))
.add_service(we(StakeQueryServiceServer::new(StakeServer::new(
storage.clone(),
))))
.add_service(we(ClientQueryServer::new(ibc.clone())))
.add_service(we(ChannelQueryServer::new(ibc.clone())))
.add_service(we(ConnectionQueryServer::new(ibc.clone())))
.add_service(we(TendermintProxyServiceServer::new(tm_proxy.clone())))
.add_service(we(tonic_reflection::server::Builder::configure()
.register_encoded_file_descriptor_set(penumbra_proto::FILE_DESCRIPTOR_SET)
.build()
.with_context(|| "could not configure grpc reflection service")?));

if enable_expensive_rpc {
grpc_server = grpc_server.add_service(we(SimulationServiceServer::new(
DexServer::new(storage.clone()),
)));
}
.add_routes(routes);

let grpc_server = if let Some(domain) = grpc_auto_https {
use pd::auto_https::Wrapper;
Expand Down
3 changes: 3 additions & 0 deletions crates/core/app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ penumbra-ibc = { path = "../component/ibc", features = ["component"] }
penumbra-distributions = { path = "../component/distributions" }
penumbra-compact-block = { path = "../component/compact-block" }
penumbra-transaction = { path = "../transaction", features = ["parallel"] }
penumbra-tendermint-proxy = { path = "../../util/tendermint-proxy" }

# External dependencies
decaf377 = { version = "0.5" }
Expand All @@ -39,6 +40,8 @@ jmt = "0.9"
tokio = { version = "1.21.1", features = ["full", "tracing"] }
async-trait = "0.1.52"
tonic = "0.10"
tonic-web = "0.10.0"
tonic-reflection = "0.10.0"
futures = "0.3"
anyhow = "1"
tracing = "0.1"
Expand Down
114 changes: 104 additions & 10 deletions crates/core/app/src/rpc.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,110 @@
use cnidarium::Storage;
use penumbra_chain::component::StateReadExt as _;
use penumbra_proto::core::app::v1alpha1::{
query_service_server::QueryService, AppParametersRequest, AppParametersResponse,
TransactionsByHeightRequest, TransactionsByHeightResponse,
use {
crate::{app::StateReadExt as _, PenumbraHost},
anyhow::Context,
cnidarium::Storage,
ibc_proto::ibc::core::{
channel::v1::query_server::QueryServer as ChannelQueryServer,
client::v1::query_server::QueryServer as ClientQueryServer,
connection::v1::query_server::QueryServer as ConnectionQueryServer,
},
penumbra_chain::component::{rpc::Server as ChainServer, StateReadExt as _},
penumbra_compact_block::component::rpc::Server as CompactBlockServer,
penumbra_dex::component::rpc::Server as DexServer,
penumbra_governance::component::rpc::Server as GovernanceServer,
penumbra_ibc::component::rpc::IbcQuery,
penumbra_proto::core::app::v1alpha1::{
query_service_server::QueryService, AppParametersRequest, AppParametersResponse,
TransactionsByHeightRequest, TransactionsByHeightResponse,
},
penumbra_proto::core::component::dex::v1alpha1::simulation_service_server::SimulationServiceServer,
penumbra_proto::core::{
app::v1alpha1::query_service_server::QueryServiceServer as AppQueryServiceServer,
component::{
chain::v1alpha1::query_service_server::QueryServiceServer as ChainQueryServiceServer,
compact_block::v1alpha1::query_service_server::QueryServiceServer as CompactBlockQueryServiceServer,
dex::v1alpha1::query_service_server::QueryServiceServer as DexQueryServiceServer,
governance::v1alpha1::query_service_server::QueryServiceServer as GovernanceQueryServiceServer,
sct::v1alpha1::query_service_server::QueryServiceServer as SctQueryServiceServer,
shielded_pool::v1alpha1::query_service_server::QueryServiceServer as ShieldedPoolQueryServiceServer,
stake::v1alpha1::query_service_server::QueryServiceServer as StakeQueryServiceServer,
},
},
penumbra_proto::util::tendermint_proxy::v1alpha1::tendermint_proxy_service_server::TendermintProxyServiceServer,
penumbra_sct::component::rpc::Server as SctServer,
penumbra_shielded_pool::component::rpc::Server as ShieldedPoolServer,
penumbra_stake::component::rpc::Server as StakeServer,
penumbra_tendermint_proxy::TendermintProxy,
tonic::Status,
tonic_web::enable as we,
tracing::instrument,
};
use tonic::Status;
use tracing::instrument;

use crate::app::StateReadExt as _;
/// Used to construct a [`tonic::transport::server::Routes`] router.
///
/// Use [`Routes::build()`] to try to construct a set of tonic routes.
pub struct Routes {
pub storage: Storage,
pub ibc: IbcQuery<PenumbraHost>,
pub tendermint_proxy: TendermintProxy,
pub enable_expensive_rpc: bool,
}

impl Routes {
/// Returns a [`Routes`] that can be used to service requests.
pub fn build(self) -> Result<tonic::transport::server::Routes, anyhow::Error> {
let Self {
storage,
ibc,
tendermint_proxy,
enable_expensive_rpc,
} = self;

let routes = tonic::transport::server::Routes::new(we(AppQueryServiceServer::new(
self::Server::new(storage.clone()),
)))
.add_service(we(ChainQueryServiceServer::new(ChainServer::new(
storage.clone(),
))))
.add_service(we(CompactBlockQueryServiceServer::new(
CompactBlockServer::new(storage.clone()),
)))
.add_service(we(DexQueryServiceServer::new(DexServer::new(
storage.clone(),
))))
.add_service(we(GovernanceQueryServiceServer::new(
GovernanceServer::new(storage.clone()),
)))
.add_service(we(SctQueryServiceServer::new(SctServer::new(
storage.clone(),
))))
.add_service(we(ShieldedPoolQueryServiceServer::new(
ShieldedPoolServer::new(storage.clone()),
)))
.add_service(we(StakeQueryServiceServer::new(StakeServer::new(
storage.clone(),
))))
.add_service(we(ClientQueryServer::new(ibc.clone())))
.add_service(we(ChannelQueryServer::new(ibc.clone())))
.add_service(we(ConnectionQueryServer::new(ibc.clone())))
.add_service(we(TendermintProxyServiceServer::new(tendermint_proxy)))
.add_service(we(tonic_reflection::server::Builder::configure()
.register_encoded_file_descriptor_set(penumbra_proto::FILE_DESCRIPTOR_SET)
.build()
.with_context(|| "could not configure grpc reflection service")?));

let routes = if enable_expensive_rpc {
routes.add_service(we(SimulationServiceServer::new(DexServer::new(
storage.clone(),
))))
} else {
routes
};

Ok(routes)
}
}

// TODO: Hide this and only expose a Router?
pub struct Server {
struct Server {
storage: Storage,
}

Expand Down

0 comments on commit e8ab3aa

Please sign in to comment.