#[derive(Debug, Clone)]
pub struct RotationProof {
pub new_public_key: Vec<u8>,
pub new_curve: auths_crypto::CurveType,
pub new_kel_tip: String,
pub new_sequence: u128,
}
pub trait KelContinuityChecker {
fn verify_rotation_continuity(
&self,
did: &str,
pinned_tip_said: &str,
presented_pk: &[u8],
) -> Result<Option<RotationProof>, crate::error::TrustError>;
}
#[cfg(test)]
mod tests {
use super::*;
struct MockChecker {
should_verify: bool,
proof: Option<RotationProof>,
}
impl KelContinuityChecker for MockChecker {
fn verify_rotation_continuity(
&self,
_did: &str,
_pinned_tip_said: &str,
_presented_pk: &[u8],
) -> Result<Option<RotationProof>, crate::error::TrustError> {
if self.should_verify {
Ok(self.proof.clone())
} else {
Ok(None)
}
}
}
#[test]
fn test_rotation_proof_fields() {
let proof = RotationProof {
new_public_key: vec![1, 2, 3, 4],
new_curve: auths_crypto::CurveType::P256,
new_kel_tip: "ENewTipSaid".to_string(),
new_sequence: 5,
};
assert_eq!(proof.new_public_key, vec![1, 2, 3, 4]);
assert_eq!(proof.new_kel_tip, "ENewTipSaid");
assert_eq!(proof.new_sequence, 5);
}
#[test]
fn test_mock_checker_verifies() {
let proof = RotationProof {
new_public_key: vec![5, 6, 7, 8],
new_curve: auths_crypto::CurveType::P256,
new_kel_tip: "ENewTip".to_string(),
new_sequence: 2,
};
let checker = MockChecker {
should_verify: true,
proof: Some(proof.clone()),
};
let result = checker
.verify_rotation_continuity("did:keri:ETest", "EOldTip", &[1, 2, 3])
.unwrap();
assert!(result.is_some());
let returned_proof = result.unwrap();
assert_eq!(returned_proof.new_sequence, 2);
}
#[test]
fn test_mock_checker_fails() {
let checker = MockChecker {
should_verify: false,
proof: None,
};
let result = checker
.verify_rotation_continuity("did:keri:ETest", "EOldTip", &[1, 2, 3])
.unwrap();
assert!(result.is_none());
}
}