diff --git a/radix-common/src/data/manifest/model/manifest_resource_assertion.rs b/radix-common/src/data/manifest/model/manifest_resource_assertion.rs index bdb6d87ed7f..8e7bbd18737 100644 --- a/radix-common/src/data/manifest/model/manifest_resource_assertion.rs +++ b/radix-common/src/data/manifest/model/manifest_resource_assertion.rs @@ -20,13 +20,25 @@ impl ManifestResourceConstraints { /// * Panics if the constraint isn't valid for the resource address /// * Panics if constraints have already been specified against the resource pub fn with( - mut self, + self, resource_address: ResourceAddress, constraint: ManifestResourceConstraint, ) -> Self { if !constraint.is_valid_for(&resource_address) { panic!("Constraint isn't valid for the resource address"); } + self.with_unchecked(resource_address, constraint) + } + + /// Unlike `with`, this does not validate the constraint. + /// + /// ## Panics + /// * Panics if constraints have already been specified against the resource + pub fn with_unchecked( + mut self, + resource_address: ResourceAddress, + constraint: ManifestResourceConstraint, + ) -> Self { let replaced = self .specified_resources .insert(resource_address, constraint); diff --git a/radix-rust/src/macros.rs b/radix-rust/src/macros.rs index 841ebe7650e..9c40dc160d4 100644 --- a/radix-rust/src/macros.rs +++ b/radix-rust/src/macros.rs @@ -46,7 +46,7 @@ macro_rules! assert_matches { ) } }; - ($expression:expr, $pattern:pat $(if $condition:expr)? $(,)? => $code:expr) => { + ($expression:expr, $pattern:pat $(if $condition:expr)? => $code:expr $(,)?) => { match $expression { $pattern $(if $condition)? => $code, ref expression => panic!( @@ -67,7 +67,7 @@ macro_rules! assert_matches { ) } }; - ($expression:expr, $pattern:pat $(if $condition:expr)? $(,)? => $code:expr, $($arg:tt)+) => { + ($expression:expr, $pattern:pat $(if $condition:expr)? => $code:expr, $($arg:tt)+) => { match $expression { $pattern $(if $condition)? => $code, ref expression => panic!( diff --git a/radix-transactions/src/builder/manifest_builder.rs b/radix-transactions/src/builder/manifest_builder.rs index 7cf253ff7c3..2c2e5844ac4 100644 --- a/radix-transactions/src/builder/manifest_builder.rs +++ b/radix-transactions/src/builder/manifest_builder.rs @@ -343,7 +343,9 @@ impl ManifestBuilder { self } - #[deprecated = "This should not be used apart from for test code purposefully constructing invalid manifests. Instead use the more-tailored instruction, or add_instruction_advanced."] + /// This should not be used apart from for test code purposefully constructing invalid manifests. + /// Instead use the more-tailored instruction, or add_instruction_advanced. + #[cfg(test)] pub fn add_raw_instruction_ignoring_all_side_effects( self, instruction: impl Into, diff --git a/radix-transactions/src/errors.rs b/radix-transactions/src/errors.rs index 02677532fc9..681155d2d57 100644 --- a/radix-transactions/src/errors.rs +++ b/radix-transactions/src/errors.rs @@ -3,11 +3,9 @@ use sbor::*; #[derive(Debug, Clone, PartialEq, Eq)] pub enum HeaderValidationError { - UnknownVersion(u8), InvalidEpochRange, InvalidTimestampRange, InvalidNetwork, - InvalidCostUnitLimit, InvalidTip, NoValidEpochRangeAcrossAllIntents, NoValidTimestampRangeAcrossAllIntents, diff --git a/radix-transactions/src/manifest/generator.rs b/radix-transactions/src/manifest/generator.rs index e51656c6443..635a8fb7842 100644 --- a/radix-transactions/src/manifest/generator.rs +++ b/radix-transactions/src/manifest/generator.rs @@ -2262,14 +2262,13 @@ pub fn generator_error_diagnostics( GeneratorErrorKind::ManifestBuildError( ManifestBuildError::PreallocatedAddressesUnsupportedByManifestType, ) => { - let title = - format!("preallocated addresses are not supported in this manifest version"); + let title = format!("preallocated addresses are not supported in this manifest type"); (title, "unsupported instruction".to_string()) } GeneratorErrorKind::ManifestBuildError( ManifestBuildError::ChildSubintentsUnsupportedByManifestType, ) => { - let title = format!("child subintents are not supported in this manifest version"); + let title = format!("child subintents are not supported in this manifest type"); (title, "unsupported instruction".to_string()) } GeneratorErrorKind::HeaderInstructionMustComeFirst => { diff --git a/radix-transactions/src/manifest/manifest_instructions.rs b/radix-transactions/src/manifest/manifest_instructions.rs index 32a2f187a19..c079bb344e3 100644 --- a/radix-transactions/src/manifest/manifest_instructions.rs +++ b/radix-transactions/src/manifest/manifest_instructions.rs @@ -1341,6 +1341,14 @@ pub struct YieldToParent { pub args: ManifestValue, } +impl YieldToParent { + pub fn empty() -> Self { + Self { + args: ManifestValue::unit(), + } + } +} + impl ManifestInstruction for YieldToParent { const IDENT: &'static str = "YIELD_TO_PARENT"; const ID: u8 = INSTRUCTION_YIELD_TO_PARENT_DISCRIMINATOR; diff --git a/radix-transactions/src/model/mod.rs b/radix-transactions/src/model/mod.rs index f7d3cde4f7b..fa9533d8cea 100644 --- a/radix-transactions/src/model/mod.rs +++ b/radix-transactions/src/model/mod.rs @@ -238,7 +238,7 @@ Enum<3u8>( assert_eq!( validated, Err(TransactionValidationError::PrepareError( - PrepareError::Other(format!("Unknown transaction payload discriminator byte: 4")) + PrepareError::UnexpectedTransactionDiscriminator { actual: Some(4) } )) ) } diff --git a/radix-transactions/src/model/preparation/decoder.rs b/radix-transactions/src/model/preparation/decoder.rs index 58f587df724..97d04bab6b4 100644 --- a/radix-transactions/src/model/preparation/decoder.rs +++ b/radix-transactions/src/model/preparation/decoder.rs @@ -4,10 +4,10 @@ use sbor::*; #[derive(Debug, Clone, Eq, PartialEq)] pub enum ValueType { Blob, - Message, Subintent, - ChildIntentConstraint, - IntentSignatures, + ChildSubintentSpecifier, + SubintentSignatureBatches, + // Too many signatures is captured at validation time } #[derive(Debug, Clone, Eq, PartialEq)] @@ -22,7 +22,9 @@ pub enum PrepareError { max: usize, }, LengthOverflow, - Other(String), + UnexpectedTransactionDiscriminator { + actual: Option, + }, } impl From for PrepareError { diff --git a/radix-transactions/src/model/user_transaction.rs b/radix-transactions/src/model/user_transaction.rs index 8e94ddb29a9..76195a1bf08 100644 --- a/radix-transactions/src/model/user_transaction.rs +++ b/radix-transactions/src/model/user_transaction.rs @@ -248,9 +248,9 @@ impl PreparedTransaction for PreparedUserTransaction { ) -> Result { let offset = decoder.get_offset(); let slice = decoder.get_input_slice(); - let discriminator_byte = slice.get(offset + 1).ok_or(PrepareError::Other( - "Could not read transaction payload discriminator byte".to_string(), - ))?; + let discriminator_byte = slice + .get(offset + 1) + .ok_or(PrepareError::UnexpectedTransactionDiscriminator { actual: None })?; let prepared = match TransactionDiscriminator::from_repr(*discriminator_byte) { Some(TransactionDiscriminator::V1Notarized) => PreparedUserTransaction::V1( @@ -260,9 +260,9 @@ impl PreparedTransaction for PreparedUserTransaction { PreparedNotarizedTransactionV2::prepare_from_transaction_enum(decoder)?, ), _ => { - return Err(PrepareError::Other(format!( - "Unknown transaction payload discriminator byte: {discriminator_byte}" - ))) + return Err(PrepareError::UnexpectedTransactionDiscriminator { + actual: Some(*discriminator_byte), + }) } }; diff --git a/radix-transactions/src/model/v1/blobs.rs b/radix-transactions/src/model/v1/blobs.rs index 54cb3059559..6954fa6f344 100644 --- a/radix-transactions/src/model/v1/blobs.rs +++ b/radix-transactions/src/model/v1/blobs.rs @@ -11,6 +11,12 @@ pub struct BlobsV1 { pub blobs: Vec, } +impl BlobsV1 { + pub fn none() -> Self { + Self { blobs: Vec::new() } + } +} + impl From>> for BlobsV1 { fn from(blobs: IndexMap>) -> Self { let blobs = blobs diff --git a/radix-transactions/src/model/v2/child_subintent_hashes_v2.rs b/radix-transactions/src/model/v2/child_subintent_hashes_v2.rs index 39273ff26dd..50b96c407f8 100644 --- a/radix-transactions/src/model/v2/child_subintent_hashes_v2.rs +++ b/radix-transactions/src/model/v2/child_subintent_hashes_v2.rs @@ -35,6 +35,12 @@ impl ChildSubintentSpecifier { } } +impl From for ChildSubintentSpecifier { + fn from(hash: SubintentHash) -> Self { + Self { hash } + } +} + /// A new-type representing the index of a referenced intent. /// The first few of these will be the children of the given intent. /// @@ -86,7 +92,7 @@ impl TransactionPreparableFromValueBody for PreparedChildSubintentSpecifiersV2 { let (hashes, summary) = ConcatenatedDigest::prepare_from_sbor_array_value_body::>( decoder, - ValueType::ChildIntentConstraint, + ValueType::ChildSubintentSpecifier, max_child_subintents_per_intent, )?; diff --git a/radix-transactions/src/model/v2/intent_signatures_v2.rs b/radix-transactions/src/model/v2/intent_signatures_v2.rs index 41657211b50..bebcafd2ccd 100644 --- a/radix-transactions/src/model/v2/intent_signatures_v2.rs +++ b/radix-transactions/src/model/v2/intent_signatures_v2.rs @@ -7,6 +7,18 @@ pub struct IntentSignaturesV2 { pub signatures: Vec, } +impl IntentSignaturesV2 { + pub fn none() -> Self { + Self { + signatures: Vec::new(), + } + } + + pub fn new(signatures: Vec) -> Self { + Self { signatures } + } +} + impl TransactionPartialPrepare for IntentSignaturesV2 { type Prepared = PreparedIntentSignaturesV2; } @@ -34,7 +46,7 @@ impl TransactionPreparableFromValueBody for PreparedNonRootSubintentSignaturesV2 Vec, >( decoder, - ValueType::IntentSignatures, + ValueType::SubintentSignatureBatches, max_subintents_per_transaction, )?; diff --git a/radix-transactions/src/model/v2/transaction_manifest_v2.rs b/radix-transactions/src/model/v2/transaction_manifest_v2.rs index 0619063e871..43b738e102c 100644 --- a/radix-transactions/src/model/v2/transaction_manifest_v2.rs +++ b/radix-transactions/src/model/v2/transaction_manifest_v2.rs @@ -84,6 +84,15 @@ impl BuildableManifest for TransactionManifestV2 { impl BuildableManifestSupportingChildren for TransactionManifestV2 {} impl TransactionManifestV2 { + pub fn empty() -> Self { + Self { + instructions: Default::default(), + blobs: Default::default(), + children: Default::default(), + object_names: ManifestObjectNames::Unknown, + } + } + pub fn from_intent_core(intent: &IntentCoreV2) -> Self { Self { instructions: intent.instructions.to_vec(), @@ -93,6 +102,18 @@ impl TransactionManifestV2 { } } + pub fn to_intent_core(self, header: IntentHeaderV2, message: MessageV2) -> IntentCoreV2 { + IntentCoreV2 { + header, + blobs: self.blobs.into(), + message, + instructions: self.instructions.into(), + children: ChildSubintentSpecifiersV2 { + children: self.children, + }, + } + } + pub fn for_intent(self) -> (InstructionsV2, BlobsV1, ChildSubintentSpecifiersV2) { ( self.instructions.into(), diff --git a/radix-transactions/src/validation/mod.rs b/radix-transactions/src/validation/mod.rs index bbae017ce6a..4732e32318f 100644 --- a/radix-transactions/src/validation/mod.rs +++ b/radix-transactions/src/validation/mod.rs @@ -16,4 +16,4 @@ pub use transaction_structure_validator::*; pub use transaction_validation_configuration::*; pub use transaction_validator::*; #[cfg(test)] -pub use validation_test_helpers::*; +pub(crate) use validation_test_helpers::*; diff --git a/radix-transactions/src/validation/signature_validator.rs b/radix-transactions/src/validation/signature_validator.rs index 57d90e38572..6699784841b 100644 --- a/radix-transactions/src/validation/signature_validator.rs +++ b/radix-transactions/src/validation/signature_validator.rs @@ -585,4 +585,112 @@ mod tests { } } } + + #[test] + fn too_many_signatures_should_be_rejected() { + fn validate_transaction( + root_signature_count: usize, + signature_counts: Vec, + ) -> Result { + TransactionV2Builder::new_with_test_defaults() + .add_children( + signature_counts + .iter() + .enumerate() + .map(|(i, signature_count)| { + create_leaf_partial_transaction(i as u64, *signature_count) + }), + ) + .add_manifest_calling_each_child_once() + .multi_sign( + (0..root_signature_count) + .into_iter() + .map(|i| Secp256k1PrivateKey::from_u64((100 + i) as u64).unwrap()), + ) + .default_notarize_and_validate() + } + + assert_matches!(validate_transaction(1, vec![10]), Ok(_)); + assert_matches!( + validate_transaction(1, vec![10, 20]), + Err(TransactionValidationError::SignatureValidationError( + TransactionValidationErrorLocation::NonRootSubintent(SubintentIndex(1), _), + SignatureValidationError::TooManySignatures { + total: 20, + limit: 16, + }, + )) + ); + assert_matches!( + validate_transaction(17, vec![0, 3]), + Err(TransactionValidationError::SignatureValidationError( + TransactionValidationErrorLocation::RootTransactionIntent(_), + SignatureValidationError::TooManySignatures { + total: 17, + limit: 16, + }, + )) + ); + assert_matches!( + validate_transaction(1, vec![10, 10, 10, 10, 10, 10, 10]), + Err(TransactionValidationError::SignatureValidationError( + TransactionValidationErrorLocation::AcrossTransaction, + SignatureValidationError::TooManySignatures { + total: 72, // 70 from subintent, 1 from transaction intent, 1 from notarization + limit: 64 + }, + )) + ); + } + + #[test] + fn test_incorrect_number_of_subintent_signature_batches() { + // CASE 1: Too fee signatures + let validator = TransactionValidator::new_for_latest_simulator(); + + let mut transaction = TransactionV2Builder::new_with_test_defaults() + .add_children(vec![PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .build()]) + .add_manifest_calling_each_child_once() + .default_notarize() + .build_minimal_no_validate(); + + // Remove one signature batch + let removed_signature_batch = transaction + .signed_transaction_intent + .non_root_subintent_signatures + .by_subintent + .pop() + .unwrap(); + + assert_matches!( + transaction.prepare_and_validate(&validator), + Err(TransactionValidationError::SignatureValidationError( + TransactionValidationErrorLocation::AcrossTransaction, + SignatureValidationError::IncorrectNumberOfSubintentSignatureBatches + )) + ); + + // CASE 2: Too many signature batches + let mut transaction = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .default_notarize() + .build_minimal_no_validate(); + + // Add an extra signature batch + transaction + .signed_transaction_intent + .non_root_subintent_signatures + .by_subintent + .push(removed_signature_batch); + + assert_matches!( + transaction.prepare_and_validate(&validator), + Err(TransactionValidationError::SignatureValidationError( + TransactionValidationErrorLocation::AcrossTransaction, + SignatureValidationError::IncorrectNumberOfSubintentSignatureBatches + )) + ); + } } diff --git a/radix-transactions/src/validation/transaction_structure_validator.rs b/radix-transactions/src/validation/transaction_structure_validator.rs index 9239ccb049b..5b4c62cbfa4 100644 --- a/radix-transactions/src/validation/transaction_structure_validator.rs +++ b/radix-transactions/src/validation/transaction_structure_validator.rs @@ -132,6 +132,9 @@ impl TransactionValidator { // We also: // * Save the unique parent on each subintent which is a child // * Save the children of an intent into its intent details + // + // After this step, we know that each subintent has at most one parent. + // We determine that every subintent has exactly one parent in step 4. // STEP 2A - Handle children of the root intent { @@ -186,8 +189,14 @@ impl TransactionValidator { // We traverse the child relationships from the root, and mark a depth. // We error if any exceed the maximum depth. // - // As each child has at most one parent, we can guarantee the work is bounded - // by the total number of subintents. + // The iteration count is guaranteed to be bounded by the number of subintents because: + // * Each subintent has at most one parent from step 2. + // * Each parent -> child relationship is traversed at most once in the iteration. + // Quick proof by contradiction: + // - Assume not. Then some parent A is visited more than once. + // - Take the earliest such A in the iteration. + // - On both of its visits, A can only have been visited from its parent B. + // - But then B must have been visited more than once, contradicting the minimality of A. let mut work_list = vec![]; for index in root_intent_details.children.iter() { work_list.push((*index, 1)); @@ -224,8 +233,8 @@ impl TransactionValidator { // * Every subintent has a unique parent. // * Every subintent is reachable from the root. // - // Therefore there is a unique path from every subintent to the root - // So we have confirmed the subintents form a tree. + // Therefore there is a unique path from every subintent to the root, which implies + // the subintents form a tree. for (hash, details) in non_root_subintent_details.iter() { if details.depth == 0 { return Err( diff --git a/radix-transactions/src/validation/transaction_validator_v1.rs b/radix-transactions/src/validation/transaction_validator_v1.rs index 33c0f017f69..5ef227cdbf5 100644 --- a/radix-transactions/src/validation/transaction_validator_v1.rs +++ b/radix-transactions/src/validation/transaction_validator_v1.rs @@ -678,7 +678,6 @@ mod tests { 123, vec![55], 66, - #[allow(deprecated)] ManifestBuilder::new() .take_from_worktop(XRD, dec!(100), "bucket") .create_proof_from_bucket_of_amount("bucket", dec!(5), "proof1") diff --git a/radix-transactions/src/validation/transaction_validator_v2.rs b/radix-transactions/src/validation/transaction_validator_v2.rs index 1efe9b04ec0..2b07a4093d4 100644 --- a/radix-transactions/src/validation/transaction_validator_v2.rs +++ b/radix-transactions/src/validation/transaction_validator_v2.rs @@ -511,64 +511,547 @@ impl SignedIntentTreeStructure for PreparedPreviewTransactionV2 { mod tests { use crate::internal_prelude::*; - #[test] - fn test_subintent_structure_errors() {} + fn mutate_subintents( + transaction: &mut NotarizedTransactionV2, + subintents_mutate: impl FnOnce(&mut Vec), + subintent_signatures_mutate: impl FnOnce(&mut Vec), + ) { + subintents_mutate( + &mut transaction + .signed_transaction_intent + .transaction_intent + .non_root_subintents + .0, + ); + subintent_signatures_mutate( + &mut transaction + .signed_transaction_intent + .non_root_subintent_signatures + .by_subintent, + ); + } #[test] - fn too_many_signatures_should_be_rejected() { - fn validate_transaction( - root_signature_count: usize, - signature_counts: Vec, - ) -> Result { - TransactionV2Builder::new_with_test_defaults() - .add_children( - signature_counts - .iter() - .enumerate() - .map(|(i, signature_count)| { - create_leaf_partial_transaction(i as u64, *signature_count) - }), - ) + fn test_subintent_structure_errors() { + let validator = TransactionValidator::new_for_latest_simulator(); + + // SubintentStructureError::DuplicateSubintent + { + let duplicated_subintent = create_leaf_partial_transaction(0, 0); + let duplicated_subintent_hash = duplicated_subintent.root_subintent_hash; + let mut transaction = TransactionV2Builder::new_with_test_defaults() + .add_children([duplicated_subintent]) .add_manifest_calling_each_child_once() - .multi_sign( - (0..root_signature_count) - .into_iter() - .map(|i| Secp256k1PrivateKey::from_u64((100 + i) as u64).unwrap()), - ) - .default_notarize_and_validate() + .default_notarize() + .build_minimal_no_validate(); + + mutate_subintents( + &mut transaction, + |subintents| { + subintents.push(subintents[0].clone()); + }, + |subintent_signatures| { + subintent_signatures.push(subintent_signatures[0].clone()); + }, + ); + + assert_matches!( + transaction.prepare_and_validate(&validator), + Err(TransactionValidationError::SubintentStructureError( + TransactionValidationErrorLocation::NonRootSubintent(SubintentIndex(1), subintent_hash), + SubintentStructureError::DuplicateSubintent, + )) => { + assert_eq!(subintent_hash, duplicated_subintent_hash); + } + ); } - assert_matches!(validate_transaction(1, vec![10]), Ok(_)); - assert_matches!( - validate_transaction(1, vec![10, 20]), - Err(TransactionValidationError::SignatureValidationError( - TransactionValidationErrorLocation::NonRootSubintent(SubintentIndex(1), _), - SignatureValidationError::TooManySignatures { - total: 20, - limit: 16, + // SubintentStructureError::SubintentHasMultipleParents + // ==================================================== + // CASE 1 - Two duplicates as children in the same intent + // =======> This isn't possible because `ChildSubintentSpecifiersV2` wraps an `IndexSet` + // Case 2 - Both duplicates across different intents + // =======> This is tested below + { + let duplicated_subintent = create_leaf_partial_transaction(1, 0); + + let parent_subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_children([duplicated_subintent.clone()]) + .add_manifest_calling_each_child_once() + .build(); + let mut transaction = TransactionV2Builder::new_with_test_defaults() + .add_children([parent_subintent, duplicated_subintent.clone()]) + .add_manifest_calling_each_child_once() + .default_notarize() + .build_minimal_no_validate(); + + mutate_subintents( + &mut transaction, + |subintents| { + subintents.remove(1); }, - )) - ); - assert_matches!( - validate_transaction(17, vec![0, 3]), - Err(TransactionValidationError::SignatureValidationError( - TransactionValidationErrorLocation::RootTransactionIntent(_), - SignatureValidationError::TooManySignatures { - total: 17, - limit: 16, + |subintent_signatures| { + subintent_signatures.remove(1); }, - )) - ); - assert_matches!( - validate_transaction(1, vec![10, 10, 10, 10, 10, 10, 10]), - Err(TransactionValidationError::SignatureValidationError( - TransactionValidationErrorLocation::AcrossTransaction, - SignatureValidationError::TooManySignatures { - total: 72, // 70 from subintent, 1 from transaction intent, 1 from notarization - limit: 64 + ); + + assert_matches!( + transaction.prepare_and_validate(&validator), + Err(TransactionValidationError::SubintentStructureError( + TransactionValidationErrorLocation::NonRootSubintent(SubintentIndex(1), subintent_hash), + SubintentStructureError::SubintentHasMultipleParents, + )) => { + assert_eq!(subintent_hash, duplicated_subintent.root_subintent_hash); + } + ); + } + + // SubintentStructureError::ChildSubintentNotIncludedInTransaction(SubintentHash) + { + let missing_subintent = create_leaf_partial_transaction(0, 0); + let missing_subintent_hash = missing_subintent.root_subintent_hash; + let mut transaction = TransactionV2Builder::new_with_test_defaults() + .add_children([missing_subintent]) + .add_manifest_calling_each_child_once() + .default_notarize() + .build_minimal_no_validate(); + + mutate_subintents( + &mut transaction, + |subintents| { + subintents.pop(); }, - )) - ); + |subintent_signatures| { + subintent_signatures.pop(); + }, + ); + + assert_matches!( + transaction.prepare_and_validate(&validator), + Err(TransactionValidationError::SubintentStructureError( + TransactionValidationErrorLocation::Unlocatable, + SubintentStructureError::ChildSubintentNotIncludedInTransaction(subintent_hash), + )) => { + assert_eq!(subintent_hash, missing_subintent_hash); + } + ); + } + + // SubintentStructureError::SubintentExceedsMaxDepth + { + let depth_4 = create_leaf_partial_transaction(0, 0); + let depth_4_hash = depth_4.root_subintent_hash; + let depth_3 = PartialTransactionV2Builder::new_with_test_defaults() + .add_children([depth_4]) + .add_manifest_calling_each_child_once() + .build(); + let depth_2 = PartialTransactionV2Builder::new_with_test_defaults() + .add_children([depth_3]) + .add_manifest_calling_each_child_once() + .build(); + let depth_1 = PartialTransactionV2Builder::new_with_test_defaults() + .add_children([depth_2]) + .add_manifest_calling_each_child_once() + .build(); + let transaction = TransactionV2Builder::new_with_test_defaults() + .add_children([depth_1]) + .add_manifest_calling_each_child_once() + .default_notarize() + .build_minimal_no_validate(); + + assert_matches!( + transaction.prepare_and_validate(&validator), + Err(TransactionValidationError::SubintentStructureError( + TransactionValidationErrorLocation::NonRootSubintent(SubintentIndex(_), subintent_hash), + SubintentStructureError::SubintentExceedsMaxDepth, + )) => { + assert_eq!(subintent_hash, depth_4_hash); + } + ); + } + + // SubintentStructureError::SubintentIsNotReachableFromTheTransactionIntent + // ======================================================================== + // CASE 1 - The subintent is superfluous / has no parent + // This is tested below + // + // CASE 2 - Without a "no parent" short-circuit. + // To hit this error (but none of the previous errors) requires that we have + // a cycle in the subintent graph. + // + // But, because parents include a subintent hash of their direct children, + // which is itself part of their hash, a cycle would require a hash collision! + // + // But we can hack around this by explicitly overwriting the prepared subintent + // hashes. + { + // CASE 1 - The subintent has no parent + let no_parent_subintent = create_leaf_partial_transaction(0, 0); + let no_parent_subintent_hash = no_parent_subintent.root_subintent_hash; + + let mut transaction = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .default_notarize() + .build_minimal_no_validate(); + + mutate_subintents( + &mut transaction, + |subintents| { + subintents.push( + no_parent_subintent + .partial_transaction + .partial_transaction + .root_subintent, + ); + }, + |subintent_signatures| { + subintent_signatures.push(IntentSignaturesV2::none()); + }, + ); + + assert_matches!( + transaction.prepare_and_validate(&validator), + Err(TransactionValidationError::SubintentStructureError( + TransactionValidationErrorLocation::NonRootSubintent(SubintentIndex(0), subintent_hash), + SubintentStructureError::SubintentIsNotReachableFromTheTransactionIntent, + )) => { + assert_eq!(subintent_hash, no_parent_subintent_hash); + } + ); + + // CASE 2 - Without a potential "no parent" short-circuit + let faked_hash = SubintentHash::from_bytes([1; 32]); + + let self_parent_subintent = SubintentV2 { + intent_core: IntentCoreV2 { + header: IntentHeaderV2 { + network_id: NetworkDefinition::simulator().id, + start_epoch_inclusive: Epoch::of(0), + end_epoch_exclusive: Epoch::of(1), + min_proposer_timestamp_inclusive: None, + max_proposer_timestamp_exclusive: None, + intent_discriminator: 0, + }, + message: MessageV2::None, + instructions: InstructionsV2(vec![InstructionV2::YieldToParent( + YieldToParent::empty(), + )]), + blobs: BlobsV1::none(), + children: ChildSubintentSpecifiersV2 { + children: indexset![faked_hash.into()], + }, + }, + }; + + let mut transaction = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .default_notarize() + .build_minimal_no_validate(); + + mutate_subintents( + &mut transaction, + |subintents| { + subintents.push(self_parent_subintent); + }, + |subintent_signatures| { + subintent_signatures.push(IntentSignaturesV2::none()); + }, + ); + + let mut prepared = transaction + .prepare(validator.preparation_settings()) + .unwrap(); + + // We overwrite the subintent hash to the faked hash + prepared + .signed_intent + .transaction_intent + .non_root_subintents + .subintents[0] + .summary + .hash = faked_hash.0; + + assert_matches!( + prepared.validate(&validator), + Err(TransactionValidationError::SubintentStructureError( + TransactionValidationErrorLocation::NonRootSubintent(SubintentIndex(0), subintent_hash), + SubintentStructureError::SubintentIsNotReachableFromTheTransactionIntent, + )) => { + assert_eq!(subintent_hash, faked_hash); + } + ); + } + + // SubintentStructureError::MismatchingYieldChildAndYieldParentCountsForSubintent + { + let single_yield_subintent = create_leaf_partial_transaction(0, 0); + let single_yield_subintent_hash = single_yield_subintent.root_subintent_hash; + + // CASE 1: We yield twice to it, but it yields to us only once + let transaction = TransactionV2Builder::new_with_test_defaults() + .add_signed_child("child", single_yield_subintent.clone()) + .manifest_builder(|builder| { + builder + .yield_to_child("child", ()) + .yield_to_child("child", ()) + }) + .default_notarize() + .build_minimal_no_validate(); + + assert_matches!( + transaction.prepare_and_validate(&validator), + Err(TransactionValidationError::SubintentStructureError( + TransactionValidationErrorLocation::NonRootSubintent(SubintentIndex(0), subintent_hash), + SubintentStructureError::MismatchingYieldChildAndYieldParentCountsForSubintent, + )) => { + assert_eq!(subintent_hash, single_yield_subintent_hash); + } + ); + + // CASE 2: We yield zero times to it + let transaction = TransactionV2Builder::new_with_test_defaults() + .add_signed_child("child", single_yield_subintent) + .manifest_builder(|builder| builder) + .default_notarize() + .build_minimal_no_validate(); + + assert_matches!( + transaction.prepare_and_validate(&validator), + Err(TransactionValidationError::SubintentStructureError( + TransactionValidationErrorLocation::NonRootSubintent(SubintentIndex(0), subintent_hash), + SubintentStructureError::MismatchingYieldChildAndYieldParentCountsForSubintent, + )) => { + assert_eq!(subintent_hash, single_yield_subintent_hash); + } + ); + + // CASE 3: More complex example, between two subintents, with 2 parent and 3 child yields: + let two_parent_yield_subintent = PartialTransactionV2Builder::new_with_test_defaults() + .manifest_builder(|builder| builder.yield_to_parent(()).yield_to_parent(())) + .build(); + let two_parent_yield_subintent_hash = two_parent_yield_subintent.root_subintent_hash; + + let three_child_yield_parent = PartialTransactionV2Builder::new_with_test_defaults() + .add_signed_child("child", two_parent_yield_subintent) + .manifest_builder(|builder| { + builder + .yield_to_child("child", ()) + .yield_to_child("child", ()) + .yield_to_child("child", ()) + .yield_to_parent(()) + }) + .build(); + + let transaction = TransactionV2Builder::new_with_test_defaults() + .add_children([three_child_yield_parent]) + .add_manifest_calling_each_child_once() + .default_notarize() + .build_minimal_no_validate(); + + assert_matches!( + transaction.prepare_and_validate(&validator), + Err(TransactionValidationError::SubintentStructureError( + TransactionValidationErrorLocation::NonRootSubintent(SubintentIndex(_), subintent_hash), + SubintentStructureError::MismatchingYieldChildAndYieldParentCountsForSubintent, + )) => { + assert_eq!(subintent_hash, two_parent_yield_subintent_hash); + } + ); + } + } + + // NOTE: This is very similar to the V1 tests, just adjusted to the V2 models + #[test] + fn test_valid_messages() { + // None + { + let message = MessageV2::None; + assert_matches!(validate_transaction_with_message(message), Ok(_),); + } + // Plaintext + { + let message = MessageV2::Plaintext(PlaintextMessageV1 { + mime_type: "text/plain".to_owned(), + message: MessageContentsV1::String("Hello world!".to_string()), + }); + assert_matches!(validate_transaction_with_message(message), Ok(_),); + } + // Encrypted + { + // Note - this isn't actually a validly encrypted message, + // this just shows that a sufficiently valid encrypted message can pass validation + let message = MessageV2::Encrypted(EncryptedMessageV2 { + encrypted: AesGcmPayload(vec![]), + decryptors_by_curve: indexmap!( + CurveType::Ed25519 => DecryptorsByCurveV2::Ed25519 { + dh_ephemeral_public_key: Ed25519PublicKey([0; Ed25519PublicKey::LENGTH]), + decryptors: indexmap!( + PublicKeyFingerprint([0; PublicKeyFingerprint::LENGTH]) => AesWrapped256BitKey([0; AesWrapped256BitKey::LENGTH]), + ), + }, + CurveType::Secp256k1 => DecryptorsByCurveV2::Secp256k1 { + dh_ephemeral_public_key: Secp256k1PublicKey([0; Secp256k1PublicKey::LENGTH]), + decryptors: indexmap!( + PublicKeyFingerprint([0; PublicKeyFingerprint::LENGTH]) => AesWrapped256BitKey([0; AesWrapped256BitKey::LENGTH]), + PublicKeyFingerprint([1; PublicKeyFingerprint::LENGTH]) => AesWrapped256BitKey([0; AesWrapped256BitKey::LENGTH]), + ), + }, + ), + }); + assert_matches!(validate_transaction_with_message(message), Ok(_),); + } + } + + // NOTE: This is very similar to the V1 tests, just adjusted to the V2 models + #[test] + fn test_invalid_message_errors() { + // MimeTypeTooLong + { + let message = MessageV2::Plaintext(PlaintextMessageV1 { + mime_type: "very long mimetype, very long mimetype, very long mimetype, very long mimetype, very long mimetype, very long mimetype, very long mimetype, very long mimetype, ".to_owned(), + message: MessageContentsV1::String("Hello".to_string()), + }); + assert_matches!( + validate_transaction_with_message(message), + Err(InvalidMessageError::MimeTypeTooLong { .. }), + ); + } + + // PlaintextMessageTooLong + { + let mut long_message: String = "".to_owned(); + while long_message.len() <= 2048 { + long_message.push_str("more text please!"); + } + let message = MessageV2::Plaintext(PlaintextMessageV1 { + mime_type: "text/plain".to_owned(), + message: MessageContentsV1::String(long_message), + }); + assert_matches!( + validate_transaction_with_message(message), + Err(InvalidMessageError::PlaintextMessageTooLong { .. }), + ); + } + + // EncryptedMessageTooLong + { + let mut message_which_is_too_long: String = "".to_owned(); + while message_which_is_too_long.len() <= 2048 + 50 { + // Some more bytes for the AES padding + message_which_is_too_long.push_str("more text please!"); + } + let message = MessageV2::Encrypted(EncryptedMessageV2 { + encrypted: AesGcmPayload(message_which_is_too_long.as_bytes().to_vec()), + decryptors_by_curve: indexmap!( + CurveType::Ed25519 => DecryptorsByCurveV2::Ed25519 { + dh_ephemeral_public_key: Ed25519PublicKey([0; Ed25519PublicKey::LENGTH]), + decryptors: indexmap!( + PublicKeyFingerprint([0; PublicKeyFingerprint::LENGTH]) => AesWrapped256BitKey([0; AesWrapped256BitKey::LENGTH]), + ), + } + ), + }); + assert_matches!( + validate_transaction_with_message(message), + Err(InvalidMessageError::EncryptedMessageTooLong { .. }), + ); + } + + // NoDecryptors + { + let message = MessageV2::Encrypted(EncryptedMessageV2 { + encrypted: AesGcmPayload(vec![]), + decryptors_by_curve: indexmap!(), + }); + assert_matches!( + validate_transaction_with_message(message), + Err(InvalidMessageError::NoDecryptors), + ); + } + + // NoDecryptorsForCurveType + { + let message = MessageV2::Encrypted(EncryptedMessageV2 { + encrypted: AesGcmPayload(vec![]), + decryptors_by_curve: indexmap!( + CurveType::Ed25519 => DecryptorsByCurveV2::Ed25519 { + dh_ephemeral_public_key: Ed25519PublicKey([0; Ed25519PublicKey::LENGTH]), + decryptors: indexmap!(), + } + ), + }); + assert_matches!( + validate_transaction_with_message(message), + Err(InvalidMessageError::NoDecryptorsForCurveType { + curve_type: CurveType::Ed25519 + }), + ); + } + + // MismatchingDecryptorCurves + { + let message = MessageV2::Encrypted(EncryptedMessageV2 { + encrypted: AesGcmPayload(vec![]), + decryptors_by_curve: indexmap!( + CurveType::Ed25519 => DecryptorsByCurveV2::Secp256k1 { + dh_ephemeral_public_key: Secp256k1PublicKey([0; Secp256k1PublicKey::LENGTH]), + decryptors: indexmap!( + PublicKeyFingerprint([0; PublicKeyFingerprint::LENGTH]) => AesWrapped256BitKey([0; AesWrapped256BitKey::LENGTH]), + ), + } + ), + }); + assert_matches!( + validate_transaction_with_message(message), + Err(InvalidMessageError::MismatchingDecryptorCurves { + actual: CurveType::Secp256k1, + expected: CurveType::Ed25519 + }), + ); + } + + // TooManyDecryptors + { + let mut decryptors = IndexMap::::default(); + for i in 0..30 { + decryptors.insert( + PublicKeyFingerprint([0, 0, 0, 0, 0, 0, 0, i as u8]), + AesWrapped256BitKey([0; AesWrapped256BitKey::LENGTH]), + ); + } + let message = MessageV2::Encrypted(EncryptedMessageV2 { + encrypted: AesGcmPayload(vec![]), + decryptors_by_curve: indexmap!( + CurveType::Ed25519 => DecryptorsByCurveV2::Ed25519 { + dh_ephemeral_public_key: Ed25519PublicKey([0; Ed25519PublicKey::LENGTH]), + decryptors, + } + ), + }); + assert_matches!( + validate_transaction_with_message(message), + Err(InvalidMessageError::TooManyDecryptors { + actual: 30, + permitted: 20 + }), + ); + } + } + + fn validate_transaction_with_message( + message: MessageV2, + ) -> Result { + TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .message(message) + .default_notarize_and_validate() + .map_err(|e| match e { + TransactionValidationError::IntentValidationError( + _, + IntentValidationError::InvalidMessage(e), + ) => e, + _ => panic!("Expected InvalidMessageError, but got: {:?}", e), + }) } #[test] @@ -638,4 +1121,1333 @@ mod tests { )) ); } + + #[test] + fn test_header_validations() { + let simulator_validator = TransactionValidator::new_for_latest_simulator(); + let network_agnostic_validator = + TransactionValidator::new_with_latest_config_network_agnostic(); + let config = simulator_validator.config().clone(); + + // InvalidEpochRange + { + // CASE 1 - Negative range + let result = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .start_epoch_inclusive(Epoch::of(100)) + .end_epoch_exclusive(Epoch::of(98)) + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::RootTransactionIntent(_), + IntentValidationError::HeaderValidationError( + HeaderValidationError::InvalidEpochRange + ), + )), + ); + + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .start_epoch_inclusive(Epoch::of(100)) + .end_epoch_exclusive(Epoch::of(98)) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::NonRootSubintent { .. }, + IntentValidationError::HeaderValidationError( + HeaderValidationError::InvalidEpochRange + ), + )), + ); + + // CASE 2 - Equal range + let result = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .start_epoch_inclusive(Epoch::of(100)) + .end_epoch_exclusive(Epoch::of(100)) + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::RootTransactionIntent(_), + IntentValidationError::HeaderValidationError( + HeaderValidationError::InvalidEpochRange + ), + )), + ); + + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .start_epoch_inclusive(Epoch::of(100)) + .end_epoch_exclusive(Epoch::of(100)) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::NonRootSubintent { .. }, + IntentValidationError::HeaderValidationError( + HeaderValidationError::InvalidEpochRange + ), + )), + ); + + // CASE 3 - Range too large + let result = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .start_epoch_inclusive(Epoch::of(100)) + .end_epoch_exclusive(Epoch::of(100 + config.max_epoch_range + 1)) + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::RootTransactionIntent(_), + IntentValidationError::HeaderValidationError( + HeaderValidationError::InvalidEpochRange + ), + )), + ); + + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .start_epoch_inclusive(Epoch::of(100)) + .end_epoch_exclusive(Epoch::of(100 + config.max_epoch_range + 1)) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::NonRootSubintent { .. }, + IntentValidationError::HeaderValidationError( + HeaderValidationError::InvalidEpochRange + ), + )), + ); + } + + // InvalidTimestampRange + { + // CASE 1 - Negative range + let result = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .min_proposer_timestamp_inclusive(Some(Instant::new(5000))) + .max_proposer_timestamp_exclusive(Some(Instant::new(4999))) + .end_epoch_exclusive(Epoch::of(98)) + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::RootTransactionIntent(_), + IntentValidationError::HeaderValidationError( + HeaderValidationError::InvalidTimestampRange + ), + )), + ); + + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .min_proposer_timestamp_inclusive(Some(Instant::new(5000))) + .max_proposer_timestamp_exclusive(Some(Instant::new(4999))) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::NonRootSubintent { .. }, + IntentValidationError::HeaderValidationError( + HeaderValidationError::InvalidTimestampRange + ), + )), + ); + + // CASE 2 - Equal range + let result = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .min_proposer_timestamp_inclusive(Some(Instant::new(5000))) + .max_proposer_timestamp_exclusive(Some(Instant::new(5000))) + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::RootTransactionIntent(_), + IntentValidationError::HeaderValidationError( + HeaderValidationError::InvalidTimestampRange + ), + )), + ); + + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .min_proposer_timestamp_inclusive(Some(Instant::new(5000))) + .max_proposer_timestamp_exclusive(Some(Instant::new(5000))) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::NonRootSubintent { .. }, + IntentValidationError::HeaderValidationError( + HeaderValidationError::InvalidTimestampRange + ), + )), + ); + + // And for good measure, let's test some valid ranges: + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .min_proposer_timestamp_inclusive(Some(Instant::new(5000))) + .max_proposer_timestamp_exclusive(Some(Instant::new(5001))) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!(result, Ok(_),); + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .min_proposer_timestamp_inclusive(Some(Instant::new(5000))) + .max_proposer_timestamp_exclusive(None) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!(result, Ok(_),); + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .min_proposer_timestamp_inclusive(None) + .max_proposer_timestamp_exclusive(Some(Instant::new(5000))) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!(result, Ok(_),); + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .min_proposer_timestamp_inclusive(None) + .max_proposer_timestamp_exclusive(None) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!(result, Ok(_),); + } + + // InvalidNetwork + { + let result = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .network_id(NetworkDefinition::mainnet().id) + .default_notarize() + .build_minimal_no_validate() + .prepare_and_validate(&simulator_validator); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::RootTransactionIntent(_), + IntentValidationError::HeaderValidationError( + HeaderValidationError::InvalidNetwork + ), + )), + ); + + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .network_id(NetworkDefinition::mainnet().id) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .add_manifest_calling_each_child_once() + .default_notarize() + .build_minimal_no_validate() + .prepare_and_validate(&simulator_validator); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::NonRootSubintent { .. }, + IntentValidationError::HeaderValidationError( + HeaderValidationError::InvalidNetwork + ), + )), + ); + + // And for good measure, demonstrate that the network agnostic validator is okay with this: + // (even with different intents being for different networks(!) - which is a bit weird, but + // it's only intended for testing) + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .network_id(NetworkDefinition::mainnet().id) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .add_manifest_calling_each_child_once() + .default_notarize() + .build_minimal_no_validate() + .prepare_and_validate(&network_agnostic_validator); + assert_matches!(result, Ok(_),); + } + + // InvalidTip + { + // Note - min tip is 0, so we can't hit that error + let result = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .tip_basis_points(config.max_tip_basis_points + 1) + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::RootTransactionIntent(_), + IntentValidationError::HeaderValidationError(HeaderValidationError::InvalidTip), + )), + ); + } + + // NoValidEpochRangeAcrossAllIntents + { + // Subintent doesn't overlap with TransactionIntent + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .start_epoch_inclusive(Epoch::of(100)) + .end_epoch_exclusive(Epoch::of(102)) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .start_epoch_inclusive(Epoch::of(102)) + .end_epoch_exclusive(Epoch::of(103)) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::NonRootSubintent { .. }, + IntentValidationError::HeaderValidationError( + HeaderValidationError::NoValidEpochRangeAcrossAllIntents + ), + )), + ); + + // Only one pair of subintents don't overlap + let subintent_1 = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .start_epoch_inclusive(Epoch::of(100)) + .end_epoch_exclusive(Epoch::of(102)) + .build(); + let subintent_2 = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .start_epoch_inclusive(Epoch::of(101)) + .end_epoch_exclusive(Epoch::of(103)) + .build(); + let subintent_3 = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .start_epoch_inclusive(Epoch::of(102)) + .end_epoch_exclusive(Epoch::of(104)) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent_1, subintent_2, subintent_3]) + .start_epoch_inclusive(Epoch::of(100)) + .end_epoch_exclusive(Epoch::of(105)) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::NonRootSubintent { .. }, + IntentValidationError::HeaderValidationError( + HeaderValidationError::NoValidEpochRangeAcrossAllIntents + ), + )), + ); + + // There is an overlap + let subintent_1 = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .start_epoch_inclusive(Epoch::of(100)) + .end_epoch_exclusive(Epoch::of(102)) + .build(); + let subintent_2 = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .start_epoch_inclusive(Epoch::of(101)) + .end_epoch_exclusive(Epoch::of(103)) + .build(); + let subintent_3 = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .start_epoch_inclusive(Epoch::of(101)) + .end_epoch_exclusive(Epoch::of(104)) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent_1, subintent_2, subintent_3]) + .start_epoch_inclusive(Epoch::of(100)) + .end_epoch_exclusive(Epoch::of(105)) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!( + result, + Ok(validated) => { + assert_eq!(validated.overall_validity_range.epoch_range.start_epoch_inclusive, Epoch::of(101)); + assert_eq!(validated.overall_validity_range.epoch_range.end_epoch_exclusive, Epoch::of(102)); + }, + ); + } + + // NoValidTimestampRangeAcrossAllIntents + { + // Subintent doesn't overlap with TransactionIntent + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .min_proposer_timestamp_inclusive(Some(Instant::new(5000))) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .max_proposer_timestamp_exclusive(Some(Instant::new(5000))) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::NonRootSubintent { .. }, + IntentValidationError::HeaderValidationError( + HeaderValidationError::NoValidTimestampRangeAcrossAllIntents + ), + )), + ); + + // Only one pair of subintents don't overlap + let subintent_1 = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .max_proposer_timestamp_exclusive(Some(Instant::new(4000))) + .build(); + let subintent_2 = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .max_proposer_timestamp_exclusive(Some(Instant::new(4003))) + .build(); + let subintent_3 = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .min_proposer_timestamp_inclusive(Some(Instant::new(4001))) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent_1, subintent_2, subintent_3]) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!( + result, + Err(TransactionValidationError::IntentValidationError( + TransactionValidationErrorLocation::NonRootSubintent { .. }, + IntentValidationError::HeaderValidationError( + HeaderValidationError::NoValidTimestampRangeAcrossAllIntents + ), + )), + ); + + // There is an overlap + let subintent_1 = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .max_proposer_timestamp_exclusive(Some(Instant::new(4003))) + .build(); + let subintent_2 = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .max_proposer_timestamp_exclusive(Some(Instant::new(4005))) + .build(); + let subintent_3 = PartialTransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .min_proposer_timestamp_inclusive(Some(Instant::new(3998))) + .max_proposer_timestamp_exclusive(Some(Instant::new(4001))) + .build(); + let result = TransactionV2Builder::new_with_test_defaults() + .add_children([subintent_1, subintent_2, subintent_3]) + .min_proposer_timestamp_inclusive(Some(Instant::new(3999))) + .max_proposer_timestamp_exclusive(Some(Instant::new(5999))) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate(); + assert_matches!( + result, + Ok(validated) => { + assert_eq!(validated.overall_validity_range.proposer_timestamp_range.start_timestamp_inclusive, Some(Instant::new(3999))); + assert_eq!(validated.overall_validity_range.proposer_timestamp_range.end_timestamp_exclusive, Some(Instant::new(4001))); + }, + ); + } + } + + trait ManifestBuilderExtensions { + fn add_test_method_call_with(self, value: impl ManifestEncode) -> Self; + } + + impl ManifestBuilderExtensions for ManifestBuilder + where + CallMethod: Into, + { + fn add_test_method_call_with(self, value: impl ManifestEncode) -> Self { + self.add_raw_instruction_ignoring_all_side_effects(CallMethod { + address: XRD.into(), + method_name: "method".into(), + args: manifest_decode(&manifest_encode(&(value,)).unwrap()).unwrap(), + }) + } + } + + #[test] + fn test_manifest_validations() { + let account_address = ComponentAddress::preallocated_account_from_public_key( + &Ed25519PublicKey([0; Ed25519PublicKey::LENGTH]), + ); + + fn validate_transaction_manifest( + manifest: TransactionManifestV2, + ) -> Result { + let builder = TransactionV2Builder::new_with_test_defaults().manifest(manifest); + validate_transaction_builder_manifest(builder) + } + + fn validate_transaction_builder_manifest( + builder: TransactionV2Builder, + ) -> Result { + builder + .default_notarize_and_validate() + .map_err(|err| match err { + TransactionValidationError::IntentValidationError( + _, + IntentValidationError::ManifestValidationError(err), + ) => err, + _ => panic!("Expected ManifestValidationError, but got: {:?}", err), + }) + } + + fn validate_subintent_manifest( + subintent_manifest: SubintentManifestV2, + ) -> Result { + let subintent = PartialTransactionV2Builder::new_with_test_defaults() + .manifest(subintent_manifest) + .build(); + TransactionV2Builder::new_with_test_defaults() + .add_children([subintent]) + .add_manifest_calling_each_child_once() + .default_notarize_and_validate() + .map_err(|err| match err { + TransactionValidationError::IntentValidationError( + _, + IntentValidationError::ManifestValidationError(err), + ) => err, + _ => panic!("Expected ManifestValidationError, but got: {:?}", err), + }) + } + + // DuplicateBlob(ManifestBlobRef) + { + // This is not actually possible to get in TransactionV2, because the manifest stores an IndexMap. + // Currently we remove duplicates at the `PreparedBlobsV1` layer. + } + + // BlobNotRegistered(ManifestBlobRef) + { + let transaction_manifest = ManifestBuilder::new_v2() + .add_test_method_call_with(ManifestBlobRef([2; 32])) + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::BlobNotRegistered(ManifestBlobRef(blob_ref))) => { + assert_eq!(blob_ref, [2; 32]); + } + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .add_test_method_call_with(ManifestBlobRef([3; 32])) + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::BlobNotRegistered(ManifestBlobRef(blob_ref))) => { + assert_eq!(blob_ref, [3; 32]); + } + ); + } + + // BucketNotYetCreated(ManifestBucket) + { + let transaction_manifest = ManifestBuilder::new_v2() + .add_test_method_call_with(ManifestBucket(2)) + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::BucketNotYetCreated(bucket)) => { + assert_eq!(bucket, ManifestBucket(2)); + }, + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .add_test_method_call_with(ManifestBucket(3)) + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::BucketNotYetCreated(bucket)) => { + assert_eq!(bucket, ManifestBucket(3)); + } + ); + } + + // BucketAlreadyUsed(ManifestBucket, String) + { + let transaction_manifest = ManifestBuilder::new_v2() + .take_all_from_worktop(XRD, "reused_bucket") + .add_test_method_call_with(ManifestBucket(0)) + .add_test_method_call_with(ManifestBucket(0)) + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::BucketAlreadyUsed(bucket, _)) => { + assert_eq!(bucket, ManifestBucket(0)); + }, + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .take_all_from_worktop(XRD, "reused_bucket") + .add_test_method_call_with(ManifestBucket(0)) + .add_test_method_call_with(ManifestBucket(0)) + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::BucketAlreadyUsed(bucket, _)) => { + assert_eq!(bucket, ManifestBucket(0)); + }, + ); + } + + // BucketConsumedWhilstLockedByProof(ManifestBucket, String) + { + let transaction_manifest = ManifestBuilder::new_v2() + .take_all_from_worktop(XRD, "my_bucket") + .create_proof_from_bucket_of_all("my_bucket", "my_proof") + .deposit(account_address, "my_bucket") + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::BucketConsumedWhilstLockedByProof(bucket, _)) => { + assert_eq!(bucket, ManifestBucket(0)); + }, + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .take_all_from_worktop(XRD, "my_bucket") + .create_proof_from_bucket_of_all("my_bucket", "my_proof") + .deposit(account_address, "my_bucket") + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::BucketConsumedWhilstLockedByProof(bucket, _)) => { + assert_eq!(bucket, ManifestBucket(0)); + }, + ); + } + + // ProofNotYetCreated(ManifestProof) + { + let transaction_manifest = ManifestBuilder::new_v2() + .add_test_method_call_with(ManifestProof(2)) + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::ProofNotYetCreated(proof)) => { + assert_eq!(proof, ManifestProof(2)); + }, + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .add_test_method_call_with(ManifestProof(2)) + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::ProofNotYetCreated(proof)) => { + assert_eq!(proof, ManifestProof(2)); + }, + ); + } + + // ProofAlreadyUsed(ManifestProof, String) + { + let transaction_manifest = ManifestBuilder::new_v2() + .create_proof_from_auth_zone_of_all(XRD, "proof") + .add_test_method_call_with(ManifestProof(0)) + .add_test_method_call_with(ManifestProof(0)) + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::ProofAlreadyUsed(proof, _)) => { + assert_eq!(proof, ManifestProof(0)); + }, + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .create_proof_from_auth_zone_of_all(XRD, "proof") + .add_test_method_call_with(ManifestProof(0)) + .add_test_method_call_with(ManifestProof(0)) + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::ProofAlreadyUsed(proof, _)) => { + assert_eq!(proof, ManifestProof(0)); + }, + ); + } + + // AddressReservationNotYetCreated(ManifestAddressReservation) + { + let transaction_manifest = ManifestBuilder::new_v2() + .add_test_method_call_with(ManifestAddressReservation(2)) + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::AddressReservationNotYetCreated(reservation)) => { + assert_eq!(reservation, ManifestAddressReservation(2)); + }, + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .add_test_method_call_with(ManifestAddressReservation(2)) + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::AddressReservationNotYetCreated(reservation)) => { + assert_eq!(reservation, ManifestAddressReservation(2)); + }, + ); + } + + // AddressReservationAlreadyUsed(ManifestAddressReservation, String) + { + let transaction_manifest = ManifestBuilder::new_v2() + .allocate_global_address( + RESOURCE_PACKAGE, + FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT, + "my_address_reservation", + "my_address", + ) + .add_test_method_call_with(ManifestAddressReservation(0)) + .add_test_method_call_with(ManifestAddressReservation(0)) + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::AddressReservationAlreadyUsed(reservation, _)) => { + assert_eq!(reservation, ManifestAddressReservation(0)); + }, + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .allocate_global_address( + RESOURCE_PACKAGE, + FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT, + "my_address_reservation", + "my_address", + ) + .add_test_method_call_with(ManifestAddressReservation(0)) + .add_test_method_call_with(ManifestAddressReservation(0)) + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::AddressReservationAlreadyUsed(reservation, _)) => { + assert_eq!(reservation, ManifestAddressReservation(0)); + }, + ); + } + + // NamedAddressNotYetCreated(ManifestNamedAddress) + { + let transaction_manifest = ManifestBuilder::new_v2() + .add_test_method_call_with(ManifestAddress::Named(ManifestNamedAddress(2))) + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::NamedAddressNotYetCreated(named_address)) => { + assert_eq!(named_address, ManifestNamedAddress(2)); + }, + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .add_test_method_call_with(ManifestAddress::Named(ManifestNamedAddress(2))) + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::NamedAddressNotYetCreated(named_address)) => { + assert_eq!(named_address, ManifestNamedAddress(2)); + }, + ); + } + + // ChildIntentNotRegistered(ManifestNamedIntent) + { + let transaction_manifest = ManifestBuilder::new_v2() + .add_raw_instruction_ignoring_all_side_effects(YieldToChild { + child_index: ManifestNamedIntentIndex(2), + args: ManifestValue::unit(), + }) + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::ChildIntentNotRegistered(named_intent)) => { + assert_eq!(named_intent, ManifestNamedIntent(2)); + }, + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .add_raw_instruction_ignoring_all_side_effects(YieldToChild { + child_index: ManifestNamedIntentIndex(3), + args: ManifestValue::unit(), + }) + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::ChildIntentNotRegistered(named_intent)) => { + assert_eq!(named_intent, ManifestNamedIntent(3)); + }, + ); + } + + // DanglingBucket(ManifestBucket, String) + { + let transaction_manifest = ManifestBuilder::new_v2() + .take_all_from_worktop(XRD, "my_bucket") + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::DanglingBucket(bucket, _)) => { + assert_eq!(bucket, ManifestBucket(0)); + }, + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .take_all_from_worktop(XRD, "my_bucket") + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::DanglingBucket(bucket, _)) => { + assert_eq!(bucket, ManifestBucket(0)); + }, + ); + } + + // DanglingAddressReservation(ManifestAddressReservation, String) + { + let transaction_manifest = ManifestBuilder::new_v2() + .allocate_global_address( + RESOURCE_PACKAGE, + FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT, + "my_address_reservation", + "my_address", + ) + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::DanglingAddressReservation(reservation, _)) => { + assert_eq!(reservation, ManifestAddressReservation(0)); + }, + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .allocate_global_address( + RESOURCE_PACKAGE, + FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT, + "my_address_reservation", + "my_address", + ) + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::DanglingAddressReservation(reservation, _)) => { + assert_eq!(reservation, ManifestAddressReservation(0)); + }, + ); + } + + // ArgsEncodeError(EncodeError) + { + // Hard to create when coming from a prepared transaction, because the values + // come from being decoded + } + + // ArgsDecodeError(DecodeError) + { + // Hard to create when coming from a prepared transaction, because the values + // come from being decoded + } + + // InstructionNotSupportedInTransactionIntent + { + // YIELD_TO_PARENT + let transaction_manifest = ManifestBuilder::new_v2() + .add_raw_instruction_ignoring_all_side_effects(YieldToParent { + args: ManifestValue::unit(), + }) + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::InstructionNotSupportedInTransactionIntent), + ); + + // VERIFY_PARENT + let transaction_manifest = ManifestBuilder::new_v2() + .add_raw_instruction_ignoring_all_side_effects(VerifyParent { + access_rule: rule!(allow_all), + }) + .build_no_validate(); + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::InstructionNotSupportedInTransactionIntent), + ); + } + + // SubintentDoesNotEndWithYieldToParent + { + // CASE 1: At least 1 instruction + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .add_test_method_call_with(()) + .build_no_validate(); + + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::SubintentDoesNotEndWithYieldToParent), + ); + + // CASE 2: No instructions + let subintent_manifest = ManifestBuilder::new_subintent_v2().build_no_validate(); + + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::SubintentDoesNotEndWithYieldToParent), + ); + } + + // ProofCannotBePassedToAnotherIntent + { + let subintent = create_leaf_partial_transaction(0, 0); + let builder = ManifestBuilder::new_v2(); + let lookup = builder.name_lookup(); + let transaction_manifest = builder + .use_child("child_1", subintent.root_subintent_hash) + .create_proof_from_auth_zone_of_all(XRD, "my_proof") + .yield_to_child("child_1", (lookup.proof("my_proof"),)) + .build_no_validate(); + let builder = TransactionV2Builder::new_with_test_defaults() + .add_signed_child("child_1", subintent) + .manifest(transaction_manifest); + + assert_matches!( + validate_transaction_builder_manifest(builder), + Err(ManifestValidationError::ProofCannotBePassedToAnotherIntent), + ); + + let builder = ManifestBuilder::new_subintent_v2(); + let lookup = builder.name_lookup(); + let subintent_manifest = builder + .create_proof_from_auth_zone_of_all(XRD, "my_proof") + .yield_to_parent((lookup.proof("my_proof"),)) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::ProofCannotBePassedToAnotherIntent), + ); + } + + // TooManyInstructions + { + let mut builder = ManifestBuilder::new_v2(); + for _ in 0..1001 { + builder = builder.drop_all_proofs(); + } + let transaction_manifest = builder.build_no_validate(); + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::TooManyInstructions), + ); + // And test that one less is fine + let mut builder = ManifestBuilder::new_v2(); + for _ in 0..1000 { + builder = builder.drop_all_proofs(); + } + let transaction_manifest = builder.build_no_validate(); + assert_matches!(validate_transaction_manifest(transaction_manifest), Ok(_),); + + let mut builder = ManifestBuilder::new_subintent_v2(); + for _ in 0..1000 { + // Only 1000 because we're adding a yield_to_parent below + builder = builder.drop_all_proofs(); + } + let subintent_manifest = builder.yield_to_parent(()).build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::TooManyInstructions), + ); + // And test that one less is fine + let mut builder = ManifestBuilder::new_subintent_v2(); + for _ in 0..999 { + builder = builder.drop_all_proofs(); + } + let subintent_manifest = builder.yield_to_parent(()).build_no_validate(); + assert_matches!(validate_subintent_manifest(subintent_manifest), Ok(_),); + } + + // InvalidResourceConstraint + { + // Invalid because there's no overlap between `required_ids` and `allowed_ids` + let invalid_constraints = ManifestResourceConstraints::new().with_unchecked( + XRD, + ManifestResourceConstraint::General(GeneralResourceConstraint { + required_ids: indexset!(NonFungibleLocalId::integer(3)), + lower_bound: LowerBound::NonZero, + upper_bound: UpperBound::Unbounded, + allowed_ids: AllowedIds::Allowlist(indexset!( + NonFungibleLocalId::integer(4), + NonFungibleLocalId::integer(5), + )), + }), + ); + + let transaction_manifest = ManifestBuilder::new_v2() + .add_raw_instruction_ignoring_all_side_effects(AssertWorktopResourcesOnly { + constraints: invalid_constraints.clone(), + }) + .build_no_validate(); + + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::InvalidResourceConstraint), + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .assert_worktop_resources_only(invalid_constraints.clone()) + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::InvalidResourceConstraint), + ); + } + + // InstructionFollowingNextCallAssertionWasNotInvocation + { + let transaction_manifest = ManifestBuilder::new_v2() + .assert_next_call_returns_include(ManifestResourceConstraints::new()) + .drop_all_proofs() // This is not an invocation + .add_test_method_call_with(()) + .build_no_validate(); + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::InstructionFollowingNextCallAssertionWasNotInvocation), + ); + + let subintent_manifest = ManifestBuilder::new_subintent_v2() + .assert_next_call_returns_only(ManifestResourceConstraints::new()) + .drop_auth_zone_signature_proofs() + .yield_to_parent(()) + .build_no_validate(); + assert_matches!( + validate_subintent_manifest(subintent_manifest), + Err(ManifestValidationError::InstructionFollowingNextCallAssertionWasNotInvocation), + ); + } + + // ManifestEndedWhilstExpectingNextCallAssertion + { + let transaction_manifest = ManifestBuilder::new_v2() + .assert_next_call_returns_include(ManifestResourceConstraints::new()) + .build_no_validate(); + assert_matches!( + validate_transaction_manifest(transaction_manifest), + Err(ManifestValidationError::ManifestEndedWhilstExpectingNextCallAssertion), + ); + } + } + + #[test] + fn test_prepare_errors() { + let babylon_validator = TransactionValidator::new_with_static_config( + TransactionValidationConfig::babylon(), + NetworkDefinition::simulator().id, + ); + let latest_validator = TransactionValidator::new_for_latest_simulator(); + + fn create_unvalidated_notarized_transaction_from_manifest( + manifest: TransactionManifestV2, + ) -> NotarizedTransactionV2 { + NotarizedTransactionV2 { + signed_transaction_intent: SignedTransactionIntentV2 { + transaction_intent: TransactionIntentV2 { + transaction_header: + TransactionV2Builder::testing_default_transaction_header(), + root_intent_core: manifest.to_intent_core( + TransactionV2Builder::testing_default_intent_header(), + MessageV2::None, + ), + non_root_subintents: NonRootSubintentsV2(vec![]), + }, + transaction_intent_signatures: IntentSignaturesV2::none(), + non_root_subintent_signatures: NonRootSubintentSignaturesV2 { + by_subintent: vec![], + }, + }, + notary_signature: NotarySignatureV2(SignatureV1::Ed25519(Ed25519Signature( + [0; Ed25519Signature::LENGTH], + ))), + } + } + + fn create_unvalidated_raw_notarized_transaction_from_manifest( + manifest: TransactionManifestV2, + ) -> RawNotarizedTransaction { + let transaction = create_unvalidated_notarized_transaction_from_manifest(manifest); + let manually_encoded_transaction = manifest_encode_with_depth_limit( + &AnyTransaction::NotarizedTransactionV2(transaction), + 100, + ) + .unwrap(); + RawNotarizedTransaction::from_vec(manually_encoded_transaction) + } + + // TransactionTypeNotSupported + { + let transaction_v2 = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .default_notarize() + .build_minimal_no_validate(); + + assert_matches!( + transaction_v2.prepare_and_validate(&babylon_validator), + Err(TransactionValidationError::PrepareError( + PrepareError::TransactionTypeNotSupported + )), + ); + } + + // TransactionTooLarge + { + let mut manifest_builder = ManifestBuilder::new_v2(); + manifest_builder.add_blob(vec![0; 1_100_000]); + let manifest = manifest_builder.build_no_validate(); + let transaction = TransactionV2Builder::new_with_test_defaults() + .manifest(manifest) + .default_notarize() + .build_minimal_no_validate(); + + assert_matches!( + transaction.prepare_and_validate(&latest_validator), + Err(TransactionValidationError::PrepareError( + PrepareError::TransactionTooLarge + )), + ); + } + + // EncodeError(EncodeError) and DecodeError(DecodeError) + // Note that EncodeError doesn't happen as part of preparation in the node, only when preparing from + // an encodable model. But we can test it here anyway... + { + let mut nested_value = ManifestValue::unit(); + for _ in 0..50 { + nested_value = ManifestValue::tuple([nested_value]); + } + let manifest = ManifestBuilder::new_v2() + .add_raw_instruction_ignoring_all_side_effects(CallMethod { + address: XRD.into(), + method_name: "method".into(), + args: nested_value, + }) + .build_no_validate(); + + let transaction = + create_unvalidated_notarized_transaction_from_manifest(manifest.clone()); + + // We get an EncodeError when preparing directly from the model + assert_matches!( + transaction.prepare_and_validate(&latest_validator), + Err(TransactionValidationError::PrepareError( + PrepareError::EncodeError(EncodeError::MaxDepthExceeded(24)) + )), + ); + + // We get a DecodeError when preparing directly from the raw transaction + let raw_transaction = + create_unvalidated_raw_notarized_transaction_from_manifest(manifest); + assert_matches!( + raw_transaction.validate(&latest_validator), + Err(TransactionValidationError::PrepareError( + PrepareError::DecodeError(DecodeError::MaxDepthExceeded(24)) + )), + ); + } + + // TooManyValues { value_type: ValueType, actual: usize, max: usize, } + { + // Blob + { + let mut manifest_builder = ManifestBuilder::new_v2(); + for i in 0..65 { + manifest_builder.add_blob(vec![0; i as usize]); + } + let transaction = create_unvalidated_notarized_transaction_from_manifest( + manifest_builder.build_no_validate(), + ); + + assert_matches!( + transaction.prepare_and_validate(&latest_validator), + Err(TransactionValidationError::PrepareError( + PrepareError::TooManyValues { + value_type: ValueType::Blob, + actual: 65, + max: 64, + } + )), + ); + } + + // Subintent + { + let mut transaction = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .default_notarize() + .build_minimal_no_validate(); + let subintents = (0..33) + .map(|i| { + create_leaf_partial_transaction(i, 0) + .partial_transaction + .partial_transaction + .root_subintent + }) + .collect::>(); + transaction + .signed_transaction_intent + .transaction_intent + .non_root_subintents = NonRootSubintentsV2(subintents); + assert_matches!( + transaction.prepare_and_validate(&latest_validator), + Err(TransactionValidationError::PrepareError( + PrepareError::TooManyValues { + value_type: ValueType::Subintent, + actual: 33, + max: 32, + } + )), + ); + } + + // ChildSubintentSpecifier + { + let mut transaction = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .default_notarize() + .build_minimal_no_validate(); + let child_specifiers = (0..33) + .map(|i| ChildSubintentSpecifier { + hash: SubintentHash::from_bytes([i as u8; Hash::LENGTH]), + }) + .collect(); + transaction + .signed_transaction_intent + .transaction_intent + .root_intent_core + .children = ChildSubintentSpecifiersV2 { + children: child_specifiers, + }; + assert_matches!( + transaction.prepare_and_validate(&latest_validator), + Err(TransactionValidationError::PrepareError( + PrepareError::TooManyValues { + value_type: ValueType::ChildSubintentSpecifier, + actual: 33, + max: 32, + } + )), + ); + } + + // SubintentSignatureBatches + { + let mut transaction = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .default_notarize() + .build_minimal_no_validate(); + let subintent_signature_batches = (0..33) + .map(|_| IntentSignaturesV2::none()) + .collect::>(); + transaction + .signed_transaction_intent + .non_root_subintent_signatures = NonRootSubintentSignaturesV2 { + by_subintent: subintent_signature_batches, + }; + assert_matches!( + transaction.prepare_and_validate(&latest_validator), + Err(TransactionValidationError::PrepareError( + PrepareError::TooManyValues { + value_type: ValueType::SubintentSignatureBatches, + actual: 33, + max: 32, + } + )), + ); + } + } + + // LengthOverflow + // -> Rather hard to test, we can leave this. + + // UnexpectedTransactionDiscriminator + { + let raw_transaction = TransactionV2Builder::new_with_test_defaults() + .add_trivial_manifest() + .default_notarize() + .build_minimal_no_validate() + .to_raw() + .unwrap(); + + let mut amended_payload = raw_transaction.to_vec(); + amended_payload[2] = 4; + let amended_raw = RawNotarizedTransaction::from_vec(amended_payload); + assert_eq!( + amended_raw.validate(&latest_validator), + Err(TransactionValidationError::PrepareError( + PrepareError::UnexpectedTransactionDiscriminator { actual: Some(4) } + )) + ) + } + } } diff --git a/radix-transactions/src/validation/validation_test_helpers.rs b/radix-transactions/src/validation/validation_test_helpers.rs index fb985eadeb8..32a37c388ba 100644 --- a/radix-transactions/src/validation/validation_test_helpers.rs +++ b/radix-transactions/src/validation/validation_test_helpers.rs @@ -19,25 +19,33 @@ pub(crate) fn unsigned_v1_builder(notary_public_key: PublicKey) -> TransactionV1 // All of these are only added when in #[cfg(test)] impl TransactionV2Builder { - pub fn default_notary() -> Ed25519PrivateKey { + pub fn testing_default_notary() -> Ed25519PrivateKey { Ed25519PrivateKey::from_u64(1337).unwrap() } + pub fn testing_default_intent_header() -> IntentHeaderV2 { + IntentHeaderV2 { + network_id: NetworkDefinition::simulator().id, + start_epoch_inclusive: Epoch::of(0), + end_epoch_exclusive: Epoch::of(1), + min_proposer_timestamp_inclusive: None, + max_proposer_timestamp_exclusive: None, + intent_discriminator: 0, + } + } + + pub fn testing_default_transaction_header() -> TransactionHeaderV2 { + TransactionHeaderV2 { + notary_public_key: Self::testing_default_notary().public_key().into(), + notary_is_signatory: false, + tip_basis_points: 0, + } + } + pub fn new_with_test_defaults() -> Self { Self::new() - .intent_header(IntentHeaderV2 { - network_id: NetworkDefinition::simulator().id, - start_epoch_inclusive: Epoch::of(0), - end_epoch_exclusive: Epoch::of(1), - min_proposer_timestamp_inclusive: None, - max_proposer_timestamp_exclusive: None, - intent_discriminator: 0, - }) - .transaction_header(TransactionHeaderV2 { - notary_public_key: Self::default_notary().public_key().into(), - notary_is_signatory: false, - tip_basis_points: 0, - }) + .intent_header(Self::testing_default_intent_header()) + .transaction_header(Self::testing_default_transaction_header()) } pub fn add_children( @@ -102,13 +110,46 @@ impl TransactionV2Builder { .expect("Intent Header should already have been set, e.g. via new_with_test_defaults()") } + pub fn network_id(mut self, network_id: u8) -> Self { + self.intent_header_mut().network_id = network_id; + self + } + + pub fn start_epoch_inclusive(mut self, start_epoch_inclusive: Epoch) -> Self { + self.intent_header_mut().start_epoch_inclusive = start_epoch_inclusive; + self + } + + pub fn end_epoch_exclusive(mut self, end_epoch_exclusive: Epoch) -> Self { + self.intent_header_mut().end_epoch_exclusive = end_epoch_exclusive; + self + } + + pub fn min_proposer_timestamp_inclusive( + mut self, + min_proposer_timestamp_inclusive: Option, + ) -> Self { + self.intent_header_mut().min_proposer_timestamp_inclusive = + min_proposer_timestamp_inclusive; + self + } + + pub fn max_proposer_timestamp_exclusive( + mut self, + max_proposer_timestamp_exclusive: Option, + ) -> Self { + self.intent_header_mut().max_proposer_timestamp_exclusive = + max_proposer_timestamp_exclusive; + self + } + pub fn intent_discriminator(mut self, intent_discriminator: u64) -> Self { self.intent_header_mut().intent_discriminator = intent_discriminator; self } pub fn default_notarize(self) -> Self { - self.notarize(&Self::default_notary()) + self.notarize(&Self::testing_default_notary()) } pub fn default_notarize_and_validate( @@ -123,24 +164,37 @@ impl TransactionV2Builder { // All of these are only added when in #[cfg(test)] impl PartialTransactionV2Builder { pub fn new_with_test_defaults() -> Self { - Self::new() - .intent_header(IntentHeaderV2 { - network_id: NetworkDefinition::simulator().id, - start_epoch_inclusive: Epoch::of(0), - end_epoch_exclusive: Epoch::of(1), - min_proposer_timestamp_inclusive: None, - max_proposer_timestamp_exclusive: None, - intent_discriminator: 0, - }) - .manifest( - ManifestBuilder::new_subintent_v2() - .yield_to_parent(()) - .build(), - ) + Self::new().intent_header(IntentHeaderV2 { + network_id: NetworkDefinition::simulator().id, + start_epoch_inclusive: Epoch::of(0), + end_epoch_exclusive: Epoch::of(1), + min_proposer_timestamp_inclusive: None, + max_proposer_timestamp_exclusive: None, + intent_discriminator: 0, + }) + } + + pub fn add_children( + mut self, + children: impl IntoIterator, + ) -> Self { + for (i, child) in children.into_iter().enumerate() { + let child_name = format!("child_{i}"); + self = self.add_signed_child(child_name, child); + } + self + } + + pub fn add_trivial_manifest(self) -> Self { + self.manifest( + ManifestBuilder::new_subintent_v2() + .yield_to_parent(()) + .build_no_validate(), + ) } /// It calls into each child once - pub fn add_valid_manifest(self) -> Self { + pub fn add_manifest_calling_each_child_once(self) -> Self { let child_names = self .child_partial_transactions .keys() @@ -160,6 +214,39 @@ impl PartialTransactionV2Builder { .expect("Intent Header should already have been set, e.g. via new_with_test_defaults()") } + pub fn network_id(mut self, network_id: u8) -> Self { + self.intent_header_mut().network_id = network_id; + self + } + + pub fn start_epoch_inclusive(mut self, start_epoch_inclusive: Epoch) -> Self { + self.intent_header_mut().start_epoch_inclusive = start_epoch_inclusive; + self + } + + pub fn end_epoch_exclusive(mut self, end_epoch_exclusive: Epoch) -> Self { + self.intent_header_mut().end_epoch_exclusive = end_epoch_exclusive; + self + } + + pub fn min_proposer_timestamp_inclusive( + mut self, + min_proposer_timestamp_inclusive: Option, + ) -> Self { + self.intent_header_mut().min_proposer_timestamp_inclusive = + min_proposer_timestamp_inclusive; + self + } + + pub fn max_proposer_timestamp_exclusive( + mut self, + max_proposer_timestamp_exclusive: Option, + ) -> Self { + self.intent_header_mut().max_proposer_timestamp_exclusive = + max_proposer_timestamp_exclusive; + self + } + pub fn intent_discriminator(mut self, intent_discriminator: u64) -> Self { self.intent_header_mut().intent_discriminator = intent_discriminator; self @@ -169,15 +256,12 @@ impl PartialTransactionV2Builder { pub(crate) fn create_leaf_partial_transaction( intent_discriminator: u64, num_signatures: usize, -) -> SignedPartialTransactionV2 { - let mut builder = PartialTransactionV2Builder::new_with_test_defaults() - .intent_discriminator(intent_discriminator); - - for i in 0..num_signatures { - let signer = - Secp256k1PrivateKey::from_u64((intent_discriminator + 1) * 1000 + (i as u64)).unwrap(); - builder = builder.sign(&signer); - } - - builder.build_minimal() +) -> DetailedSignedPartialTransactionV2 { + PartialTransactionV2Builder::new_with_test_defaults() + .intent_discriminator(intent_discriminator) + .add_trivial_manifest() + .multi_sign((0..num_signatures).into_iter().map(|i| { + Secp256k1PrivateKey::from_u64((intent_discriminator + 1) * 1000 + (i as u64)).unwrap() + })) + .build() } diff --git a/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_1.diag b/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_1.diag new file mode 100644 index 00000000000..59a54b0e77c --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_1.diag @@ -0,0 +1,11 @@ +error: an argument's structure does not fit with the radix_common::data::manifest::model::manifest_resource_assertion::ManifestResourceConstraints type. [ERROR] byte offset: 36-38, value path: ManifestResourceConstraints.[0].Value->ManifestResourceConstraint::{8}, cause: { unknown_variant_id: 8 } + | +1 | ASSERT_WORKTOP_RESOURCES_INCLUDE +2 | Map( + | ^^^ cannot be decoded as a radix_common::data::manifest::model::manifest_resource_assertion::ManifestResourceConstraints +3 | Address("resource_sim1thqu8jcc3zh8ukuh0rwtllr84dgrd3z8j9zjdelkx3zf4kjasgvnm8") => Enum<8u8>( +4 | Decimal("10") +5 | ) +6 | ) +7 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_1.rtm b/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_1.rtm new file mode 100644 index 00000000000..3fa56747833 --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_1.rtm @@ -0,0 +1,7 @@ +ASSERT_WORKTOP_RESOURCES_INCLUDE + Map( + Address("resource_sim1thqu8jcc3zh8ukuh0rwtllr84dgrd3z8j9zjdelkx3zf4kjasgvnm8") => Enum<8u8>( + Decimal("10") + ) + ) +; \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_2.diag b/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_2.diag new file mode 100644 index 00000000000..98e6a751d5b --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_2.diag @@ -0,0 +1,11 @@ +error: an argument's structure does not fit with the radix_common::data::manifest::model::manifest_resource_assertion::ManifestResourceConstraint type. [ERROR] byte offset: 1-26, value path: [Root], cause: { expected_type: Enum, found: Custom(Decimal) } + | +2 | Address("resource_sim1thqu8jcc3zh8ukuh0rwtllr84dgrd3z8j9zjdelkx3zf4kjasgvnm8") +3 | Bucket("my_bucket") +4 | ; +5 | ASSERT_BUCKET_CONTENTS +6 | Bucket("my_bucket") +7 | Decimal("10") + | ^^^^^^^ cannot be decoded as a radix_common::data::manifest::model::manifest_resource_assertion::ManifestResourceConstraint +8 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_2.rtm b/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_2.rtm new file mode 100644 index 00000000000..5bf7bacfb68 --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_2.rtm @@ -0,0 +1,8 @@ +TAKE_ALL_FROM_WORKTOP + Address("resource_sim1thqu8jcc3zh8ukuh0rwtllr84dgrd3z8j9zjdelkx3zf4kjasgvnm8") + Bucket("my_bucket") +; +ASSERT_BUCKET_CONTENTS + Bucket("my_bucket") + Decimal("10") +; \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_3.diag b/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_3.diag new file mode 100644 index 00000000000..9c39c013ba9 --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_3.diag @@ -0,0 +1,7 @@ +error: an argument's structure does not fit with the radix_engine_interface::blueprints::resource::proof_rule::AccessRule type. [ERROR] byte offset: 1-3, value path: [Root], cause: { expected_type: Enum, found: Tuple } + | +1 | VERIFY_PARENT +2 | Tuple() + | ^^^^^ cannot be decoded as a radix_engine_interface::blueprints::resource::proof_rule::AccessRule +3 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_3.rtm b/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_3.rtm new file mode 100644 index 00000000000..46a27ab9016 --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_argument_could_not_be_read_as_expected_type_3.rtm @@ -0,0 +1,3 @@ +VERIFY_PARENT + Tuple() +; \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_blob_not_found_1.diag b/radix-transactions/tests/assets/manifest_generator_error_blob_not_found_1.diag index 6f7b2ac96f1..61a2198dfa3 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_blob_not_found_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_blob_not_found_1.diag @@ -1,15 +1,15 @@ -error: blob with hash 'f531e5e82dc195a7a9f6709f5ee048d9541d51c52904b7a76295a13ddfa377b1' not found - | -12 | PUBLISH_PACKAGE_ADVANCED -13 | Enum() -14 | Tuple( -15 | Map() -16 | ) -17 | Blob("f531e5e82dc195a7a9f6709f5ee048d9541d51c52904b7a76295a13ddfa377b1") - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ blob not found -18 | Map() -19 | Some(AddressReservation("my_reservation")) -20 | ; -21 | CALL_FUNCTION -22 | NamedAddress("my_package") - | \ No newline at end of file +error: blob with hash 'f531e5e82dc195a7a9f6709f5ee048d9541d51c52904b7a76295a13ddfa377b1' not found + | +12 | PUBLISH_PACKAGE_ADVANCED +13 | Enum() +14 | Tuple( +15 | Map() +16 | ) +17 | Blob("f531e5e82dc195a7a9f6709f5ee048d9541d51c52904b7a76295a13ddfa377b1") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ blob not found +18 | Map() +19 | Some(AddressReservation("my_reservation")) +20 | ; +21 | CALL_FUNCTION +22 | NamedAddress("my_package") + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_bucket_locked_1.diag b/radix-transactions/tests/assets/manifest_generator_error_bucket_locked_1.diag index 700ab8e825c..b263cd9f252 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_bucket_locked_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_bucket_locked_1.diag @@ -1,11 +1,11 @@ -error: cannot consume bucket 'some_bucket' because it's believed to be currently locked - | -18 | Bucket("some_bucket") -19 | Decimal("1") -20 | Proof("proof"); -21 | -22 | RETURN_TO_WORKTOP -23 | Bucket("some_bucket"); - | ^^^^^^^^^^^^^ bucket locked -24 | - | \ No newline at end of file +error: cannot consume bucket 'some_bucket' because it's believed to be currently locked + | +18 | Bucket("some_bucket") +19 | Decimal("1") +20 | Proof("proof"); +21 | +22 | RETURN_TO_WORKTOP +23 | Bucket("some_bucket"); + | ^^^^^^^^^^^^^ bucket locked +24 | + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_bucket_not_found_1.diag b/radix-transactions/tests/assets/manifest_generator_error_bucket_not_found_1.diag index d9f38247632..c6636b835de 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_bucket_not_found_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_bucket_not_found_1.diag @@ -1,15 +1,15 @@ -error: bucket id 'ManifestBucket(1)' not found - | - 7 | TAKE_ALL_FROM_WORKTOP - 8 | Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") - 9 | Bucket("some_xrd"); -10 | -11 | CREATE_PROOF_FROM_BUCKET_OF_AMOUNT -12 | Bucket(1u32) - | ^^^^ bucket not found -13 | Decimal("1") -14 | Proof("proof"); -15 | -16 | DROP_PROOF -17 | Proof("proof"); - | \ No newline at end of file +error: bucket id 'ManifestBucket(1)' not found + | + 7 | TAKE_ALL_FROM_WORKTOP + 8 | Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") + 9 | Bucket("some_xrd"); +10 | +11 | CREATE_PROOF_FROM_BUCKET_OF_AMOUNT +12 | Bucket(1u32) + | ^^^^ bucket not found +13 | Decimal("1") +14 | Proof("proof"); +15 | +16 | DROP_PROOF +17 | Proof("proof"); + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_bucket_not_found_2.diag b/radix-transactions/tests/assets/manifest_generator_error_bucket_not_found_2.diag index d90077a7c84..b401a209f67 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_bucket_not_found_2.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_bucket_not_found_2.diag @@ -1,10 +1,10 @@ -error: bucket id 'ManifestBucket(1)' not found - | - 7 | TAKE_ALL_FROM_WORKTOP - 8 | Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") - 9 | Bucket("some_xrd"); -10 | -11 | BURN_RESOURCE -12 | Bucket(1u32); - | ^^^^ bucket not found - | \ No newline at end of file +error: bucket id 'ManifestBucket(1)' not found + | + 7 | TAKE_ALL_FROM_WORKTOP + 8 | Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") + 9 | Bucket("some_xrd"); +10 | +11 | BURN_RESOURCE +12 | Bucket(1u32); + | ^^^^ bucket not found + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_child_subintents_unsupported_by_manifest_type_1.diag b/radix-transactions/tests/assets/manifest_generator_error_child_subintents_unsupported_by_manifest_type_1.diag new file mode 100644 index 00000000000..0937897f28c --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_child_subintents_unsupported_by_manifest_type_1.diag @@ -0,0 +1,8 @@ +error: child subintents are not supported in this manifest type + | +1 | / USE_CHILD +2 | | NamedIntent("my_child") +3 | | Intent("subtxid_sim1f0dp5mcrzvgnujw33lgnjy9usluaek6edfkqdjkj5vhuqf8t7apqnaqedd") +4 | | ; + | |_^ unsupported instruction + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_child_subintents_unsupported_by_manifest_type_1.rtm b/radix-transactions/tests/assets/manifest_generator_error_child_subintents_unsupported_by_manifest_type_1.rtm new file mode 100644 index 00000000000..e6d8e9232c5 --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_child_subintents_unsupported_by_manifest_type_1.rtm @@ -0,0 +1,4 @@ +USE_CHILD + NamedIntent("my_child") + Intent("subtxid_sim1f0dp5mcrzvgnujw33lgnjy9usluaek6edfkqdjkj5vhuqf8t7apqnaqedd") +; \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_duplicate_subintent_hash_1.diag b/radix-transactions/tests/assets/manifest_generator_error_duplicate_subintent_hash_1.diag new file mode 100644 index 00000000000..7edfc392d4f --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_duplicate_subintent_hash_1.diag @@ -0,0 +1,12 @@ +error: child subintents cannot have the same hash + | +1 | USE_CHILD +2 | NamedIntent("my_child") +3 | Intent("subtxid_sim1f0dp5mcrzvgnujw33lgnjy9usluaek6edfkqdjkj5vhuqf8t7apqnaqedd") +4 | ; +5 | / USE_CHILD +6 | | NamedIntent("my_second_child") +7 | | Intent("subtxid_sim1f0dp5mcrzvgnujw33lgnjy9usluaek6edfkqdjkj5vhuqf8t7apqnaqedd") +8 | | ; + | |_^ duplicate hash + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_duplicate_subintent_hash_1.rtm b/radix-transactions/tests/assets/manifest_generator_error_duplicate_subintent_hash_1.rtm new file mode 100644 index 00000000000..732a3e3b23d --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_duplicate_subintent_hash_1.rtm @@ -0,0 +1,8 @@ +USE_CHILD + NamedIntent("my_child") + Intent("subtxid_sim1f0dp5mcrzvgnujw33lgnjy9usluaek6edfkqdjkj5vhuqf8t7apqnaqedd") +; +USE_CHILD + NamedIntent("my_second_child") + Intent("subtxid_sim1f0dp5mcrzvgnujw33lgnjy9usluaek6edfkqdjkj5vhuqf8t7apqnaqedd") +; \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_header_instruction_must_come_first_1.diag b/radix-transactions/tests/assets/manifest_generator_error_header_instruction_must_come_first_1.diag new file mode 100644 index 00000000000..6cac57f9cc6 --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_header_instruction_must_come_first_1.diag @@ -0,0 +1,9 @@ +error: a psuedo-instruction such as USE_CHILD must come before all other instructions + | +1 | DROP_ALL_PROOFS; +2 | / USE_CHILD +3 | | NamedIntent("my_child") +4 | | Intent("subtxid_sim1f0dp5mcrzvgnujw33lgnjy9usluaek6edfkqdjkj5vhuqf8t7apqnaqedd") +5 | | ; + | |_^ must be at the start of the manifest + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_header_instruction_must_come_first_1.rtm b/radix-transactions/tests/assets/manifest_generator_error_header_instruction_must_come_first_1.rtm new file mode 100644 index 00000000000..1f76645ebbe --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_header_instruction_must_come_first_1.rtm @@ -0,0 +1,5 @@ +DROP_ALL_PROOFS; +USE_CHILD + NamedIntent("my_child") + Intent("subtxid_sim1f0dp5mcrzvgnujw33lgnjy9usluaek6edfkqdjkj5vhuqf8t7apqnaqedd") +; \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_instruction_not_supported_in_manifest_version_1.diag b/radix-transactions/tests/assets/manifest_generator_error_instruction_not_supported_in_manifest_version_1.diag new file mode 100644 index 00000000000..b1c3b00cddf --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_instruction_not_supported_in_manifest_version_1.diag @@ -0,0 +1,5 @@ +error: unsupported instruction for this manifest version + | +1 | YIELD_TO_PARENT; + | ^^^^^^^^^^^^^^^^ unsupported instruction + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_instruction_not_supported_in_manifest_version_1.rtm b/radix-transactions/tests/assets/manifest_generator_error_instruction_not_supported_in_manifest_version_1.rtm new file mode 100644 index 00000000000..8c1cf6d7144 --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_instruction_not_supported_in_manifest_version_1.rtm @@ -0,0 +1 @@ +YIELD_TO_PARENT; \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_intent_cannot_be_used_as_value_kind_1.diag b/radix-transactions/tests/assets/manifest_generator_error_intent_cannot_be_used_as_value_kind_1.diag new file mode 100644 index 00000000000..3243f202e1c --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_intent_cannot_be_used_as_value_kind_1.diag @@ -0,0 +1,9 @@ +error: an Intent cannot be used as a value kind + | +1 | CALL_METHOD +2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") +3 | "my_method" +4 | Array() + | ^^^^^^ cannot be used as a value kind +5 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_intent_cannot_be_used_as_value_kind_1.rtm b/radix-transactions/tests/assets/manifest_generator_error_intent_cannot_be_used_as_value_kind_1.rtm new file mode 100644 index 00000000000..02dbb30ee70 --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_intent_cannot_be_used_as_value_kind_1.rtm @@ -0,0 +1,5 @@ +CALL_METHOD + Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") + "my_method" + Array() +; \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_intent_cannot_be_used_in_value_1.diag b/radix-transactions/tests/assets/manifest_generator_error_intent_cannot_be_used_in_value_1.diag new file mode 100644 index 00000000000..281acb638ce --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_intent_cannot_be_used_in_value_1.diag @@ -0,0 +1,9 @@ +error: an Intent(...) cannot currently be used inside a value + | +1 | CALL_METHOD +2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") +3 | "my_method" +4 | Intent("subtxid_sim1f0dp5mcrzvgnujw33lgnjy9usluaek6edfkqdjkj5vhuqf8t7apqnaqedd") + | ^^^^^^ cannot be used inside a value +5 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_intent_cannot_be_used_in_value_1.rtm b/radix-transactions/tests/assets/manifest_generator_error_intent_cannot_be_used_in_value_1.rtm new file mode 100644 index 00000000000..b147cab9fbb --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_intent_cannot_be_used_in_value_1.rtm @@ -0,0 +1,5 @@ +CALL_METHOD + Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") + "my_method" + Intent("subtxid_sim1f0dp5mcrzvgnujw33lgnjy9usluaek6edfkqdjkj5vhuqf8t7apqnaqedd") +; \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_type_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_type_1.diag index 08eee13ac3d..816d18a8043 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_type_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_type_1.diag @@ -1,15 +1,15 @@ -error: expected NonFungibleLocalId, found String - | - 1 | CALL_METHOD Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") "withdraw" Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") Decimal("5.0"); - 2 | - 3 | # Create a proof from bucket, clone it and drop both - 4 | TAKE_ALL_FROM_WORKTOP Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") Bucket("some_xrd"); - 5 | CREATE_PROOF_FROM_BUCKET_OF_AMOUNT Bucket("some_xrd") Decimal("1") Proof("proof1a"); - 6 | CREATE_PROOF_FROM_BUCKET_OF_NON_FUNGIBLES Bucket("some_xrd") Array("some_string") Proof("proof1b"); - | ^^^^^^ expected NonFungibleLocalId - 7 | CREATE_PROOF_FROM_BUCKET_OF_ALL Bucket("some_xrd") Proof("proof1c"); - 8 | CLONE_PROOF Proof("proof1c") Proof("proof1d"); - 9 | DROP_PROOF Proof("proof1d"); -10 | DROP_PROOF Proof("proof1c"); -11 | DROP_AUTH_ZONE_PROOFS; - | \ No newline at end of file +error: expected NonFungibleLocalId, found String + | + 1 | CALL_METHOD Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") "withdraw" Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") Decimal("5.0"); + 2 | + 3 | # Create a proof from bucket, clone it and drop both + 4 | TAKE_ALL_FROM_WORKTOP Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") Bucket("some_xrd"); + 5 | CREATE_PROOF_FROM_BUCKET_OF_AMOUNT Bucket("some_xrd") Decimal("1") Proof("proof1a"); + 6 | CREATE_PROOF_FROM_BUCKET_OF_NON_FUNGIBLES Bucket("some_xrd") Array("some_string") Proof("proof1b"); + | ^^^^^^ expected NonFungibleLocalId + 7 | CREATE_PROOF_FROM_BUCKET_OF_ALL Bucket("some_xrd") Proof("proof1c"); + 8 | CLONE_PROOF Proof("proof1c") Proof("proof1d"); + 9 | DROP_PROOF Proof("proof1d"); +10 | DROP_PROOF Proof("proof1c"); +11 | DROP_AUTH_ZONE_PROOFS; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_1.diag index 54f96d3133c..7e13b060a93 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_1.diag @@ -1,11 +1,11 @@ -error: expected String, found U32 - | -1 | CALL_METHOD -2 | Address(100u32) - | ^^^^^^ expected String -3 | "lock_fee" -4 | ; -5 | CALL_FUNCTION -6 | Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") -7 | "Hello" - | \ No newline at end of file +error: expected String, found U32 + | +1 | CALL_METHOD +2 | Address(100u32) + | ^^^^^^ expected String +3 | "lock_fee" +4 | ; +5 | CALL_FUNCTION +6 | Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") +7 | "Hello" + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_2.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_2.diag index 994ff43d6f0..1f4541e6743 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_2.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_2.diag @@ -1,11 +1,11 @@ -error: expected String, found Decimal - | - 6 | CALL_METHOD - 7 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") - 8 | "create_proof_of_amount" - 9 | Address("resource_sim1t5lam43hk5fg9h2x7a8zgpfxsd78539kzm4h0xugldymfexuh2wzru") -10 | Expression( -11 | Decimal("1") - | ^^^^^^^ expected String -12 | ); - | \ No newline at end of file +error: expected String, found Decimal + | + 6 | CALL_METHOD + 7 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") + 8 | "create_proof_of_amount" + 9 | Address("resource_sim1t5lam43hk5fg9h2x7a8zgpfxsd78539kzm4h0xugldymfexuh2wzru") +10 | Expression( +11 | Decimal("1") + | ^^^^^^^ expected String +12 | ); + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_3.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_3.diag index 0c40c5ed9db..caeabfd6453 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_3.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_3.diag @@ -1,15 +1,15 @@ -error: expected Address or NamedAddress, found String - | - 8 | "create_proof_of_amount" - 9 | Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") -10 | Decimal("1"); -11 | -12 | MINT_FUNGIBLE -13 | "component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh" - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected Address or NamedAddress -14 | Decimal("20"); -15 | -16 | CALL_METHOD -17 | Address("${account_address}") -18 | "deposit_batch" - | \ No newline at end of file +error: expected Address or NamedAddress, found String + | + 8 | "create_proof_of_amount" + 9 | Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") +10 | Decimal("1"); +11 | +12 | MINT_FUNGIBLE +13 | "component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected Address or NamedAddress +14 | Decimal("20"); +15 | +16 | CALL_METHOD +17 | Address("${account_address}") +18 | "deposit_batch" + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_4.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_4.diag index 51848754627..49ffe39d905 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_4.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_4.diag @@ -1,15 +1,15 @@ -error: expected NonFungibleLocalId, found U32 - | - 1 | CALL_METHOD Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") "withdraw" Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") Decimal("5.0"); - 2 | - 3 | # Create a proof from bucket, clone it and drop both - 4 | TAKE_ALL_FROM_WORKTOP Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") Bucket("some_xrd"); - 5 | CREATE_PROOF_FROM_BUCKET_OF_AMOUNT Bucket("some_xrd") Decimal("1") Proof("proof1a"); - 6 | CREATE_PROOF_FROM_BUCKET_OF_NON_FUNGIBLES Bucket("some_xrd") Array(1u32) Proof("proof1b"); - | ^^^^ expected NonFungibleLocalId - 7 | CREATE_PROOF_FROM_BUCKET_OF_ALL Bucket("some_xrd") Proof("proof1c"); - 8 | CLONE_PROOF Proof("proof1c") Proof("proof1d"); - 9 | DROP_PROOF Proof("proof1d"); -10 | DROP_PROOF Proof("proof1c"); -11 | DROP_AUTH_ZONE_PROOFS; - | \ No newline at end of file +error: expected NonFungibleLocalId, found U32 + | + 1 | CALL_METHOD Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") "withdraw" Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") Decimal("5.0"); + 2 | + 3 | # Create a proof from bucket, clone it and drop both + 4 | TAKE_ALL_FROM_WORKTOP Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") Bucket("some_xrd"); + 5 | CREATE_PROOF_FROM_BUCKET_OF_AMOUNT Bucket("some_xrd") Decimal("1") Proof("proof1a"); + 6 | CREATE_PROOF_FROM_BUCKET_OF_NON_FUNGIBLES Bucket("some_xrd") Array(1u32) Proof("proof1b"); + | ^^^^ expected NonFungibleLocalId + 7 | CREATE_PROOF_FROM_BUCKET_OF_ALL Bucket("some_xrd") Proof("proof1c"); + 8 | CLONE_PROOF Proof("proof1c") Proof("proof1d"); + 9 | DROP_PROOF Proof("proof1d"); +10 | DROP_PROOF Proof("proof1c"); +11 | DROP_AUTH_ZONE_PROOFS; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_5.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_5.diag index 858487a368b..c63c806ba2b 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_5.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_ast_value_5.diag @@ -1,11 +1,11 @@ -error: expected String, found Bool - | - 6 | CALL_METHOD - 7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") - 8 | "some_method" - 9 | "text mixed with 🤓 and 🥸 unicodes" -10 | "\uD83D\uDC69" -11 | Decimal(true) - | ^^^^ expected String -12 | ; - | \ No newline at end of file +error: expected String, found Bool + | + 6 | CALL_METHOD + 7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") + 8 | "some_method" + 9 | "text mixed with 🤓 and 🥸 unicodes" +10 | "\uD83D\uDC69" +11 | Decimal(true) + | ^^^^ expected String +12 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_blob_hash_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_blob_hash_1.diag index 328c2e55bae..6ba19d89a25 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_blob_hash_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_blob_hash_1.diag @@ -1,15 +1,15 @@ -error: invalid blob hash 'abbcc' - invalid hex value - | -12 | PUBLISH_PACKAGE_ADVANCED -13 | Enum() -14 | Tuple( -15 | Map() -16 | ) -17 | Blob("abbcc") - | ^^^^^^^ invalid blob hash -18 | Map() -19 | Some(AddressReservation("my_reservation")) -20 | ; -21 | CALL_FUNCTION -22 | NamedAddress("my_package") - | \ No newline at end of file +error: invalid blob hash 'abbcc' - invalid hex value + | +12 | PUBLISH_PACKAGE_ADVANCED +13 | Enum() +14 | Tuple( +15 | Map() +16 | ) +17 | Blob("abbcc") + | ^^^^^^^ invalid blob hash +18 | Map() +19 | Some(AddressReservation("my_reservation")) +20 | ; +21 | CALL_FUNCTION +22 | NamedAddress("my_package") + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_blob_hash_2.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_blob_hash_2.diag index 9761242d5e2..60868b5606f 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_blob_hash_2.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_blob_hash_2.diag @@ -1,15 +1,15 @@ -error: invalid blob hash 'aabbcc' - invalid hash length 3, expected 32 - | -12 | PUBLISH_PACKAGE_ADVANCED -13 | Enum() -14 | Tuple( -15 | Map() -16 | ) -17 | Blob("aabbcc") - | ^^^^^^^^ invalid blob hash -18 | Map() -19 | Some(AddressReservation("my_reservation")) -20 | ; -21 | CALL_FUNCTION -22 | NamedAddress("my_package") - | \ No newline at end of file +error: invalid blob hash 'aabbcc' - invalid hash length 3, expected 32 + | +12 | PUBLISH_PACKAGE_ADVANCED +13 | Enum() +14 | Tuple( +15 | Map() +16 | ) +17 | Blob("aabbcc") + | ^^^^^^^^ invalid blob hash +18 | Map() +19 | Some(AddressReservation("my_reservation")) +20 | ; +21 | CALL_FUNCTION +22 | NamedAddress("my_package") + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_bytes_hex_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_bytes_hex_1.diag index 2d42635b6a5..3eb344cb2f5 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_bytes_hex_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_bytes_hex_1.diag @@ -1,11 +1,11 @@ -error: invalid hex value 'invalid_hex' - | - 4 | ; - 5 | CALL_FUNCTION - 6 | Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") - 7 | "Hello" - 8 | "instantiate_hello" - 9 | Bytes("invalid_hex") - | ^^^^^^^^^^^^^ invalid hex value -10 | ; - | \ No newline at end of file +error: invalid hex value 'invalid_hex' + | + 4 | ; + 5 | CALL_FUNCTION + 6 | Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") + 7 | "Hello" + 8 | "instantiate_hello" + 9 | Bytes("invalid_hex") + | ^^^^^^^^^^^^^ invalid hex value +10 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_decimal_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_decimal_1.diag index 7a120a91968..c692b27bada 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_decimal_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_decimal_1.diag @@ -1,11 +1,11 @@ -error: invalid decimal '1.000000000000000011111111' - MoreThanEighteenDecimalPlaces - | - 8 | Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") - 9 | Bucket("some_xrd"); -10 | -11 | CREATE_PROOF_FROM_BUCKET_OF_AMOUNT -12 | Bucket("some_xrd") -13 | Decimal("1.000000000000000011111111") - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid decimal -14 | Proof("proof1a"); - | \ No newline at end of file +error: invalid decimal '1.000000000000000011111111' - MoreThanEighteenDecimalPlaces + | + 8 | Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") + 9 | Bucket("some_xrd"); +10 | +11 | CREATE_PROOF_FROM_BUCKET_OF_AMOUNT +12 | Bucket("some_xrd") +13 | Decimal("1.000000000000000011111111") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid decimal +14 | Proof("proof1a"); + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_decimal_2.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_decimal_2.diag index 1ef179e6353..2d1f23b1403 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_decimal_2.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_decimal_2.diag @@ -1,11 +1,11 @@ -error: invalid decimal '基数引擎' - InvalidDigit - | - 4 | ; - 5 | - 6 | CALL_METHOD - 7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") - 8 | "some_method" - 9 | Decimal("基数引擎") - | ^^^^^^^^^^ invalid decimal -10 | ; - | \ No newline at end of file +error: invalid decimal '基数引擎' - InvalidDigit + | + 4 | ; + 5 | + 6 | CALL_METHOD + 7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") + 8 | "some_method" + 9 | Decimal("基数引擎") + | ^^^^^^^^^^ invalid decimal +10 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_decimal_3.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_decimal_3.diag index 0c440621062..00d62a99e59 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_decimal_3.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_decimal_3.diag @@ -1,11 +1,11 @@ -error: invalid decimal '👩' - InvalidDigit - | - 4 | ; - 5 | - 6 | CALL_METHOD - 7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") - 8 | "some_method" - 9 | Decimal("\uD83D\uDC69") - | ^^^^^^^^^^^^^^ invalid decimal -10 | ; - | \ No newline at end of file +error: invalid decimal '👩' - InvalidDigit + | + 4 | ; + 5 | + 6 | CALL_METHOD + 7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") + 8 | "some_method" + 9 | Decimal("\uD83D\uDC69") + | ^^^^^^^^^^^^^^ invalid decimal +10 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_expression_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_expression_1.diag index 780ed980a63..27794c88359 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_expression_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_expression_1.diag @@ -1,10 +1,10 @@ -error: invalid expression 'FULL_WORKTOP' - | -24 | Expression("ENTIRE_AUTH_ZONE"); -25 | -26 | CALL_METHOD -27 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") -28 | "deposit_batch" -29 | Expression("FULL_WORKTOP"); - | ^^^^^^^^^^^^^^ invalid expression - | \ No newline at end of file +error: invalid expression 'FULL_WORKTOP' + | +24 | Expression("ENTIRE_AUTH_ZONE"); +25 | +26 | CALL_METHOD +27 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") +28 | "deposit_batch" +29 | Expression("FULL_WORKTOP"); + | ^^^^^^^^^^^^^^ invalid expression + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_global_address_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_global_address_1.diag index 9b4375b5adb..86e10b6ac26 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_global_address_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_global_address_1.diag @@ -1,15 +1,15 @@ -error: invalid global address 'invalid_address' - | - 2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") - 3 | "lock_fee" - 4 | Decimal("500"); - 5 | - 6 | CALL_METHOD - 7 | Address("invalid_address") - | ^^^^^^^^^^^^^^^^^ invalid global address - 8 | "create_proof_of_amount" - 9 | Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") -10 | Decimal("1"); -11 | -12 | MINT_FUNGIBLE - | \ No newline at end of file +error: invalid global address 'invalid_address' + | + 2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") + 3 | "lock_fee" + 4 | Decimal("500"); + 5 | + 6 | CALL_METHOD + 7 | Address("invalid_address") + | ^^^^^^^^^^^^^^^^^ invalid global address + 8 | "create_proof_of_amount" + 9 | Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") +10 | Decimal("1"); +11 | +12 | MINT_FUNGIBLE + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_internal_address_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_internal_address_1.diag index e3257522677..66844e1210a 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_internal_address_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_internal_address_1.diag @@ -1,14 +1,14 @@ -error: invalid internal address 'component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh' - | - 2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") - 3 | "lock_fee" - 4 | Decimal("5000") - 5 | ; - 6 | FREEZE_VAULT - 7 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid internal address - 8 | Tuple( - 9 | 2u32 -10 | ) -11 | ; - | \ No newline at end of file +error: invalid internal address 'component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh' + | + 2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") + 3 | "lock_fee" + 4 | Decimal("5000") + 5 | ; + 6 | FREEZE_VAULT + 7 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid internal address + 8 | Tuple( + 9 | 2u32 +10 | ) +11 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_non_fungible_global_id_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_non_fungible_global_id_1.diag index 7f358808963..8ffc245467f 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_non_fungible_global_id_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_non_fungible_global_id_1.diag @@ -1,11 +1,11 @@ -error: invalid non-fungible global id - | - 4 | ; - 5 | CALL_FUNCTION - 6 | Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") - 7 | "Hello" - 8 | "instantiate_hello" - 9 | NonFungibleGlobalId("resource_sim1n2n538l5hpaagvl0phkff3qkdd6pxh0kskh8umuknr8c3whsl62dxp:some_id") - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid non-fungible global id -10 | ; - | \ No newline at end of file +error: invalid non-fungible global id + | + 4 | ; + 5 | CALL_FUNCTION + 6 | Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") + 7 | "Hello" + 8 | "instantiate_hello" + 9 | NonFungibleGlobalId("resource_sim1n2n538l5hpaagvl0phkff3qkdd6pxh0kskh8umuknr8c3whsl62dxp:some_id") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid non-fungible global id +10 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_non_fungible_local_id_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_non_fungible_local_id_1.diag index 96ff669c6fb..bb691917d1d 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_non_fungible_local_id_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_non_fungible_local_id_1.diag @@ -1,15 +1,15 @@ -error: invalid non-fungible local id 'some_id' - | - 1 | CALL_METHOD Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") "withdraw" Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") Decimal("5.0"); - 2 | - 3 | # Create a proof from bucket, clone it and drop both - 4 | TAKE_ALL_FROM_WORKTOP Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") Bucket("some_xrd"); - 5 | CREATE_PROOF_FROM_BUCKET_OF_AMOUNT Bucket("some_xrd") Decimal("1") Proof("proof1a"); - 6 | CREATE_PROOF_FROM_BUCKET_OF_NON_FUNGIBLES Bucket("some_xrd") Array(NonFungibleLocalId("some_id")) Proof("proof1b"); - | ^^^^^^^^^ invalid non-fungible local id - 7 | CREATE_PROOF_FROM_BUCKET_OF_ALL Bucket("some_xrd") Proof("proof1c"); - 8 | CLONE_PROOF Proof("proof1c") Proof("proof1d"); - 9 | DROP_PROOF Proof("proof1d"); -10 | DROP_PROOF Proof("proof1c"); -11 | DROP_AUTH_ZONE_PROOFS; - | \ No newline at end of file +error: invalid non-fungible local id 'some_id' + | + 1 | CALL_METHOD Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") "withdraw" Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") Decimal("5.0"); + 2 | + 3 | # Create a proof from bucket, clone it and drop both + 4 | TAKE_ALL_FROM_WORKTOP Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") Bucket("some_xrd"); + 5 | CREATE_PROOF_FROM_BUCKET_OF_AMOUNT Bucket("some_xrd") Decimal("1") Proof("proof1a"); + 6 | CREATE_PROOF_FROM_BUCKET_OF_NON_FUNGIBLES Bucket("some_xrd") Array(NonFungibleLocalId("some_id")) Proof("proof1b"); + | ^^^^^^^^^ invalid non-fungible local id + 7 | CREATE_PROOF_FROM_BUCKET_OF_ALL Bucket("some_xrd") Proof("proof1c"); + 8 | CLONE_PROOF Proof("proof1c") Proof("proof1d"); + 9 | DROP_PROOF Proof("proof1d"); +10 | DROP_PROOF Proof("proof1c"); +11 | DROP_AUTH_ZONE_PROOFS; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_package_address_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_package_address_1.diag index 7252a8bbc89..611dca21e6a 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_package_address_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_package_address_1.diag @@ -1,13 +1,13 @@ -error: invalid package address 'package_1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk' - | -1 | CALL_METHOD -2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") -3 | "lock_fee" -4 | ; -5 | CALL_FUNCTION -6 | Address("package_1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid package address -7 | "Hello" -8 | "instantiate_hello" -9 | ; - | \ No newline at end of file +error: invalid package address 'package_1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk' + | +1 | CALL_METHOD +2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") +3 | "lock_fee" +4 | ; +5 | CALL_FUNCTION +6 | Address("package_1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid package address +7 | "Hello" +8 | "instantiate_hello" +9 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_package_address_2.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_package_address_2.diag index a5b236ea291..d43dc6fea0e 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_package_address_2.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_package_address_2.diag @@ -1,15 +1,15 @@ -error: invalid package address 'package_1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk' - | - 2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") - 3 | "lock_fee" - 4 | Decimal("500") - 5 | ; - 6 | ALLOCATE_GLOBAL_ADDRESS - 7 | Address("package_1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid package address - 8 | "Package" - 9 | AddressReservation("my_reservation") -10 | NamedAddress("my_package") -11 | ; -12 | PUBLISH_PACKAGE_ADVANCED - | \ No newline at end of file +error: invalid package address 'package_1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk' + | + 2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") + 3 | "lock_fee" + 4 | Decimal("500") + 5 | ; + 6 | ALLOCATE_GLOBAL_ADDRESS + 7 | Address("package_1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid package address + 8 | "Package" + 9 | AddressReservation("my_reservation") +10 | NamedAddress("my_package") +11 | ; +12 | PUBLISH_PACKAGE_ADVANCED + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_precise_decimal_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_precise_decimal_1.diag index 72698659e99..0fba58760fb 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_precise_decimal_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_precise_decimal_1.diag @@ -1,11 +1,11 @@ -error: invalid precise decimal '1.' - EmptyFractionalPart - | - 4 | ; - 5 | CALL_FUNCTION - 6 | Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") - 7 | "Hello" - 8 | "instantiate_hello" - 9 | PreciseDecimal("1.") - | ^^^^ invalid precise decimal -10 | ; - | \ No newline at end of file +error: invalid precise decimal '1.' - EmptyFractionalPart + | + 4 | ; + 5 | CALL_FUNCTION + 6 | Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") + 7 | "Hello" + 8 | "instantiate_hello" + 9 | PreciseDecimal("1.") + | ^^^^ invalid precise decimal +10 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_resource_address_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_resource_address_1.diag index e1882fa8921..329416a84c8 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_invalid_resource_address_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_resource_address_1.diag @@ -1,15 +1,15 @@ -error: invalid resource address 'resource_address' - | -13 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") -14 | "buy_gumball" -15 | Bucket("xrd_bucket"); -16 | -17 | ASSERT_WORKTOP_CONTAINS_ANY -18 | Address("resource_address"); - | ^^^^^^^^^^^^^^^^^^ invalid resource address -19 | -20 | ASSERT_WORKTOP_CONTAINS -21 | Address("resource_sim1t5q5qqum600pwwu27zl7m4rpr8g0400e72n368g09tgnptqe6kuwst") -22 | Decimal("3.0"); -23 | - | \ No newline at end of file +error: invalid resource address 'resource_address' + | +13 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") +14 | "buy_gumball" +15 | Bucket("xrd_bucket"); +16 | +17 | ASSERT_WORKTOP_CONTAINS_ANY +18 | Address("resource_address"); + | ^^^^^^^^^^^^^^^^^^ invalid resource address +19 | +20 | ASSERT_WORKTOP_CONTAINS +21 | Address("resource_sim1t5q5qqum600pwwu27zl7m4rpr8g0400e72n368g09tgnptqe6kuwst") +22 | Decimal("3.0"); +23 | + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_sub_transaction_id_1.diag b/radix-transactions/tests/assets/manifest_generator_error_invalid_sub_transaction_id_1.diag new file mode 100644 index 00000000000..c8e9c84dcd0 --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_sub_transaction_id_1.diag @@ -0,0 +1,8 @@ +error: invalid sub transaction id 'subtxid_sim1___oops_this_is_invalid' + | +1 | USE_CHILD +2 | NamedIntent("my_child") +3 | Intent("subtxid_sim1___oops_this_is_invalid") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid sub transaction id +4 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_invalid_sub_transaction_id_1.rtm b/radix-transactions/tests/assets/manifest_generator_error_invalid_sub_transaction_id_1.rtm new file mode 100644 index 00000000000..c255e6b47f8 --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_invalid_sub_transaction_id_1.rtm @@ -0,0 +1,4 @@ +USE_CHILD + NamedIntent("my_child") + Intent("subtxid_sim1___oops_this_is_invalid") +; \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_1.diag b/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_1.diag index 299b7f08e54..51dbaa555fd 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_1.diag @@ -1,15 +1,15 @@ -error: name already defined 'my_reservation' - | -10 | NamedAddress("my_package") -11 | ; -12 | ALLOCATE_GLOBAL_ADDRESS -13 | Address("package_sim1pkgxxxxxxxxxpackgexxxxxxxxx000726633226xxxxxxxxxlk8hc9") -14 | "Package" -15 | AddressReservation("my_reservation") - | ^^^^^^^^^^^^^^^^ name already defined -16 | NamedAddress("my_second_package") -17 | ; -18 | PUBLISH_PACKAGE_ADVANCED -19 | Enum() -20 | Tuple( - | \ No newline at end of file +error: name already defined 'my_reservation' + | +10 | NamedAddress("my_package") +11 | ; +12 | ALLOCATE_GLOBAL_ADDRESS +13 | Address("package_sim1pkgxxxxxxxxxpackgexxxxxxxxx000726633226xxxxxxxxxlk8hc9") +14 | "Package" +15 | AddressReservation("my_reservation") + | ^^^^^^^^^^^^^^^^ name already defined +16 | NamedAddress("my_second_package") +17 | ; +18 | PUBLISH_PACKAGE_ADVANCED +19 | Enum() +20 | Tuple( + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_2.diag b/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_2.diag index f8eafd763a5..ef8932e8635 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_2.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_2.diag @@ -1,15 +1,15 @@ -error: name already defined 'my_package' - | -11 | ; -12 | ALLOCATE_GLOBAL_ADDRESS -13 | Address("package_sim1pkgxxxxxxxxxpackgexxxxxxxxx000726633226xxxxxxxxxlk8hc9") -14 | "Package" -15 | AddressReservation("my_second_reservation") -16 | NamedAddress("my_package") - | ^^^^^^^^^^^^ name already defined -17 | ; -18 | PUBLISH_PACKAGE_ADVANCED -19 | Enum() -20 | Tuple( -21 | Map() - | \ No newline at end of file +error: name already defined 'my_package' + | +11 | ; +12 | ALLOCATE_GLOBAL_ADDRESS +13 | Address("package_sim1pkgxxxxxxxxxpackgexxxxxxxxx000726633226xxxxxxxxxlk8hc9") +14 | "Package" +15 | AddressReservation("my_second_reservation") +16 | NamedAddress("my_package") + | ^^^^^^^^^^^^ name already defined +17 | ; +18 | PUBLISH_PACKAGE_ADVANCED +19 | Enum() +20 | Tuple( +21 | Map() + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_3.diag b/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_3.diag index de6ecdab440..904c3b6b3f3 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_3.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_3.diag @@ -1,14 +1,14 @@ -error: name already defined 'proof1a' - | - 7 | Bucket("some_xrd") - 8 | Array( - 9 | NonFungibleLocalId("#123#") -10 | ) -11 | Proof("proof1b"); -12 | CREATE_PROOF_FROM_BUCKET_OF_ALL Bucket("some_xrd") Proof("proof1a"); - | ^^^^^^^^^ name already defined -13 | CLONE_PROOF Proof("proof1c") Proof("proof1d"); -14 | DROP_PROOF Proof("proof1d"); -15 | DROP_PROOF Proof("proof1c"); -16 | DROP_AUTH_ZONE_PROOFS; - | \ No newline at end of file +error: name already defined 'proof1a' + | + 7 | Bucket("some_xrd") + 8 | Array( + 9 | NonFungibleLocalId("#123#") +10 | ) +11 | Proof("proof1b"); +12 | CREATE_PROOF_FROM_BUCKET_OF_ALL Bucket("some_xrd") Proof("proof1a"); + | ^^^^^^^^^ name already defined +13 | CLONE_PROOF Proof("proof1c") Proof("proof1d"); +14 | DROP_PROOF Proof("proof1d"); +15 | DROP_PROOF Proof("proof1c"); +16 | DROP_AUTH_ZONE_PROOFS; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_4.diag b/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_4.diag index e5ca302bb57..d0bbf8406c3 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_4.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_name_already_defined_4.diag @@ -1,15 +1,15 @@ -error: name already defined 'xrd' - | -10 | Bucket("xrd"); -11 | -12 | TAKE_FROM_WORKTOP -13 | Address("resource_sim1t45r6lyr36ypj64sumrmkk9pjesfyl9na849jz00qrwnx28c8sletw") -14 | Decimal("1.0") -15 | Bucket("xrd"); - | ^^^^^ name already defined -16 | -17 | CALL_METHOD -18 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") -19 | "buy_gumball" -20 | Bucket("xrd"); - | \ No newline at end of file +error: name already defined 'xrd' + | +10 | Bucket("xrd"); +11 | +12 | TAKE_FROM_WORKTOP +13 | Address("resource_sim1t45r6lyr36ypj64sumrmkk9pjesfyl9na849jz00qrwnx28c8sletw") +14 | Decimal("1.0") +15 | Bucket("xrd"); + | ^^^^^ name already defined +16 | +17 | CALL_METHOD +18 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") +19 | "buy_gumball" +20 | Bucket("xrd"); + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_named_intent_cannot_be_used_as_value_kind_1.diag b/radix-transactions/tests/assets/manifest_generator_error_named_intent_cannot_be_used_as_value_kind_1.diag new file mode 100644 index 00000000000..0271473b8bd --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_named_intent_cannot_be_used_as_value_kind_1.diag @@ -0,0 +1,9 @@ +error: a NamedIntent cannot be used as a value kind + | +1 | CALL_METHOD +2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") +3 | "my_method" +4 | Array() + | ^^^^^^^^^^^ cannot be used as a value kind +5 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_named_intent_cannot_be_used_as_value_kind_1.rtm b/radix-transactions/tests/assets/manifest_generator_error_named_intent_cannot_be_used_as_value_kind_1.rtm new file mode 100644 index 00000000000..9cd76399b2f --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_named_intent_cannot_be_used_as_value_kind_1.rtm @@ -0,0 +1,5 @@ +CALL_METHOD + Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") + "my_method" + Array() +; \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_named_intent_cannot_be_used_in_value_1.diag b/radix-transactions/tests/assets/manifest_generator_error_named_intent_cannot_be_used_in_value_1.diag new file mode 100644 index 00000000000..b7d75d84917 --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_named_intent_cannot_be_used_in_value_1.diag @@ -0,0 +1,9 @@ +error: a NamedIntent(...) cannot currently be used inside a value + | +1 | CALL_METHOD +2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") +3 | "my_method" +4 | NamedIntent("my_intent") + | ^^^^^^^^^^^ cannot be used inside a value +5 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_named_intent_cannot_be_used_in_value_1.rtm b/radix-transactions/tests/assets/manifest_generator_error_named_intent_cannot_be_used_in_value_1.rtm new file mode 100644 index 00000000000..62e95fc4e42 --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_named_intent_cannot_be_used_in_value_1.rtm @@ -0,0 +1,5 @@ +CALL_METHOD + Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") + "my_method" + NamedIntent("my_intent") +; \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_preallocated_addresses_unsupported_by_manifest_type_1.diag b/radix-transactions/tests/assets/manifest_generator_error_preallocated_addresses_unsupported_by_manifest_type_1.diag new file mode 100644 index 00000000000..3710ba18e16 --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_preallocated_addresses_unsupported_by_manifest_type_1.diag @@ -0,0 +1,10 @@ +error: preallocated addresses are not supported in this manifest type + | +1 | / USE_PREALLOCATED_ADDRESS +2 | | Address("package_sim1pkgxxxxxxxxxresrcexxxxxxxxx000538436477xxxxxxxxxaj0zg9") +3 | | "FungibleResourceManager" +4 | | AddressReservation("reservation1") +5 | | Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") +6 | | ; + | |_^ unsupported instruction + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_preallocated_addresses_unsupported_by_manifest_type_1.rtm b/radix-transactions/tests/assets/manifest_generator_error_preallocated_addresses_unsupported_by_manifest_type_1.rtm new file mode 100644 index 00000000000..7bb1535527b --- /dev/null +++ b/radix-transactions/tests/assets/manifest_generator_error_preallocated_addresses_unsupported_by_manifest_type_1.rtm @@ -0,0 +1,6 @@ +USE_PREALLOCATED_ADDRESS + Address("package_sim1pkgxxxxxxxxxresrcexxxxxxxxx000538436477xxxxxxxxxaj0zg9") + "FungibleResourceManager" + AddressReservation("reservation1") + Address("resource_sim1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxakj8n3") +; \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_proof_not_found_1.diag b/radix-transactions/tests/assets/manifest_generator_error_proof_not_found_1.diag index 11e7b02d8bc..c29ba35ca78 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_proof_not_found_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_proof_not_found_1.diag @@ -1,12 +1,12 @@ -error: proof id 'ManifestProof(1)' not found - | -18 | Bucket("some_bucket") -19 | Decimal("1") -20 | Proof("proof"); -21 | -22 | CLONE_PROOF -23 | Proof(1u32) - | ^^^^ proof not found -24 | Proof("cloned_proof") -25 | ; - | \ No newline at end of file +error: proof id 'ManifestProof(1)' not found + | +18 | Bucket("some_bucket") +19 | Decimal("1") +20 | Proof("proof"); +21 | +22 | CLONE_PROOF +23 | Proof(1u32) + | ^^^^ proof not found +24 | Proof("cloned_proof") +25 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_proof_not_found_2.diag b/radix-transactions/tests/assets/manifest_generator_error_proof_not_found_2.diag index 0a3753914b1..63e0d224b20 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_proof_not_found_2.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_proof_not_found_2.diag @@ -1,11 +1,11 @@ -error: proof id 'ManifestProof(1)' not found - | -18 | Bucket("some_bucket") -19 | Decimal("1") -20 | Proof("proof"); -21 | -22 | DROP_PROOF -23 | Proof(1u32) - | ^^^^ proof not found -24 | ; - | \ No newline at end of file +error: proof id 'ManifestProof(1)' not found + | +18 | Bucket("some_bucket") +19 | Decimal("1") +20 | Proof("proof"); +21 | +22 | DROP_PROOF +23 | Proof(1u32) + | ^^^^ proof not found +24 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_undefined_address_reservation_1.diag b/radix-transactions/tests/assets/manifest_generator_error_undefined_address_reservation_1.diag index 691494056b6..9c62d25a26f 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_undefined_address_reservation_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_undefined_address_reservation_1.diag @@ -1,15 +1,15 @@ -error: undefined address reservation 'invalid_reservation' - | -14 | Tuple( -15 | Map() -16 | ) -17 | Blob("f531e5e82dc195a7a9f6709f5ee048d9541d51c52904b7a76295a13ddfa377b1") -18 | Map() -19 | Some(AddressReservation("invalid_reservation")) - | ^^^^^^^^^^^^^^^^^^^^^ undefined address reservation -20 | ; -21 | CALL_FUNCTION -22 | NamedAddress("my_package") -23 | "BlueprintName" -24 | "no_such_function" - | \ No newline at end of file +error: undefined address reservation 'invalid_reservation' + | +14 | Tuple( +15 | Map() +16 | ) +17 | Blob("f531e5e82dc195a7a9f6709f5ee048d9541d51c52904b7a76295a13ddfa377b1") +18 | Map() +19 | Some(AddressReservation("invalid_reservation")) + | ^^^^^^^^^^^^^^^^^^^^^ undefined address reservation +20 | ; +21 | CALL_FUNCTION +22 | NamedAddress("my_package") +23 | "BlueprintName" +24 | "no_such_function" + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_undefined_bucket_1.diag b/radix-transactions/tests/assets/manifest_generator_error_undefined_bucket_1.diag index 52eae70ea94..7978e8a0da9 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_undefined_bucket_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_undefined_bucket_1.diag @@ -1,15 +1,15 @@ -error: undefined bucket 'another_xrd_bucket' - | -10 | Bucket("xrd_bucket"); -11 | -12 | CALL_METHOD -13 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") -14 | "buy_gumball" -15 | Bucket("another_xrd_bucket"); - | ^^^^^^^^^^^^^^^^^^^^ undefined bucket -16 | -17 | ASSERT_WORKTOP_CONTAINS_ANY -18 | Address("resource_sim1t5q5qqum600pwwu27zl7m4rpr8g0400e72n368g09tgnptqe6kuwst"); -19 | -20 | ASSERT_WORKTOP_CONTAINS - | \ No newline at end of file +error: undefined bucket 'another_xrd_bucket' + | +10 | Bucket("xrd_bucket"); +11 | +12 | CALL_METHOD +13 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") +14 | "buy_gumball" +15 | Bucket("another_xrd_bucket"); + | ^^^^^^^^^^^^^^^^^^^^ undefined bucket +16 | +17 | ASSERT_WORKTOP_CONTAINS_ANY +18 | Address("resource_sim1t5q5qqum600pwwu27zl7m4rpr8g0400e72n368g09tgnptqe6kuwst"); +19 | +20 | ASSERT_WORKTOP_CONTAINS + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_undefined_named_address_1.diag b/radix-transactions/tests/assets/manifest_generator_error_undefined_named_address_1.diag index 792e4dcd61e..0c8d9ab0d3f 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_undefined_named_address_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_undefined_named_address_1.diag @@ -1,15 +1,15 @@ -error: undefined named address 'package_address' - | -17 | Blob("f531e5e82dc195a7a9f6709f5ee048d9541d51c52904b7a76295a13ddfa377b1") -18 | Map() -19 | Some(AddressReservation("my_reservation")) -20 | ; -21 | CALL_FUNCTION -22 | NamedAddress("package_address") - | ^^^^^^^^^^^^^^^^^ undefined named address -23 | "BlueprintName" -24 | "no_such_function" -25 | Decimal("1.0") -26 | NamedAddress("my_package") -27 | ; - | \ No newline at end of file +error: undefined named address 'package_address' + | +17 | Blob("f531e5e82dc195a7a9f6709f5ee048d9541d51c52904b7a76295a13ddfa377b1") +18 | Map() +19 | Some(AddressReservation("my_reservation")) +20 | ; +21 | CALL_FUNCTION +22 | NamedAddress("package_address") + | ^^^^^^^^^^^^^^^^^ undefined named address +23 | "BlueprintName" +24 | "no_such_function" +25 | Decimal("1.0") +26 | NamedAddress("my_package") +27 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_undefined_proof_1.diag b/radix-transactions/tests/assets/manifest_generator_error_undefined_proof_1.diag index 474eeb3f72e..a5a2f7d2117 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_undefined_proof_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_undefined_proof_1.diag @@ -1,14 +1,14 @@ -error: undefined proof 'proof_2' - | -11 | CREATE_PROOF_FROM_BUCKET_OF_AMOUNT Bucket("some_xrd") -12 | Decimal("1") -13 | Proof("proof_1"); -14 | -15 | CLONE_PROOF -16 | Proof("proof_2") - | ^^^^^^^^^ undefined proof -17 | Proof("cloned_proof"); -18 | -19 | DROP_PROOF Proof("proof_1"); -20 | DROP_PROOF Proof("cloned_proof"); - | \ No newline at end of file +error: undefined proof 'proof_2' + | +11 | CREATE_PROOF_FROM_BUCKET_OF_AMOUNT Bucket("some_xrd") +12 | Decimal("1") +13 | Proof("proof_1"); +14 | +15 | CLONE_PROOF +16 | Proof("proof_2") + | ^^^^^^^^^ undefined proof +17 | Proof("cloned_proof"); +18 | +19 | DROP_PROOF Proof("proof_1"); +20 | DROP_PROOF Proof("cloned_proof"); + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_unexpected_value_1.diag b/radix-transactions/tests/assets/manifest_generator_error_unexpected_value_1.diag index 494c002efb0..5ad2117d8b2 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_unexpected_value_1.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_unexpected_value_1.diag @@ -1,13 +1,13 @@ -error: expected String, found U32 - | - 5 | CALL_METHOD - 6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") - 7 | "some_method" - 8 | Array( - 9 | "one", -10 | 2u32, - | ^^^^ expected String -11 | "three" -12 | ) -13 | ; - | \ No newline at end of file +error: expected String, found U32 + | + 5 | CALL_METHOD + 6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") + 7 | "some_method" + 8 | Array( + 9 | "one", +10 | 2u32, + | ^^^^ expected String +11 | "three" +12 | ) +13 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_generator_error_unexpected_value_2.diag b/radix-transactions/tests/assets/manifest_generator_error_unexpected_value_2.diag index 77f5b22c09e..dd29fe04191 100644 --- a/radix-transactions/tests/assets/manifest_generator_error_unexpected_value_2.diag +++ b/radix-transactions/tests/assets/manifest_generator_error_unexpected_value_2.diag @@ -1,13 +1,13 @@ -error: expected String, found Bytes - | - 5 | CALL_METHOD - 6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") - 7 | "some_method" - 8 | Array( - 9 | "one", -10 | Bytes(1u32), - | ^^^^^ expected String -11 | "three" -12 | ) -13 | ; - | \ No newline at end of file +error: expected String, found Bytes + | + 5 | CALL_METHOD + 6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") + 7 | "some_method" + 8 | Array( + 9 | "one", +10 | Bytes(1u32), + | ^^^^^ expected String +11 | "three" +12 | ) +13 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_1.diag b/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_1.diag index b5cd44d3cc7..cbe6d1b9b50 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_1.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_1.diag @@ -1,15 +1,15 @@ -error: invalid integer value '-300i8' - number too small to fit in target type - | - 2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") - 3 | "lock_fee"; - 4 | CALL_METHOD - 5 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") - 6 | "some_method" - 7 | -300i8; - | ^^^^^^ invalid integer value - 8 | CALL_METHOD - 9 | Address("account_sim1c956qr3kxlgypxwst89j9yf24tjc7zxd4up38x37zr6q4jxdx9rhma") -10 | "try_deposit_batch_or_abort" -11 | Expression("ENTIRE_WORKTOP") -12 | None; - | \ No newline at end of file +error: invalid integer value '-300i8' - number too small to fit in target type + | + 2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") + 3 | "lock_fee"; + 4 | CALL_METHOD + 5 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") + 6 | "some_method" + 7 | -300i8; + | ^^^^^^ invalid integer value + 8 | CALL_METHOD + 9 | Address("account_sim1c956qr3kxlgypxwst89j9yf24tjc7zxd4up38x37zr6q4jxdx9rhma") +10 | "try_deposit_batch_or_abort" +11 | Expression("ENTIRE_WORKTOP") +12 | None; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_2.diag b/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_2.diag index 8232fc29dd0..e582b8d24e2 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_2.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_2.diag @@ -1,7 +1,7 @@ -error: invalid integer value '300i8' - number too large to fit in target type - | -1 | CALL_METHOD Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") "lock_fee"; -2 | CALL_METHOD Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") "some_method" 300i8; - | ^^^^^ invalid integer value -3 | CALL_METHOD Address("account_sim1c956qr3kxlgypxwst89j9yf24tjc7zxd4up38x37zr6q4jxdx9rhma") "try_deposit_batch_or_abort" Expression("ENTIRE_WORKTOP") None; - | \ No newline at end of file +error: invalid integer value '300i8' - number too large to fit in target type + | +1 | CALL_METHOD Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") "lock_fee"; +2 | CALL_METHOD Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") "some_method" 300i8; + | ^^^^^ invalid integer value +3 | CALL_METHOD Address("account_sim1c956qr3kxlgypxwst89j9yf24tjc7zxd4up38x37zr6q4jxdx9rhma") "try_deposit_batch_or_abort" Expression("ENTIRE_WORKTOP") None; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_3.diag b/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_3.diag index 45e240aad6d..33f188a2ccc 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_3.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_3.diag @@ -1,11 +1,11 @@ -error: invalid integer value '-300u8' - invalid digit found in string - | -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "some_method" -8 | -300u8 - | ^^^^^^ invalid integer value -9 | ; - | \ No newline at end of file +error: invalid integer value '-300u8' - invalid digit found in string + | +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "some_method" +8 | -300u8 + | ^^^^^^ invalid integer value +9 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_literal_1.diag b/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_literal_1.diag index 7d58aac6ddf..b78b194c0c9 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_literal_1.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_literal_1.diag @@ -1,11 +1,11 @@ -error: invalid integer literal '- ' - | -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "some_method" -8 | - 107u32 - | ^^ invalid integer literal -9 | ; - | \ No newline at end of file +error: invalid integer literal '- ' + | +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "some_method" +8 | - 107u32 + | ^^ invalid integer literal +9 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_type_1.diag b/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_type_1.diag index edd531c5547..8635c184cab 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_type_1.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_type_1.diag @@ -1,11 +1,11 @@ -error: invalid integer type 'i9' - | -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "some_method" -8 | Decimal(300i9) - | ^^ invalid integer type -9 | ; - | \ No newline at end of file +error: invalid integer type 'i9' + | +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "some_method" +8 | Decimal(300i9) + | ^^ invalid integer type +9 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_type_2.diag b/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_type_2.diag index 4657f773242..7b8f4b32f7c 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_type_2.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_invalid_integer_type_2.diag @@ -1,11 +1,11 @@ -error: invalid integer type '_' - | -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "some_method" -8 | 3_0u32 - | ^ invalid integer type -9 | - | \ No newline at end of file +error: invalid integer type '_' + | +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "some_method" +8 | 3_0u32 + | ^ invalid integer type +9 | + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_invalid_unicode_1.diag b/radix-transactions/tests/assets/manifest_lexer_error_invalid_unicode_1.diag index 852bde78c1d..b48f61e92fc 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_invalid_unicode_1.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_invalid_unicode_1.diag @@ -1,11 +1,11 @@ -error: invalid unicode code point 1238580 - | -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "some_method" -8 | "\uDCAC\u1234" - | ^^^^^^^^^^^ invalid unicode code point -9 | ; - | \ No newline at end of file +error: invalid unicode code point 1238580 + | +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "some_method" +8 | "\uDCAC\u1234" + | ^^^^^^^^^^^ invalid unicode code point +9 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_missing_unicode_surrogate_1.diag b/radix-transactions/tests/assets/manifest_lexer_error_missing_unicode_surrogate_1.diag index 01666e39d16..ae91640881b 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_missing_unicode_surrogate_1.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_missing_unicode_surrogate_1.diag @@ -1,11 +1,11 @@ -error: missing unicode 'DCAC' surrogate pair - | -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "some_method" -8 | "\uDCACsome_text" - | ^^^^^ missing unicode surrogate pair -9 | ; - | \ No newline at end of file +error: missing unicode 'DCAC' surrogate pair + | +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "some_method" +8 | "\uDCACsome_text" + | ^^^^^ missing unicode surrogate pair +9 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_1.diag b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_1.diag index 753d8cec1d3..c551e1fa4ed 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_1.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_1.diag @@ -1,11 +1,11 @@ -error: unexpected character '%', expected digit, letter, quotation mark or one of punctuation characters '(', ')', '<', '>', ',', ';', '=' - | -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "some_method" -8 | Decimal(%27) - | ^ unexpected character -9 | ; - | \ No newline at end of file +error: unexpected character '%', expected digit, letter, quotation mark or one of punctuation characters '(', ')', '<', '>', ',', ';', '=' + | +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "some_method" +8 | Decimal(%27) + | ^ unexpected character +9 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_2.diag b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_2.diag index 50c44558efe..308bc7bc44d 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_2.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_2.diag @@ -1,10 +1,10 @@ -error: unexpected character 'x', expected '"', '\', '/', 'b', 'f', 'n', 'r', 't' or 'u' - | -2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "\xaaaa" - | ^ unexpected character - | \ No newline at end of file +error: unexpected character 'x', expected '"', '\', '/', 'b', 'f', 'n', 'r', 't' or 'u' + | +2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "\xaaaa" + | ^ unexpected character + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_3.diag b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_3.diag index 0a928060467..6e4d8fd48c0 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_3.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_3.diag @@ -1,5 +1,5 @@ -error: unexpected character '7', expected '>' - | -1 | x=7 - | ^ unexpected character - | \ No newline at end of file +error: unexpected character '7', expected '>' + | +1 | x=7 + | ^ unexpected character + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_4.diag b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_4.diag index 71c54c925a2..9809aed1231 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_4.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_4.diag @@ -1,11 +1,11 @@ -error: unexpected character 'K', expected hex digit - | -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "some_method" -8 | "\uFAKE" - | ^ unexpected character -9 | ; - | \ No newline at end of file +error: unexpected character 'K', expected hex digit + | +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "some_method" +8 | "\uFAKE" + | ^ unexpected character +9 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_5.diag b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_5.diag index 6eff6d05e73..faa988a7a4b 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_5.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_char_5.diag @@ -1,11 +1,11 @@ -error: unexpected character '基', expected digit, letter, quotation mark or one of punctuation characters '(', ')', '<', '>', ',', ';', '=' - | - 4 | ; - 5 | - 6 | CALL_METHOD - 7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") - 8 | "some_method" - 9 | 基数引擎 - | ^^ unexpected character -10 | ; - | \ No newline at end of file +error: unexpected character '基', expected digit, letter, quotation mark or one of punctuation characters '(', ')', '<', '>', ',', ';', '=' + | + 4 | ; + 5 | + 6 | CALL_METHOD + 7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") + 8 | "some_method" + 9 | 基数引擎 + | ^^ unexpected character +10 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_eof_1.diag b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_eof_1.diag index a6f61a31e63..737892c261f 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_eof_1.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_eof_1.diag @@ -1,10 +1,10 @@ -error: unexpected end of file - | -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "some_method" -8 | "\uDCA - | ^ unexpected end of file - | \ No newline at end of file +error: unexpected end of file + | +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "some_method" +8 | "\uDCA + | ^ unexpected end of file + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_eof_2.diag b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_eof_2.diag index 4bde2141752..827f96b6a3a 100644 --- a/radix-transactions/tests/assets/manifest_lexer_error_unexpected_eof_2.diag +++ b/radix-transactions/tests/assets/manifest_lexer_error_unexpected_eof_2.diag @@ -1,10 +1,10 @@ -error: unexpected end of file - | -2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "xxx - | ^ unexpected end of file - | \ No newline at end of file +error: unexpected end of file + | +2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "xxx + | ^ unexpected end of file + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_invalid_argument_1.diag b/radix-transactions/tests/assets/manifest_parser_error_invalid_argument_1.diag index eea1243b9df..1c28108464a 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_invalid_argument_1.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_invalid_argument_1.diag @@ -1,15 +1,15 @@ -error: expected a manifest SBOR value or ';' to end an argument list, found 'SET_COMPONENT_ROYALTY' - | -10 | SET_COMPONENT_ROYALTY -11 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -12 | "method_with_xrd_package_royalty" -13 | Enum<0u8>() -14 | -15 | SET_COMPONENT_ROYALTY - | ^^^^^^^^^^^^^^^^^^^^^ expected a manifest SBOR value or ';' to end an argument list -16 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -17 | "method_with_usd_package_royalty" -18 | Enum<0u8>() -19 | ; -20 | SET_COMPONENT_ROYALTY - | \ No newline at end of file +error: expected a manifest SBOR value or ';' to end an argument list, found 'SET_COMPONENT_ROYALTY' + | +10 | SET_COMPONENT_ROYALTY +11 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +12 | "method_with_xrd_package_royalty" +13 | Enum<0u8>() +14 | +15 | SET_COMPONENT_ROYALTY + | ^^^^^^^^^^^^^^^^^^^^^ expected a manifest SBOR value or ';' to end an argument list +16 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +17 | "method_with_usd_package_royalty" +18 | Enum<0u8>() +19 | ; +20 | SET_COMPONENT_ROYALTY + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_invalid_argument_2.diag b/radix-transactions/tests/assets/manifest_parser_error_invalid_argument_2.diag index 3ba965733a6..6d7875e73c4 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_invalid_argument_2.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_invalid_argument_2.diag @@ -1,11 +1,11 @@ -error: expected a manifest SBOR value or ';' to end an argument list, found ')' - | -3 | "lock_fee" -4 | ; -5 | SET_COMPONENT_ROYALTY -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "method_with_no_package_royalty" -8 | Enum<0u8>()) - | ^ expected a manifest SBOR value or ';' to end an argument list -9 | ; - | \ No newline at end of file +error: expected a manifest SBOR value or ';' to end an argument list, found ')' + | +3 | "lock_fee" +4 | ; +5 | SET_COMPONENT_ROYALTY +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "method_with_no_package_royalty" +8 | Enum<0u8>()) + | ^ expected a manifest SBOR value or ';' to end an argument list +9 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_1.diag b/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_1.diag index 0038cfc6e3e..9f1b99d60ef 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_1.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_1.diag @@ -1,15 +1,15 @@ -error: expected 2 number of types, found 3 - | -19 | None, -20 | None, -21 | None -22 | ) -23 | Tuple( -24 | Map( - | ^^^^^^^^^^^^^^^^^^^^ expected 2 number of types -25 | "name" => Tuple( -26 | Some(Enum("MyResource")), -27 | true -28 | ) -29 | ), - | \ No newline at end of file +error: expected 2 number of types, found 3 + | +19 | None, +20 | None, +21 | None +22 | ) +23 | Tuple( +24 | Map( + | ^^^^^^^^^^^^^^^^^^^^ expected 2 number of types +25 | "name" => Tuple( +26 | Some(Enum("MyResource")), +27 | true +28 | ) +29 | ), + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_2.diag b/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_2.diag index b6c36886708..4fd23752ad3 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_2.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_2.diag @@ -1,15 +1,15 @@ -error: expected 1 number of types, found 2 - | - 5 | - 6 | CREATE_NON_FUNGIBLE_RESOURCE - 7 | Enum() - 8 | Enum() - 9 | true -10 | Enum<0u8>(Enum<0u8>(Tuple(Array(), Array(), Array())), Enum<0u8>(66u8), Array()) - | ^^^^^^^^^^^^^ expected 1 number of types -11 | Tuple( -12 | Some( -13 | Tuple( -14 | Some(Enum()), -15 | Some(Enum()) - | \ No newline at end of file +error: expected 1 number of types, found 2 + | + 5 | + 6 | CREATE_NON_FUNGIBLE_RESOURCE + 7 | Enum() + 8 | Enum() + 9 | true +10 | Enum<0u8>(Enum<0u8>(Tuple(Array(), Array(), Array())), Enum<0u8>(66u8), Array()) + | ^^^^^^^^^^^^^ expected 1 number of types +11 | Tuple( +12 | Some( +13 | Tuple( +14 | Some(Enum()), +15 | Some(Enum()) + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_3.diag b/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_3.diag index 0e47f1e1c95..3b1d28d8f43 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_3.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_3.diag @@ -1,11 +1,11 @@ -error: expected 1 number of types, found 0 - | - 5 | - 6 | CALL_METHOD - 7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") - 8 | "some_method" - 9 | # Invalid array specification -10 | Array<> - | ^^ expected 1 number of types -11 | ; - | \ No newline at end of file +error: expected 1 number of types, found 0 + | + 5 | + 6 | CALL_METHOD + 7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") + 8 | "some_method" + 9 | # Invalid array specification +10 | Array<> + | ^^ expected 1 number of types +11 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_4.diag b/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_4.diag index 153642a2f12..3d86edef3e7 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_4.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_types_4.diag @@ -1,14 +1,14 @@ -error: expected 2 number of types, found 0 - | - 5 | - 6 | CALL_METHOD - 7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") - 8 | "some_method" - 9 | # Invalid array specification -10 | Map< - | ________^ -11 | | -12 | | > - | |_____^ expected 2 number of types -13 | ; - | \ No newline at end of file +error: expected 2 number of types, found 0 + | + 5 | + 6 | CALL_METHOD + 7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") + 8 | "some_method" + 9 | # Invalid array specification +10 | Map< + | ________^ +11 | | +12 | | > + | |_____^ expected 2 number of types +13 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_values_1.diag b/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_values_1.diag index b429df63b34..3bccbc706da 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_values_1.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_values_1.diag @@ -1,14 +1,14 @@ -error: expected 1 number of values, found 2 - | -1 | CALL_METHOD -2 | Address( -3 | "component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh", - | _______^ -4 | | "component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") - | |____________________________________________________________________________^ expected 1 number of values -5 | "lock_fee" -6 | ; -7 | SET_COMPONENT_ROYALTY -8 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -9 | "method_with_no_package_royalty" - | \ No newline at end of file +error: expected 1 number of values, found 2 + | +1 | CALL_METHOD +2 | Address( +3 | "component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh", + | _______^ +4 | | "component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") + | |____________________________________________________________________________^ expected 1 number of values +5 | "lock_fee" +6 | ; +7 | SET_COMPONENT_ROYALTY +8 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +9 | "method_with_no_package_royalty" + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_values_2.diag b/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_values_2.diag index e88191b84c5..696a44b6105 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_values_2.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_invalid_number_of_values_2.diag @@ -1,12 +1,12 @@ -error: expected 1 number of values, found 3 - | - 3 | "lock_fee" - 4 | ; - 5 | CALL_METHOD - 6 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") - 7 | "some_method" - 8 | Some("radix", "is", "fun") - | ^^^^^^^^^^^^^^^^^^^^ expected 1 number of values - 9 | Enum<0u8>() -10 | ; - | \ No newline at end of file +error: expected 1 number of values, found 3 + | + 3 | "lock_fee" + 4 | ; + 5 | CALL_METHOD + 6 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") + 7 | "some_method" + 8 | Some("radix", "is", "fun") + | ^^^^^^^^^^^^^^^^^^^^ expected 1 number of values + 9 | Enum<0u8>() +10 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_max_depth_exceeded_1.diag b/radix-transactions/tests/assets/manifest_parser_error_max_depth_exceeded_1.diag index 18dc640f84c..29caeaa74ec 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_max_depth_exceeded_1.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_max_depth_exceeded_1.diag @@ -1,15 +1,15 @@ -error: manifest actual depth 21 exceeded max 20 - | -20 | Tuple( -21 | Tuple( -22 | Tuple( -23 | Tuple( -24 | Tuple( -25 | Tuple( - | ^^^^^ max depth exceeded -26 | Tuple( -27 | Tuple( -28 | Tuple( -29 | Tuple( -30 | Tuple( - | \ No newline at end of file +error: manifest actual depth 21 exceeded max 20 + | +20 | Tuple( +21 | Tuple( +22 | Tuple( +23 | Tuple( +24 | Tuple( +25 | Tuple( + | ^^^^^ max depth exceeded +26 | Tuple( +27 | Tuple( +28 | Tuple( +29 | Tuple( +30 | Tuple( + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_max_depth_exceeded_2.diag b/radix-transactions/tests/assets/manifest_parser_error_max_depth_exceeded_2.diag index 81bdf782198..4403e7298d7 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_max_depth_exceeded_2.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_max_depth_exceeded_2.diag @@ -1,9 +1,9 @@ -error: manifest actual depth 21 exceeded max 20 - | -1 | CALL_FUNCTION -2 | Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") -3 | "blueprint" -4 | "func" -5 | Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(0u8))))))))))))))))))))))))))))); - | ^^^^^ max depth exceeded - | \ No newline at end of file +error: manifest actual depth 21 exceeded max 20 + | +1 | CALL_FUNCTION +2 | Address("package_sim1p4r4955skdjq9swg8s5jguvcjvyj7tsxct87a9z6sw76cdfd2jg3zk") +3 | "blueprint" +4 | "func" +5 | Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(Tuple(0u8))))))))))))))))))))))))))))); + | ^^^^^ max depth exceeded + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_unexpected_eof_1.diag b/radix-transactions/tests/assets/manifest_parser_error_unexpected_eof_1.diag index defa1575abc..31f6a888d39 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_unexpected_eof_1.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_unexpected_eof_1.diag @@ -1,10 +1,10 @@ -error: unexpected end of file - | -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") -7 | "some_method" -8 | Enum<0u8>( - | ^ unexpected end of file - | \ No newline at end of file +error: unexpected end of file + | +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") +7 | "some_method" +8 | Enum<0u8>( + | ^ unexpected end of file + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_unexpected_eof_2.diag b/radix-transactions/tests/assets/manifest_parser_error_unexpected_eof_2.diag index a8ef0b94dd2..77c34732f34 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_unexpected_eof_2.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_unexpected_eof_2.diag @@ -1,10 +1,10 @@ -error: unexpected end of file - | -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "some_method" -8 | Decimal("700" - | ^ unexpected end of file - | \ No newline at end of file +error: unexpected end of file + | +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "some_method" +8 | Decimal("700" + | ^ unexpected end of file + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_unexpected_eof_3.diag b/radix-transactions/tests/assets/manifest_parser_error_unexpected_eof_3.diag index 4308eb68baa..17dde15bd08 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_unexpected_eof_3.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_unexpected_eof_3.diag @@ -1,10 +1,10 @@ -error: unexpected end of file - | -4 | ; -5 | -6 | CALL_METHOD -7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -8 | "some_method" -9 | Address("基数引擎") - | ^ unexpected end of file - | \ No newline at end of file +error: unexpected end of file + | +4 | ; +5 | +6 | CALL_METHOD +7 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +8 | "some_method" +9 | Address("基数引擎") + | ^ unexpected end of file + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_1.diag b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_1.diag index 895ae876dbc..739a1827872 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_1.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_1.diag @@ -1,10 +1,10 @@ -error: expected an instruction, found ';' - | -1 | ; - | ^ expected an instruction -2 | CALL_METHOD -3 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") -4 | "lock_fee" -5 | ; -6 | SET_COMPONENT_ROYALTY - | \ No newline at end of file +error: expected an instruction, found ';' + | +1 | ; + | ^ expected an instruction +2 | CALL_METHOD +3 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") +4 | "lock_fee" +5 | ; +6 | SET_COMPONENT_ROYALTY + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_2.diag b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_2.diag index 4f17e6c39ee..ca6210f2570 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_2.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_2.diag @@ -1,15 +1,15 @@ -error: expected an instruction, found ';' - | -10 | SET_COMPONENT_ROYALTY -11 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -12 | "method_with_xrd_package_royalty" -13 | Enum<0u8>() -14 | ; -15 | ; - | ^ expected an instruction -16 | SET_COMPONENT_ROYALTY -17 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -18 | "method_with_usd_package_royalty" -19 | Enum<0u8>() -20 | ; - | \ No newline at end of file +error: expected an instruction, found ';' + | +10 | SET_COMPONENT_ROYALTY +11 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +12 | "method_with_xrd_package_royalty" +13 | Enum<0u8>() +14 | ; +15 | ; + | ^ expected an instruction +16 | SET_COMPONENT_ROYALTY +17 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +18 | "method_with_usd_package_royalty" +19 | Enum<0u8>() +20 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_3.diag b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_3.diag index c3db3e7698c..8e2eb8a71f6 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_3.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_3.diag @@ -1,11 +1,11 @@ -error: expected an instruction, found '1u32' - | - 4 | ; - 5 | SET_COMPONENT_ROYALTY - 6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") - 7 | "method_with_no_package_royalty" - 8 | Enum<0u8>(); - 9 | 1u32 - | ^^^^ expected an instruction -10 | ; - | \ No newline at end of file +error: expected an instruction, found '1u32' + | + 4 | ; + 5 | SET_COMPONENT_ROYALTY + 6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") + 7 | "method_with_no_package_royalty" + 8 | Enum<0u8>(); + 9 | 1u32 + | ^^^^ expected an instruction +10 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_4.diag b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_4.diag index 7bd32999df4..95e43a79026 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_4.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_4.diag @@ -1,10 +1,10 @@ -error: expected an instruction, found "CALL_METHOD" - | - 5 | SET_COMPONENT_ROYALTY - 6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") - 7 | "method_with_no_package_royalty" - 8 | Enum<0u8>() - 9 | ; -10 | "CALL_METHOD" - | ^^^^^^^^^^^^^ expected an instruction - | \ No newline at end of file +error: expected an instruction, found "CALL_METHOD" + | + 5 | SET_COMPONENT_ROYALTY + 6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") + 7 | "method_with_no_package_royalty" + 8 | Enum<0u8>() + 9 | ; +10 | "CALL_METHOD" + | ^^^^^^^^^^^^^ expected an instruction + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_5.diag b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_5.diag index 82df10271f5..aaa3c1f9a4b 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_5.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_5.diag @@ -1,11 +1,11 @@ -error: expected an instruction, found 'true' - | - 4 | ; - 5 | SET_COMPONENT_ROYALTY - 6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") - 7 | "method_with_no_package_royalty" - 8 | Enum<0u8>(); - 9 | true - | ^^^^ expected an instruction -10 | ; - | \ No newline at end of file +error: expected an instruction, found 'true' + | + 4 | ; + 5 | SET_COMPONENT_ROYALTY + 6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") + 7 | "method_with_no_package_royalty" + 8 | Enum<0u8>(); + 9 | true + | ^^^^ expected an instruction +10 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_6.diag b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_6.diag index 31350cf3297..4794d6d0099 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_6.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_6.diag @@ -1,11 +1,11 @@ -error: expected a u8 enum discriminator or valid discriminator alias, found '1u128' - | -3 | "lock_fee" -4 | ; -5 | SET_COMPONENT_ROYALTY -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "method_with_no_package_royalty" -8 | Enum<1u128>() - | ^^^^^ expected a u8 enum discriminator or valid discriminator alias -9 | ; - | \ No newline at end of file +error: expected a u8 enum discriminator or valid discriminator alias, found '1u128' + | +3 | "lock_fee" +4 | ; +5 | SET_COMPONENT_ROYALTY +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "method_with_no_package_royalty" +8 | Enum<1u128>() + | ^^^^^ expected a u8 enum discriminator or valid discriminator alias +9 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_7.diag b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_7.diag index ba46bbff952..f3bb7ec8440 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_7.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_7.diag @@ -1,11 +1,11 @@ -error: expected a manifest SBOR value kind, found '1u8' - | -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "some_method" -8 | Array<1u8>() - | ^^^ expected a manifest SBOR value kind -9 | ; - | \ No newline at end of file +error: expected a manifest SBOR value kind, found '1u8' + | +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "some_method" +8 | Array<1u8>() + | ^^^ expected a manifest SBOR value kind +9 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_8.diag b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_8.diag index 89c0eb2bf3a..6f2e8f2aab2 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_8.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_unexpected_token_8.diag @@ -1,11 +1,11 @@ -error: expected exactly '>', found ')' - | -3 | "lock_fee" -4 | ; -5 | CALL_METHOD -6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") -7 | "some_method" -8 | Enum<0u8) - | ^ expected exactly '>' -9 | ; - | \ No newline at end of file +error: expected exactly '>', found ')' + | +3 | "lock_fee" +4 | ; +5 | CALL_METHOD +6 | Address("component_sim1cpyavrltfeu9ppx24pcpvh93xf44sfjygtv6dgf6uq3cdwafl7f9rq") +7 | "some_method" +8 | Enum<0u8) + | ^ expected exactly '>' +9 | ; + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_unknown_enum_discriminator_1.diag b/radix-transactions/tests/assets/manifest_parser_error_unknown_enum_discriminator_1.diag index 258bc7cb315..5eb1d0735cd 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_unknown_enum_discriminator_1.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_unknown_enum_discriminator_1.diag @@ -1,15 +1,15 @@ -error: unknown enum discriminator found 'OwnerRol::Updatable' - | - 1 | CALL_METHOD - 2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") - 3 | "lock_fee" - 4 | ; - 5 | CREATE_ACCOUNT_ADVANCED - 6 | Enum( - | ^^^^^^^^^^^^^^^^^^^ unknown enum discriminator - 7 | Enum() - 8 | ) - 9 | ; -10 | TAKE_ALL_FROM_WORKTOP -11 | Address("${resource_address}") - | \ No newline at end of file +error: unknown enum discriminator found 'OwnerRol::Updatable' + | + 1 | CALL_METHOD + 2 | Address("component_sim1cptxxxxxxxxxfaucetxxxxxxxxx000527798379xxxxxxxxxhkrefh") + 3 | "lock_fee" + 4 | ; + 5 | CREATE_ACCOUNT_ADVANCED + 6 | Enum( + | ^^^^^^^^^^^^^^^^^^^ unknown enum discriminator + 7 | Enum() + 8 | ) + 9 | ; +10 | TAKE_ALL_FROM_WORKTOP +11 | Address("${resource_address}") + | \ No newline at end of file diff --git a/radix-transactions/tests/assets/manifest_parser_error_unknown_enum_discriminator_2.diag b/radix-transactions/tests/assets/manifest_parser_error_unknown_enum_discriminator_2.diag index 0edbaa17b1c..e2cbf39e2d8 100644 --- a/radix-transactions/tests/assets/manifest_parser_error_unknown_enum_discriminator_2.diag +++ b/radix-transactions/tests/assets/manifest_parser_error_unknown_enum_discriminator_2.diag @@ -1,15 +1,15 @@ -error: unknown enum discriminator found 'Metadata::StingArray' - | - 3 | "lock_fee" - 4 | ; - 5 | SET_METADATA - 6 | Address("resource_sim1n2pqvufl0fmexzpkl6rzk50n2seaz49jgfaqensv7ujxdlf6szr08f") - 7 | "field_name" - 8 | Enum( - | ^^^^^^^^^^^^^^^^^^^^ unknown enum discriminator - 9 | Array( -10 | "some_string", -11 | "another_string", -12 | "yet_another_string" -13 | ) - | \ No newline at end of file +error: unknown enum discriminator found 'Metadata::StingArray' + | + 3 | "lock_fee" + 4 | ; + 5 | SET_METADATA + 6 | Address("resource_sim1n2pqvufl0fmexzpkl6rzk50n2seaz49jgfaqensv7ujxdlf6szr08f") + 7 | "field_name" + 8 | Enum( + | ^^^^^^^^^^^^^^^^^^^^ unknown enum discriminator + 9 | Array( +10 | "some_string", +11 | "another_string", +12 | "yet_another_string" +13 | ) + | \ No newline at end of file diff --git a/radix-transactions/tests/test_manifest_compiler_error_diagnostics.rs b/radix-transactions/tests/test_manifest_compiler_error_diagnostics.rs index a9f0046baa0..6e1e159a961 100644 --- a/radix-transactions/tests/test_manifest_compiler_error_diagnostics.rs +++ b/radix-transactions/tests/test_manifest_compiler_error_diagnostics.rs @@ -1,15 +1,19 @@ use radix_common::network::NetworkDefinition; -use radix_transactions::manifest::blob_provider::*; -use radix_transactions::manifest::compiler::*; +use radix_transactions::manifest::*; macro_rules! check_manifest { - ($manifest:expr, $blob_provider:expr, $style:expr) => {{ + ($manifest_kind:expr, $manifest:expr, $blob_provider:expr $(,)?) => {{ let manifest = include_str!(concat!("assets/", $manifest, ".rtm")); let diagnostic = include_str!(concat!("assets/", $manifest, ".diag")); - let err = compile(manifest, &NetworkDefinition::simulator(), $blob_provider).unwrap_err(); - - let x = compile_error_diagnostics(manifest, err, $style); + let x = compile_any_manifest_with_pretty_error( + manifest, + $manifest_kind, + &NetworkDefinition::simulator(), + $blob_provider, + CompileErrorDiagnosticsStyle::PlainText, + ) + .unwrap_err(); if x != diagnostic { let path = format!("tests/assets/{}.diag.res", $manifest); @@ -24,13 +28,20 @@ macro_rules! check_manifest { panic!("diagnostic reports differ"); } }}; - ($manifest:expr) => {{ - // Some instructions require valid blob in order to let - // manifest compile, eg. PUBLISH_PACKAGE_ADVANCED + ($manifest_kind:expr, $manifest:expr $(,)?) => {{ check_manifest!( + $manifest_kind, $manifest, - MockBlobProvider::default(), - CompileErrorDiagnosticsStyle::TextTerminalColors + // The MockBlobProvider pretends any blob is valid + MockBlobProvider::default() + ) + }}; + ($manifest:expr $(,)?) => {{ + check_manifest!( + ManifestKind::V1, + $manifest, + // The MockBlobProvider pretends any blob is valid + MockBlobProvider::default() ) }}; } @@ -212,9 +223,9 @@ fn test_manifest_generator_error_invalid_blob_hash() { fn test_manifest_generator_error_blob_not_found() { // BlobNotFound check_manifest!( + ManifestKind::V1, "manifest_generator_error_blob_not_found_1", - BlobProvider::default(), - CompileErrorDiagnosticsStyle::TextTerminalColors + BlobProvider::default() ); } @@ -302,11 +313,118 @@ fn test_manifest_generator_error_proof_not_found() { check_manifest!("manifest_generator_error_proof_not_found_2"); } +#[test] +fn test_manifest_generator_error_invalid_sub_transaction_id() { + // InvalidSubTransactionId(String) + check_manifest!( + ManifestKind::V2, + "manifest_generator_error_invalid_sub_transaction_id_1" + ); +} + +#[test] +fn test_manifest_generator_error_instruction_not_supported_in_manifest_version() { + // InstructionNotSupportedInManifestVersion + check_manifest!( + ManifestKind::V1, + "manifest_generator_error_instruction_not_supported_in_manifest_version_1" + ); +} + +#[test] +fn test_manifest_generator_error_duplicate_subintent_hash() { + // ManifestBuildError(ManifestBuildError::DuplicateChildSubintentHash) + check_manifest!( + ManifestKind::V2, + "manifest_generator_error_duplicate_subintent_hash_1" + ); +} + +#[test] +fn test_manifest_generator_error_child_subintents_unsupported_by_manifest_type() { + // ManifestBuildError(ManifestBuildError::ChildSubintentsUnsupportedByManifestType) + check_manifest!( + ManifestKind::V1, + "manifest_generator_error_child_subintents_unsupported_by_manifest_type_1" + ); +} + +#[test] +fn test_manifest_generator_error_preallocated_addresses_unsupported_by_manifest_type() { + // ManifestBuildError(ManifestBuildError::PreallocatedAddressesUnsupportedByManifestType) + check_manifest!( + ManifestKind::V2, + "manifest_generator_error_preallocated_addresses_unsupported_by_manifest_type_1" + ); +} + +#[test] +fn test_manifest_generator_error_header_instruction_must_come_first() { + // HeaderInstructionMustComeFirst + check_manifest!( + ManifestKind::SubintentV2, + "manifest_generator_error_header_instruction_must_come_first_1" + ); +} + +#[test] +fn test_manifest_generator_error_intent_cannot_be_used_in_value() { + // IntentCannotBeUsedInValue + check_manifest!( + ManifestKind::SubintentV2, + "manifest_generator_error_intent_cannot_be_used_in_value_1" + ); +} + +#[test] +fn test_manifest_generator_error_intent_cannot_be_used_as_value_kind() { + // IntentCannotBeUsedAsValueKind + check_manifest!( + ManifestKind::SubintentV2, + "manifest_generator_error_intent_cannot_be_used_as_value_kind_1" + ); +} + +#[test] +fn test_manifest_generator_error_named_intent_cannot_be_used_in_value() { + // NamedIntentCannotBeUsedInValue + check_manifest!( + ManifestKind::SubintentV2, + "manifest_generator_error_named_intent_cannot_be_used_in_value_1" + ); +} + +#[test] +fn test_manifest_generator_error_named_intent_cannot_be_used_as_value_kind() { + // NamedIntentCannotBeUsedAsValueKind + check_manifest!( + ManifestKind::SubintentV2, + "manifest_generator_error_named_intent_cannot_be_used_as_value_kind_1" + ); +} + +#[test] +fn test_manifest_generator_error_argument_could_not_be_read_as_expected_type() { + // ArgumentCouldNotBeReadAsExpectedType { type_name: String, error_message: String, }, + check_manifest!( + ManifestKind::V2, + "manifest_generator_error_argument_could_not_be_read_as_expected_type_1" + ); + check_manifest!( + ManifestKind::V2, + "manifest_generator_error_argument_could_not_be_read_as_expected_type_2" + ); + check_manifest!( + ManifestKind::V2, + "manifest_generator_error_argument_could_not_be_read_as_expected_type_3" + ); +} + #[test] fn test_manifest_compiler_error_plain_text() { check_manifest!( + ManifestKind::V1, "manifest_compiler_error_plain_text_1", BlobProvider::default(), - CompileErrorDiagnosticsStyle::PlainText ); } diff --git a/sbor/src/lib.rs b/sbor/src/lib.rs index f2bd9fab953..c23f2ad2683 100644 --- a/sbor/src/lib.rs +++ b/sbor/src/lib.rs @@ -122,5 +122,10 @@ pub(crate) mod internal_prelude { pub use crate::prelude::*; // These are mostly used for more advanced use cases, // so aren't included in the general prelude + pub use crate::basic::*; + pub use crate::decoder::*; + pub use crate::encoder::*; + pub use crate::payload_validation::*; + pub use crate::schema::*; pub use crate::vec_traits::*; } diff --git a/sbor/src/payload_validation/payload_validator.rs b/sbor/src/payload_validation/payload_validator.rs index 78a46bafc7b..c1e5cd41693 100644 --- a/sbor/src/payload_validation/payload_validator.rs +++ b/sbor/src/payload_validation/payload_validator.rs @@ -780,7 +780,7 @@ mod tests { ]; check_location_path::>( payload, - "", // container state not established due to failing to read size + "[Root]", // container state not established due to failing to read size "DecodeError(InvalidSize)", ); } diff --git a/sbor/src/traversal/path_formatting.rs b/sbor/src/traversal/path_formatting.rs index 644560a5683..63ecd5ae962 100644 --- a/sbor/src/traversal/path_formatting.rs +++ b/sbor/src/traversal/path_formatting.rs @@ -233,7 +233,11 @@ pub trait PathAnnotate { if let Some(leaf) = self.annotated_leaf() { leaf.write(f, is_start_of_path)?; - }; + } else { + if is_start_of_path { + write!(f, "[Root]")?; + } + } Ok(()) } diff --git a/sbor/src/value.rs b/sbor/src/value.rs index fca666c449c..0237798a93f 100644 --- a/sbor/src/value.rs +++ b/sbor/src/value.rs @@ -1,13 +1,4 @@ -use crate::decode::*; -use crate::decoder::*; -use crate::encode::*; -use crate::encoder::*; -use crate::path::SborPathBuf; -use crate::rust::fmt::Debug; -use crate::rust::string::String; -use crate::rust::vec::Vec; -use crate::value_kind::*; -use crate::*; +use crate::internal_prelude::*; #[cfg(feature = "fuzzing")] use arbitrary::Arbitrary; @@ -77,6 +68,25 @@ pub enum Value> { }, } +impl> Value { + pub fn unit() -> Self { + Value::Tuple { fields: vec![] } + } + + pub fn tuple(fields: impl IntoIterator) -> Self { + Value::Tuple { + fields: fields.into_iter().collect(), + } + } + + pub fn enum_variant(discriminator: u8, fields: impl IntoIterator) -> Self { + Value::Enum { + discriminator, + fields: fields.into_iter().collect(), + } + } +} + /// Represents a custom SBOR value. pub trait CustomValue { fn get_custom_value_kind(&self) -> X; @@ -520,7 +530,6 @@ pub trait ValueVisitor> { #[cfg(test)] mod tests { - use super::*; use crate::internal_prelude::*; #[derive(Categorize, Encode)] diff --git a/sbor/src/vec_traits.rs b/sbor/src/vec_traits.rs index 47559947b58..8b1ca011acf 100644 --- a/sbor/src/vec_traits.rs +++ b/sbor/src/vec_traits.rs @@ -1,7 +1,4 @@ -use crate::{ - internal_prelude::*, validate_payload_against_schema, CustomExtension, CustomSchema, - Decoder as _, Describe, Encoder as _, ValidatableCustomExtension, VecDecoder, VecEncoder, -}; +use crate::internal_prelude::*; pub trait VecEncode: for<'a> Encode> {} impl Encode> + ?Sized> VecEncode for T {}