Skip to main content

guardian_shared/
auth_request_message.rs

1use crate::auth_request_payload::AuthRequestPayload;
2use miden_protocol::account::AccountId;
3use miden_protocol::crypto::hash::rpo::Rpo256;
4use miden_protocol::{Felt, Word};
5use serde::Serialize;
6
7#[derive(Clone, Debug, PartialEq, Eq)]
8pub struct AuthRequestMessage {
9    account_id: AccountId,
10    timestamp: i64,
11    payload: AuthRequestPayload,
12}
13
14impl AuthRequestMessage {
15    pub fn new(account_id: AccountId, timestamp: i64, payload: AuthRequestPayload) -> Self {
16        Self {
17            account_id,
18            timestamp,
19            payload,
20        }
21    }
22
23    pub fn from_account_id_hex(
24        account_id_hex: &str,
25        timestamp: i64,
26        payload: AuthRequestPayload,
27    ) -> Result<Self, String> {
28        let account_id = AccountId::from_hex(account_id_hex)
29            .map_err(|e| format!("Invalid account ID hex: {e}"))?;
30        Ok(Self::new(account_id, timestamp, payload))
31    }
32
33    pub fn from_protobuf_message<T: prost::Message>(
34        account_id: AccountId,
35        timestamp: i64,
36        request: &T,
37    ) -> Self {
38        Self::new(
39            account_id,
40            timestamp,
41            AuthRequestPayload::from_protobuf_message(request),
42        )
43    }
44
45    pub fn from_json_serializable<T: Serialize>(
46        account_id: AccountId,
47        timestamp: i64,
48        request: &T,
49    ) -> Result<Self, String> {
50        let payload = AuthRequestPayload::from_json_serializable(request)?;
51        Ok(Self::new(account_id, timestamp, payload))
52    }
53
54    pub fn to_word(&self) -> Word {
55        let account_id_felts: [Felt; 2] = self.account_id.into();
56        let timestamp_felt = Felt::new(self.timestamp as u64);
57        let payload_elements = self.payload.as_elements();
58        let message_elements = vec![
59            account_id_felts[0],
60            account_id_felts[1],
61            timestamp_felt,
62            payload_elements[0],
63            payload_elements[1],
64            payload_elements[2],
65            payload_elements[3],
66        ];
67        Rpo256::hash_elements(&message_elements)
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::AuthRequestMessage;
74    use crate::auth_request_payload::AuthRequestPayload;
75    use miden_protocol::account::AccountId;
76
77    #[test]
78    fn request_message_digest_changes_with_payload() {
79        let account_id =
80            AccountId::from_hex("0x8a65fc5a39e4cd106d648e3eb4ab5f").expect("account id");
81        let timestamp = 1_700_000_000i64;
82        let left_payload =
83            AuthRequestPayload::from_json_bytes(br#"{"op":"get_state"}"#).expect("left payload");
84        let right_payload =
85            AuthRequestPayload::from_json_bytes(br#"{"op":"push_delta"}"#).expect("right payload");
86
87        let left = AuthRequestMessage::new(account_id, timestamp, left_payload).to_word();
88        let right = AuthRequestMessage::new(account_id, timestamp, right_payload).to_word();
89
90        assert_ne!(left, right);
91    }
92}