minerva 0.2.0

Causal ordering for distributed systems
use crate::metis::DotSet;

/// Evidence that a context was received from a named peer.
///
/// A `Received` records two facts a receive path can *prove*: which peer the
/// evidence came from, and the [`DotSet`] context that peer demonstrably held
/// (a peer cannot ship what it has not seen, so the context of a delta *it*
/// sent is a lower bound on what it holds). Both fields are private, so the
/// only way to obtain one carrying a real receipt is the receive path,
/// [`Composer::absorb`](crate::metis::Composer::absorb), which testifies to
/// exactly what it merged. [`Purview::note`](super::Purview::note) reads the
/// peer *out of* the evidence. That makes two hazards unrepresentable, both of
/// which prose used to guard: over-claiming a context the peer never had, and
/// misattributing a context to the wrong peer. There is no way to hand `note`
/// a bare [`DotSet`] paired with an arbitrary station id.
///
/// This is the receive-side twin of [`Cut`](crate::metis::Cut): a witness minted
/// only where the proof exists, guarding a downstream read that would otherwise
/// trust an unaudited claim. The one deliberate door out of that discipline is
/// [`trust`](Self::trust); see its warning.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Received {
    /// The peer this evidence came from: the station whose row a
    /// [`note`](super::Purview::note) of this evidence raises.
    from: u32,
    /// The context that peer demonstrably held (a lower bound on what it has
    /// seen), read into the row by [`note`](super::Purview::note).
    context: DotSet,
}

impl Received {
    /// The peer this evidence came from.
    #[must_use]
    pub const fn from(&self) -> u32 {
        self.from
    }

    /// Borrows the received context: the dots the peer demonstrably held.
    #[must_use]
    pub const fn context(&self) -> &DotSet {
        &self.context
    }

    /// Mints receive-evidence directly, *asserting* that `from` has seen
    /// `context` on the caller's word alone.
    ///
    /// The single audited escape, the receive-side analogue of
    /// [`Scoped::forget`](crate::metis::Scoped::forget) and
    /// [`Cut::into_vector`](crate::metis::Cut::into_vector): every other
    /// `Received` carries a proof from the receive path, and this one carries
    /// only the caller's claim. Its use is a full-state anti-entropy exchange,
    /// where a peer hands over its whole state out of band and the receiver has
    /// genuine grounds, an ack round or a quorum sweep, to vouch that the peer
    /// held that context. The name is the warning: an over-claim minted here
    /// makes [`Purview::note`](super::Purview::note) raise a row past what the
    /// peer actually holds, and [`owed`](super::Purview::owed) then *under*-ships,
    /// stalling convergence silently (the unsafe direction the tracker warns
    /// about). Reach for it only where the receive path cannot, and where the
    /// burden of honesty is the caller's to carry.
    #[must_use]
    pub const fn trust(from: u32, context: DotSet) -> Self {
        Self { from, context }
    }

    /// Mints receive-evidence from a proven receipt: `from` shipped a delta or
    /// state whose context was `context`, so it demonstrably held `context`.
    ///
    /// Crate-internal because the proof is the receive path's to make: the
    /// public receive path [`Composer::absorb`](crate::metis::Composer::absorb)
    /// mints through here, and the public escape [`trust`](Self::trust) carries
    /// the audit warning. There is no unaudited public constructor.
    pub(crate) const fn witness(from: u32, context: DotSet) -> Self {
        Self { from, context }
    }
}