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 self.custom_policy
34 .validate_key(key)
35 .map_err(RuntimePolicyError::Custom)
36 }
37
38 fn validate_slot(
39 &self,
40 key: &StableKey,
41 slot: &AllocationSlotDescriptor,
42 ) -> Result<(), Self::Error> {
43 let authority = self.declaration_authority(key)?;
44 self.validate_runtime_range(authority, slot)?;
45 if matches!(authority, RuntimeDeclarationAuthority::Internal) {
46 return Ok(());
47 }
48 self.custom_policy
49 .validate_slot(key, slot)
50 .map_err(RuntimePolicyError::Custom)
51 }
52
53 fn validate_reserved_slot(
54 &self,
55 key: &StableKey,
56 slot: &AllocationSlotDescriptor,
57 ) -> Result<(), Self::Error> {
58 let authority = self.declaration_authority(key)?;
59 self.validate_runtime_range(authority, slot)?;
60 if matches!(authority, RuntimeDeclarationAuthority::Internal) {
61 return Ok(());
62 }
63 self.custom_policy
64 .validate_reserved_slot(key, slot)
65 .map_err(RuntimePolicyError::Custom)
66 }
67}
68
69impl<P: AllocationPolicy> RuntimeMemoryManagerPolicy<'_, P> {
70 fn declaration_authority(
71 &self,
72 key: &StableKey,
73 ) -> Result<&RuntimeDeclarationAuthority, RuntimePolicyError<P::Error>> {
74 self.declarations
75 .declaration_authority()
76 .get(key.as_str())
77 .ok_or_else(|| RuntimePolicyError::MissingDeclarationMetadata(key.as_str().to_string()))
78 }
79
80 fn validate_runtime_range(
81 &self,
82 authority: &RuntimeDeclarationAuthority,
83 slot: &AllocationSlotDescriptor,
84 ) -> Result<(), RuntimePolicyError<P::Error>> {
85 let authority = match authority {
86 RuntimeDeclarationAuthority::Internal => {
87 return self
88 .declarations
89 .range_authority()
90 .validate_slot_authority(slot, IC_MEMORY_AUTHORITY_OWNER)
91 .map(|_| ())
92 .map_err(RuntimePolicyError::Range);
93 }
94 RuntimeDeclarationAuthority::External(authority) => authority,
95 };
96 if self.declarations.user_ranges_registered() {
97 self.declarations
98 .range_authority()
99 .validate_slot_authority(slot, authority)?;
100 return Ok(());
101 }
102
103 let id = slot
104 .memory_manager_id()
105 .map_err(MemoryManagerRangeAuthorityError::Slot)?;
106 if self
107 .declarations
108 .range_authority()
109 .authority_for_id(id)?
110 .is_some()
111 {
112 self.declarations
113 .range_authority()
114 .validate_slot_authority(slot, authority)?;
115 }
116 Ok(())
117 }
118}
119
120pub struct GenericRangePolicy;
133
134impl AllocationPolicy for GenericRangePolicy {
135 type Error = Infallible;
136
137 fn validate_key(&self, _key: &StableKey) -> Result<(), Self::Error> {
138 Ok(())
139 }
140
141 fn validate_slot(
142 &self,
143 _key: &StableKey,
144 _slot: &AllocationSlotDescriptor,
145 ) -> Result<(), Self::Error> {
146 Ok(())
147 }
148
149 fn validate_reserved_slot(
150 &self,
151 _key: &StableKey,
152 _slot: &AllocationSlotDescriptor,
153 ) -> Result<(), Self::Error> {
154 Ok(())
155 }
156}
157
158impl RuntimeBootstrapPolicy for GenericRangePolicy {
159 fn runtime_bootstrap_identity(&self) -> Result<PolicyIdentity, PolicyIdentityError> {
160 PolicyIdentity::new("ic-memory.noop-policy", 1)
161 }
162}