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::{from_decimal, from_non_fungible_local_id, from_precise_decimal};
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        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        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        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        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        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))
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))
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))
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                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                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                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                Err(GeneratorError {
1327                    error_kind: GeneratorErrorKind::InvalidGlobalAddress(s.into()),
1328                    span: inner.span,
1329                })
1330            }
1331            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1332        },
1333        ast::Value::NamedAddress(inner) => match &inner.value {
1334            ast::Value::U32(n) => Ok(ManifestGlobalAddress::Named(ManifestNamedAddress(*n))),
1335            ast::Value::String(s) => {
1336                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            }
1344            v => invalid_type!(value.span, v, ast::ValueKind::U32, ast::ValueKind::String),
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                Err(GeneratorError {
1368                    error_kind: GeneratorErrorKind::InvalidInternalAddress(s.into()),
1369                    span: inner.span,
1370                })
1371            }
1372            v => 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                Err(GeneratorError {
1392                    error_kind: GeneratorErrorKind::InvalidPackageAddress(s.into()),
1393                    span: inner.span,
1394                })
1395            }
1396            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1397        },
1398        ast::Value::NamedAddress(inner) => match &inner.value {
1399            ast::Value::U32(n) => Ok(ManifestPackageAddress::Named(ManifestNamedAddress(*n))),
1400            ast::Value::String(s) => {
1401                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            }
1409            v => invalid_type!(value.span, v, ast::ValueKind::U32, ast::ValueKind::String),
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) => resolver.resolve_bucket(s).map_err(|err| GeneratorError {
1448                    error_kind: GeneratorErrorKind::NameResolverError(err),
1449                    span: inner.span,
1450                }),
1451                v => invalid_type!(inner.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1452            }?;
1453            Ok((bucket, inner.span))
1454        }
1455        v => invalid_type!(value.span, v, ast::ValueKind::Bucket),
1456    }
1457}
1458
1459fn declare_proof(
1460    value: &ast::ValueWithSpan,
1461    resolver: &mut NameResolver,
1462    proof_id: ManifestProof,
1463) -> Result<(), GeneratorError> {
1464    match &value.value {
1465        ast::Value::Proof(inner) => {
1466            match &inner.value {
1467                ast::Value::String(name) => resolver
1468                    .insert_proof(name.to_string(), proof_id)
1469                    .map_err(|err| GeneratorError {
1470                        error_kind: GeneratorErrorKind::NameResolverError(err),
1471                        span: inner.span,
1472                    }),
1473                v => invalid_type!(inner.span, v, ast::ValueKind::String),
1474            }
1475        }
1476        v => invalid_type!(value.span, v, ast::ValueKind::Proof),
1477    }
1478}
1479
1480fn declare_address_reservation(
1481    value: &ast::ValueWithSpan,
1482    resolver: &mut NameResolver,
1483    address_reservation_id: ManifestAddressReservation,
1484) -> Result<(), GeneratorError> {
1485    match &value.value {
1486        ast::Value::AddressReservation(inner) => match &inner.value {
1487            ast::Value::String(name) => resolver
1488                .insert_address_reservation(name.to_string(), address_reservation_id)
1489                .map_err(|err| GeneratorError {
1490                    error_kind: GeneratorErrorKind::NameResolverError(err),
1491                    span: inner.span,
1492                }),
1493            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1494        },
1495        v => invalid_type!(value.span, v, ast::ValueKind::AddressReservation),
1496    }
1497}
1498
1499fn declare_named_address(
1500    value: &ast::ValueWithSpan,
1501    resolver: &mut NameResolver,
1502    address_id: ManifestNamedAddress,
1503) -> Result<(), GeneratorError> {
1504    match &value.value {
1505        ast::Value::NamedAddress(inner) => match &inner.value {
1506            ast::Value::String(name) => resolver
1507                .insert_named_address(name.to_string(), address_id)
1508                .map_err(|err| GeneratorError {
1509                    error_kind: GeneratorErrorKind::NameResolverError(err),
1510                    span: inner.span,
1511                }),
1512            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1513        },
1514        v => invalid_type!(value.span, v, ast::ValueKind::NamedAddress),
1515    }
1516}
1517
1518fn declare_named_intent(
1519    value: &ast::ValueWithSpan,
1520    resolver: &mut NameResolver,
1521    intent_id: ManifestNamedIntent,
1522) -> Result<(), GeneratorError> {
1523    match &value.value {
1524        ast::Value::NamedIntent(inner) => match &inner.value {
1525            ast::Value::String(name) => resolver
1526                .insert_intent(name.to_string(), intent_id)
1527                .map_err(|err| GeneratorError {
1528                    error_kind: GeneratorErrorKind::NameResolverError(err),
1529                    span: inner.span,
1530                }),
1531            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1532        },
1533        v => invalid_type!(value.span, v, ast::ValueKind::NamedIntent),
1534    }
1535}
1536
1537fn generate_named_intent(
1538    value: &ast::ValueWithSpan,
1539    resolver: &mut NameResolver,
1540) -> Result<ManifestNamedIntent, GeneratorError> {
1541    match &value.value {
1542        ast::Value::NamedIntent(inner) => {
1543            let out = match &inner.value {
1544                // Don't support U32 for new types like this
1545                ast::Value::String(s) => {
1546                    resolver
1547                        .resolve_named_intent(s)
1548                        .map_err(|err| GeneratorError {
1549                            error_kind: GeneratorErrorKind::NameResolverError(err),
1550                            span: inner.span,
1551                        })
1552                }
1553                v => invalid_type!(inner.span, v, ast::ValueKind::String),
1554            }?;
1555            Ok(out)
1556        }
1557        v => invalid_type!(value.span, v, ast::ValueKind::NamedIntent),
1558    }
1559}
1560
1561fn generate_proof(
1562    value: &ast::ValueWithSpan,
1563    resolver: &mut NameResolver,
1564) -> Result<(ManifestProof, Span), GeneratorError> {
1565    match &value.value {
1566        ast::Value::Proof(inner) => {
1567            let proof = match &inner.value {
1568                ast::Value::U32(n) => Ok(ManifestProof(*n)),
1569                ast::Value::String(s) => resolver.resolve_proof(s).map_err(|err| GeneratorError {
1570                    error_kind: GeneratorErrorKind::NameResolverError(err),
1571                    span: inner.span,
1572                }),
1573                v => invalid_type!(inner.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1574            }?;
1575            Ok((proof, inner.span))
1576        }
1577        v => invalid_type!(value.span, v, ast::ValueKind::Proof),
1578    }
1579}
1580
1581fn generate_address_reservation(
1582    value: &ast::ValueWithSpan,
1583    resolver: &mut NameResolver,
1584) -> Result<ManifestAddressReservation, GeneratorError> {
1585    match &value.value {
1586        ast::Value::AddressReservation(inner) => match &inner.value {
1587            ast::Value::U32(n) => Ok(ManifestAddressReservation(*n)),
1588            ast::Value::String(s) => {
1589                resolver
1590                    .resolve_address_reservation(s)
1591                    .map_err(|err| GeneratorError {
1592                        error_kind: GeneratorErrorKind::NameResolverError(err),
1593                        span: inner.span,
1594                    })
1595            }
1596            v => invalid_type!(inner.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1597        },
1598        v => invalid_type!(value.span, v, ast::ValueKind::AddressReservation),
1599    }
1600}
1601
1602fn generate_static_address(
1603    value: &ast::ValueWithSpan,
1604    address_bech32_decoder: &AddressBech32Decoder,
1605) -> Result<ManifestAddress, GeneratorError> {
1606    match &value.value {
1607        ast::Value::Address(inner) => match &inner.value {
1608            ast::Value::String(s) => {
1609                // Check bech32 && entity type
1610                if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1611                    // Check length
1612                    if full_data.len() == NodeId::LENGTH {
1613                        return Ok(ManifestAddress::Static(NodeId(
1614                            full_data.try_into().unwrap(),
1615                        )));
1616                    }
1617                }
1618                Err(GeneratorError {
1619                    error_kind: GeneratorErrorKind::InvalidGlobalAddress(s.into()),
1620                    span: inner.span,
1621                })
1622            }
1623            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1624        },
1625        v => invalid_type!(value.span, v, ast::ValueKind::Address),
1626    }
1627}
1628
1629fn generate_named_address(
1630    value: &ast::ValueWithSpan,
1631    resolver: &mut NameResolver,
1632) -> Result<ManifestAddress, GeneratorError> {
1633    match &value.value {
1634        ast::Value::NamedAddress(inner) => match &inner.value {
1635            ast::Value::U32(n) => Ok(ManifestAddress::Named(ManifestNamedAddress(*n))),
1636            ast::Value::String(s) => resolver
1637                .resolve_named_address(s)
1638                .map(ManifestAddress::Named)
1639                .map_err(|err| GeneratorError {
1640                    error_kind: GeneratorErrorKind::NameResolverError(err),
1641                    span: inner.span,
1642                }),
1643            v => invalid_type!(inner.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1644        },
1645        v => invalid_type!(value.span, v, ast::ValueKind::NamedAddress),
1646    }
1647}
1648
1649fn generate_non_fungible_local_id(
1650    value: &ast::ValueWithSpan,
1651) -> Result<NonFungibleLocalId, GeneratorError> {
1652    match &value.value {
1653        ast::Value::NonFungibleLocalId(inner) => match &inner.value {
1654            ast::Value::String(s) => NonFungibleLocalId::from_str(s)
1655                // TODO: Consider more precise message by interpreting ParseNonFungibleLocalIdError
1656                .map_err(|_| GeneratorError {
1657                    error_kind: GeneratorErrorKind::InvalidNonFungibleLocalId(s.into()),
1658                    span: inner.span,
1659                }),
1660            v => invalid_type!(inner.span, v, ast::ValueKind::String)?,
1661        },
1662        v => invalid_type!(value.span, v, ast::ValueKind::NonFungibleLocalId),
1663    }
1664}
1665
1666fn generate_expression(value: &ast::ValueWithSpan) -> Result<ManifestExpression, GeneratorError> {
1667    match &value.value {
1668        ast::Value::Expression(inner) => match &inner.value {
1669            ast::Value::String(s) => match s.as_str() {
1670                "ENTIRE_WORKTOP" => Ok(ManifestExpression::EntireWorktop),
1671                "ENTIRE_AUTH_ZONE" => Ok(ManifestExpression::EntireAuthZone),
1672                _ => Err(GeneratorError {
1673                    error_kind: GeneratorErrorKind::InvalidExpression(s.into()),
1674                    span: inner.span,
1675                }),
1676            },
1677            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1678        },
1679        v => invalid_type!(value.span, v, ast::ValueKind::Expression),
1680    }
1681}
1682
1683fn translate_parse_hash_error(err: ParseHashError) -> String {
1684    match err {
1685        ParseHashError::InvalidHex(_) => "invalid hex value".to_string(),
1686        ParseHashError::InvalidLength { actual, expected } => {
1687            format!("invalid hash length {}, expected {}", actual, expected)
1688        }
1689    }
1690}
1691
1692fn generate_blob<B>(
1693    value: &ast::ValueWithSpan,
1694    blobs: &B,
1695) -> Result<ManifestBlobRef, GeneratorError>
1696where
1697    B: IsBlobProvider,
1698{
1699    match &value.value {
1700        ast::Value::Blob(inner) => match &inner.value {
1701            ast::Value::String(s) => {
1702                let hash = Hash::from_str(s).map_err(|err| GeneratorError {
1703                    error_kind: GeneratorErrorKind::InvalidBlobHash {
1704                        actual: s.to_string(),
1705                        err: translate_parse_hash_error(err),
1706                    },
1707                    span: inner.span,
1708                })?;
1709                blobs.get_blob(&hash).ok_or(GeneratorError {
1710                    error_kind: GeneratorErrorKind::BlobNotFound(s.clone()),
1711                    span: inner.span,
1712                })?;
1713                Ok(ManifestBlobRef(hash.0))
1714            }
1715            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1716        },
1717        v => invalid_type!(value.span, v, ast::ValueKind::Blob),
1718    }
1719}
1720
1721fn generate_non_fungible_local_ids(
1722    value: &ast::ValueWithSpan,
1723) -> Result<Vec<NonFungibleLocalId>, GeneratorError> {
1724    match &value.value {
1725        ast::Value::Array(kind, values) => {
1726            if kind.value_kind != ast::ValueKind::NonFungibleLocalId {
1727                return Err(GeneratorError {
1728                    error_kind: GeneratorErrorKind::InvalidAstType {
1729                        expected_value_kind: ast::ValueKind::NonFungibleLocalId,
1730                        actual: kind.value_kind,
1731                    },
1732                    span: kind.span,
1733                });
1734            }
1735
1736            values.iter().map(generate_non_fungible_local_id).collect()
1737        }
1738        v => invalid_type!(value.span, v, ast::ValueKind::Array),
1739    }
1740}
1741
1742fn generate_byte_vec_from_hex(value: &ast::ValueWithSpan) -> Result<Vec<u8>, GeneratorError> {
1743    let bytes = match &value.value {
1744        ast::Value::String(s) => hex::decode(s).map_err(|_| GeneratorError {
1745            error_kind: GeneratorErrorKind::InvalidBytesHex(s.to_string()),
1746            span: value.span,
1747        })?,
1748        v => invalid_type!(value.span, v, ast::ValueKind::String)?,
1749    };
1750    Ok(bytes)
1751}
1752
1753fn generate_subintent_hash(
1754    decoder: &TransactionHashBech32Decoder,
1755    value: &ast::ValueWithSpan,
1756) -> Result<SubintentHash, GeneratorError> {
1757    match &value.value {
1758        ast::Value::Intent(inner) => match &inner.value {
1759            ast::Value::String(s) => decoder.validate_and_decode(s).map_err(|_| GeneratorError {
1760                error_kind: GeneratorErrorKind::InvalidSubTransactionId(s.into()),
1761                span: inner.span,
1762            }),
1763            v => invalid_type!(inner.span, v, ast::ValueKind::String),
1764        },
1765        v => invalid_type!(value.span, v, ast::ValueKind::Intent),
1766    }
1767}
1768
1769pub fn generate_typed_value<T: ManifestDecode + ScryptoDescribe, B>(
1770    value_with_span: &ast::ValueWithSpan,
1771    resolver: &mut NameResolver,
1772    address_bech32_decoder: &AddressBech32Decoder,
1773    blobs: &B,
1774) -> Result<T, GeneratorError>
1775where
1776    B: IsBlobProvider,
1777{
1778    let value = generate_value(
1779        value_with_span,
1780        None,
1781        resolver,
1782        address_bech32_decoder,
1783        blobs,
1784    )?;
1785    let encoded = manifest_encode(&value).map_err(|encode_error| GeneratorError {
1786        span: value_with_span.span,
1787        error_kind: GeneratorErrorKind::ArgumentCouldNotBeReadAsExpectedType {
1788            type_name: core::any::type_name::<T>().to_string(),
1789            error_message: format!("{encode_error:?}"),
1790        },
1791    })?;
1792    let decoded =
1793        manifest_decode_with_nice_error(&encoded).map_err(|error_message| GeneratorError {
1794            span: value_with_span.span,
1795            error_kind: GeneratorErrorKind::ArgumentCouldNotBeReadAsExpectedType {
1796                type_name: core::any::type_name::<T>().to_string(),
1797                error_message,
1798            },
1799        })?;
1800    Ok(decoded)
1801}
1802
1803pub fn generate_value<B>(
1804    value_with_span: &ast::ValueWithSpan,
1805    expected_value_kind: Option<&ast::ValueKindWithSpan>,
1806    resolver: &mut NameResolver,
1807    address_bech32_decoder: &AddressBech32Decoder,
1808    blobs: &B,
1809) -> Result<ManifestValue, GeneratorError>
1810where
1811    B: IsBlobProvider,
1812{
1813    if let Some(value_kind) = expected_value_kind {
1814        // We check sbor value kinds to permit structures which are SBOR-compatible,
1815        // even if they don't look immediately valid in SBOR land
1816        // e.g. an Array<Tuple>(NonFungibleGlobalId("..."))
1817        // e.g. an Array<Vec>(Bytes("..."))
1818        if value_kind.sbor_value_kind() != value_with_span.value_kind().sbor_value_kind() {
1819            return Err(GeneratorError {
1820                span: value_with_span.span,
1821                error_kind: GeneratorErrorKind::UnexpectedValueKind {
1822                    expected_value_kind: value_kind.value_kind,
1823                    actual_value: value_with_span.value.clone(),
1824                },
1825            });
1826        }
1827    }
1828
1829    match &value_with_span.value {
1830        // ==============
1831        // Basic types
1832        // ==============
1833        ast::Value::Bool(value) => Ok(Value::Bool { value: *value }),
1834        ast::Value::I8(value) => Ok(Value::I8 { value: *value }),
1835        ast::Value::I16(value) => Ok(Value::I16 { value: *value }),
1836        ast::Value::I32(value) => Ok(Value::I32 { value: *value }),
1837        ast::Value::I64(value) => Ok(Value::I64 { value: *value }),
1838        ast::Value::I128(value) => Ok(Value::I128 { value: *value }),
1839        ast::Value::U8(value) => Ok(Value::U8 { value: *value }),
1840        ast::Value::U16(value) => Ok(Value::U16 { value: *value }),
1841        ast::Value::U32(value) => Ok(Value::U32 { value: *value }),
1842        ast::Value::U64(value) => Ok(Value::U64 { value: *value }),
1843        ast::Value::U128(value) => Ok(Value::U128 { value: *value }),
1844        ast::Value::String(value) => Ok(Value::String {
1845            value: value.clone(),
1846        }),
1847        ast::Value::Tuple(fields) => Ok(Value::Tuple {
1848            fields: generate_singletons(fields, None, resolver, address_bech32_decoder, blobs)?,
1849        }),
1850        ast::Value::Enum(discriminator, fields) => Ok(Value::Enum {
1851            discriminator: *discriminator,
1852            fields: generate_singletons(fields, None, resolver, address_bech32_decoder, blobs)?,
1853        }),
1854        ast::Value::Array(element_type, elements) => {
1855            let element_value_kind = element_type.sbor_value_kind()?;
1856            Ok(Value::Array {
1857                element_value_kind,
1858                elements: generate_singletons(
1859                    elements,
1860                    Some(element_type),
1861                    resolver,
1862                    address_bech32_decoder,
1863                    blobs,
1864                )?,
1865            })
1866        }
1867        ast::Value::Map(key_type, value_type, entries) => {
1868            let key_value_kind = key_type.sbor_value_kind()?;
1869            let value_value_kind = value_type.sbor_value_kind()?;
1870            Ok(Value::Map {
1871                key_value_kind,
1872                value_value_kind,
1873                entries: generate_kv_entries(
1874                    entries,
1875                    key_type,
1876                    value_type,
1877                    resolver,
1878                    address_bech32_decoder,
1879                    blobs,
1880                )?,
1881            })
1882        }
1883        // ==============
1884        // Aliases
1885        // ==============
1886        ast::Value::Some(value) => Ok(Value::Enum {
1887            discriminator: OPTION_VARIANT_SOME,
1888            fields: vec![generate_value(
1889                value,
1890                None,
1891                resolver,
1892                address_bech32_decoder,
1893                blobs,
1894            )?],
1895        }),
1896        ast::Value::None => Ok(Value::Enum {
1897            discriminator: OPTION_VARIANT_NONE,
1898            fields: vec![],
1899        }),
1900        ast::Value::Ok(value) => Ok(Value::Enum {
1901            discriminator: RESULT_VARIANT_OK,
1902            fields: vec![generate_value(
1903                value,
1904                None,
1905                resolver,
1906                address_bech32_decoder,
1907                blobs,
1908            )?],
1909        }),
1910        ast::Value::Err(value) => Ok(Value::Enum {
1911            discriminator: RESULT_VARIANT_ERR,
1912            fields: vec![generate_value(
1913                value,
1914                None,
1915                resolver,
1916                address_bech32_decoder,
1917                blobs,
1918            )?],
1919        }),
1920        ast::Value::Bytes(value) => {
1921            let bytes = generate_byte_vec_from_hex(value)?;
1922            Ok(Value::Array {
1923                element_value_kind: ValueKind::U8,
1924                elements: bytes.iter().map(|i| Value::U8 { value: *i }).collect(),
1925            })
1926        }
1927        ast::Value::NonFungibleGlobalId(value) => {
1928            let global_id = match &value.value {
1929                ast::Value::String(s) => NonFungibleGlobalId::try_from_canonical_string(
1930                    address_bech32_decoder,
1931                    s.as_str(),
1932                )
1933                .map_err(|_| GeneratorError {
1934                    error_kind: GeneratorErrorKind::InvalidNonFungibleGlobalId,
1935                    span: value.span,
1936                }),
1937                v => invalid_type!(value.span, v, ast::ValueKind::String)?,
1938            }?;
1939            Ok(Value::Tuple {
1940                fields: vec![
1941                    Value::Custom {
1942                        value: ManifestCustomValue::Address(ManifestAddress::Static(
1943                            global_id.resource_address().into(),
1944                        )),
1945                    },
1946                    Value::Custom {
1947                        value: ManifestCustomValue::NonFungibleLocalId(from_non_fungible_local_id(
1948                            global_id.local_id().clone(),
1949                        )),
1950                    },
1951                ],
1952            })
1953        }
1954        // ==============
1955        // Custom Types
1956        // ==============
1957        ast::Value::Address(_) => generate_static_address(value_with_span, address_bech32_decoder)
1958            .map(|v| Value::Custom {
1959                value: ManifestCustomValue::Address(v),
1960            }),
1961        ast::Value::NamedAddress(_) => {
1962            generate_named_address(value_with_span, resolver).map(|v| Value::Custom {
1963                value: ManifestCustomValue::Address(v),
1964            })
1965        }
1966        ast::Value::Bucket(_) => {
1967            generate_bucket(value_with_span, resolver).map(|(v, _span)| Value::Custom {
1968                value: ManifestCustomValue::Bucket(v),
1969            })
1970        }
1971        ast::Value::Proof(_) => {
1972            generate_proof(value_with_span, resolver).map(|(v, _span)| Value::Custom {
1973                value: ManifestCustomValue::Proof(v),
1974            })
1975        }
1976        ast::Value::Expression(_) => generate_expression(value_with_span).map(|v| Value::Custom {
1977            value: ManifestCustomValue::Expression(v),
1978        }),
1979        ast::Value::Blob(_) => generate_blob(value_with_span, blobs).map(|v| Value::Custom {
1980            value: ManifestCustomValue::Blob(v),
1981        }),
1982        ast::Value::Decimal(_) => generate_decimal(value_with_span).map(|v| Value::Custom {
1983            value: ManifestCustomValue::Decimal(from_decimal(v)),
1984        }),
1985        ast::Value::PreciseDecimal(_) => {
1986            generate_precise_decimal(value_with_span).map(|v| Value::Custom {
1987                value: ManifestCustomValue::PreciseDecimal(from_precise_decimal(v)),
1988            })
1989        }
1990        ast::Value::NonFungibleLocalId(_) => {
1991            generate_non_fungible_local_id(value_with_span).map(|v| Value::Custom {
1992                value: ManifestCustomValue::NonFungibleLocalId(from_non_fungible_local_id(v)),
1993            })
1994        }
1995        ast::Value::AddressReservation(_) => {
1996            generate_address_reservation(value_with_span, resolver).map(|v| Value::Custom {
1997                value: ManifestCustomValue::AddressReservation(v),
1998            })
1999        }
2000        ast::Value::NamedIntent(_) => Err(GeneratorError {
2001            error_kind: GeneratorErrorKind::NamedIntentCannotBeUsedInValue,
2002            span: value_with_span.span,
2003        }),
2004        ast::Value::Intent(_) => Err(GeneratorError {
2005            error_kind: GeneratorErrorKind::IntentCannotBeUsedInValue,
2006            span: value_with_span.span,
2007        }),
2008    }
2009}
2010
2011fn generate_singletons<B>(
2012    elements: &Vec<ast::ValueWithSpan>,
2013    expected_value_kind: Option<&ast::ValueKindWithSpan>,
2014    resolver: &mut NameResolver,
2015    address_bech32_decoder: &AddressBech32Decoder,
2016    blobs: &B,
2017) -> Result<Vec<ManifestValue>, GeneratorError>
2018where
2019    B: IsBlobProvider,
2020{
2021    let mut result = vec![];
2022    for element in elements {
2023        result.push(generate_value(
2024            element,
2025            expected_value_kind,
2026            resolver,
2027            address_bech32_decoder,
2028            blobs,
2029        )?);
2030    }
2031    Ok(result)
2032}
2033
2034fn generate_kv_entries<B>(
2035    entries: &[(ast::ValueWithSpan, ast::ValueWithSpan)],
2036    key_value_kind: &ValueKindWithSpan,
2037    value_value_kind: &ValueKindWithSpan,
2038    resolver: &mut NameResolver,
2039    address_bech32_decoder: &AddressBech32Decoder,
2040    blobs: &B,
2041) -> Result<Vec<(ManifestValue, ManifestValue)>, GeneratorError>
2042where
2043    B: IsBlobProvider,
2044{
2045    let mut result = vec![];
2046    for entry in entries {
2047        let key = generate_value(
2048            &entry.0,
2049            Some(key_value_kind),
2050            resolver,
2051            address_bech32_decoder,
2052            blobs,
2053        )?;
2054        let value = generate_value(
2055            &entry.1,
2056            Some(value_value_kind),
2057            resolver,
2058            address_bech32_decoder,
2059            blobs,
2060        )?;
2061        result.push((key, value));
2062    }
2063    Ok(result)
2064}
2065
2066pub fn generator_error_diagnostics(
2067    s: &str,
2068    err: GeneratorError,
2069    style: CompileErrorDiagnosticsStyle,
2070) -> String {
2071    // The title should be a little longer, and include context about what triggered
2072    // the error. The label is inline next to arrows pointing to the span which is
2073    // invalid, so can be shorter.
2074    // These will appear roughly like below:
2075    //
2076    //   error: <TITLE>
2077    //     ...
2078    //   12 |       Bytes(1u32),
2079    //      |       ^^^^^ <LABEL>
2080    let (title, label) = match err.error_kind {
2081        GeneratorErrorKind::InvalidAstType {
2082            expected_value_kind,
2083            actual,
2084        } => {
2085            let title = format!("expected {:?}, found {:?}", expected_value_kind, actual,);
2086            let label = format!("expected {:?}", expected_value_kind);
2087            (title, label)
2088        }
2089        GeneratorErrorKind::InvalidAstValue {
2090            expected_value_kinds,
2091            actual,
2092        } => {
2093            let expected_value_kinds = expected_value_kinds
2094                .iter()
2095                .map(|vk| vk.to_string())
2096                .collect::<Vec<_>>()
2097                .join(" or ");
2098            let actual_value_kind = actual.value_kind();
2099            let title = format!("expected {expected_value_kinds}, found {actual_value_kind}",);
2100            let label = format!("expected {expected_value_kinds}");
2101            (title, label)
2102        }
2103        GeneratorErrorKind::UnexpectedValueKind {
2104            expected_value_kind,
2105            actual_value: actual,
2106        } => {
2107            let title = format!(
2108                "expected {}, found {}",
2109                expected_value_kind,
2110                actual.value_kind(),
2111            );
2112            let label = format!("expected {}", expected_value_kind);
2113            (title, label)
2114        }
2115        GeneratorErrorKind::InvalidPackageAddress(string) => {
2116            let title = format!("invalid package address '{}'", string);
2117            (title, "invalid package address".to_string())
2118        }
2119        GeneratorErrorKind::InvalidResourceAddress(string) => {
2120            let title = format!("invalid resource address '{}'", string);
2121            (title, "invalid resource address".to_string())
2122        }
2123        GeneratorErrorKind::InvalidDecimal { actual, err } => {
2124            let title = format!("invalid decimal '{}' - {}", actual, err);
2125            (title, "invalid decimal".to_string())
2126        }
2127        GeneratorErrorKind::InvalidPreciseDecimal { actual, err } => {
2128            let title = format!("invalid precise decimal '{}' - {}", actual, err);
2129            (title, "invalid precise decimal".to_string())
2130        }
2131        GeneratorErrorKind::InvalidNonFungibleLocalId(string) => {
2132            let title = format!("invalid non-fungible local id '{}'", string);
2133            (title, "invalid non-fungible local id".to_string())
2134        }
2135        GeneratorErrorKind::InvalidNonFungibleGlobalId => {
2136            let title = "invalid non-fungible global id".to_string();
2137            (title, "invalid non-fungible global id".to_string())
2138        }
2139        GeneratorErrorKind::InvalidExpression(string) => {
2140            let title = format!("invalid expression '{}'", string);
2141            (title, "invalid expression".to_string())
2142        }
2143        GeneratorErrorKind::InvalidBlobHash { actual, err } => {
2144            let title = format!("invalid blob hash '{}' - {}", actual, err);
2145            (title, "invalid blob hash".to_string())
2146        }
2147        GeneratorErrorKind::BlobNotFound(string) => {
2148            let title = format!("blob with hash '{}' not found", string);
2149            (title, "blob not found".to_string())
2150        }
2151        GeneratorErrorKind::InvalidBytesHex(string) => {
2152            let title = format!("invalid hex value '{}'", string);
2153            (title, "invalid hex value".to_string())
2154        }
2155        GeneratorErrorKind::NameResolverError(error) => match error {
2156            NameResolverError::UndefinedBucket(string) => {
2157                let title = format!("undefined bucket '{}'", string);
2158                (title, "undefined bucket".to_string())
2159            }
2160            NameResolverError::UndefinedProof(string) => {
2161                let title = format!("undefined proof '{}'", string);
2162                (title, "undefined proof".to_string())
2163            }
2164            NameResolverError::UndefinedAddressReservation(string) => {
2165                let title = format!("undefined address reservation '{}'", string);
2166                (title, "undefined address reservation".to_string())
2167            }
2168            NameResolverError::UndefinedNamedAddress(string) => {
2169                let title = format!("undefined named address '{}'", string);
2170                (title, "undefined named address".to_string())
2171            }
2172            NameResolverError::UndefinedIntent(string) => {
2173                let title = format!("undefined intent '{}'", string);
2174                (title, "undefined intent".to_string())
2175            }
2176            NameResolverError::NamedAlreadyDefined(string) => {
2177                let title = format!("name already defined '{}'", string);
2178                (title, "name already defined".to_string())
2179            }
2180        },
2181        GeneratorErrorKind::IdValidationError { err, name } => {
2182            match err {
2183                ManifestIdValidationError::BucketNotFound(bucket_id) => {
2184                    let title = if let Some(name) = name {
2185                        format!("bucket '{}' not found", name)
2186                    } else {
2187                        format!("bucket id '{:?}' not found", bucket_id)
2188                    };
2189                    (title, "bucket not found".to_string())
2190                }
2191                ManifestIdValidationError::ProofNotFound(proof_id) => {
2192                    let title = if let Some(name) = name {
2193                        format!("proof '{}' not found", name)
2194                    } else {
2195                        format!("proof id '{:?}' not found", proof_id)
2196                    };
2197                    (title, "proof not found".to_string())
2198                }
2199                ManifestIdValidationError::BucketLocked(bucket_id) => {
2200                    let title = if let Some(name) = name {
2201                        format!("cannot consume bucket '{}' because it's believed to be currently locked", name)
2202                    } else {
2203                        format!("cannot consume bucket id '{:?}' because it's believed to be currently locked", bucket_id)
2204                    };
2205                    (title, "bucket locked".to_string())
2206                }
2207                ManifestIdValidationError::AddressReservationNotFound(reservation) => {
2208                    let title = if let Some(name) = name {
2209                        format!("address reservation '{}' not found", name)
2210                    } else {
2211                        format!("address reservation id '{:?}' not found", reservation)
2212                    };
2213                    (title, "address reservation not found".to_string())
2214                }
2215                ManifestIdValidationError::AddressNotFound(address) => {
2216                    let title = if let Some(name) = name {
2217                        format!("address '{}' not found", name)
2218                    } else {
2219                        format!("address id '{:?}' not found", address)
2220                    };
2221                    (title, "address not found".to_string())
2222                }
2223                ManifestIdValidationError::IntentNotFound(intent) => {
2224                    let title = if let Some(name) = name {
2225                        format!("intent '{}' not found", name)
2226                    } else {
2227                        format!("intent id '{:?}' not found", intent)
2228                    };
2229                    (title, "intent not found".to_string())
2230                }
2231            }
2232        }
2233        GeneratorErrorKind::InvalidGlobalAddress(string) => {
2234            let title = format!("invalid global address '{}'", string);
2235            (title, "invalid global address".to_string())
2236        }
2237        GeneratorErrorKind::InvalidInternalAddress(string) => {
2238            let title = format!("invalid internal address '{}'", string);
2239            (title, "invalid internal address".to_string())
2240        }
2241        GeneratorErrorKind::InvalidSubTransactionId(string) => {
2242            let title = format!("invalid sub transaction id '{}'", string);
2243            (title, "invalid sub transaction id".to_string())
2244        }
2245        GeneratorErrorKind::InstructionNotSupportedInManifestVersion => {
2246            let title = "unsupported instruction for this manifest version".to_string();
2247            (title, "unsupported instruction".to_string())
2248        }
2249        GeneratorErrorKind::ManifestBuildError(ManifestBuildError::DuplicateChildSubintentHash) => {
2250            let title = "child subintents cannot have the same hash".to_string();
2251            (title, "duplicate hash".to_string())
2252        }
2253        GeneratorErrorKind::ManifestBuildError(
2254            ManifestBuildError::PreallocatedAddressesUnsupportedByManifestType,
2255        ) => {
2256            let title =
2257                "preallocated addresses are not supported in this manifest type".to_string();
2258            (title, "unsupported instruction".to_string())
2259        }
2260        GeneratorErrorKind::ManifestBuildError(
2261            ManifestBuildError::ChildSubintentsUnsupportedByManifestType,
2262        ) => {
2263            let title = "child subintents are not supported in this manifest type".to_string();
2264            (title, "unsupported instruction".to_string())
2265        }
2266        GeneratorErrorKind::HeaderInstructionMustComeFirst => {
2267            let title =
2268                "a psuedo-instruction such as USE_CHILD must come before all other instructions"
2269                    .to_string();
2270            (title, "must be at the start of the manifest".to_string())
2271        }
2272        GeneratorErrorKind::IntentCannotBeUsedInValue => {
2273            let title = "an Intent(...) cannot currently be used inside a value".to_string();
2274            (title, "cannot be used inside a value".to_string())
2275        }
2276        GeneratorErrorKind::NamedIntentCannotBeUsedInValue => {
2277            let title = "a NamedIntent(...) cannot currently be used inside a value".to_string();
2278            (title, "cannot be used inside a value".to_string())
2279        }
2280        GeneratorErrorKind::IntentCannotBeUsedAsValueKind => {
2281            let title = "an Intent cannot be used as a value kind".to_string();
2282            (title, "cannot be used as a value kind".to_string())
2283        }
2284        GeneratorErrorKind::NamedIntentCannotBeUsedAsValueKind => {
2285            let title = "a NamedIntent cannot be used as a value kind".to_string();
2286            (title, "cannot be used as a value kind".to_string())
2287        }
2288        GeneratorErrorKind::ArgumentCouldNotBeReadAsExpectedType {
2289            type_name,
2290            error_message,
2291        } => {
2292            let title = format!(
2293                "an argument's structure does not fit with the {type_name} type. {error_message}"
2294            );
2295            let description = format!("cannot be decoded as a {type_name}");
2296            (title, description)
2297        }
2298    };
2299
2300    create_snippet(s, &err.span, &title, &label, style)
2301}
2302
2303#[cfg(test)]
2304mod tests {
2305    use super::*;
2306    use crate::manifest::lexer::tokenize;
2307    use crate::manifest::parser::{Parser, ParserError, ParserErrorKind, PARSER_MAX_DEPTH};
2308    use crate::manifest::token::{Position, Span};
2309    use crate::{position, span};
2310    use radix_common::address::AddressBech32Decoder;
2311    use radix_common::constants::CONSENSUS_MANAGER;
2312    use radix_common::crypto::Secp256k1PrivateKey;
2313    use radix_common::manifest_args;
2314    use radix_common::network::NetworkDefinition;
2315    use radix_common::traits::NonFungibleData;
2316    use radix_common::types::{ComponentAddress, PackageAddress};
2317    use radix_engine_interface::blueprints::consensus_manager::ConsensusManagerCreateValidatorManifestInput;
2318    use radix_engine_interface::blueprints::resource::{
2319        NonFungibleDataSchema, NonFungibleResourceManagerMintManifestInput,
2320        NonFungibleResourceManagerMintRuidManifestInput,
2321    };
2322    use radix_engine_interface::object_modules::metadata::MetadataValue;
2323    use radix_engine_interface::object_modules::ModuleConfig;
2324    use radix_engine_interface::types::PackageRoyaltyConfig;
2325    use radix_rust::prelude::IndexMap;
2326    use scrypto::radix_blueprint_schema_init::BlueprintStateSchemaInit;
2327
2328    #[macro_export]
2329    macro_rules! generate_value_ok {
2330        ( $s:expr,   $expected:expr ) => {{
2331            let value = Parser::new(tokenize($s).unwrap(), PARSER_MAX_DEPTH)
2332                .unwrap()
2333                .parse_value()
2334                .unwrap();
2335            let mut resolver = NameResolver::new();
2336            assert_eq!(
2337                generate_value(
2338                    &value,
2339                    None,
2340                    &mut resolver,
2341                    &AddressBech32Decoder::new(&NetworkDefinition::simulator()),
2342                    &BlobProvider::default()
2343                ),
2344                Ok($expected)
2345            );
2346        }};
2347    }
2348
2349    #[macro_export]
2350    macro_rules! generate_instruction_ok {
2351        ( $s:expr, $expected:expr $(,)? ) => {{
2352            // If you use the following output for test cases, make sure you've checked the diff
2353            // println!("{}", crate::manifest::decompile(&[$expected.clone()], &NetworkDefinition::simulator()).unwrap());
2354            let instruction = Parser::new(tokenize($s).unwrap(), PARSER_MAX_DEPTH)
2355                .unwrap()
2356                .parse_instruction()
2357                .unwrap();
2358            let mut id_validator = BasicManifestValidator::new();
2359            let mut resolver = NameResolver::new();
2360            assert_eq!(
2361                generate_instruction(
2362                    &instruction,
2363                    &mut id_validator,
2364                    &mut resolver,
2365                    &AddressBech32Decoder::new(&NetworkDefinition::simulator()),
2366                    &MockBlobProvider::default()
2367                ),
2368                Ok($expected.into())
2369            );
2370        }}
2371    }
2372
2373    #[macro_export]
2374    macro_rules! generate_value_error {
2375        ( $s:expr, $expected:expr ) => {{
2376            let value = Parser::new(tokenize($s).unwrap(), PARSER_MAX_DEPTH)
2377                .unwrap()
2378                .parse_value()
2379                .unwrap();
2380            match generate_value(
2381                &value,
2382                None,
2383                &mut NameResolver::new(),
2384                &AddressBech32Decoder::new(&NetworkDefinition::simulator()),
2385                &BlobProvider::default(),
2386            ) {
2387                Ok(_) => {
2388                    panic!("Expected {:?} but no error is thrown", $expected);
2389                }
2390                Err(e) => {
2391                    assert_eq!(e, $expected);
2392                }
2393            }
2394        }};
2395    }
2396
2397    #[test]
2398    fn test_value() {
2399        generate_value_ok!(r#"Tuple()"#, Value::Tuple { fields: vec![] });
2400        generate_value_ok!(r#"true"#, Value::Bool { value: true });
2401        generate_value_ok!(r#"false"#, Value::Bool { value: false });
2402        generate_value_ok!(r#"1i8"#, Value::I8 { value: 1 });
2403        generate_value_ok!(r#"1i128"#, Value::I128 { value: 1 });
2404        generate_value_ok!(r#"1u8"#, Value::U8 { value: 1 });
2405        generate_value_ok!(r#"1u128"#, Value::U128 { value: 1 });
2406        generate_value_ok!(
2407            r#"Tuple(Bucket(1u32), Proof(2u32), "bar")"#,
2408            Value::Tuple {
2409                fields: vec![
2410                    Value::Custom {
2411                        value: ManifestCustomValue::Bucket(ManifestBucket(1))
2412                    },
2413                    Value::Custom {
2414                        value: ManifestCustomValue::Proof(ManifestProof(2))
2415                    },
2416                    Value::String {
2417                        value: "bar".into()
2418                    }
2419                ]
2420            }
2421        );
2422        generate_value_ok!(
2423            r#"Tuple(Decimal("1"))"#,
2424            Value::Tuple {
2425                fields: vec![Value::Custom {
2426                    value: ManifestCustomValue::Decimal(from_decimal(
2427                        Decimal::from_str("1").unwrap()
2428                    ))
2429                },]
2430            }
2431        );
2432        generate_value_ok!(r#"Tuple()"#, Value::Tuple { fields: vec![] });
2433        generate_value_ok!(
2434            r#"Enum<0u8>( "abc")"#,
2435            Value::Enum {
2436                discriminator: 0,
2437                fields: vec![Value::String {
2438                    value: "abc".to_owned()
2439                }]
2440            }
2441        );
2442        generate_value_ok!(
2443            r#"Enum<1u8>()"#,
2444            Value::Enum {
2445                discriminator: 1,
2446                fields: vec![]
2447            }
2448        );
2449        generate_value_ok!(
2450            r#"Enum<AccessRule::AllowAll>()"#,
2451            Value::Enum {
2452                discriminator: 0,
2453                fields: vec![]
2454            }
2455        );
2456        generate_value_ok!(
2457            r#"Expression("ENTIRE_WORKTOP")"#,
2458            Value::Custom {
2459                value: ManifestCustomValue::Expression(ManifestExpression::EntireWorktop)
2460            }
2461        );
2462        generate_value_ok!(
2463            r#"Expression("ENTIRE_AUTH_ZONE")"#,
2464            Value::Custom {
2465                value: ManifestCustomValue::Expression(ManifestExpression::EntireAuthZone)
2466            }
2467        );
2468    }
2469
2470    #[test]
2471    fn test_failures() {
2472        generate_value_error!(
2473            r#"Address(100u32)"#,
2474            GeneratorError {
2475                error_kind: GeneratorErrorKind::InvalidAstValue {
2476                    expected_value_kinds: vec![ast::ValueKind::String],
2477                    actual: ast::Value::U32(100),
2478                },
2479                span: span!(start = (8, 0, 8), end = (14, 0, 14)),
2480            }
2481        );
2482        generate_value_error!(
2483            r#"Address("invalid_package_address")"#,
2484            GeneratorError {
2485                error_kind: GeneratorErrorKind::InvalidGlobalAddress(
2486                    "invalid_package_address".into(),
2487                ),
2488                span: span!(start = (8, 0, 8), end = (33, 0, 33))
2489            }
2490        );
2491        generate_value_error!(
2492            r#"Decimal("invalid_decimal")"#,
2493            GeneratorError {
2494                error_kind: GeneratorErrorKind::InvalidDecimal {
2495                    actual: "invalid_decimal".to_string(),
2496                    err: "InvalidDigit".to_string(),
2497                },
2498                span: span!(start = (8, 0, 8), end = (25, 0, 25))
2499            }
2500        );
2501        generate_value_error!(
2502            r#"Decimal("i")"#,
2503            GeneratorError {
2504                error_kind: GeneratorErrorKind::InvalidDecimal {
2505                    actual: "i".to_string(),
2506                    err: "InvalidDigit".to_string(),
2507                },
2508                span: span!(start = (8, 0, 8), end = (11, 0, 11))
2509            }
2510        );
2511
2512        // Test unicode and spans
2513        generate_value_error!(
2514            r#"Decimal("🤓")"#,
2515            GeneratorError {
2516                error_kind: GeneratorErrorKind::InvalidDecimal {
2517                    actual: "🤓".to_string(),
2518                    err: "InvalidDigit".to_string(),
2519                },
2520                span: span!(start = (8, 0, 8), end = (11, 0, 11))
2521            }
2522        );
2523
2524        generate_value_error!(
2525            r#"Decimal("\uD83D\uDC69")"#,
2526            GeneratorError {
2527                error_kind: GeneratorErrorKind::InvalidDecimal {
2528                    actual: "\u{1f469}".to_string(), // this is a value of '👩'
2529                    err: "InvalidDigit".to_string(),
2530                },
2531                span: span!(start = (8, 0, 8), end = (22, 0, 22))
2532            }
2533        );
2534        generate_value_error!(
2535            r#"Decimal("👩")"#,
2536            GeneratorError {
2537                error_kind: GeneratorErrorKind::InvalidDecimal {
2538                    actual: "👩".to_string(),
2539                    err: "InvalidDigit".to_string(),
2540                },
2541                span: span!(start = (8, 0, 8), end = (11, 0, 11))
2542            }
2543        );
2544    }
2545
2546    #[test]
2547    fn test_instructions() {
2548        let address_bech32_decoder = AddressBech32Decoder::new(&NetworkDefinition::simulator());
2549        let package_address = PackageAddress::try_from_bech32(
2550            &address_bech32_decoder,
2551            "package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk",
2552        )
2553        .unwrap();
2554        let component = ComponentAddress::try_from_bech32(
2555            &address_bech32_decoder,
2556            "component_sim1cqvgx33089ukm2pl97pv4max0x40ruvfy4lt60yvya744cvemygpmu",
2557        )
2558        .unwrap();
2559        let resource_address = ResourceAddress::try_from_bech32(
2560            &address_bech32_decoder,
2561            "resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez",
2562        )
2563        .unwrap();
2564
2565        generate_instruction_ok!(
2566            r#"TAKE_FROM_WORKTOP  Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez")  Decimal("1")  Bucket("xrd_bucket");"#,
2567            TakeFromWorktop {
2568                amount: Decimal::from(1),
2569                resource_address,
2570            },
2571        );
2572        generate_instruction_ok!(
2573            r#"TAKE_ALL_FROM_WORKTOP  Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez")  Bucket("xrd_bucket");"#,
2574            TakeAllFromWorktop { resource_address },
2575        );
2576        generate_instruction_ok!(
2577            r#"ASSERT_WORKTOP_CONTAINS  Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez")  Decimal("1");"#,
2578            AssertWorktopContains {
2579                amount: Decimal::from(1),
2580                resource_address,
2581            },
2582        );
2583        generate_instruction_ok!(
2584            r#"CALL_FUNCTION  Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk")  "Airdrop"  "new"  500u32  PreciseDecimal("120");"#,
2585            CallFunction {
2586                package_address: package_address.into(),
2587                blueprint_name: "Airdrop".into(),
2588                function_name: "new".to_string(),
2589                args: manifest_args!(500u32, pdec!("120")).into()
2590            },
2591        );
2592        generate_instruction_ok!(
2593            r#"CALL_METHOD  Address("component_sim1cqvgx33089ukm2pl97pv4max0x40ruvfy4lt60yvya744cvemygpmu")  "refill";"#,
2594            CallMethod {
2595                address: component.into(),
2596                method_name: "refill".to_string(),
2597                args: manifest_args!().into()
2598            },
2599        );
2600        generate_instruction_ok!(
2601            r#"MINT_FUNGIBLE Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez") Decimal("100");"#,
2602            CallMethod {
2603                address: resource_address.into(),
2604                method_name: "mint".to_string(),
2605                args: manifest_args!(dec!("100")).into()
2606            },
2607        );
2608    }
2609
2610    #[test]
2611    fn test_publish_instruction() {
2612        generate_instruction_ok!(
2613            r#"PUBLISH_PACKAGE_ADVANCED Blob("a710f0959d8e139b3c1ca74ac4fcb9a95ada2c82e7f563304c5487e0117095c0") Map<String, Tuple>() Map<String, Enum>() Map<String, Enum>() Map<String, Enum>();"#,
2614            CallFunction {
2615                package_address: PACKAGE_PACKAGE.into(),
2616                blueprint_name: PACKAGE_BLUEPRINT.to_string(),
2617                function_name: PACKAGE_PUBLISH_WASM_ADVANCED_IDENT.to_string(),
2618                args: manifest_args!(
2619                    ManifestBlobRef(
2620                        hex::decode(
2621                            "a710f0959d8e139b3c1ca74ac4fcb9a95ada2c82e7f563304c5487e0117095c0"
2622                        )
2623                        .unwrap()
2624                        .try_into()
2625                        .unwrap()
2626                    ),
2627                    IndexMap::<String, BlueprintStateSchemaInit, _>::new(),
2628                    IndexMap::<String, PackageRoyaltyConfig, _>::new(),
2629                    IndexMap::<String, MetadataValue, _>::new(),
2630                    ManifestRoleAssignmentInit::new()
2631                )
2632                .into(),
2633            },
2634        );
2635    }
2636
2637    #[test]
2638    fn test_create_non_fungible_instruction() {
2639        generate_instruction_ok!(
2640            r#"CREATE_NON_FUNGIBLE_RESOURCE
2641                Enum<0u8>()
2642                Enum<NonFungibleIdType::Integer>()
2643                false
2644                Enum<0u8>(
2645                    Enum<0u8>(
2646                        Tuple(
2647                            Array<Enum>(),
2648                            Array<Tuple>(),
2649                            Array<Enum>()
2650                        )
2651                    ),
2652                    Enum<0u8>(66u8),
2653                    Array<String>()
2654                )
2655                Tuple(
2656                    Enum<0u8>(),
2657                    Enum<0u8>(),
2658                    Enum<0u8>(),
2659                    Enum<0u8>(),
2660                    Enum<0u8>(),
2661                    Enum<0u8>(),
2662                    Enum<0u8>()
2663                )
2664                Tuple(
2665                    Map<String, Tuple>(
2666                        "name" => Tuple(
2667                            Enum<Option::Some>(Enum<Metadata::String>("Token")),
2668                            true
2669                        ),
2670                    ),
2671                    Map<String, Enum>()
2672                )
2673                Enum<0u8>();"#,
2674            CallFunction {
2675                package_address: RESOURCE_PACKAGE.into(),
2676                blueprint_name: NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
2677                function_name: NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT.to_string(),
2678                args: to_manifest_value_and_unwrap!(
2679                    &NonFungibleResourceManagerCreateManifestInput {
2680                        owner_role: OwnerRole::None.into(),
2681                        id_type: NonFungibleIdType::Integer,
2682                        track_total_supply: false,
2683                        non_fungible_schema:
2684                            NonFungibleDataSchema::new_local_without_self_package_replacement::<()>(
2685                            ),
2686                        metadata: metadata! {
2687                            init {
2688                                "name" => "Token".to_string(), locked;
2689                            }
2690                        }
2691                        .into(),
2692                        resource_roles: NonFungibleResourceRoles::default().into(),
2693                        address_reservation: None,
2694                    }
2695                ),
2696            },
2697        );
2698    }
2699
2700    #[derive(ScryptoSbor)]
2701    struct MyNonFungibleData {
2702        name: String,
2703        description: String,
2704        stored_number: Decimal,
2705    }
2706
2707    // Because we can't import the derive trait
2708    impl NonFungibleData for MyNonFungibleData {
2709        const MUTABLE_FIELDS: &'static [&'static str] = &["description", "stored_number"];
2710    }
2711
2712    #[test]
2713    fn test_generate_non_fungible_instruction_with_specific_data() {
2714        // This test is mostly to assist with generating manifest instructions for the testing harness
2715        let manifest = ManifestBuilder::new_v1()
2716            .call_function(
2717                RESOURCE_PACKAGE,
2718                NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT,
2719                NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT,
2720                NonFungibleResourceManagerCreateManifestInput {
2721                    owner_role: OwnerRole::None.into(),
2722                    track_total_supply: false,
2723                    id_type: NonFungibleIdType::Integer,
2724                    non_fungible_schema:
2725                        NonFungibleDataSchema::new_local_without_self_package_replacement::<
2726                            MyNonFungibleData,
2727                        >(),
2728                    resource_roles: NonFungibleResourceRoles::default().into(),
2729                    metadata: metadata!().into(),
2730                    address_reservation: None,
2731                },
2732            )
2733            .build();
2734        println!(
2735            "{}",
2736            crate::manifest::decompile(&manifest, &NetworkDefinition::simulator()).unwrap()
2737        );
2738    }
2739
2740    #[test]
2741    fn test_create_non_fungible_with_initial_supply_instruction() {
2742        generate_instruction_ok!(
2743            r##"CREATE_NON_FUNGIBLE_RESOURCE_WITH_INITIAL_SUPPLY
2744                Enum<0u8>()
2745                Enum<NonFungibleIdType::Integer>()
2746                false
2747                Enum<0u8>(
2748                    Enum<0u8>(
2749                        Tuple(
2750                            Array<Enum>(),
2751                            Array<Tuple>(),
2752                            Array<Enum>()
2753                        )
2754                    ),
2755                    Enum<0u8>(66u8),
2756                    Array<String>()
2757                )
2758                Map<NonFungibleLocalId, Tuple>(
2759                    NonFungibleLocalId("#1#") => Tuple(
2760                        Tuple(
2761                            "Hello World",
2762                            Decimal("12")
2763                        )
2764                    )
2765                )
2766                Tuple(
2767                    Enum<0u8>(),
2768                    Enum<0u8>(),
2769                    Enum<0u8>(),
2770                    Enum<0u8>(),
2771                    Enum<0u8>(),
2772                    Enum<0u8>(),
2773                    Enum<0u8>()
2774                )
2775                Tuple(
2776                    Map<String, Tuple>(
2777                        "name" => Tuple(Enum<Option::Some>(Enum<Metadata::String>("Token")), true)
2778                    ),
2779                    Map<String, Enum>()
2780                )
2781                Enum<0u8>()
2782            ;"##,
2783            CallFunction {
2784                package_address: RESOURCE_PACKAGE.into(),
2785                blueprint_name: NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
2786                function_name: NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT
2787                    .to_string(),
2788                args: to_manifest_value_and_unwrap!(
2789                    &NonFungibleResourceManagerCreateWithInitialSupplyManifestInput {
2790                        owner_role: OwnerRole::None.into(),
2791                        track_total_supply: false,
2792                        id_type: NonFungibleIdType::Integer,
2793                        non_fungible_schema:
2794                            NonFungibleDataSchema::new_local_without_self_package_replacement::<()>(
2795                            ),
2796                        resource_roles: NonFungibleResourceRoles::default().into(),
2797                        metadata: metadata! {
2798                            init {
2799                                "name" => "Token".to_string(), locked;
2800                            }
2801                        }
2802                        .into(),
2803                        entries: indexmap!(
2804                            NonFungibleLocalId::integer(1) =>
2805                            (to_manifest_value_and_unwrap!(&(
2806                                String::from("Hello World"),
2807                                dec!("12")
2808                            )),),
2809                        ),
2810                        address_reservation: None,
2811                    }
2812                ),
2813            },
2814        );
2815    }
2816
2817    #[test]
2818    fn test_create_fungible_instruction() {
2819        generate_instruction_ok!(
2820            r#"CREATE_FUNGIBLE_RESOURCE
2821                Enum<0u8>()
2822                false
2823                18u8
2824                Tuple(
2825                    Enum<0u8>(),
2826                    Enum<0u8>(),
2827                    Enum<0u8>(),
2828                    Enum<0u8>(),
2829                    Enum<0u8>(),
2830                    Enum<0u8>()
2831                )
2832                Tuple(
2833                    Map<String, Tuple>(
2834                        "name" => Tuple(Enum<Option::Some>(Enum<Metadata::String>("Token")), false)
2835                    ),
2836                    Map<String, Enum>()
2837                )
2838                Enum<0u8>()
2839            ;"#,
2840            CallFunction {
2841                package_address: RESOURCE_PACKAGE.into(),
2842                blueprint_name: FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
2843                function_name: FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT.to_string(),
2844                args: to_manifest_value_and_unwrap!(&FungibleResourceManagerCreateManifestInput {
2845                    owner_role: OwnerRole::None.into(),
2846                    track_total_supply: false,
2847                    divisibility: 18,
2848                    resource_roles: FungibleResourceRoles::default().into(),
2849                    metadata: metadata! {
2850                        init {
2851                            "name" => "Token".to_owned(), updatable;
2852                        }
2853                    }
2854                    .into(),
2855                    address_reservation: None,
2856                }),
2857            },
2858        );
2859    }
2860
2861    #[test]
2862    fn test_create_fungible_with_initial_supply_instruction() {
2863        generate_instruction_ok!(
2864            r#"CREATE_FUNGIBLE_RESOURCE_WITH_INITIAL_SUPPLY
2865                Enum<0u8>()
2866                false
2867                18u8
2868                Decimal("500")
2869                Tuple(
2870                    Enum<0u8>(),
2871                    Enum<0u8>(),
2872                    Enum<0u8>(),
2873                    Enum<0u8>(),
2874                    Enum<0u8>(),
2875                    Enum<0u8>()
2876                )
2877                Tuple(
2878                    Map<String, Tuple>(
2879                        "name" => Tuple(Enum<Option::Some>(Enum<Metadata::String>("Token")), false)
2880                    ),
2881                    Map<String, Enum>()
2882                )
2883                Enum<0u8>()
2884            ;"#,
2885            CallFunction {
2886                package_address: RESOURCE_PACKAGE.into(),
2887                blueprint_name: FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
2888                function_name: FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT
2889                    .to_string(),
2890                args: to_manifest_value_and_unwrap!(
2891                    &FungibleResourceManagerCreateWithInitialSupplyManifestInput {
2892                        owner_role: OwnerRole::None.into(),
2893                        track_total_supply: false,
2894                        divisibility: 18,
2895                        initial_supply: "500".parse().unwrap(),
2896                        resource_roles: FungibleResourceRoles::default().into(),
2897                        metadata: metadata! {
2898                            init {
2899                                "name" => "Token".to_owned(), updatable;
2900                            }
2901                        }
2902                        .into(),
2903                        address_reservation: None,
2904                    }
2905                )
2906            },
2907        );
2908    }
2909
2910    #[test]
2911    fn test_mint_non_fungible_instruction() {
2912        let address_bech32_decoder = AddressBech32Decoder::new(&NetworkDefinition::simulator());
2913        let resource_address = ResourceAddress::try_from_bech32(
2914            &address_bech32_decoder,
2915            "resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez",
2916        )
2917        .unwrap();
2918
2919        generate_instruction_ok!(
2920            r##"
2921            MINT_NON_FUNGIBLE
2922                Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez")
2923                Map<NonFungibleLocalId, Tuple>(NonFungibleLocalId("#1#") => Tuple(Tuple("Hello World", Decimal("12"))));
2924            "##,
2925            CallMethod {
2926                address: resource_address.into(),
2927                method_name: NON_FUNGIBLE_RESOURCE_MANAGER_MINT_IDENT.to_string(),
2928                args: to_manifest_value_and_unwrap!(&NonFungibleResourceManagerMintManifestInput {
2929                    entries: indexmap!(
2930                        NonFungibleLocalId::integer(1) =>
2931                        (to_manifest_value_and_unwrap!(&(
2932                            String::from("Hello World"),
2933                            dec!("12")
2934                        )),)
2935                    )
2936                })
2937            },
2938        );
2939    }
2940
2941    #[test]
2942    fn test_mint_ruid_non_fungible_instruction() {
2943        let address_bech32_decoder = AddressBech32Decoder::new(&NetworkDefinition::simulator());
2944        let resource_address = ResourceAddress::try_from_bech32(
2945            &address_bech32_decoder,
2946            "resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez",
2947        )
2948        .unwrap();
2949
2950        generate_instruction_ok!(
2951            r#"
2952            MINT_RUID_NON_FUNGIBLE
2953                Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez")
2954                Array<Tuple>(
2955                    Tuple(Tuple("Hello World", Decimal("12")))
2956                );
2957            "#,
2958            CallMethod {
2959                address: resource_address.into(),
2960                method_name: NON_FUNGIBLE_RESOURCE_MANAGER_MINT_RUID_IDENT.to_string(),
2961                args: to_manifest_value_and_unwrap!(
2962                    &NonFungibleResourceManagerMintRuidManifestInput {
2963                        entries: Vec::from([(to_manifest_value_and_unwrap!(&(
2964                            String::from("Hello World"),
2965                            dec!("12")
2966                        )),),])
2967                    }
2968                ),
2969            },
2970        );
2971    }
2972
2973    #[test]
2974    fn test_create_validator_instruction() {
2975        let tokens = tokenize(
2976            r#"
2977            CREATE_VALIDATOR Bytes("02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5") Decimal("1") Bucket("xrd_bucket");
2978            "#
2979        ).unwrap();
2980        let instruction = Parser::new(tokens, PARSER_MAX_DEPTH)
2981            .unwrap()
2982            .parse_instruction()
2983            .unwrap();
2984        let mut id_validator = BasicManifestValidator::new();
2985        let mut resolver = NameResolver::new();
2986        resolver
2987            .named_buckets
2988            .insert("xrd_bucket".to_string(), ManifestBucket(0u32));
2989        assert_eq!(
2990            generate_instruction(
2991                &instruction,
2992                &mut id_validator,
2993                &mut resolver,
2994                &AddressBech32Decoder::new(&NetworkDefinition::simulator()),
2995                &MockBlobProvider
2996            ),
2997            Ok(CallMethod {
2998                address: CONSENSUS_MANAGER.into(),
2999                method_name: CONSENSUS_MANAGER_CREATE_VALIDATOR_IDENT.to_string(),
3000                args: to_manifest_value_and_unwrap!(
3001                    &ConsensusManagerCreateValidatorManifestInput {
3002                        key: Secp256k1PrivateKey::from_u64(2u64).unwrap().public_key(),
3003                        fee_factor: Decimal::ONE,
3004                        xrd_payment: ManifestBucket(0u32)
3005                    }
3006                ),
3007            }
3008            .into())
3009        );
3010    }
3011
3012    macro_rules! generate_manifest_input_with_given_depth {
3013        ( $depth:expr ) => {{
3014            let depth: usize = $depth;
3015            // check depth
3016            let mut manifest = r#"CALL_FUNCTION Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") "blueprint" "func" "#.to_string();
3017            for _ in 0..depth - 1 {
3018                manifest.push_str("Tuple(");
3019            }
3020            manifest.push_str("0u8");
3021            for _ in 0..depth - 1 {
3022                manifest.push_str(")");
3023            }
3024            manifest.push_str(";");
3025            manifest
3026        }};
3027    }
3028
3029    macro_rules! generate_compiled_manifest_with_given_depth {
3030        ( $depth:expr ) => {{
3031            let manifest = generate_manifest_input_with_given_depth!($depth);
3032            let address_bech32_decoder = AddressBech32Decoder::new(&NetworkDefinition::simulator());
3033            let transaction_bech32_decoder =
3034                TransactionHashBech32Decoder::new(&NetworkDefinition::simulator());
3035
3036            let tokens = tokenize(&manifest)
3037                .map_err(CompileError::LexerError)
3038                .unwrap();
3039
3040            let instructions = parser::Parser::new(tokens, $depth)
3041                .unwrap()
3042                .parse_manifest()
3043                .unwrap();
3044            let blobs = BlobProvider::new();
3045
3046            generate_manifest::<_, TransactionManifestV1>(
3047                &instructions,
3048                &address_bech32_decoder,
3049                &transaction_bech32_decoder,
3050                blobs,
3051            )
3052            .unwrap()
3053        }};
3054    }
3055
3056    #[test]
3057    fn test_no_stack_overflow_for_very_deep_manifest() {
3058        use crate::manifest::*;
3059
3060        let manifest = generate_manifest_input_with_given_depth!(1000);
3061
3062        let result = compile_manifest_v1(
3063            &manifest,
3064            &NetworkDefinition::simulator(),
3065            BlobProvider::default(),
3066        );
3067        let expected = CompileError::ParserError(ParserError {
3068            error_kind: ParserErrorKind::MaxDepthExceeded {
3069                actual: 21,
3070                max: 20,
3071            },
3072            span: span!(start = (231, 0, 231), end = (236, 0, 236)),
3073        });
3074
3075        match result {
3076            Ok(_) => {
3077                panic!("Expected {:?} but no error is thrown", expected);
3078            }
3079            Err(e) => {
3080                assert_eq!(e, expected);
3081            }
3082        }
3083    }
3084
3085    #[test]
3086    fn test_if_max_depth_is_possibly_maximal() {
3087        use crate::manifest::*;
3088        // This test checks if PARSER_MAX_DEPTH is correctly adjusted in relation with
3089        // MANIFEST_SBOR_V1_MAX_DEPTH
3090
3091        // When using manifest input with maximum depth we expect to
3092        // successfully encode manifest back from compiled one
3093        let compiled = generate_compiled_manifest_with_given_depth!(PARSER_MAX_DEPTH);
3094
3095        let _result = manifest_encode(&compiled).unwrap();
3096
3097        // When using manifest input maximum depth is exceeded by one we expect
3098        // encoding error when encoding the compiled one.
3099        let compiled = generate_compiled_manifest_with_given_depth!(PARSER_MAX_DEPTH + 1);
3100
3101        let expected = EncodeError::MaxDepthExceeded(MANIFEST_SBOR_V1_MAX_DEPTH);
3102
3103        let result = manifest_encode(&compiled);
3104        assert_eq!(result, Err(expected));
3105    }
3106}