ic_memory/runtime/
policy.rs1use super::{RuntimeBootstrapError, RuntimePolicyError};
2use crate::{
3 AllocationPolicy, AllocationSlotDescriptor, PolicyIdentity, PolicyIdentityError,
4 RuntimeBootstrapPolicy, StableKey,
5 registry::SealedDeclarationSnapshot,
6 slot::{
7 IC_MEMORY_AUTHORITY_OWNER, IC_MEMORY_LEDGER_STABLE_KEY, MemoryManagerRangeAuthorityError,
8 },
9};
10use std::convert::Infallible;
11
12pub(super) fn runtime_bootstrap_error_from_bootstrap<P>(
13 err: crate::BootstrapError<RuntimePolicyError<P>>,
14) -> RuntimeBootstrapError<P> {
15 match err {
16 crate::BootstrapError::Ledger(err) => RuntimeBootstrapError::LedgerCommit(err),
17 crate::BootstrapError::Validation(err) => RuntimeBootstrapError::Validation(err),
18 crate::BootstrapError::Staging(err) => RuntimeBootstrapError::Staging(err),
19 }
20}
21
22pub(super) struct RuntimeMemoryManagerPolicy<'a, P> {
23 pub(super) declarations: &'a SealedDeclarationSnapshot,
24 pub(super) custom_policy: &'a P,
25}
26
27impl<P: AllocationPolicy> AllocationPolicy for RuntimeMemoryManagerPolicy<'_, P> {
28 type Error = RuntimePolicyError<P::Error>;
29
30 fn validate_key(&self, key: &StableKey) -> Result<(), Self::Error> {
31 let authority = self.declaration_authority(key)?;
32 if authority == IC_MEMORY_AUTHORITY_OWNER {
33 return Ok(());
34 }
35 self.custom_policy
36 .validate_key(key)
37 .map_err(RuntimePolicyError::Custom)
38 }
39
40 fn validate_slot(
41 &self,
42 key: &StableKey,
43 slot: &AllocationSlotDescriptor,
44 ) -> Result<(), Self::Error> {
45 let authority = self.declaration_authority(key)?;
46 self.validate_runtime_range(authority, slot)?;
47 if authority == IC_MEMORY_AUTHORITY_OWNER {
48 return Ok(());
49 }
50 self.custom_policy
51 .validate_slot(key, slot)
52 .map_err(RuntimePolicyError::Custom)
53 }
54
55 fn validate_reserved_slot(
56 &self,
57 key: &StableKey,
58 slot: &AllocationSlotDescriptor,
59 ) -> Result<(), Self::Error> {
60 let authority = self.declaration_authority(key)?;
61 self.validate_runtime_range(authority, slot)?;
62 if authority == IC_MEMORY_AUTHORITY_OWNER {
63 return Ok(());
64 }
65 self.custom_policy
66 .validate_reserved_slot(key, slot)
67 .map_err(RuntimePolicyError::Custom)
68 }
69}
70
71impl<P: AllocationPolicy> RuntimeMemoryManagerPolicy<'_, P> {
72 fn declaration_authority(&self, key: &StableKey) -> Result<&str, RuntimePolicyError<P::Error>> {
73 if key.as_str() == IC_MEMORY_LEDGER_STABLE_KEY {
74 return Ok(IC_MEMORY_AUTHORITY_OWNER);
75 }
76 self.declarations
77 .registered_declaration(key)
78 .map(crate::StaticMemoryDeclaration::authority)
79 .ok_or_else(|| RuntimePolicyError::MissingDeclarationMetadata(key.as_str().to_string()))
80 }
81
82 fn validate_runtime_range(
83 &self,
84 authority: &str,
85 slot: &AllocationSlotDescriptor,
86 ) -> Result<(), RuntimePolicyError<P::Error>> {
87 if authority == IC_MEMORY_AUTHORITY_OWNER || self.declarations.user_ranges_registered() {
88 self.declarations
89 .range_authority()
90 .validate_slot_authority(slot, authority)?;
91 return Ok(());
92 }
93
94 let id = slot
95 .memory_manager_id()
96 .map_err(MemoryManagerRangeAuthorityError::Slot)?;
97 if self
98 .declarations
99 .range_authority()
100 .authority_for_id(id)?
101 .is_some()
102 {
103 self.declarations
104 .range_authority()
105 .validate_slot_authority(slot, authority)?;
106 }
107 Ok(())
108 }
109}
110
111pub struct GenericRangePolicy;
124
125impl AllocationPolicy for GenericRangePolicy {
126 type Error = Infallible;
127
128 fn validate_key(&self, _key: &StableKey) -> Result<(), Self::Error> {
129 Ok(())
130 }
131
132 fn validate_slot(
133 &self,
134 _key: &StableKey,
135 _slot: &AllocationSlotDescriptor,
136 ) -> Result<(), Self::Error> {
137 Ok(())
138 }
139
140 fn validate_reserved_slot(
141 &self,
142 _key: &StableKey,
143 _slot: &AllocationSlotDescriptor,
144 ) -> Result<(), Self::Error> {
145 Ok(())
146 }
147}
148
149impl RuntimeBootstrapPolicy for GenericRangePolicy {
150 fn runtime_bootstrap_identity(&self) -> Result<PolicyIdentity, PolicyIdentityError> {
151 PolicyIdentity::new("ic-memory.noop-policy", 1)
152 }
153}