simperby_network/dms/
messages.rs

1use std::fmt::Debug;
2
3use super::*;
4use serde::{de::DeserializeOwned, ser::Serialize};
5
6pub type DmsKey = String;
7
8pub trait DmsMessage:
9    Send + Sync + 'static + ToHash256 + Serialize + DeserializeOwned + Debug
10{
11    /// The tag for the DMS instance that handles this message.
12    ///
13    /// The DMS key will be deduced using this data and the hash of the last finalized header.
14    const DMS_TAG: &'static str;
15
16    /// Checks if the message is valid.
17    fn check(&self) -> Result<(), Error>;
18
19    /// Defines how to commit a message, by cryptographically signing it.
20    ///
21    /// In case that the message can't be guaranteed to be unique among other protocols,
22    /// this method provides `dms_key` to be used as a unique identifier.
23    ///
24    /// One potential use case other than the default implementation which ignores `dms_key`
25    /// is when the messages of which the signature is presented to another protocol,
26    /// so not aggregating `dms_key`, (which is a very specific implementation detail of of DMS)
27    /// makes sense.
28    /// Of course, the message must be guaranteed to be unique so that the signature can't be replayed
29    /// on another height or another chain.
30    fn commit(
31        &self,
32        dms_key: &DmsKey,
33        private_key: &PrivateKey,
34    ) -> Result<MessageCommitmentProof, CryptoError>
35    where
36        Self: Sized,
37    {
38        let hash = self.to_hash256();
39        Signature::sign(hash.aggregate(&dms_key.to_hash256()), private_key).map(|signature| {
40            MessageCommitmentProof {
41                committer: private_key.public_key(),
42                signature,
43            }
44        })
45    }
46
47    /// It must match the `commit()` method if you implemented it.
48    fn verify_commitment(
49        &self,
50        proof: &MessageCommitmentProof,
51        dms_key: &DmsKey,
52    ) -> Result<(), CryptoError> {
53        proof.signature.verify(
54            self.to_hash256().aggregate(&dms_key.to_hash256()),
55            &proof.committer,
56        )
57    }
58}
59
60/// A message that the user of DMS observes.
61#[derive(Debug, Clone, PartialEq, Eq)]
62pub struct Message<T: DmsMessage> {
63    pub message: T,
64    pub committers: Vec<MessageCommitmentProof>,
65}
66
67#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
68pub struct MessageCommitmentProof {
69    pub committer: PublicKey,
70    pub signature: Signature,
71}
72
73/// The physical packet that is sent over the network.
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct Packet {
76    /// The original message data encoded in `serde_spb`.
77    pub message: Vec<u8>,
78    /// Commitment to the message with the proof.
79    pub commitment: MessageCommitmentProof,
80}
81
82impl ToHash256 for Packet {
83    fn to_hash256(&self) -> Hash256 {
84        Hash256::hash(serde_spb::to_vec(self).unwrap())
85    }
86}
87
88#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
89pub struct MessageMetadata {
90    pub message_hash: Hash256,
91    pub committers: Vec<MessageCommitmentProof>,
92}