Skip to main content

ic_memory/
capability.rs

1use crate::{declaration::AllocationDeclaration, key::StableKey, slot::AllocationSlotDescriptor};
2use std::sync::Arc;
3
4///
5/// ValidatedAllocations
6///
7/// Pre-commit allocation declarations accepted by policy and historical ledger
8/// validation.
9///
10/// This value is produced by [`crate::validate_allocations`] and may be staged
11/// into the next ledger generation. It cannot open storage. Only a
12/// [`CommittedAllocations`] capability confirmed after persistence can do that.
13///
14/// This is an in-memory capability, not a serde DTO. It has no public
15/// constructor and should only be produced by validation or bootstrap paths.
16///
17
18#[derive(Clone, Debug, Eq, PartialEq)]
19pub struct ValidatedAllocations {
20    inner: Arc<ValidatedState>,
21    _private: (),
22}
23
24#[derive(Clone, Debug, Eq, PartialEq)]
25struct ValidatedState {
26    /// Recovered generation against which these declarations were validated.
27    base_generation: u64,
28    /// Validated declarations.
29    declarations: Vec<AllocationDeclaration>,
30    /// Optional binary/runtime identity for generation diagnostics.
31    runtime_fingerprint: Option<String>,
32}
33
34impl ValidatedAllocations {
35    pub(crate) fn new(
36        base_generation: u64,
37        declarations: Vec<AllocationDeclaration>,
38        runtime_fingerprint: Option<String>,
39    ) -> Self {
40        Self {
41            inner: Arc::new(ValidatedState {
42                base_generation,
43                declarations,
44                runtime_fingerprint,
45            }),
46            _private: (),
47        }
48    }
49
50    /// Return the recovered generation used as the validation base.
51    #[must_use]
52    pub fn base_generation(&self) -> u64 {
53        self.inner.base_generation
54    }
55
56    /// Borrow the validated declarations.
57    #[must_use]
58    pub fn declarations(&self) -> &[AllocationDeclaration] {
59        &self.inner.declarations
60    }
61
62    /// Borrow the optional runtime fingerprint.
63    #[must_use]
64    pub fn runtime_fingerprint(&self) -> Option<&str> {
65        self.inner.runtime_fingerprint.as_deref()
66    }
67
68    /// Find a validated slot by stable key.
69    #[must_use]
70    pub fn slot_for(&self, key: &StableKey) -> Option<&AllocationSlotDescriptor> {
71        self.declarations()
72            .iter()
73            .find(|declaration| &declaration.stable_key == key)
74            .map(|declaration| &declaration.slot)
75    }
76
77    pub(crate) const fn confirm_persisted(self, generation: u64) -> CommittedAllocations {
78        CommittedAllocations {
79            validated: self,
80            generation,
81            _private: (),
82        }
83    }
84}
85
86///
87/// CommittedAllocations
88///
89/// Allocation-open capability confirmed after the validated ledger generation
90/// was persisted.
91///
92/// This type is not serializable, default-constructible, or publicly
93/// constructible. Generic persistence owners obtain it only by explicitly
94/// confirming a successful [`crate::PendingBootstrapCommit`]. The default runtime
95/// publishes it only after its stable cell write succeeds.
96///
97
98#[derive(Clone, Debug, Eq, PartialEq)]
99pub struct CommittedAllocations {
100    validated: ValidatedAllocations,
101    generation: u64,
102    _private: (),
103}
104
105impl CommittedAllocations {
106    /// Return the persisted ledger generation that grants this capability.
107    #[must_use]
108    pub const fn generation(&self) -> u64 {
109        self.generation
110    }
111
112    /// Borrow the committed allocation declarations.
113    #[must_use]
114    pub fn declarations(&self) -> &[AllocationDeclaration] {
115        self.validated.declarations()
116    }
117
118    /// Borrow the optional runtime fingerprint.
119    #[must_use]
120    pub fn runtime_fingerprint(&self) -> Option<&str> {
121        self.validated.runtime_fingerprint()
122    }
123
124    /// Find a committed slot by stable key.
125    #[must_use]
126    pub fn slot_for(&self, key: &StableKey) -> Option<&AllocationSlotDescriptor> {
127        self.validated.slot_for(key)
128    }
129
130    pub(crate) fn without_stable_key_prefix(mut self, prefix: &str) -> Self {
131        let mut state = (*self.validated.inner).clone();
132        state
133            .declarations
134            .retain(|declaration| !declaration.stable_key.as_str().starts_with(prefix));
135        self.validated.inner = Arc::new(state);
136        self
137    }
138}