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.clone(), 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.clone()))
50            }
51        } else {
52            Err(ManifestIdValidationError::BucketNotFound(bucket_id.clone()))
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.clone()));
66                }
67            }
68            ProofKind::AuthZoneProof => {}
69        }
70
71        let proof_id = self.id_allocator.new_proof_id();
72        self.proof_ids.insert(proof_id.clone(), 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.clone(), kind);
90            Ok(proof_id)
91        } else {
92            Err(ManifestIdValidationError::ProofNotFound(proof_id.clone()))
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.clone()))
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
125            .insert(address_reservation_id.clone());
126        address_reservation_id
127    }
128
129    pub fn drop_address_reservation(
130        &mut self,
131        address_reservation_id: &ManifestAddressReservation,
132    ) -> Result<(), ManifestIdValidationError> {
133        if self
134            .address_reservation_ids
135            .swap_remove(address_reservation_id)
136        {
137            Ok(())
138        } else {
139            Err(ManifestIdValidationError::AddressReservationNotFound(
140                address_reservation_id.clone(),
141            ))
142        }
143    }
144
145    pub fn new_named_address(&mut self) -> ManifestNamedAddress {
146        let address_id = self.id_allocator.new_address_id();
147        self.address_ids.insert(address_id.clone());
148        address_id
149    }
150
151    pub fn check_bucket(
152        &mut self,
153        bucket_id: &ManifestBucket,
154    ) -> Result<(), ManifestIdValidationError> {
155        if self.bucket_ids.contains_key(bucket_id) {
156            Ok(())
157        } else {
158            Err(ManifestIdValidationError::BucketNotFound(bucket_id.clone()))
159        }
160    }
161
162    pub fn check_named_address(
163        &mut self,
164        address_id: &ManifestNamedAddress,
165    ) -> Result<(), ManifestIdValidationError> {
166        if self.address_ids.contains(address_id) {
167            Ok(())
168        } else {
169            Err(ManifestIdValidationError::AddressNotFound(
170                address_id.clone(),
171            ))
172        }
173    }
174
175    pub fn new_intent(&mut self) -> ManifestNamedIntent {
176        let intent_id = self.id_allocator.new_named_intent_id();
177        self.intent_ids.insert(intent_id.clone());
178        intent_id
179    }
180
181    pub fn process_call_data(
182        &mut self,
183        args: &ManifestValue,
184    ) -> Result<(), ManifestIdValidationError> {
185        transform(args.clone(), self).map(|_| ())
186    }
187}
188
189impl TransformHandler<ManifestIdValidationError> for BasicManifestValidator {
190    fn replace_bucket(&mut self, b: ManifestBucket) -> Result<Own, ManifestIdValidationError> {
191        self.drop_bucket(&b)?;
192        Ok(Own(NodeId([0u8; NodeId::LENGTH])))
193    }
194
195    fn replace_proof(&mut self, p: ManifestProof) -> Result<Own, ManifestIdValidationError> {
196        self.drop_proof(&p)?;
197        Ok(Own(NodeId([0u8; NodeId::LENGTH])))
198    }
199
200    fn replace_address_reservation(
201        &mut self,
202        r: ManifestAddressReservation,
203    ) -> Result<Own, ManifestIdValidationError> {
204        self.drop_address_reservation(&r)?;
205        Ok(Own(NodeId([0u8; NodeId::LENGTH])))
206    }
207
208    fn replace_named_address(
209        &mut self,
210        a: ManifestNamedAddress,
211    ) -> Result<Reference, ManifestIdValidationError> {
212        self.check_named_address(&a)?;
213        Ok(Reference(NodeId([0u8; NodeId::LENGTH])))
214    }
215
216    fn replace_expression(
217        &mut self,
218        _e: ManifestExpression,
219    ) -> Result<Vec<Own>, ManifestIdValidationError> {
220        Ok(Vec::new())
221    }
222
223    // TODO: validate blob as well?
224    fn replace_blob(&mut self, _b: ManifestBlobRef) -> Result<Vec<u8>, ManifestIdValidationError> {
225        Ok(Vec::new())
226    }
227}