omnimesh 1.0.1

Zero-allocation mesh networking middleware for autonomous robot fleets, edge-AI swarms, and multi-agent systems
Documentation
use super::header::EnvelopeHeader;
use super::wire::{ParseError, RawEnvelopeHeader};
use crate::buffer::PayloadStorage;
// Vec no longer needed as serialization writes to slice
use blake3::Hasher;
use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};

#[derive(Debug, Clone, Copy)]
pub struct SignedEnvelope<const N: usize> {
    pub header: EnvelopeHeader,
    pub payload: PayloadStorage<N>,
    pub signature: [u8; 64],
}

impl<const N: usize> SignedEnvelope<N> {
    pub const SIGNATURE_SIZE: usize = 64;

    pub fn new(header: EnvelopeHeader, payload: PayloadStorage<N>, signature: [u8; 64]) -> Self {
        SignedEnvelope {
            header,
            payload,
            signature,
        }
    }

    pub fn sign(header: EnvelopeHeader, payload: PayloadStorage<N>, keypair: &SigningKey) -> Self {
        let mut hasher = Hasher::new();
        hasher.update(&header.to_bytes());
        hasher.update(payload.as_slice());
        let hash = hasher.finalize();

        let signature = keypair.sign(hash.as_bytes());

        SignedEnvelope {
            header,
            payload,
            signature: signature.to_bytes(),
        }
    }

    pub fn hash_payload(&self) -> [u8; 32] {
        let mut hasher = Hasher::new();
        hasher.update(&self.header.to_bytes());
        hasher.update(self.payload.as_slice());
        hasher.finalize().into()
    }

    pub fn verify_signature(
        &self,
        public_key: &VerifyingKey,
    ) -> Result<(), ed25519_dalek::SignatureError> {
        let hash = self.hash_payload();
        let signature = Signature::from_bytes(&self.signature);
        public_key.verify(&hash, &signature)
    }

    pub fn serialize_into(&self, buf: &mut [u8]) -> Result<usize, ParseError> {
        let size = RawEnvelopeHeader::SIZE + self.payload.len() + Self::SIGNATURE_SIZE;
        if buf.len() < size {
            return Err(ParseError::PayloadOverflow);
        }

        let (header_slice, rest) = buf.split_at_mut(RawEnvelopeHeader::SIZE);
        header_slice.copy_from_slice(&self.header.to_bytes());

        let (payload_slice, sig_slice) = rest.split_at_mut(self.payload.len());
        payload_slice.copy_from_slice(self.payload.as_slice());

        sig_slice[..Self::SIGNATURE_SIZE].copy_from_slice(&self.signature);

        Ok(size)
    }

    pub fn deserialize(buf: &[u8]) -> Result<Self, ParseError> {
        let header = EnvelopeHeader::from_bytes(buf)?;
        let start_of_payload = RawEnvelopeHeader::SIZE;
        let end_of_signature = buf
            .len()
            .checked_sub(Self::SIGNATURE_SIZE)
            .ok_or(ParseError::Truncated)?;

        if end_of_signature < start_of_payload {
            return Err(ParseError::Truncated);
        }

        let payload = PayloadStorage::try_from_slice(&buf[start_of_payload..end_of_signature])
            .map_err(|_| ParseError::PayloadOverflow)?;

        let mut signature = [0u8; 64];
        signature.copy_from_slice(&buf[end_of_signature..]);

        Ok(SignedEnvelope {
            header,
            payload,
            signature,
        })
    }
}