macroonz-harness 0.1.0

Safe-Rust property, fuzz, fault, schedule, mutation, network, and benchmark testing with typed evidence, reduction, and replay.
Documentation
//! Source-specific transcript reading against owner-built topology and schedule values.

use super::admit::lawful_entries;
use super::encode::{copy_of, source_of};
use super::{
    SimulationAction, SimulationManifest, TRANSCRIPT_FORMAT_VERSION, TRANSCRIPT_TAG,
    TranscriptAddress, TranscriptEntry, TranscriptMaterial, TranscriptPack, TranscriptRefusal,
    TranscriptSourceClaim,
};
use crate::descriptor::NamespacedName;
use crate::identity::ContentAddress;
use crate::network::simulation::{
    Link, LinkDiscipline, LinkFault, NetworkSchedule, NodeRef, SendOrdinal, Tick, Topology,
};

/// Read one live-recorded transcript envelope for the topology the caller expects.
///
/// The leading claim is settled before a member of the body is interpreted, and the body must declare the live-recorded source posture.
///
/// # Errors
///
/// Refuses every malformed envelope in reading order and a body whose source claim is not live-recorded.
pub fn read_recorded_live(
    expected: &Topology,
    encoded: &[u8],
) -> Result<TranscriptPack, TranscriptRefusal> {
    read_as(expected, None, TranscriptSourceClaim::RecordedLive, encoded)
}

/// Read one simulated transcript envelope for the topology and selected schedule the caller expects.
///
/// The static names remain owner-built values: foreign bytes are compared with the supplied schedule and never mint names.
/// Reading admits addressed declaration material only; [`crate::network::reproduce`] is the separate operation that can mint simulation standing.
///
/// # Errors
///
/// Refuses every malformed envelope in reading order, a body whose source claim is not simulated, or a schedule different from the owner-built expected value.
pub fn read_simulated(
    expected: &Topology,
    schedule: &NetworkSchedule,
    encoded: &[u8],
) -> Result<TranscriptPack, TranscriptRefusal> {
    read_as(
        expected,
        Some(schedule),
        TranscriptSourceClaim::Simulated,
        encoded,
    )
}

/// Read one envelope under the source-specific public road that called here.
fn read_as(
    expected: &Topology,
    schedule: Option<&NetworkSchedule>,
    source: TranscriptSourceClaim,
    encoded: &[u8],
) -> Result<TranscriptPack, TranscriptRefusal> {
    let (address, body) = addressed_body(encoded)?;
    let (material, entries) = read_body(expected, schedule, source, body)?;
    lawful_entries(expected, &entries)?;
    Ok(TranscriptPack::assembled(
        expected.clone(),
        material,
        address,
        entries,
        encoded.to_vec(),
    ))
}

/// Split the envelope at its address claim and keep the body only if the body derives that claim.
fn addressed_body(encoded: &[u8]) -> Result<(TranscriptAddress, &[u8]), TranscriptRefusal> {
    let width = ContentAddress::derived(TRANSCRIPT_TAG, &[])
        .as_bytes()
        .len();
    let Some((claimed, body)) = encoded.split_at_checked(width) else {
        return Err(TranscriptRefusal::Truncated);
    };
    let address = TranscriptAddress::derived(ContentAddress::derived(TRANSCRIPT_TAG, body));
    if claimed != address.address().as_bytes() {
        return Err(TranscriptRefusal::AddressMismatch { derived: address });
    }
    Ok((address, body))
}

/// Read every member the body declares under the source-specific public road.
fn read_body(
    expected: &Topology,
    expected_schedule: Option<&NetworkSchedule>,
    expected_source: TranscriptSourceClaim,
    body: &[u8],
) -> Result<(TranscriptMaterial, Vec<TranscriptEntry>), TranscriptRefusal> {
    let mut reader = BodyReader::over(body);
    let found = reader.u32()?;
    if found != TRANSCRIPT_FORMAT_VERSION {
        return Err(TranscriptRefusal::UnsupportedFormat { found });
    }
    let source = source_of(reader.u32()?)?;
    if source != expected_source {
        return Err(TranscriptRefusal::SourceClaimMismatch {
            expected: expected_source,
            found: source,
        });
    }
    read_topology(expected, &mut reader)?;
    let material = read_material(source, expected, expected_schedule, &mut reader)?;
    let entries = read_entries(expected, &mut reader)?;
    let trailing = reader.remaining();
    if trailing != 0usize {
        return Err(TranscriptRefusal::TrailingBytes { count: trailing });
    }
    Ok((material, entries))
}

