server.rs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. //! This module contains the generated gRPC server code for the Signatory service.
  2. use std::net::SocketAddr;
  3. use std::path::Path;
  4. use std::sync::Arc;
  5. use tokio::io::{AsyncRead, AsyncWrite};
  6. use tokio_stream::Stream;
  7. use tonic::metadata::MetadataMap;
  8. use tonic::transport::server::Connected;
  9. use tonic::transport::{Certificate, Identity, Server, ServerTlsConfig};
  10. use tonic::{Request, Response, Status};
  11. use crate::proto::{self, signatory_server};
  12. use crate::signatory::Signatory;
  13. /// The server implementation for the Signatory service.
  14. pub struct CdkSignatoryServer<S, T>
  15. where
  16. S: Signatory + Send + Sync + 'static,
  17. T: SignatoryLoader<S> + 'static,
  18. {
  19. loader: T,
  20. _phantom: std::marker::PhantomData<S>,
  21. }
  22. impl<S, T> CdkSignatoryServer<S, T>
  23. where
  24. S: Signatory + Send + Sync + 'static,
  25. T: SignatoryLoader<S> + 'static,
  26. {
  27. pub fn new(loader: T) -> Self {
  28. Self {
  29. loader,
  30. _phantom: std::marker::PhantomData,
  31. }
  32. }
  33. async fn load_signatory(&self, metadata: &MetadataMap) -> Result<Arc<S>, Status> {
  34. self.loader
  35. .load_signatory(metadata)
  36. .await
  37. .map_err(|_| Status::internal("Failed to load signatory"))
  38. }
  39. }
  40. #[tonic::async_trait]
  41. impl<S, T> signatory_server::Signatory for CdkSignatoryServer<S, T>
  42. where
  43. S: Signatory + Send + Sync + 'static,
  44. T: SignatoryLoader<S> + 'static,
  45. {
  46. #[tracing::instrument(skip_all)]
  47. async fn blind_sign(
  48. &self,
  49. request: Request<proto::BlindedMessages>,
  50. ) -> Result<Response<proto::BlindSignResponse>, Status> {
  51. let metadata = request.metadata();
  52. let signatory = self.load_signatory(metadata).await?;
  53. let result = match signatory
  54. .blind_sign(
  55. request
  56. .into_inner()
  57. .blinded_messages
  58. .into_iter()
  59. .map(|blind_message| blind_message.try_into())
  60. .collect::<Result<Vec<_>, _>>()?,
  61. )
  62. .await
  63. {
  64. Ok(blind_signatures) => proto::BlindSignResponse {
  65. sigs: Some(proto::BlindSignatures {
  66. blind_signatures: blind_signatures
  67. .into_iter()
  68. .map(|blind_sign| blind_sign.into())
  69. .collect(),
  70. }),
  71. ..Default::default()
  72. },
  73. Err(err) => proto::BlindSignResponse {
  74. error: Some(err.into()),
  75. ..Default::default()
  76. },
  77. };
  78. Ok(Response::new(result))
  79. }
  80. #[tracing::instrument(skip_all)]
  81. async fn verify_proofs(
  82. &self,
  83. request: Request<proto::Proofs>,
  84. ) -> Result<Response<proto::BooleanResponse>, Status> {
  85. let metadata = request.metadata();
  86. let signatory = self.load_signatory(metadata).await?;
  87. let result = match signatory
  88. .verify_proofs(
  89. request
  90. .into_inner()
  91. .proof
  92. .into_iter()
  93. .map(|x| x.try_into())
  94. .collect::<Result<Vec<_>, _>>()?,
  95. )
  96. .await
  97. {
  98. Ok(()) => proto::BooleanResponse {
  99. success: true,
  100. ..Default::default()
  101. },
  102. Err(cdk_common::Error::DHKE(_)) => proto::BooleanResponse {
  103. success: false,
  104. ..Default::default()
  105. },
  106. Err(err) => proto::BooleanResponse {
  107. error: Some(err.into()),
  108. ..Default::default()
  109. },
  110. };
  111. Ok(Response::new(result))
  112. }
  113. async fn keysets(
  114. &self,
  115. request: Request<proto::EmptyRequest>,
  116. ) -> Result<Response<proto::KeysResponse>, Status> {
  117. let metadata = request.metadata();
  118. let signatory = self.load_signatory(metadata).await?;
  119. let result = match signatory.keysets().await {
  120. Ok(result) => proto::KeysResponse {
  121. keysets: Some(result.into()),
  122. ..Default::default()
  123. },
  124. Err(err) => proto::KeysResponse {
  125. error: Some(err.into()),
  126. ..Default::default()
  127. },
  128. };
  129. Ok(Response::new(result))
  130. }
  131. async fn rotate_keyset(
  132. &self,
  133. request: Request<proto::RotationRequest>,
  134. ) -> Result<Response<proto::KeyRotationResponse>, Status> {
  135. let metadata = request.metadata();
  136. let signatory = self.load_signatory(metadata).await?;
  137. let mint_keyset_info = match signatory
  138. .rotate_keyset(request.into_inner().try_into()?)
  139. .await
  140. {
  141. Ok(result) => proto::KeyRotationResponse {
  142. keyset: Some(result.into()),
  143. ..Default::default()
  144. },
  145. Err(err) => proto::KeyRotationResponse {
  146. error: Some(err.into()),
  147. ..Default::default()
  148. },
  149. };
  150. Ok(Response::new(mint_keyset_info))
  151. }
  152. }
  153. /// Trait for loading a signatory instance from gRPC metadata
  154. #[async_trait::async_trait]
  155. pub trait SignatoryLoader<S>: Send + Sync {
  156. /// Loads the signatory instance based on the provided metadata.
  157. async fn load_signatory(&self, metadata: &MetadataMap) -> Result<Arc<S>, ()>;
  158. }
  159. #[async_trait::async_trait]
  160. impl<T> SignatoryLoader<T> for Arc<T>
  161. where
  162. T: Signatory + Send + Sync + 'static,
  163. {
  164. async fn load_signatory(&self, _metadata: &MetadataMap) -> Result<Arc<T>, ()> {
  165. Ok(self.clone())
  166. }
  167. }
  168. /// Error type for the gRPC server
  169. #[derive(thiserror::Error, Debug)]
  170. pub enum Error {
  171. /// Transport error
  172. #[error(transparent)]
  173. Transport(#[from] tonic::transport::Error),
  174. /// Io error
  175. #[error(transparent)]
  176. Io(#[from] std::io::Error),
  177. }
  178. /// Runs the signatory server
  179. pub async fn start_grpc_server<S, T, I: AsRef<Path>>(
  180. signatory_loader: T,
  181. addr: SocketAddr,
  182. tls_dir: Option<I>,
  183. ) -> Result<(), Error>
  184. where
  185. S: Signatory + Send + Sync + 'static,
  186. T: SignatoryLoader<S> + 'static,
  187. {
  188. tracing::info!("Starting RPC server {}", addr);
  189. let mut server = match tls_dir {
  190. Some(tls_dir) => {
  191. tracing::info!("TLS configuration found, starting secure server");
  192. let tls_dir = tls_dir.as_ref();
  193. let server_pem_path = tls_dir.join("server.pem");
  194. let server_key_path = tls_dir.join("server.key");
  195. let ca_pem_path = tls_dir.join("ca.pem");
  196. if !server_pem_path.exists() {
  197. tracing::error!(
  198. "Server certificate file does not exist: {}",
  199. server_pem_path.display()
  200. );
  201. return Err(Error::Io(std::io::Error::new(
  202. std::io::ErrorKind::NotFound,
  203. format!(
  204. "Server certificate file not found: {}",
  205. server_pem_path.display()
  206. ),
  207. )));
  208. }
  209. if !server_key_path.exists() {
  210. tracing::error!(
  211. "Server key file does not exist: {}",
  212. server_key_path.display()
  213. );
  214. return Err(Error::Io(std::io::Error::new(
  215. std::io::ErrorKind::NotFound,
  216. format!("Server key file not found: {}", server_key_path.display()),
  217. )));
  218. }
  219. if !ca_pem_path.exists() {
  220. tracing::error!(
  221. "CA certificate file does not exist: {}",
  222. ca_pem_path.display()
  223. );
  224. return Err(Error::Io(std::io::Error::new(
  225. std::io::ErrorKind::NotFound,
  226. format!("CA certificate file not found: {}", ca_pem_path.display()),
  227. )));
  228. }
  229. let cert = std::fs::read_to_string(&server_pem_path)?;
  230. let key = std::fs::read_to_string(&server_key_path)?;
  231. let client_ca_cert = std::fs::read_to_string(&ca_pem_path)?;
  232. let client_ca_cert = Certificate::from_pem(client_ca_cert);
  233. let server_identity = Identity::from_pem(cert, key);
  234. let tls_config = ServerTlsConfig::new()
  235. .identity(server_identity)
  236. .client_ca_root(client_ca_cert);
  237. Server::builder().tls_config(tls_config)?
  238. }
  239. None => {
  240. tracing::warn!("No valid TLS configuration found, starting insecure server");
  241. Server::builder()
  242. }
  243. };
  244. server
  245. .add_service(signatory_server::SignatoryServer::new(
  246. CdkSignatoryServer::new(signatory_loader),
  247. ))
  248. .serve(addr)
  249. .await?;
  250. Ok(())
  251. }
  252. /// Starts the gRPC signatory server with an incoming stream of connections.
  253. pub async fn start_grpc_server_with_incoming<S, T, I, IO, IE>(
  254. signatory_loader: T,
  255. incoming: I,
  256. ) -> Result<(), Error>
  257. where
  258. S: Signatory + Send + Sync + 'static,
  259. T: SignatoryLoader<S> + 'static,
  260. I: Stream<Item = Result<IO, IE>>,
  261. IO: AsyncRead + AsyncWrite + Connected + Unpin + Send + 'static,
  262. IE: Into<Box<dyn std::error::Error + Send + Sync>>,
  263. {
  264. Server::builder()
  265. .add_service(signatory_server::SignatoryServer::new(
  266. CdkSignatoryServer::new(signatory_loader),
  267. ))
  268. .serve_with_incoming(incoming)
  269. .await?;
  270. Ok(())
  271. }