ic_memory/runtime/
policy.rs1use super::{RuntimeBootstrapError, RuntimePolicyError};
2use crate::{
3 AllocationPolicy, MemoryManagerSlot, 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(&self, key: &StableKey, slot: &MemoryManagerSlot) -> Result<(), Self::Error> {
41 let authority = self.declaration_authority(key);
42 self.validate_runtime_range(authority, slot)?;
43 if authority == IC_MEMORY_AUTHORITY_OWNER {
44 return Ok(());
45 }
46 self.custom_policy
47 .validate_slot(key, slot)
48 .map_err(RuntimePolicyError::Custom)
49 }
50
51 fn validate_reserved_slot(
52 &self,
53 key: &StableKey,
54 slot: &MemoryManagerSlot,
55 ) -> Result<(), Self::Error> {
56 let authority = self.declaration_authority(key);
57 self.validate_runtime_range(authority, slot)?;
58 if authority == IC_MEMORY_AUTHORITY_OWNER {
59 return Ok(());
60 }
61 self.custom_policy
62 .validate_reserved_slot(key, slot)
63 .map_err(RuntimePolicyError::Custom)
64 }
65}
66
67impl<P: AllocationPolicy> RuntimeMemoryManagerPolicy<'_, P> {
68 fn declaration_authority(&self, key: &StableKey) -> &str {
69 if key.as_str() == IC_MEMORY_LEDGER_STABLE_KEY {
70 return IC_MEMORY_AUTHORITY_OWNER;
71 }
72 self.declarations
75 .registered_declaration(key)
76 .expect("validated declaration belongs to the resolved snapshot")
77 .authority()
78 }
79
80 fn validate_runtime_range(
81 &self,
82 authority: &str,
83 slot: &MemoryManagerSlot,
84 ) -> Result<(), RuntimePolicyError<P::Error>> {
85 match self
86 .declarations
87 .range_authority()
88 .validate_slot_authority(slot, authority)
89 {
90 Err(MemoryManagerRangeAuthorityError::UnclaimedId { .. })
93 if authority != IC_MEMORY_AUTHORITY_OWNER
94 && !self.declarations.user_ranges_registered() =>
95 {
96 Ok(())
97 }
98 result => result.map(|_| ()).map_err(RuntimePolicyError::Range),
99 }
100 }
101}
102
103pub struct GenericRangePolicy;
116
117impl AllocationPolicy for GenericRangePolicy {
118 type Error = Infallible;
119
120 fn validate_key(&self, _key: &StableKey) -> Result<(), Self::Error> {
121 Ok(())
122 }
123
124 fn validate_slot(
125 &self,
126 _key: &StableKey,
127 _slot: &MemoryManagerSlot,
128 ) -> Result<(), Self::Error> {
129 Ok(())
130 }
131
132 fn validate_reserved_slot(
133 &self,
134 _key: &StableKey,
135 _slot: &MemoryManagerSlot,
136 ) -> Result<(), Self::Error> {
137 Ok(())
138 }
139}
140
141impl RuntimeBootstrapPolicy for GenericRangePolicy {
142 fn runtime_bootstrap_identity(&self) -> Result<PolicyIdentity, PolicyIdentityError> {
143 PolicyIdentity::new("ic-memory.noop-policy", 1)
144 }
145}