liminal-protocol 0.3.2

Shared participant-lifecycle protocol types for liminal
Documentation
use super::{
    ActiveIdentityRanks, BindingEpoch, ClaimFrontiers, DeliverySeq, FrontierBinding,
    FrontierParticipant, LiveFrontierTransitionError, ParticipantId,
};

pub(in crate::lifecycle) struct BindingFateFrontierPlan {
    active_identities: ActiveIdentityRanks,
    resulting_floor: u128,
}

impl ClaimFrontiers {
    pub(in crate::lifecycle) fn prepare_binding_fate_transition(
        &self,
        participant_id: ParticipantId,
        binding_epoch: BindingEpoch,
        cursor: DeliverySeq,
        resulting_floor: DeliverySeq,
        reserve_finalizer: bool,
    ) -> Result<BindingFateFrontierPlan, LiveFrontierTransitionError> {
        let mut participants = self.active_identities.participants().to_vec();
        let Some(participant) = participants
            .iter_mut()
            .find(|participant| participant.participant_index() == participant_id)
        else {
            return Err(LiveFrontierTransitionError::Authority);
        };
        if participant.cursor() != cursor
            || participant.binding() != FrontierBinding::Detached(binding_epoch)
        {
            return Err(LiveFrontierTransitionError::Authority);
        }
        let high_watermark = self.sequence.ledger().high_watermark();
        let resulting_floor = u128::from(resulting_floor);
        let retained_end = u128::from(high_watermark) + 1;
        if resulting_floor < self.retained_floor || resulting_floor > retained_end {
            return Err(LiveFrontierTransitionError::ResultingFrontier);
        }
        if self
            .marker_records
            .iter()
            .any(|record| u128::from(record.delivery_seq) < resulting_floor)
        {
            return Err(LiveFrontierTransitionError::Precedence);
        }
        let resulting_cursor = if reserve_finalizer {
            cursor
        } else {
            high_watermark
        };
        *participant = FrontierParticipant::new(
            participant_id,
            resulting_cursor,
            FrontierBinding::Detached(binding_epoch),
        );
        let active_identities =
            ActiveIdentityRanks::try_new(participants, high_watermark, self.identity_slot_limit)
                .map_err(|_| LiveFrontierTransitionError::Authority)?;
        Ok(BindingFateFrontierPlan {
            active_identities,
            resulting_floor,
        })
    }

    pub(in crate::lifecycle) fn install_binding_fate_transition(
        mut self,
        plan: BindingFateFrontierPlan,
    ) -> Self {
        self.active_identities = plan.active_identities;
        self.retained_floor = plan.resulting_floor;
        self.retained_records
            .retain(|record| u128::from(record.delivery_seq) >= plan.resulting_floor);
        self.marker_records
            .retain(|record| u128::from(record.delivery_seq) >= plan.resulting_floor);
        self
    }

    pub(in crate::lifecycle) fn install_finalized_binding_fate_floor(
        mut self,
        resulting_floor: DeliverySeq,
    ) -> Result<Self, LiveFrontierTransitionError> {
        let resulting_floor = u128::from(resulting_floor);
        let retained_end = u128::from(self.sequence.ledger().high_watermark()) + 1;
        if resulting_floor < self.retained_floor || resulting_floor > retained_end {
            return Err(LiveFrontierTransitionError::ResultingFrontier);
        }
        if self
            .marker_records
            .iter()
            .any(|record| u128::from(record.delivery_seq) < resulting_floor)
        {
            return Err(LiveFrontierTransitionError::Precedence);
        }
        self.retained_floor = resulting_floor;
        self.retained_records
            .retain(|record| u128::from(record.delivery_seq) >= resulting_floor);
        self.marker_records
            .retain(|record| u128::from(record.delivery_seq) >= resulting_floor);
        Ok(self)
    }
}