radix_common/data/manifest/model/
manifest_address_kinds.rs

1use crate::internal_prelude::*;
2use radix_common::scrypto_describe_for_manifest_type;
3use sbor::{Decoder, Encoder};
4
5/*
6=================================================================================
7NOTE: For now, we only support "dynamic" addresses for CALL instructions.
8=================================================================================
9This is to reduce the scope of change and make manifest easier to reason about.
10
11In theory, we can apply it to all types of global addresses (`GlobalAddress`,
12`PackageAddress`, `ResourceAddress` and `ComponentAddress`).
13
14Then, we can do more advanced stuff in manifest, such as
15```
16ALLOCATE_GLOBAL_ADDRESS
17    Address("{resource_package}")
18    "FungibleResourceManager"
19    AddressReservation("address_reservation")
20    NamedAddress("new_resource")
21;
22CALL_FUNCTION
23    Address("{resource_package}")
24    "FungibleResourceManager"
25    "create_with_initial_supply_and_address"
26    Decimal("10")
27    AddressReservation("address_reservation")
28;
29TAKE_FROM_WORKTOP
30    NamedAddress("new_resource")
31    Decimal("5.0")
32    Bucket("bucket1")
33;
34TAKE_FROM_WORKTOP
35    NamedAddress("new_resource")
36    Decimal("5.0")
37    Bucket("bucket2")
38;
39```
40*/
41
42macro_rules! labelled_resolvable_address {
43    ($ty:ty$(,)?) => {
44        resolvable_with_try_into_impls!($ty);
45        labelled_resolvable_using_resolvable_impl!($ty, resolver_output: ManifestNamedAddress);
46
47        impl<'a> LabelledResolveFrom<&'a str> for $ty {
48            fn labelled_resolve_from(value: &'a str, resolver: &impl LabelResolver<ManifestNamedAddress>) -> Self {
49                resolver.resolve_label_into(value).into()
50            }
51        }
52
53        impl<'a> LabelledResolveFrom<&'a String> for $ty {
54            fn labelled_resolve_from(value: &'a String, resolver: &impl LabelResolver<ManifestNamedAddress>) -> Self {
55                resolver.resolve_label_into(value.as_str()).into()
56            }
57        }
58
59        impl<'a> LabelledResolveFrom<String> for $ty {
60            fn labelled_resolve_from(value: String, resolver: &impl LabelResolver<ManifestNamedAddress>) -> Self {
61                resolver.resolve_label_into(value.as_str()).into()
62            }
63        }
64    };
65}
66
67pub trait IntoManifestAddress {
68    type ManifestAddress;
69
70    fn into_manifest_address(self) -> Self::ManifestAddress;
71}
72
73// Alias for backwards-compatibility
74pub type DynamicGlobalAddress = ManifestGlobalAddress;
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
77pub enum ManifestGlobalAddress {
78    Static(GlobalAddress),
79    Named(ManifestNamedAddress),
80}
81
82impl IntoManifestAddress for GlobalAddress {
83    type ManifestAddress = ManifestGlobalAddress;
84
85    fn into_manifest_address(self) -> Self::ManifestAddress {
86        Self::ManifestAddress::Static(self)
87    }
88}
89
90scrypto_describe_for_manifest_type!(
91    ManifestGlobalAddress,
92    GLOBAL_ADDRESS_TYPE,
93    global_address_type_data,
94);
95
96labelled_resolvable_address!(ManifestGlobalAddress);
97
98impl Categorize<ManifestCustomValueKind> for ManifestGlobalAddress {
99    #[inline]
100    fn value_kind() -> ValueKind<ManifestCustomValueKind> {
101        ValueKind::Custom(ManifestCustomValueKind::Address)
102    }
103}
104
105impl<E: Encoder<ManifestCustomValueKind>> Encode<ManifestCustomValueKind, E>
106    for ManifestGlobalAddress
107{
108    #[inline]
109    fn encode_value_kind(&self, encoder: &mut E) -> Result<(), EncodeError> {
110        encoder.write_value_kind(Self::value_kind())
111    }
112
113    #[inline]
114    fn encode_body(&self, encoder: &mut E) -> Result<(), EncodeError> {
115        match self {
116            Self::Static(address) => {
117                encoder.write_discriminator(MANIFEST_ADDRESS_DISCRIMINATOR_STATIC)?;
118                encoder.write_slice(address.as_node_id().as_bytes())?;
119            }
120            Self::Named(address_id) => {
121                encoder.write_discriminator(MANIFEST_ADDRESS_DISCRIMINATOR_NAMED)?;
122                encoder.write_slice(&address_id.0.to_le_bytes())?;
123            }
124        }
125        Ok(())
126    }
127}
128
129impl<D: Decoder<ManifestCustomValueKind>> Decode<ManifestCustomValueKind, D>
130    for ManifestGlobalAddress
131{
132    fn decode_body_with_value_kind(
133        decoder: &mut D,
134        value_kind: ValueKind<ManifestCustomValueKind>,
135    ) -> Result<Self, DecodeError> {
136        decoder.check_preloaded_value_kind(value_kind, Self::value_kind())?;
137        match decoder.read_discriminator()? {
138            MANIFEST_ADDRESS_DISCRIMINATOR_STATIC => {
139                let slice = decoder.read_slice(NodeId::LENGTH)?;
140                Ok(Self::Static(
141                    GlobalAddress::try_from(slice).map_err(|_| DecodeError::InvalidCustomValue)?,
142                ))
143            }
144            MANIFEST_ADDRESS_DISCRIMINATOR_NAMED => {
145                let slice = decoder.read_slice(4)?;
146                let id = u32::from_le_bytes(slice.try_into().unwrap());
147                Ok(Self::Named(ManifestNamedAddress(id)))
148            }
149            _ => Err(DecodeError::InvalidCustomValue),
150        }
151    }
152}
153
154impl ManifestGlobalAddress {
155    /// This is to support either `Address("static_address")` or `NamedAddress("abc")` in manifest instruction,
156    /// instead of `Enum<0u8>(Address("static_address"))`.
157    pub fn to_instruction_argument(&self) -> ManifestValue {
158        match self {
159            Self::Static(address) => ManifestValue::Custom {
160                value: ManifestCustomValue::Address(ManifestAddress::Static(
161                    address.into_node_id(),
162                )),
163            },
164            Self::Named(id) => ManifestValue::Custom {
165                value: ManifestCustomValue::Address(ManifestAddress::Named(*id)),
166            },
167        }
168    }
169
170    pub fn is_static_global_package(&self) -> bool {
171        match self {
172            Self::Static(address) => address.as_node_id().is_global_package(),
173            Self::Named(_) => false,
174        }
175    }
176
177    pub fn is_static_global_fungible_resource_manager(&self) -> bool {
178        match self {
179            Self::Static(address) => address.as_node_id().is_global_fungible_resource_manager(),
180            Self::Named(_) => false,
181        }
182    }
183    pub fn is_static_global_non_fungible_resource_manager(&self) -> bool {
184        match self {
185            Self::Static(address) => address
186                .as_node_id()
187                .is_global_non_fungible_resource_manager(),
188            Self::Named(_) => false,
189        }
190    }
191}
192
193impl From<GlobalAddress> for ManifestGlobalAddress {
194    fn from(value: GlobalAddress) -> Self {
195        Self::Static(value)
196    }
197}
198
199impl From<PackageAddress> for ManifestGlobalAddress {
200    fn from(value: PackageAddress) -> Self {
201        Self::Static(value.into())
202    }
203}
204
205impl From<ManifestPackageAddress> for ManifestGlobalAddress {
206    fn from(value: ManifestPackageAddress) -> Self {
207        match value {
208            ManifestPackageAddress::Static(value) => Self::Static(value.into()),
209            ManifestPackageAddress::Named(value) => Self::Named(value),
210        }
211    }
212}
213
214impl From<ResourceAddress> for ManifestGlobalAddress {
215    fn from(value: ResourceAddress) -> Self {
216        Self::Static(value.into())
217    }
218}
219
220impl From<ManifestResourceAddress> for ManifestGlobalAddress {
221    fn from(value: ManifestResourceAddress) -> Self {
222        match value {
223            ManifestResourceAddress::Static(value) => Self::Static(value.into()),
224            ManifestResourceAddress::Named(value) => Self::Named(value),
225        }
226    }
227}
228
229impl From<ComponentAddress> for ManifestGlobalAddress {
230    fn from(value: ComponentAddress) -> Self {
231        Self::Static(value.into())
232    }
233}
234
235impl From<ManifestComponentAddress> for ManifestGlobalAddress {
236    fn from(value: ManifestComponentAddress) -> Self {
237        match value {
238            ManifestComponentAddress::Static(value) => Self::Static(value.into()),
239            ManifestComponentAddress::Named(value) => Self::Named(value),
240        }
241    }
242}
243
244impl From<ManifestNamedAddress> for ManifestGlobalAddress {
245    fn from(value: ManifestNamedAddress) -> Self {
246        Self::Named(value)
247    }
248}
249
250impl TryFrom<ManifestAddress> for ManifestGlobalAddress {
251    type Error = ParseGlobalAddressError;
252
253    fn try_from(value: ManifestAddress) -> Result<Self, Self::Error> {
254        Ok(match value {
255            ManifestAddress::Static(value) => Self::Static(value.try_into()?),
256            ManifestAddress::Named(value) => Self::Named(value),
257        })
258    }
259}
260
261// Alias for backwards-compatibility
262pub type DynamicPackageAddress = ManifestPackageAddress;
263
264#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
265pub enum ManifestPackageAddress {
266    Static(PackageAddress),
267    Named(ManifestNamedAddress),
268}
269
270impl IntoManifestAddress for PackageAddress {
271    type ManifestAddress = ManifestPackageAddress;
272
273    fn into_manifest_address(self) -> Self::ManifestAddress {
274        Self::ManifestAddress::Static(self)
275    }
276}
277
278scrypto_describe_for_manifest_type!(
279    ManifestPackageAddress,
280    PACKAGE_ADDRESS_TYPE,
281    package_address_type_data,
282);
283
284labelled_resolvable_address!(ManifestPackageAddress);
285
286impl Categorize<ManifestCustomValueKind> for ManifestPackageAddress {
287    #[inline]
288    fn value_kind() -> ValueKind<ManifestCustomValueKind> {
289        ValueKind::Custom(ManifestCustomValueKind::Address)
290    }
291}
292
293impl<E: Encoder<ManifestCustomValueKind>> Encode<ManifestCustomValueKind, E>
294    for ManifestPackageAddress
295{
296    #[inline]
297    fn encode_value_kind(&self, encoder: &mut E) -> Result<(), EncodeError> {
298        encoder.write_value_kind(Self::value_kind())
299    }
300
301    #[inline]
302    fn encode_body(&self, encoder: &mut E) -> Result<(), EncodeError> {
303        match self {
304            Self::Static(address) => {
305                encoder.write_discriminator(0)?;
306                encoder.write_slice(address.as_node_id().as_bytes())?;
307            }
308            Self::Named(address_id) => {
309                encoder.write_discriminator(1)?;
310                encoder.write_slice(&address_id.0.to_le_bytes())?;
311            }
312        }
313        Ok(())
314    }
315}
316
317impl<D: Decoder<ManifestCustomValueKind>> Decode<ManifestCustomValueKind, D>
318    for ManifestPackageAddress
319{
320    fn decode_body_with_value_kind(
321        decoder: &mut D,
322        value_kind: ValueKind<ManifestCustomValueKind>,
323    ) -> Result<Self, DecodeError> {
324        decoder.check_preloaded_value_kind(value_kind, Self::value_kind())?;
325        match decoder.read_discriminator()? {
326            MANIFEST_ADDRESS_DISCRIMINATOR_STATIC => {
327                let slice = decoder.read_slice(NodeId::LENGTH)?;
328                Ok(Self::Static(
329                    PackageAddress::try_from(slice).map_err(|_| DecodeError::InvalidCustomValue)?,
330                ))
331            }
332            MANIFEST_ADDRESS_DISCRIMINATOR_NAMED => {
333                let slice = decoder.read_slice(4)?;
334                let id = u32::from_le_bytes(slice.try_into().unwrap());
335                Ok(Self::Named(ManifestNamedAddress(id)))
336            }
337            _ => Err(DecodeError::InvalidCustomValue),
338        }
339    }
340}
341
342impl ManifestPackageAddress {
343    /// This is to support either `Address("static_address")` or `NamedAddress("abc")` in manifest instruction,
344    /// instead of `Enum<0u8>(Address("static_address"))`.
345    pub fn to_instruction_argument(&self) -> ManifestValue {
346        match self {
347            Self::Static(address) => ManifestValue::Custom {
348                value: ManifestCustomValue::Address(ManifestAddress::Static(
349                    address.into_node_id(),
350                )),
351            },
352            Self::Named(id) => ManifestValue::Custom {
353                value: ManifestCustomValue::Address(ManifestAddress::Named(*id)),
354            },
355        }
356    }
357
358    pub fn is_static_global_package_of(&self, package_address: &PackageAddress) -> bool {
359        match self {
360            Self::Static(address) => address.as_node_id().eq(package_address.as_node_id()),
361            Self::Named(_) => false,
362        }
363    }
364}
365
366impl From<PackageAddress> for ManifestPackageAddress {
367    fn from(value: PackageAddress) -> Self {
368        Self::Static(value)
369    }
370}
371
372impl From<ManifestNamedAddress> for ManifestPackageAddress {
373    fn from(value: ManifestNamedAddress) -> Self {
374        Self::Named(value)
375    }
376}
377
378impl TryFrom<GlobalAddress> for ManifestPackageAddress {
379    type Error = ParsePackageAddressError;
380
381    fn try_from(value: GlobalAddress) -> Result<Self, Self::Error> {
382        Ok(Self::Static(PackageAddress::try_from(
383            value.into_node_id(),
384        )?))
385    }
386}
387
388impl TryFrom<ManifestAddress> for ManifestPackageAddress {
389    type Error = ParsePackageAddressError;
390
391    fn try_from(value: ManifestAddress) -> Result<Self, Self::Error> {
392        Ok(match value {
393            ManifestAddress::Static(value) => Self::Static(value.try_into()?),
394            ManifestAddress::Named(value) => Self::Named(value),
395        })
396    }
397}
398
399/// This trait resolves a static resource address for manifest instructions which
400/// (as of Cuttlefish) only support a fixed address.
401///
402/// We hope to remove this restriction and enable these instructions to take a
403/// dynamic package address at a protocol update soon.
404pub trait ResolvableStaticManifestPackageAddress: Sized {
405    fn resolve_static(self) -> PackageAddress;
406}
407
408impl<A, E> ResolvableStaticManifestPackageAddress for A
409where
410    A: TryInto<ManifestPackageAddress, Error = E>,
411    E: Debug,
412{
413    fn resolve_static(self) -> PackageAddress {
414        let address = self
415            .try_into()
416            .expect("Address was not a valid ManifestPackageAddress");
417        match address {
418            ManifestPackageAddress::Static(address) => address,
419            ManifestPackageAddress::Named(_) => {
420                panic!("This address needs to be a static/fixed address")
421            }
422        }
423    }
424}
425
426// Alias for backwards-compatibility
427pub type DynamicComponentAddress = ManifestComponentAddress;
428
429#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
430pub enum ManifestComponentAddress {
431    Static(ComponentAddress),
432    Named(ManifestNamedAddress),
433}
434
435impl IntoManifestAddress for ComponentAddress {
436    type ManifestAddress = ManifestComponentAddress;
437
438    fn into_manifest_address(self) -> Self::ManifestAddress {
439        Self::ManifestAddress::Static(self)
440    }
441}
442
443scrypto_describe_for_manifest_type!(
444    ManifestComponentAddress,
445    COMPONENT_ADDRESS_TYPE,
446    component_address_type_data,
447);
448
449labelled_resolvable_address!(ManifestComponentAddress);
450
451impl Categorize<ManifestCustomValueKind> for ManifestComponentAddress {
452    #[inline]
453    fn value_kind() -> ValueKind<ManifestCustomValueKind> {
454        ValueKind::Custom(ManifestCustomValueKind::Address)
455    }
456}
457
458impl<E: Encoder<ManifestCustomValueKind>> Encode<ManifestCustomValueKind, E>
459    for ManifestComponentAddress
460{
461    #[inline]
462    fn encode_value_kind(&self, encoder: &mut E) -> Result<(), EncodeError> {
463        encoder.write_value_kind(Self::value_kind())
464    }
465
466    #[inline]
467    fn encode_body(&self, encoder: &mut E) -> Result<(), EncodeError> {
468        match self {
469            Self::Static(address) => {
470                encoder.write_discriminator(MANIFEST_ADDRESS_DISCRIMINATOR_STATIC)?;
471                encoder.write_slice(address.as_node_id().as_bytes())?;
472            }
473            Self::Named(address_id) => {
474                encoder.write_discriminator(MANIFEST_ADDRESS_DISCRIMINATOR_NAMED)?;
475                encoder.write_slice(&address_id.0.to_le_bytes())?;
476            }
477        }
478        Ok(())
479    }
480}
481
482impl<D: Decoder<ManifestCustomValueKind>> Decode<ManifestCustomValueKind, D>
483    for ManifestComponentAddress
484{
485    fn decode_body_with_value_kind(
486        decoder: &mut D,
487        value_kind: ValueKind<ManifestCustomValueKind>,
488    ) -> Result<Self, DecodeError> {
489        decoder.check_preloaded_value_kind(value_kind, Self::value_kind())?;
490        match decoder.read_discriminator()? {
491            MANIFEST_ADDRESS_DISCRIMINATOR_STATIC => {
492                let slice = decoder.read_slice(NodeId::LENGTH)?;
493                Ok(Self::Static(
494                    ComponentAddress::try_from(slice)
495                        .map_err(|_| DecodeError::InvalidCustomValue)?,
496                ))
497            }
498            MANIFEST_ADDRESS_DISCRIMINATOR_NAMED => {
499                let slice = decoder.read_slice(4)?;
500                let id = u32::from_le_bytes(slice.try_into().unwrap());
501                Ok(Self::Named(ManifestNamedAddress(id)))
502            }
503            _ => Err(DecodeError::InvalidCustomValue),
504        }
505    }
506}
507
508impl From<ComponentAddress> for ManifestComponentAddress {
509    fn from(value: ComponentAddress) -> Self {
510        Self::Static(value)
511    }
512}
513
514impl From<ManifestNamedAddress> for ManifestComponentAddress {
515    fn from(value: ManifestNamedAddress) -> Self {
516        Self::Named(value)
517    }
518}
519
520impl TryFrom<GlobalAddress> for ManifestComponentAddress {
521    type Error = ParseComponentAddressError;
522
523    fn try_from(value: GlobalAddress) -> Result<Self, Self::Error> {
524        Ok(Self::Static(ComponentAddress::try_from(
525            value.into_node_id(),
526        )?))
527    }
528}
529
530impl TryFrom<ManifestAddress> for ManifestComponentAddress {
531    type Error = ParseComponentAddressError;
532
533    fn try_from(value: ManifestAddress) -> Result<Self, Self::Error> {
534        Ok(match value {
535            ManifestAddress::Static(value) => Self::Static(value.try_into()?),
536            ManifestAddress::Named(value) => Self::Named(value),
537        })
538    }
539}
540
541// Alias for backwards compatibility
542pub type DynamicResourceAddress = ManifestResourceAddress;
543
544#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
545pub enum ManifestResourceAddress {
546    Static(ResourceAddress),
547    Named(ManifestNamedAddress),
548}
549
550impl IntoManifestAddress for ResourceAddress {
551    type ManifestAddress = ManifestResourceAddress;
552
553    fn into_manifest_address(self) -> Self::ManifestAddress {
554        Self::ManifestAddress::Static(self)
555    }
556}
557
558scrypto_describe_for_manifest_type!(
559    ManifestResourceAddress,
560    RESOURCE_ADDRESS_TYPE,
561    resource_address_type_data,
562);
563
564labelled_resolvable_address!(ManifestResourceAddress);
565
566impl Categorize<ManifestCustomValueKind> for ManifestResourceAddress {
567    #[inline]
568    fn value_kind() -> ValueKind<ManifestCustomValueKind> {
569        ValueKind::Custom(ManifestCustomValueKind::Address)
570    }
571}
572
573impl<E: Encoder<ManifestCustomValueKind>> Encode<ManifestCustomValueKind, E>
574    for ManifestResourceAddress
575{
576    #[inline]
577    fn encode_value_kind(&self, encoder: &mut E) -> Result<(), EncodeError> {
578        encoder.write_value_kind(Self::value_kind())
579    }
580
581    #[inline]
582    fn encode_body(&self, encoder: &mut E) -> Result<(), EncodeError> {
583        match self {
584            Self::Static(address) => {
585                encoder.write_discriminator(MANIFEST_ADDRESS_DISCRIMINATOR_STATIC)?;
586                encoder.write_slice(address.as_node_id().as_bytes())?;
587            }
588            Self::Named(address_id) => {
589                encoder.write_discriminator(MANIFEST_ADDRESS_DISCRIMINATOR_NAMED)?;
590                encoder.write_slice(&address_id.0.to_le_bytes())?;
591            }
592        }
593        Ok(())
594    }
595}
596
597impl<D: Decoder<ManifestCustomValueKind>> Decode<ManifestCustomValueKind, D>
598    for ManifestResourceAddress
599{
600    fn decode_body_with_value_kind(
601        decoder: &mut D,
602        value_kind: ValueKind<ManifestCustomValueKind>,
603    ) -> Result<Self, DecodeError> {
604        decoder.check_preloaded_value_kind(value_kind, Self::value_kind())?;
605        match decoder.read_discriminator()? {
606            MANIFEST_ADDRESS_DISCRIMINATOR_STATIC => {
607                let slice = decoder.read_slice(NodeId::LENGTH)?;
608                Ok(Self::Static(
609                    ResourceAddress::try_from(slice)
610                        .map_err(|_| DecodeError::InvalidCustomValue)?,
611                ))
612            }
613            MANIFEST_ADDRESS_DISCRIMINATOR_NAMED => {
614                let slice = decoder.read_slice(4)?;
615                let id = u32::from_le_bytes(slice.try_into().unwrap());
616                Ok(Self::Named(ManifestNamedAddress(id)))
617            }
618            _ => Err(DecodeError::InvalidCustomValue),
619        }
620    }
621}
622
623impl From<ResourceAddress> for ManifestResourceAddress {
624    fn from(value: ResourceAddress) -> Self {
625        Self::Static(value)
626    }
627}
628
629impl From<ManifestNamedAddress> for ManifestResourceAddress {
630    fn from(value: ManifestNamedAddress) -> Self {
631        Self::Named(value)
632    }
633}
634
635impl TryFrom<GlobalAddress> for ManifestResourceAddress {
636    type Error = ParseResourceAddressError;
637
638    fn try_from(value: GlobalAddress) -> Result<Self, Self::Error> {
639        Ok(Self::Static(ResourceAddress::try_from(
640            value.into_node_id(),
641        )?))
642    }
643}
644
645impl TryFrom<ManifestAddress> for ManifestResourceAddress {
646    type Error = ParseResourceAddressError;
647
648    fn try_from(value: ManifestAddress) -> Result<Self, Self::Error> {
649        Ok(match value {
650            ManifestAddress::Static(value) => Self::Static(value.try_into()?),
651            ManifestAddress::Named(value) => Self::Named(value),
652        })
653    }
654}
655
656/// This trait resolves a static resource address for manifest instructions which
657/// (as of Cuttlefish) only support a fixed address.
658///
659/// We hope to remove this restriction and enable these instructions to take a
660/// dynamic package address at a protocol update soon.
661pub trait ResolvableStaticManifestResourceAddress: Sized {
662    fn resolve_static(self) -> ResourceAddress;
663}
664
665impl<A, E> ResolvableStaticManifestResourceAddress for A
666where
667    A: TryInto<ManifestResourceAddress, Error = E>,
668    E: Debug,
669{
670    fn resolve_static(self) -> ResourceAddress {
671        let address = self
672            .try_into()
673            .expect("Address was not a valid ManifestResourceAddress");
674        match address {
675            ManifestResourceAddress::Static(address) => address,
676            ManifestResourceAddress::Named(_) => {
677                panic!("This address needs to be a static/fixed address")
678            }
679        }
680    }
681}