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 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 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 ast::Instruction::UsePreallocatedAddress { .. } | ast::Instruction::UseChild { .. } => {
497 return Err(GeneratorError {
498 span: instruction.span,
499 error_kind: GeneratorErrorKind::HeaderInstructionMustComeFirst,
500 })
501 }
502 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 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 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 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 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 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 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 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 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 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 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 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 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 if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1611 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 .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 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 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 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 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 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 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 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(), 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 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 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 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 let compiled = generate_compiled_manifest_with_given_depth!(PARSER_MAX_DEPTH);
3094
3095 let _result = manifest_encode(&compiled).unwrap();
3096
3097 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}