ic_backup/policy/ic_mutation/
mod.rs1use super::response_identity::{ResponseIdentity, ResponseIdentityMismatch};
4use crate::model::{
5 attempt_journal::AttemptJournalRecord,
6 ic_lifecycle_reply::{IcLifecycleReply, IcLifecycleReplyError},
7 ic_mutation::{IcMutationAcknowledgement, IcMutationRequest, IcMutationRequestError},
8 ic_request::IcManagementMethodRecord,
9 ic_snapshot_reply::{IcSnapshotReply, IcSnapshotReplyError},
10};
11use thiserror::Error;
12
13#[derive(Debug)]
15pub enum IcMutationReplyView<'a> {
16 Capture(IcSnapshotReply<'a>),
18 Lifecycle(IcLifecycleReply<'a>),
20}
21
22#[derive(Debug)]
27pub struct IcMutationAcknowledgementView<'a> {
28 acknowledgement: &'a IcMutationAcknowledgement,
29 reply: IcMutationReplyView<'a>,
30}
31impl<'a> IcMutationAcknowledgementView<'a> {
32 #[must_use]
34 pub const fn acknowledgement(&self) -> &'a IcMutationAcknowledgement {
35 self.acknowledgement
36 }
37 #[must_use]
39 pub const fn reply(&self) -> &IcMutationReplyView<'a> {
40 &self.reply
41 }
42}
43
44pub fn validate_acknowledgement<'a>(
52 request: &IcMutationRequest<'a>,
53 journal: &AttemptJournalRecord,
54 acknowledgement: &'a IcMutationAcknowledgement,
55) -> Result<IcMutationAcknowledgementView<'a>, IcMutationAssociationError> {
56 request.validate_journal(journal)?;
57 let input = acknowledgement.input();
58 ResponseIdentity::from(input)
59 .compare(&ResponseIdentity {
60 authority: &request.authority().digest(),
61 mutation_attempt: request.mutation_attempt(),
62 context: request.plan().context(),
63 target: request.payload().target(),
64 })
65 .map_err(|mismatch| match mismatch {
66 ResponseIdentityMismatch::Authority => IcMutationAssociationError::AuthorityMismatch,
67 ResponseIdentityMismatch::Attempt => IcMutationAssociationError::AttemptMismatch,
68 ResponseIdentityMismatch::Context => IcMutationAssociationError::ContextMismatch,
69 ResponseIdentityMismatch::Target => IcMutationAssociationError::TargetMismatch,
70 })?;
71 let reply = match request.payload().method() {
72 IcManagementMethodRecord::TakeCanisterSnapshot => {
73 IcMutationReplyView::Capture(IcSnapshotReply::decode(request.payload(), &input.reply)?)
74 }
75 _ => IcMutationReplyView::Lifecycle(IcLifecycleReply::decode(
78 request.payload(),
79 &input.reply,
80 )?),
81 };
82 Ok(IcMutationAcknowledgementView {
83 acknowledgement,
84 reply,
85 })
86}
87
88#[derive(Debug, Error)]
90pub enum IcMutationAssociationError {
91 #[error(transparent)]
93 Reservation(#[from] IcMutationRequestError),
94 #[error("IC mutation acknowledgement authority mismatch")]
96 AuthorityMismatch,
97 #[error("IC mutation acknowledgement attempt mismatch")]
99 AttemptMismatch,
100 #[error("IC mutation acknowledgement context mismatch")]
102 ContextMismatch,
103 #[error("IC mutation acknowledgement target mismatch")]
105 TargetMismatch,
106 #[error(transparent)]
108 Snapshot(#[from] IcSnapshotReplyError),
109 #[error(transparent)]
111 Lifecycle(#[from] IcLifecycleReplyError),
112}
113
114#[cfg(test)]
115mod tests;