cdk_signatory/
embedded.rs1use std::sync::Arc;
4
5use cdk_common::{BlindSignature, BlindedMessage, Error, Proof};
6use tokio::sync::{mpsc, oneshot, watch};
7use tokio::task::JoinHandle;
8
9use crate::signatory::{RotateKeyArguments, Signatory, SignatoryKeySet, SignatoryKeysets};
10
11enum Request {
12 BlindSign(
13 (
14 Vec<BlindedMessage>,
15 oneshot::Sender<Result<Vec<BlindSignature>, Error>>,
16 ),
17 ),
18 VerifyProof((Vec<Proof>, oneshot::Sender<Result<(), Error>>)),
19 Keysets(oneshot::Sender<Result<SignatoryKeysets, Error>>),
20 SubscribeKeysets(oneshot::Sender<Result<watch::Receiver<SignatoryKeysets>, Error>>),
21 RotateKeyset(
22 (
23 RotateKeyArguments,
24 oneshot::Sender<Result<SignatoryKeySet, Error>>,
25 ),
26 ),
27}
28
29#[allow(missing_debug_implementations)]
35pub struct Service {
36 pipeline: mpsc::Sender<Request>,
37 runner: Option<JoinHandle<()>>,
38}
39
40impl Drop for Service {
41 fn drop(&mut self) {
42 if let Some(runner) = self.runner.take() {
43 runner.abort();
44 }
45 }
46}
47
48impl Service {
49 pub fn new(handler: Arc<dyn Signatory + Send + Sync>) -> Self {
52 let (tx, rx) = mpsc::channel(10_000);
53 let runner = Some(tokio::spawn(Self::runner(rx, handler)));
54
55 Self {
56 pipeline: tx,
57 runner,
58 }
59 }
60
61 #[tracing::instrument(skip_all)]
62 async fn runner(
63 mut receiver: mpsc::Receiver<Request>,
64 handler: Arc<dyn Signatory + Send + Sync>,
65 ) {
66 while let Some(request) = receiver.recv().await {
67 match request {
68 Request::BlindSign((blinded_message, response)) => {
69 let output = handler.blind_sign(blinded_message).await;
70 if response.send(output).is_err() {
71 tracing::error!("Error sending blind-sign response: receiver dropped");
72 }
73 }
74 Request::VerifyProof((proof, response)) => {
75 let output = handler.verify_proofs(proof).await;
76 if response.send(output).is_err() {
77 tracing::error!(
78 "Error sending proof-verification response: receiver dropped"
79 );
80 }
81 }
82 Request::Keysets(response) => {
83 let output = handler.keysets().await;
84 if response.send(output).is_err() {
85 tracing::error!("Error sending keysets response: receiver dropped");
86 }
87 }
88 Request::SubscribeKeysets(response) => {
89 let output = handler.subscribe_keysets().await;
90 if response.send(output).is_err() {
91 tracing::error!("Error sending keyset subscription");
92 }
93 }
94 Request::RotateKeyset((args, response)) => {
95 let output = handler.rotate_keyset(args).await;
96 if response.send(output).is_err() {
97 tracing::error!("Error sending keyset-rotation response: receiver dropped");
98 }
99 }
100 }
101 }
102 }
103}
104
105#[async_trait::async_trait]
106impl Signatory for Service {
107 fn name(&self) -> String {
108 "Embedded".to_owned()
109 }
110
111 #[tracing::instrument(skip_all)]
112 async fn blind_sign(
113 &self,
114 blinded_messages: Vec<BlindedMessage>,
115 ) -> Result<Vec<BlindSignature>, Error> {
116 let (tx, rx) = oneshot::channel();
117 self.pipeline
118 .send(Request::BlindSign((blinded_messages, tx)))
119 .await
120 .map_err(|e| Error::SendError(e.to_string()))?;
121
122 rx.await.map_err(|e| Error::RecvError(e.to_string()))?
123 }
124
125 #[tracing::instrument(skip_all)]
126 async fn verify_proofs(&self, proofs: Vec<Proof>) -> Result<(), Error> {
127 let (tx, rx) = oneshot::channel();
128 self.pipeline
129 .send(Request::VerifyProof((proofs, tx)))
130 .await
131 .map_err(|e| Error::SendError(e.to_string()))?;
132
133 rx.await.map_err(|e| Error::RecvError(e.to_string()))?
134 }
135
136 #[tracing::instrument(skip_all)]
137 async fn keysets(&self) -> Result<SignatoryKeysets, Error> {
138 let (tx, rx) = oneshot::channel();
139 self.pipeline
140 .send(Request::Keysets(tx))
141 .await
142 .map_err(|e| Error::SendError(e.to_string()))?;
143
144 rx.await.map_err(|e| Error::RecvError(e.to_string()))?
145 }
146
147 #[tracing::instrument(skip_all)]
148 async fn subscribe_keysets(&self) -> Result<watch::Receiver<SignatoryKeysets>, Error> {
149 let (tx, rx) = oneshot::channel();
150 self.pipeline
151 .send(Request::SubscribeKeysets(tx))
152 .await
153 .map_err(|e| Error::SendError(e.to_string()))?;
154
155 rx.await.map_err(|e| Error::RecvError(e.to_string()))?
156 }
157
158 #[tracing::instrument(skip(self))]
159 async fn rotate_keyset(&self, args: RotateKeyArguments) -> Result<SignatoryKeySet, Error> {
160 let (tx, rx) = oneshot::channel();
161 self.pipeline
162 .send(Request::RotateKeyset((args, tx)))
163 .await
164 .map_err(|e| Error::SendError(e.to_string()))?;
165
166 rx.await.map_err(|e| Error::RecvError(e.to_string()))?
167 }
168}