radix_transactions/model/execution/
executable_common.rs1use crate::internal_prelude::*;
2use decompiler::*;
3
4#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor, Default)]
5pub struct AuthZoneInit {
6 pub initial_non_fungible_id_proofs: BTreeSet<NonFungibleGlobalId>,
7 pub simulate_every_proof_under_resources: BTreeSet<ResourceAddress>,
9}
10
11impl AuthZoneInit {
12 pub fn proofs(proofs: BTreeSet<NonFungibleGlobalId>) -> Self {
13 Self::new(proofs, btreeset!())
14 }
15
16 pub fn new(
17 proofs: BTreeSet<NonFungibleGlobalId>,
18 resources: BTreeSet<ResourceAddress>,
19 ) -> Self {
20 Self {
21 initial_non_fungible_id_proofs: proofs,
22 simulate_every_proof_under_resources: resources,
23 }
24 }
25}
26
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct EpochRange {
29 pub start_epoch_inclusive: Epoch,
30 pub end_epoch_exclusive: Epoch,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
34pub struct ProposerTimestampRange {
35 pub start_timestamp_inclusive: Option<Instant>,
36 pub end_timestamp_exclusive: Option<Instant>,
37}
38
39#[derive(Debug, Clone, Eq, PartialEq, ManifestSbor, ScryptoSbor)]
40pub struct PreAllocatedAddress {
41 pub blueprint_id: BlueprintId,
42 pub address: GlobalAddress,
43}
44
45impl PreAllocatedAddress {
46 pub fn decompile_as_pseudo_instruction(
47 &self,
48 context: &mut DecompilationContext,
49 ) -> Result<DecompiledInstruction, DecompileError> {
50 let instruction = DecompiledInstruction::new("USE_PREALLOCATED_ADDRESS")
52 .add_argument(self.blueprint_id.package_address)
53 .add_argument(&self.blueprint_id.blueprint_name)
54 .add_argument(context.new_address_reservation())
55 .add_argument(self.address);
56 Ok(instruction)
57 }
58}
59
60impl From<(BlueprintId, GlobalAddress)> for PreAllocatedAddress {
61 fn from((blueprint_id, address): (BlueprintId, GlobalAddress)) -> Self {
62 PreAllocatedAddress {
63 blueprint_id,
64 address,
65 }
66 }
67}
68
69#[derive(Debug, Clone, PartialEq, Eq)]
70pub enum IntentHashNullification {
71 TransactionIntent {
74 intent_hash: TransactionIntentHash,
75 expiry_epoch: Epoch,
76 },
77 SimulatedTransactionIntent {
80 simulated: SimulatedTransactionIntentNullification,
81 },
82 Subintent {
84 intent_hash: SubintentHash,
85 expiry_epoch: Epoch,
86 },
87 SimulatedSubintent {
90 simulated: SimulatedSubintentNullification,
91 },
92}
93
94impl IntentHashNullification {
95 pub fn intent_hash(&self) -> IntentHash {
96 match self {
97 IntentHashNullification::TransactionIntent { intent_hash, .. } => {
98 IntentHash::Transaction(*intent_hash)
99 }
100 IntentHashNullification::SimulatedTransactionIntent { simulated } => {
101 IntentHash::Transaction(simulated.transaction_intent_hash())
102 }
103 IntentHashNullification::Subintent { intent_hash, .. } => {
104 IntentHash::Subintent(*intent_hash)
105 }
106 IntentHashNullification::SimulatedSubintent { simulated } => {
107 IntentHash::Subintent(simulated.subintent_hash())
108 }
109 }
110 }
111}
112
113#[derive(Debug, Clone, PartialEq, Eq)]
114pub struct SimulatedTransactionIntentNullification;
115
116impl SimulatedTransactionIntentNullification {
117 pub fn transaction_intent_hash(&self) -> TransactionIntentHash {
118 TransactionIntentHash::from_hash(Hash([0; Hash::LENGTH]))
119 }
120
121 pub fn expiry_epoch(&self, current_epoch: Epoch) -> Epoch {
122 current_epoch.next().unwrap_or(Epoch::of(u64::MAX))
123 }
124}
125
126#[derive(Debug, Clone, PartialEq, Eq)]
127pub struct SimulatedSubintentNullification {
128 index: SubintentIndex,
129}
130
131impl SimulatedSubintentNullification {
132 pub fn subintent_hash(&self) -> SubintentHash {
133 let mut simulated_hash = [0u8; Hash::LENGTH];
134 simulated_hash[0] = 1; let index_bytes = self.index.0.to_be_bytes();
136 let target = &mut simulated_hash[1..(index_bytes.len() + 1)];
137 target.copy_from_slice(&index_bytes);
138 SubintentHash::from_hash(Hash(simulated_hash))
139 }
140
141 pub fn expiry_epoch(&self, current_epoch: Epoch) -> Epoch {
142 current_epoch.next().unwrap_or(Epoch::of(u64::MAX))
143 }
144}
145
146#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor, ManifestSbor, Default)]
147pub struct TransactionCostingParameters {
148 pub tip: TipSpecifier,
149
150 pub free_credit_in_xrd: Decimal,
152}
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq, ScryptoSbor, ManifestSbor, Default)]
155pub enum TipSpecifier {
156 #[default]
157 None,
158 Percentage(u16),
159 BasisPoints(u32),
160}
161
162impl TipSpecifier {
163 pub fn basis_points(&self) -> u32 {
164 match self {
165 TipSpecifier::None => 0,
166 TipSpecifier::Percentage(percentage) => (*percentage as u32) * 100,
167 TipSpecifier::BasisPoints(basis_points) => *basis_points,
168 }
169 }
170
171 pub fn proportion(&self) -> Decimal {
172 match self {
176 TipSpecifier::None => Decimal::ZERO,
177 TipSpecifier::Percentage(percentage) => {
178 Decimal::from_attos(I192::from(*percentage) * dec!(0.01).attos())
179 }
180 TipSpecifier::BasisPoints(basis_points) => {
181 Decimal::from_attos(I192::from(*basis_points) * dec!(0.0001).attos())
182 }
183 }
184 }
185
186 pub fn fee_multiplier(&self) -> Decimal {
187 Decimal::ONE + self.proportion()
188 }
189
190 pub fn truncate_to_percentage_u32(&self) -> u32 {
191 match self {
192 TipSpecifier::None => 0,
193 TipSpecifier::Percentage(percentage) => *percentage as u32,
194 TipSpecifier::BasisPoints(basis_points) => *basis_points / 100,
195 }
196 }
197}
198
199#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor, ManifestSbor, Default)]
200pub struct TransactionCostingParametersReceiptV1 {
201 pub tip_percentage: u16,
202 pub free_credit_in_xrd: Decimal,
203}
204
205#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor, ManifestSbor, Default)]
206pub struct TransactionCostingParametersReceiptV2 {
207 pub tip_proportion: Decimal,
208 pub free_credit_in_xrd: Decimal,
209}
210
211impl From<TransactionCostingParametersReceiptV1> for TransactionCostingParametersReceiptV2 {
212 fn from(value: TransactionCostingParametersReceiptV1) -> Self {
213 Self {
214 tip_proportion: TipSpecifier::Percentage(value.tip_percentage).proportion(),
215 free_credit_in_xrd: value.free_credit_in_xrd,
216 }
217 }
218}
219
220#[cfg(test)]
221mod tests {
222 use crate::internal_prelude::*;
223
224 #[test]
225 fn test_uniqueness_of_simulated_hashes_inside_single_transaction() {
226 let mut hashes: IndexSet<IntentHash> = Default::default();
227
228 let num_subintents = 10;
229
230 hashes.insert(
231 SimulatedTransactionIntentNullification
232 .transaction_intent_hash()
233 .into(),
234 );
235 for i in 0..num_subintents {
236 let nullification = SimulatedSubintentNullification {
237 index: SubintentIndex(i),
238 };
239 hashes.insert(nullification.subintent_hash().into());
240 }
241
242 assert_eq!(hashes.len(), num_subintents + 1);
243 }
244
245 #[test]
246 fn tip_specifier_conversion_tests() {
247 {
249 let tip = TipSpecifier::BasisPoints(1500);
250 assert_eq!(tip.basis_points(), 1500);
251 assert_eq!(tip.proportion(), dec!(0.15));
252 assert_eq!(tip.fee_multiplier(), dec!(1.15));
253 assert_eq!(tip.truncate_to_percentage_u32(), 15);
254 }
255
256 {
257 let tip = TipSpecifier::Percentage(50);
258 assert_eq!(tip.basis_points(), 5000);
259 assert_eq!(tip.proportion(), dec!(0.5));
260 assert_eq!(tip.fee_multiplier(), dec!(1.5));
261 assert_eq!(tip.truncate_to_percentage_u32(), 50);
262 }
263
264 {
265 let tip = TipSpecifier::None;
266 assert_eq!(tip.basis_points(), 0);
267 assert_eq!(tip.proportion(), dec!(0));
268 assert_eq!(tip.fee_multiplier(), dec!(1));
269 assert_eq!(tip.truncate_to_percentage_u32(), 0);
270 }
271
272 {
274 let tip = TipSpecifier::BasisPoints(7);
275 assert_eq!(tip.basis_points(), 7);
276 assert_eq!(tip.proportion(), dec!(0.0007));
277 assert_eq!(tip.fee_multiplier(), dec!(1.0007));
278 assert_eq!(tip.truncate_to_percentage_u32(), 0); }
280
281 {
282 let tip = TipSpecifier::Percentage(u16::MAX);
283 assert_eq!(tip.basis_points(), 6553500);
284 assert_eq!(tip.proportion(), dec!(655.35));
285 assert_eq!(tip.fee_multiplier(), dec!(656.35));
286 assert_eq!(tip.truncate_to_percentage_u32(), 65535);
287 }
288
289 {
290 let tip = TipSpecifier::BasisPoints(u32::MAX);
291 assert_eq!(tip.basis_points(), 4294967295);
292 assert_eq!(tip.proportion(), dec!(429496.7295));
293 assert_eq!(tip.fee_multiplier(), dec!(429497.7295));
294 assert_eq!(tip.truncate_to_percentage_u32(), 42949672); }
296 }
297}