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) -> &str {
73 if key.as_str() == IC_MEMORY_LEDGER_STABLE_KEY {
74 return IC_MEMORY_AUTHORITY_OWNER;
75 }
76 self.declarations
79 .registered_declaration(key)
80 .expect("validated declaration belongs to the resolved snapshot")
81 .authority()
82 }
83
84 fn validate_runtime_range(
85 &self,
86 authority: &str,
87 slot: &AllocationSlotDescriptor,
88 ) -> Result<(), RuntimePolicyError<P::Error>> {
89 if authority == IC_MEMORY_AUTHORITY_OWNER || self.declarations.user_ranges_registered() {
90 self.declarations
91 .range_authority()
92 .validate_slot_authority(slot, authority)?;
93 return Ok(());
94 }
95
96 let id = slot
97 .memory_manager_id()
98 .map_err(MemoryManagerRangeAuthorityError::Slot)?;
99 if self
100 .declarations
101 .range_authority()
102 .authority_for_id(id)?
103 .is_some()
104 {
105 self.declarations
106 .range_authority()
107 .validate_slot_authority(slot, authority)?;
108 }
109 Ok(())
110 }
111}
112
113pub struct GenericRangePolicy;
126
127impl AllocationPolicy for GenericRangePolicy {
128 type Error = Infallible;
129
130 fn validate_key(&self, _key: &StableKey) -> Result<(), Self::Error> {
131 Ok(())
132 }
133
134 fn validate_slot(
135 &self,
136 _key: &StableKey,
137 _slot: &AllocationSlotDescriptor,
138 ) -> Result<(), Self::Error> {
139 Ok(())
140 }
141
142 fn validate_reserved_slot(
143 &self,
144 _key: &StableKey,
145 _slot: &AllocationSlotDescriptor,
146 ) -> Result<(), Self::Error> {
147 Ok(())
148 }
149}
150
151impl RuntimeBootstrapPolicy for GenericRangePolicy {
152 fn runtime_bootstrap_identity(&self) -> Result<PolicyIdentity, PolicyIdentityError> {
153 PolicyIdentity::new("ic-memory.noop-policy", 1)
154 }
155}