use crate::model::inventory_settlement::IcInventorySettlement;
use super::{IcObservationAssociationError, IcObservationReplyView, validate_response};
use crate::{
model::{
artifacts::ArtifactChecksumRecord,
attempt_journal::AttemptJournalRecord,
ic_observation::{IcObservationRequest, IcObservationResponse},
ic_request::IcManagementMethodRecord as Method,
ic_snapshot_reply::IcSnapshotReply,
},
policy::{
inventory_settlement::{
IcInventorySettlementView, InventorySettlementIdentity, InventorySettlementMismatch,
admitted_outcome, validate_pair,
},
settlement_identity::SettlementIdentity,
snapshot_inventory_delta::SnapshotInventoryDeltaError,
},
};
use thiserror::Error;
pub fn validate_capture_settlement<'a>(
request: &IcObservationRequest<'a>,
journal: &AttemptJournalRecord,
baseline: &'a IcSnapshotReply<'a>,
response: &'a IcObservationResponse,
challenge: &ArtifactChecksumRecord,
settlement: &'a IcInventorySettlement,
) -> Result<IcInventorySettlementView<'a>, IcCaptureSettlementError> {
if request.mutation().method() != Method::TakeCanisterSnapshot
|| request.payload().method() != Method::ListCanisterSnapshots
{
return Err(IcCaptureSettlementError::UnsupportedMethod);
}
let observation = validate_response(request, journal, response)?;
let IcObservationReplyView::Inventory(inventory) = observation.reply() else {
return Err(IcCaptureSettlementError::UnsupportedMethod);
};
let authority = request.authority().digest();
let candidates = validate_pair::<IcCaptureSettlementError>(
request.mutation().target(),
baseline,
inventory,
&InventorySettlementIdentity::from(settlement),
&SettlementIdentity {
authority: &authority,
mutation_attempt: request.mutation_attempt(),
observation_attempt: request.observation_attempt(),
challenge,
},
&response.input().evidence,
)?;
let resolution = admitted_outcome(inventory, &candidates, &settlement.attribution)
.map_err(|()| IcCaptureSettlementError::NotNewCandidate)?;
Ok(IcInventorySettlementView {
observation,
baseline,
settlement,
resolution,
})
}
#[derive(Debug, Error)]
pub enum IcCaptureSettlementError {
#[error("capture settlement requires original capture and list observation")]
UnsupportedMethod,
#[error(transparent)]
Observation(#[from] IcObservationAssociationError),
#[error(transparent)]
Baseline(#[from] SnapshotInventoryDeltaError),
#[error(transparent)]
Identity(#[from] InventorySettlementMismatch),
#[error("capture settlement ID is not a new candidate")]
NotNewCandidate,
}
#[cfg(test)]
mod tests;