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    ///
8    /// This method may be called multiple times on the same provider process
9    /// to reload certificates. Implementations should return the current set
10    /// of available certificates each time.
11    fn initialize(
12        &self,
13    ) -> impl std::future::Future<
14        Output = Result<crate::message::InitializeResult, crate::message::ErrorCode>,
15    > + Send;
16
17    /// Handle a `sign` request. Sign the blob using the specified certificate and scheme.
18    fn sign(
19        &self,
20        params: crate::message::SignParams,
21    ) -> impl std::future::Future<
22        Output = Result<crate::message::SignResult, crate::message::ErrorCode>,
23    > + Send;
24}
25
26/// Main event loop for a key provider process.
27///
28/// Reads requests from stdin, dispatches to the [`Handler`], and writes responses to stdout.
29/// Returns `Ok(())` when stdin reaches EOF (i.e., the proxy closed the connection).
30pub async fn run(handler: impl Handler) -> Result<(), crate::error::Error> {
31    let stdin = tokio::io::stdin();
32    let stdout = tokio::io::stdout();
33
34    let mut reader = crate::codec::framed_read(stdin);
35    let mut writer = crate::codec::framed_write(stdout);
36
37    loop {
38        let request: crate::message::Request = match crate::codec::recv_message(&mut reader).await {
39            Ok(req) => req,
40            Err(crate::error::Error::ProcessExited) => break,
41            Err(e) => return Err(e),
42        };
43
44        let id = request.id();
45
46        let response = match request {
47            crate::message::Request::Initialize { .. } => crate::message::Response::initialize(
48                id,
49                handler
50                    .initialize()
51                    .await
52                    .map_err(crate::message::ErrorPayload::from),
53            ),
54            crate::message::Request::Sign { params, .. } => crate::message::Response::sign(
55                id,
56                handler
57                    .sign(params)
58                    .await
59                    .map_err(crate::message::ErrorPayload::from),
60            ),
61        };
62
63        crate::codec::send_message(&mut writer, &response).await?;
64    }
65
66    Ok(())
67}