/// Read source-specific material after the common header and topology.
fn read_material(
    source: TranscriptSourceClaim,
    expected: &Topology,
    expected_schedule: Option<&NetworkSchedule>,
    reader: &mut BodyReader<'_>,
) -> Result<TranscriptMaterial, TranscriptRefusal> {
    match source {
        TranscriptSourceClaim::RecordedLive => Ok(TranscriptMaterial::RecordedLive),
        TranscriptSourceClaim::Simulated => {
            let Some(schedule) = expected_schedule else {
                return Err(TranscriptRefusal::ScheduleMismatch);
            };
            read_schedule(schedule, reader)?;
            let actions = read_actions(expected, reader)?;
            Ok(TranscriptMaterial::Simulated(SimulationManifest::captured(
                schedule.clone(),
                actions,
            )))
        }
    }
}

/// Compare the encoded topology section with the owner-built expected value.
fn read_topology(
    expected: &Topology,
    reader: &mut BodyReader<'_>,
) -> Result<(), TranscriptRefusal> {
    let nodes = reader.count()?;
    if nodes != expected.nodes().len() {
        return Err(TranscriptRefusal::TopologyMismatch);
    }
    for node in expected.nodes() {
        read_expected_name(node.name(), reader, TranscriptRefusal::TopologyMismatch)?;
    }
    let links = reader.count()?;
    if links != expected.links().len() {
        return Err(TranscriptRefusal::TopologyMismatch);
    }
    for link in expected.links() {
        read_expected_link(*link, reader, TranscriptRefusal::TopologyMismatch)?;
    }
    Ok(())
}

/// Compare the encoded schedule section with the owner-built expected value.
fn read_schedule(
    expected: &NetworkSchedule,
    reader: &mut BodyReader<'_>,
) -> Result<(), TranscriptRefusal> {
    read_expected_name(expected.name(), reader, TranscriptRefusal::ScheduleMismatch)?;
    let count = reader.count()?;
    if count != expected.disciplines().len() {
        return Err(TranscriptRefusal::ScheduleMismatch);
    }
    for discipline in expected.disciplines() {
        read_discipline(discipline, reader)?;
    }
    Ok(())
}

/// Compare one encoded discipline and fault roster with the expected value.
fn read_discipline(
    expected: &LinkDiscipline,
    reader: &mut BodyReader<'_>,
) -> Result<(), TranscriptRefusal> {
    read_expected_link(expected.link(), reader, TranscriptRefusal::ScheduleMismatch)?;
    let count = reader.count()?;
    if count != expected.faults().len() {
        return Err(TranscriptRefusal::ScheduleMismatch);
    }
    for fault in expected.faults() {
        read_fault(*fault, reader)?;
    }
    Ok(())
}

/// Compare one encoded fault with its expected typed value.
fn read_fault(expected: LinkFault, reader: &mut BodyReader<'_>) -> Result<(), TranscriptRefusal> {
    let slot = reader.u32()?;
    let matches = match slot {
        0u32 => {
            expected
                == LinkFault::DropAt {
                    position: SendOrdinal::at(reader.u32()?),
                }
        }
        1u32 => {
            let position = SendOrdinal::at(reader.u32()?);
            let ticks = reader.u32()?;
            matches!(expected, LinkFault::DelayAt { position: expected_position, ticks: expected_ticks } if expected_position == position && expected_ticks.ticks() == ticks)
        }
        2u32 => {
            expected
                == LinkFault::DuplicateAt {
                    position: SendOrdinal::at(reader.u32()?),
                }
        }
        3u32 => {
            expected
                == LinkFault::Partition {
                    opens: Tick::at(reader.u64()?),
                    heals: Tick::at(reader.u64()?),
                }
        }
        found => return Err(TranscriptRefusal::UnknownFault { found }),
    };
    if !matches {
        return Err(TranscriptRefusal::ScheduleMismatch);
    }
    Ok(())
}

/// Read the complete action roster, resolving every send link against the expected topology.
fn read_actions(
    expected: &Topology,
    reader: &mut BodyReader<'_>,
) -> Result<Vec<SimulationAction>, TranscriptRefusal> {
    let count = reader.count()?;
    let mut actions = Vec::new();
    for at in 0..count {
        match reader.u32()? {
            0u32 => {
                let link = read_action_link(expected, at, reader)?;
                let payload = reader.bytes()?.to_vec();
                actions.push(SimulationAction::Send { link, payload });
            }
            1u32 => actions.push(SimulationAction::Advance),
            found => return Err(TranscriptRefusal::UnknownAction { found }),
        }
    }
    Ok(actions)
}

/// Read the entry roster, resolving each row's link against the expected topology.
fn read_entries(
    expected: &Topology,
    reader: &mut BodyReader<'_>,
) -> Result<Vec<TranscriptEntry>, TranscriptRefusal> {
    let count = reader.count()?;
    let mut entries = Vec::new();
    for at in 0..count {
        let link = read_entry_link(expected, at, reader)?;
        let ordinal = SendOrdinal::at(reader.u32()?);
        let payload = reader.bytes()?.to_vec();
        let sent_at = Tick::at(reader.u64()?);
        let delivered_at = Tick::at(reader.u64()?);
        let copy = copy_of(reader.u32()?)?;
        entries.push(TranscriptEntry::witnessed(
            link,
            ordinal,
            payload,
            sent_at,
            delivered_at,
            copy,
        ));
    }
    Ok(entries)
}

