radix_engine/blueprints/resource/auth_zone/
blueprint.rs

1use crate::blueprints::resource::ComposedProof;
2use crate::errors::*;
3use crate::internal_prelude::*;
4use crate::kernel::kernel_api::{KernelNodeApi, KernelSubstateApi};
5use crate::system::node_init::type_info_partition;
6use crate::system::system_callback::SystemBasedKernelInternalApi;
7use crate::system::system_callback::SystemLockData;
8use crate::system::system_modules::auth::{Authorization, AuthorizationCheckResult};
9use crate::system::type_info::TypeInfoSubstate;
10use radix_engine_interface::api::{LockFlags, SystemApi, ACTOR_REF_SELF, ACTOR_STATE_SELF};
11use radix_engine_interface::blueprints::package::BlueprintVersion;
12use radix_engine_interface::blueprints::resource::*;
13use radix_native_sdk::resource::NativeProof;
14
15use super::{compose_proof_by_amount, compose_proof_by_ids, AuthZone, ComposeProofError};
16
17#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
18pub enum AuthZoneError {
19    ComposeProofError(ComposeProofError),
20}
21
22pub struct AuthZoneBlueprint;
23
24impl AuthZoneBlueprint {
25    pub fn pop<Y: SystemApi<RuntimeError>>(api: &mut Y) -> Result<Option<Proof>, RuntimeError> {
26        let auth_zone_handle = api.actor_open_field(
27            ACTOR_STATE_SELF,
28            AuthZoneField::AuthZone.into(),
29            LockFlags::MUTABLE,
30        )?;
31
32        let mut auth_zone: AuthZone = api.field_read_typed(auth_zone_handle)?;
33        let maybe_proof = auth_zone.pop();
34        api.field_write_typed(auth_zone_handle, &auth_zone)?;
35
36        Ok(maybe_proof)
37    }
38
39    pub fn push<Y: SystemApi<RuntimeError>>(proof: Proof, api: &mut Y) -> Result<(), RuntimeError> {
40        let auth_zone_handle = api.actor_open_field(
41            ACTOR_STATE_SELF,
42            AuthZoneField::AuthZone.into(),
43            LockFlags::MUTABLE,
44        )?;
45
46        let mut auth_zone: AuthZone = api.field_read_typed(auth_zone_handle)?;
47        auth_zone.push(proof);
48
49        api.field_write_typed(auth_zone_handle, &auth_zone)?;
50        api.field_close(auth_zone_handle)?;
51
52        Ok(())
53    }
54
55    pub fn create_proof_of_amount<
56        Y: SystemApi<RuntimeError> + KernelNodeApi + KernelSubstateApi<SystemLockData>,
57    >(
58        resource_address: ResourceAddress,
59        amount: Decimal,
60        api: &mut Y,
61    ) -> Result<Proof, RuntimeError> {
62        let auth_zone_handle = api.actor_open_field(
63            ACTOR_STATE_SELF,
64            AuthZoneField::AuthZone.into(),
65            LockFlags::read_only(),
66        )?;
67
68        let composed_proof = {
69            let auth_zone: AuthZone = api.field_read_typed(auth_zone_handle)?;
70            let proofs: Vec<Proof> = auth_zone.proofs.iter().map(|p| Proof(p.0)).collect();
71            compose_proof_by_amount(&proofs, resource_address, Some(amount), api)?
72        };
73
74        let node_id = api.kernel_allocate_node_id(EntityType::InternalGenericComponent)?;
75        match composed_proof {
76            ComposedProof::Fungible(..) => {
77                api.kernel_create_node(
78                    node_id,
79                    btreemap!(
80                        MAIN_BASE_PARTITION => composed_proof.into(),
81                        TYPE_INFO_FIELD_PARTITION => type_info_partition(TypeInfoSubstate::Object(ObjectInfo {
82                            blueprint_info: BlueprintInfo {
83                                blueprint_id: BlueprintId::new(&RESOURCE_PACKAGE, FUNGIBLE_PROOF_BLUEPRINT),
84                                blueprint_version: BlueprintVersion::default(),
85                                outer_obj_info: OuterObjectInfo::Some {
86                                    outer_object: resource_address.into(),
87                                },
88                                features: indexset!(),
89                                generic_substitutions: vec![],
90                            },
91                            object_type: ObjectType::Owned,
92                        })),
93                    ),
94                )?;
95                api.kernel_pin_node(node_id)?;
96            }
97            ComposedProof::NonFungible(..) => {
98                api.kernel_create_node(
99                    node_id,
100                    btreemap!(
101                    MAIN_BASE_PARTITION => composed_proof.into(),
102                    TYPE_INFO_FIELD_PARTITION => type_info_partition(TypeInfoSubstate::Object(ObjectInfo {
103                        blueprint_info: BlueprintInfo {
104                            blueprint_id: BlueprintId::new(&RESOURCE_PACKAGE, NON_FUNGIBLE_PROOF_BLUEPRINT),
105                            blueprint_version: BlueprintVersion::default(),
106                            outer_obj_info: OuterObjectInfo::Some {
107                                outer_object: resource_address.into(),
108                            },
109                            features: indexset!(),
110                            generic_substitutions: vec![],
111                        },
112                        object_type: ObjectType::Owned,
113                    }))),
114                )?;
115                api.kernel_pin_node(node_id)?;
116            }
117        }
118
119        Ok(Proof(Own(node_id)))
120    }
121
122    pub fn create_proof_of_non_fungibles<
123        Y: SystemApi<RuntimeError> + KernelNodeApi + KernelSubstateApi<SystemLockData>,
124    >(
125        resource_address: ResourceAddress,
126        ids: IndexSet<NonFungibleLocalId>,
127        api: &mut Y,
128    ) -> Result<Proof, RuntimeError> {
129        let auth_zone_handle = api.actor_open_field(
130            ACTOR_STATE_SELF,
131            AuthZoneField::AuthZone.into(),
132            LockFlags::MUTABLE,
133        )?;
134
135        let composed_proof = {
136            let auth_zone: AuthZone = api.field_read_typed(auth_zone_handle)?;
137            let proofs: Vec<Proof> = auth_zone.proofs.iter().map(|p| Proof(p.0)).collect();
138            compose_proof_by_ids(&proofs, resource_address, Some(ids), api)?
139        };
140
141        let node_id = api.kernel_allocate_node_id(EntityType::InternalGenericComponent)?;
142        api.kernel_create_node(
143            node_id,
144            btreemap!(
145                MAIN_BASE_PARTITION => composed_proof.into(),
146                TYPE_INFO_FIELD_PARTITION => type_info_partition(TypeInfoSubstate::Object(ObjectInfo {
147                    blueprint_info: BlueprintInfo {
148                        blueprint_id: BlueprintId::new(&RESOURCE_PACKAGE, NON_FUNGIBLE_PROOF_BLUEPRINT),
149                        blueprint_version: BlueprintVersion::default(),
150                        outer_obj_info: OuterObjectInfo::Some {
151                            outer_object: resource_address.into(),
152                        },
153                        features: indexset!(),
154                        generic_substitutions: vec![],
155                    },
156                    object_type: ObjectType::Owned,
157                }))
158            ),
159        )?;
160        api.kernel_pin_node(node_id)?;
161
162        Ok(Proof(Own(node_id)))
163    }
164
165    pub fn create_proof_of_all<
166        Y: SystemApi<RuntimeError> + KernelNodeApi + KernelSubstateApi<SystemLockData>,
167    >(
168        resource_address: ResourceAddress,
169        api: &mut Y,
170    ) -> Result<Proof, RuntimeError> {
171        let auth_zone_handle = api.actor_open_field(
172            ACTOR_STATE_SELF,
173            AuthZoneField::AuthZone.into(),
174            LockFlags::MUTABLE,
175        )?;
176
177        let auth_zone: AuthZone = api.field_read_typed(auth_zone_handle)?;
178        let proofs: Vec<Proof> = auth_zone.proofs.iter().map(|p| Proof(p.0)).collect();
179        let composed_proof = compose_proof_by_amount(&proofs, resource_address, None, api)?;
180
181        let blueprint_name = match &composed_proof {
182            ComposedProof::Fungible(..) => FUNGIBLE_PROOF_BLUEPRINT,
183            ComposedProof::NonFungible(..) => NON_FUNGIBLE_PROOF_BLUEPRINT,
184        };
185        api.field_write_typed(auth_zone_handle, &auth_zone)?;
186
187        let node_id = api.kernel_allocate_node_id(EntityType::InternalGenericComponent)?;
188        api.kernel_create_node(
189            node_id,
190            btreemap!(
191                MAIN_BASE_PARTITION => composed_proof.into(),
192                TYPE_INFO_FIELD_PARTITION => type_info_partition(TypeInfoSubstate::Object(ObjectInfo {
193                    blueprint_info: BlueprintInfo {
194                        blueprint_id: BlueprintId::new(&RESOURCE_PACKAGE, blueprint_name),
195                        blueprint_version: BlueprintVersion::default(),
196                        outer_obj_info: OuterObjectInfo::Some {
197                            outer_object: resource_address.into(),
198                        },
199                        features: indexset!(),
200                        generic_substitutions: vec![],
201                    },
202                    object_type: ObjectType::Owned,
203                }))
204            ),
205        )?;
206        api.kernel_pin_node(node_id)?;
207
208        Ok(Proof(Own(node_id)))
209    }
210
211    pub fn drop_proofs<Y: SystemApi<RuntimeError>>(api: &mut Y) -> Result<(), RuntimeError> {
212        Self::drop_signature_proofs(api)?;
213        Self::drop_regular_proofs(api)?;
214        Ok(())
215    }
216
217    pub fn drop_signature_proofs<Y: SystemApi<RuntimeError>>(
218        api: &mut Y,
219    ) -> Result<(), RuntimeError> {
220        let handle = api.actor_open_field(
221            ACTOR_STATE_SELF,
222            AuthZoneField::AuthZone.into(),
223            LockFlags::MUTABLE,
224        )?;
225        let mut auth_zone: AuthZone = api.field_read_typed(handle)?;
226        auth_zone.remove_signature_proofs();
227        api.field_write_typed(handle, &auth_zone)?;
228        api.field_close(handle)?;
229
230        Ok(())
231    }
232
233    pub fn drop_regular_proofs<Y: SystemApi<RuntimeError>>(
234        api: &mut Y,
235    ) -> Result<(), RuntimeError> {
236        let handle = api.actor_open_field(
237            ACTOR_STATE_SELF,
238            AuthZoneField::AuthZone.into(),
239            LockFlags::MUTABLE,
240        )?;
241        let mut auth_zone: AuthZone = api.field_read_typed(handle)?;
242        let proofs = auth_zone.remove_regular_proofs();
243        api.field_write_typed(handle, &auth_zone)?;
244        api.field_close(handle)?;
245
246        for proof in proofs {
247            proof.drop(api)?;
248        }
249
250        Ok(())
251    }
252
253    pub fn drain<Y: SystemApi<RuntimeError>>(api: &mut Y) -> Result<Vec<Proof>, RuntimeError> {
254        let auth_zone_handle = api.actor_open_field(
255            ACTOR_STATE_SELF,
256            AuthZoneField::AuthZone.into(),
257            LockFlags::MUTABLE,
258        )?;
259
260        let mut auth_zone: AuthZone = api.field_read_typed(auth_zone_handle)?;
261        let proofs = auth_zone.remove_regular_proofs();
262        api.field_write_typed(auth_zone_handle, &auth_zone)?;
263
264        Ok(proofs)
265    }
266
267    pub fn assert_access_rule<
268        Y: SystemApi<RuntimeError> + KernelSubstateApi<L> + SystemBasedKernelInternalApi,
269        L: Default,
270    >(
271        access_rule: AccessRule,
272        api: &mut Y,
273    ) -> Result<(), RuntimeError> {
274        let node_id = api.actor_get_node_id(ACTOR_REF_SELF)?;
275
276        let system = api.kernel_get_system();
277        if system
278            .versioned_system_logic
279            .assert_access_rule_is_noop_when_auth_module_disabled()
280            && !system.modules.is_auth_enabled()
281        {
282            return Ok(());
283        }
284
285        let auth_result =
286            Authorization::check_authorization_against_access_rule(api, &node_id, &access_rule)?;
287
288        match auth_result {
289            AuthorizationCheckResult::Authorized => Ok(()),
290            AuthorizationCheckResult::Failed(..) => Err(RuntimeError::SystemError(
291                SystemError::AssertAccessRuleFailed,
292            )),
293        }
294    }
295}