radix_transactions/manifest/
generator.rs

1use core::iter::*;
2
3use super::ast::Instruction;
4use super::ast::InstructionWithSpan;
5use super::ast::ValueKindWithSpan;
6use super::blob_provider::*;
7use crate::data::*;
8use crate::errors::*;
9use crate::internal_prelude::*;
10use crate::manifest::ast;
11use crate::manifest::compiler::CompileErrorDiagnosticsStyle;
12use crate::manifest::diagnostic_snippets::create_snippet;
13use crate::manifest::token::Span;
14use crate::model::*;
15use crate::validation::*;
16use radix_common::address::AddressBech32Decoder;
17use radix_common::constants::*;
18use radix_common::crypto::Hash;
19use radix_common::data::manifest::model::*;
20use radix_common::data::manifest::*;
21use radix_common::data::scrypto::model::*;
22use radix_common::math::{Decimal, PreciseDecimal};
23use radix_common::prelude::CONSENSUS_MANAGER;
24use radix_common::types::NodeId;
25use radix_common::types::NonFungibleGlobalId;
26use radix_common::types::PackageAddress;
27use radix_engine_interface::blueprints::access_controller::*;
28use radix_engine_interface::blueprints::account::*;
29use radix_engine_interface::blueprints::consensus_manager::*;
30use radix_engine_interface::blueprints::identity::*;
31use radix_engine_interface::blueprints::package::*;
32use radix_engine_interface::blueprints::resource::*;
33use radix_engine_interface::object_modules::metadata::*;
34use radix_engine_interface::object_modules::role_assignment::*;
35use radix_engine_interface::object_modules::royalty::*;
36use radix_engine_interface::types::*;
37use sbor::prelude::*;
38
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub enum GeneratorErrorKind {
41    InvalidAstType {
42        expected_value_kind: ast::ValueKind,
43        actual: ast::ValueKind,
44    },
45    InvalidAstValue {
46        expected_value_kinds: Vec<ast::ValueKind>,
47        actual: ast::Value,
48    },
49    UnexpectedValueKind {
50        expected_value_kind: ast::ValueKind,
51        actual_value: ast::Value,
52    },
53    InvalidPackageAddress(String),
54    InvalidResourceAddress(String),
55    InvalidDecimal {
56        actual: String,
57        err: String,
58    },
59    InvalidPreciseDecimal {
60        actual: String,
61        err: String,
62    },
63    InvalidNonFungibleLocalId(String),
64    InvalidNonFungibleGlobalId,
65    InvalidExpression(String),
66    InvalidBlobHash {
67        actual: String,
68        err: String,
69    },
70    BlobNotFound(String),
71    InvalidBytesHex(String),
72    NameResolverError(NameResolverError),
73    IdValidationError {
74        err: ManifestIdValidationError,
75        name: Option<String>,
76    },
77    InvalidGlobalAddress(String),
78    InvalidInternalAddress(String),
79    InvalidSubTransactionId(String),
80    InstructionNotSupportedInManifestVersion,
81    ManifestBuildError(ManifestBuildError),
82    HeaderInstructionMustComeFirst,
83    IntentCannotBeUsedInValue,
84    IntentCannotBeUsedAsValueKind,
85    NamedIntentCannotBeUsedInValue,
86    NamedIntentCannotBeUsedAsValueKind,
87    ArgumentCouldNotBeReadAsExpectedType {
88        type_name: String,
89        error_message: String,
90    },
91}
92
93#[derive(Debug, Clone, PartialEq, Eq)]
94pub struct GeneratorError {
95    pub error_kind: GeneratorErrorKind,
96    pub span: Span,
97}
98
99#[derive(Debug, Clone, PartialEq, Eq)]
100pub enum NameResolverError {
101    UndefinedBucket(String),
102    UndefinedProof(String),
103    UndefinedAddressReservation(String),
104    UndefinedNamedAddress(String),
105    UndefinedIntent(String),
106    NamedAlreadyDefined(String),
107}
108
109#[derive(Default)]
110pub struct NameResolver {
111    named_buckets: IndexMap<String, ManifestBucket>,
112    named_proofs: IndexMap<String, ManifestProof>,
113    named_address_reservations: IndexMap<String, ManifestAddressReservation>,
114    named_addresses: IndexMap<String, ManifestNamedAddress>,
115    named_intents: IndexMap<String, ManifestNamedIntent>,
116}
117
118impl NameResolver {
119    pub fn new() -> Self {
120        Self::default()
121    }
122
123    pub fn insert_bucket(
124        &mut self,
125        name: String,
126        bucket_id: ManifestBucket,
127    ) -> Result<(), NameResolverError> {
128        if self.named_buckets.contains_key(&name) {
129            Err(NameResolverError::NamedAlreadyDefined(name))
130        } else {
131            self.named_buckets.insert(name, bucket_id);
132            Ok(())
133        }
134    }
135
136    pub fn insert_proof(
137        &mut self,
138        name: String,
139        proof_id: ManifestProof,
140    ) -> Result<(), NameResolverError> {
141        if self.named_proofs.contains_key(&name) {
142            Err(NameResolverError::NamedAlreadyDefined(name))
143        } else {
144            self.named_proofs.insert(name, proof_id);
145            Ok(())
146        }
147    }
148
149    pub fn insert_address_reservation(
150        &mut self,
151        name: String,
152        address_reservation_id: ManifestAddressReservation,
153    ) -> Result<(), NameResolverError> {
154        if self.named_address_reservations.contains_key(&name) {
155            Err(NameResolverError::NamedAlreadyDefined(name))
156        } else {
157            self.named_address_reservations
158                .insert(name, address_reservation_id);
159            Ok(())
160        }
161    }
162
163    pub fn insert_named_address(
164        &mut self,
165        name: String,
166        address_id: ManifestNamedAddress,
167    ) -> Result<(), NameResolverError> {
168        if self.named_addresses.contains_key(&name) {
169            Err(NameResolverError::NamedAlreadyDefined(name))
170        } else {
171            self.named_addresses.insert(name, address_id);
172            Ok(())
173        }
174    }
175
176    pub fn insert_intent(
177        &mut self,
178        name: String,
179        intent_id: ManifestNamedIntent,
180    ) -> Result<(), NameResolverError> {
181        if self.named_intents.contains_key(&name) {
182            Err(NameResolverError::NamedAlreadyDefined(name))
183        } else {
184            self.named_intents.insert(name, intent_id);
185            Ok(())
186        }
187    }
188
189    pub fn resolve_bucket(&mut self, name: &str) -> Result<ManifestBucket, NameResolverError> {
190        match self.named_buckets.get(name).cloned() {
191            Some(bucket_id) => Ok(bucket_id),
192            None => Err(NameResolverError::UndefinedBucket(name.into())),
193        }
194    }
195
196    pub fn resolve_proof(&mut self, name: &str) -> Result<ManifestProof, NameResolverError> {
197        match self.named_proofs.get(name).cloned() {
198            Some(proof_id) => Ok(proof_id),
199            None => Err(NameResolverError::UndefinedProof(name.into())),
200        }
201    }
202
203    pub fn resolve_address_reservation(
204        &mut self,
205        name: &str,
206    ) -> Result<ManifestAddressReservation, NameResolverError> {
207        match self.named_address_reservations.get(name).cloned() {
208            Some(address_reservation_id) => Ok(address_reservation_id),
209            None => Err(NameResolverError::UndefinedAddressReservation(name.into())),
210        }
211    }
212
213    pub fn resolve_named_address(
214        &mut self,
215        name: &str,
216    ) -> Result<ManifestNamedAddress, NameResolverError> {
217        match self.named_addresses.get(name).cloned() {
218            Some(address_id) => Ok(address_id),
219            None => Err(NameResolverError::UndefinedNamedAddress(name.into())),
220        }
221    }
222
223    pub fn resolve_named_intent(
224        &mut self,
225        name: &str,
226    ) -> Result<ManifestNamedIntent, NameResolverError> {
227        match self.named_intents.get(name).cloned() {
228            Some(intent_id) => Ok(intent_id),
229            None => Err(NameResolverError::UndefinedIntent(name.into())),
230        }
231    }
232
233    pub fn resolve_bucket_name(&self, bucket: ManifestBucket) -> Option<String> {
234        for (name, id) in self.named_buckets.iter() {
235            if id.eq(&bucket) {
236                return Some(name.to_string());
237            }
238        }
239        return None;
240    }
241
242    pub fn resove_proof_name(&self, proof: ManifestProof) -> Option<String> {
243        for (name, id) in self.named_proofs.iter() {
244            if id.eq(&proof) {
245                return Some(name.to_string());
246            }
247        }
248        return None;
249    }
250
251    pub fn resolve_address_reservation_name(
252        &self,
253        reservation: ManifestAddressReservation,
254    ) -> Option<String> {
255        for (name, id) in self.named_address_reservations.iter() {
256            if id.eq(&reservation) {
257                return Some(name.to_string());
258            }
259        }
260        return None;
261    }
262
263    pub fn resolve_named_address_name(&self, address: ManifestNamedAddress) -> Option<String> {
264        for (name, id) in self.named_addresses.iter() {
265            if id.eq(&address) {
266                return Some(name.to_string());
267            }
268        }
269        return None;
270    }
271
272    pub fn resolve_intent_name(&self, address: ManifestNamedIntent) -> Option<String> {
273        for (name, id) in self.named_intents.iter() {
274            if id.eq(&address) {
275                return Some(name.to_string());
276            }
277        }
278        return None;
279    }
280
281    pub fn into_known_names(self) -> KnownManifestObjectNames {
282        KnownManifestObjectNames {
283            bucket_names: self
284                .named_buckets
285                .into_iter()
286                .map(|(name, value)| (value, name))
287                .collect(),
288            proof_names: self
289                .named_proofs
290                .into_iter()
291                .map(|(name, value)| (value, name))
292                .collect(),
293            address_reservation_names: self
294                .named_address_reservations
295                .into_iter()
296                .map(|(name, value)| (value, name))
297                .collect(),
298            address_names: self
299                .named_addresses
300                .into_iter()
301                .map(|(name, value)| (value, name))
302                .collect(),
303            intent_names: self
304                .named_intents
305                .into_iter()
306                .map(|(name, value)| (value, name))
307                .collect(),
308        }
309    }
310}
311
312pub fn generate_manifest<B, M: BuildableManifest>(
313    instructions: &[ast::InstructionWithSpan],
314    address_bech32_decoder: &AddressBech32Decoder,
315    transaction_bech32_decoder: &TransactionHashBech32Decoder,
316    blobs: B,
317) -> Result<M, GeneratorError>
318where
319    B: IsBlobProvider,
320{
321    let mut id_validator = BasicManifestValidator::new();
322    let mut name_resolver = NameResolver::new();
323
324    let mut manifest = M::default();
325
326    let mut instructions_iter = instructions.iter().peekable();
327
328    generate_pseudo_instructions(
329        &mut manifest,
330        &mut instructions_iter,
331        &mut id_validator,
332        &mut name_resolver,
333        address_bech32_decoder,
334        transaction_bech32_decoder,
335    )?;
336
337    for instruction in instructions_iter {
338        let any_instruction = generate_instruction(
339            instruction,
340            &mut id_validator,
341            &mut name_resolver,
342            address_bech32_decoder,
343            &blobs,
344        )?;
345        let valid_instruction = any_instruction.try_into().map_err(|_| GeneratorError {
346            span: instruction.span,
347            error_kind: GeneratorErrorKind::InstructionNotSupportedInManifestVersion,
348        })?;
349        manifest.add_instruction(valid_instruction);
350    }
351    for (hash, blob_content) in blobs.blobs() {
352        manifest.add_blob(hash, blob_content);
353    }
354    manifest.set_names(name_resolver.into_known_names());
355
356    Ok(manifest)
357}
358
359fn generate_pseudo_instructions(
360    manifest: &mut impl BuildableManifest,
361    instructions_iter: &mut Peekable<core::slice::Iter<ast::InstructionWithSpan>>,
362    id_validator: &mut BasicManifestValidator,
363    name_resolver: &mut NameResolver,
364    address_bech32_decoder: &AddressBech32Decoder,
365    transaction_bech32_decoder: &TransactionHashBech32Decoder,
366) -> Result<(), GeneratorError> {
367    // First handle the USE_PREALLOCATED_ADDRESS pseudo-instructions
368    loop {
369        let Some(InstructionWithSpan {
370            instruction: Instruction::UsePreallocatedAddress { .. },
371            ..
372        }) = instructions_iter.peek()
373        else {
374            break;
375        };
376        let Some(InstructionWithSpan {
377            instruction:
378                Instruction::UsePreallocatedAddress {
379                    package_address,
380                    blueprint_name,
381                    address_reservation,
382                    preallocated_address,
383                },
384            span,
385        }) = instructions_iter.next()
386        else {
387            unreachable!("Just peeked and verified");
388        };
389        declare_address_reservation(
390            address_reservation,
391            name_resolver,
392            id_validator.new_address_reservation(),
393        )?;
394        manifest
395            .add_preallocated_address(PreAllocatedAddress {
396                blueprint_id: BlueprintId {
397                    package_address: generate_package_address(
398                        package_address,
399                        address_bech32_decoder,
400                    )?,
401                    blueprint_name: generate_string(blueprint_name)?,
402                },
403                address: generate_global_address(preallocated_address, address_bech32_decoder)?,
404            })
405            .map_err(|err| GeneratorError {
406                span: *span,
407                error_kind: GeneratorErrorKind::ManifestBuildError(err),
408            })?;
409    }
410
411    // Next, handle the USE_CHILD pseudo-instructions
412    loop {
413        let Some(InstructionWithSpan {
414            instruction: Instruction::UseChild { .. },
415            ..
416        }) = instructions_iter.peek()
417        else {
418            break;
419        };
420        let Some(InstructionWithSpan {
421            instruction:
422                Instruction::UseChild {
423                    named_intent,
424                    subintent_hash,
425                },
426            span,
427        }) = instructions_iter.next()
428        else {
429            unreachable!("Just peeked and verified");
430        };
431        declare_named_intent(named_intent, name_resolver, id_validator.new_intent())?;
432        manifest
433            .add_child_subintent(generate_subintent_hash(
434                transaction_bech32_decoder,
435                subintent_hash,
436            )?)
437            .map_err(|err| GeneratorError {
438                span: *span,
439                error_kind: GeneratorErrorKind::ManifestBuildError(err),
440            })?;
441    }
442
443    Ok(())
444}
445
446macro_rules! get_span {
447    ($outer:expr, $inner_vec:expr) => {
448        if $inner_vec.is_empty() {
449            $outer.span
450        } else {
451            let start = $inner_vec.get(0).unwrap().span.start;
452            let end = $inner_vec.get($inner_vec.len() - 1).unwrap().span.end;
453            Span { start, end }
454        }
455    };
456}
457
458fn generate_id_validation_error(
459    resolver: &NameResolver,
460    err: ManifestIdValidationError,
461    span: Span,
462) -> GeneratorError {
463    let name = match err {
464        ManifestIdValidationError::BucketLocked(bucket) => resolver.resolve_bucket_name(bucket),
465        ManifestIdValidationError::BucketNotFound(bucket) => resolver.resolve_bucket_name(bucket),
466        ManifestIdValidationError::ProofNotFound(proof) => resolver.resove_proof_name(proof),
467        ManifestIdValidationError::AddressNotFound(address) => {
468            resolver.resolve_named_address_name(address)
469        }
470        ManifestIdValidationError::AddressReservationNotFound(reservation) => {
471            resolver.resolve_address_reservation_name(reservation)
472        }
473        ManifestIdValidationError::IntentNotFound(intent) => resolver.resolve_intent_name(intent),
474    };
475
476    GeneratorError {
477        error_kind: GeneratorErrorKind::IdValidationError { err, name },
478        span,
479    }
480}
481
482pub fn generate_instruction<B>(
483    instruction: &ast::InstructionWithSpan,
484    id_validator: &mut BasicManifestValidator,
485    resolver: &mut NameResolver,
486    address_bech32_decoder: &AddressBech32Decoder,
487    blobs: &B,
488) -> Result<AnyInstruction, GeneratorError>
489where
490    B: IsBlobProvider,
491{
492    Ok(match &instruction.instruction {
493        // ==============
494        // Pseudo-instructions
495        // ==============
496        ast::Instruction::UsePreallocatedAddress { .. } | ast::Instruction::UseChild { .. } => {
497            return Err(GeneratorError {
498                span: instruction.span,
499                error_kind: GeneratorErrorKind::HeaderInstructionMustComeFirst,
500            })
501        }
502        // ==============
503        // Standard instructions (in canonical order)
504        // ==============
505
506        // Bucket Lifecycle
507        ast::Instruction::TakeFromWorktop {
508            resource_address,
509            amount,
510            new_bucket,
511        } => {
512            let bucket_id = id_validator.new_bucket();
513            declare_bucket(new_bucket, resolver, bucket_id)?;
514
515            TakeFromWorktop {
516                amount: generate_decimal(amount)?,
517                resource_address: generate_resource_address(
518                    resource_address,
519                    address_bech32_decoder,
520                )?,
521            }
522            .into()
523        }
524        ast::Instruction::TakeNonFungiblesFromWorktop {
525            resource_address,
526            ids,
527            new_bucket,
528        } => {
529            let bucket_id = id_validator.new_bucket();
530            declare_bucket(new_bucket, resolver, bucket_id)?;
531
532            TakeNonFungiblesFromWorktop {
533                ids: generate_non_fungible_local_ids(ids)?,
534                resource_address: generate_resource_address(
535                    resource_address,
536                    address_bech32_decoder,
537                )?,
538            }
539            .into()
540        }
541        ast::Instruction::TakeAllFromWorktop {
542            resource_address,
543            new_bucket,
544        } => {
545            let bucket_id = id_validator.new_bucket();
546            declare_bucket(new_bucket, resolver, bucket_id)?;
547
548            TakeAllFromWorktop {
549                resource_address: generate_resource_address(
550                    resource_address,
551                    address_bech32_decoder,
552                )?,
553            }
554            .into()
555        }
556        ast::Instruction::ReturnToWorktop { bucket } => {
557            let (bucket_id, span) = generate_bucket(bucket, resolver)?;
558            id_validator
559                .drop_bucket(&bucket_id)
560                .map_err(|err| generate_id_validation_error(resolver, err, span))?;
561            ReturnToWorktop { bucket_id }.into()
562        }
563        ast::Instruction::BurnResource { bucket } => {
564            let (bucket_id, span) = generate_bucket(bucket, resolver)?;
565            id_validator
566                .drop_bucket(&bucket_id)
567                .map_err(|err| generate_id_validation_error(resolver, err, span))?;
568            BurnResource { bucket_id }.into()
569        }
570
571        // Resource Assertions
572        ast::Instruction::AssertWorktopContains {
573            resource_address,
574            amount,
575        } => AssertWorktopContains {
576            amount: generate_decimal(amount)?,
577            resource_address: generate_resource_address(resource_address, address_bech32_decoder)?,
578        }
579        .into(),
580        ast::Instruction::AssertWorktopContainsNonFungibles {
581            resource_address,
582            ids,
583        } => AssertWorktopContainsNonFungibles {
584            resource_address: generate_resource_address(resource_address, address_bech32_decoder)?,
585            ids: generate_non_fungible_local_ids(ids)?,
586        }
587        .into(),
588        ast::Instruction::AssertWorktopContainsAny { resource_address } => {
589            AssertWorktopContainsAny {
590                resource_address: generate_resource_address(
591                    resource_address,
592                    address_bech32_decoder,
593                )?,
594            }
595            .into()
596        }
597        ast::Instruction::AssertWorktopIsEmpty {} => AssertWorktopResourcesOnly {
598            constraints: Default::default(),
599        }
600        .into(),
601        ast::Instruction::AssertWorktopResourcesOnly { constraints } => {
602            AssertWorktopResourcesOnly {
603                constraints: generate_typed_value(
604                    constraints,
605                    resolver,
606                    address_bech32_decoder,
607                    blobs,
608                )?,
609            }
610            .into()
611        }
612        ast::Instruction::AssertWorktopResourcesInclude { constraints } => {
613            AssertWorktopResourcesInclude {
614                constraints: generate_typed_value(
615                    constraints,
616                    resolver,
617                    address_bech32_decoder,
618                    blobs,
619                )?,
620            }
621            .into()
622        }
623        ast::Instruction::AssertNextCallReturnsOnly { constraints } => AssertNextCallReturnsOnly {
624            constraints: generate_typed_value(
625                constraints,
626                resolver,
627                address_bech32_decoder,
628                blobs,
629            )?,
630        }
631        .into(),
632        ast::Instruction::AssertNextCallReturnsInclude { constraints } => {
633            AssertNextCallReturnsInclude {
634                constraints: generate_typed_value(
635                    constraints,
636                    resolver,
637                    address_bech32_decoder,
638                    blobs,
639                )?,
640            }
641            .into()
642        }
643        ast::Instruction::AssertBucketContents { bucket, constraint } => {
644            let (bucket_id, span) = generate_bucket(bucket, resolver)?;
645            id_validator
646                .check_bucket(&bucket_id)
647                .map_err(|err| generate_id_validation_error(resolver, err, span))?;
648            AssertBucketContents {
649                bucket_id,
650                constraint: generate_typed_value(
651                    constraint,
652                    resolver,
653                    address_bech32_decoder,
654                    blobs,
655                )?,
656            }
657            .into()
658        }
659
660        // Proof Lifecycle
661        ast::Instruction::CreateProofFromBucketOfAmount {
662            bucket,
663            amount,
664            new_proof,
665        } => {
666            let (bucket_id, span) = generate_bucket(bucket, resolver)?;
667            let amount = generate_decimal(amount)?;
668            let proof_id = id_validator
669                .new_proof(ProofKind::BucketProof(bucket_id.clone()))
670                .map_err(|err| generate_id_validation_error(resolver, err, span))?;
671            declare_proof(new_proof, resolver, proof_id)?;
672
673            CreateProofFromBucketOfAmount { bucket_id, amount }.into()
674        }
675        ast::Instruction::CreateProofFromBucketOfNonFungibles {
676            bucket,
677            ids,
678            new_proof,
679        } => {
680            let (bucket_id, span) = generate_bucket(bucket, resolver)?;
681            let ids = generate_non_fungible_local_ids(ids)?;
682            let proof_id = id_validator
683                .new_proof(ProofKind::BucketProof(bucket_id.clone()))
684                .map_err(|err| generate_id_validation_error(resolver, err, span))?;
685            declare_proof(new_proof, resolver, proof_id)?;
686
687            CreateProofFromBucketOfNonFungibles { bucket_id, ids }.into()
688        }
689        ast::Instruction::CreateProofFromBucketOfAll { bucket, new_proof } => {
690            let (bucket_id, span) = generate_bucket(bucket, resolver)?;
691            let proof_id = id_validator
692                .new_proof(ProofKind::BucketProof(bucket_id.clone()))
693                .map_err(|err| generate_id_validation_error(resolver, err, span))?;
694            declare_proof(new_proof, resolver, proof_id)?;
695
696            CreateProofFromBucketOfAll { bucket_id }.into()
697        }
698        ast::Instruction::CreateProofFromAuthZoneOfAmount {
699            resource_address,
700            amount,
701            new_proof,
702        } => {
703            let resource_address =
704                generate_resource_address(resource_address, address_bech32_decoder)?;
705            let amount = generate_decimal(amount)?;
706            let proof_id = id_validator
707                .new_proof(ProofKind::AuthZoneProof)
708                .map_err(|err| generate_id_validation_error(resolver, err, instruction.span))?;
709            declare_proof(new_proof, resolver, proof_id)?;
710
711            CreateProofFromAuthZoneOfAmount {
712                amount,
713                resource_address,
714            }
715            .into()
716        }
717        ast::Instruction::CreateProofFromAuthZoneOfNonFungibles {
718            resource_address,
719            ids,
720            new_proof,
721        } => {
722            let resource_address =
723                generate_resource_address(resource_address, address_bech32_decoder)?;
724            let ids = generate_non_fungible_local_ids(ids)?;
725            let proof_id = id_validator
726                .new_proof(ProofKind::AuthZoneProof)
727                .map_err(|err| generate_id_validation_error(resolver, err, instruction.span))?;
728            declare_proof(new_proof, resolver, proof_id)?;
729
730            CreateProofFromAuthZoneOfNonFungibles {
731                ids,
732                resource_address,
733            }
734            .into()
735        }
736        ast::Instruction::CreateProofFromAuthZoneOfAll {
737            resource_address,
738            new_proof,
739        } => {
740            let resource_address =
741                generate_resource_address(resource_address, address_bech32_decoder)?;
742            let proof_id = id_validator
743                .new_proof(ProofKind::AuthZoneProof)
744                .map_err(|err| generate_id_validation_error(resolver, err, instruction.span))?;
745            declare_proof(new_proof, resolver, proof_id)?;
746
747            CreateProofFromAuthZoneOfAll { resource_address }.into()
748        }
749        ast::Instruction::CloneProof { proof, new_proof } => {
750            let (proof_id, span) = generate_proof(proof, resolver)?;
751            let proof_id2 = id_validator
752                .clone_proof(&proof_id)
753                .map_err(|err| generate_id_validation_error(resolver, err, span))?;
754            declare_proof(new_proof, resolver, proof_id2)?;
755
756            CloneProof { proof_id }.into()
757        }
758        ast::Instruction::DropProof { proof } => {
759            let (proof_id, span) = generate_proof(proof, resolver)?;
760            id_validator
761                .drop_proof(&proof_id)
762                .map_err(|err| generate_id_validation_error(resolver, err, span))?;
763            DropProof { proof_id }.into()
764        }
765        ast::Instruction::PushToAuthZone { proof } => {
766            let (proof_id, span) = generate_proof(proof, resolver)?;
767            id_validator
768                .drop_proof(&proof_id)
769                .map_err(|err| generate_id_validation_error(resolver, err, span))?;
770            PushToAuthZone { proof_id }.into()
771        }
772        ast::Instruction::PopFromAuthZone { new_proof } => {
773            let proof_id = id_validator
774                .new_proof(ProofKind::AuthZoneProof)
775                .map_err(|err| generate_id_validation_error(resolver, err, instruction.span))?;
776            declare_proof(new_proof, resolver, proof_id)?;
777
778            PopFromAuthZone.into()
779        }
780        ast::Instruction::DropAuthZoneProofs => DropAuthZoneProofs.into(),
781        ast::Instruction::DropAuthZoneRegularProofs => DropAuthZoneRegularProofs.into(),
782        ast::Instruction::DropAuthZoneSignatureProofs => DropAuthZoneSignatureProofs.into(),
783        ast::Instruction::DropNamedProofs => {
784            id_validator
785                .drop_all_named_proofs()
786                .map_err(|err| generate_id_validation_error(resolver, err, instruction.span))?;
787            DropNamedProofs.into()
788        }
789
790        ast::Instruction::DropAllProofs => {
791            id_validator
792                .drop_all_named_proofs()
793                .map_err(|err| generate_id_validation_error(resolver, err, instruction.span))?;
794            DropAllProofs.into()
795        }
796
797        // Invocation
798        ast::Instruction::CallFunction {
799            package_address,
800            blueprint_name,
801            function_name,
802            args,
803        } => {
804            let package_address = generate_dynamic_package_address(
805                &package_address,
806                address_bech32_decoder,
807                resolver,
808            )?;
809            let blueprint_name = generate_string(blueprint_name)?;
810            let function_name = generate_string(function_name)?;
811            let args_inner = generate_args(args, resolver, address_bech32_decoder, blobs)?;
812
813            id_validator.process_call_data(&args_inner).map_err(|err| {
814                generate_id_validation_error(resolver, err, get_span!(instruction, args))
815            })?;
816
817            CallFunction {
818                package_address,
819                blueprint_name,
820                function_name,
821                args: args_inner,
822            }
823            .into()
824        }
825        ast::Instruction::CallMethod {
826            address,
827            method_name,
828            args,
829        } => {
830            let address =
831                generate_dynamic_global_address(address, address_bech32_decoder, resolver)?;
832            let method_name = generate_string(method_name)?;
833            let args_inner = generate_args(args, resolver, address_bech32_decoder, blobs)?;
834            id_validator.process_call_data(&args_inner).map_err(|err| {
835                generate_id_validation_error(resolver, err, get_span!(instruction, args))
836            })?;
837            CallMethod {
838                address,
839                method_name,
840                args: args_inner,
841            }
842            .into()
843        }
844        ast::Instruction::CallRoyaltyMethod {
845            address,
846            method_name,
847            args,
848        } => {
849            let address =
850                generate_dynamic_global_address(address, address_bech32_decoder, resolver)?;
851            let method_name = generate_string(method_name)?;
852            let args_inner = generate_args(args, resolver, address_bech32_decoder, blobs)?;
853            id_validator.process_call_data(&args_inner).map_err(|err| {
854                generate_id_validation_error(resolver, err, get_span!(instruction, args))
855            })?;
856            CallRoyaltyMethod {
857                address,
858                method_name,
859                args: args_inner,
860            }
861            .into()
862        }
863        ast::Instruction::CallMetadataMethod {
864            address,
865            method_name,
866            args,
867        } => {
868            let address =
869                generate_dynamic_global_address(address, address_bech32_decoder, resolver)?;
870            let method_name = generate_string(method_name)?;
871            let args_inner = generate_args(args, resolver, address_bech32_decoder, blobs)?;
872            id_validator.process_call_data(&args_inner).map_err(|err| {
873                generate_id_validation_error(resolver, err, get_span!(instruction, args))
874            })?;
875            CallMetadataMethod {
876                address,
877                method_name,
878                args: args_inner,
879            }
880            .into()
881        }
882        ast::Instruction::CallRoleAssignmentMethod {
883            address,
884            method_name,
885            args,
886        } => {
887            let address =
888                generate_dynamic_global_address(address, address_bech32_decoder, resolver)?;
889            let method_name = generate_string(method_name)?;
890            let args_inner = generate_args(args, resolver, address_bech32_decoder, blobs)?;
891            id_validator.process_call_data(&args_inner).map_err(|err| {
892                generate_id_validation_error(resolver, err, get_span!(instruction, args))
893            })?;
894            CallRoleAssignmentMethod {
895                address,
896                method_name,
897                args: args_inner,
898            }
899            .into()
900        }
901        ast::Instruction::CallDirectVaultMethod {
902            address,
903            method_name,
904            args,
905        } => {
906            let address = generate_internal_address(address, address_bech32_decoder)?;
907            let method_name = generate_string(method_name)?;
908            let args_inner = generate_args(args, resolver, address_bech32_decoder, blobs)?;
909            id_validator.process_call_data(&args_inner).map_err(|err| {
910                generate_id_validation_error(resolver, err, get_span!(instruction, args))
911            })?;
912            CallDirectVaultMethod {
913                address,
914                method_name,
915                args: args_inner,
916            }
917            .into()
918        }
919
920        // Address Allocation
921        ast::Instruction::AllocateGlobalAddress {
922            package_address,
923            blueprint_name,
924            address_reservation,
925            named_address,
926        } => {
927            let address_reservation_id = id_validator.new_address_reservation();
928            declare_address_reservation(address_reservation, resolver, address_reservation_id)?;
929
930            let address_id = id_validator.new_named_address();
931            declare_named_address(named_address, resolver, address_id)?;
932
933            AllocateGlobalAddress {
934                package_address: generate_package_address(package_address, address_bech32_decoder)?,
935                blueprint_name: generate_string(blueprint_name)?,
936            }
937            .into()
938        }
939
940        // Interaction with other intents
941        ast::Instruction::YieldToParent { args } => YieldToParent {
942            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
943        }
944        .into(),
945        ast::Instruction::YieldToChild { child, args } => YieldToChild {
946            child_index: generate_named_intent(child, resolver)?.into(),
947            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
948        }
949        .into(),
950        ast::Instruction::VerifyParent { access_rule } => VerifyParent {
951            access_rule: generate_typed_value(
952                access_rule,
953                resolver,
954                address_bech32_decoder,
955                blobs,
956            )?,
957        }
958        .into(),
959
960        // ==============
961        // Call direct vault method aliases
962        // ==============
963        ast::Instruction::RecallFromVault { vault_id, args } => CallDirectVaultMethod {
964            address: generate_internal_address(vault_id, address_bech32_decoder)?,
965            method_name: VAULT_RECALL_IDENT.to_string(),
966            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
967        }
968        .into(),
969        ast::Instruction::FreezeVault { vault_id, args } => CallDirectVaultMethod {
970            address: generate_internal_address(vault_id, address_bech32_decoder)?,
971            method_name: VAULT_FREEZE_IDENT.to_string(),
972            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
973        }
974        .into(),
975        ast::Instruction::UnfreezeVault { vault_id, args } => CallDirectVaultMethod {
976            address: generate_internal_address(vault_id, address_bech32_decoder)?,
977            method_name: VAULT_UNFREEZE_IDENT.to_string(),
978            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
979        }
980        .into(),
981        ast::Instruction::RecallNonFungiblesFromVault { vault_id, args } => CallDirectVaultMethod {
982            address: generate_internal_address(vault_id, address_bech32_decoder)?,
983            method_name: NON_FUNGIBLE_VAULT_RECALL_NON_FUNGIBLES_IDENT.to_string(),
984            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
985        }
986        .into(),
987
988        // ==============
989        // Call function aliases
990        // ==============
991        ast::Instruction::PublishPackage { args } => CallFunction {
992            package_address: PACKAGE_PACKAGE.into(),
993            blueprint_name: PACKAGE_BLUEPRINT.to_string(),
994            function_name: PACKAGE_PUBLISH_WASM_IDENT.to_string(),
995            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
996        }
997        .into(),
998        ast::Instruction::PublishPackageAdvanced { args } => CallFunction {
999            package_address: PACKAGE_PACKAGE.into(),
1000            blueprint_name: PACKAGE_BLUEPRINT.to_string(),
1001            function_name: PACKAGE_PUBLISH_WASM_ADVANCED_IDENT.to_string(),
1002            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1003        }
1004        .into(),
1005        ast::Instruction::CreateFungibleResource { args } => CallFunction {
1006            package_address: RESOURCE_PACKAGE.into(),
1007            blueprint_name: FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
1008            function_name: FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT.to_string(),
1009            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1010        }
1011        .into(),
1012        ast::Instruction::CreateFungibleResourceWithInitialSupply { args } => CallFunction {
1013            package_address: RESOURCE_PACKAGE.into(),
1014            blueprint_name: FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
1015            function_name: FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT.to_string(),
1016            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1017        }
1018        .into(),
1019        ast::Instruction::CreateNonFungibleResource { args } => CallFunction {
1020            package_address: RESOURCE_PACKAGE.into(),
1021            blueprint_name: NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
1022            function_name: NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT.to_string(),
1023            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1024        }
1025        .into(),
1026        ast::Instruction::CreateNonFungibleResourceWithInitialSupply { args } => CallFunction {
1027            package_address: RESOURCE_PACKAGE.into(),
1028            blueprint_name: NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
1029            function_name: NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT
1030                .to_string(),
1031            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1032        }
1033        .into(),
1034        ast::Instruction::CreateAccessController { args } => CallFunction {
1035            package_address: ACCESS_CONTROLLER_PACKAGE.into(),
1036            blueprint_name: ACCESS_CONTROLLER_BLUEPRINT.to_string(),
1037            function_name: ACCESS_CONTROLLER_CREATE_IDENT.to_string(),
1038            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1039        }
1040        .into(),
1041        ast::Instruction::CreateIdentity { args } => CallFunction {
1042            package_address: IDENTITY_PACKAGE.into(),
1043            blueprint_name: IDENTITY_BLUEPRINT.to_string(),
1044            function_name: IDENTITY_CREATE_IDENT.to_string(),
1045            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1046        }
1047        .into(),
1048        ast::Instruction::CreateIdentityAdvanced { args } => CallFunction {
1049            package_address: IDENTITY_PACKAGE.into(),
1050            blueprint_name: IDENTITY_BLUEPRINT.to_string(),
1051            function_name: IDENTITY_CREATE_ADVANCED_IDENT.to_string(),
1052            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1053        }
1054        .into(),
1055        ast::Instruction::CreateAccount { args } => CallFunction {
1056            package_address: ACCOUNT_PACKAGE.into(),
1057            blueprint_name: ACCOUNT_BLUEPRINT.to_string(),
1058            function_name: ACCOUNT_CREATE_IDENT.to_string(),
1059            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1060        }
1061        .into(),
1062        ast::Instruction::CreateAccountAdvanced { args } => CallFunction {
1063            package_address: ACCOUNT_PACKAGE.into(),
1064            blueprint_name: ACCOUNT_BLUEPRINT.to_string(),
1065            function_name: ACCOUNT_CREATE_ADVANCED_IDENT.to_string(),
1066            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1067        }
1068        .into(),
1069
1070        // ==============
1071        // Call non-main-method aliases
1072        // ==============
1073        ast::Instruction::SetMetadata { address, args } => CallMetadataMethod {
1074            address: generate_dynamic_global_address(address, address_bech32_decoder, resolver)?,
1075            method_name: METADATA_SET_IDENT.to_string(),
1076            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1077        }
1078        .into(),
1079        ast::Instruction::RemoveMetadata { address, args } => CallMetadataMethod {
1080            address: generate_dynamic_global_address(address, address_bech32_decoder, resolver)?,
1081            method_name: METADATA_REMOVE_IDENT.to_string(),
1082            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1083        }
1084        .into(),
1085        ast::Instruction::LockMetadata { address, args } => CallMetadataMethod {
1086            address: generate_dynamic_global_address(address, address_bech32_decoder, resolver)?,
1087            method_name: METADATA_LOCK_IDENT.to_string(),
1088            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1089        }
1090        .into(),
1091        ast::Instruction::SetComponentRoyalty { address, args } => CallRoyaltyMethod {
1092            address: generate_dynamic_global_address(address, address_bech32_decoder, resolver)?,
1093            method_name: COMPONENT_ROYALTY_SET_ROYALTY_IDENT.to_string(),
1094            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1095        }
1096        .into(),
1097        ast::Instruction::LockComponentRoyalty { address, args } => CallRoyaltyMethod {
1098            address: generate_dynamic_global_address(address, address_bech32_decoder, resolver)?,
1099            method_name: COMPONENT_ROYALTY_LOCK_ROYALTY_IDENT.to_string(),
1100            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1101        }
1102        .into(),
1103        ast::Instruction::ClaimComponentRoyalties { address, args } => CallRoyaltyMethod {
1104            address: generate_dynamic_global_address(address, address_bech32_decoder, resolver)?,
1105            method_name: COMPONENT_ROYALTY_CLAIM_ROYALTIES_IDENT.to_string(),
1106            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1107        }
1108        .into(),
1109        ast::Instruction::SetOwnerRole { address, args } => CallRoleAssignmentMethod {
1110            address: generate_dynamic_global_address(address, address_bech32_decoder, resolver)?,
1111            method_name: ROLE_ASSIGNMENT_SET_OWNER_IDENT.to_string(),
1112            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1113        }
1114        .into(),
1115        ast::Instruction::LockOwnerRole { address, args } => CallRoleAssignmentMethod {
1116            address: generate_dynamic_global_address(address, address_bech32_decoder, resolver)?,
1117            method_name: ROLE_ASSIGNMENT_LOCK_OWNER_IDENT.to_string(),
1118            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1119        }
1120        .into(),
1121        ast::Instruction::SetRole { address, args } => CallRoleAssignmentMethod {
1122            address: generate_dynamic_global_address(address, address_bech32_decoder, resolver)?,
1123            method_name: ROLE_ASSIGNMENT_SET_IDENT.to_string(),
1124            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1125        }
1126        .into(),
1127
1128        // ==============
1129        // Call main-method aliases
1130        // ==============
1131        ast::Instruction::MintFungible { address, args } => CallMethod {
1132            address: generate_dynamic_global_address(address, address_bech32_decoder, resolver)?,
1133            method_name: FUNGIBLE_RESOURCE_MANAGER_MINT_IDENT.to_string(),
1134            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1135        }
1136        .into(),
1137        ast::Instruction::MintNonFungible { address, args } => CallMethod {
1138            address: generate_dynamic_global_address(address, address_bech32_decoder, resolver)?,
1139            method_name: NON_FUNGIBLE_RESOURCE_MANAGER_MINT_IDENT.to_string(),
1140            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1141        }
1142        .into(),
1143        ast::Instruction::MintRuidNonFungible { address, args } => CallMethod {
1144            address: generate_dynamic_global_address(address, address_bech32_decoder, resolver)?,
1145            method_name: NON_FUNGIBLE_RESOURCE_MANAGER_MINT_RUID_IDENT.to_string(),
1146            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1147        }
1148        .into(),
1149        ast::Instruction::ClaimPackageRoyalties { address, args } => CallMethod {
1150            address: generate_dynamic_global_address(address, address_bech32_decoder, resolver)?,
1151            method_name: PACKAGE_CLAIM_ROYALTIES_IDENT.to_string(),
1152            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1153        }
1154        .into(),
1155        ast::Instruction::CreateValidator { args } => CallMethod {
1156            address: CONSENSUS_MANAGER.into(),
1157            method_name: CONSENSUS_MANAGER_CREATE_VALIDATOR_IDENT.to_string(),
1158            args: generate_args(args, resolver, address_bech32_decoder, blobs)?,
1159        }
1160        .into(),
1161    })
1162}
1163
1164#[macro_export]
1165macro_rules! invalid_type {
1166    ( $span:expr, $v:expr, $($exp:expr),+ ) => {
1167        Err(GeneratorError {
1168            error_kind: GeneratorErrorKind::InvalidAstValue {
1169                expected_value_kinds: vec!($($exp),+),
1170                actual: $v.clone(),
1171            },
1172            span: $span,
1173        })
1174    };
1175}
1176
1177fn generate_args<B>(
1178    values: &Vec<ast::ValueWithSpan>,
1179    resolver: &mut NameResolver,
1180    address_bech32_decoder: &AddressBech32Decoder,
1181    blobs: &B,
1182) -> Result<ManifestValue, GeneratorError>
1183where
1184    B: IsBlobProvider,
1185{
1186    let mut fields = Vec::new();
1187    for v in values {
1188        fields.push(generate_value(
1189            &v,
1190            None,
1191            resolver,
1192            address_bech32_decoder,
1193            blobs,
1194        )?)
1195    }
1196
1197    Ok(ManifestValue::Tuple { fields })
1198}
1199
1200fn generate_string(value: &ast::ValueWithSpan) -> Result<String, GeneratorError> {
1201    match &value.value {
1202        ast::Value::String(s) => Ok(s.into()),
1203        v => invalid_type!(value.span, v, ast::ValueKind::String),
1204    }
1205}
1206
1207fn generate_decimal(value: &ast::ValueWithSpan) -> Result<Decimal, GeneratorError> {
1208    match &value.value {
1209        ast::Value::Decimal(inner) => match &inner.value {
1210            ast::Value::String(s) => Decimal::from_str(&s).map_err(|err| GeneratorError {
1211                error_kind: GeneratorErrorKind::InvalidDecimal {
1212                    actual: s.to_string(),
1213                    err: format!("{:?}", err),
1214                },
1215                span: inner.span,
1216            }),
1217            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1218        },
1219        v => invalid_type!(value.span, v, ast::ValueKind::Decimal),
1220    }
1221}
1222
1223fn generate_precise_decimal(value: &ast::ValueWithSpan) -> Result<PreciseDecimal, GeneratorError> {
1224    match &value.value {
1225        ast::Value::PreciseDecimal(inner) => match &inner.value {
1226            ast::Value::String(s) => PreciseDecimal::from_str(s).map_err(|err| GeneratorError {
1227                error_kind: GeneratorErrorKind::InvalidPreciseDecimal {
1228                    actual: s.to_string(),
1229                    err: format!("{:?}", err),
1230                },
1231                span: inner.span,
1232            }),
1233
1234            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1235        },
1236        v => invalid_type!(value.span, v, ast::ValueKind::Decimal),
1237    }
1238}
1239
1240fn generate_global_address(
1241    value: &ast::ValueWithSpan,
1242    address_bech32_decoder: &AddressBech32Decoder,
1243) -> Result<GlobalAddress, GeneratorError> {
1244    match &value.value {
1245        ast::Value::Address(inner) => match &inner.value {
1246            ast::Value::String(s) => {
1247                // TODO: Consider more precise message by interpreting AddressBech32DecodeError
1248                // (applies everywhere where validate_and_decode() is used)
1249                if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1250                    if let Ok(address) = GlobalAddress::try_from(full_data.as_ref()) {
1251                        return Ok(address);
1252                    }
1253                }
1254                return Err(GeneratorError {
1255                    error_kind: GeneratorErrorKind::InvalidGlobalAddress(s.into()),
1256                    span: inner.span,
1257                });
1258            }
1259            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1260        },
1261        v => invalid_type!(value.span, v, ast::ValueKind::Address),
1262    }
1263}
1264
1265fn generate_package_address(
1266    value: &ast::ValueWithSpan,
1267    address_bech32_decoder: &AddressBech32Decoder,
1268) -> Result<PackageAddress, GeneratorError> {
1269    match &value.value {
1270        ast::Value::Address(inner) => match &inner.value {
1271            ast::Value::String(s) => {
1272                // TODO: Consider more precise message by interpreting AddressBech32DecodeError
1273                // (applies everywhere where validate_and_decode() is used)
1274                if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1275                    if let Ok(address) = PackageAddress::try_from(full_data.as_ref()) {
1276                        return Ok(address);
1277                    }
1278                }
1279                return Err(GeneratorError {
1280                    error_kind: GeneratorErrorKind::InvalidPackageAddress(s.into()),
1281                    span: inner.span,
1282                });
1283            }
1284            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1285        },
1286        v => invalid_type!(value.span, v, ast::ValueKind::Address),
1287    }
1288}
1289
1290fn generate_resource_address(
1291    value: &ast::ValueWithSpan,
1292    address_bech32_decoder: &AddressBech32Decoder,
1293) -> Result<ResourceAddress, GeneratorError> {
1294    match &value.value {
1295        ast::Value::Address(inner) => match &inner.value {
1296            ast::Value::String(s) => {
1297                if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1298                    if let Ok(address) = ResourceAddress::try_from(full_data.as_ref()) {
1299                        return Ok(address);
1300                    }
1301                }
1302                return Err(GeneratorError {
1303                    error_kind: GeneratorErrorKind::InvalidResourceAddress(s.into()),
1304                    span: inner.span,
1305                });
1306            }
1307            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1308        },
1309        v => invalid_type!(value.span, v, ast::ValueKind::Address),
1310    }
1311}
1312
1313fn generate_dynamic_global_address(
1314    value: &ast::ValueWithSpan,
1315    address_bech32_decoder: &AddressBech32Decoder,
1316    resolver: &mut NameResolver,
1317) -> Result<ManifestGlobalAddress, GeneratorError> {
1318    match &value.value {
1319        ast::Value::Address(inner) => match &inner.value {
1320            ast::Value::String(s) => {
1321                if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1322                    if let Ok(address) = GlobalAddress::try_from(full_data.as_ref()) {
1323                        return Ok(ManifestGlobalAddress::Static(address));
1324                    }
1325                }
1326                return Err(GeneratorError {
1327                    error_kind: GeneratorErrorKind::InvalidGlobalAddress(s.into()),
1328                    span: inner.span,
1329                });
1330            }
1331            v => return invalid_type!(inner.span, v, ast::ValueKind::String),
1332        },
1333        ast::Value::NamedAddress(inner) => {
1334            match &inner.value {
1335                ast::Value::U32(n) => Ok(ManifestGlobalAddress::Named(ManifestNamedAddress(*n))),
1336                ast::Value::String(s) => resolver
1337                    .resolve_named_address(&s)
1338                    .map(Into::into)
1339                    .map_err(|err| GeneratorError {
1340                        error_kind: GeneratorErrorKind::NameResolverError(err),
1341                        span: inner.span,
1342                    }),
1343                v => invalid_type!(value.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1344            }
1345        }
1346        v => invalid_type!(
1347            value.span,
1348            v,
1349            ast::ValueKind::Address,
1350            ast::ValueKind::NamedAddress
1351        ),
1352    }
1353}
1354
1355fn generate_internal_address(
1356    value: &ast::ValueWithSpan,
1357    address_bech32_decoder: &AddressBech32Decoder,
1358) -> Result<InternalAddress, GeneratorError> {
1359    match &value.value {
1360        ast::Value::Address(inner) => match &inner.value {
1361            ast::Value::String(s) => {
1362                if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1363                    if let Ok(address) = InternalAddress::try_from(full_data.as_ref()) {
1364                        return Ok(address);
1365                    }
1366                }
1367                return Err(GeneratorError {
1368                    error_kind: GeneratorErrorKind::InvalidInternalAddress(s.into()),
1369                    span: inner.span,
1370                });
1371            }
1372            v => return invalid_type!(inner.span, v, ast::ValueKind::String),
1373        },
1374        v => invalid_type!(value.span, v, ast::ValueKind::Address),
1375    }
1376}
1377
1378fn generate_dynamic_package_address(
1379    value: &ast::ValueWithSpan,
1380    address_bech32_decoder: &AddressBech32Decoder,
1381    resolver: &mut NameResolver,
1382) -> Result<ManifestPackageAddress, GeneratorError> {
1383    match &value.value {
1384        ast::Value::Address(inner) => match &inner.value {
1385            ast::Value::String(s) => {
1386                if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1387                    if let Ok(address) = PackageAddress::try_from(full_data.as_ref()) {
1388                        return Ok(ManifestPackageAddress::Static(address));
1389                    }
1390                }
1391                return Err(GeneratorError {
1392                    error_kind: GeneratorErrorKind::InvalidPackageAddress(s.into()),
1393                    span: inner.span,
1394                });
1395            }
1396            v => return invalid_type!(inner.span, v, ast::ValueKind::String),
1397        },
1398        ast::Value::NamedAddress(inner) => {
1399            match &inner.value {
1400                ast::Value::U32(n) => Ok(ManifestPackageAddress::Named(ManifestNamedAddress(*n))),
1401                ast::Value::String(s) => resolver
1402                    .resolve_named_address(&s)
1403                    .map(Into::into)
1404                    .map_err(|err| GeneratorError {
1405                        error_kind: GeneratorErrorKind::NameResolverError(err),
1406                        span: inner.span,
1407                    }),
1408                v => invalid_type!(value.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1409            }
1410        }
1411        v => invalid_type!(
1412            value.span,
1413            v,
1414            ast::ValueKind::Address,
1415            ast::ValueKind::NamedAddress
1416        ),
1417    }
1418}
1419
1420fn declare_bucket(
1421    value: &ast::ValueWithSpan,
1422    resolver: &mut NameResolver,
1423    bucket_id: ManifestBucket,
1424) -> Result<(), GeneratorError> {
1425    match &value.value {
1426        ast::Value::Bucket(inner) => match &inner.value {
1427            ast::Value::String(name) => resolver
1428                .insert_bucket(name.to_string(), bucket_id)
1429                .map_err(|err| GeneratorError {
1430                    error_kind: GeneratorErrorKind::NameResolverError(err),
1431                    span: inner.span,
1432                }),
1433            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1434        },
1435        v => invalid_type!(value.span, v, ast::ValueKind::Bucket),
1436    }
1437}
1438
1439fn generate_bucket(
1440    value: &ast::ValueWithSpan,
1441    resolver: &mut NameResolver,
1442) -> Result<(ManifestBucket, Span), GeneratorError> {
1443    match &value.value {
1444        ast::Value::Bucket(inner) => {
1445            let bucket = match &inner.value {
1446                ast::Value::U32(n) => Ok(ManifestBucket(*n)),
1447                ast::Value::String(s) => {
1448                    resolver.resolve_bucket(&s).map_err(|err| GeneratorError {
1449                        error_kind: GeneratorErrorKind::NameResolverError(err),
1450                        span: inner.span,
1451                    })
1452                }
1453                v => invalid_type!(inner.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1454            }?;
1455            Ok((bucket, inner.span))
1456        }
1457        v => invalid_type!(value.span, v, ast::ValueKind::Bucket),
1458    }
1459}
1460
1461fn declare_proof(
1462    value: &ast::ValueWithSpan,
1463    resolver: &mut NameResolver,
1464    proof_id: ManifestProof,
1465) -> Result<(), GeneratorError> {
1466    match &value.value {
1467        ast::Value::Proof(inner) => {
1468            match &inner.value {
1469                ast::Value::String(name) => resolver
1470                    .insert_proof(name.to_string(), proof_id)
1471                    .map_err(|err| GeneratorError {
1472                        error_kind: GeneratorErrorKind::NameResolverError(err),
1473                        span: inner.span,
1474                    }),
1475                v => invalid_type!(inner.span, v, ast::ValueKind::String),
1476            }
1477        }
1478        v => invalid_type!(value.span, v, ast::ValueKind::Proof),
1479    }
1480}
1481
1482fn declare_address_reservation(
1483    value: &ast::ValueWithSpan,
1484    resolver: &mut NameResolver,
1485    address_reservation_id: ManifestAddressReservation,
1486) -> Result<(), GeneratorError> {
1487    match &value.value {
1488        ast::Value::AddressReservation(inner) => match &inner.value {
1489            ast::Value::String(name) => resolver
1490                .insert_address_reservation(name.to_string(), address_reservation_id)
1491                .map_err(|err| GeneratorError {
1492                    error_kind: GeneratorErrorKind::NameResolverError(err),
1493                    span: inner.span,
1494                }),
1495            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1496        },
1497        v => invalid_type!(value.span, v, ast::ValueKind::AddressReservation),
1498    }
1499}
1500
1501fn declare_named_address(
1502    value: &ast::ValueWithSpan,
1503    resolver: &mut NameResolver,
1504    address_id: ManifestNamedAddress,
1505) -> Result<(), GeneratorError> {
1506    match &value.value {
1507        ast::Value::NamedAddress(inner) => match &inner.value {
1508            ast::Value::String(name) => resolver
1509                .insert_named_address(name.to_string(), address_id)
1510                .map_err(|err| GeneratorError {
1511                    error_kind: GeneratorErrorKind::NameResolverError(err),
1512                    span: inner.span,
1513                }),
1514            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1515        },
1516        v => invalid_type!(value.span, v, ast::ValueKind::NamedAddress),
1517    }
1518}
1519
1520fn declare_named_intent(
1521    value: &ast::ValueWithSpan,
1522    resolver: &mut NameResolver,
1523    intent_id: ManifestNamedIntent,
1524) -> Result<(), GeneratorError> {
1525    match &value.value {
1526        ast::Value::NamedIntent(inner) => match &inner.value {
1527            ast::Value::String(name) => resolver
1528                .insert_intent(name.to_string(), intent_id)
1529                .map_err(|err| GeneratorError {
1530                    error_kind: GeneratorErrorKind::NameResolverError(err),
1531                    span: inner.span,
1532                }),
1533            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1534        },
1535        v => invalid_type!(value.span, v, ast::ValueKind::NamedIntent),
1536    }
1537}
1538
1539fn generate_named_intent(
1540    value: &ast::ValueWithSpan,
1541    resolver: &mut NameResolver,
1542) -> Result<ManifestNamedIntent, GeneratorError> {
1543    match &value.value {
1544        ast::Value::NamedIntent(inner) => {
1545            let out = match &inner.value {
1546                // Don't support U32 for new types like this
1547                ast::Value::String(s) => {
1548                    resolver
1549                        .resolve_named_intent(&s)
1550                        .map_err(|err| GeneratorError {
1551                            error_kind: GeneratorErrorKind::NameResolverError(err),
1552                            span: inner.span,
1553                        })
1554                }
1555                v => invalid_type!(inner.span, v, ast::ValueKind::String),
1556            }?;
1557            Ok(out)
1558        }
1559        v => invalid_type!(value.span, v, ast::ValueKind::NamedIntent),
1560    }
1561}
1562
1563fn generate_proof(
1564    value: &ast::ValueWithSpan,
1565    resolver: &mut NameResolver,
1566) -> Result<(ManifestProof, Span), GeneratorError> {
1567    match &value.value {
1568        ast::Value::Proof(inner) => {
1569            let proof = match &inner.value {
1570                ast::Value::U32(n) => Ok(ManifestProof(*n)),
1571                ast::Value::String(s) => resolver.resolve_proof(&s).map_err(|err| GeneratorError {
1572                    error_kind: GeneratorErrorKind::NameResolverError(err),
1573                    span: inner.span,
1574                }),
1575                v => invalid_type!(inner.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1576            }?;
1577            Ok((proof, inner.span))
1578        }
1579        v => invalid_type!(value.span, v, ast::ValueKind::Proof),
1580    }
1581}
1582
1583fn generate_address_reservation(
1584    value: &ast::ValueWithSpan,
1585    resolver: &mut NameResolver,
1586) -> Result<ManifestAddressReservation, GeneratorError> {
1587    match &value.value {
1588        ast::Value::AddressReservation(inner) => match &inner.value {
1589            ast::Value::U32(n) => Ok(ManifestAddressReservation(*n)),
1590            ast::Value::String(s) => {
1591                resolver
1592                    .resolve_address_reservation(&s)
1593                    .map_err(|err| GeneratorError {
1594                        error_kind: GeneratorErrorKind::NameResolverError(err),
1595                        span: inner.span,
1596                    })
1597            }
1598            v => invalid_type!(inner.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1599        },
1600        v => invalid_type!(value.span, v, ast::ValueKind::AddressReservation),
1601    }
1602}
1603
1604fn generate_static_address(
1605    value: &ast::ValueWithSpan,
1606    address_bech32_decoder: &AddressBech32Decoder,
1607) -> Result<ManifestAddress, GeneratorError> {
1608    match &value.value {
1609        ast::Value::Address(inner) => match &inner.value {
1610            ast::Value::String(s) => {
1611                // Check bech32 && entity type
1612                if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1613                    // Check length
1614                    if full_data.len() == NodeId::LENGTH {
1615                        return Ok(ManifestAddress::Static(NodeId(
1616                            full_data.try_into().unwrap(),
1617                        )));
1618                    }
1619                }
1620                return Err(GeneratorError {
1621                    error_kind: GeneratorErrorKind::InvalidGlobalAddress(s.into()),
1622                    span: inner.span,
1623                });
1624            }
1625            v => return invalid_type!(inner.span, v, ast::ValueKind::String),
1626        },
1627        v => invalid_type!(value.span, v, ast::ValueKind::Address),
1628    }
1629}
1630
1631fn generate_named_address(
1632    value: &ast::ValueWithSpan,
1633    resolver: &mut NameResolver,
1634) -> Result<ManifestAddress, GeneratorError> {
1635    match &value.value {
1636        ast::Value::NamedAddress(inner) => match &inner.value {
1637            ast::Value::U32(n) => Ok(ManifestAddress::Named(ManifestNamedAddress(*n))),
1638            ast::Value::String(s) => resolver
1639                .resolve_named_address(&s)
1640                .map(|x| ManifestAddress::Named(x))
1641                .map_err(|err| GeneratorError {
1642                    error_kind: GeneratorErrorKind::NameResolverError(err),
1643                    span: inner.span,
1644                }),
1645            v => invalid_type!(inner.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1646        },
1647        v => invalid_type!(value.span, v, ast::ValueKind::NamedAddress),
1648    }
1649}
1650
1651fn generate_non_fungible_local_id(
1652    value: &ast::ValueWithSpan,
1653) -> Result<NonFungibleLocalId, GeneratorError> {
1654    match &value.value {
1655        ast::Value::NonFungibleLocalId(inner) => match &inner.value {
1656            ast::Value::String(s) => NonFungibleLocalId::from_str(s)
1657                // TODO: Consider more precise message by interpreting ParseNonFungibleLocalIdError
1658                .map_err(|_| GeneratorError {
1659                    error_kind: GeneratorErrorKind::InvalidNonFungibleLocalId(s.into()),
1660                    span: inner.span,
1661                }),
1662            v => invalid_type!(inner.span, v, ast::ValueKind::String)?,
1663        },
1664        v => invalid_type!(value.span, v, ast::ValueKind::NonFungibleLocalId),
1665    }
1666}
1667
1668fn generate_expression(value: &ast::ValueWithSpan) -> Result<ManifestExpression, GeneratorError> {
1669    match &value.value {
1670        ast::Value::Expression(inner) => match &inner.value {
1671            ast::Value::String(s) => match s.as_str() {
1672                "ENTIRE_WORKTOP" => Ok(ManifestExpression::EntireWorktop),
1673                "ENTIRE_AUTH_ZONE" => Ok(ManifestExpression::EntireAuthZone),
1674                _ => Err(GeneratorError {
1675                    error_kind: GeneratorErrorKind::InvalidExpression(s.into()),
1676                    span: inner.span,
1677                }),
1678            },
1679            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1680        },
1681        v => invalid_type!(value.span, v, ast::ValueKind::Expression),
1682    }
1683}
1684
1685fn translate_parse_hash_error(err: ParseHashError) -> String {
1686    match err {
1687        ParseHashError::InvalidHex(_) => "invalid hex value".to_string(),
1688        ParseHashError::InvalidLength { actual, expected } => {
1689            format!("invalid hash length {}, expected {}", actual, expected)
1690        }
1691    }
1692}
1693
1694fn generate_blob<B>(
1695    value: &ast::ValueWithSpan,
1696    blobs: &B,
1697) -> Result<ManifestBlobRef, GeneratorError>
1698where
1699    B: IsBlobProvider,
1700{
1701    match &value.value {
1702        ast::Value::Blob(inner) => match &inner.value {
1703            ast::Value::String(s) => {
1704                let hash = Hash::from_str(s).map_err(|err| GeneratorError {
1705                    error_kind: GeneratorErrorKind::InvalidBlobHash {
1706                        actual: s.to_string(),
1707                        err: translate_parse_hash_error(err),
1708                    },
1709                    span: inner.span,
1710                })?;
1711                blobs.get_blob(&hash).ok_or(GeneratorError {
1712                    error_kind: GeneratorErrorKind::BlobNotFound(s.clone()),
1713                    span: inner.span,
1714                })?;
1715                Ok(ManifestBlobRef(hash.0))
1716            }
1717            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1718        },
1719        v => invalid_type!(value.span, v, ast::ValueKind::Blob),
1720    }
1721}
1722
1723fn generate_non_fungible_local_ids(
1724    value: &ast::ValueWithSpan,
1725) -> Result<Vec<NonFungibleLocalId>, GeneratorError> {
1726    match &value.value {
1727        ast::Value::Array(kind, values) => {
1728            if kind.value_kind != ast::ValueKind::NonFungibleLocalId {
1729                return Err(GeneratorError {
1730                    error_kind: GeneratorErrorKind::InvalidAstType {
1731                        expected_value_kind: ast::ValueKind::NonFungibleLocalId,
1732                        actual: kind.value_kind.clone(),
1733                    },
1734                    span: kind.span,
1735                });
1736            }
1737
1738            values
1739                .iter()
1740                .map(|v| generate_non_fungible_local_id(v))
1741                .collect()
1742        }
1743        v => invalid_type!(value.span, v, ast::ValueKind::Array),
1744    }
1745}
1746
1747fn generate_byte_vec_from_hex(value: &ast::ValueWithSpan) -> Result<Vec<u8>, GeneratorError> {
1748    let bytes = match &value.value {
1749        ast::Value::String(s) => hex::decode(s).map_err(|_| GeneratorError {
1750            error_kind: GeneratorErrorKind::InvalidBytesHex(s.to_string()),
1751            span: value.span,
1752        })?,
1753        v => invalid_type!(value.span, v, ast::ValueKind::String)?,
1754    };
1755    Ok(bytes)
1756}
1757
1758fn generate_subintent_hash(
1759    decoder: &TransactionHashBech32Decoder,
1760    value: &ast::ValueWithSpan,
1761) -> Result<SubintentHash, GeneratorError> {
1762    match &value.value {
1763        ast::Value::Intent(inner) => match &inner.value {
1764            ast::Value::String(s) => decoder.validate_and_decode(s).map_err(|_| GeneratorError {
1765                error_kind: GeneratorErrorKind::InvalidSubTransactionId(s.into()),
1766                span: inner.span,
1767            }),
1768            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1769        },
1770        v => invalid_type!(value.span, v, ast::ValueKind::Intent),
1771    }
1772}
1773
1774pub fn generate_typed_value<T: ManifestDecode + ScryptoDescribe, B>(
1775    value_with_span: &ast::ValueWithSpan,
1776    resolver: &mut NameResolver,
1777    address_bech32_decoder: &AddressBech32Decoder,
1778    blobs: &B,
1779) -> Result<T, GeneratorError>
1780where
1781    B: IsBlobProvider,
1782{
1783    let value = generate_value(
1784        value_with_span,
1785        None,
1786        resolver,
1787        address_bech32_decoder,
1788        blobs,
1789    )?;
1790    let encoded = manifest_encode(&value).map_err(|encode_error| GeneratorError {
1791        span: value_with_span.span,
1792        error_kind: GeneratorErrorKind::ArgumentCouldNotBeReadAsExpectedType {
1793            type_name: core::any::type_name::<T>().to_string(),
1794            error_message: format!("{encode_error:?}"),
1795        },
1796    })?;
1797    let decoded =
1798        manifest_decode_with_nice_error(&encoded).map_err(|error_message| GeneratorError {
1799            span: value_with_span.span,
1800            error_kind: GeneratorErrorKind::ArgumentCouldNotBeReadAsExpectedType {
1801                type_name: core::any::type_name::<T>().to_string(),
1802                error_message,
1803            },
1804        })?;
1805    Ok(decoded)
1806}
1807
1808pub fn generate_value<B>(
1809    value_with_span: &ast::ValueWithSpan,
1810    expected_value_kind: Option<&ast::ValueKindWithSpan>,
1811    resolver: &mut NameResolver,
1812    address_bech32_decoder: &AddressBech32Decoder,
1813    blobs: &B,
1814) -> Result<ManifestValue, GeneratorError>
1815where
1816    B: IsBlobProvider,
1817{
1818    if let Some(value_kind) = expected_value_kind {
1819        // We check sbor value kinds to permit structures which are SBOR-compatible,
1820        // even if they don't look immediately valid in SBOR land
1821        // e.g. an Array<Tuple>(NonFungibleGlobalId("..."))
1822        // e.g. an Array<Vec>(Bytes("..."))
1823        if value_kind.sbor_value_kind() != value_with_span.value_kind().sbor_value_kind() {
1824            return Err(GeneratorError {
1825                span: value_with_span.span,
1826                error_kind: GeneratorErrorKind::UnexpectedValueKind {
1827                    expected_value_kind: value_kind.value_kind,
1828                    actual_value: value_with_span.value.clone(),
1829                },
1830            });
1831        }
1832    }
1833
1834    match &value_with_span.value {
1835        // ==============
1836        // Basic types
1837        // ==============
1838        ast::Value::Bool(value) => Ok(Value::Bool { value: *value }),
1839        ast::Value::I8(value) => Ok(Value::I8 { value: *value }),
1840        ast::Value::I16(value) => Ok(Value::I16 { value: *value }),
1841        ast::Value::I32(value) => Ok(Value::I32 { value: *value }),
1842        ast::Value::I64(value) => Ok(Value::I64 { value: *value }),
1843        ast::Value::I128(value) => Ok(Value::I128 { value: *value }),
1844        ast::Value::U8(value) => Ok(Value::U8 { value: *value }),
1845        ast::Value::U16(value) => Ok(Value::U16 { value: *value }),
1846        ast::Value::U32(value) => Ok(Value::U32 { value: *value }),
1847        ast::Value::U64(value) => Ok(Value::U64 { value: *value }),
1848        ast::Value::U128(value) => Ok(Value::U128 { value: *value }),
1849        ast::Value::String(value) => Ok(Value::String {
1850            value: value.clone(),
1851        }),
1852        ast::Value::Tuple(fields) => Ok(Value::Tuple {
1853            fields: generate_singletons(&fields, None, resolver, address_bech32_decoder, blobs)?,
1854        }),
1855        ast::Value::Enum(discriminator, fields) => Ok(Value::Enum {
1856            discriminator: discriminator.clone(),
1857            fields: generate_singletons(&fields, None, resolver, address_bech32_decoder, blobs)?,
1858        }),
1859        ast::Value::Array(element_type, elements) => {
1860            let element_value_kind = element_type.sbor_value_kind()?;
1861            Ok(Value::Array {
1862                element_value_kind,
1863                elements: generate_singletons(
1864                    &elements,
1865                    Some(element_type),
1866                    resolver,
1867                    address_bech32_decoder,
1868                    blobs,
1869                )?,
1870            })
1871        }
1872        ast::Value::Map(key_type, value_type, entries) => {
1873            let key_value_kind = key_type.sbor_value_kind()?;
1874            let value_value_kind = value_type.sbor_value_kind()?;
1875            Ok(Value::Map {
1876                key_value_kind,
1877                value_value_kind,
1878                entries: generate_kv_entries(
1879                    &entries,
1880                    &key_type,
1881                    &value_type,
1882                    resolver,
1883                    address_bech32_decoder,
1884                    blobs,
1885                )?,
1886            })
1887        }
1888        // ==============
1889        // Aliases
1890        // ==============
1891        ast::Value::Some(value) => Ok(Value::Enum {
1892            discriminator: OPTION_VARIANT_SOME,
1893            fields: vec![generate_value(
1894                &value,
1895                None,
1896                resolver,
1897                address_bech32_decoder,
1898                blobs,
1899            )?],
1900        }),
1901        ast::Value::None => Ok(Value::Enum {
1902            discriminator: OPTION_VARIANT_NONE,
1903            fields: vec![],
1904        }),
1905        ast::Value::Ok(value) => Ok(Value::Enum {
1906            discriminator: RESULT_VARIANT_OK,
1907            fields: vec![generate_value(
1908                &value,
1909                None,
1910                resolver,
1911                address_bech32_decoder,
1912                blobs,
1913            )?],
1914        }),
1915        ast::Value::Err(value) => Ok(Value::Enum {
1916            discriminator: RESULT_VARIANT_ERR,
1917            fields: vec![generate_value(
1918                &value,
1919                None,
1920                resolver,
1921                address_bech32_decoder,
1922                blobs,
1923            )?],
1924        }),
1925        ast::Value::Bytes(value) => {
1926            let bytes = generate_byte_vec_from_hex(&value)?;
1927            Ok(Value::Array {
1928                element_value_kind: ValueKind::U8,
1929                elements: bytes.iter().map(|i| Value::U8 { value: *i }).collect(),
1930            })
1931        }
1932        ast::Value::NonFungibleGlobalId(value) => {
1933            let global_id = match &value.value {
1934                ast::Value::String(s) => NonFungibleGlobalId::try_from_canonical_string(
1935                    address_bech32_decoder,
1936                    s.as_str(),
1937                )
1938                .map_err(|_| GeneratorError {
1939                    error_kind: GeneratorErrorKind::InvalidNonFungibleGlobalId,
1940                    span: value.span,
1941                }),
1942                v => invalid_type!(value.span, v, ast::ValueKind::String)?,
1943            }?;
1944            Ok(Value::Tuple {
1945                fields: vec![
1946                    Value::Custom {
1947                        value: ManifestCustomValue::Address(ManifestAddress::Static(
1948                            global_id.resource_address().into(),
1949                        )),
1950                    },
1951                    Value::Custom {
1952                        value: ManifestCustomValue::NonFungibleLocalId(from_non_fungible_local_id(
1953                            global_id.local_id().clone(),
1954                        )),
1955                    },
1956                ],
1957            })
1958        }
1959        // ==============
1960        // Custom Types
1961        // ==============
1962        ast::Value::Address(_) => generate_static_address(value_with_span, address_bech32_decoder)
1963            .map(|v| Value::Custom {
1964                value: ManifestCustomValue::Address(v),
1965            }),
1966        ast::Value::NamedAddress(_) => {
1967            generate_named_address(value_with_span, resolver).map(|v| Value::Custom {
1968                value: ManifestCustomValue::Address(v),
1969            })
1970        }
1971        ast::Value::Bucket(_) => {
1972            generate_bucket(value_with_span, resolver).map(|(v, _span)| Value::Custom {
1973                value: ManifestCustomValue::Bucket(v),
1974            })
1975        }
1976        ast::Value::Proof(_) => {
1977            generate_proof(value_with_span, resolver).map(|(v, _span)| Value::Custom {
1978                value: ManifestCustomValue::Proof(v),
1979            })
1980        }
1981        ast::Value::Expression(_) => generate_expression(value_with_span).map(|v| Value::Custom {
1982            value: ManifestCustomValue::Expression(v),
1983        }),
1984        ast::Value::Blob(_) => generate_blob(value_with_span, blobs).map(|v| Value::Custom {
1985            value: ManifestCustomValue::Blob(v),
1986        }),
1987        ast::Value::Decimal(_) => generate_decimal(value_with_span).map(|v| Value::Custom {
1988            value: ManifestCustomValue::Decimal(from_decimal(v)),
1989        }),
1990        ast::Value::PreciseDecimal(_) => {
1991            generate_precise_decimal(value_with_span).map(|v| Value::Custom {
1992                value: ManifestCustomValue::PreciseDecimal(from_precise_decimal(v)),
1993            })
1994        }
1995        ast::Value::NonFungibleLocalId(_) => {
1996            generate_non_fungible_local_id(value_with_span).map(|v| Value::Custom {
1997                value: ManifestCustomValue::NonFungibleLocalId(from_non_fungible_local_id(v)),
1998            })
1999        }
2000        ast::Value::AddressReservation(_) => {
2001            generate_address_reservation(value_with_span, resolver).map(|v| Value::Custom {
2002                value: ManifestCustomValue::AddressReservation(v),
2003            })
2004        }
2005        ast::Value::NamedIntent(_) => {
2006            return Err(GeneratorError {
2007                error_kind: GeneratorErrorKind::NamedIntentCannotBeUsedInValue,
2008                span: value_with_span.span,
2009            });
2010        }
2011        ast::Value::Intent(_) => {
2012            return Err(GeneratorError {
2013                error_kind: GeneratorErrorKind::IntentCannotBeUsedInValue,
2014                span: value_with_span.span,
2015            });
2016        }
2017    }
2018}
2019
2020fn generate_singletons<B>(
2021    elements: &Vec<ast::ValueWithSpan>,
2022    expected_value_kind: Option<&ast::ValueKindWithSpan>,
2023    resolver: &mut NameResolver,
2024    address_bech32_decoder: &AddressBech32Decoder,
2025    blobs: &B,
2026) -> Result<Vec<ManifestValue>, GeneratorError>
2027where
2028    B: IsBlobProvider,
2029{
2030    let mut result = vec![];
2031    for element in elements {
2032        result.push(generate_value(
2033            element,
2034            expected_value_kind,
2035            resolver,
2036            address_bech32_decoder,
2037            blobs,
2038        )?);
2039    }
2040    Ok(result)
2041}
2042
2043fn generate_kv_entries<B>(
2044    entries: &[(ast::ValueWithSpan, ast::ValueWithSpan)],
2045    key_value_kind: &ValueKindWithSpan,
2046    value_value_kind: &ValueKindWithSpan,
2047    resolver: &mut NameResolver,
2048    address_bech32_decoder: &AddressBech32Decoder,
2049    blobs: &B,
2050) -> Result<Vec<(ManifestValue, ManifestValue)>, GeneratorError>
2051where
2052    B: IsBlobProvider,
2053{
2054    let mut result = vec![];
2055    for entry in entries {
2056        let key = generate_value(
2057            &entry.0,
2058            Some(key_value_kind),
2059            resolver,
2060            address_bech32_decoder,
2061            blobs,
2062        )?;
2063        let value = generate_value(
2064            &entry.1,
2065            Some(value_value_kind),
2066            resolver,
2067            address_bech32_decoder,
2068            blobs,
2069        )?;
2070        result.push((key, value));
2071    }
2072    Ok(result)
2073}
2074
2075pub fn generator_error_diagnostics(
2076    s: &str,
2077    err: GeneratorError,
2078    style: CompileErrorDiagnosticsStyle,
2079) -> String {
2080    // The title should be a little longer, and include context about what triggered
2081    // the error. The label is inline next to arrows pointing to the span which is
2082    // invalid, so can be shorter.
2083    // These will appear roughly like below:
2084    //
2085    //   error: <TITLE>
2086    //     ...
2087    //   12 |       Bytes(1u32),
2088    //      |       ^^^^^ <LABEL>
2089    let (title, label) = match err.error_kind {
2090        GeneratorErrorKind::InvalidAstType {
2091            expected_value_kind,
2092            actual,
2093        } => {
2094            let title = format!("expected {:?}, found {:?}", expected_value_kind, actual,);
2095            let label = format!("expected {:?}", expected_value_kind);
2096            (title, label)
2097        }
2098        GeneratorErrorKind::InvalidAstValue {
2099            expected_value_kinds,
2100            actual,
2101        } => {
2102            let expected_value_kinds = expected_value_kinds
2103                .iter()
2104                .map(|vk| vk.to_string())
2105                .collect::<Vec<_>>()
2106                .join(" or ");
2107            let actual_value_kind = actual.value_kind();
2108            let title = format!("expected {expected_value_kinds}, found {actual_value_kind}",);
2109            let label = format!("expected {expected_value_kinds}");
2110            (title, label)
2111        }
2112        GeneratorErrorKind::UnexpectedValueKind {
2113            expected_value_kind,
2114            actual_value: actual,
2115        } => {
2116            let title = format!(
2117                "expected {}, found {}",
2118                expected_value_kind,
2119                actual.value_kind(),
2120            );
2121            let label = format!("expected {}", expected_value_kind);
2122            (title, label)
2123        }
2124        GeneratorErrorKind::InvalidPackageAddress(string) => {
2125            let title = format!("invalid package address '{}'", string);
2126            (title, "invalid package address".to_string())
2127        }
2128        GeneratorErrorKind::InvalidResourceAddress(string) => {
2129            let title = format!("invalid resource address '{}'", string);
2130            (title, "invalid resource address".to_string())
2131        }
2132        GeneratorErrorKind::InvalidDecimal { actual, err } => {
2133            let title = format!("invalid decimal '{}' - {}", actual, err);
2134            (title, "invalid decimal".to_string())
2135        }
2136        GeneratorErrorKind::InvalidPreciseDecimal { actual, err } => {
2137            let title = format!("invalid precise decimal '{}' - {}", actual, err);
2138            (title, "invalid precise decimal".to_string())
2139        }
2140        GeneratorErrorKind::InvalidNonFungibleLocalId(string) => {
2141            let title = format!("invalid non-fungible local id '{}'", string);
2142            (title, "invalid non-fungible local id".to_string())
2143        }
2144        GeneratorErrorKind::InvalidNonFungibleGlobalId => {
2145            let title = format!("invalid non-fungible global id");
2146            (title, "invalid non-fungible global id".to_string())
2147        }
2148        GeneratorErrorKind::InvalidExpression(string) => {
2149            let title = format!("invalid expression '{}'", string);
2150            (title, "invalid expression".to_string())
2151        }
2152        GeneratorErrorKind::InvalidBlobHash { actual, err } => {
2153            let title = format!("invalid blob hash '{}' - {}", actual, err);
2154            (title, "invalid blob hash".to_string())
2155        }
2156        GeneratorErrorKind::BlobNotFound(string) => {
2157            let title = format!("blob with hash '{}' not found", string);
2158            (title, "blob not found".to_string())
2159        }
2160        GeneratorErrorKind::InvalidBytesHex(string) => {
2161            let title = format!("invalid hex value '{}'", string);
2162            (title, "invalid hex value".to_string())
2163        }
2164        GeneratorErrorKind::NameResolverError(error) => match error {
2165            NameResolverError::UndefinedBucket(string) => {
2166                let title = format!("undefined bucket '{}'", string);
2167                (title, "undefined bucket".to_string())
2168            }
2169            NameResolverError::UndefinedProof(string) => {
2170                let title = format!("undefined proof '{}'", string);
2171                (title, "undefined proof".to_string())
2172            }
2173            NameResolverError::UndefinedAddressReservation(string) => {
2174                let title = format!("undefined address reservation '{}'", string);
2175                (title, "undefined address reservation".to_string())
2176            }
2177            NameResolverError::UndefinedNamedAddress(string) => {
2178                let title = format!("undefined named address '{}'", string);
2179                (title, "undefined named address".to_string())
2180            }
2181            NameResolverError::UndefinedIntent(string) => {
2182                let title = format!("undefined intent '{}'", string);
2183                (title, "undefined intent".to_string())
2184            }
2185            NameResolverError::NamedAlreadyDefined(string) => {
2186                let title = format!("name already defined '{}'", string);
2187                (title, "name already defined".to_string())
2188            }
2189        },
2190        GeneratorErrorKind::IdValidationError { err, name } => {
2191            match err {
2192                ManifestIdValidationError::BucketNotFound(bucket_id) => {
2193                    let title = if let Some(name) = name {
2194                        format!("bucket '{}' not found", name)
2195                    } else {
2196                        format!("bucket id '{:?}' not found", bucket_id)
2197                    };
2198                    (title, "bucket not found".to_string())
2199                }
2200                ManifestIdValidationError::ProofNotFound(proof_id) => {
2201                    let title = if let Some(name) = name {
2202                        format!("proof '{}' not found", name)
2203                    } else {
2204                        format!("proof id '{:?}' not found", proof_id)
2205                    };
2206                    (title, "proof not found".to_string())
2207                }
2208                ManifestIdValidationError::BucketLocked(bucket_id) => {
2209                    let title = if let Some(name) = name {
2210                        format!("cannot consume bucket '{}' because it's believed to be currently locked", name)
2211                    } else {
2212                        format!("cannot consume bucket id '{:?}' because it's believed to be currently locked", bucket_id)
2213                    };
2214                    (title, "bucket locked".to_string())
2215                }
2216                ManifestIdValidationError::AddressReservationNotFound(reservation) => {
2217                    let title = if let Some(name) = name {
2218                        format!("address reservation '{}' not found", name)
2219                    } else {
2220                        format!("address reservation id '{:?}' not found", reservation)
2221                    };
2222                    (title, "address reservation not found".to_string())
2223                }
2224                ManifestIdValidationError::AddressNotFound(address) => {
2225                    let title = if let Some(name) = name {
2226                        format!("address '{}' not found", name)
2227                    } else {
2228                        format!("address id '{:?}' not found", address)
2229                    };
2230                    (title, "address not found".to_string())
2231                }
2232                ManifestIdValidationError::IntentNotFound(intent) => {
2233                    let title = if let Some(name) = name {
2234                        format!("intent '{}' not found", name)
2235                    } else {
2236                        format!("intent id '{:?}' not found", intent)
2237                    };
2238                    (title, "intent not found".to_string())
2239                }
2240            }
2241        }
2242        GeneratorErrorKind::InvalidGlobalAddress(string) => {
2243            let title = format!("invalid global address '{}'", string);
2244            (title, "invalid global address".to_string())
2245        }
2246        GeneratorErrorKind::InvalidInternalAddress(string) => {
2247            let title = format!("invalid internal address '{}'", string);
2248            (title, "invalid internal address".to_string())
2249        }
2250        GeneratorErrorKind::InvalidSubTransactionId(string) => {
2251            let title = format!("invalid sub transaction id '{}'", string);
2252            (title, "invalid sub transaction id".to_string())
2253        }
2254        GeneratorErrorKind::InstructionNotSupportedInManifestVersion => {
2255            let title = format!("unsupported instruction for this manifest version");
2256            (title, "unsupported instruction".to_string())
2257        }
2258        GeneratorErrorKind::ManifestBuildError(ManifestBuildError::DuplicateChildSubintentHash) => {
2259            let title = format!("child subintents cannot have the same hash");
2260            (title, "duplicate hash".to_string())
2261        }
2262        GeneratorErrorKind::ManifestBuildError(
2263            ManifestBuildError::PreallocatedAddressesUnsupportedByManifestType,
2264        ) => {
2265            let title = format!("preallocated addresses are not supported in this manifest type");
2266            (title, "unsupported instruction".to_string())
2267        }
2268        GeneratorErrorKind::ManifestBuildError(
2269            ManifestBuildError::ChildSubintentsUnsupportedByManifestType,
2270        ) => {
2271            let title = format!("child subintents are not supported in this manifest type");
2272            (title, "unsupported instruction".to_string())
2273        }
2274        GeneratorErrorKind::HeaderInstructionMustComeFirst => {
2275            let title = format!(
2276                "a psuedo-instruction such as USE_CHILD must come before all other instructions"
2277            );
2278            (title, "must be at the start of the manifest".to_string())
2279        }
2280        GeneratorErrorKind::IntentCannotBeUsedInValue => {
2281            let title = format!("an Intent(...) cannot currently be used inside a value");
2282            (title, "cannot be used inside a value".to_string())
2283        }
2284        GeneratorErrorKind::NamedIntentCannotBeUsedInValue => {
2285            let title = format!("a NamedIntent(...) cannot currently be used inside a value");
2286            (title, "cannot be used inside a value".to_string())
2287        }
2288        GeneratorErrorKind::IntentCannotBeUsedAsValueKind => {
2289            let title = format!("an Intent cannot be used as a value kind");
2290            (title, "cannot be used as a value kind".to_string())
2291        }
2292        GeneratorErrorKind::NamedIntentCannotBeUsedAsValueKind => {
2293            let title = format!("a NamedIntent cannot be used as a value kind");
2294            (title, "cannot be used as a value kind".to_string())
2295        }
2296        GeneratorErrorKind::ArgumentCouldNotBeReadAsExpectedType {
2297            type_name,
2298            error_message,
2299        } => {
2300            let title = format!(
2301                "an argument's structure does not fit with the {type_name} type. {error_message}"
2302            );
2303            let description = format!("cannot be decoded as a {type_name}");
2304            (title, description)
2305        }
2306    };
2307
2308    create_snippet(s, &err.span, &title, &label, style)
2309}
2310
2311#[cfg(test)]
2312mod tests {
2313    use super::*;
2314    use crate::manifest::lexer::tokenize;
2315    use crate::manifest::parser::{Parser, ParserError, ParserErrorKind, PARSER_MAX_DEPTH};
2316    use crate::manifest::token::{Position, Span};
2317    use crate::{position, span};
2318    use radix_common::address::AddressBech32Decoder;
2319    use radix_common::constants::CONSENSUS_MANAGER;
2320    use radix_common::crypto::Secp256k1PrivateKey;
2321    use radix_common::manifest_args;
2322    use radix_common::network::NetworkDefinition;
2323    use radix_common::traits::NonFungibleData;
2324    use radix_common::types::{ComponentAddress, PackageAddress};
2325    use radix_engine_interface::blueprints::consensus_manager::ConsensusManagerCreateValidatorManifestInput;
2326    use radix_engine_interface::blueprints::resource::{
2327        NonFungibleDataSchema, NonFungibleResourceManagerMintManifestInput,
2328        NonFungibleResourceManagerMintRuidManifestInput,
2329    };
2330    use radix_engine_interface::object_modules::metadata::MetadataValue;
2331    use radix_engine_interface::object_modules::ModuleConfig;
2332    use radix_engine_interface::types::PackageRoyaltyConfig;
2333    use radix_rust::prelude::IndexMap;
2334    use scrypto::radix_blueprint_schema_init::BlueprintStateSchemaInit;
2335
2336    #[macro_export]
2337    macro_rules! generate_value_ok {
2338        ( $s:expr,   $expected:expr ) => {{
2339            let value = Parser::new(tokenize($s).unwrap(), PARSER_MAX_DEPTH)
2340                .unwrap()
2341                .parse_value()
2342                .unwrap();
2343            let mut resolver = NameResolver::new();
2344            assert_eq!(
2345                generate_value(
2346                    &value,
2347                    None,
2348                    &mut resolver,
2349                    &AddressBech32Decoder::new(&NetworkDefinition::simulator()),
2350                    &BlobProvider::default()
2351                ),
2352                Ok($expected)
2353            );
2354        }};
2355    }
2356
2357    #[macro_export]
2358    macro_rules! generate_instruction_ok {
2359        ( $s:expr, $expected:expr $(,)? ) => {{
2360            // If you use the following output for test cases, make sure you've checked the diff
2361            // println!("{}", crate::manifest::decompile(&[$expected.clone()], &NetworkDefinition::simulator()).unwrap());
2362            let instruction = Parser::new(tokenize($s).unwrap(), PARSER_MAX_DEPTH)
2363                .unwrap()
2364                .parse_instruction()
2365                .unwrap();
2366            let mut id_validator = BasicManifestValidator::new();
2367            let mut resolver = NameResolver::new();
2368            assert_eq!(
2369                generate_instruction(
2370                    &instruction,
2371                    &mut id_validator,
2372                    &mut resolver,
2373                    &AddressBech32Decoder::new(&NetworkDefinition::simulator()),
2374                    &MockBlobProvider::default()
2375                ),
2376                Ok($expected.into())
2377            );
2378        }}
2379    }
2380
2381    #[macro_export]
2382    macro_rules! generate_value_error {
2383        ( $s:expr, $expected:expr ) => {{
2384            let value = Parser::new(tokenize($s).unwrap(), PARSER_MAX_DEPTH)
2385                .unwrap()
2386                .parse_value()
2387                .unwrap();
2388            match generate_value(
2389                &value,
2390                None,
2391                &mut NameResolver::new(),
2392                &AddressBech32Decoder::new(&NetworkDefinition::simulator()),
2393                &BlobProvider::default(),
2394            ) {
2395                Ok(_) => {
2396                    panic!("Expected {:?} but no error is thrown", $expected);
2397                }
2398                Err(e) => {
2399                    assert_eq!(e, $expected);
2400                }
2401            }
2402        }};
2403    }
2404
2405    #[test]
2406    fn test_value() {
2407        generate_value_ok!(r#"Tuple()"#, Value::Tuple { fields: vec![] });
2408        generate_value_ok!(r#"true"#, Value::Bool { value: true });
2409        generate_value_ok!(r#"false"#, Value::Bool { value: false });
2410        generate_value_ok!(r#"1i8"#, Value::I8 { value: 1 });
2411        generate_value_ok!(r#"1i128"#, Value::I128 { value: 1 });
2412        generate_value_ok!(r#"1u8"#, Value::U8 { value: 1 });
2413        generate_value_ok!(r#"1u128"#, Value::U128 { value: 1 });
2414        generate_value_ok!(
2415            r#"Tuple(Bucket(1u32), Proof(2u32), "bar")"#,
2416            Value::Tuple {
2417                fields: vec![
2418                    Value::Custom {
2419                        value: ManifestCustomValue::Bucket(ManifestBucket(1))
2420                    },
2421                    Value::Custom {
2422                        value: ManifestCustomValue::Proof(ManifestProof(2))
2423                    },
2424                    Value::String {
2425                        value: "bar".into()
2426                    }
2427                ]
2428            }
2429        );
2430        generate_value_ok!(
2431            r#"Tuple(Decimal("1"))"#,
2432            Value::Tuple {
2433                fields: vec![Value::Custom {
2434                    value: ManifestCustomValue::Decimal(from_decimal(
2435                        Decimal::from_str("1").unwrap()
2436                    ))
2437                },]
2438            }
2439        );
2440        generate_value_ok!(r#"Tuple()"#, Value::Tuple { fields: vec![] });
2441        generate_value_ok!(
2442            r#"Enum<0u8>( "abc")"#,
2443            Value::Enum {
2444                discriminator: 0,
2445                fields: vec![Value::String {
2446                    value: "abc".to_owned()
2447                }]
2448            }
2449        );
2450        generate_value_ok!(
2451            r#"Enum<1u8>()"#,
2452            Value::Enum {
2453                discriminator: 1,
2454                fields: vec![]
2455            }
2456        );
2457        generate_value_ok!(
2458            r#"Enum<AccessRule::AllowAll>()"#,
2459            Value::Enum {
2460                discriminator: 0,
2461                fields: vec![]
2462            }
2463        );
2464        generate_value_ok!(
2465            r#"Expression("ENTIRE_WORKTOP")"#,
2466            Value::Custom {
2467                value: ManifestCustomValue::Expression(ManifestExpression::EntireWorktop)
2468            }
2469        );
2470        generate_value_ok!(
2471            r#"Expression("ENTIRE_AUTH_ZONE")"#,
2472            Value::Custom {
2473                value: ManifestCustomValue::Expression(ManifestExpression::EntireAuthZone)
2474            }
2475        );
2476    }
2477
2478    #[test]
2479    fn test_failures() {
2480        generate_value_error!(
2481            r#"Address(100u32)"#,
2482            GeneratorError {
2483                error_kind: GeneratorErrorKind::InvalidAstValue {
2484                    expected_value_kinds: vec![ast::ValueKind::String],
2485                    actual: ast::Value::U32(100),
2486                },
2487                span: span!(start = (8, 0, 8), end = (14, 0, 14)),
2488            }
2489        );
2490        generate_value_error!(
2491            r#"Address("invalid_package_address")"#,
2492            GeneratorError {
2493                error_kind: GeneratorErrorKind::InvalidGlobalAddress(
2494                    "invalid_package_address".into(),
2495                ),
2496                span: span!(start = (8, 0, 8), end = (33, 0, 33))
2497            }
2498        );
2499        generate_value_error!(
2500            r#"Decimal("invalid_decimal")"#,
2501            GeneratorError {
2502                error_kind: GeneratorErrorKind::InvalidDecimal {
2503                    actual: "invalid_decimal".to_string(),
2504                    err: "InvalidDigit".to_string(),
2505                },
2506                span: span!(start = (8, 0, 8), end = (25, 0, 25))
2507            }
2508        );
2509        generate_value_error!(
2510            r#"Decimal("i")"#,
2511            GeneratorError {
2512                error_kind: GeneratorErrorKind::InvalidDecimal {
2513                    actual: "i".to_string(),
2514                    err: "InvalidDigit".to_string(),
2515                },
2516                span: span!(start = (8, 0, 8), end = (11, 0, 11))
2517            }
2518        );
2519
2520        // Test unicode and spans
2521        generate_value_error!(
2522            r#"Decimal("🤓")"#,
2523            GeneratorError {
2524                error_kind: GeneratorErrorKind::InvalidDecimal {
2525                    actual: "🤓".to_string(),
2526                    err: "InvalidDigit".to_string(),
2527                },
2528                span: span!(start = (8, 0, 8), end = (11, 0, 11))
2529            }
2530        );
2531
2532        generate_value_error!(
2533            r#"Decimal("\uD83D\uDC69")"#,
2534            GeneratorError {
2535                error_kind: GeneratorErrorKind::InvalidDecimal {
2536                    actual: "\u{1f469}".to_string(), // this is a value of '👩'
2537                    err: "InvalidDigit".to_string(),
2538                },
2539                span: span!(start = (8, 0, 8), end = (22, 0, 22))
2540            }
2541        );
2542        generate_value_error!(
2543            r#"Decimal("👩")"#,
2544            GeneratorError {
2545                error_kind: GeneratorErrorKind::InvalidDecimal {
2546                    actual: "👩".to_string(),
2547                    err: "InvalidDigit".to_string(),
2548                },
2549                span: span!(start = (8, 0, 8), end = (11, 0, 11))
2550            }
2551        );
2552    }
2553
2554    #[test]
2555    fn test_instructions() {
2556        let address_bech32_decoder = AddressBech32Decoder::new(&NetworkDefinition::simulator());
2557        let package_address = PackageAddress::try_from_bech32(
2558            &address_bech32_decoder,
2559            "package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk".into(),
2560        )
2561        .unwrap();
2562        let component = ComponentAddress::try_from_bech32(
2563            &address_bech32_decoder,
2564            "component_sim1cqvgx33089ukm2pl97pv4max0x40ruvfy4lt60yvya744cvemygpmu",
2565        )
2566        .unwrap();
2567        let resource_address = ResourceAddress::try_from_bech32(
2568            &address_bech32_decoder,
2569            "resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez",
2570        )
2571        .unwrap();
2572
2573        generate_instruction_ok!(
2574            r#"TAKE_FROM_WORKTOP  Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez")  Decimal("1")  Bucket("xrd_bucket");"#,
2575            TakeFromWorktop {
2576                amount: Decimal::from(1),
2577                resource_address,
2578            },
2579        );
2580        generate_instruction_ok!(
2581            r#"TAKE_ALL_FROM_WORKTOP  Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez")  Bucket("xrd_bucket");"#,
2582            TakeAllFromWorktop { resource_address },
2583        );
2584        generate_instruction_ok!(
2585            r#"ASSERT_WORKTOP_CONTAINS  Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez")  Decimal("1");"#,
2586            AssertWorktopContains {
2587                amount: Decimal::from(1),
2588                resource_address,
2589            },
2590        );
2591        generate_instruction_ok!(
2592            r#"CALL_FUNCTION  Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk")  "Airdrop"  "new"  500u32  PreciseDecimal("120");"#,
2593            CallFunction {
2594                package_address: package_address.into(),
2595                blueprint_name: "Airdrop".into(),
2596                function_name: "new".to_string(),
2597                args: manifest_args!(500u32, pdec!("120")).into()
2598            },
2599        );
2600        generate_instruction_ok!(
2601            r#"CALL_METHOD  Address("component_sim1cqvgx33089ukm2pl97pv4max0x40ruvfy4lt60yvya744cvemygpmu")  "refill";"#,
2602            CallMethod {
2603                address: component.into(),
2604                method_name: "refill".to_string(),
2605                args: manifest_args!().into()
2606            },
2607        );
2608        generate_instruction_ok!(
2609            r#"MINT_FUNGIBLE Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez") Decimal("100");"#,
2610            CallMethod {
2611                address: resource_address.into(),
2612                method_name: "mint".to_string(),
2613                args: manifest_args!(dec!("100")).into()
2614            },
2615        );
2616    }
2617
2618    #[test]
2619    fn test_publish_instruction() {
2620        generate_instruction_ok!(
2621            r#"PUBLISH_PACKAGE_ADVANCED Blob("a710f0959d8e139b3c1ca74ac4fcb9a95ada2c82e7f563304c5487e0117095c0") Map<String, Tuple>() Map<String, Enum>() Map<String, Enum>() Map<String, Enum>();"#,
2622            CallFunction {
2623                package_address: PACKAGE_PACKAGE.into(),
2624                blueprint_name: PACKAGE_BLUEPRINT.to_string(),
2625                function_name: PACKAGE_PUBLISH_WASM_ADVANCED_IDENT.to_string(),
2626                args: manifest_args!(
2627                    ManifestBlobRef(
2628                        hex::decode(
2629                            "a710f0959d8e139b3c1ca74ac4fcb9a95ada2c82e7f563304c5487e0117095c0"
2630                        )
2631                        .unwrap()
2632                        .try_into()
2633                        .unwrap()
2634                    ),
2635                    IndexMap::<String, BlueprintStateSchemaInit, _>::new(),
2636                    IndexMap::<String, PackageRoyaltyConfig, _>::new(),
2637                    IndexMap::<String, MetadataValue, _>::new(),
2638                    RoleAssignmentInit::new()
2639                )
2640                .into(),
2641            },
2642        );
2643    }
2644
2645    #[test]
2646    fn test_create_non_fungible_instruction() {
2647        generate_instruction_ok!(
2648            r#"CREATE_NON_FUNGIBLE_RESOURCE
2649                Enum<0u8>()
2650                Enum<NonFungibleIdType::Integer>()
2651                false
2652                Enum<0u8>(
2653                    Enum<0u8>(
2654                        Tuple(
2655                            Array<Enum>(),
2656                            Array<Tuple>(),
2657                            Array<Enum>()
2658                        )
2659                    ),
2660                    Enum<0u8>(66u8),
2661                    Array<String>()
2662                )
2663                Tuple(
2664                    Enum<0u8>(),
2665                    Enum<0u8>(),
2666                    Enum<0u8>(),
2667                    Enum<0u8>(),
2668                    Enum<0u8>(),
2669                    Enum<0u8>(),
2670                    Enum<0u8>()
2671                )
2672                Tuple(
2673                    Map<String, Tuple>(
2674                        "name" => Tuple(
2675                            Enum<Option::Some>(Enum<Metadata::String>("Token")),
2676                            true
2677                        ),
2678                    ),
2679                    Map<String, Enum>()
2680                )
2681                Enum<0u8>();"#,
2682            CallFunction {
2683                package_address: RESOURCE_PACKAGE.into(),
2684                blueprint_name: NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
2685                function_name: NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT.to_string(),
2686                args: to_manifest_value_and_unwrap!(
2687                    &NonFungibleResourceManagerCreateManifestInput {
2688                        owner_role: OwnerRole::None,
2689                        id_type: NonFungibleIdType::Integer,
2690                        track_total_supply: false,
2691                        non_fungible_schema:
2692                            NonFungibleDataSchema::new_local_without_self_package_replacement::<()>(
2693                            ),
2694                        metadata: metadata! {
2695                            init {
2696                                "name" => "Token".to_string(), locked;
2697                            }
2698                        },
2699                        resource_roles: NonFungibleResourceRoles::default(),
2700                        address_reservation: None,
2701                    }
2702                ),
2703            },
2704        );
2705    }
2706
2707    #[derive(ScryptoSbor)]
2708    struct MyNonFungibleData {
2709        name: String,
2710        description: String,
2711        stored_number: Decimal,
2712    }
2713
2714    // Because we can't import the derive trait
2715    impl NonFungibleData for MyNonFungibleData {
2716        const MUTABLE_FIELDS: &'static [&'static str] = &["description", "stored_number"];
2717    }
2718
2719    #[test]
2720    fn test_generate_non_fungible_instruction_with_specific_data() {
2721        // This test is mostly to assist with generating manifest instructions for the testing harness
2722        let manifest = ManifestBuilder::new_v1()
2723            .call_function(
2724                RESOURCE_PACKAGE,
2725                NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT,
2726                NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT,
2727                NonFungibleResourceManagerCreateManifestInput {
2728                    owner_role: OwnerRole::None,
2729                    track_total_supply: false,
2730                    id_type: NonFungibleIdType::Integer,
2731                    non_fungible_schema:
2732                        NonFungibleDataSchema::new_local_without_self_package_replacement::<
2733                            MyNonFungibleData,
2734                        >(),
2735                    resource_roles: NonFungibleResourceRoles::default(),
2736                    metadata: metadata!(),
2737                    address_reservation: None,
2738                },
2739            )
2740            .build();
2741        println!(
2742            "{}",
2743            crate::manifest::decompile(&manifest, &NetworkDefinition::simulator()).unwrap()
2744        );
2745    }
2746
2747    #[test]
2748    fn test_create_non_fungible_with_initial_supply_instruction() {
2749        generate_instruction_ok!(
2750            r##"CREATE_NON_FUNGIBLE_RESOURCE_WITH_INITIAL_SUPPLY
2751                Enum<0u8>()
2752                Enum<NonFungibleIdType::Integer>()
2753                false
2754                Enum<0u8>(
2755                    Enum<0u8>(
2756                        Tuple(
2757                            Array<Enum>(),
2758                            Array<Tuple>(),
2759                            Array<Enum>()
2760                        )
2761                    ),
2762                    Enum<0u8>(66u8),
2763                    Array<String>()
2764                )
2765                Map<NonFungibleLocalId, Tuple>(
2766                    NonFungibleLocalId("#1#") => Tuple(
2767                        Tuple(
2768                            "Hello World",
2769                            Decimal("12")
2770                        )
2771                    )
2772                )
2773                Tuple(
2774                    Enum<0u8>(),
2775                    Enum<0u8>(),
2776                    Enum<0u8>(),
2777                    Enum<0u8>(),
2778                    Enum<0u8>(),
2779                    Enum<0u8>(),
2780                    Enum<0u8>()
2781                )
2782                Tuple(
2783                    Map<String, Tuple>(
2784                        "name" => Tuple(Enum<Option::Some>(Enum<Metadata::String>("Token")), true)
2785                    ),
2786                    Map<String, Enum>()
2787                )
2788                Enum<0u8>()
2789            ;"##,
2790            CallFunction {
2791                package_address: RESOURCE_PACKAGE.into(),
2792                blueprint_name: NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
2793                function_name: NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT
2794                    .to_string(),
2795                args: to_manifest_value_and_unwrap!(
2796                    &NonFungibleResourceManagerCreateWithInitialSupplyManifestInput {
2797                        owner_role: OwnerRole::None,
2798                        track_total_supply: false,
2799                        id_type: NonFungibleIdType::Integer,
2800                        non_fungible_schema:
2801                            NonFungibleDataSchema::new_local_without_self_package_replacement::<()>(
2802                            ),
2803                        resource_roles: NonFungibleResourceRoles::default(),
2804                        metadata: metadata! {
2805                            init {
2806                                "name" => "Token".to_string(), locked;
2807                            }
2808                        },
2809                        entries: indexmap!(
2810                            NonFungibleLocalId::integer(1) =>
2811                            (to_manifest_value_and_unwrap!(&(
2812                                String::from("Hello World"),
2813                                dec!("12")
2814                            )),),
2815                        ),
2816                        address_reservation: None,
2817                    }
2818                ),
2819            },
2820        );
2821    }
2822
2823    #[test]
2824    fn test_create_fungible_instruction() {
2825        generate_instruction_ok!(
2826            r#"CREATE_FUNGIBLE_RESOURCE
2827                Enum<0u8>()
2828                false
2829                18u8
2830                Tuple(
2831                    Enum<0u8>(),
2832                    Enum<0u8>(),
2833                    Enum<0u8>(),
2834                    Enum<0u8>(),
2835                    Enum<0u8>(),
2836                    Enum<0u8>()
2837                )
2838                Tuple(
2839                    Map<String, Tuple>(
2840                        "name" => Tuple(Enum<Option::Some>(Enum<Metadata::String>("Token")), false)
2841                    ),
2842                    Map<String, Enum>()
2843                )
2844                Enum<0u8>()
2845            ;"#,
2846            CallFunction {
2847                package_address: RESOURCE_PACKAGE.into(),
2848                blueprint_name: FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
2849                function_name: FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT.to_string(),
2850                args: to_manifest_value_and_unwrap!(&FungibleResourceManagerCreateManifestInput {
2851                    owner_role: OwnerRole::None,
2852                    track_total_supply: false,
2853                    divisibility: 18,
2854                    resource_roles: FungibleResourceRoles::default(),
2855                    metadata: metadata! {
2856                        init {
2857                            "name" => "Token".to_owned(), updatable;
2858                        }
2859                    },
2860                    address_reservation: None,
2861                }),
2862            },
2863        );
2864    }
2865
2866    #[test]
2867    fn test_create_fungible_with_initial_supply_instruction() {
2868        generate_instruction_ok!(
2869            r#"CREATE_FUNGIBLE_RESOURCE_WITH_INITIAL_SUPPLY
2870                Enum<0u8>()
2871                false
2872                18u8
2873                Decimal("500")
2874                Tuple(
2875                    Enum<0u8>(),
2876                    Enum<0u8>(),
2877                    Enum<0u8>(),
2878                    Enum<0u8>(),
2879                    Enum<0u8>(),
2880                    Enum<0u8>()
2881                )
2882                Tuple(
2883                    Map<String, Tuple>(
2884                        "name" => Tuple(Enum<Option::Some>(Enum<Metadata::String>("Token")), false)
2885                    ),
2886                    Map<String, Enum>()
2887                )
2888                Enum<0u8>()
2889            ;"#,
2890            CallFunction {
2891                package_address: RESOURCE_PACKAGE.into(),
2892                blueprint_name: FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
2893                function_name: FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT
2894                    .to_string(),
2895                args: to_manifest_value_and_unwrap!(
2896                    &FungibleResourceManagerCreateWithInitialSupplyManifestInput {
2897                        owner_role: OwnerRole::None,
2898                        track_total_supply: false,
2899                        divisibility: 18,
2900                        initial_supply: "500".parse().unwrap(),
2901                        resource_roles: FungibleResourceRoles::default(),
2902                        metadata: metadata! {
2903                            init {
2904                                "name" => "Token".to_owned(), updatable;
2905                            }
2906                        },
2907                        address_reservation: None,
2908                    }
2909                )
2910            },
2911        );
2912    }
2913
2914    #[test]
2915    fn test_mint_non_fungible_instruction() {
2916        let address_bech32_decoder = AddressBech32Decoder::new(&NetworkDefinition::simulator());
2917        let resource_address = ResourceAddress::try_from_bech32(
2918            &address_bech32_decoder,
2919            "resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez",
2920        )
2921        .unwrap();
2922
2923        generate_instruction_ok!(
2924            r##"
2925            MINT_NON_FUNGIBLE
2926                Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez")
2927                Map<NonFungibleLocalId, Tuple>(NonFungibleLocalId("#1#") => Tuple(Tuple("Hello World", Decimal("12"))));
2928            "##,
2929            CallMethod {
2930                address: resource_address.into(),
2931                method_name: NON_FUNGIBLE_RESOURCE_MANAGER_MINT_IDENT.to_string(),
2932                args: to_manifest_value_and_unwrap!(&NonFungibleResourceManagerMintManifestInput {
2933                    entries: indexmap!(
2934                        NonFungibleLocalId::integer(1) =>
2935                        (to_manifest_value_and_unwrap!(&(
2936                            String::from("Hello World"),
2937                            dec!("12")
2938                        )),)
2939                    )
2940                })
2941            },
2942        );
2943    }
2944
2945    #[test]
2946    fn test_mint_ruid_non_fungible_instruction() {
2947        let address_bech32_decoder = AddressBech32Decoder::new(&NetworkDefinition::simulator());
2948        let resource_address = ResourceAddress::try_from_bech32(
2949            &address_bech32_decoder,
2950            "resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez",
2951        )
2952        .unwrap();
2953
2954        generate_instruction_ok!(
2955            r#"
2956            MINT_RUID_NON_FUNGIBLE
2957                Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez")
2958                Array<Tuple>(
2959                    Tuple(Tuple("Hello World", Decimal("12")))
2960                );
2961            "#,
2962            CallMethod {
2963                address: resource_address.into(),
2964                method_name: NON_FUNGIBLE_RESOURCE_MANAGER_MINT_RUID_IDENT.to_string(),
2965                args: to_manifest_value_and_unwrap!(
2966                    &NonFungibleResourceManagerMintRuidManifestInput {
2967                        entries: Vec::from([(to_manifest_value_and_unwrap!(&(
2968                            String::from("Hello World"),
2969                            dec!("12")
2970                        )),),])
2971                    }
2972                ),
2973            },
2974        );
2975    }
2976
2977    #[test]
2978    fn test_create_validator_instruction() {
2979        let tokens = tokenize(
2980            r#"
2981            CREATE_VALIDATOR Bytes("02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5") Decimal("1") Bucket("xrd_bucket");
2982            "#
2983        ).unwrap();
2984        let instruction = Parser::new(tokens, PARSER_MAX_DEPTH)
2985            .unwrap()
2986            .parse_instruction()
2987            .unwrap();
2988        let mut id_validator = BasicManifestValidator::new();
2989        let mut resolver = NameResolver::new();
2990        resolver
2991            .named_buckets
2992            .insert("xrd_bucket".to_string(), ManifestBucket(0u32));
2993        assert_eq!(
2994            generate_instruction(
2995                &instruction,
2996                &mut id_validator,
2997                &mut resolver,
2998                &AddressBech32Decoder::new(&NetworkDefinition::simulator()),
2999                &MockBlobProvider::default()
3000            ),
3001            Ok(CallMethod {
3002                address: CONSENSUS_MANAGER.into(),
3003                method_name: CONSENSUS_MANAGER_CREATE_VALIDATOR_IDENT.to_string(),
3004                args: to_manifest_value_and_unwrap!(
3005                    &ConsensusManagerCreateValidatorManifestInput {
3006                        key: Secp256k1PrivateKey::from_u64(2u64).unwrap().public_key(),
3007                        fee_factor: Decimal::ONE,
3008                        xrd_payment: ManifestBucket(0u32)
3009                    }
3010                ),
3011            }
3012            .into())
3013        );
3014    }
3015
3016    macro_rules! generate_manifest_input_with_given_depth {
3017        ( $depth:expr ) => {{
3018            let depth: usize = $depth;
3019            // check depth
3020            let mut manifest = r#"CALL_FUNCTION Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") "blueprint" "func" "#.to_string();
3021            for _ in 0..depth - 1 {
3022                manifest.push_str("Tuple(");
3023            }
3024            manifest.push_str("0u8");
3025            for _ in 0..depth - 1 {
3026                manifest.push_str(")");
3027            }
3028            manifest.push_str(";");
3029            manifest
3030        }};
3031    }
3032
3033    macro_rules! generate_compiled_manifest_with_given_depth {
3034        ( $depth:expr ) => {{
3035            let manifest = generate_manifest_input_with_given_depth!($depth);
3036            let address_bech32_decoder = AddressBech32Decoder::new(&NetworkDefinition::simulator());
3037            let transaction_bech32_decoder =
3038                TransactionHashBech32Decoder::new(&NetworkDefinition::simulator());
3039
3040            let tokens = tokenize(&manifest)
3041                .map_err(CompileError::LexerError)
3042                .unwrap();
3043
3044            let instructions = parser::Parser::new(tokens, $depth)
3045                .unwrap()
3046                .parse_manifest()
3047                .unwrap();
3048            let blobs = BlobProvider::new();
3049
3050            generate_manifest::<_, TransactionManifestV1>(
3051                &instructions,
3052                &address_bech32_decoder,
3053                &transaction_bech32_decoder,
3054                blobs,
3055            )
3056            .unwrap()
3057        }};
3058    }
3059
3060    #[test]
3061    fn test_no_stack_overflow_for_very_deep_manifest() {
3062        use crate::manifest::*;
3063
3064        let manifest = generate_manifest_input_with_given_depth!(1000);
3065
3066        let result = compile_manifest_v1(
3067            &manifest,
3068            &NetworkDefinition::simulator(),
3069            BlobProvider::default(),
3070        );
3071        let expected = CompileError::ParserError(ParserError {
3072            error_kind: ParserErrorKind::MaxDepthExceeded {
3073                actual: 21,
3074                max: 20,
3075            },
3076            span: span!(start = (231, 0, 231), end = (236, 0, 236)),
3077        });
3078
3079        match result {
3080            Ok(_) => {
3081                panic!("Expected {:?} but no error is thrown", expected);
3082            }
3083            Err(e) => {
3084                assert_eq!(e, expected);
3085            }
3086        }
3087    }
3088
3089    #[test]
3090    fn test_if_max_depth_is_possibly_maximal() {
3091        use crate::manifest::*;
3092        // This test checks if PARSER_MAX_DEPTH is correctly adjusted in relation with
3093        // MANIFEST_SBOR_V1_MAX_DEPTH
3094
3095        // When using manifest input with maximum depth we expect to
3096        // successfully encode manifest back from compiled one
3097        let compiled = generate_compiled_manifest_with_given_depth!(PARSER_MAX_DEPTH);
3098
3099        let _result = manifest_encode(&compiled).unwrap();
3100
3101        // When using manifest input maximum depth is exceeded by one we expect
3102        // encoding error when encoding the compiled one.
3103        let compiled = generate_compiled_manifest_with_given_depth!(PARSER_MAX_DEPTH + 1);
3104
3105        let expected = EncodeError::MaxDepthExceeded(MANIFEST_SBOR_V1_MAX_DEPTH);
3106
3107        let result = manifest_encode(&compiled);
3108        assert_eq!(result, Err(expected));
3109    }
3110}