radix_transactions/builder/
manifest_namer.rs

1use crate::internal_prelude::*;
2
3/// This is used by a user to lookup buckets/proofs/reservations/addresses
4/// for working with a manifest builder.
5pub struct ManifestNameLookup {
6    core: Rc<RefCell<ManifestNamerCore>>,
7}
8
9/// This is used by a manifest builder.
10///
11/// It shares a core with a ManifestNameLookup.
12///
13/// It offers more options than a ManifestNamer, to allow for the manifest instructions
14/// to control the association of names (eg `NewManifestBucket`) with the corresponding ids
15/// (eg `ManifestBucket`).
16pub struct ManifestNameRegistrar {
17    core: Rc<RefCell<ManifestNamerCore>>,
18}
19
20/// The ManifestNamerId is a mechanism to try to avoid people accidentally mismatching namers and builders
21/// Such a mismatch would create unexpected behaviour
22#[derive(PartialEq, Eq, Clone, Copy, Default)]
23struct ManifestNamerId(u64);
24
25static GLOBAL_INCREMENTER: core::sync::atomic::AtomicU64 = core::sync::atomic::AtomicU64::new(0);
26
27impl ManifestNamerId {
28    pub fn new_unique() -> Self {
29        Self(GLOBAL_INCREMENTER.fetch_add(1, core::sync::atomic::Ordering::Acquire))
30    }
31}
32
33/// This exposes a shared stateful core between a ManifestNamer and its corresponding Registrar.
34/// This core is wrapped in a Rc<RefCell> for sharing between the two.
35#[derive(Default)]
36struct ManifestNamerCore {
37    namer_id: ManifestNamerId,
38    id_allocator: ManifestIdAllocator,
39    named_buckets: IndexMap<String, ManifestObjectState<ManifestBucket>>,
40    named_proofs: IndexMap<String, ManifestObjectState<ManifestProof>>,
41    named_addresses: NonIterMap<String, ManifestObjectState<ManifestNamedAddress>>,
42    named_address_reservations: NonIterMap<String, ManifestObjectState<ManifestAddressReservation>>,
43    named_intents: NonIterMap<String, ManifestObjectState<ManifestNamedIntent>>,
44    object_names: KnownManifestObjectNames,
45}
46
47impl ManifestNamerCore {
48    pub fn new_named_bucket(&mut self, name: impl Into<String>) -> NamedManifestBucket {
49        let name = name.into();
50        let old_entry = self
51            .named_buckets
52            .insert(name.clone(), ManifestObjectState::Unregistered);
53        if old_entry.is_some() {
54            panic!("You cannot create a new bucket with the same name \"{name}\" multiple times");
55        }
56        NamedManifestBucket {
57            namer_id: self.namer_id,
58            name,
59        }
60    }
61
62    pub fn new_collision_free_bucket_name(&mut self, prefix: &str) -> String {
63        for name_counter in 1..u32::MAX {
64            let name = if name_counter == 1 {
65                prefix.to_string()
66            } else {
67                format!("{prefix}_{name_counter}")
68            };
69            if !self.named_buckets.contains_key(&name) {
70                return name;
71            }
72        }
73        panic!("Did not resolve a name");
74    }
75
76    pub fn resolve_named_bucket(&self, name: impl AsRef<str>) -> ManifestBucket {
77        match self.named_buckets.get(name.as_ref()) {
78            Some(ManifestObjectState::Present(bucket)) => *bucket,
79            Some(ManifestObjectState::Consumed) => panic!("Bucket with name \"{}\" has already been consumed", name.as_ref()),
80            _ => panic!("You cannot use a bucket with name \"{}\" before it has been created with a relevant instruction in the manifest builder", name.as_ref()),
81        }
82    }
83
84    /// This is intended for registering a bucket name to an allocated identifier, as part of processing a manifest
85    /// instruction which creates a bucket.
86    pub fn register_bucket(&mut self, new: NamedManifestBucket) {
87        if self.namer_id != new.namer_id {
88            panic!("NewManifestBucket cannot be registered against a different ManifestNamer")
89        }
90        let new_bucket = self.id_allocator.new_bucket_id();
91        match self.named_buckets.get_mut(&new.name) {
92            Some(allocated @ ManifestObjectState::Unregistered) => {
93                *allocated = ManifestObjectState::Present(new_bucket);
94                self
95                .object_names.bucket_names.insert(new_bucket, new.name);
96            },
97            Some(_) => unreachable!("NewManifestBucket was somehow registered twice"),
98            None => unreachable!("NewManifestBucket was somehow created without a corresponding entry being added in the name allocation map"),
99        }
100    }
101
102    pub fn consume_bucket(&mut self, consumed: ManifestBucket) {
103        let name = self
104            .object_names
105            .bucket_names
106            .get(&consumed)
107            .expect("Consumed bucket was not recognised")
108            .to_string();
109        let entry = self
110            .named_buckets
111            .get_mut(&name)
112            .expect("Inverse index somehow became inconsistent");
113        *entry = ManifestObjectState::Consumed;
114    }
115
116    pub fn consume_all_buckets(&mut self) {
117        for (_, state) in self.named_buckets.iter_mut() {
118            if let ManifestObjectState::Present(_) = state {
119                *state = ManifestObjectState::Consumed;
120            }
121        }
122    }
123
124    pub fn assert_bucket_exists(&self, bucket: ManifestBucket) {
125        self.object_names
126            .bucket_names
127            .get(&bucket)
128            .expect("Bucket was not recognised - perhaps you're using a bucket not sourced from this builder?");
129    }
130
131    pub fn new_named_proof(&mut self, name: impl Into<String>) -> NamedManifestProof {
132        let name = name.into();
133        let old_entry = self
134            .named_proofs
135            .insert(name.clone(), ManifestObjectState::Unregistered);
136        if old_entry.is_some() {
137            panic!("You cannot create a new proof with the same name \"{name}\" multiple times");
138        }
139        NamedManifestProof {
140            namer_id: self.namer_id,
141            name,
142        }
143    }
144
145    pub fn new_collision_free_proof_name(&mut self, prefix: &str) -> String {
146        for name_counter in 1..u32::MAX {
147            let name = if name_counter == 1 {
148                prefix.to_string()
149            } else {
150                format!("{prefix}_{name_counter}")
151            };
152            if !self.named_proofs.contains_key(&name) {
153                return name;
154            }
155        }
156        panic!("Did not resolve a name");
157    }
158
159    pub fn resolve_named_proof(&self, name: impl AsRef<str>) -> ManifestProof {
160        match self.named_proofs.get(name.as_ref()) {
161            Some(ManifestObjectState::Present(proof)) => *proof,
162            Some(ManifestObjectState::Consumed) => panic!("Proof with name \"{}\" has already been consumed", name.as_ref()),
163            _ => panic!("You cannot use a proof with name \"{}\" before it has been created with a relevant instruction in the manifest builder", name.as_ref()),
164        }
165    }
166
167    /// This is intended for registering a proof name to an allocated identifier, as part of processing a manifest
168    /// instruction which creates a proof.
169    pub fn register_proof(&mut self, new: NamedManifestProof) {
170        if self.namer_id != new.namer_id {
171            panic!("NewManifestProof cannot be registered against a different ManifestNamer")
172        }
173        let new_proof = self.id_allocator.new_proof_id();
174        match self.named_proofs.get_mut(&new.name) {
175            Some(allocated @ ManifestObjectState::Unregistered) => {
176                *allocated = ManifestObjectState::Present(new_proof);
177                self
178                .object_names.proof_names.insert(new_proof, new.name);
179            },
180            Some(_) => unreachable!("NewManifestProof was somehow registered twice"),
181            None => unreachable!("NewManifestProof was somehow created without a corresponding entry being added in the name allocation map"),
182        }
183    }
184
185    pub fn consume_proof(&mut self, consumed: ManifestProof) {
186        let name = self
187            .object_names
188            .proof_names
189            .get(&consumed)
190            .expect("Consumed proof was not recognised")
191            .to_string();
192        let entry = self
193            .named_proofs
194            .get_mut(&name)
195            .expect("Inverse index somehow became inconsistent");
196        *entry = ManifestObjectState::Consumed;
197    }
198
199    pub fn consume_all_proofs(&mut self) {
200        for (_, state) in self.named_proofs.iter_mut() {
201            if let ManifestObjectState::Present(_) = state {
202                *state = ManifestObjectState::Consumed;
203            }
204        }
205    }
206
207    pub fn assert_proof_exists(&self, proof: ManifestProof) {
208        self.object_names
209            .proof_names
210            .get(&proof)
211            .expect("Proof was not recognised - perhaps you're using a proof not sourced from this builder?");
212    }
213
214    pub fn new_named_address_reservation(
215        &mut self,
216        name: impl Into<String>,
217    ) -> NamedManifestAddressReservation {
218        let name = name.into();
219        let old_entry = self
220            .named_address_reservations
221            .insert(name.clone(), ManifestObjectState::Unregistered);
222        if old_entry.is_some() {
223            panic!("You cannot create a new address reservation with the same name \"{name}\" multiple times");
224        }
225        NamedManifestAddressReservation {
226            namer_id: self.namer_id,
227            name,
228        }
229    }
230
231    pub fn new_collision_free_address_reservation_name(&mut self, prefix: &str) -> String {
232        for name_counter in 1..u32::MAX {
233            let name = if name_counter == 1 {
234                prefix.to_string()
235            } else {
236                format!("{prefix}_{name_counter}")
237            };
238            if !self.named_address_reservations.contains_key(&name) {
239                return name;
240            }
241        }
242        panic!("Did not resolve a name");
243    }
244
245    pub fn resolve_named_address_reservation(
246        &self,
247        name: impl AsRef<str>,
248    ) -> ManifestAddressReservation {
249        match self.named_address_reservations.get(name.as_ref()) {
250            Some(ManifestObjectState::Present(address_reservation)) => *address_reservation,
251            Some(ManifestObjectState::Consumed) => panic!("Address reservation with name \"{}\" has already been consumed", name.as_ref()),
252            _ => panic!("You cannot use an address reservation with name \"{}\" before it has been created with a relevant instruction in the manifest builder", name.as_ref()),
253        }
254    }
255
256    /// This is intended for registering an address reservation to an allocated identifier, as part of processing a manifest
257    /// instruction which creates an address reservation.
258    pub fn register_address_reservation(&mut self, new: NamedManifestAddressReservation) {
259        if self.namer_id != new.namer_id {
260            panic!("NewManifestAddressReservation cannot be registered against a different ManifestNamer")
261        }
262        let new_address_reservation = self.id_allocator.new_address_reservation_id();
263        match self.named_address_reservations.get_mut(&new.name) {
264            Some(allocated @ ManifestObjectState::Unregistered) => {
265                *allocated = ManifestObjectState::Present(new_address_reservation);
266                self
267                .object_names.address_reservation_names.insert(new_address_reservation, new.name);
268            },
269            Some(_) => unreachable!("NewManifestAddressReservation was somehow registered twice"),
270            None => unreachable!("NewManifestAddressReservation was somehow created without a corresponding entry being added in the name allocation map"),
271        }
272    }
273
274    pub fn consume_address_reservation(&mut self, consumed: ManifestAddressReservation) {
275        let name = self
276            .object_names
277            .address_reservation_names
278            .get(&consumed)
279            .expect("Consumed address reservation was not recognised")
280            .to_string();
281        let entry = self
282            .named_address_reservations
283            .get_mut(&name)
284            .expect("Inverse index somehow became inconsistent");
285        *entry = ManifestObjectState::Consumed;
286    }
287
288    pub fn assert_address_reservation_exists(
289        &self,
290        address_reservation: ManifestAddressReservation,
291    ) {
292        self.object_names
293            .address_reservation_names
294            .get(&address_reservation)
295            .expect("Address reservation was not recognised - perhaps you're using an address reservation not sourced from this builder?");
296    }
297
298    pub fn new_named_address(&mut self, name: impl Into<String>) -> NamedManifestAddress {
299        let name = name.into();
300        let old_entry = self
301            .named_addresses
302            .insert(name.clone(), ManifestObjectState::Unregistered);
303        if old_entry.is_some() {
304            panic!("You cannot create a new named address with the same name \"{name}\" multiple times");
305        }
306        NamedManifestAddress {
307            namer_id: self.namer_id,
308            name,
309        }
310    }
311
312    pub fn new_collision_free_address_name(&mut self, prefix: &str) -> String {
313        for name_counter in 1..u32::MAX {
314            let name = if name_counter == 1 {
315                prefix.to_string()
316            } else {
317                format!("{prefix}_{name_counter}")
318            };
319            if !self.named_addresses.contains_key(&name) {
320                return name;
321            }
322        }
323        panic!("Did not resolve a name");
324    }
325
326    pub fn resolve_named_address(&self, name: impl AsRef<str>) -> ManifestNamedAddress {
327        match self.named_addresses.get(name.as_ref()) {
328            Some(ManifestObjectState::Present(address)) => *address,
329            Some(ManifestObjectState::Consumed) => unreachable!("Address not consumable"),
330            _ => panic!("You cannot use a named address with name \"{}\" before it has been created with a relevant instruction in the manifest builder", name.as_ref()),
331        }
332    }
333
334    /// This is intended for registering an address reservation to an allocated identifier, as part of processing a manifest
335    /// instruction which creates a named address.
336    pub fn register_named_address(&mut self, new: NamedManifestAddress) {
337        if self.namer_id != new.namer_id {
338            panic!("NewManifestNamedAddress cannot be registered against a different ManifestNamer")
339        }
340        let address_id = self.id_allocator.new_address_id();
341        match self.named_addresses.get_mut(&new.name) {
342            Some(allocated @ ManifestObjectState::Unregistered) => {
343                *allocated = ManifestObjectState::Present(address_id);
344                self
345                .object_names.address_names.insert(address_id, new.name);
346            },
347            Some(_) => unreachable!("NewManifestNamedAddress was somehow registered twice"),
348            None => unreachable!("NewManifestNamedAddress was somehow created without a corresponding entry being added in the name allocation map"),
349        }
350    }
351
352    pub fn assert_named_address_exists(&self, named_address: ManifestNamedAddress) {
353        self.object_names
354            .address_names
355            .get(&named_address)
356            .expect("Address was not recognised - perhaps you're using a named address not sourced from this builder?");
357    }
358
359    // Intent
360    pub fn new_intent(&mut self, name: impl Into<String>) -> NamedManifestIntent {
361        let name = name.into();
362        let old_entry = self
363            .named_intents
364            .insert(name.clone(), ManifestObjectState::Unregistered);
365        if old_entry.is_some() {
366            panic!(
367                "You cannot create a new named intent with the same name \"{name}\" multiple times"
368            );
369        }
370        NamedManifestIntent {
371            namer_id: self.namer_id,
372            name,
373        }
374    }
375
376    pub fn new_collision_free_intent_name(&mut self, prefix: &str) -> String {
377        for name_counter in 1..u32::MAX {
378            let name = if name_counter == 1 {
379                prefix.to_string()
380            } else {
381                format!("{prefix}_{name_counter}")
382            };
383            if !self.named_intents.contains_key(&name) {
384                return name;
385            }
386        }
387        panic!("Did not resolve a name");
388    }
389
390    pub fn resolve_intent(&self, name: impl AsRef<str>) -> ManifestNamedIntent {
391        match self.named_intents.get(name.as_ref()) {
392            Some(ManifestObjectState::Present(id)) => *id,
393            Some(ManifestObjectState::Consumed) => unreachable!("Intent binding has already been consumed"),
394            _ => panic!("\nAn intent with name \"{}\" has been referenced before it has been registered. To register:\n * If using a transaction builder, first use `add_signed_child(\"{}\", signed_partial_transaction)` to register the child, and then use `manifest_builder(|builder| builder...)` to build the manifest, which automatically adds the `use_child` lines at the start of the manifest.\n * If using the manifest builder by itself, use `manifest_builder.use_child(\"{}\", root_subintent_hash)` at the start to register the child subintent.\n", name.as_ref(), name.as_ref(), name.as_ref()),
395        }
396    }
397
398    /// This is intended for registering an address reservation to an allocated identifier, as part of processing a manifest
399    /// instruction which creates a named address.
400    pub fn register_intent(&mut self, new: NamedManifestIntent) {
401        if self.namer_id != new.namer_id {
402            panic!("NamedManifestIntent cannot be registered against a different ManifestNamer")
403        }
404        let id = self.id_allocator.new_named_intent_id();
405        match self.named_intents.get_mut(&new.name) {
406            Some(allocated @ ManifestObjectState::Unregistered) => {
407                *allocated = ManifestObjectState::Present(id);
408                self
409                .object_names.intent_names.insert(id, new.name);
410            },
411            Some(_) => unreachable!("NamedManifestIntent was somehow registered twice"),
412            None => unreachable!("NamedManifestIntent was somehow created without a corresponding entry being added in the name allocation map"),
413        }
414    }
415
416    pub fn assert_intent_exists(&self, intent: impl Into<ManifestNamedIntent>) {
417        self.object_names
418            .intent_names
419            .get(&intent.into())
420            .expect("Named intent was not recognised - perhaps you're using a named intent not sourced from this builder?");
421    }
422}
423
424impl ManifestNameLookup {
425    pub fn bucket(&self, name: impl AsRef<str>) -> ManifestBucket {
426        self.core.borrow().resolve_named_bucket(name)
427    }
428
429    pub fn proof(&self, name: impl AsRef<str>) -> ManifestProof {
430        self.core.borrow().resolve_named_proof(name)
431    }
432
433    pub fn address_reservation(&self, name: impl AsRef<str>) -> ManifestAddressReservation {
434        self.core.borrow().resolve_named_address_reservation(name)
435    }
436
437    pub fn named_address(&self, name: impl AsRef<str>) -> ManifestNamedAddress {
438        self.core.borrow().resolve_named_address(name)
439    }
440
441    pub fn intent(&self, name: impl AsRef<str>) -> ManifestNamedIntent {
442        self.core.borrow().resolve_intent(name)
443    }
444}
445
446impl Default for ManifestNameRegistrar {
447    fn default() -> Self {
448        Self::new()
449    }
450}
451
452impl ManifestNameRegistrar {
453    pub fn new() -> Self {
454        Self {
455            core: Rc::new(RefCell::new(ManifestNamerCore {
456                namer_id: ManifestNamerId::new_unique(),
457                ..Default::default()
458            })),
459        }
460    }
461
462    pub fn name_lookup(&self) -> ManifestNameLookup {
463        ManifestNameLookup {
464            core: self.core.clone(),
465        }
466    }
467
468    /// This just registers a string name.
469    /// It's not yet bound to anything until `register_bucket` is called.
470    pub fn new_bucket(&self, name: impl Into<String>) -> NamedManifestBucket {
471        self.core.borrow_mut().new_named_bucket(name)
472    }
473
474    pub fn new_collision_free_bucket_name(&self, prefix: impl Into<String>) -> String {
475        self.core
476            .borrow_mut()
477            .new_collision_free_bucket_name(&prefix.into())
478    }
479
480    /// This is intended for registering a bucket name to an allocated identifier, as part of processing a manifest
481    /// instruction which creates a bucket.
482    pub fn register_bucket(&self, new: NamedManifestBucket) {
483        self.core.borrow_mut().register_bucket(new);
484    }
485
486    pub fn consume_bucket(&self, consumed: ManifestBucket) {
487        self.core.borrow_mut().consume_bucket(consumed);
488    }
489
490    pub fn consume_all_buckets(&self) {
491        self.core.borrow_mut().consume_all_buckets();
492    }
493
494    /// This just registers a string name.
495    /// It's not yet bound to anything until `register_proof` is called.
496    pub fn new_proof(&self, name: impl Into<String>) -> NamedManifestProof {
497        self.core.borrow_mut().new_named_proof(name)
498    }
499
500    pub fn new_collision_free_proof_name(&self, prefix: impl Into<String>) -> String {
501        self.core
502            .borrow_mut()
503            .new_collision_free_proof_name(&prefix.into())
504    }
505
506    /// This is intended for registering a proof name to an allocated identifier, as part of processing a manifest
507    /// instruction which creates a proof.
508    pub fn register_proof(&self, new: NamedManifestProof) {
509        self.core.borrow_mut().register_proof(new)
510    }
511
512    pub fn consume_proof(&self, consumed: ManifestProof) {
513        self.core.borrow_mut().consume_proof(consumed)
514    }
515
516    pub fn consume_all_proofs(&self) {
517        self.core.borrow_mut().consume_all_proofs()
518    }
519
520    /// This just registers a string name.
521    /// It's not yet bound to anything until `register_address_reservation` is called.
522    pub fn new_address_reservation(
523        &self,
524        name: impl Into<String>,
525    ) -> NamedManifestAddressReservation {
526        self.core.borrow_mut().new_named_address_reservation(name)
527    }
528
529    pub fn new_collision_free_address_reservation_name(&self, prefix: impl Into<String>) -> String {
530        self.core
531            .borrow_mut()
532            .new_collision_free_address_reservation_name(&prefix.into())
533    }
534
535    /// This is intended for registering an address reservation to an allocated identifier, as part of processing a manifest
536    /// instruction which creates an address reservation.
537    pub fn register_address_reservation(&self, new: NamedManifestAddressReservation) {
538        self.core.borrow_mut().register_address_reservation(new);
539    }
540
541    pub fn consume_address_reservation(&self, consumed: ManifestAddressReservation) {
542        self.core.borrow_mut().consume_address_reservation(consumed);
543    }
544
545    /// This just registers a string name.
546    /// It's not yet bound to anything until `register_named_address` is called.
547    pub fn new_named_address(&self, name: impl Into<String>) -> NamedManifestAddress {
548        self.core.borrow_mut().new_named_address(name)
549    }
550
551    pub fn new_collision_free_address_name(&self, prefix: impl Into<String>) -> String {
552        self.core
553            .borrow_mut()
554            .new_collision_free_address_name(&prefix.into())
555    }
556
557    /// This is intended for registering an address reservation to an allocated identifier, as part of processing a manifest
558    /// instruction which creates a named address.
559    pub fn register_named_address(&self, new: NamedManifestAddress) {
560        self.core.borrow_mut().register_named_address(new)
561    }
562
563    /// This just registers a string name.
564    /// It's not yet bound to anything until `register_intent` is called.
565    pub fn new_intent(&self, name: impl Into<String>) -> NamedManifestIntent {
566        self.core.borrow_mut().new_intent(name)
567    }
568
569    pub fn new_collision_free_intent_name(&self, prefix: impl Into<String>) -> String {
570        self.core
571            .borrow_mut()
572            .new_collision_free_intent_name(&prefix.into())
573    }
574
575    /// This is intended for registering an intent to an allocated identifier, as part of processing a manifest
576    /// instruction which creates a named intent.
577    pub fn register_intent(&self, new: NamedManifestIntent) {
578        self.core.borrow_mut().register_intent(new)
579    }
580
581    pub fn check_intent_exists(&self, intent: impl Into<ManifestNamedIntent>) {
582        self.core.borrow().assert_intent_exists(intent)
583    }
584
585    pub fn object_names(&self) -> KnownManifestObjectNames {
586        self.core.borrow().object_names.clone()
587    }
588}
589
590pub enum ManifestObjectState<T> {
591    Unregistered,
592    Present(T),
593    Consumed,
594}
595
596//=====================
597// BUCKET
598//=====================
599
600impl LabelResolver<ManifestBucket> for ManifestNameRegistrar {
601    fn resolve_label_into(&self, name: &str) -> ManifestBucket {
602        self.name_lookup().bucket(name)
603    }
604}
605
606/// Represents a new [`ManifestBucket`] which needs registering.
607#[must_use]
608pub struct NamedManifestBucket {
609    namer_id: ManifestNamerId,
610    name: String,
611}
612
613labelled_resolvable_with_identity_impl!(NamedManifestBucket, resolver_output: Self);
614
615impl LabelResolver<NamedManifestBucket> for ManifestNameRegistrar {
616    fn resolve_label_into(&self, name: &str) -> NamedManifestBucket {
617        self.new_bucket(name)
618    }
619}
620
621/// Binds a name for a new [`ManifestBucket`].
622///
623/// Accepts a string representing the name to use for the bucket,
624/// or a newly created bucket from a [`ManifestNameRegistrar`].
625pub trait NewManifestBucket {
626    fn register(self, registrar: &ManifestNameRegistrar);
627}
628
629impl<T: LabelledResolve<NamedManifestBucket>> NewManifestBucket for T {
630    fn register(self, registrar: &ManifestNameRegistrar) {
631        registrar.register_bucket(self.labelled_resolve(registrar));
632    }
633}
634
635/// An existing bucket. Its handle will NOT be consumed by this instruction.
636///
637/// Accepts a string referencing the name of an existing created bucket,
638/// or an existing bucket from a [`ManifestNameLookup`].
639pub trait ReferencedManifestBucket {
640    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestBucket;
641}
642
643impl<T: LabelledResolve<ManifestBucket>> ReferencedManifestBucket for T {
644    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestBucket {
645        let bucket = self.labelled_resolve(registrar);
646        registrar.core.borrow().assert_bucket_exists(bucket);
647        bucket
648    }
649}
650
651/// A bucket which whose name/handle will be marked as used by this action.
652///
653/// This doesn't necessarily mean that the underlying bucket will be dropped,
654/// but if its name/handle in the manifest can no longer be used.
655///
656/// Accepts a string referencing the name of an existing created bucket,
657/// or an existing bucket from a [`ManifestNameLookup`].
658pub trait ConsumedManifestBucket {
659    fn mark_consumed(self, registrar: &ManifestNameRegistrar) -> ManifestBucket;
660}
661
662impl<T: LabelledResolve<ManifestBucket>> ConsumedManifestBucket for T {
663    fn mark_consumed(self, registrar: &ManifestNameRegistrar) -> ManifestBucket {
664        let bucket = self.labelled_resolve(registrar);
665        registrar.consume_bucket(bucket);
666        bucket
667    }
668}
669
670//=====================
671// BUCKET BATCHES
672//=====================
673
674pub trait ConsumedBucketBatch {
675    fn resolve_and_consume(self, registrar: &ManifestNameRegistrar) -> ManifestBucketBatch;
676}
677
678impl<B: LabelledResolve<ManifestBucketBatch>> ConsumedBucketBatch for B {
679    fn resolve_and_consume(self, registrar: &ManifestNameRegistrar) -> ManifestBucketBatch {
680        let bucket_batch = self.labelled_resolve(registrar);
681        match &bucket_batch {
682            ManifestBucketBatch::ManifestBuckets(owned_buckets) => {
683                for owned_bucket in owned_buckets {
684                    registrar.consume_bucket(*owned_bucket);
685                }
686            }
687            ManifestBucketBatch::EntireWorktop => {
688                // No named buckets are consumed - instead EntireWorktop refers only to the
689                // unnamed buckets on the worktop part of the transaction processor
690            }
691        }
692        bucket_batch
693    }
694}
695
696//=====================
697// PROOFS
698//=====================
699
700impl LabelResolver<ManifestProof> for ManifestNameRegistrar {
701    fn resolve_label_into(&self, name: &str) -> ManifestProof {
702        self.name_lookup().proof(name)
703    }
704}
705
706/// Represents a new [`ManifestProof`] which needs registering.
707#[must_use]
708pub struct NamedManifestProof {
709    namer_id: ManifestNamerId,
710    name: String,
711}
712
713labelled_resolvable_with_identity_impl!(NamedManifestProof, resolver_output: Self);
714
715impl LabelResolver<NamedManifestProof> for ManifestNameRegistrar {
716    fn resolve_label_into(&self, name: &str) -> NamedManifestProof {
717        self.new_proof(name)
718    }
719}
720
721/// Binds a name for a new [`ManifestProof`].
722pub trait NewManifestProof {
723    fn register(self, registrar: &ManifestNameRegistrar);
724}
725
726impl<T: LabelledResolve<NamedManifestProof>> NewManifestProof for T {
727    fn register(self, registrar: &ManifestNameRegistrar) {
728        registrar.register_proof(self.labelled_resolve(registrar));
729    }
730}
731
732/// An existing proof. Its handle will NOT be consumed by this instruction.
733///
734/// Accepts a string referencing the name of an existing created proof,
735/// or an existing proof from a [`ManifestNameLookup`].
736pub trait ReferencedManifestProof {
737    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestProof;
738}
739
740impl<T: LabelledResolve<ManifestProof>> ReferencedManifestProof for T {
741    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestProof {
742        let resolved = self.labelled_resolve(registrar);
743        registrar.core.borrow().assert_proof_exists(resolved);
744        resolved
745    }
746}
747
748/// A proof which whose name/handle will be marked as used by this action.
749///
750/// This doesn't necessarily mean that the underlying proof will be dropped,
751/// but if its name/handle in the manifest can no longer be used.
752///
753/// Accepts a string referencing the name of an existing created proof,
754/// or an existing proof from a [`ManifestNameLookup`].
755pub trait ConsumedManifestProof {
756    fn mark_consumed(self, registrar: &ManifestNameRegistrar) -> ManifestProof;
757}
758
759impl<T: LabelledResolve<ManifestProof>> ConsumedManifestProof for T {
760    fn mark_consumed(self, registrar: &ManifestNameRegistrar) -> ManifestProof {
761        let proof = self.labelled_resolve(registrar);
762        registrar.consume_proof(proof);
763        proof
764    }
765}
766
767//=====================
768// INTENTS
769//=====================
770
771impl LabelResolver<ManifestNamedIntent> for ManifestNameRegistrar {
772    fn resolve_label_into(&self, name: &str) -> ManifestNamedIntent {
773        self.name_lookup().intent(name)
774    }
775}
776
777/// Represents a new [`ManifestNamedIntent`] which needs registering.
778#[must_use]
779pub struct NamedManifestIntent {
780    namer_id: ManifestNamerId,
781    name: String,
782}
783
784labelled_resolvable_with_identity_impl!(NamedManifestIntent, resolver_output: Self);
785
786impl LabelResolver<NamedManifestIntent> for ManifestNameRegistrar {
787    fn resolve_label_into(&self, name: &str) -> NamedManifestIntent {
788        self.new_intent(name)
789    }
790}
791
792/// Binds a name for a new manifest intent.
793pub trait NewManifestIntent {
794    fn register(self, registrar: &ManifestNameRegistrar);
795}
796
797impl<T: LabelledResolve<NamedManifestIntent>> NewManifestIntent for T {
798    fn register(self, registrar: &ManifestNameRegistrar) {
799        registrar.register_intent(self.labelled_resolve(registrar));
800    }
801}
802
803/// An existing manifest intent. Its handle will NOT be consumed by this instruction.
804///
805/// Accepts a string referencing the name of an existing created named intent
806/// (created with `USE_CHILD`), or an existing intent from a [`ManifestNameLookup`].
807pub trait ReferencedManifestIntent {
808    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestNamedIntent;
809}
810
811impl<T: LabelledResolve<ManifestNamedIntent>> ReferencedManifestIntent for T {
812    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestNamedIntent {
813        let resolved = self.labelled_resolve(registrar);
814        registrar.core.borrow().assert_intent_exists(resolved);
815        resolved
816    }
817}
818
819//=====================
820// ADDRESS RESERVATIONS
821//=====================
822
823impl LabelResolver<ManifestAddressReservation> for ManifestNameRegistrar {
824    fn resolve_label_into(&self, name: &str) -> ManifestAddressReservation {
825        self.name_lookup().address_reservation(name)
826    }
827}
828
829/// Represents a new [`ManifestAddressReservation`] which needs registering.
830#[must_use]
831pub struct NamedManifestAddressReservation {
832    namer_id: ManifestNamerId,
833    name: String,
834}
835
836labelled_resolvable_with_identity_impl!(NamedManifestAddressReservation, resolver_output: Self);
837
838impl LabelResolver<NamedManifestAddressReservation> for ManifestNameRegistrar {
839    fn resolve_label_into(&self, name: &str) -> NamedManifestAddressReservation {
840        self.new_address_reservation(name)
841    }
842}
843
844/// Binds a name for a new [`ManifestAddressReservation`].
845///
846/// Accepts a string representing the name to use for the address reservation,
847/// or a newly created address reservation from a [`ManifestNameRegistrar`].
848pub trait NewManifestAddressReservation: Sized {
849    fn into_named(self, registrar: &ManifestNameRegistrar) -> NamedManifestAddressReservation;
850
851    fn register(self, registrar: &ManifestNameRegistrar) {
852        registrar.register_address_reservation(self.into_named(registrar))
853    }
854
855    fn register_and_yield(self, registrar: &ManifestNameRegistrar) -> ManifestAddressReservation {
856        let named = self.into_named(registrar);
857        let name = named.name.clone();
858        registrar.register_address_reservation(named);
859        registrar.name_lookup().address_reservation(name)
860    }
861}
862
863impl<T: LabelledResolve<NamedManifestAddressReservation>> NewManifestAddressReservation for T {
864    fn into_named(self, registrar: &ManifestNameRegistrar) -> NamedManifestAddressReservation {
865        self.labelled_resolve(registrar)
866    }
867}
868
869/// An address reservation handle will NOT be consumed by this instruction.
870pub trait ReferencedManifestAddressReservation {
871    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestAddressReservation;
872}
873
874impl<T: LabelledResolve<ManifestAddressReservation>> ReferencedManifestAddressReservation for T {
875    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestAddressReservation {
876        let address_reservation = self.labelled_resolve(registrar);
877        registrar
878            .core
879            .borrow()
880            .assert_address_reservation_exists(address_reservation);
881        address_reservation
882    }
883}
884
885/// An address reservation whose name/handle will be marked as used by this action.
886///
887/// Accepts a string referencing the name of an existing created address reservation,
888/// or an existing address reservation from a [`ManifestNameLookup`].
889pub trait ConsumedManifestAddressReservation {
890    fn mark_consumed(self, registrar: &ManifestNameRegistrar) -> ManifestAddressReservation;
891}
892
893impl<T: LabelledResolve<ManifestAddressReservation>> ConsumedManifestAddressReservation for T {
894    fn mark_consumed(self, registrar: &ManifestNameRegistrar) -> ManifestAddressReservation {
895        let address_reservation = self.labelled_resolve(registrar);
896        registrar.consume_address_reservation(address_reservation);
897        address_reservation
898    }
899}
900
901pub trait ConsumedOptionalManifestAddressReservation {
902    fn mark_consumed(self, registrar: &ManifestNameRegistrar)
903        -> Option<ManifestAddressReservation>;
904}
905
906impl<T: LabelledResolve<Option<ManifestAddressReservation>>>
907    ConsumedOptionalManifestAddressReservation for T
908{
909    fn mark_consumed(
910        self,
911        registrar: &ManifestNameRegistrar,
912    ) -> Option<ManifestAddressReservation> {
913        let reservation = self.labelled_resolve(registrar);
914        if let Some(reservation) = reservation {
915            registrar.consume_address_reservation(reservation);
916        }
917        reservation
918    }
919}
920
921//=====================
922// NAMED ADDRESSES
923//=====================
924
925impl LabelResolver<ManifestNamedAddress> for ManifestNameRegistrar {
926    fn resolve_label_into(&self, name: &str) -> ManifestNamedAddress {
927        self.name_lookup().named_address(name)
928    }
929}
930/// Represents a new [`ManifestNamedAddress`] which needs registering.
931#[must_use]
932pub struct NamedManifestAddress {
933    namer_id: ManifestNamerId,
934    name: String,
935}
936
937labelled_resolvable_with_identity_impl!(NamedManifestAddress, resolver_output: Self);
938
939impl LabelResolver<NamedManifestAddress> for ManifestNameRegistrar {
940    fn resolve_label_into(&self, name: &str) -> NamedManifestAddress {
941        self.new_named_address(name)
942    }
943}
944
945/// Binds a name for a new [`ManifestAddressReservation`].
946///
947/// Accepts a string representing the name to use for the address,
948/// or a newly created address from a [`ManifestNameRegistrar`].
949pub trait NewNamedManifestAddress {
950    fn register(self, registrar: &ManifestNameRegistrar);
951}
952
953impl<T: LabelledResolve<NamedManifestAddress>> NewNamedManifestAddress for T {
954    fn register(self, registrar: &ManifestNameRegistrar) {
955        registrar.register_named_address(self.labelled_resolve(registrar));
956    }
957}
958
959/// An address handle will NOT be consumed by this instruction.
960pub trait ReferencedManifestGlobalAddress {
961    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestGlobalAddress;
962}
963
964impl<T: LabelledResolve<ManifestGlobalAddress>> ReferencedManifestGlobalAddress for T {
965    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestGlobalAddress {
966        let address = self.labelled_resolve(registrar);
967        if let ManifestGlobalAddress::Named(named_address) = address {
968            registrar
969                .core
970                .borrow()
971                .assert_named_address_exists(named_address);
972        }
973        address
974    }
975}
976
977/// An address handle will NOT be consumed by this instruction.
978pub trait ReferencedManifestComponentAddress {
979    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestComponentAddress;
980}
981
982impl<T: LabelledResolve<ManifestComponentAddress>> ReferencedManifestComponentAddress for T {
983    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestComponentAddress {
984        let address = self.labelled_resolve(registrar);
985        if let ManifestComponentAddress::Named(named_address) = address {
986            registrar
987                .core
988                .borrow()
989                .assert_named_address_exists(named_address);
990        }
991        address
992    }
993}
994
995/// An address handle will NOT be consumed by this instruction.
996pub trait ReferencedManifestResourceAddress {
997    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestResourceAddress;
998}
999
1000impl<T: LabelledResolve<ManifestResourceAddress>> ReferencedManifestResourceAddress for T {
1001    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestResourceAddress {
1002        let address = self.labelled_resolve(registrar);
1003        if let ManifestResourceAddress::Named(named_address) = address {
1004            registrar
1005                .core
1006                .borrow()
1007                .assert_named_address_exists(named_address);
1008        }
1009        address
1010    }
1011}
1012
1013/// An address handle will NOT be consumed by this instruction.
1014pub trait ReferencedManifestPackageAddress {
1015    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestPackageAddress;
1016}
1017
1018impl<T: LabelledResolve<ManifestPackageAddress>> ReferencedManifestPackageAddress for T {
1019    fn resolve_referenced(self, registrar: &ManifestNameRegistrar) -> ManifestPackageAddress {
1020        let address = self.labelled_resolve(registrar);
1021        if let ManifestPackageAddress::Named(named_address) = address {
1022            registrar
1023                .core
1024                .borrow()
1025                .assert_named_address_exists(named_address);
1026        }
1027        address
1028    }
1029}
1030
1031//=====================
1032// ARGUMENTS
1033//=====================
1034
1035pub trait ResolvableArguments {
1036    fn resolve(self) -> ManifestValue;
1037}
1038
1039impl<T: ManifestEncode + ManifestSborTuple> ResolvableArguments for T {
1040    fn resolve(self) -> ManifestValue {
1041        manifest_decode(&manifest_encode(&self).unwrap()).unwrap()
1042    }
1043}