ic_memory/runtime/
policy.rs1use super::{RuntimeBootstrapError, RuntimePolicyError};
2use crate::{
3 AllocationPolicy, AllocationSlotDescriptor, PolicyIdentity, PolicyIdentityError,
4 RuntimeBootstrapPolicy, StableKey,
5 registry::{RuntimeDeclarationAuthority, SealedDeclarationSnapshot},
6 slot::{IC_MEMORY_AUTHORITY_OWNER, MemoryManagerRangeAuthorityError},
7};
8use std::convert::Infallible;
9
10pub(super) fn runtime_bootstrap_error_from_bootstrap<P>(
11 err: crate::BootstrapError<RuntimePolicyError<P>>,
12) -> RuntimeBootstrapError<P> {
13 match err {
14 crate::BootstrapError::Ledger(err) => RuntimeBootstrapError::LedgerCommit(err),
15 crate::BootstrapError::Validation(err) => RuntimeBootstrapError::Validation(err),
16 crate::BootstrapError::Staging(err) => RuntimeBootstrapError::Staging(err),
17 }
18}
19
20pub(super) struct RuntimeMemoryManagerPolicy<'a, P> {
21 pub(super) declarations: &'a SealedDeclarationSnapshot,
22 pub(super) custom_policy: &'a P,
23}
24
25impl<P: AllocationPolicy> AllocationPolicy for RuntimeMemoryManagerPolicy<'_, P> {
26 type Error = RuntimePolicyError<P::Error>;
27
28 fn validate_key(&self, key: &StableKey) -> Result<(), Self::Error> {
29 let authority = self.declaration_authority(key)?;
30 if matches!(authority, RuntimeDeclarationAuthority::Internal) {
31 return Ok(());
32 }
33 if crate::is_ic_memory_stable_key(key.as_str()) {
34 return Err(RuntimePolicyError::ReservedStableKeyAuthority {
35 stable_key: key.as_str().to_string(),
36 expected_authority: IC_MEMORY_AUTHORITY_OWNER,
37 });
38 }
39 self.custom_policy
40 .validate_key(key)
41 .map_err(RuntimePolicyError::Custom)
42 }
43
44 fn validate_slot(
45 &self,
46 key: &StableKey,
47 slot: &AllocationSlotDescriptor,
48 ) -> Result<(), Self::Error> {
49 self.validate_runtime_range(key, slot)?;
50 if matches!(
51 self.declaration_authority(key)?,
52 RuntimeDeclarationAuthority::Internal
53 ) {
54 return Ok(());
55 }
56 self.custom_policy
57 .validate_slot(key, slot)
58 .map_err(RuntimePolicyError::Custom)
59 }
60
61 fn validate_reserved_slot(
62 &self,
63 key: &StableKey,
64 slot: &AllocationSlotDescriptor,
65 ) -> Result<(), Self::Error> {
66 self.validate_runtime_range(key, slot)?;
67 if matches!(
68 self.declaration_authority(key)?,
69 RuntimeDeclarationAuthority::Internal
70 ) {
71 return Ok(());
72 }
73 self.custom_policy
74 .validate_reserved_slot(key, slot)
75 .map_err(RuntimePolicyError::Custom)
76 }
77}
78
79impl<P: AllocationPolicy> RuntimeMemoryManagerPolicy<'_, P> {
80 fn declaration_authority(
81 &self,
82 key: &StableKey,
83 ) -> Result<&RuntimeDeclarationAuthority, RuntimePolicyError<P::Error>> {
84 self.declarations
85 .declaration_authority()
86 .get(key.as_str())
87 .ok_or_else(|| RuntimePolicyError::MissingDeclarationMetadata(key.as_str().to_string()))
88 }
89
90 fn validate_runtime_range(
91 &self,
92 key: &StableKey,
93 slot: &AllocationSlotDescriptor,
94 ) -> Result<(), RuntimePolicyError<P::Error>> {
95 let authority = self.declaration_authority(key)?;
96 if matches!(authority, RuntimeDeclarationAuthority::Internal) {
97 self.declarations
98 .range_authority()
99 .validate_slot_authority(slot, IC_MEMORY_AUTHORITY_OWNER)?;
100 return Ok(());
101 }
102
103 let RuntimeDeclarationAuthority::External(authority) = authority else {
104 return Err(RuntimePolicyError::MissingDeclarationMetadata(
105 key.as_str().to_string(),
106 ));
107 };
108 if self.declarations.user_ranges_registered() {
109 self.declarations
110 .range_authority()
111 .validate_slot_authority(slot, authority)?;
112 return Ok(());
113 }
114
115 let id = slot
116 .memory_manager_id()
117 .map_err(MemoryManagerRangeAuthorityError::Slot)?;
118 if self
119 .declarations
120 .range_authority()
121 .authority_for_id(id)?
122 .is_some()
123 {
124 self.declarations
125 .range_authority()
126 .validate_slot_authority(slot, authority)?;
127 }
128 Ok(())
129 }
130}
131
132pub struct GenericRangePolicy;
145
146impl AllocationPolicy for GenericRangePolicy {
147 type Error = Infallible;
148
149 fn validate_key(&self, _key: &StableKey) -> Result<(), Self::Error> {
150 Ok(())
151 }
152
153 fn validate_slot(
154 &self,
155 _key: &StableKey,
156 _slot: &AllocationSlotDescriptor,
157 ) -> Result<(), Self::Error> {
158 Ok(())
159 }
160
161 fn validate_reserved_slot(
162 &self,
163 _key: &StableKey,
164 _slot: &AllocationSlotDescriptor,
165 ) -> Result<(), Self::Error> {
166 Ok(())
167 }
168}
169
170impl RuntimeBootstrapPolicy for GenericRangePolicy {
171 fn runtime_bootstrap_identity(&self) -> Result<PolicyIdentity, PolicyIdentityError> {
172 PolicyIdentity::new("ic-memory.noop-policy", 1)
173 }
174}