ic_backup/model/ic_snapshot_upload_observation/
mod.rs1use crate::model::attempt_journal::ObservationReservation;
4use crate::model::{
5 attempt_journal::{AttemptAuthorityRecord, AttemptJournalRecord},
6 ic_observation::IcObservationRequestError,
7 ic_request::{IcManagementMethodRecord, IcManagementRequestRecord},
8 ic_snapshot_upload::{
9 IcSnapshotUploadAttemptError, IcSnapshotUploadKind, IcSnapshotUploadRequest,
10 original_authority,
11 },
12 operation_plan::OperationPlanRecord,
13};
14use thiserror::Error;
15
16mod settlement;
17pub use settlement::{IcSnapshotUploadAttribution, IcSnapshotUploadSettlement};
18
19#[derive(Debug)]
26pub struct IcSnapshotUploadObservationRequest<'request, 'source> {
27 plan: &'request OperationPlanRecord,
28 mutation: &'request IcSnapshotUploadRequest<'source>,
29 payload: &'request IcManagementRequestRecord,
30 reservation: ObservationReservation,
31}
32
33impl<'request, 'source> IcSnapshotUploadObservationRequest<'request, 'source> {
34 pub fn new(
41 plan: &'request OperationPlanRecord,
42 operation_sequence: u64,
43 journal: &AttemptJournalRecord,
44 mutation: &'request IcSnapshotUploadRequest<'source>,
45 payload: &'request IcManagementRequestRecord,
46 ) -> Result<Self, IcSnapshotUploadObservationError> {
47 if !matches!(mutation.kind(), IcSnapshotUploadKind::Metadata) {
48 return Err(IcSnapshotUploadObservationError::UnsupportedUpload);
49 }
50 if payload.method() != IcManagementMethodRecord::ListCanisterSnapshots {
51 return Err(IcSnapshotUploadObservationError::UnsupportedObservation);
52 }
53 let authority = original_authority(plan, operation_sequence, journal, mutation)?;
54 payload
55 .validate_observation_binding(authority.binding(), &payload.digest())
56 .map_err(IcObservationRequestError::from)?;
57 let reservation = ObservationReservation::new(authority, journal, payload.digest())
58 .map_err(crate::model::ic_observation::IcObservationRequestError::from)?;
59 let request = Self {
60 plan,
61 mutation,
62 payload,
63 reservation,
64 };
65 Ok(request)
66 }
67
68 #[must_use]
70 pub const fn plan(&self) -> &OperationPlanRecord {
71 self.plan
72 }
73 #[must_use]
75 pub const fn mutation(&self) -> &'request IcSnapshotUploadRequest<'source> {
76 self.mutation
77 }
78 #[must_use]
80 pub const fn payload(&self) -> &'request IcManagementRequestRecord {
81 self.payload
82 }
83 #[must_use]
85 pub const fn authority(&self) -> &AttemptAuthorityRecord {
86 &self.reservation.authority
87 }
88 #[must_use]
90 pub const fn mutation_attempt(&self) -> u32 {
91 self.reservation.mutation_attempt
92 }
93 #[must_use]
95 pub const fn observation_attempt(&self) -> u32 {
96 self.reservation.observation_attempt
97 }
98 pub fn validate_journal(
102 &self,
103 journal: &AttemptJournalRecord,
104 ) -> Result<(), IcObservationRequestError> {
105 self.reservation
106 .validate(journal)
107 .map_err(IcObservationRequestError::from)
108 }
109}
110
111#[derive(Debug, Error)]
113pub enum IcSnapshotUploadObservationError {
114 #[error("snapshot upload observation requires metadata intent")]
116 UnsupportedUpload,
117 #[error("snapshot upload observation requires snapshot list")]
119 UnsupportedObservation,
120 #[error(transparent)]
122 Upload(#[from] IcSnapshotUploadAttemptError),
123 #[error(transparent)]
125 Observation(#[from] IcObservationRequestError),
126}
127
128#[cfg(test)]
129mod tests;