radix_transactions/validation/
id_validator.rs

1use crate::data::*;
2use crate::internal_prelude::*;
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum ProofKind {
6    /// Proof created from a bucket
7    BucketProof(ManifestBucket),
8    /// Proof created from auth zone.
9    AuthZoneProof,
10}
11
12/// For advanced validation, you should consider using the
13/// [`StaticManifestInterpreter`] instead.
14#[derive(Default)]
15pub struct BasicManifestValidator {
16    id_allocator: ManifestIdAllocator,
17    /// Bucket id -> lock count
18    bucket_ids: NonIterMap<ManifestBucket, usize>,
19    /// Proof id to proof info
20    proof_ids: BTreeMap<ManifestProof, ProofKind>,
21    /// Set of active allocated global address reservation ids
22    address_reservation_ids: IndexSet<ManifestAddressReservation>,
23    /// Set of named global address ids
24    address_ids: IndexSet<ManifestNamedAddress>,
25    /// Set of named intent hashes
26    intent_ids: IndexSet<ManifestNamedIntent>,
27}
28
29impl BasicManifestValidator {
30    pub fn new() -> Self {
31        Self::default()
32    }
33
34    pub fn new_bucket(&mut self) -> ManifestBucket {
35        let bucket_id = self.id_allocator.new_bucket_id();
36        self.bucket_ids.insert(bucket_id, 0);
37        bucket_id
38    }
39
40    pub fn drop_bucket(
41        &mut self,
42        bucket_id: &ManifestBucket,
43    ) -> Result<(), ManifestIdValidationError> {
44        if let Some(cnt) = self.bucket_ids.get(bucket_id) {
45            if *cnt == 0 {
46                self.bucket_ids.remove(bucket_id);
47                Ok(())
48            } else {
49                Err(ManifestIdValidationError::BucketLocked(*bucket_id))
50            }
51        } else {
52            Err(ManifestIdValidationError::BucketNotFound(*bucket_id))
53        }
54    }
55
56    pub fn new_proof(
57        &mut self,
58        kind: ProofKind,
59    ) -> Result<ManifestProof, ManifestIdValidationError> {
60        match &kind {
61            ProofKind::BucketProof(bucket_id) => {
62                if let Some(cnt) = self.bucket_ids.get_mut(bucket_id) {
63                    *cnt += 1;
64                } else {
65                    return Err(ManifestIdValidationError::BucketNotFound(*bucket_id));
66                }
67            }
68            ProofKind::AuthZoneProof => {}
69        }
70
71        let proof_id = self.id_allocator.new_proof_id();
72        self.proof_ids.insert(proof_id, kind);
73        Ok(proof_id)
74    }
75
76    pub fn clone_proof(
77        &mut self,
78        proof_id: &ManifestProof,
79    ) -> Result<ManifestProof, ManifestIdValidationError> {
80        if let Some(kind) = self.proof_ids.get(proof_id).cloned() {
81            if let ProofKind::BucketProof(bucket_id) = &kind {
82                if let Some(cnt) = self.bucket_ids.get_mut(bucket_id) {
83                    *cnt += 1;
84                } else {
85                    panic!("Illegal state");
86                }
87            }
88            let proof_id = self.id_allocator.new_proof_id();
89            self.proof_ids.insert(proof_id, kind);
90            Ok(proof_id)
91        } else {
92            Err(ManifestIdValidationError::ProofNotFound(*proof_id))
93        }
94    }
95
96    pub fn drop_proof(
97        &mut self,
98        proof_id: &ManifestProof,
99    ) -> Result<(), ManifestIdValidationError> {
100        if let Some(kind) = self.proof_ids.remove(proof_id) {
101            if let ProofKind::BucketProof(bucket_id) = kind {
102                if let Some(cnt) = self.bucket_ids.get_mut(&bucket_id) {
103                    *cnt -= 1;
104                } else {
105                    panic!("Illegal state");
106                }
107            }
108            Ok(())
109        } else {
110            Err(ManifestIdValidationError::ProofNotFound(*proof_id))
111        }
112    }
113
114    pub fn drop_all_named_proofs(&mut self) -> Result<(), ManifestIdValidationError> {
115        let proof_ids = self.proof_ids.keys().copied().collect::<Vec<_>>();
116        for proof_id in proof_ids {
117            self.drop_proof(&proof_id)?
118        }
119        Ok(())
120    }
121
122    pub fn new_address_reservation(&mut self) -> ManifestAddressReservation {
123        let address_reservation_id = self.id_allocator.new_address_reservation_id();
124        self.address_reservation_ids.insert(address_reservation_id);
125        address_reservation_id
126    }
127
128    pub fn drop_address_reservation(
129        &mut self,
130        address_reservation_id: &ManifestAddressReservation,
131    ) -> Result<(), ManifestIdValidationError> {
132        if self
133            .address_reservation_ids
134            .swap_remove(address_reservation_id)
135        {
136            Ok(())
137        } else {
138            Err(ManifestIdValidationError::AddressReservationNotFound(
139                *address_reservation_id,
140            ))
141        }
142    }
143
144    pub fn new_named_address(&mut self) -> ManifestNamedAddress {
145        let address_id = self.id_allocator.new_address_id();
146        self.address_ids.insert(address_id);
147        address_id
148    }
149
150    pub fn check_bucket(
151        &mut self,
152        bucket_id: &ManifestBucket,
153    ) -> Result<(), ManifestIdValidationError> {
154        if self.bucket_ids.contains_key(bucket_id) {
155            Ok(())
156        } else {
157            Err(ManifestIdValidationError::BucketNotFound(*bucket_id))
158        }
159    }
160
161    pub fn check_named_address(
162        &mut self,
163        address_id: &ManifestNamedAddress,
164    ) -> Result<(), ManifestIdValidationError> {
165        if self.address_ids.contains(address_id) {
166            Ok(())
167        } else {
168            Err(ManifestIdValidationError::AddressNotFound(*address_id))
169        }
170    }
171
172    pub fn new_intent(&mut self) -> ManifestNamedIntent {
173        let intent_id = self.id_allocator.new_named_intent_id();
174        self.intent_ids.insert(intent_id);
175        intent_id
176    }
177
178    pub fn process_call_data(
179        &mut self,
180        args: &ManifestValue,
181    ) -> Result<(), ManifestIdValidationError> {
182        transform(args.clone(), self).map(|_| ())
183    }
184}
185
186impl TransformHandler<ManifestIdValidationError> for BasicManifestValidator {
187    fn replace_bucket(&mut self, b: ManifestBucket) -> Result<Own, ManifestIdValidationError> {
188        self.drop_bucket(&b)?;
189        Ok(Own(NodeId([0u8; NodeId::LENGTH])))
190    }
191
192    fn replace_proof(&mut self, p: ManifestProof) -> Result<Own, ManifestIdValidationError> {
193        self.drop_proof(&p)?;
194        Ok(Own(NodeId([0u8; NodeId::LENGTH])))
195    }
196
197    fn replace_address_reservation(
198        &mut self,
199        r: ManifestAddressReservation,
200    ) -> Result<Own, ManifestIdValidationError> {
201        self.drop_address_reservation(&r)?;
202        Ok(Own(NodeId([0u8; NodeId::LENGTH])))
203    }
204
205    fn replace_named_address(
206        &mut self,
207        a: ManifestNamedAddress,
208    ) -> Result<Reference, ManifestIdValidationError> {
209        self.check_named_address(&a)?;
210        Ok(Reference(NodeId([0u8; NodeId::LENGTH])))
211    }
212
213    fn replace_expression(
214        &mut self,
215        _e: ManifestExpression,
216    ) -> Result<Vec<Own>, ManifestIdValidationError> {
217        Ok(Vec::new())
218    }
219
220    // TODO: validate blob as well?
221    fn replace_blob(&mut self, _b: ManifestBlobRef) -> Result<Vec<u8>, ManifestIdValidationError> {
222        Ok(Vec::new())
223    }
224}