use super::*;
use crate::metis::Vouched;
fn zero_station_declaration_frame() -> Vec<u8> {
let mut frame = vec![0x02];
frame.extend_from_slice(&2u64.to_be_bytes());
frame.extend_from_slice(&0u32.to_be_bytes());
frame.extend_from_slice(&1u64.to_be_bytes());
frame.extend_from_slice(&crate::kairos::Kairos::new(7, 0u16, 0, 0u16).to_bytes());
frame.extend_from_slice(&cut(&[(0, 1)]).to_have_set().to_bytes());
frame.extend_from_slice(&1u64.to_be_bytes());
frame.extend_from_slice(&0u32.to_be_bytes());
frame.extend_from_slice(&1u64.to_be_bytes());
frame.extend_from_slice(&1u32.to_be_bytes());
frame.extend_from_slice(&0u32.to_be_bytes());
frame.extend_from_slice(&[0x5a; 32]);
frame
}
fn zero_station_seal_frame() -> Vec<u8> {
let mut frame = vec![0x02];
frame.extend_from_slice(&2u64.to_be_bytes());
frame.extend_from_slice(&0u32.to_be_bytes());
frame.extend_from_slice(&1u64.to_be_bytes());
frame.extend_from_slice(&1u32.to_be_bytes());
frame.extend_from_slice(&2u64.to_be_bytes());
frame.extend_from_slice(&0u32.to_be_bytes());
frame.extend_from_slice(&1u64.to_be_bytes());
frame.extend_from_slice(&1u32.to_be_bytes());
frame.extend_from_slice(&0u32.to_be_bytes());
frame.extend_from_slice(&1u64.to_be_bytes());
frame.extend_from_slice(&cut(&[(0, 1)]).to_have_set().to_bytes());
frame.extend_from_slice(&1u64.to_be_bytes());
frame.extend_from_slice(&0u32.to_be_bytes());
frame.extend_from_slice(&1u64.to_be_bytes());
frame.extend_from_slice(&1u32.to_be_bytes());
frame.extend_from_slice(&0u32.to_be_bytes());
frame
}
#[test]
fn test_station_zero_round_trips_through_every_lifecycle_codec() {
let declaration_frame = zero_station_declaration_frame();
let declaration = Declaration::from_bytes(&declaration_frame).expect("declaration decodes");
assert_eq!(declaration.dot(), d(0, 1));
assert_eq!(declaration.rank().station_id(), 0);
assert_eq!(declaration.cut(), &cut(&[(0, 1)]));
let admission = declaration.admission().expect("the v2 admission rides");
assert_eq!(admission.base(), address(1, (0, 1)));
assert_eq!(admission.joiners().collect::<Vec<_>>(), [0]);
assert_eq!(declaration.to_bytes(), declaration_frame);
let confirmation = ConfirmationRecord::new(address(2, (0, 1)), cut(&[(0, 1)]));
let confirmation_frame = confirmation.to_bytes();
let decoded =
ConfirmationRecord::from_bytes(&confirmation_frame).expect("confirmation decodes");
assert_eq!(decoded, confirmation);
assert_eq!(decoded.to_bytes(), confirmation_frame);
let adoption = AdoptionReportRecord::new(address(2, (0, 1)), 0);
let adoption_frame = adoption.to_bytes();
let decoded = AdoptionReportRecord::from_bytes(&adoption_frame).expect("adoption decodes");
assert_eq!(decoded, adoption);
assert_eq!(decoded.to_bytes(), adoption_frame);
let seal_frame = zero_station_seal_frame();
let seal = SealRecord::from_bytes(&seal_frame).expect("seal decodes");
assert_eq!(seal.declaration(), address(2, (0, 1)));
assert_eq!(seal.candidates().collect::<Vec<_>>(), [address(2, (0, 1))]);
assert_eq!(seal.declaration_dots().collect::<Vec<_>>(), [d(0, 1)]);
assert_eq!(seal.sealed_join(), cut(&[(0, 1)]).as_vector());
let admission = seal.admission().expect("the v2 admission rides");
assert_eq!(admission.base(), address(1, (0, 1)));
assert_eq!(admission.joiners().collect::<Vec<_>>(), [0]);
assert_eq!(seal.to_bytes(), seal_frame);
let proof = LineageProofRecord::try_new(vec![LineageProofEntry::new(seal, [0x33; 32])])
.expect("one retained generation is consecutive");
let proof_frame = proof.to_bytes();
assert_eq!(proof_frame[0], 0x02);
let decoded = LineageProofRecord::from_bytes(&proof_frame).expect("lineage proof decodes");
assert_eq!(decoded, proof);
assert_eq!(decoded.to_bytes(), proof_frame);
}
#[test]
fn test_declaration_to_bytes_layout() {
let record = declaration(&[1, 2], d(2, 3), 7, &[(1, 2), (2, 2)]);
let frame = record.to_bytes();
let mut expected = vec![
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, ];
expected.extend_from_slice(&rank(7).to_bytes());
expected.extend_from_slice(&[
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, ]);
assert_eq!(frame, expected);
assert_eq!(record.encoded_len(), frame.len());
assert_eq!(Declaration::from_bytes(&frame), Ok(record));
}
#[test]
fn test_confirmation_to_bytes_layout() {
let record = ConfirmationRecord::new(address(1, (2, 3)), cut(&[(1, 3), (2, 3)]));
let frame = record.to_bytes();
assert_eq!(
frame,
[
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, ]
);
assert_eq!(record.encoded_len(), frame.len());
let decoded = ConfirmationRecord::from_bytes(&frame).unwrap();
assert_eq!(decoded, record);
let (epoch, delivered) = decoded.into_parts();
assert_eq!(epoch, address(1, (2, 3)));
assert_eq!(delivered, cut(&[(1, 3), (2, 3)]));
}
#[test]
fn test_adoption_report_to_bytes_layout() {
let record = AdoptionReportRecord::new(address(1, (2, 3)), 5);
let frame = record.to_bytes();
assert_eq!(
frame,
[
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, ]
);
assert_eq!(record.encoded_len(), frame.len());
assert_eq!(AdoptionReportRecord::from_bytes(&frame), Ok(record));
}
#[test]
fn test_seal_to_bytes_layout_keeps_the_displaced_dot() {
let (_, sealed) = displaced_window();
let record = SealRecord::from_sealed(&sealed);
let frame = record.to_bytes();
assert_eq!(
frame,
[
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, ]
);
assert_eq!(record.encoded_len(), frame.len());
let decoded = SealRecord::from_bytes(&frame).unwrap();
assert_eq!(decoded, record);
let candidates: Vec<EpochAddress> = decoded.candidates().collect();
assert_eq!(candidates, [address(1, (2, 3))]);
let dots: Vec<Dot> = decoded.declaration_dots().collect();
assert_eq!(dots, [d(1, 3), d(2, 3)]);
}
#[test]
fn test_lineage_proof_round_trips_the_displaced_window() {
let (mut epochs, first) = displaced_window();
let mut stability = crate::metis::Stability::new([1, 2]);
for station in [1, 2] {
stability
.report_cut(station, &cut(&[(1, 4), (2, 4)]))
.unwrap();
}
let second = epochs
.declare(d(1, 5), rank(11), &stability, &Cut::bottom())
.expect("the second window opens");
assert_eq!(second.address().generation(), 2);
let delivered = cut(&[(1, 5), (2, 5)]);
for station in [1, 2] {
stability.report_cut(station, &delivered).unwrap();
}
epochs
.confirm(second.address(), &Vouched::trust(1, delivered.clone()))
.unwrap();
epochs
.confirm(second.address(), &Vouched::trust(2, delivered.clone()))
.unwrap();
let _ = epochs.adopt(1, 5, &stability).unwrap();
epochs
.adopt_report(second.address(), &Vouched::trust(2, 5))
.unwrap();
let sealed_two = epochs
.try_seal(&stability)
.expect("the second seal fires")
.clone();
let proof = LineageProofRecord::try_new(vec![
LineageProofEntry::new(SealRecord::from_sealed(&first), [0xAA; 32]),
LineageProofEntry::new(SealRecord::from_sealed(&sealed_two), [0xBB; 32]),
])
.expect("consecutive generations construct");
let frame = proof.to_bytes();
assert_eq!(proof.encoded_len(), frame.len());
let decoded = LineageProofRecord::from_bytes(&frame).unwrap();
assert_eq!(decoded, proof);
assert_eq!(decoded.len(), 2);
assert_eq!(decoded.entries()[0].node(), [0xAA; 32]);
let dots: Vec<Dot> = decoded.entries()[0].seal().declaration_dots().collect();
assert_eq!(dots, [d(1, 3), d(2, 3)], "the displaced dot crossed whole");
assert_eq!(decoded.entries()[0].seal().candidates().count(), 1);
let generous = LineageProofDecodeBudget::new(2, 4);
assert_eq!(
LineageProofRecord::from_bytes_with_budget(&frame, generous),
Ok(proof)
);
assert_eq!(
LineageProofRecord::from_bytes_with_budget(&frame, LineageProofDecodeBudget::new(1, 4)),
Err(LineageProofDecodeError::TooManyGenerations {
count: 2,
budget: 1
})
);
assert_eq!(
LineageProofRecord::from_bytes_with_budget(&frame, LineageProofDecodeBudget::new(2, 0)),
Err(LineageProofDecodeError::Seal(
SealDecodeError::TooManyCandidates {
count: 1,
budget: 0
}
))
);
}