radix_transactions/model/v2/
preview_v2.rs1use crate::internal_prelude::*;
2
3#[derive(Debug, Clone, Eq, PartialEq, ManifestSbor, ScryptoDescribe, ScryptoSborAssertion)]
21#[sbor_assert(
22 fixed("FILE:preview_transaction_v2_schema.bin"),
23 settings(allow_name_changes)
24)]
25pub struct PreviewTransactionV2 {
26 pub transaction_intent: TransactionIntentV2,
27 pub root_signer_public_keys: IndexSet<PublicKey>,
28 pub non_root_subintent_signer_public_keys: Vec<Vec<PublicKey>>,
29}
30
31impl PreviewTransactionV2 {
32 pub fn prepare_and_validate(
33 &self,
34 validator: &TransactionValidator,
35 ) -> Result<ValidatedPreviewTransactionV2, TransactionValidationError> {
36 self.prepare(validator.preparation_settings())?
37 .validate(validator)
38 }
39}
40
41define_transaction_payload!(
42 PreviewTransactionV2,
43 RawPreviewTransaction,
44 PreparedPreviewTransactionV2 {
45 transaction_intent: PreparedTransactionIntentV2,
46 root_subintent_signatures: SummarizedRawValueBody<Vec<PublicKey>>,
47 non_root_subintent_signatures: SummarizedRawValueBody<Vec<Vec<PublicKey>>>,
48 },
49 TransactionDiscriminator::V2PreviewTransaction,
50);
51
52impl PreparedPreviewTransactionV2 {
53 pub fn validate(
54 self,
55 validator: &TransactionValidator,
56 ) -> Result<ValidatedPreviewTransactionV2, TransactionValidationError> {
57 validator.validate_preview_transaction_v2(self)
58 }
59}
60
61#[derive(Debug, Eq, PartialEq, Clone)]
62pub struct ValidatedPreviewTransactionV2 {
63 pub prepared: PreparedPreviewTransactionV2,
64 pub overall_validity_range: OverallValidityRangeV2,
65 pub total_expected_signature_validations: usize,
68 pub transaction_intent_info: ValidatedIntentInformationV2,
69 pub non_root_subintents_info: Vec<ValidatedIntentInformationV2>,
70}
71
72impl ValidatedPreviewTransactionV2 {
73 pub fn create_executable(self, flags: PreviewFlags) -> ExecutableTransaction {
74 let transaction_intent = self.prepared.transaction_intent;
75 let transaction_intent_hash = transaction_intent.transaction_intent_hash();
76 let transaction_header = transaction_intent.transaction_header.inner;
77 let subintents = transaction_intent.non_root_subintents.subintents;
78
79 let payload_size = transaction_intent.summary.effective_length;
83
84 let mut simulate_every_proof_under_resources = BTreeSet::new();
85 if flags.assume_all_signature_proofs {
86 simulate_every_proof_under_resources.insert(SECP256K1_SIGNATURE_RESOURCE);
87 simulate_every_proof_under_resources.insert(ED25519_SIGNATURE_RESOURCE);
88 }
89
90 let costing_parameters = TransactionCostingParameters {
91 tip: TipSpecifier::BasisPoints(transaction_header.tip_basis_points),
92 free_credit_in_xrd: if flags.use_free_credit {
93 Decimal::try_from(PREVIEW_CREDIT_IN_XRD).unwrap()
94 } else {
95 Decimal::ZERO
96 },
97 };
98
99 let mut intent_hash_nullifications =
100 Vec::with_capacity(self.non_root_subintents_info.len() + 1);
101 {
102 let expiry_epoch = transaction_intent
103 .root_intent_core
104 .header
105 .inner
106 .end_epoch_exclusive;
107 intent_hash_nullifications
108 .push(IntentHash::from(transaction_intent_hash).to_nullification(expiry_epoch));
109 }
110 for subintent in subintents.iter() {
111 let expiry_epoch = subintent.intent_core.header.inner.end_epoch_exclusive;
112 intent_hash_nullifications
113 .push(IntentHash::from(subintent.subintent_hash()).to_nullification(expiry_epoch))
114 }
115
116 let executable_transaction_intent = create_executable_intent(
117 transaction_intent.root_intent_core,
118 self.transaction_intent_info,
119 &flags,
120 );
121
122 let executable_subintents = subintents
123 .into_iter()
124 .zip(self.non_root_subintents_info.into_iter())
125 .map(|(subintent, info)| create_executable_intent(subintent.intent_core, info, &flags))
126 .collect();
127
128 ExecutableTransaction::new_v2(
129 executable_transaction_intent,
130 executable_subintents,
131 ExecutionContext {
132 unique_hash: transaction_intent_hash.0,
133 intent_hash_nullifications,
134 payload_size,
135 num_of_signature_validations: self.total_expected_signature_validations,
136 costing_parameters,
137 pre_allocated_addresses: vec![],
138 disable_limits_and_costing_modules: false,
139 epoch_range: Some(self.overall_validity_range.epoch_range.clone()),
140 proposer_timestamp_range: Some(
141 self.overall_validity_range.proposer_timestamp_range.clone(),
142 ),
143 },
144 )
145 }
146}
147
148fn create_executable_intent(
149 core: PreparedIntentCoreV2,
150 validated_info: ValidatedIntentInformationV2,
151 flags: &PreviewFlags,
152) -> ExecutableIntent {
153 let signer_keys = validated_info.signer_keys;
154
155 let mut simulate_every_proof_under_resources = BTreeSet::new();
156 if flags.assume_all_signature_proofs {
157 simulate_every_proof_under_resources.insert(SECP256K1_SIGNATURE_RESOURCE);
158 simulate_every_proof_under_resources.insert(ED25519_SIGNATURE_RESOURCE);
159 }
160
161 let auth_zone_init = AuthZoneInit::new(
162 AuthAddresses::signer_set(&signer_keys),
163 simulate_every_proof_under_resources,
164 );
165
166 ExecutableIntent {
167 encoded_instructions: validated_info.encoded_instructions,
168 auth_zone_init,
169 references: core.instructions.references,
170 blobs: core.blobs.blobs_by_hash,
171 children_subintent_indices: validated_info.children_subintent_indices,
172 }
173}