/// Read one expected name without minting names from foreign bytes.
fn read_expected_name(
    expected: NamespacedName,
    reader: &mut BodyReader<'_>,
    mismatch: TranscriptRefusal,
) -> Result<(), TranscriptRefusal> {
    let namespace = reader.bytes()?;
    let stem = reader.bytes()?;
    if namespace != expected.namespace().written().as_bytes()
        || stem != expected.stem().written().as_bytes()
    {
        return Err(mismatch);
    }
    Ok(())
}

/// Read one expected link without minting node names from foreign bytes.
fn read_expected_link(
    expected: Link,
    reader: &mut BodyReader<'_>,
    mismatch: TranscriptRefusal,
) -> Result<(), TranscriptRefusal> {
    read_expected_name(expected.from().name(), reader, mismatch)?;
    read_expected_name(expected.to().name(), reader, mismatch)
}

/// Resolve one action link from encoded name bytes.
fn read_action_link(
    expected: &Topology,
    at: usize,
    reader: &mut BodyReader<'_>,
) -> Result<Link, TranscriptRefusal> {
    read_link(expected, reader)?.ok_or(TranscriptRefusal::SimulationActionForeignLink { at })
}

/// Resolve one delivery-entry link from encoded name bytes.
fn read_entry_link(
    expected: &Topology,
    at: usize,
    reader: &mut BodyReader<'_>,
) -> Result<Link, TranscriptRefusal> {
    read_link(expected, reader)?.ok_or(TranscriptRefusal::ForeignLink { at })
}

/// Read four name parts and resolve them against the expected topology's links.
fn read_link(
    expected: &Topology,
    reader: &mut BodyReader<'_>,
) -> Result<Option<Link>, TranscriptRefusal> {
    let from_namespace = reader.bytes()?.to_vec();
    let from_stem = reader.bytes()?.to_vec();
    let to_namespace = reader.bytes()?.to_vec();
    let to_stem = reader.bytes()?.to_vec();
    Ok(expected
        .links()
        .iter()
        .find(|link| {
            spells(link.from(), &from_namespace, &from_stem)
                && spells(link.to(), &to_namespace, &to_stem)
        })
        .copied())
}

/// Whether this node's name is spelled by these two byte strings.
fn spells(node: NodeRef, namespace: &[u8], stem: &[u8]) -> bool {
    let name = node.name();
    name.namespace().written().as_bytes() == namespace && name.stem().written().as_bytes() == stem
}

/// A cursor over one body, which never indexes and never trusts a declared width.
struct BodyReader<'body> {
    body: &'body [u8],
    at: usize,
}

impl<'body> BodyReader<'body> {
    /// Open at the first body byte.
    const fn over(body: &'body [u8]) -> Self {
        Self { body, at: 0 }
    }

    /// Read one fixed-width 32-bit integer.
    fn u32(&mut self) -> Result<u32, TranscriptRefusal> {
        self.fixed::<4>().map(u32::from_be_bytes)
    }

    /// Read one fixed-width 64-bit integer.
    fn u64(&mut self) -> Result<u64, TranscriptRefusal> {
        self.fixed::<8>().map(u64::from_be_bytes)
    }

    /// Read one declared count, refused where the platform cannot index it.
    fn count(&mut self) -> Result<usize, TranscriptRefusal> {
        let declared = self.u64()?;
        usize::try_from(declared)
            .map_err(|_beyond_platform| TranscriptRefusal::LengthOutsidePlatform { declared })
    }

    /// Read one length-prefixed byte string.
    fn bytes(&mut self) -> Result<&'body [u8], TranscriptRefusal> {
        let length = self.count()?;
        self.take(length)
    }

    /// Read one fixed-width byte array.
    fn fixed<const WIDTH: usize>(&mut self) -> Result<[u8; WIDTH], TranscriptRefusal> {
        let bytes = self.take(WIDTH)?;
        <[u8; WIDTH]>::try_from(bytes).map_err(|_unexpected_width| TranscriptRefusal::Truncated)
    }

    /// Advance over exactly this many bytes, or refuse the envelope as truncated.
    fn take(&mut self, width: usize) -> Result<&'body [u8], TranscriptRefusal> {
        let Some(end) = self.at.checked_add(width) else {
            return Err(TranscriptRefusal::Truncated);
        };
        let Some(bytes) = self.body.get(self.at..end) else {
            return Err(TranscriptRefusal::Truncated);
        };
        self.at = end;
        Ok(bytes)
    }

    /// How many bytes are still unread.
    const fn remaining(&self) -> usize {
        self.body.len().saturating_sub(self.at)
    }
}