use alloc::vec::Vec;
use crate::{algebra::ResourceVector, outcome::ParticipantStateCorruptReason};
use super::{
PhysicalCompaction, StoredEdge,
claim_frontier::{
ClaimFrontiers, ClaimFrontiersDescription, ExitProductRangeRestore, FrontierBinding,
HistoricalMarkerDeliveryFactRestore, ImmutableOrderCandidateMajorRestore,
MarkerRecordRequest, RecoveryOrderBlockRestore, RecoverySequenceBlock,
RecoverySequenceBlockRestore, ReplacementTerminalProductRangeRestore,
TerminalProductRangeRestore, ValidatedConversationHistory,
},
claim_frontier_tests::{
detached_dcr_fixture, epoch, initial_enrollment_operation, recovery_candidate_fixture,
single_bound_marker_fixture, two_participant_product_fixture,
},
};
const DCR_CONVERSATION_ID: u64 = 1;
fn restore_described(
description: ClaimFrontiersDescription,
) -> Result<ClaimFrontiers, ParticipantStateCorruptReason> {
let history = ValidatedConversationHistory::empty();
ClaimFrontiers::prevalidate_description(description, &history)?.finish(None)
}
fn assert_describes_live(
frontiers: &ClaimFrontiers,
description: &ClaimFrontiersDescription,
retained_record_limit: u64,
) {
let restore = &description.restore;
assert_eq!(restore.conversation_id, frontiers.conversation_id());
assert_eq!(
restore.active_identities.as_slice(),
frontiers.active_identities().participants()
);
assert_eq!(restore.identity_slot_limit, frontiers.identity_slot_limit());
assert_eq!(restore.retained_floor, frontiers.retained_floor());
assert_eq!(restore.retained_record_limit, retained_record_limit);
assert_eq!(
restore.retained_records.as_slice(),
frontiers.retained_records()
);
let anchors: Vec<_> = frontiers
.retained_marker_records()
.iter()
.map(|record| record.delivery_seq)
.collect();
assert_eq!(restore.active_marker_anchors, anchors);
let deliveries: Vec<_> = frontiers
.historical_marker_deliveries()
.iter()
.map(|authority| HistoricalMarkerDeliveryFactRestore {
conversation_id: frontiers.conversation_id(),
participant_index: authority.participant_index(),
marker_delivery_seq: authority.marker_delivery_seq(),
delivered_binding_epoch: authority.delivered_binding_epoch(),
})
.collect();
assert_eq!(restore.historical_marker_deliveries, deliveries);
assert_describes_live_sequence(frontiers, description);
assert_describes_live_order(frontiers, description);
}
fn assert_describes_live_sequence(
frontiers: &ClaimFrontiers,
description: &ClaimFrontiersDescription,
) {
let restore = &description.restore;
let sequence = frontiers.sequence();
assert_eq!(
restore.sequence.movable_claims.as_slice(),
sequence.movable_claims()
);
assert_eq!(
restore.sequence.immutable_candidates.as_slice(),
sequence.immutable_candidates()
);
let terminal_products: Vec<_> = sequence
.products()
.live_times_terminal()
.iter()
.map(|range| TerminalProductRangeRestore {
start: range.start(),
length: range.length(),
terminal: range.terminal(),
})
.collect();
assert_eq!(
restore.sequence.products.live_times_terminal,
terminal_products
);
assert_eq!(
restore.sequence.products.live_times_replacement_terminal,
sequence
.products()
.live_times_replacement_terminal()
.map(|range| ReplacementTerminalProductRangeRestore {
start: range.start(),
length: range.length(),
})
);
let exit_products: Vec<_> = sequence
.products()
.other_live_times_exit()
.iter()
.map(|range| ExitProductRangeRestore {
start: range.start(),
length: range.length(),
exit_participant: range.exit_participant(),
})
.collect();
assert_eq!(
restore.sequence.products.other_live_times_exit,
exit_products
);
assert_eq!(
restore.sequence.recovery,
sequence
.recovery()
.map(|block| RecoverySequenceBlockRestore {
terminal: block.terminal(),
recovery_attach_seq: block.recovery_attach_seq(),
replacement_terminal_seq: block.replacement_terminal_seq(),
})
);
assert_eq!(
restore.recovery_marker_delivery_seq,
sequence
.recovery()
.map(RecoverySequenceBlock::marker_delivery_seq)
);
assert_eq!(description.sequence_ledger, sequence.ledger());
}
fn assert_describes_live_order(
frontiers: &ClaimFrontiers,
description: &ClaimFrontiersDescription,
) {
let restore = &description.restore;
let order = frontiers.order();
assert_eq!(
restore.order.movable_claims.as_slice(),
order.movable_claims()
);
let order_candidates: Vec<_> = order
.immutable_candidates()
.iter()
.map(|major| ImmutableOrderCandidateMajorRestore {
transaction_order: major.transaction_order(),
candidate_keys: major.candidate_keys().to_vec(),
})
.collect();
assert_eq!(restore.order.immutable_candidates, order_candidates);
assert_eq!(
restore.order.recovery,
order.recovery().map(|block| RecoveryOrderBlockRestore {
active_binding: block.active_binding(),
recovery_operation_order: block.recovery_operation_order(),
replacement_terminal_order: block.replacement_terminal_order(),
})
);
assert_eq!(description.order_ledger, order.ledger());
}
#[test]
fn a_restored_marker_frontier_describes_its_exact_restore_input() -> Result<(), &'static str> {
for (marker_major, marker_above_high) in [(0, false), (1, true)] {
let (restore, sequence, order) =
single_bound_marker_fixture(marker_major, marker_above_high);
let frontiers = ClaimFrontiers::restore(restore.clone(), sequence, order)
.map_err(|_| "the bound marker fixture restores")?;
let description = frontiers.describe(restore.retained_record_limit);
assert_describes_live(&frontiers, &description, restore.retained_record_limit);
assert_eq!(
description.restore, restore,
"the input comes back unchanged"
);
assert_eq!(description.sequence_ledger, sequence);
assert_eq!(description.order_ledger, order);
assert_eq!(description.fenced_marker_issued, None);
let restored = restore_described(description)
.map_err(|_| "the description of a restored frontier restores")?;
assert_eq!(restored, frontiers);
}
Ok(())
}
#[test]
fn a_two_participant_product_frontier_round_trips() -> Result<(), &'static str> {
let (restore, sequence, order) = two_participant_product_fixture();
let frontiers = ClaimFrontiers::restore(restore.clone(), sequence, order)
.map_err(|_| "the two-participant product fixture restores")?;
let description = frontiers.describe(restore.retained_record_limit);
assert_describes_live(&frontiers, &description, restore.retained_record_limit);
assert_eq!(
description.restore, restore,
"the input comes back unchanged"
);
let restored =
restore_described(description).map_err(|_| "the described product frontier restores")?;
assert_eq!(restored, frontiers);
Ok(())
}
#[test]
fn a_drained_marker_frontier_describes_its_new_retained_anchor() -> Result<(), &'static str> {
let (restore, sequence, order) = single_bound_marker_fixture(0, false);
let frontiers = ClaimFrontiers::restore(restore, sequence, order)
.map_err(|_| "the bound marker fixture restores")?;
let (drained, _candidate, record) = frontiers
.drain_next_marker_core()
.map_err(|_| "the exact next bound marker drains")?
.into_parts();
record.consume();
let retained_record_limit = u64::try_from(drained.retained_records().len())
.map_err(|_| "the retained corpus fits u64")?;
let description = drained.describe(retained_record_limit);
assert_describes_live(&drained, &description, retained_record_limit);
assert_eq!(description.restore.active_marker_anchors, [1]);
assert!(description.restore.historical_causal_facts.is_empty());
let restored = restore_described(description)
.map_err(|_| "the description of a live drained frontier restores")?;
assert_eq!(restored, drained);
Ok(())
}
#[test]
fn an_initial_enrollment_frontier_round_trips() -> Result<(), &'static str> {
let committed = ClaimFrontiers::from_initial_enrollment(
initial_enrollment_operation(ResourceVector::new(6, 24)),
ResourceVector::new(1, 4),
)
.map_err(|_| "the clear initial frontier is exact")?;
let frontiers = committed.frontiers();
let retained_record_limit = u64::try_from(frontiers.retained_records().len())
.map_err(|_| "the retained corpus fits u64")?;
let description = frontiers.describe(retained_record_limit);
assert_describes_live(frontiers, &description, retained_record_limit);
assert!(description.restore.historical_marker_deliveries.is_empty());
assert!(description.restore.historical_causal_facts.is_empty());
assert_eq!(description.fenced_marker_issued, None);
let restored = restore_described(description)
.map_err(|_| "the description of a directly constructed frontier restores")?;
assert_eq!(&restored, frontiers);
Ok(())
}
#[test]
fn a_prefate_recovery_frontier_describes_its_blocks_without_provenance() -> Result<(), &'static str>
{
let binding_epoch = epoch(1, 1);
let (restore, sequence, order) =
recovery_candidate_fixture(FrontierBinding::Bound(binding_epoch));
let edge = Some(StoredEdge::PhysicalCompaction(
PhysicalCompaction::new(0, 0).ok_or("single-record compaction range")?,
));
let frontiers = ClaimFrontiers::prevalidate(restore.clone(), sequence, order)
.map_err(|_| "the candidate recovery frontier prevalidates")?
.finish(edge)
.map_err(|_| "PC does not hide the candidate recovery quartet")?;
let description = frontiers.describe(restore.retained_record_limit);
assert_describes_live(&frontiers, &description, restore.retained_record_limit);
assert_eq!(description.restore.recovery_marker_delivery_seq, Some(1));
assert_eq!(
description.restore, restore,
"the input comes back unchanged"
);
let history = ValidatedConversationHistory::empty();
let restored = ClaimFrontiers::prevalidate_description(description, &history)
.map_err(|_| "the described recovery frontier prevalidates")?
.finish(edge)
.map_err(|_| "the same edge re-derives the same recovery provenance")?;
assert_eq!(restored, frontiers);
Ok(())
}
#[test]
fn the_fenced_marker_latch_survives_describe_and_restore() -> Result<(), &'static str> {
let (mut restore, sequence, order, dcr, binding_epoch) = detached_dcr_fixture()?;
restore.conversation_id = DCR_CONVERSATION_ID;
for fact in &mut restore.historical_marker_deliveries {
fact.conversation_id = DCR_CONVERSATION_ID;
}
let request = MarkerRecordRequest::delivered(0, 1, FrontierBinding::Detached(binding_epoch));
let edge = Some(StoredEdge::DetachedCredentialRecovery(dcr));
let mut prevalidated = ClaimFrontiers::prevalidate(restore.clone(), sequence, order)
.map_err(|_| "the post-fate frontier prevalidates")?;
prevalidated
.take_marker_record(request)
.ok_or("the exact retained DCR marker is selected once")?
.consume();
let mut frontiers = prevalidated
.finish(edge)
.map_err(|_| "the exact detached DCR proves the post-fate recovery pair")?;
let unissued = frontiers.describe(restore.retained_record_limit);
assert_eq!(unissued.fenced_marker_issued, None);
assert_eq!(unissued.restore, restore, "the input comes back unchanged");
frontiers
.take_fenced_marker_record(dcr)
.ok_or("the detached recovery takes its one fenced marker")?
.consume();
let issued = frontiers.describe(restore.retained_record_limit);
assert_describes_live(&frontiers, &issued, restore.retained_record_limit);
assert_eq!(issued.fenced_marker_issued, Some((0, 1, binding_epoch)));
assert_eq!(
issued.restore, restore,
"the latch is not part of the input"
);
assert_eq!(
issued.restore.historical_marker_deliveries,
[HistoricalMarkerDeliveryFactRestore {
conversation_id: DCR_CONVERSATION_ID,
participant_index: 0,
marker_delivery_seq: 1,
delivered_binding_epoch: binding_epoch,
}]
);
let history = ValidatedConversationHistory::empty();
let mut described = ClaimFrontiers::prevalidate_description(issued.clone(), &history)
.map_err(|_| "the described post-fate frontier prevalidates")?;
described
.take_marker_record(request)
.ok_or("the described retained DCR marker is selected once")?
.consume();
let mut restored = described
.finish(edge)
.map_err(|_| "the described frontier finishes against the same edge")?;
assert_eq!(
restored, frontiers,
"the latch is installed, not forced to None"
);
assert!(
restored.take_fenced_marker_record(dcr).is_none(),
"a restored latch still refuses a second take"
);
let mut public = ClaimFrontiers::prevalidate(issued.restore, sequence, order)
.map_err(|_| "the public route prevalidates the same input")?;
public
.take_marker_record(request)
.ok_or("the public route selects the same marker")?
.consume();
let public = public
.finish(edge)
.map_err(|_| "the public route finishes against the same edge")?;
assert_ne!(public, frontiers, "the public route keeps its forced None");
Ok(())
}