xmtp_mls/groups/
message_id.rs1use xmtp_db::group_intent::IntentKind;
2
3use crate::groups::intents::{IntentError, SendMessageIntentData};
4use prost::Message;
5use xmtp_proto::xmtp::mls::message_contents::PlaintextEnvelope;
6use xmtp_proto::xmtp::mls::message_contents::plaintext_envelope::Content;
7
8const MESSAGE_ID_HEX_LEN: usize = 64;
10
11pub fn decode_message_reference(reference: &str) -> Option<Vec<u8>> {
15 if reference.len() != MESSAGE_ID_HEX_LEN {
16 return None;
17 }
18 hex::decode(reference)
19 .ok()
20 .filter(|id| id.len() == MESSAGE_ID_HEX_LEN / 2)
21}
22
23pub fn calculate_message_id(
26 group_id: impl AsRef<[u8]>,
27 decrypted_message_bytes: &[u8],
28 idempotency_key: &str,
29) -> Vec<u8> {
30 use sha2::{Digest, Sha256};
31 let separator = b"\t";
34 Sha256::new()
35 .chain_update(group_id.as_ref())
36 .chain_update(separator)
37 .chain_update(idempotency_key.as_bytes())
38 .chain_update(separator)
39 .chain_update(decrypted_message_bytes)
40 .finalize()
41 .to_vec()
42}
43
44pub fn calculate_message_id_for_intent(
55 intent: &xmtp_db::group_intent::StoredGroupIntent,
56) -> Result<Option<Vec<u8>>, IntentError> {
57 if intent.kind != IntentKind::SendMessage {
58 return Ok(None);
59 }
60
61 let data = SendMessageIntentData::from_bytes(intent.data.as_slice())?;
62 let envelope: PlaintextEnvelope = PlaintextEnvelope::decode(data.message.as_slice())?;
63
64 let Some(Content::V1(v1)) = &envelope.content else {
68 return Ok(None);
69 };
70 Ok(Some(calculate_message_id(
71 intent.group_id,
72 &v1.content,
73 &v1.idempotency_key,
74 )))
75}