1use core::iter::*;
2
3use super::ast::Instruction;
4use super::ast::InstructionWithSpan;
5use super::ast::ValueKindWithSpan;
6use super::blob_provider::*;
7use crate::data::*;
8use crate::errors::*;
9use crate::internal_prelude::*;
10use crate::manifest::ast;
11use crate::manifest::compiler::CompileErrorDiagnosticsStyle;
12use crate::manifest::diagnostic_snippets::create_snippet;
13use crate::manifest::token::Span;
14use crate::model::*;
15use crate::validation::*;
16use radix_common::address::AddressBech32Decoder;
17use radix_common::constants::*;
18use radix_common::crypto::Hash;
19use radix_common::data::manifest::model::*;
20use radix_common::data::manifest::*;
21use radix_common::data::scrypto::model::*;
22use radix_common::math::{Decimal, PreciseDecimal};
23use radix_common::prelude::CONSENSUS_MANAGER;
24use radix_common::types::NodeId;
25use radix_common::types::NonFungibleGlobalId;
26use radix_common::types::PackageAddress;
27use radix_engine_interface::blueprints::access_controller::*;
28use radix_engine_interface::blueprints::account::*;
29use radix_engine_interface::blueprints::consensus_manager::*;
30use radix_engine_interface::blueprints::identity::*;
31use radix_engine_interface::blueprints::package::*;
32use radix_engine_interface::blueprints::resource::*;
33use radix_engine_interface::object_modules::metadata::*;
34use radix_engine_interface::object_modules::role_assignment::*;
35use radix_engine_interface::object_modules::royalty::*;
36use radix_engine_interface::types::*;
37use sbor::prelude::*;
38
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub enum GeneratorErrorKind {
41 InvalidAstType {
42 expected_value_kind: ast::ValueKind,
43 actual: ast::ValueKind,
44 },
45 InvalidAstValue {
46 expected_value_kinds: Vec<ast::ValueKind>,
47 actual: ast::Value,
48 },
49 UnexpectedValueKind {
50 expected_value_kind: ast::ValueKind,
51 actual_value: ast::Value,
52 },
53 InvalidPackageAddress(String),
54 InvalidResourceAddress(String),
55 InvalidDecimal {
56 actual: String,
57 err: String,
58 },
59 InvalidPreciseDecimal {
60 actual: String,
61 err: String,
62 },
63 InvalidNonFungibleLocalId(String),
64 InvalidNonFungibleGlobalId,
65 InvalidExpression(String),
66 InvalidBlobHash {
67 actual: String,
68 err: String,
69 },
70 BlobNotFound(String),
71 InvalidBytesHex(String),
72 NameResolverError(NameResolverError),
73 IdValidationError {
74 err: ManifestIdValidationError,
75 name: Option<String>,
76 },
77 InvalidGlobalAddress(String),
78 InvalidInternalAddress(String),
79 InvalidSubTransactionId(String),
80 InstructionNotSupportedInManifestVersion,
81 ManifestBuildError(ManifestBuildError),
82 HeaderInstructionMustComeFirst,
83 IntentCannotBeUsedInValue,
84 IntentCannotBeUsedAsValueKind,
85 NamedIntentCannotBeUsedInValue,
86 NamedIntentCannotBeUsedAsValueKind,
87 ArgumentCouldNotBeReadAsExpectedType {
88 type_name: String,
89 error_message: String,
90 },
91}
92
93#[derive(Debug, Clone, PartialEq, Eq)]
94pub struct GeneratorError {
95 pub error_kind: GeneratorErrorKind,
96 pub span: Span,
97}
98
99#[derive(Debug, Clone, PartialEq, Eq)]
100pub enum NameResolverError {
101 UndefinedBucket(String),
102 UndefinedProof(String),
103 UndefinedAddressReservation(String),
104 UndefinedNamedAddress(String),
105 UndefinedIntent(String),
106 NamedAlreadyDefined(String),
107}
108
109#[derive(Default)]
110pub struct NameResolver {
111 named_buckets: IndexMap<String, ManifestBucket>,
112 named_proofs: IndexMap<String, ManifestProof>,
113 named_address_reservations: IndexMap<String, ManifestAddressReservation>,
114 named_addresses: IndexMap<String, ManifestNamedAddress>,
115 named_intents: IndexMap<String, ManifestNamedIntent>,
116}
117
118impl NameResolver {
119 pub fn new() -> Self {
120 Self::default()
121 }
122
123 pub fn insert_bucket(
124 &mut self,
125 name: String,
126 bucket_id: ManifestBucket,
127 ) -> Result<(), NameResolverError> {
128 if self.named_buckets.contains_key(&name) {
129 Err(NameResolverError::NamedAlreadyDefined(name))
130 } else {
131 self.named_buckets.insert(name, bucket_id);
132 Ok(())
133 }
134 }
135
136 pub fn insert_proof(
137 &mut self,
138 name: String,
139 proof_id: ManifestProof,
140 ) -> Result<(), NameResolverError> {
141 if self.named_proofs.contains_key(&name) {
142 Err(NameResolverError::NamedAlreadyDefined(name))
143 } else {
144 self.named_proofs.insert(name, proof_id);
145 Ok(())
146 }
147 }
148
149 pub fn insert_address_reservation(
150 &mut self,
151 name: String,
152 address_reservation_id: ManifestAddressReservation,
153 ) -> Result<(), NameResolverError> {
154 if self.named_address_reservations.contains_key(&name) {
155 Err(NameResolverError::NamedAlreadyDefined(name))
156 } else {
157 self.named_address_reservations
158 .insert(name, address_reservation_id);
159 Ok(())
160 }
161 }
162
163 pub fn insert_named_address(
164 &mut self,
165 name: String,
166 address_id: ManifestNamedAddress,
167 ) -> Result<(), NameResolverError> {
168 if self.named_addresses.contains_key(&name) {
169 Err(NameResolverError::NamedAlreadyDefined(name))
170 } else {
171 self.named_addresses.insert(name, address_id);
172 Ok(())
173 }
174 }
175
176 pub fn insert_intent(
177 &mut self,
178 name: String,
179 intent_id: ManifestNamedIntent,
180 ) -> Result<(), NameResolverError> {
181 if self.named_intents.contains_key(&name) {
182 Err(NameResolverError::NamedAlreadyDefined(name))
183 } else {
184 self.named_intents.insert(name, intent_id);
185 Ok(())
186 }
187 }
188
189 pub fn resolve_bucket(&mut self, name: &str) -> Result<ManifestBucket, NameResolverError> {
190 match self.named_buckets.get(name).cloned() {
191 Some(bucket_id) => Ok(bucket_id),
192 None => Err(NameResolverError::UndefinedBucket(name.into())),
193 }
194 }
195
196 pub fn resolve_proof(&mut self, name: &str) -> Result<ManifestProof, NameResolverError> {
197 match self.named_proofs.get(name).cloned() {
198 Some(proof_id) => Ok(proof_id),
199 None => Err(NameResolverError::UndefinedProof(name.into())),
200 }
201 }
202
203 pub fn resolve_address_reservation(
204 &mut self,
205 name: &str,
206 ) -> Result<ManifestAddressReservation, NameResolverError> {
207 match self.named_address_reservations.get(name).cloned() {
208 Some(address_reservation_id) => Ok(address_reservation_id),
209 None => Err(NameResolverError::UndefinedAddressReservation(name.into())),
210 }
211 }
212
213 pub fn resolve_named_address(
214 &mut self,
215 name: &str,
216 ) -> Result<ManifestNamedAddress, NameResolverError> {
217 match self.named_addresses.get(name).cloned() {
218 Some(address_id) => Ok(address_id),
219 None => Err(NameResolverError::UndefinedNamedAddress(name.into())),
220 }
221 }
222
223 pub fn resolve_named_intent(
224 &mut self,
225 name: &str,
226 ) -> Result<ManifestNamedIntent, NameResolverError> {
227 match self.named_intents.get(name).cloned() {
228 Some(intent_id) => Ok(intent_id),
229 None => Err(NameResolverError::UndefinedIntent(name.into())),
230 }
231 }
232
233 pub fn resolve_bucket_name(&self, bucket: ManifestBucket) -> Option<String> {
234 for (name, id) in self.named_buckets.iter() {
235 if id.eq(&bucket) {
236 return Some(name.to_string());
237 }
238 }
239 return None;
240 }
241
242 pub fn resove_proof_name(&self, proof: ManifestProof) -> Option<String> {
243 for (name, id) in self.named_proofs.iter() {
244 if id.eq(&proof) {
245 return Some(name.to_string());
246 }
247 }
248 return None;
249 }
250
251 pub fn resolve_address_reservation_name(
252 &self,
253 reservation: ManifestAddressReservation,
254 ) -> Option<String> {
255 for (name, id) in self.named_address_reservations.iter() {
256 if id.eq(&reservation) {
257 return Some(name.to_string());
258 }
259 }
260 return None;
261 }
262
263 pub fn resolve_named_address_name(&self, address: ManifestNamedAddress) -> Option<String> {
264 for (name, id) in self.named_addresses.iter() {
265 if id.eq(&address) {
266 return Some(name.to_string());
267 }
268 }
269 return None;
270 }
271
272 pub fn resolve_intent_name(&self, address: ManifestNamedIntent) -> Option<String> {
273 for (name, id) in self.named_intents.iter() {
274 if id.eq(&address) {
275 return Some(name.to_string());
276 }
277 }
278 return None;
279 }
280
281 pub fn into_known_names(self) -> KnownManifestObjectNames {
282 KnownManifestObjectNames {
283 bucket_names: self
284 .named_buckets
285 .into_iter()
286 .map(|(name, value)| (value, name))
287 .collect(),
288 proof_names: self
289 .named_proofs
290 .into_iter()
291 .map(|(name, value)| (value, name))
292 .collect(),
293 address_reservation_names: self
294 .named_address_reservations
295 .into_iter()
296 .map(|(name, value)| (value, name))
297 .collect(),
298 address_names: self
299 .named_addresses
300 .into_iter()
301 .map(|(name, value)| (value, name))
302 .collect(),
303 intent_names: self
304 .named_intents
305 .into_iter()
306 .map(|(name, value)| (value, name))
307 .collect(),
308 }
309 }
310}
311
312pub fn generate_manifest<B, M: BuildableManifest>(
313 instructions: &[ast::InstructionWithSpan],
314 address_bech32_decoder: &AddressBech32Decoder,
315 transaction_bech32_decoder: &TransactionHashBech32Decoder,
316 blobs: B,
317) -> Result<M, GeneratorError>
318where
319 B: IsBlobProvider,
320{
321 let mut id_validator = BasicManifestValidator::new();
322 let mut name_resolver = NameResolver::new();
323
324 let mut manifest = M::default();
325
326 let mut instructions_iter = instructions.iter().peekable();
327
328 generate_pseudo_instructions(
329 &mut manifest,
330 &mut instructions_iter,
331 &mut id_validator,
332 &mut name_resolver,
333 address_bech32_decoder,
334 transaction_bech32_decoder,
335 )?;
336
337 for instruction in instructions_iter {
338 let any_instruction = generate_instruction(
339 instruction,
340 &mut id_validator,
341 &mut name_resolver,
342 address_bech32_decoder,
343 &blobs,
344 )?;
345 let valid_instruction = any_instruction.try_into().map_err(|_| GeneratorError {
346 span: instruction.span,
347 error_kind: GeneratorErrorKind::InstructionNotSupportedInManifestVersion,
348 })?;
349 manifest.add_instruction(valid_instruction);
350 }
351 for (hash, blob_content) in blobs.blobs() {
352 manifest.add_blob(hash, blob_content);
353 }
354 manifest.set_names(name_resolver.into_known_names());
355
356 Ok(manifest)
357}
358
359fn generate_pseudo_instructions(
360 manifest: &mut impl BuildableManifest,
361 instructions_iter: &mut Peekable<core::slice::Iter<ast::InstructionWithSpan>>,
362 id_validator: &mut BasicManifestValidator,
363 name_resolver: &mut NameResolver,
364 address_bech32_decoder: &AddressBech32Decoder,
365 transaction_bech32_decoder: &TransactionHashBech32Decoder,
366) -> Result<(), GeneratorError> {
367 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.clone()))
670 .map_err(|err| generate_id_validation_error(resolver, err, span))?;
671 declare_proof(new_proof, resolver, proof_id)?;
672
673 CreateProofFromBucketOfAmount { bucket_id, amount }.into()
674 }
675 ast::Instruction::CreateProofFromBucketOfNonFungibles {
676 bucket,
677 ids,
678 new_proof,
679 } => {
680 let (bucket_id, span) = generate_bucket(bucket, resolver)?;
681 let ids = generate_non_fungible_local_ids(ids)?;
682 let proof_id = id_validator
683 .new_proof(ProofKind::BucketProof(bucket_id.clone()))
684 .map_err(|err| generate_id_validation_error(resolver, err, span))?;
685 declare_proof(new_proof, resolver, proof_id)?;
686
687 CreateProofFromBucketOfNonFungibles { bucket_id, ids }.into()
688 }
689 ast::Instruction::CreateProofFromBucketOfAll { bucket, new_proof } => {
690 let (bucket_id, span) = generate_bucket(bucket, resolver)?;
691 let proof_id = id_validator
692 .new_proof(ProofKind::BucketProof(bucket_id.clone()))
693 .map_err(|err| generate_id_validation_error(resolver, err, span))?;
694 declare_proof(new_proof, resolver, proof_id)?;
695
696 CreateProofFromBucketOfAll { bucket_id }.into()
697 }
698 ast::Instruction::CreateProofFromAuthZoneOfAmount {
699 resource_address,
700 amount,
701 new_proof,
702 } => {
703 let resource_address =
704 generate_resource_address(resource_address, address_bech32_decoder)?;
705 let amount = generate_decimal(amount)?;
706 let proof_id = id_validator
707 .new_proof(ProofKind::AuthZoneProof)
708 .map_err(|err| generate_id_validation_error(resolver, err, instruction.span))?;
709 declare_proof(new_proof, resolver, proof_id)?;
710
711 CreateProofFromAuthZoneOfAmount {
712 amount,
713 resource_address,
714 }
715 .into()
716 }
717 ast::Instruction::CreateProofFromAuthZoneOfNonFungibles {
718 resource_address,
719 ids,
720 new_proof,
721 } => {
722 let resource_address =
723 generate_resource_address(resource_address, address_bech32_decoder)?;
724 let ids = generate_non_fungible_local_ids(ids)?;
725 let proof_id = id_validator
726 .new_proof(ProofKind::AuthZoneProof)
727 .map_err(|err| generate_id_validation_error(resolver, err, instruction.span))?;
728 declare_proof(new_proof, resolver, proof_id)?;
729
730 CreateProofFromAuthZoneOfNonFungibles {
731 ids,
732 resource_address,
733 }
734 .into()
735 }
736 ast::Instruction::CreateProofFromAuthZoneOfAll {
737 resource_address,
738 new_proof,
739 } => {
740 let resource_address =
741 generate_resource_address(resource_address, address_bech32_decoder)?;
742 let proof_id = id_validator
743 .new_proof(ProofKind::AuthZoneProof)
744 .map_err(|err| generate_id_validation_error(resolver, err, instruction.span))?;
745 declare_proof(new_proof, resolver, proof_id)?;
746
747 CreateProofFromAuthZoneOfAll { resource_address }.into()
748 }
749 ast::Instruction::CloneProof { proof, new_proof } => {
750 let (proof_id, span) = generate_proof(proof, resolver)?;
751 let proof_id2 = id_validator
752 .clone_proof(&proof_id)
753 .map_err(|err| generate_id_validation_error(resolver, err, span))?;
754 declare_proof(new_proof, resolver, proof_id2)?;
755
756 CloneProof { proof_id }.into()
757 }
758 ast::Instruction::DropProof { proof } => {
759 let (proof_id, span) = generate_proof(proof, resolver)?;
760 id_validator
761 .drop_proof(&proof_id)
762 .map_err(|err| generate_id_validation_error(resolver, err, span))?;
763 DropProof { proof_id }.into()
764 }
765 ast::Instruction::PushToAuthZone { proof } => {
766 let (proof_id, span) = generate_proof(proof, resolver)?;
767 id_validator
768 .drop_proof(&proof_id)
769 .map_err(|err| generate_id_validation_error(resolver, err, span))?;
770 PushToAuthZone { proof_id }.into()
771 }
772 ast::Instruction::PopFromAuthZone { new_proof } => {
773 let proof_id = id_validator
774 .new_proof(ProofKind::AuthZoneProof)
775 .map_err(|err| generate_id_validation_error(resolver, err, instruction.span))?;
776 declare_proof(new_proof, resolver, proof_id)?;
777
778 PopFromAuthZone.into()
779 }
780 ast::Instruction::DropAuthZoneProofs => DropAuthZoneProofs.into(),
781 ast::Instruction::DropAuthZoneRegularProofs => DropAuthZoneRegularProofs.into(),
782 ast::Instruction::DropAuthZoneSignatureProofs => DropAuthZoneSignatureProofs.into(),
783 ast::Instruction::DropNamedProofs => {
784 id_validator
785 .drop_all_named_proofs()
786 .map_err(|err| generate_id_validation_error(resolver, err, instruction.span))?;
787 DropNamedProofs.into()
788 }
789
790 ast::Instruction::DropAllProofs => {
791 id_validator
792 .drop_all_named_proofs()
793 .map_err(|err| generate_id_validation_error(resolver, err, instruction.span))?;
794 DropAllProofs.into()
795 }
796
797 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 return Err(GeneratorError {
1255 error_kind: GeneratorErrorKind::InvalidGlobalAddress(s.into()),
1256 span: inner.span,
1257 });
1258 }
1259 v => invalid_type!(inner.span, v, ast::ValueKind::String),
1260 },
1261 v => invalid_type!(value.span, v, ast::ValueKind::Address),
1262 }
1263}
1264
1265fn generate_package_address(
1266 value: &ast::ValueWithSpan,
1267 address_bech32_decoder: &AddressBech32Decoder,
1268) -> Result<PackageAddress, GeneratorError> {
1269 match &value.value {
1270 ast::Value::Address(inner) => match &inner.value {
1271 ast::Value::String(s) => {
1272 if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1275 if let Ok(address) = PackageAddress::try_from(full_data.as_ref()) {
1276 return Ok(address);
1277 }
1278 }
1279 return Err(GeneratorError {
1280 error_kind: GeneratorErrorKind::InvalidPackageAddress(s.into()),
1281 span: inner.span,
1282 });
1283 }
1284 v => invalid_type!(inner.span, v, ast::ValueKind::String),
1285 },
1286 v => invalid_type!(value.span, v, ast::ValueKind::Address),
1287 }
1288}
1289
1290fn generate_resource_address(
1291 value: &ast::ValueWithSpan,
1292 address_bech32_decoder: &AddressBech32Decoder,
1293) -> Result<ResourceAddress, GeneratorError> {
1294 match &value.value {
1295 ast::Value::Address(inner) => match &inner.value {
1296 ast::Value::String(s) => {
1297 if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1298 if let Ok(address) = ResourceAddress::try_from(full_data.as_ref()) {
1299 return Ok(address);
1300 }
1301 }
1302 return Err(GeneratorError {
1303 error_kind: GeneratorErrorKind::InvalidResourceAddress(s.into()),
1304 span: inner.span,
1305 });
1306 }
1307 v => invalid_type!(inner.span, v, ast::ValueKind::String),
1308 },
1309 v => invalid_type!(value.span, v, ast::ValueKind::Address),
1310 }
1311}
1312
1313fn generate_dynamic_global_address(
1314 value: &ast::ValueWithSpan,
1315 address_bech32_decoder: &AddressBech32Decoder,
1316 resolver: &mut NameResolver,
1317) -> Result<ManifestGlobalAddress, GeneratorError> {
1318 match &value.value {
1319 ast::Value::Address(inner) => match &inner.value {
1320 ast::Value::String(s) => {
1321 if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1322 if let Ok(address) = GlobalAddress::try_from(full_data.as_ref()) {
1323 return Ok(ManifestGlobalAddress::Static(address));
1324 }
1325 }
1326 return Err(GeneratorError {
1327 error_kind: GeneratorErrorKind::InvalidGlobalAddress(s.into()),
1328 span: inner.span,
1329 });
1330 }
1331 v => return invalid_type!(inner.span, v, ast::ValueKind::String),
1332 },
1333 ast::Value::NamedAddress(inner) => {
1334 match &inner.value {
1335 ast::Value::U32(n) => Ok(ManifestGlobalAddress::Named(ManifestNamedAddress(*n))),
1336 ast::Value::String(s) => resolver
1337 .resolve_named_address(&s)
1338 .map(Into::into)
1339 .map_err(|err| GeneratorError {
1340 error_kind: GeneratorErrorKind::NameResolverError(err),
1341 span: inner.span,
1342 }),
1343 v => invalid_type!(value.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1344 }
1345 }
1346 v => invalid_type!(
1347 value.span,
1348 v,
1349 ast::ValueKind::Address,
1350 ast::ValueKind::NamedAddress
1351 ),
1352 }
1353}
1354
1355fn generate_internal_address(
1356 value: &ast::ValueWithSpan,
1357 address_bech32_decoder: &AddressBech32Decoder,
1358) -> Result<InternalAddress, GeneratorError> {
1359 match &value.value {
1360 ast::Value::Address(inner) => match &inner.value {
1361 ast::Value::String(s) => {
1362 if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1363 if let Ok(address) = InternalAddress::try_from(full_data.as_ref()) {
1364 return Ok(address);
1365 }
1366 }
1367 return Err(GeneratorError {
1368 error_kind: GeneratorErrorKind::InvalidInternalAddress(s.into()),
1369 span: inner.span,
1370 });
1371 }
1372 v => return invalid_type!(inner.span, v, ast::ValueKind::String),
1373 },
1374 v => invalid_type!(value.span, v, ast::ValueKind::Address),
1375 }
1376}
1377
1378fn generate_dynamic_package_address(
1379 value: &ast::ValueWithSpan,
1380 address_bech32_decoder: &AddressBech32Decoder,
1381 resolver: &mut NameResolver,
1382) -> Result<ManifestPackageAddress, GeneratorError> {
1383 match &value.value {
1384 ast::Value::Address(inner) => match &inner.value {
1385 ast::Value::String(s) => {
1386 if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1387 if let Ok(address) = PackageAddress::try_from(full_data.as_ref()) {
1388 return Ok(ManifestPackageAddress::Static(address));
1389 }
1390 }
1391 return Err(GeneratorError {
1392 error_kind: GeneratorErrorKind::InvalidPackageAddress(s.into()),
1393 span: inner.span,
1394 });
1395 }
1396 v => return invalid_type!(inner.span, v, ast::ValueKind::String),
1397 },
1398 ast::Value::NamedAddress(inner) => {
1399 match &inner.value {
1400 ast::Value::U32(n) => Ok(ManifestPackageAddress::Named(ManifestNamedAddress(*n))),
1401 ast::Value::String(s) => resolver
1402 .resolve_named_address(&s)
1403 .map(Into::into)
1404 .map_err(|err| GeneratorError {
1405 error_kind: GeneratorErrorKind::NameResolverError(err),
1406 span: inner.span,
1407 }),
1408 v => invalid_type!(value.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1409 }
1410 }
1411 v => invalid_type!(
1412 value.span,
1413 v,
1414 ast::ValueKind::Address,
1415 ast::ValueKind::NamedAddress
1416 ),
1417 }
1418}
1419
1420fn declare_bucket(
1421 value: &ast::ValueWithSpan,
1422 resolver: &mut NameResolver,
1423 bucket_id: ManifestBucket,
1424) -> Result<(), GeneratorError> {
1425 match &value.value {
1426 ast::Value::Bucket(inner) => match &inner.value {
1427 ast::Value::String(name) => resolver
1428 .insert_bucket(name.to_string(), bucket_id)
1429 .map_err(|err| GeneratorError {
1430 error_kind: GeneratorErrorKind::NameResolverError(err),
1431 span: inner.span,
1432 }),
1433 v => invalid_type!(inner.span, v, ast::ValueKind::String),
1434 },
1435 v => invalid_type!(value.span, v, ast::ValueKind::Bucket),
1436 }
1437}
1438
1439fn generate_bucket(
1440 value: &ast::ValueWithSpan,
1441 resolver: &mut NameResolver,
1442) -> Result<(ManifestBucket, Span), GeneratorError> {
1443 match &value.value {
1444 ast::Value::Bucket(inner) => {
1445 let bucket = match &inner.value {
1446 ast::Value::U32(n) => Ok(ManifestBucket(*n)),
1447 ast::Value::String(s) => {
1448 resolver.resolve_bucket(&s).map_err(|err| GeneratorError {
1449 error_kind: GeneratorErrorKind::NameResolverError(err),
1450 span: inner.span,
1451 })
1452 }
1453 v => invalid_type!(inner.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1454 }?;
1455 Ok((bucket, inner.span))
1456 }
1457 v => invalid_type!(value.span, v, ast::ValueKind::Bucket),
1458 }
1459}
1460
1461fn declare_proof(
1462 value: &ast::ValueWithSpan,
1463 resolver: &mut NameResolver,
1464 proof_id: ManifestProof,
1465) -> Result<(), GeneratorError> {
1466 match &value.value {
1467 ast::Value::Proof(inner) => {
1468 match &inner.value {
1469 ast::Value::String(name) => resolver
1470 .insert_proof(name.to_string(), proof_id)
1471 .map_err(|err| GeneratorError {
1472 error_kind: GeneratorErrorKind::NameResolverError(err),
1473 span: inner.span,
1474 }),
1475 v => invalid_type!(inner.span, v, ast::ValueKind::String),
1476 }
1477 }
1478 v => invalid_type!(value.span, v, ast::ValueKind::Proof),
1479 }
1480}
1481
1482fn declare_address_reservation(
1483 value: &ast::ValueWithSpan,
1484 resolver: &mut NameResolver,
1485 address_reservation_id: ManifestAddressReservation,
1486) -> Result<(), GeneratorError> {
1487 match &value.value {
1488 ast::Value::AddressReservation(inner) => match &inner.value {
1489 ast::Value::String(name) => resolver
1490 .insert_address_reservation(name.to_string(), address_reservation_id)
1491 .map_err(|err| GeneratorError {
1492 error_kind: GeneratorErrorKind::NameResolverError(err),
1493 span: inner.span,
1494 }),
1495 v => invalid_type!(inner.span, v, ast::ValueKind::String),
1496 },
1497 v => invalid_type!(value.span, v, ast::ValueKind::AddressReservation),
1498 }
1499}
1500
1501fn declare_named_address(
1502 value: &ast::ValueWithSpan,
1503 resolver: &mut NameResolver,
1504 address_id: ManifestNamedAddress,
1505) -> Result<(), GeneratorError> {
1506 match &value.value {
1507 ast::Value::NamedAddress(inner) => match &inner.value {
1508 ast::Value::String(name) => resolver
1509 .insert_named_address(name.to_string(), address_id)
1510 .map_err(|err| GeneratorError {
1511 error_kind: GeneratorErrorKind::NameResolverError(err),
1512 span: inner.span,
1513 }),
1514 v => invalid_type!(inner.span, v, ast::ValueKind::String),
1515 },
1516 v => invalid_type!(value.span, v, ast::ValueKind::NamedAddress),
1517 }
1518}
1519
1520fn declare_named_intent(
1521 value: &ast::ValueWithSpan,
1522 resolver: &mut NameResolver,
1523 intent_id: ManifestNamedIntent,
1524) -> Result<(), GeneratorError> {
1525 match &value.value {
1526 ast::Value::NamedIntent(inner) => match &inner.value {
1527 ast::Value::String(name) => resolver
1528 .insert_intent(name.to_string(), intent_id)
1529 .map_err(|err| GeneratorError {
1530 error_kind: GeneratorErrorKind::NameResolverError(err),
1531 span: inner.span,
1532 }),
1533 v => invalid_type!(inner.span, v, ast::ValueKind::String),
1534 },
1535 v => invalid_type!(value.span, v, ast::ValueKind::NamedIntent),
1536 }
1537}
1538
1539fn generate_named_intent(
1540 value: &ast::ValueWithSpan,
1541 resolver: &mut NameResolver,
1542) -> Result<ManifestNamedIntent, GeneratorError> {
1543 match &value.value {
1544 ast::Value::NamedIntent(inner) => {
1545 let out = match &inner.value {
1546 ast::Value::String(s) => {
1548 resolver
1549 .resolve_named_intent(&s)
1550 .map_err(|err| GeneratorError {
1551 error_kind: GeneratorErrorKind::NameResolverError(err),
1552 span: inner.span,
1553 })
1554 }
1555 v => invalid_type!(inner.span, v, ast::ValueKind::String),
1556 }?;
1557 Ok(out)
1558 }
1559 v => invalid_type!(value.span, v, ast::ValueKind::NamedIntent),
1560 }
1561}
1562
1563fn generate_proof(
1564 value: &ast::ValueWithSpan,
1565 resolver: &mut NameResolver,
1566) -> Result<(ManifestProof, Span), GeneratorError> {
1567 match &value.value {
1568 ast::Value::Proof(inner) => {
1569 let proof = match &inner.value {
1570 ast::Value::U32(n) => Ok(ManifestProof(*n)),
1571 ast::Value::String(s) => resolver.resolve_proof(&s).map_err(|err| GeneratorError {
1572 error_kind: GeneratorErrorKind::NameResolverError(err),
1573 span: inner.span,
1574 }),
1575 v => invalid_type!(inner.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1576 }?;
1577 Ok((proof, inner.span))
1578 }
1579 v => invalid_type!(value.span, v, ast::ValueKind::Proof),
1580 }
1581}
1582
1583fn generate_address_reservation(
1584 value: &ast::ValueWithSpan,
1585 resolver: &mut NameResolver,
1586) -> Result<ManifestAddressReservation, GeneratorError> {
1587 match &value.value {
1588 ast::Value::AddressReservation(inner) => match &inner.value {
1589 ast::Value::U32(n) => Ok(ManifestAddressReservation(*n)),
1590 ast::Value::String(s) => {
1591 resolver
1592 .resolve_address_reservation(&s)
1593 .map_err(|err| GeneratorError {
1594 error_kind: GeneratorErrorKind::NameResolverError(err),
1595 span: inner.span,
1596 })
1597 }
1598 v => invalid_type!(inner.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1599 },
1600 v => invalid_type!(value.span, v, ast::ValueKind::AddressReservation),
1601 }
1602}
1603
1604fn generate_static_address(
1605 value: &ast::ValueWithSpan,
1606 address_bech32_decoder: &AddressBech32Decoder,
1607) -> Result<ManifestAddress, GeneratorError> {
1608 match &value.value {
1609 ast::Value::Address(inner) => match &inner.value {
1610 ast::Value::String(s) => {
1611 if let Ok((_, full_data)) = address_bech32_decoder.validate_and_decode(s) {
1613 if full_data.len() == NodeId::LENGTH {
1615 return Ok(ManifestAddress::Static(NodeId(
1616 full_data.try_into().unwrap(),
1617 )));
1618 }
1619 }
1620 return Err(GeneratorError {
1621 error_kind: GeneratorErrorKind::InvalidGlobalAddress(s.into()),
1622 span: inner.span,
1623 });
1624 }
1625 v => return invalid_type!(inner.span, v, ast::ValueKind::String),
1626 },
1627 v => invalid_type!(value.span, v, ast::ValueKind::Address),
1628 }
1629}
1630
1631fn generate_named_address(
1632 value: &ast::ValueWithSpan,
1633 resolver: &mut NameResolver,
1634) -> Result<ManifestAddress, GeneratorError> {
1635 match &value.value {
1636 ast::Value::NamedAddress(inner) => match &inner.value {
1637 ast::Value::U32(n) => Ok(ManifestAddress::Named(ManifestNamedAddress(*n))),
1638 ast::Value::String(s) => resolver
1639 .resolve_named_address(&s)
1640 .map(|x| ManifestAddress::Named(x))
1641 .map_err(|err| GeneratorError {
1642 error_kind: GeneratorErrorKind::NameResolverError(err),
1643 span: inner.span,
1644 }),
1645 v => invalid_type!(inner.span, v, ast::ValueKind::U32, ast::ValueKind::String),
1646 },
1647 v => invalid_type!(value.span, v, ast::ValueKind::NamedAddress),
1648 }
1649}
1650
1651fn generate_non_fungible_local_id(
1652 value: &ast::ValueWithSpan,
1653) -> Result<NonFungibleLocalId, GeneratorError> {
1654 match &value.value {
1655 ast::Value::NonFungibleLocalId(inner) => match &inner.value {
1656 ast::Value::String(s) => NonFungibleLocalId::from_str(s)
1657 .map_err(|_| GeneratorError {
1659 error_kind: GeneratorErrorKind::InvalidNonFungibleLocalId(s.into()),
1660 span: inner.span,
1661 }),
1662 v => invalid_type!(inner.span, v, ast::ValueKind::String)?,
1663 },
1664 v => invalid_type!(value.span, v, ast::ValueKind::NonFungibleLocalId),
1665 }
1666}
1667
1668fn generate_expression(value: &ast::ValueWithSpan) -> Result<ManifestExpression, GeneratorError> {
1669 match &value.value {
1670 ast::Value::Expression(inner) => match &inner.value {
1671 ast::Value::String(s) => match s.as_str() {
1672 "ENTIRE_WORKTOP" => Ok(ManifestExpression::EntireWorktop),
1673 "ENTIRE_AUTH_ZONE" => Ok(ManifestExpression::EntireAuthZone),
1674 _ => Err(GeneratorError {
1675 error_kind: GeneratorErrorKind::InvalidExpression(s.into()),
1676 span: inner.span,
1677 }),
1678 },
1679 v => invalid_type!(inner.span, v, ast::ValueKind::String),
1680 },
1681 v => invalid_type!(value.span, v, ast::ValueKind::Expression),
1682 }
1683}
1684
1685fn translate_parse_hash_error(err: ParseHashError) -> String {
1686 match err {
1687 ParseHashError::InvalidHex(_) => "invalid hex value".to_string(),
1688 ParseHashError::InvalidLength { actual, expected } => {
1689 format!("invalid hash length {}, expected {}", actual, expected)
1690 }
1691 }
1692}
1693
1694fn generate_blob<B>(
1695 value: &ast::ValueWithSpan,
1696 blobs: &B,
1697) -> Result<ManifestBlobRef, GeneratorError>
1698where
1699 B: IsBlobProvider,
1700{
1701 match &value.value {
1702 ast::Value::Blob(inner) => match &inner.value {
1703 ast::Value::String(s) => {
1704 let hash = Hash::from_str(s).map_err(|err| GeneratorError {
1705 error_kind: GeneratorErrorKind::InvalidBlobHash {
1706 actual: s.to_string(),
1707 err: translate_parse_hash_error(err),
1708 },
1709 span: inner.span,
1710 })?;
1711 blobs.get_blob(&hash).ok_or(GeneratorError {
1712 error_kind: GeneratorErrorKind::BlobNotFound(s.clone()),
1713 span: inner.span,
1714 })?;
1715 Ok(ManifestBlobRef(hash.0))
1716 }
1717 v => invalid_type!(inner.span, v, ast::ValueKind::String),
1718 },
1719 v => invalid_type!(value.span, v, ast::ValueKind::Blob),
1720 }
1721}
1722
1723fn generate_non_fungible_local_ids(
1724 value: &ast::ValueWithSpan,
1725) -> Result<Vec<NonFungibleLocalId>, GeneratorError> {
1726 match &value.value {
1727 ast::Value::Array(kind, values) => {
1728 if kind.value_kind != ast::ValueKind::NonFungibleLocalId {
1729 return Err(GeneratorError {
1730 error_kind: GeneratorErrorKind::InvalidAstType {
1731 expected_value_kind: ast::ValueKind::NonFungibleLocalId,
1732 actual: kind.value_kind.clone(),
1733 },
1734 span: kind.span,
1735 });
1736 }
1737
1738 values
1739 .iter()
1740 .map(|v| generate_non_fungible_local_id(v))
1741 .collect()
1742 }
1743 v => invalid_type!(value.span, v, ast::ValueKind::Array),
1744 }
1745}
1746
1747fn generate_byte_vec_from_hex(value: &ast::ValueWithSpan) -> Result<Vec<u8>, GeneratorError> {
1748 let bytes = match &value.value {
1749 ast::Value::String(s) => hex::decode(s).map_err(|_| GeneratorError {
1750 error_kind: GeneratorErrorKind::InvalidBytesHex(s.to_string()),
1751 span: value.span,
1752 })?,
1753 v => invalid_type!(value.span, v, ast::ValueKind::String)?,
1754 };
1755 Ok(bytes)
1756}
1757
1758fn generate_subintent_hash(
1759 decoder: &TransactionHashBech32Decoder,
1760 value: &ast::ValueWithSpan,
1761) -> Result<SubintentHash, GeneratorError> {
1762 match &value.value {
1763 ast::Value::Intent(inner) => match &inner.value {
1764 ast::Value::String(s) => decoder.validate_and_decode(s).map_err(|_| GeneratorError {
1765 error_kind: GeneratorErrorKind::InvalidSubTransactionId(s.into()),
1766 span: inner.span,
1767 }),
1768 v => invalid_type!(inner.span, v, ast::ValueKind::String),
1769 },
1770 v => invalid_type!(value.span, v, ast::ValueKind::Intent),
1771 }
1772}
1773
1774pub fn generate_typed_value<T: ManifestDecode + ScryptoDescribe, B>(
1775 value_with_span: &ast::ValueWithSpan,
1776 resolver: &mut NameResolver,
1777 address_bech32_decoder: &AddressBech32Decoder,
1778 blobs: &B,
1779) -> Result<T, GeneratorError>
1780where
1781 B: IsBlobProvider,
1782{
1783 let value = generate_value(
1784 value_with_span,
1785 None,
1786 resolver,
1787 address_bech32_decoder,
1788 blobs,
1789 )?;
1790 let encoded = manifest_encode(&value).map_err(|encode_error| GeneratorError {
1791 span: value_with_span.span,
1792 error_kind: GeneratorErrorKind::ArgumentCouldNotBeReadAsExpectedType {
1793 type_name: core::any::type_name::<T>().to_string(),
1794 error_message: format!("{encode_error:?}"),
1795 },
1796 })?;
1797 let decoded =
1798 manifest_decode_with_nice_error(&encoded).map_err(|error_message| GeneratorError {
1799 span: value_with_span.span,
1800 error_kind: GeneratorErrorKind::ArgumentCouldNotBeReadAsExpectedType {
1801 type_name: core::any::type_name::<T>().to_string(),
1802 error_message,
1803 },
1804 })?;
1805 Ok(decoded)
1806}
1807
1808pub fn generate_value<B>(
1809 value_with_span: &ast::ValueWithSpan,
1810 expected_value_kind: Option<&ast::ValueKindWithSpan>,
1811 resolver: &mut NameResolver,
1812 address_bech32_decoder: &AddressBech32Decoder,
1813 blobs: &B,
1814) -> Result<ManifestValue, GeneratorError>
1815where
1816 B: IsBlobProvider,
1817{
1818 if let Some(value_kind) = expected_value_kind {
1819 if value_kind.sbor_value_kind() != value_with_span.value_kind().sbor_value_kind() {
1824 return Err(GeneratorError {
1825 span: value_with_span.span,
1826 error_kind: GeneratorErrorKind::UnexpectedValueKind {
1827 expected_value_kind: value_kind.value_kind,
1828 actual_value: value_with_span.value.clone(),
1829 },
1830 });
1831 }
1832 }
1833
1834 match &value_with_span.value {
1835 ast::Value::Bool(value) => Ok(Value::Bool { value: *value }),
1839 ast::Value::I8(value) => Ok(Value::I8 { value: *value }),
1840 ast::Value::I16(value) => Ok(Value::I16 { value: *value }),
1841 ast::Value::I32(value) => Ok(Value::I32 { value: *value }),
1842 ast::Value::I64(value) => Ok(Value::I64 { value: *value }),
1843 ast::Value::I128(value) => Ok(Value::I128 { value: *value }),
1844 ast::Value::U8(value) => Ok(Value::U8 { value: *value }),
1845 ast::Value::U16(value) => Ok(Value::U16 { value: *value }),
1846 ast::Value::U32(value) => Ok(Value::U32 { value: *value }),
1847 ast::Value::U64(value) => Ok(Value::U64 { value: *value }),
1848 ast::Value::U128(value) => Ok(Value::U128 { value: *value }),
1849 ast::Value::String(value) => Ok(Value::String {
1850 value: value.clone(),
1851 }),
1852 ast::Value::Tuple(fields) => Ok(Value::Tuple {
1853 fields: generate_singletons(&fields, None, resolver, address_bech32_decoder, blobs)?,
1854 }),
1855 ast::Value::Enum(discriminator, fields) => Ok(Value::Enum {
1856 discriminator: discriminator.clone(),
1857 fields: generate_singletons(&fields, None, resolver, address_bech32_decoder, blobs)?,
1858 }),
1859 ast::Value::Array(element_type, elements) => {
1860 let element_value_kind = element_type.sbor_value_kind()?;
1861 Ok(Value::Array {
1862 element_value_kind,
1863 elements: generate_singletons(
1864 &elements,
1865 Some(element_type),
1866 resolver,
1867 address_bech32_decoder,
1868 blobs,
1869 )?,
1870 })
1871 }
1872 ast::Value::Map(key_type, value_type, entries) => {
1873 let key_value_kind = key_type.sbor_value_kind()?;
1874 let value_value_kind = value_type.sbor_value_kind()?;
1875 Ok(Value::Map {
1876 key_value_kind,
1877 value_value_kind,
1878 entries: generate_kv_entries(
1879 &entries,
1880 &key_type,
1881 &value_type,
1882 resolver,
1883 address_bech32_decoder,
1884 blobs,
1885 )?,
1886 })
1887 }
1888 ast::Value::Some(value) => Ok(Value::Enum {
1892 discriminator: OPTION_VARIANT_SOME,
1893 fields: vec![generate_value(
1894 &value,
1895 None,
1896 resolver,
1897 address_bech32_decoder,
1898 blobs,
1899 )?],
1900 }),
1901 ast::Value::None => Ok(Value::Enum {
1902 discriminator: OPTION_VARIANT_NONE,
1903 fields: vec![],
1904 }),
1905 ast::Value::Ok(value) => Ok(Value::Enum {
1906 discriminator: RESULT_VARIANT_OK,
1907 fields: vec![generate_value(
1908 &value,
1909 None,
1910 resolver,
1911 address_bech32_decoder,
1912 blobs,
1913 )?],
1914 }),
1915 ast::Value::Err(value) => Ok(Value::Enum {
1916 discriminator: RESULT_VARIANT_ERR,
1917 fields: vec![generate_value(
1918 &value,
1919 None,
1920 resolver,
1921 address_bech32_decoder,
1922 blobs,
1923 )?],
1924 }),
1925 ast::Value::Bytes(value) => {
1926 let bytes = generate_byte_vec_from_hex(&value)?;
1927 Ok(Value::Array {
1928 element_value_kind: ValueKind::U8,
1929 elements: bytes.iter().map(|i| Value::U8 { value: *i }).collect(),
1930 })
1931 }
1932 ast::Value::NonFungibleGlobalId(value) => {
1933 let global_id = match &value.value {
1934 ast::Value::String(s) => NonFungibleGlobalId::try_from_canonical_string(
1935 address_bech32_decoder,
1936 s.as_str(),
1937 )
1938 .map_err(|_| GeneratorError {
1939 error_kind: GeneratorErrorKind::InvalidNonFungibleGlobalId,
1940 span: value.span,
1941 }),
1942 v => invalid_type!(value.span, v, ast::ValueKind::String)?,
1943 }?;
1944 Ok(Value::Tuple {
1945 fields: vec![
1946 Value::Custom {
1947 value: ManifestCustomValue::Address(ManifestAddress::Static(
1948 global_id.resource_address().into(),
1949 )),
1950 },
1951 Value::Custom {
1952 value: ManifestCustomValue::NonFungibleLocalId(from_non_fungible_local_id(
1953 global_id.local_id().clone(),
1954 )),
1955 },
1956 ],
1957 })
1958 }
1959 ast::Value::Address(_) => generate_static_address(value_with_span, address_bech32_decoder)
1963 .map(|v| Value::Custom {
1964 value: ManifestCustomValue::Address(v),
1965 }),
1966 ast::Value::NamedAddress(_) => {
1967 generate_named_address(value_with_span, resolver).map(|v| Value::Custom {
1968 value: ManifestCustomValue::Address(v),
1969 })
1970 }
1971 ast::Value::Bucket(_) => {
1972 generate_bucket(value_with_span, resolver).map(|(v, _span)| Value::Custom {
1973 value: ManifestCustomValue::Bucket(v),
1974 })
1975 }
1976 ast::Value::Proof(_) => {
1977 generate_proof(value_with_span, resolver).map(|(v, _span)| Value::Custom {
1978 value: ManifestCustomValue::Proof(v),
1979 })
1980 }
1981 ast::Value::Expression(_) => generate_expression(value_with_span).map(|v| Value::Custom {
1982 value: ManifestCustomValue::Expression(v),
1983 }),
1984 ast::Value::Blob(_) => generate_blob(value_with_span, blobs).map(|v| Value::Custom {
1985 value: ManifestCustomValue::Blob(v),
1986 }),
1987 ast::Value::Decimal(_) => generate_decimal(value_with_span).map(|v| Value::Custom {
1988 value: ManifestCustomValue::Decimal(from_decimal(v)),
1989 }),
1990 ast::Value::PreciseDecimal(_) => {
1991 generate_precise_decimal(value_with_span).map(|v| Value::Custom {
1992 value: ManifestCustomValue::PreciseDecimal(from_precise_decimal(v)),
1993 })
1994 }
1995 ast::Value::NonFungibleLocalId(_) => {
1996 generate_non_fungible_local_id(value_with_span).map(|v| Value::Custom {
1997 value: ManifestCustomValue::NonFungibleLocalId(from_non_fungible_local_id(v)),
1998 })
1999 }
2000 ast::Value::AddressReservation(_) => {
2001 generate_address_reservation(value_with_span, resolver).map(|v| Value::Custom {
2002 value: ManifestCustomValue::AddressReservation(v),
2003 })
2004 }
2005 ast::Value::NamedIntent(_) => {
2006 return Err(GeneratorError {
2007 error_kind: GeneratorErrorKind::NamedIntentCannotBeUsedInValue,
2008 span: value_with_span.span,
2009 });
2010 }
2011 ast::Value::Intent(_) => {
2012 return Err(GeneratorError {
2013 error_kind: GeneratorErrorKind::IntentCannotBeUsedInValue,
2014 span: value_with_span.span,
2015 });
2016 }
2017 }
2018}
2019
2020fn generate_singletons<B>(
2021 elements: &Vec<ast::ValueWithSpan>,
2022 expected_value_kind: Option<&ast::ValueKindWithSpan>,
2023 resolver: &mut NameResolver,
2024 address_bech32_decoder: &AddressBech32Decoder,
2025 blobs: &B,
2026) -> Result<Vec<ManifestValue>, GeneratorError>
2027where
2028 B: IsBlobProvider,
2029{
2030 let mut result = vec![];
2031 for element in elements {
2032 result.push(generate_value(
2033 element,
2034 expected_value_kind,
2035 resolver,
2036 address_bech32_decoder,
2037 blobs,
2038 )?);
2039 }
2040 Ok(result)
2041}
2042
2043fn generate_kv_entries<B>(
2044 entries: &[(ast::ValueWithSpan, ast::ValueWithSpan)],
2045 key_value_kind: &ValueKindWithSpan,
2046 value_value_kind: &ValueKindWithSpan,
2047 resolver: &mut NameResolver,
2048 address_bech32_decoder: &AddressBech32Decoder,
2049 blobs: &B,
2050) -> Result<Vec<(ManifestValue, ManifestValue)>, GeneratorError>
2051where
2052 B: IsBlobProvider,
2053{
2054 let mut result = vec![];
2055 for entry in entries {
2056 let key = generate_value(
2057 &entry.0,
2058 Some(key_value_kind),
2059 resolver,
2060 address_bech32_decoder,
2061 blobs,
2062 )?;
2063 let value = generate_value(
2064 &entry.1,
2065 Some(value_value_kind),
2066 resolver,
2067 address_bech32_decoder,
2068 blobs,
2069 )?;
2070 result.push((key, value));
2071 }
2072 Ok(result)
2073}
2074
2075pub fn generator_error_diagnostics(
2076 s: &str,
2077 err: GeneratorError,
2078 style: CompileErrorDiagnosticsStyle,
2079) -> String {
2080 let (title, label) = match err.error_kind {
2090 GeneratorErrorKind::InvalidAstType {
2091 expected_value_kind,
2092 actual,
2093 } => {
2094 let title = format!("expected {:?}, found {:?}", expected_value_kind, actual,);
2095 let label = format!("expected {:?}", expected_value_kind);
2096 (title, label)
2097 }
2098 GeneratorErrorKind::InvalidAstValue {
2099 expected_value_kinds,
2100 actual,
2101 } => {
2102 let expected_value_kinds = expected_value_kinds
2103 .iter()
2104 .map(|vk| vk.to_string())
2105 .collect::<Vec<_>>()
2106 .join(" or ");
2107 let actual_value_kind = actual.value_kind();
2108 let title = format!("expected {expected_value_kinds}, found {actual_value_kind}",);
2109 let label = format!("expected {expected_value_kinds}");
2110 (title, label)
2111 }
2112 GeneratorErrorKind::UnexpectedValueKind {
2113 expected_value_kind,
2114 actual_value: actual,
2115 } => {
2116 let title = format!(
2117 "expected {}, found {}",
2118 expected_value_kind,
2119 actual.value_kind(),
2120 );
2121 let label = format!("expected {}", expected_value_kind);
2122 (title, label)
2123 }
2124 GeneratorErrorKind::InvalidPackageAddress(string) => {
2125 let title = format!("invalid package address '{}'", string);
2126 (title, "invalid package address".to_string())
2127 }
2128 GeneratorErrorKind::InvalidResourceAddress(string) => {
2129 let title = format!("invalid resource address '{}'", string);
2130 (title, "invalid resource address".to_string())
2131 }
2132 GeneratorErrorKind::InvalidDecimal { actual, err } => {
2133 let title = format!("invalid decimal '{}' - {}", actual, err);
2134 (title, "invalid decimal".to_string())
2135 }
2136 GeneratorErrorKind::InvalidPreciseDecimal { actual, err } => {
2137 let title = format!("invalid precise decimal '{}' - {}", actual, err);
2138 (title, "invalid precise decimal".to_string())
2139 }
2140 GeneratorErrorKind::InvalidNonFungibleLocalId(string) => {
2141 let title = format!("invalid non-fungible local id '{}'", string);
2142 (title, "invalid non-fungible local id".to_string())
2143 }
2144 GeneratorErrorKind::InvalidNonFungibleGlobalId => {
2145 let title = format!("invalid non-fungible global id");
2146 (title, "invalid non-fungible global id".to_string())
2147 }
2148 GeneratorErrorKind::InvalidExpression(string) => {
2149 let title = format!("invalid expression '{}'", string);
2150 (title, "invalid expression".to_string())
2151 }
2152 GeneratorErrorKind::InvalidBlobHash { actual, err } => {
2153 let title = format!("invalid blob hash '{}' - {}", actual, err);
2154 (title, "invalid blob hash".to_string())
2155 }
2156 GeneratorErrorKind::BlobNotFound(string) => {
2157 let title = format!("blob with hash '{}' not found", string);
2158 (title, "blob not found".to_string())
2159 }
2160 GeneratorErrorKind::InvalidBytesHex(string) => {
2161 let title = format!("invalid hex value '{}'", string);
2162 (title, "invalid hex value".to_string())
2163 }
2164 GeneratorErrorKind::NameResolverError(error) => match error {
2165 NameResolverError::UndefinedBucket(string) => {
2166 let title = format!("undefined bucket '{}'", string);
2167 (title, "undefined bucket".to_string())
2168 }
2169 NameResolverError::UndefinedProof(string) => {
2170 let title = format!("undefined proof '{}'", string);
2171 (title, "undefined proof".to_string())
2172 }
2173 NameResolverError::UndefinedAddressReservation(string) => {
2174 let title = format!("undefined address reservation '{}'", string);
2175 (title, "undefined address reservation".to_string())
2176 }
2177 NameResolverError::UndefinedNamedAddress(string) => {
2178 let title = format!("undefined named address '{}'", string);
2179 (title, "undefined named address".to_string())
2180 }
2181 NameResolverError::UndefinedIntent(string) => {
2182 let title = format!("undefined intent '{}'", string);
2183 (title, "undefined intent".to_string())
2184 }
2185 NameResolverError::NamedAlreadyDefined(string) => {
2186 let title = format!("name already defined '{}'", string);
2187 (title, "name already defined".to_string())
2188 }
2189 },
2190 GeneratorErrorKind::IdValidationError { err, name } => {
2191 match err {
2192 ManifestIdValidationError::BucketNotFound(bucket_id) => {
2193 let title = if let Some(name) = name {
2194 format!("bucket '{}' not found", name)
2195 } else {
2196 format!("bucket id '{:?}' not found", bucket_id)
2197 };
2198 (title, "bucket not found".to_string())
2199 }
2200 ManifestIdValidationError::ProofNotFound(proof_id) => {
2201 let title = if let Some(name) = name {
2202 format!("proof '{}' not found", name)
2203 } else {
2204 format!("proof id '{:?}' not found", proof_id)
2205 };
2206 (title, "proof not found".to_string())
2207 }
2208 ManifestIdValidationError::BucketLocked(bucket_id) => {
2209 let title = if let Some(name) = name {
2210 format!("cannot consume bucket '{}' because it's believed to be currently locked", name)
2211 } else {
2212 format!("cannot consume bucket id '{:?}' because it's believed to be currently locked", bucket_id)
2213 };
2214 (title, "bucket locked".to_string())
2215 }
2216 ManifestIdValidationError::AddressReservationNotFound(reservation) => {
2217 let title = if let Some(name) = name {
2218 format!("address reservation '{}' not found", name)
2219 } else {
2220 format!("address reservation id '{:?}' not found", reservation)
2221 };
2222 (title, "address reservation not found".to_string())
2223 }
2224 ManifestIdValidationError::AddressNotFound(address) => {
2225 let title = if let Some(name) = name {
2226 format!("address '{}' not found", name)
2227 } else {
2228 format!("address id '{:?}' not found", address)
2229 };
2230 (title, "address not found".to_string())
2231 }
2232 ManifestIdValidationError::IntentNotFound(intent) => {
2233 let title = if let Some(name) = name {
2234 format!("intent '{}' not found", name)
2235 } else {
2236 format!("intent id '{:?}' not found", intent)
2237 };
2238 (title, "intent not found".to_string())
2239 }
2240 }
2241 }
2242 GeneratorErrorKind::InvalidGlobalAddress(string) => {
2243 let title = format!("invalid global address '{}'", string);
2244 (title, "invalid global address".to_string())
2245 }
2246 GeneratorErrorKind::InvalidInternalAddress(string) => {
2247 let title = format!("invalid internal address '{}'", string);
2248 (title, "invalid internal address".to_string())
2249 }
2250 GeneratorErrorKind::InvalidSubTransactionId(string) => {
2251 let title = format!("invalid sub transaction id '{}'", string);
2252 (title, "invalid sub transaction id".to_string())
2253 }
2254 GeneratorErrorKind::InstructionNotSupportedInManifestVersion => {
2255 let title = format!("unsupported instruction for this manifest version");
2256 (title, "unsupported instruction".to_string())
2257 }
2258 GeneratorErrorKind::ManifestBuildError(ManifestBuildError::DuplicateChildSubintentHash) => {
2259 let title = format!("child subintents cannot have the same hash");
2260 (title, "duplicate hash".to_string())
2261 }
2262 GeneratorErrorKind::ManifestBuildError(
2263 ManifestBuildError::PreallocatedAddressesUnsupportedByManifestType,
2264 ) => {
2265 let title = format!("preallocated addresses are not supported in this manifest type");
2266 (title, "unsupported instruction".to_string())
2267 }
2268 GeneratorErrorKind::ManifestBuildError(
2269 ManifestBuildError::ChildSubintentsUnsupportedByManifestType,
2270 ) => {
2271 let title = format!("child subintents are not supported in this manifest type");
2272 (title, "unsupported instruction".to_string())
2273 }
2274 GeneratorErrorKind::HeaderInstructionMustComeFirst => {
2275 let title = format!(
2276 "a psuedo-instruction such as USE_CHILD must come before all other instructions"
2277 );
2278 (title, "must be at the start of the manifest".to_string())
2279 }
2280 GeneratorErrorKind::IntentCannotBeUsedInValue => {
2281 let title = format!("an Intent(...) cannot currently be used inside a value");
2282 (title, "cannot be used inside a value".to_string())
2283 }
2284 GeneratorErrorKind::NamedIntentCannotBeUsedInValue => {
2285 let title = format!("a NamedIntent(...) cannot currently be used inside a value");
2286 (title, "cannot be used inside a value".to_string())
2287 }
2288 GeneratorErrorKind::IntentCannotBeUsedAsValueKind => {
2289 let title = format!("an Intent cannot be used as a value kind");
2290 (title, "cannot be used as a value kind".to_string())
2291 }
2292 GeneratorErrorKind::NamedIntentCannotBeUsedAsValueKind => {
2293 let title = format!("a NamedIntent cannot be used as a value kind");
2294 (title, "cannot be used as a value kind".to_string())
2295 }
2296 GeneratorErrorKind::ArgumentCouldNotBeReadAsExpectedType {
2297 type_name,
2298 error_message,
2299 } => {
2300 let title = format!(
2301 "an argument's structure does not fit with the {type_name} type. {error_message}"
2302 );
2303 let description = format!("cannot be decoded as a {type_name}");
2304 (title, description)
2305 }
2306 };
2307
2308 create_snippet(s, &err.span, &title, &label, style)
2309}
2310
2311#[cfg(test)]
2312mod tests {
2313 use super::*;
2314 use crate::manifest::lexer::tokenize;
2315 use crate::manifest::parser::{Parser, ParserError, ParserErrorKind, PARSER_MAX_DEPTH};
2316 use crate::manifest::token::{Position, Span};
2317 use crate::{position, span};
2318 use radix_common::address::AddressBech32Decoder;
2319 use radix_common::constants::CONSENSUS_MANAGER;
2320 use radix_common::crypto::Secp256k1PrivateKey;
2321 use radix_common::manifest_args;
2322 use radix_common::network::NetworkDefinition;
2323 use radix_common::traits::NonFungibleData;
2324 use radix_common::types::{ComponentAddress, PackageAddress};
2325 use radix_engine_interface::blueprints::consensus_manager::ConsensusManagerCreateValidatorManifestInput;
2326 use radix_engine_interface::blueprints::resource::{
2327 NonFungibleDataSchema, NonFungibleResourceManagerMintManifestInput,
2328 NonFungibleResourceManagerMintRuidManifestInput,
2329 };
2330 use radix_engine_interface::object_modules::metadata::MetadataValue;
2331 use radix_engine_interface::object_modules::ModuleConfig;
2332 use radix_engine_interface::types::PackageRoyaltyConfig;
2333 use radix_rust::prelude::IndexMap;
2334 use scrypto::radix_blueprint_schema_init::BlueprintStateSchemaInit;
2335
2336 #[macro_export]
2337 macro_rules! generate_value_ok {
2338 ( $s:expr, $expected:expr ) => {{
2339 let value = Parser::new(tokenize($s).unwrap(), PARSER_MAX_DEPTH)
2340 .unwrap()
2341 .parse_value()
2342 .unwrap();
2343 let mut resolver = NameResolver::new();
2344 assert_eq!(
2345 generate_value(
2346 &value,
2347 None,
2348 &mut resolver,
2349 &AddressBech32Decoder::new(&NetworkDefinition::simulator()),
2350 &BlobProvider::default()
2351 ),
2352 Ok($expected)
2353 );
2354 }};
2355 }
2356
2357 #[macro_export]
2358 macro_rules! generate_instruction_ok {
2359 ( $s:expr, $expected:expr $(,)? ) => {{
2360 let instruction = Parser::new(tokenize($s).unwrap(), PARSER_MAX_DEPTH)
2363 .unwrap()
2364 .parse_instruction()
2365 .unwrap();
2366 let mut id_validator = BasicManifestValidator::new();
2367 let mut resolver = NameResolver::new();
2368 assert_eq!(
2369 generate_instruction(
2370 &instruction,
2371 &mut id_validator,
2372 &mut resolver,
2373 &AddressBech32Decoder::new(&NetworkDefinition::simulator()),
2374 &MockBlobProvider::default()
2375 ),
2376 Ok($expected.into())
2377 );
2378 }}
2379 }
2380
2381 #[macro_export]
2382 macro_rules! generate_value_error {
2383 ( $s:expr, $expected:expr ) => {{
2384 let value = Parser::new(tokenize($s).unwrap(), PARSER_MAX_DEPTH)
2385 .unwrap()
2386 .parse_value()
2387 .unwrap();
2388 match generate_value(
2389 &value,
2390 None,
2391 &mut NameResolver::new(),
2392 &AddressBech32Decoder::new(&NetworkDefinition::simulator()),
2393 &BlobProvider::default(),
2394 ) {
2395 Ok(_) => {
2396 panic!("Expected {:?} but no error is thrown", $expected);
2397 }
2398 Err(e) => {
2399 assert_eq!(e, $expected);
2400 }
2401 }
2402 }};
2403 }
2404
2405 #[test]
2406 fn test_value() {
2407 generate_value_ok!(r#"Tuple()"#, Value::Tuple { fields: vec![] });
2408 generate_value_ok!(r#"true"#, Value::Bool { value: true });
2409 generate_value_ok!(r#"false"#, Value::Bool { value: false });
2410 generate_value_ok!(r#"1i8"#, Value::I8 { value: 1 });
2411 generate_value_ok!(r#"1i128"#, Value::I128 { value: 1 });
2412 generate_value_ok!(r#"1u8"#, Value::U8 { value: 1 });
2413 generate_value_ok!(r#"1u128"#, Value::U128 { value: 1 });
2414 generate_value_ok!(
2415 r#"Tuple(Bucket(1u32), Proof(2u32), "bar")"#,
2416 Value::Tuple {
2417 fields: vec![
2418 Value::Custom {
2419 value: ManifestCustomValue::Bucket(ManifestBucket(1))
2420 },
2421 Value::Custom {
2422 value: ManifestCustomValue::Proof(ManifestProof(2))
2423 },
2424 Value::String {
2425 value: "bar".into()
2426 }
2427 ]
2428 }
2429 );
2430 generate_value_ok!(
2431 r#"Tuple(Decimal("1"))"#,
2432 Value::Tuple {
2433 fields: vec![Value::Custom {
2434 value: ManifestCustomValue::Decimal(from_decimal(
2435 Decimal::from_str("1").unwrap()
2436 ))
2437 },]
2438 }
2439 );
2440 generate_value_ok!(r#"Tuple()"#, Value::Tuple { fields: vec![] });
2441 generate_value_ok!(
2442 r#"Enum<0u8>( "abc")"#,
2443 Value::Enum {
2444 discriminator: 0,
2445 fields: vec![Value::String {
2446 value: "abc".to_owned()
2447 }]
2448 }
2449 );
2450 generate_value_ok!(
2451 r#"Enum<1u8>()"#,
2452 Value::Enum {
2453 discriminator: 1,
2454 fields: vec![]
2455 }
2456 );
2457 generate_value_ok!(
2458 r#"Enum<AccessRule::AllowAll>()"#,
2459 Value::Enum {
2460 discriminator: 0,
2461 fields: vec![]
2462 }
2463 );
2464 generate_value_ok!(
2465 r#"Expression("ENTIRE_WORKTOP")"#,
2466 Value::Custom {
2467 value: ManifestCustomValue::Expression(ManifestExpression::EntireWorktop)
2468 }
2469 );
2470 generate_value_ok!(
2471 r#"Expression("ENTIRE_AUTH_ZONE")"#,
2472 Value::Custom {
2473 value: ManifestCustomValue::Expression(ManifestExpression::EntireAuthZone)
2474 }
2475 );
2476 }
2477
2478 #[test]
2479 fn test_failures() {
2480 generate_value_error!(
2481 r#"Address(100u32)"#,
2482 GeneratorError {
2483 error_kind: GeneratorErrorKind::InvalidAstValue {
2484 expected_value_kinds: vec![ast::ValueKind::String],
2485 actual: ast::Value::U32(100),
2486 },
2487 span: span!(start = (8, 0, 8), end = (14, 0, 14)),
2488 }
2489 );
2490 generate_value_error!(
2491 r#"Address("invalid_package_address")"#,
2492 GeneratorError {
2493 error_kind: GeneratorErrorKind::InvalidGlobalAddress(
2494 "invalid_package_address".into(),
2495 ),
2496 span: span!(start = (8, 0, 8), end = (33, 0, 33))
2497 }
2498 );
2499 generate_value_error!(
2500 r#"Decimal("invalid_decimal")"#,
2501 GeneratorError {
2502 error_kind: GeneratorErrorKind::InvalidDecimal {
2503 actual: "invalid_decimal".to_string(),
2504 err: "InvalidDigit".to_string(),
2505 },
2506 span: span!(start = (8, 0, 8), end = (25, 0, 25))
2507 }
2508 );
2509 generate_value_error!(
2510 r#"Decimal("i")"#,
2511 GeneratorError {
2512 error_kind: GeneratorErrorKind::InvalidDecimal {
2513 actual: "i".to_string(),
2514 err: "InvalidDigit".to_string(),
2515 },
2516 span: span!(start = (8, 0, 8), end = (11, 0, 11))
2517 }
2518 );
2519
2520 generate_value_error!(
2522 r#"Decimal("🤓")"#,
2523 GeneratorError {
2524 error_kind: GeneratorErrorKind::InvalidDecimal {
2525 actual: "🤓".to_string(),
2526 err: "InvalidDigit".to_string(),
2527 },
2528 span: span!(start = (8, 0, 8), end = (11, 0, 11))
2529 }
2530 );
2531
2532 generate_value_error!(
2533 r#"Decimal("\uD83D\uDC69")"#,
2534 GeneratorError {
2535 error_kind: GeneratorErrorKind::InvalidDecimal {
2536 actual: "\u{1f469}".to_string(), err: "InvalidDigit".to_string(),
2538 },
2539 span: span!(start = (8, 0, 8), end = (22, 0, 22))
2540 }
2541 );
2542 generate_value_error!(
2543 r#"Decimal("👩")"#,
2544 GeneratorError {
2545 error_kind: GeneratorErrorKind::InvalidDecimal {
2546 actual: "👩".to_string(),
2547 err: "InvalidDigit".to_string(),
2548 },
2549 span: span!(start = (8, 0, 8), end = (11, 0, 11))
2550 }
2551 );
2552 }
2553
2554 #[test]
2555 fn test_instructions() {
2556 let address_bech32_decoder = AddressBech32Decoder::new(&NetworkDefinition::simulator());
2557 let package_address = PackageAddress::try_from_bech32(
2558 &address_bech32_decoder,
2559 "package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk".into(),
2560 )
2561 .unwrap();
2562 let component = ComponentAddress::try_from_bech32(
2563 &address_bech32_decoder,
2564 "component_sim1cqvgx33089ukm2pl97pv4max0x40ruvfy4lt60yvya744cvemygpmu",
2565 )
2566 .unwrap();
2567 let resource_address = ResourceAddress::try_from_bech32(
2568 &address_bech32_decoder,
2569 "resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez",
2570 )
2571 .unwrap();
2572
2573 generate_instruction_ok!(
2574 r#"TAKE_FROM_WORKTOP Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez") Decimal("1") Bucket("xrd_bucket");"#,
2575 TakeFromWorktop {
2576 amount: Decimal::from(1),
2577 resource_address,
2578 },
2579 );
2580 generate_instruction_ok!(
2581 r#"TAKE_ALL_FROM_WORKTOP Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez") Bucket("xrd_bucket");"#,
2582 TakeAllFromWorktop { resource_address },
2583 );
2584 generate_instruction_ok!(
2585 r#"ASSERT_WORKTOP_CONTAINS Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez") Decimal("1");"#,
2586 AssertWorktopContains {
2587 amount: Decimal::from(1),
2588 resource_address,
2589 },
2590 );
2591 generate_instruction_ok!(
2592 r#"CALL_FUNCTION Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") "Airdrop" "new" 500u32 PreciseDecimal("120");"#,
2593 CallFunction {
2594 package_address: package_address.into(),
2595 blueprint_name: "Airdrop".into(),
2596 function_name: "new".to_string(),
2597 args: manifest_args!(500u32, pdec!("120")).into()
2598 },
2599 );
2600 generate_instruction_ok!(
2601 r#"CALL_METHOD Address("component_sim1cqvgx33089ukm2pl97pv4max0x40ruvfy4lt60yvya744cvemygpmu") "refill";"#,
2602 CallMethod {
2603 address: component.into(),
2604 method_name: "refill".to_string(),
2605 args: manifest_args!().into()
2606 },
2607 );
2608 generate_instruction_ok!(
2609 r#"MINT_FUNGIBLE Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez") Decimal("100");"#,
2610 CallMethod {
2611 address: resource_address.into(),
2612 method_name: "mint".to_string(),
2613 args: manifest_args!(dec!("100")).into()
2614 },
2615 );
2616 }
2617
2618 #[test]
2619 fn test_publish_instruction() {
2620 generate_instruction_ok!(
2621 r#"PUBLISH_PACKAGE_ADVANCED Blob("a710f0959d8e139b3c1ca74ac4fcb9a95ada2c82e7f563304c5487e0117095c0") Map<String, Tuple>() Map<String, Enum>() Map<String, Enum>() Map<String, Enum>();"#,
2622 CallFunction {
2623 package_address: PACKAGE_PACKAGE.into(),
2624 blueprint_name: PACKAGE_BLUEPRINT.to_string(),
2625 function_name: PACKAGE_PUBLISH_WASM_ADVANCED_IDENT.to_string(),
2626 args: manifest_args!(
2627 ManifestBlobRef(
2628 hex::decode(
2629 "a710f0959d8e139b3c1ca74ac4fcb9a95ada2c82e7f563304c5487e0117095c0"
2630 )
2631 .unwrap()
2632 .try_into()
2633 .unwrap()
2634 ),
2635 IndexMap::<String, BlueprintStateSchemaInit, _>::new(),
2636 IndexMap::<String, PackageRoyaltyConfig, _>::new(),
2637 IndexMap::<String, MetadataValue, _>::new(),
2638 RoleAssignmentInit::new()
2639 )
2640 .into(),
2641 },
2642 );
2643 }
2644
2645 #[test]
2646 fn test_create_non_fungible_instruction() {
2647 generate_instruction_ok!(
2648 r#"CREATE_NON_FUNGIBLE_RESOURCE
2649 Enum<0u8>()
2650 Enum<NonFungibleIdType::Integer>()
2651 false
2652 Enum<0u8>(
2653 Enum<0u8>(
2654 Tuple(
2655 Array<Enum>(),
2656 Array<Tuple>(),
2657 Array<Enum>()
2658 )
2659 ),
2660 Enum<0u8>(66u8),
2661 Array<String>()
2662 )
2663 Tuple(
2664 Enum<0u8>(),
2665 Enum<0u8>(),
2666 Enum<0u8>(),
2667 Enum<0u8>(),
2668 Enum<0u8>(),
2669 Enum<0u8>(),
2670 Enum<0u8>()
2671 )
2672 Tuple(
2673 Map<String, Tuple>(
2674 "name" => Tuple(
2675 Enum<Option::Some>(Enum<Metadata::String>("Token")),
2676 true
2677 ),
2678 ),
2679 Map<String, Enum>()
2680 )
2681 Enum<0u8>();"#,
2682 CallFunction {
2683 package_address: RESOURCE_PACKAGE.into(),
2684 blueprint_name: NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
2685 function_name: NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT.to_string(),
2686 args: to_manifest_value_and_unwrap!(
2687 &NonFungibleResourceManagerCreateManifestInput {
2688 owner_role: OwnerRole::None,
2689 id_type: NonFungibleIdType::Integer,
2690 track_total_supply: false,
2691 non_fungible_schema:
2692 NonFungibleDataSchema::new_local_without_self_package_replacement::<()>(
2693 ),
2694 metadata: metadata! {
2695 init {
2696 "name" => "Token".to_string(), locked;
2697 }
2698 },
2699 resource_roles: NonFungibleResourceRoles::default(),
2700 address_reservation: None,
2701 }
2702 ),
2703 },
2704 );
2705 }
2706
2707 #[derive(ScryptoSbor)]
2708 struct MyNonFungibleData {
2709 name: String,
2710 description: String,
2711 stored_number: Decimal,
2712 }
2713
2714 impl NonFungibleData for MyNonFungibleData {
2716 const MUTABLE_FIELDS: &'static [&'static str] = &["description", "stored_number"];
2717 }
2718
2719 #[test]
2720 fn test_generate_non_fungible_instruction_with_specific_data() {
2721 let manifest = ManifestBuilder::new_v1()
2723 .call_function(
2724 RESOURCE_PACKAGE,
2725 NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT,
2726 NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT,
2727 NonFungibleResourceManagerCreateManifestInput {
2728 owner_role: OwnerRole::None,
2729 track_total_supply: false,
2730 id_type: NonFungibleIdType::Integer,
2731 non_fungible_schema:
2732 NonFungibleDataSchema::new_local_without_self_package_replacement::<
2733 MyNonFungibleData,
2734 >(),
2735 resource_roles: NonFungibleResourceRoles::default(),
2736 metadata: metadata!(),
2737 address_reservation: None,
2738 },
2739 )
2740 .build();
2741 println!(
2742 "{}",
2743 crate::manifest::decompile(&manifest, &NetworkDefinition::simulator()).unwrap()
2744 );
2745 }
2746
2747 #[test]
2748 fn test_create_non_fungible_with_initial_supply_instruction() {
2749 generate_instruction_ok!(
2750 r##"CREATE_NON_FUNGIBLE_RESOURCE_WITH_INITIAL_SUPPLY
2751 Enum<0u8>()
2752 Enum<NonFungibleIdType::Integer>()
2753 false
2754 Enum<0u8>(
2755 Enum<0u8>(
2756 Tuple(
2757 Array<Enum>(),
2758 Array<Tuple>(),
2759 Array<Enum>()
2760 )
2761 ),
2762 Enum<0u8>(66u8),
2763 Array<String>()
2764 )
2765 Map<NonFungibleLocalId, Tuple>(
2766 NonFungibleLocalId("#1#") => Tuple(
2767 Tuple(
2768 "Hello World",
2769 Decimal("12")
2770 )
2771 )
2772 )
2773 Tuple(
2774 Enum<0u8>(),
2775 Enum<0u8>(),
2776 Enum<0u8>(),
2777 Enum<0u8>(),
2778 Enum<0u8>(),
2779 Enum<0u8>(),
2780 Enum<0u8>()
2781 )
2782 Tuple(
2783 Map<String, Tuple>(
2784 "name" => Tuple(Enum<Option::Some>(Enum<Metadata::String>("Token")), true)
2785 ),
2786 Map<String, Enum>()
2787 )
2788 Enum<0u8>()
2789 ;"##,
2790 CallFunction {
2791 package_address: RESOURCE_PACKAGE.into(),
2792 blueprint_name: NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
2793 function_name: NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT
2794 .to_string(),
2795 args: to_manifest_value_and_unwrap!(
2796 &NonFungibleResourceManagerCreateWithInitialSupplyManifestInput {
2797 owner_role: OwnerRole::None,
2798 track_total_supply: false,
2799 id_type: NonFungibleIdType::Integer,
2800 non_fungible_schema:
2801 NonFungibleDataSchema::new_local_without_self_package_replacement::<()>(
2802 ),
2803 resource_roles: NonFungibleResourceRoles::default(),
2804 metadata: metadata! {
2805 init {
2806 "name" => "Token".to_string(), locked;
2807 }
2808 },
2809 entries: indexmap!(
2810 NonFungibleLocalId::integer(1) =>
2811 (to_manifest_value_and_unwrap!(&(
2812 String::from("Hello World"),
2813 dec!("12")
2814 )),),
2815 ),
2816 address_reservation: None,
2817 }
2818 ),
2819 },
2820 );
2821 }
2822
2823 #[test]
2824 fn test_create_fungible_instruction() {
2825 generate_instruction_ok!(
2826 r#"CREATE_FUNGIBLE_RESOURCE
2827 Enum<0u8>()
2828 false
2829 18u8
2830 Tuple(
2831 Enum<0u8>(),
2832 Enum<0u8>(),
2833 Enum<0u8>(),
2834 Enum<0u8>(),
2835 Enum<0u8>(),
2836 Enum<0u8>()
2837 )
2838 Tuple(
2839 Map<String, Tuple>(
2840 "name" => Tuple(Enum<Option::Some>(Enum<Metadata::String>("Token")), false)
2841 ),
2842 Map<String, Enum>()
2843 )
2844 Enum<0u8>()
2845 ;"#,
2846 CallFunction {
2847 package_address: RESOURCE_PACKAGE.into(),
2848 blueprint_name: FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
2849 function_name: FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT.to_string(),
2850 args: to_manifest_value_and_unwrap!(&FungibleResourceManagerCreateManifestInput {
2851 owner_role: OwnerRole::None,
2852 track_total_supply: false,
2853 divisibility: 18,
2854 resource_roles: FungibleResourceRoles::default(),
2855 metadata: metadata! {
2856 init {
2857 "name" => "Token".to_owned(), updatable;
2858 }
2859 },
2860 address_reservation: None,
2861 }),
2862 },
2863 );
2864 }
2865
2866 #[test]
2867 fn test_create_fungible_with_initial_supply_instruction() {
2868 generate_instruction_ok!(
2869 r#"CREATE_FUNGIBLE_RESOURCE_WITH_INITIAL_SUPPLY
2870 Enum<0u8>()
2871 false
2872 18u8
2873 Decimal("500")
2874 Tuple(
2875 Enum<0u8>(),
2876 Enum<0u8>(),
2877 Enum<0u8>(),
2878 Enum<0u8>(),
2879 Enum<0u8>(),
2880 Enum<0u8>()
2881 )
2882 Tuple(
2883 Map<String, Tuple>(
2884 "name" => Tuple(Enum<Option::Some>(Enum<Metadata::String>("Token")), false)
2885 ),
2886 Map<String, Enum>()
2887 )
2888 Enum<0u8>()
2889 ;"#,
2890 CallFunction {
2891 package_address: RESOURCE_PACKAGE.into(),
2892 blueprint_name: FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT.to_string(),
2893 function_name: FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT
2894 .to_string(),
2895 args: to_manifest_value_and_unwrap!(
2896 &FungibleResourceManagerCreateWithInitialSupplyManifestInput {
2897 owner_role: OwnerRole::None,
2898 track_total_supply: false,
2899 divisibility: 18,
2900 initial_supply: "500".parse().unwrap(),
2901 resource_roles: FungibleResourceRoles::default(),
2902 metadata: metadata! {
2903 init {
2904 "name" => "Token".to_owned(), updatable;
2905 }
2906 },
2907 address_reservation: None,
2908 }
2909 )
2910 },
2911 );
2912 }
2913
2914 #[test]
2915 fn test_mint_non_fungible_instruction() {
2916 let address_bech32_decoder = AddressBech32Decoder::new(&NetworkDefinition::simulator());
2917 let resource_address = ResourceAddress::try_from_bech32(
2918 &address_bech32_decoder,
2919 "resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez",
2920 )
2921 .unwrap();
2922
2923 generate_instruction_ok!(
2924 r##"
2925 MINT_NON_FUNGIBLE
2926 Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez")
2927 Map<NonFungibleLocalId, Tuple>(NonFungibleLocalId("#1#") => Tuple(Tuple("Hello World", Decimal("12"))));
2928 "##,
2929 CallMethod {
2930 address: resource_address.into(),
2931 method_name: NON_FUNGIBLE_RESOURCE_MANAGER_MINT_IDENT.to_string(),
2932 args: to_manifest_value_and_unwrap!(&NonFungibleResourceManagerMintManifestInput {
2933 entries: indexmap!(
2934 NonFungibleLocalId::integer(1) =>
2935 (to_manifest_value_and_unwrap!(&(
2936 String::from("Hello World"),
2937 dec!("12")
2938 )),)
2939 )
2940 })
2941 },
2942 );
2943 }
2944
2945 #[test]
2946 fn test_mint_ruid_non_fungible_instruction() {
2947 let address_bech32_decoder = AddressBech32Decoder::new(&NetworkDefinition::simulator());
2948 let resource_address = ResourceAddress::try_from_bech32(
2949 &address_bech32_decoder,
2950 "resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez",
2951 )
2952 .unwrap();
2953
2954 generate_instruction_ok!(
2955 r#"
2956 MINT_RUID_NON_FUNGIBLE
2957 Address("resource_sim1thvwu8dh6lk4y9mntemkvj25wllq8adq42skzufp4m8wxxuemugnez")
2958 Array<Tuple>(
2959 Tuple(Tuple("Hello World", Decimal("12")))
2960 );
2961 "#,
2962 CallMethod {
2963 address: resource_address.into(),
2964 method_name: NON_FUNGIBLE_RESOURCE_MANAGER_MINT_RUID_IDENT.to_string(),
2965 args: to_manifest_value_and_unwrap!(
2966 &NonFungibleResourceManagerMintRuidManifestInput {
2967 entries: Vec::from([(to_manifest_value_and_unwrap!(&(
2968 String::from("Hello World"),
2969 dec!("12")
2970 )),),])
2971 }
2972 ),
2973 },
2974 );
2975 }
2976
2977 #[test]
2978 fn test_create_validator_instruction() {
2979 let tokens = tokenize(
2980 r#"
2981 CREATE_VALIDATOR Bytes("02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5") Decimal("1") Bucket("xrd_bucket");
2982 "#
2983 ).unwrap();
2984 let instruction = Parser::new(tokens, PARSER_MAX_DEPTH)
2985 .unwrap()
2986 .parse_instruction()
2987 .unwrap();
2988 let mut id_validator = BasicManifestValidator::new();
2989 let mut resolver = NameResolver::new();
2990 resolver
2991 .named_buckets
2992 .insert("xrd_bucket".to_string(), ManifestBucket(0u32));
2993 assert_eq!(
2994 generate_instruction(
2995 &instruction,
2996 &mut id_validator,
2997 &mut resolver,
2998 &AddressBech32Decoder::new(&NetworkDefinition::simulator()),
2999 &MockBlobProvider::default()
3000 ),
3001 Ok(CallMethod {
3002 address: CONSENSUS_MANAGER.into(),
3003 method_name: CONSENSUS_MANAGER_CREATE_VALIDATOR_IDENT.to_string(),
3004 args: to_manifest_value_and_unwrap!(
3005 &ConsensusManagerCreateValidatorManifestInput {
3006 key: Secp256k1PrivateKey::from_u64(2u64).unwrap().public_key(),
3007 fee_factor: Decimal::ONE,
3008 xrd_payment: ManifestBucket(0u32)
3009 }
3010 ),
3011 }
3012 .into())
3013 );
3014 }
3015
3016 macro_rules! generate_manifest_input_with_given_depth {
3017 ( $depth:expr ) => {{
3018 let depth: usize = $depth;
3019 let mut manifest = r#"CALL_FUNCTION Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") "blueprint" "func" "#.to_string();
3021 for _ in 0..depth - 1 {
3022 manifest.push_str("Tuple(");
3023 }
3024 manifest.push_str("0u8");
3025 for _ in 0..depth - 1 {
3026 manifest.push_str(")");
3027 }
3028 manifest.push_str(";");
3029 manifest
3030 }};
3031 }
3032
3033 macro_rules! generate_compiled_manifest_with_given_depth {
3034 ( $depth:expr ) => {{
3035 let manifest = generate_manifest_input_with_given_depth!($depth);
3036 let address_bech32_decoder = AddressBech32Decoder::new(&NetworkDefinition::simulator());
3037 let transaction_bech32_decoder =
3038 TransactionHashBech32Decoder::new(&NetworkDefinition::simulator());
3039
3040 let tokens = tokenize(&manifest)
3041 .map_err(CompileError::LexerError)
3042 .unwrap();
3043
3044 let instructions = parser::Parser::new(tokens, $depth)
3045 .unwrap()
3046 .parse_manifest()
3047 .unwrap();
3048 let blobs = BlobProvider::new();
3049
3050 generate_manifest::<_, TransactionManifestV1>(
3051 &instructions,
3052 &address_bech32_decoder,
3053 &transaction_bech32_decoder,
3054 blobs,
3055 )
3056 .unwrap()
3057 }};
3058 }
3059
3060 #[test]
3061 fn test_no_stack_overflow_for_very_deep_manifest() {
3062 use crate::manifest::*;
3063
3064 let manifest = generate_manifest_input_with_given_depth!(1000);
3065
3066 let result = compile_manifest_v1(
3067 &manifest,
3068 &NetworkDefinition::simulator(),
3069 BlobProvider::default(),
3070 );
3071 let expected = CompileError::ParserError(ParserError {
3072 error_kind: ParserErrorKind::MaxDepthExceeded {
3073 actual: 21,
3074 max: 20,
3075 },
3076 span: span!(start = (231, 0, 231), end = (236, 0, 236)),
3077 });
3078
3079 match result {
3080 Ok(_) => {
3081 panic!("Expected {:?} but no error is thrown", expected);
3082 }
3083 Err(e) => {
3084 assert_eq!(e, expected);
3085 }
3086 }
3087 }
3088
3089 #[test]
3090 fn test_if_max_depth_is_possibly_maximal() {
3091 use crate::manifest::*;
3092 let compiled = generate_compiled_manifest_with_given_depth!(PARSER_MAX_DEPTH);
3098
3099 let _result = manifest_encode(&compiled).unwrap();
3100
3101 let compiled = generate_compiled_manifest_with_given_depth!(PARSER_MAX_DEPTH + 1);
3104
3105 let expected = EncodeError::MaxDepthExceeded(MANIFEST_SBOR_V1_MAX_DEPTH);
3106
3107 let result = manifest_encode(&compiled);
3108 assert_eq!(result, Err(expected));
3109 }
3110}