Skip to main content

keri_controller/identifier/
nontransferable.rs

1use std::sync::Arc;
2
3use crate::{
4    communication::Communication, error::ControllerError, BasicPrefix, IdentifierPrefix,
5    LocationScheme, SelfSigningPrefix,
6};
7use keri_core::{
8    actor::{
9        possible_response::PossibleResponse,
10        prelude::{HashFunctionCode, SerializationFormats},
11    },
12    event_message::{
13        msg::KeriEvent,
14        signature::{Nontransferable, Signature},
15        timestamped::Timestamped,
16    },
17    oobi::Scheme,
18    query::query_event::{LogsQueryArgs, QueryEvent, QueryRoute, SignedKelQuery},
19};
20use teliox::query::{SignedTelQuery, TelQueryArgs, TelQueryEvent, TelQueryRoute};
21
22use super::mechanics::MechanicsError;
23
24pub struct NontransferableIdentifier {
25    id: BasicPrefix,
26    communication: Arc<Communication>,
27}
28
29impl NontransferableIdentifier {
30    pub fn new(public_key: BasicPrefix, communication: Arc<Communication>) -> Self {
31        Self {
32            id: public_key,
33            communication,
34        }
35    }
36
37    pub fn sign(&self, signature: Vec<u8>) -> Signature {
38        Signature::NonTransferable(Nontransferable::Couplet(vec![(
39            self.id.clone(),
40            SelfSigningPrefix::Ed25519Sha512(signature),
41        )]))
42    }
43
44    pub fn query_log(
45        &self,
46        identifier: IdentifierPrefix,
47        sn: u64,
48        limit: u64,
49        witness: BasicPrefix,
50    ) -> QueryEvent {
51        QueryEvent::new_query(
52            QueryRoute::Logs {
53                reply_route: "".to_string(),
54                args: LogsQueryArgs {
55                    s: Some(sn),
56                    i: identifier,
57                    src: Some(IdentifierPrefix::Basic(witness)),
58                    limit: Some(limit),
59                },
60            },
61            SerializationFormats::JSON,
62            HashFunctionCode::Blake3_256,
63        )
64    }
65
66    pub fn query_ksn(&self, id: &IdentifierPrefix, witness: BasicPrefix) -> QueryEvent {
67        QueryEvent::new_query(
68            QueryRoute::Ksn {
69                reply_route: "".to_string(),
70                args: LogsQueryArgs {
71                    s: None,
72                    i: id.clone(),
73                    src: Some(IdentifierPrefix::Basic(witness)),
74                    limit: None,
75                },
76            },
77            SerializationFormats::JSON,
78            HashFunctionCode::Blake3_256,
79        )
80    }
81
82    pub async fn finalize_query(
83        &self,
84        witness: LocationScheme,
85        qry: QueryEvent,
86        signature: Signature,
87    ) -> Result<PossibleResponse, ControllerError> {
88        self.communication.resolve_loc_schema(&witness).await?;
89        let signed_qry = SignedKelQuery {
90            query: qry,
91            signature: signature,
92        };
93
94        Ok(self
95            .communication
96            .send_query_to(&witness.eid, Scheme::Http, signed_qry)
97            .await?)
98    }
99
100    pub fn query_tel(
101        &self,
102        registry_id: IdentifierPrefix,
103        vc_identifier: Option<IdentifierPrefix>,
104    ) -> Result<TelQueryEvent, ControllerError> {
105        let route = TelQueryRoute::Tels {
106            reply_route: "".into(),
107            args: TelQueryArgs {
108                i: vc_identifier,
109                ri: Some(registry_id),
110            },
111        };
112        let env = Timestamped::new(route);
113        Ok(KeriEvent::new(
114            SerializationFormats::JSON,
115            HashFunctionCode::Blake3_256.into(),
116            env,
117        ))
118    }
119
120    pub async fn finalize_query_tel(
121        &self,
122        witness_location: LocationScheme,
123        qry: TelQueryEvent,
124        sig: Signature,
125    ) -> Result<String, MechanicsError> {
126        let signed_qry = SignedTelQuery {
127            query: qry,
128            signature: sig,
129        };
130
131        let tel_res = self
132            .communication
133            .send_tel_query(signed_qry, witness_location)
134            .await
135            .map_err(|e| MechanicsError::OtherError(e.to_string()))?;
136        Ok(tel_res)
137    }
138}