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)]
155pub enum TipSpecifier {
156 None,
157 Percentage(u16),
158 BasisPoints(u32),
159}
160
161impl TipSpecifier {
162 pub fn basis_points(&self) -> u32 {
163 match self {
164 TipSpecifier::None => 0,
165 TipSpecifier::Percentage(percentage) => (*percentage as u32) * 100,
166 TipSpecifier::BasisPoints(basis_points) => *basis_points,
167 }
168 }
169
170 pub fn proportion(&self) -> Decimal {
171 match self {
175 TipSpecifier::None => Decimal::ZERO,
176 TipSpecifier::Percentage(percentage) => {
177 Decimal::from_attos(I192::from(*percentage) * dec!(0.01).attos())
178 }
179 TipSpecifier::BasisPoints(basis_points) => {
180 Decimal::from_attos(I192::from(*basis_points) * dec!(0.0001).attos())
181 }
182 }
183 }
184
185 pub fn fee_multiplier(&self) -> Decimal {
186 Decimal::ONE + self.proportion()
187 }
188
189 pub fn truncate_to_percentage_u32(&self) -> u32 {
190 match self {
191 TipSpecifier::None => 0,
192 TipSpecifier::Percentage(percentage) => *percentage as u32,
193 TipSpecifier::BasisPoints(basis_points) => {
194 let truncated_percentage = *basis_points / 100;
195 truncated_percentage
196 }
197 }
198 }
199}
200
201impl Default for TipSpecifier {
202 fn default() -> Self {
203 TipSpecifier::None
204 }
205}
206
207#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor, ManifestSbor, Default)]
208pub struct TransactionCostingParametersReceiptV1 {
209 pub tip_percentage: u16,
210 pub free_credit_in_xrd: Decimal,
211}
212
213#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor, ManifestSbor, Default)]
214pub struct TransactionCostingParametersReceiptV2 {
215 pub tip_proportion: Decimal,
216 pub free_credit_in_xrd: Decimal,
217}
218
219impl From<TransactionCostingParametersReceiptV1> for TransactionCostingParametersReceiptV2 {
220 fn from(value: TransactionCostingParametersReceiptV1) -> Self {
221 Self {
222 tip_proportion: TipSpecifier::Percentage(value.tip_percentage).proportion(),
223 free_credit_in_xrd: value.free_credit_in_xrd,
224 }
225 }
226}
227
228#[cfg(test)]
229mod tests {
230 use crate::internal_prelude::*;
231
232 #[test]
233 fn test_uniqueness_of_simulated_hashes_inside_single_transaction() {
234 let mut hashes: IndexSet<IntentHash> = Default::default();
235
236 let num_subintents = 10;
237
238 hashes.insert(
239 SimulatedTransactionIntentNullification
240 .transaction_intent_hash()
241 .into(),
242 );
243 for i in 0..num_subintents {
244 let nullification = SimulatedSubintentNullification {
245 index: SubintentIndex(i),
246 };
247 hashes.insert(nullification.subintent_hash().into());
248 }
249
250 assert_eq!(hashes.len(), num_subintents + 1);
251 }
252
253 #[test]
254 fn tip_specifier_conversion_tests() {
255 {
257 let tip = TipSpecifier::BasisPoints(1500);
258 assert_eq!(tip.basis_points(), 1500);
259 assert_eq!(tip.proportion(), dec!(0.15));
260 assert_eq!(tip.fee_multiplier(), dec!(1.15));
261 assert_eq!(tip.truncate_to_percentage_u32(), 15);
262 }
263
264 {
265 let tip = TipSpecifier::Percentage(50);
266 assert_eq!(tip.basis_points(), 5000);
267 assert_eq!(tip.proportion(), dec!(0.5));
268 assert_eq!(tip.fee_multiplier(), dec!(1.5));
269 assert_eq!(tip.truncate_to_percentage_u32(), 50);
270 }
271
272 {
273 let tip = TipSpecifier::None;
274 assert_eq!(tip.basis_points(), 0);
275 assert_eq!(tip.proportion(), dec!(0));
276 assert_eq!(tip.fee_multiplier(), dec!(1));
277 assert_eq!(tip.truncate_to_percentage_u32(), 0);
278 }
279
280 {
282 let tip = TipSpecifier::BasisPoints(7);
283 assert_eq!(tip.basis_points(), 7);
284 assert_eq!(tip.proportion(), dec!(0.0007));
285 assert_eq!(tip.fee_multiplier(), dec!(1.0007));
286 assert_eq!(tip.truncate_to_percentage_u32(), 0); }
288
289 {
290 let tip = TipSpecifier::Percentage(u16::MAX);
291 assert_eq!(tip.basis_points(), 6553500);
292 assert_eq!(tip.proportion(), dec!(655.35));
293 assert_eq!(tip.fee_multiplier(), dec!(656.35));
294 assert_eq!(tip.truncate_to_percentage_u32(), 65535);
295 }
296
297 {
298 let tip = TipSpecifier::BasisPoints(u32::MAX);
299 assert_eq!(tip.basis_points(), 4294967295);
300 assert_eq!(tip.proportion(), dec!(429496.7295));
301 assert_eq!(tip.fee_multiplier(), dec!(429497.7295));
302 assert_eq!(tip.truncate_to_percentage_u32(), 42949672); }
304 }
305}