liminal-protocol 0.14.1

Shared participant-lifecycle protocol types for liminal
Documentation
use super::checkpoint::DigestParticipantView;
use super::test_support_external::{ExecutableRecoveredAttach, executable_recovered_attach};
use super::{
    ConversationGenesis, ConversationLifecycleView, LifecycleCapsule, LifecycleView,
    ParticipantConversation, SealedBindingFateToken,
};

fn fixture_capsule(fixture: &ExecutableRecoveredAttach) -> Result<LifecycleCapsule, &'static str> {
    let shell = ParticipantConversation::from_checkpoint(ConversationGenesis::new(1), 4, true);
    let closure = fixture.owner.closure_accounting().state();
    LifecycleCapsule::capture(&LifecycleView {
        sealed: None,
        conversation: &shell,
        covered_log_sequence: 3,
        lifecycle: Some(ConversationLifecycleView {
            participants: alloc::vec![DigestParticipantView::Live {
                member: &fixture.member,
                binding: &fixture.binding,
                detach_cell: &fixture.detach_cell,
                binding_origin: Some(&fixture.binding_origin),
            }],
            frontiers: fixture.owner.frontiers(),
            retained_record_limit: fixture.owner.retained_record_limit(),
            closure: &closure,
        }),
    })
    .map_err(|_| "recovered capsule capture refused")
}

#[test]
fn checkpoint_saved_fenced_predecessor_restores_before_its_sealed_token() -> Result<(), &'static str>
{
    let fixture = executable_recovered_attach().map_err(|_| "native fixture refused")?;
    let capsule = fixture_capsule(&fixture)?;
    let bytes = capsule.encode_canonical();
    let mut restored = LifecycleCapsule::decode_canonical(&bytes)
        .map_err(|_| "capsule decode refused")?
        .restore()
        .map_err(|_| "joint restore refused")?;
    let proof = restored
        .restore_checkpoint_fenced_attach(fixture.fenced_predecessor, &fixture.marker_source)
        .map_err(|_| "saved native fenced source refused")?;
    let token = fixture
        .fate_token
        .encode_checkpoint()
        .map_err(|_| "token capture refused")?;
    let decoded = SealedBindingFateToken::restore_checkpoint(
        &token,
        &fixture.binding_origin,
        fixture.member.cursor(),
        Some(proof),
    )
    .map_err(|_| "saved recovered token refused")?;
    assert_eq!(
        decoded
            .encode_checkpoint()
            .map_err(|_| "token recapture refused")?,
        token
    );
    assert_eq!(decoded, fixture.fate_token);
    assert!(
        restored
            .restore_checkpoint_fenced_attach(fixture.fenced_predecessor, &fixture.marker_source)
            .is_err()
    );
    Ok(())
}

#[test]
fn checkpoint_saved_fenced_source_refusals_preserve_the_joint_owner() -> Result<(), &'static str> {
    let fixture = executable_recovered_attach().map_err(|_| "native fixture refused")?;
    let mut restored = fixture_capsule(&fixture)?
        .restore()
        .map_err(|_| "joint restore refused")?;
    let mut foreign = fixture.fenced_predecessor;
    foreign.participant_id += 1;
    assert!(
        restored
            .restore_checkpoint_fenced_attach(foreign, &fixture.marker_source)
            .is_err()
    );
    let mut altered = fixture.marker_source.clone();
    let byte = altered.last_mut().ok_or("marker source absent")?;
    *byte ^= 1;
    assert!(
        restored
            .restore_checkpoint_fenced_attach(fixture.fenced_predecessor, &altered)
            .is_err()
    );
    let mut invalid = fixture.fenced_predecessor;
    invalid.predecessor_debt = crate::algebra::WideResourceVector::new(0, 0);
    assert!(
        restored
            .restore_checkpoint_fenced_attach(invalid, &fixture.marker_source)
            .is_err()
    );
    assert!(
        restored
            .restore_checkpoint_fenced_attach(fixture.fenced_predecessor, &fixture.marker_source)
            .is_ok()
    );
    Ok(())
}