miden_node_rpc/server/
mod.rs1use std::time::Duration;
2
3use accept::AcceptHeaderLayer;
4use anyhow::Context;
5use miden_node_proto::generated::rpc::api_server;
6use miden_node_proto_build::rpc_api_descriptor;
7use miden_node_utils::cors::cors_for_grpc_web_layer;
8use miden_node_utils::panic::{CatchPanicLayer, catch_panic_layer_fn};
9use miden_node_utils::tracing::grpc::grpc_trace_fn;
10use tokio::net::TcpListener;
11use tokio_stream::wrappers::TcpListenerStream;
12use tonic_reflection::server;
13use tonic_web::GrpcWebLayer;
14use tower_http::trace::TraceLayer;
15use tracing::info;
16use url::Url;
17
18use crate::COMPONENT;
19use crate::server::health::HealthCheckLayer;
20
21mod accept;
22mod api;
23mod health;
24
25pub struct Rpc {
31 pub listener: TcpListener,
32 pub store_url: Url,
33 pub block_producer_url: Option<Url>,
34 pub validator_url: Url,
35 pub grpc_timeout: Duration,
39}
40
41impl Rpc {
42 pub async fn serve(self) -> anyhow::Result<()> {
47 let mut api = api::RpcService::new(
48 self.store_url.clone(),
49 self.block_producer_url.clone(),
50 self.validator_url,
51 );
52
53 let genesis = api
54 .get_genesis_header_with_retry()
55 .await
56 .context("Fetching genesis header from store")?;
57
58 api.set_genesis_commitment(genesis.commitment())?;
59
60 let api_service = api_server::ApiServer::new(api);
61 let reflection_service = server::Builder::configure()
62 .register_file_descriptor_set(rpc_api_descriptor())
63 .build_v1()
64 .context("failed to build reflection service")?;
65
66 let reflection_service_alpha = server::Builder::configure()
71 .register_file_descriptor_set(rpc_api_descriptor())
72 .build_v1alpha()
73 .context("failed to build reflection service")?;
74
75 info!(target: COMPONENT, endpoint=?self.listener, store=%self.store_url, block_producer=?self.block_producer_url, "Server initialized");
76
77 let rpc_version = env!("CARGO_PKG_VERSION");
78 let rpc_version =
79 semver::Version::parse(rpc_version).context("failed to parse crate version")?;
80
81 tonic::transport::Server::builder()
82 .accept_http1(true)
83 .timeout(self.grpc_timeout)
84 .layer(CatchPanicLayer::custom(catch_panic_layer_fn))
85 .layer(TraceLayer::new_for_grpc().make_span_with(grpc_trace_fn))
86 .layer(HealthCheckLayer)
87 .layer(cors_for_grpc_web_layer())
91 .layer(
92 AcceptHeaderLayer::new(&rpc_version, genesis.commitment())
93 .with_genesis_enforced_method("SubmitProvenTransaction")
94 .with_genesis_enforced_method("SubmitProvenBatch"),
95 )
96 .layer(GrpcWebLayer::new())
98 .add_service(api_service)
99 .add_service(reflection_service)
101 .add_service(reflection_service_alpha)
102 .serve_with_incoming(TcpListenerStream::new(self.listener))
103 .await
104 .context("failed to serve RPC API")
105 }
106}