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