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 match self
90 .declarations
91 .range_authority()
92 .validate_slot_authority(slot, authority)
93 {
94 Err(MemoryManagerRangeAuthorityError::UnclaimedId { .. })
97 if authority != IC_MEMORY_AUTHORITY_OWNER
98 && !self.declarations.user_ranges_registered() =>
99 {
100 Ok(())
101 }
102 result => result.map(|_| ()).map_err(RuntimePolicyError::Range),
103 }
104 }
105}
106
107pub struct GenericRangePolicy;
120
121impl AllocationPolicy for GenericRangePolicy {
122 type Error = Infallible;
123
124 fn validate_key(&self, _key: &StableKey) -> Result<(), Self::Error> {
125 Ok(())
126 }
127
128 fn validate_slot(
129 &self,
130 _key: &StableKey,
131 _slot: &AllocationSlotDescriptor,
132 ) -> Result<(), Self::Error> {
133 Ok(())
134 }
135
136 fn validate_reserved_slot(
137 &self,
138 _key: &StableKey,
139 _slot: &AllocationSlotDescriptor,
140 ) -> Result<(), Self::Error> {
141 Ok(())
142 }
143}
144
145impl RuntimeBootstrapPolicy for GenericRangePolicy {
146 fn runtime_bootstrap_identity(&self) -> Result<PolicyIdentity, PolicyIdentityError> {
147 PolicyIdentity::new("ic-memory.noop-policy", 1)
148 }
149}