minerva 0.2.0

Causal ordering for distributed systems
//! Lineage-proof construction and generation-sequence validation.

use super::*;

/// The lawful fresh-fleet proof is header-only.
#[test]
fn test_lineage_proof_empty_frame() {
    let proof = LineageProofRecord::try_new(Vec::new()).unwrap();
    assert!(proof.is_empty());
    let frame = proof.to_bytes();
    assert_eq!(frame, [0x01, 0x00, 0x00, 0x00, 0x00]);
    assert_eq!(proof.encoded_len(), frame.len());
    assert_eq!(LineageProofRecord::from_bytes(&frame), Ok(proof));
}

/// Construction and decoding share the consecutive-generation validator.
#[test]
fn test_lineage_proof_refuses_non_consecutive_generations() {
    let (_, sealed) = displaced_window();
    let entry = LineageProofEntry::new(SealRecord::from_sealed(&sealed), [0x00; 32]);
    let outcome = LineageProofRecord::try_new(vec![entry.clone(), entry]);
    assert_eq!(
        outcome,
        Err(LineageProofDecodeError::NonConsecutiveGenerations {
            previous: 1,
            found: 1
        })
    );
}

/// Checked succession rejects a repeated `u64::MAX`; saturation would accept it.
#[test]
fn test_lineage_proof_refuses_a_repeated_ceiling_generation() {
    // A minimal seal frame at the generation ceiling: winner address
    // (u64::MAX, (1, 1)), no candidates, no ledger dots, empty join.
    let mut seal_frame = vec![0x01];
    seal_frame.extend_from_slice(&u64::MAX.to_be_bytes());
    seal_frame.extend_from_slice(&1u32.to_be_bytes());
    seal_frame.extend_from_slice(&1u64.to_be_bytes());
    seal_frame.extend_from_slice(&0u32.to_be_bytes()); // candidates
    seal_frame.extend_from_slice(&0u32.to_be_bytes()); // ledger
    seal_frame.extend_from_slice(&[0x01, 0, 0, 0, 0]); // empty join
    let seal = SealRecord::from_bytes(&seal_frame).unwrap();
    assert_eq!(seal.declaration().generation(), u64::MAX);

    let entry = LineageProofEntry::new(seal, [0x00; 32]);
    assert_eq!(
        LineageProofRecord::try_new(vec![entry.clone(), entry]),
        Err(LineageProofDecodeError::NonConsecutiveGenerations {
            previous: u64::MAX,
            found: u64::MAX
        })
    );

    let mut frame = vec![0x01];
    frame.extend_from_slice(&2u32.to_be_bytes());
    for _ in 0..2 {
        frame.extend_from_slice(&[0x00; 32]);
        frame.extend_from_slice(&seal_frame);
    }
    assert_eq!(
        LineageProofRecord::from_bytes(&frame),
        Err(LineageProofDecodeError::NonConsecutiveGenerations {
            previous: u64::MAX,
            found: u64::MAX
        })
    );
}