Skip to main content

trustless_protocol/
handler.rs

1/// Trait for implementing a key provider.
2///
3/// Implement this trait and pass it to [`run`] to start the provider event loop.
4/// See `trustless-provider-filesystem` for a complete example.
5pub trait Handler: Send + Sync {
6    /// Handle an `initialize` request. Return all available certificates.
7    fn initialize(
8        &self,
9    ) -> impl std::future::Future<
10        Output = Result<crate::message::InitializeResult, crate::message::ErrorCode>,
11    > + Send;
12
13    /// Handle a `sign` request. Sign the blob using the specified certificate and scheme.
14    fn sign(
15        &self,
16        params: crate::message::SignParams,
17    ) -> impl std::future::Future<
18        Output = Result<crate::message::SignResult, crate::message::ErrorCode>,
19    > + Send;
20}
21
22/// Main event loop for a key provider process.
23///
24/// Reads requests from stdin, dispatches to the [`Handler`], and writes responses to stdout.
25/// Returns `Ok(())` when stdin reaches EOF (i.e., the proxy closed the connection).
26pub async fn run(handler: impl Handler) -> Result<(), crate::error::Error> {
27    let stdin = tokio::io::stdin();
28    let stdout = tokio::io::stdout();
29
30    let mut reader = crate::codec::framed_read(stdin);
31    let mut writer = crate::codec::framed_write(stdout);
32
33    loop {
34        let request: crate::message::Request = match crate::codec::recv_message(&mut reader).await {
35            Ok(req) => req,
36            Err(crate::error::Error::ProcessExited) => break,
37            Err(e) => return Err(e),
38        };
39
40        let id = request.id();
41
42        let response = match request {
43            crate::message::Request::Initialize { .. } => crate::message::Response::initialize(
44                id,
45                handler
46                    .initialize()
47                    .await
48                    .map_err(crate::message::ErrorPayload::from),
49            ),
50            crate::message::Request::Sign { params, .. } => crate::message::Response::sign(
51                id,
52                handler
53                    .sign(params)
54                    .await
55                    .map_err(crate::message::ErrorPayload::from),
56            ),
57        };
58
59        crate::codec::send_message(&mut writer, &response).await?;
60    }
61
62    Ok(())
63}