1use crate::{Process, Stack, StackProgramTypes};
17
18use crate::stack::StackRef;
19use console::{
20 prelude::*,
21 program::{FinalizeType, Identifier, LiteralType, PlaintextType},
22};
23use ledger_block::{Deployment, Execution, Transaction};
24use synthesizer_program::{CastType, Command, Finalize, Instruction, Operand, StackProgram};
25
26pub fn deployment_cost<N: Network>(deployment: &Deployment<N>) -> Result<(u64, (u64, u64, u64))> {
28 let size_in_bytes = deployment.size_in_bytes()?;
30 let program_id = deployment.program_id();
32 let num_characters = u32::try_from(program_id.name().to_string().len())?;
34 let num_combined_variables = deployment.num_combined_variables()?;
36 let num_combined_constraints = deployment.num_combined_constraints()?;
38
39 let storage_cost = size_in_bytes
41 .checked_mul(N::DEPLOYMENT_FEE_MULTIPLIER)
42 .ok_or(anyhow!("The storage cost computation overflowed for a deployment"))?;
43
44 let synthesis_cost = num_combined_variables.saturating_add(num_combined_constraints) * N::SYNTHESIS_FEE_MULTIPLIER;
46
47 let namespace_cost = 10u64
49 .checked_pow(10u32.saturating_sub(num_characters))
50 .ok_or(anyhow!("The namespace cost computation overflowed for a deployment"))?
51 .saturating_mul(1_000_000); let total_cost = storage_cost
55 .checked_add(synthesis_cost)
56 .and_then(|x| x.checked_add(namespace_cost))
57 .ok_or(anyhow!("The total cost computation overflowed for a deployment"))?;
58
59 Ok((total_cost, (storage_cost, synthesis_cost, namespace_cost)))
60}
61
62pub fn execution_cost_v2<N: Network>(process: &Process<N>, execution: &Execution<N>) -> Result<(u64, (u64, u64))> {
64 let storage_cost = execution_storage_cost::<N>(execution.size_in_bytes()?);
66
67 let transition = execution.peek()?;
69
70 let stack = process.get_stack(transition.program_id())?;
72 let finalize_cost = cost_in_microcredits_v2(&stack, transition.function_name())?;
73
74 let total_cost = storage_cost
76 .checked_add(finalize_cost)
77 .ok_or(anyhow!("The total cost computation overflowed for an execution"))?;
78
79 Ok((total_cost, (storage_cost, finalize_cost)))
80}
81
82pub fn execution_cost_v1<N: Network>(process: &Process<N>, execution: &Execution<N>) -> Result<(u64, (u64, u64))> {
84 let storage_cost = execution_storage_cost::<N>(execution.size_in_bytes()?);
86
87 let transition = execution.peek()?;
89
90 let stack = process.get_stack(transition.program_id())?;
92 let finalize_cost = cost_in_microcredits_v1(&stack, transition.function_name())?;
93
94 let total_cost = storage_cost
96 .checked_add(finalize_cost)
97 .ok_or(anyhow!("The total cost computation overflowed for an execution"))?;
98
99 Ok((total_cost, (storage_cost, finalize_cost)))
100}
101
102fn execution_storage_cost<N: Network>(size_in_bytes: u64) -> u64 {
104 if size_in_bytes > N::EXECUTION_STORAGE_PENALTY_THRESHOLD {
105 size_in_bytes.saturating_mul(size_in_bytes).saturating_div(N::EXECUTION_STORAGE_FEE_SCALING_FACTOR)
106 } else {
107 size_in_bytes
108 }
109}
110
111const CAST_BASE_COST: u64 = 500;
115const CAST_PER_BYTE_COST: u64 = 30;
116
117const HASH_BASE_COST: u64 = 10_000;
118const HASH_PER_BYTE_COST: u64 = 30;
119
120const HASH_BHP_BASE_COST: u64 = 50_000;
121const HASH_BHP_PER_BYTE_COST: u64 = 300;
122
123const HASH_PSD_BASE_COST: u64 = 40_000;
124const HASH_PSD_PER_BYTE_COST: u64 = 75;
125
126#[derive(Copy, Clone)]
127pub enum ConsensusFeeVersion {
128 V1,
129 V2,
130}
131
132const MAPPING_BASE_COST_V1: u64 = 10_000;
133const MAPPING_BASE_COST_V2: u64 = 1_500;
134const MAPPING_PER_BYTE_COST: u64 = 10;
135
136const SET_BASE_COST: u64 = 10_000;
137const SET_PER_BYTE_COST: u64 = 100;
138
139fn plaintext_size_in_bytes<N: Network>(stack: &Stack<N>, plaintext_type: &PlaintextType<N>) -> Result<u64> {
141 match plaintext_type {
142 PlaintextType::Literal(literal_type) => Ok(literal_type.size_in_bytes::<N>() as u64),
143 PlaintextType::Struct(struct_name) => {
144 let struct_ = stack.program().get_struct(struct_name)?;
146 let size_of_name = struct_.name().to_bytes_le()?.len() as u64;
148 let size_of_members = struct_.members().iter().try_fold(0u64, |acc, (_, member_type)| {
150 acc.checked_add(plaintext_size_in_bytes(stack, member_type)?).ok_or(anyhow!(
151 "Overflowed while computing the size of the struct '{}/{struct_name}' - {member_type}",
152 stack.program_id()
153 ))
154 })?;
155 Ok(size_of_name.saturating_add(size_of_members))
157 }
158 PlaintextType::Array(array_type) => {
159 let num_elements = **array_type.length() as u64;
161 let size_of_element = plaintext_size_in_bytes(stack, array_type.next_element_type())?;
163 Ok(num_elements.saturating_mul(size_of_element))
165 }
166 }
167}
168
169fn cost_in_size<'a, N: Network>(
171 stack: &Stack<N>,
172 finalize: &Finalize<N>,
173 operands: impl IntoIterator<Item = &'a Operand<N>>,
174 byte_multiplier: u64,
175 base_cost: u64,
176) -> Result<u64> {
177 let finalize_types = stack.get_finalize_types(finalize.name())?;
179 let size_of_operands = operands.into_iter().try_fold(0u64, |acc, operand| {
181 let operand_size = match finalize_types.get_type_from_operand(stack, operand)? {
183 FinalizeType::Plaintext(plaintext_type) => plaintext_size_in_bytes(stack, &plaintext_type)?,
184 FinalizeType::Future(future) => {
185 bail!("Future '{future}' is not a valid operand in the finalize scope");
186 }
187 };
188 acc.checked_add(operand_size).ok_or(anyhow!(
190 "Overflowed while computing the size of the operand '{operand}' in '{}/{}' (finalize)",
191 stack.program_id(),
192 finalize.name()
193 ))
194 })?;
195 Ok(base_cost.saturating_add(byte_multiplier.saturating_mul(size_of_operands)))
197}
198
199pub fn cost_per_command<N: Network>(
201 stack: &Stack<N>,
202 finalize: &Finalize<N>,
203 command: &Command<N>,
204 consensus_fee_version: ConsensusFeeVersion,
205) -> Result<u64> {
206 let mapping_base_cost = match consensus_fee_version {
207 ConsensusFeeVersion::V1 => MAPPING_BASE_COST_V1,
208 ConsensusFeeVersion::V2 => MAPPING_BASE_COST_V2,
209 };
210
211 match command {
212 Command::Instruction(Instruction::Abs(_)) => Ok(500),
213 Command::Instruction(Instruction::AbsWrapped(_)) => Ok(500),
214 Command::Instruction(Instruction::Add(_)) => Ok(500),
215 Command::Instruction(Instruction::AddWrapped(_)) => Ok(500),
216 Command::Instruction(Instruction::And(_)) => Ok(500),
217 Command::Instruction(Instruction::AssertEq(_)) => Ok(500),
218 Command::Instruction(Instruction::AssertNeq(_)) => Ok(500),
219 Command::Instruction(Instruction::Async(_)) => bail!("'async' is not supported in finalize"),
220 Command::Instruction(Instruction::Call(_)) => bail!("'call' is not supported in finalize"),
221 Command::Instruction(Instruction::Cast(cast)) => match cast.cast_type() {
222 CastType::Plaintext(PlaintextType::Literal(_)) => Ok(500),
223 CastType::Plaintext(plaintext_type) => Ok(plaintext_size_in_bytes(stack, plaintext_type)?
224 .saturating_mul(CAST_PER_BYTE_COST)
225 .saturating_add(CAST_BASE_COST)),
226 CastType::GroupXCoordinate
227 | CastType::GroupYCoordinate
228 | CastType::Record(_)
229 | CastType::ExternalRecord(_) => Ok(500),
230 },
231 Command::Instruction(Instruction::CastLossy(cast_lossy)) => match cast_lossy.cast_type() {
232 CastType::Plaintext(PlaintextType::Literal(_)) => Ok(500),
233 CastType::Plaintext(plaintext_type) => Ok(plaintext_size_in_bytes(stack, plaintext_type)?
234 .saturating_mul(CAST_PER_BYTE_COST)
235 .saturating_add(CAST_BASE_COST)),
236 CastType::GroupXCoordinate
237 | CastType::GroupYCoordinate
238 | CastType::Record(_)
239 | CastType::ExternalRecord(_) => Ok(500),
240 },
241 Command::Instruction(Instruction::CommitBHP256(commit)) => {
242 cost_in_size(stack, finalize, commit.operands(), HASH_BHP_PER_BYTE_COST, HASH_BHP_BASE_COST)
243 }
244 Command::Instruction(Instruction::CommitBHP512(commit)) => {
245 cost_in_size(stack, finalize, commit.operands(), HASH_BHP_PER_BYTE_COST, HASH_BHP_BASE_COST)
246 }
247 Command::Instruction(Instruction::CommitBHP768(commit)) => {
248 cost_in_size(stack, finalize, commit.operands(), HASH_BHP_PER_BYTE_COST, HASH_BHP_BASE_COST)
249 }
250 Command::Instruction(Instruction::CommitBHP1024(commit)) => {
251 cost_in_size(stack, finalize, commit.operands(), HASH_BHP_PER_BYTE_COST, HASH_BHP_BASE_COST)
252 }
253 Command::Instruction(Instruction::CommitPED64(commit)) => {
254 cost_in_size(stack, finalize, commit.operands(), HASH_PER_BYTE_COST, HASH_BASE_COST)
255 }
256 Command::Instruction(Instruction::CommitPED128(commit)) => {
257 cost_in_size(stack, finalize, commit.operands(), HASH_PER_BYTE_COST, HASH_BASE_COST)
258 }
259 Command::Instruction(Instruction::Div(div)) => {
260 ensure!(div.operands().len() == 2, "'div' must contain exactly 2 operands");
262 let finalize_types = stack.get_finalize_types(finalize.name())?;
264 match finalize_types.get_type_from_operand(stack, &div.operands()[0])? {
266 FinalizeType::Plaintext(PlaintextType::Literal(LiteralType::Field)) => Ok(1_500),
267 FinalizeType::Plaintext(PlaintextType::Literal(_)) => Ok(500),
268 FinalizeType::Plaintext(PlaintextType::Array(_)) => bail!("'div' does not support arrays"),
269 FinalizeType::Plaintext(PlaintextType::Struct(_)) => bail!("'div' does not support structs"),
270 FinalizeType::Future(_) => bail!("'div' does not support futures"),
271 }
272 }
273 Command::Instruction(Instruction::DivWrapped(_)) => Ok(500),
274 Command::Instruction(Instruction::Double(_)) => Ok(500),
275 Command::Instruction(Instruction::GreaterThan(_)) => Ok(500),
276 Command::Instruction(Instruction::GreaterThanOrEqual(_)) => Ok(500),
277 Command::Instruction(Instruction::HashBHP256(hash)) => {
278 cost_in_size(stack, finalize, hash.operands(), HASH_BHP_PER_BYTE_COST, HASH_BHP_BASE_COST)
279 }
280 Command::Instruction(Instruction::HashBHP512(hash)) => {
281 cost_in_size(stack, finalize, hash.operands(), HASH_BHP_PER_BYTE_COST, HASH_BHP_BASE_COST)
282 }
283 Command::Instruction(Instruction::HashBHP768(hash)) => {
284 cost_in_size(stack, finalize, hash.operands(), HASH_BHP_PER_BYTE_COST, HASH_BHP_BASE_COST)
285 }
286 Command::Instruction(Instruction::HashBHP1024(hash)) => {
287 cost_in_size(stack, finalize, hash.operands(), HASH_BHP_PER_BYTE_COST, HASH_BHP_BASE_COST)
288 }
289 Command::Instruction(Instruction::HashKeccak256(hash)) => {
290 cost_in_size(stack, finalize, hash.operands(), HASH_PER_BYTE_COST, HASH_BASE_COST)
291 }
292 Command::Instruction(Instruction::HashKeccak384(hash)) => {
293 cost_in_size(stack, finalize, hash.operands(), HASH_PER_BYTE_COST, HASH_BASE_COST)
294 }
295 Command::Instruction(Instruction::HashKeccak512(hash)) => {
296 cost_in_size(stack, finalize, hash.operands(), HASH_PER_BYTE_COST, HASH_BASE_COST)
297 }
298 Command::Instruction(Instruction::HashPED64(hash)) => {
299 cost_in_size(stack, finalize, hash.operands(), HASH_PER_BYTE_COST, HASH_BASE_COST)
300 }
301 Command::Instruction(Instruction::HashPED128(hash)) => {
302 cost_in_size(stack, finalize, hash.operands(), HASH_PER_BYTE_COST, HASH_BASE_COST)
303 }
304 Command::Instruction(Instruction::HashPSD2(hash)) => {
305 cost_in_size(stack, finalize, hash.operands(), HASH_PSD_PER_BYTE_COST, HASH_PSD_BASE_COST)
306 }
307 Command::Instruction(Instruction::HashPSD4(hash)) => {
308 cost_in_size(stack, finalize, hash.operands(), HASH_PSD_PER_BYTE_COST, HASH_PSD_BASE_COST)
309 }
310 Command::Instruction(Instruction::HashPSD8(hash)) => {
311 cost_in_size(stack, finalize, hash.operands(), HASH_PSD_PER_BYTE_COST, HASH_PSD_BASE_COST)
312 }
313 Command::Instruction(Instruction::HashSha3_256(hash)) => {
314 cost_in_size(stack, finalize, hash.operands(), HASH_PER_BYTE_COST, HASH_BASE_COST)
315 }
316 Command::Instruction(Instruction::HashSha3_384(hash)) => {
317 cost_in_size(stack, finalize, hash.operands(), HASH_PER_BYTE_COST, HASH_BASE_COST)
318 }
319 Command::Instruction(Instruction::HashSha3_512(hash)) => {
320 cost_in_size(stack, finalize, hash.operands(), HASH_PER_BYTE_COST, HASH_BASE_COST)
321 }
322 Command::Instruction(Instruction::HashManyPSD2(_)) => {
323 bail!("`hash_many.psd2` is not supported in finalize")
324 }
325 Command::Instruction(Instruction::HashManyPSD4(_)) => {
326 bail!("`hash_many.psd4` is not supported in finalize")
327 }
328 Command::Instruction(Instruction::HashManyPSD8(_)) => {
329 bail!("`hash_many.psd8` is not supported in finalize")
330 }
331 Command::Instruction(Instruction::Inv(_)) => Ok(2_500),
332 Command::Instruction(Instruction::IsEq(_)) => Ok(500),
333 Command::Instruction(Instruction::IsNeq(_)) => Ok(500),
334 Command::Instruction(Instruction::LessThan(_)) => Ok(500),
335 Command::Instruction(Instruction::LessThanOrEqual(_)) => Ok(500),
336 Command::Instruction(Instruction::Modulo(_)) => Ok(500),
337 Command::Instruction(Instruction::Mul(mul)) => {
338 ensure!(mul.operands().len() == 2, "'mul' must contain exactly 2 operands");
340 let finalize_types = stack.get_finalize_types(finalize.name())?;
342 match finalize_types.get_type_from_operand(stack, &mul.operands()[0])? {
344 FinalizeType::Plaintext(PlaintextType::Literal(LiteralType::Group)) => Ok(10_000),
345 FinalizeType::Plaintext(PlaintextType::Literal(LiteralType::Scalar)) => Ok(10_000),
346 FinalizeType::Plaintext(PlaintextType::Literal(_)) => Ok(500),
347 FinalizeType::Plaintext(PlaintextType::Array(_)) => bail!("'mul' does not support arrays"),
348 FinalizeType::Plaintext(PlaintextType::Struct(_)) => bail!("'mul' does not support structs"),
349 FinalizeType::Future(_) => bail!("'mul' does not support futures"),
350 }
351 }
352 Command::Instruction(Instruction::MulWrapped(_)) => Ok(500),
353 Command::Instruction(Instruction::Nand(_)) => Ok(500),
354 Command::Instruction(Instruction::Neg(_)) => Ok(500),
355 Command::Instruction(Instruction::Nor(_)) => Ok(500),
356 Command::Instruction(Instruction::Not(_)) => Ok(500),
357 Command::Instruction(Instruction::Or(_)) => Ok(500),
358 Command::Instruction(Instruction::Pow(pow)) => {
359 ensure!(!pow.operands().is_empty(), "'pow' must contain at least 1 operand");
361 let finalize_types = stack.get_finalize_types(finalize.name())?;
363 match finalize_types.get_type_from_operand(stack, &pow.operands()[0])? {
365 FinalizeType::Plaintext(PlaintextType::Literal(LiteralType::Field)) => Ok(1_500),
366 FinalizeType::Plaintext(PlaintextType::Literal(_)) => Ok(500),
367 FinalizeType::Plaintext(PlaintextType::Array(_)) => bail!("'pow' does not support arrays"),
368 FinalizeType::Plaintext(PlaintextType::Struct(_)) => bail!("'pow' does not support structs"),
369 FinalizeType::Future(_) => bail!("'pow' does not support futures"),
370 }
371 }
372 Command::Instruction(Instruction::PowWrapped(_)) => Ok(500),
373 Command::Instruction(Instruction::Rem(_)) => Ok(500),
374 Command::Instruction(Instruction::RemWrapped(_)) => Ok(500),
375 Command::Instruction(Instruction::SignVerify(sign)) => {
376 cost_in_size(stack, finalize, sign.operands(), HASH_PSD_PER_BYTE_COST, HASH_PSD_BASE_COST)
377 }
378 Command::Instruction(Instruction::Shl(_)) => Ok(500),
379 Command::Instruction(Instruction::ShlWrapped(_)) => Ok(500),
380 Command::Instruction(Instruction::Shr(_)) => Ok(500),
381 Command::Instruction(Instruction::ShrWrapped(_)) => Ok(500),
382 Command::Instruction(Instruction::Square(_)) => Ok(500),
383 Command::Instruction(Instruction::SquareRoot(_)) => Ok(2_500),
384 Command::Instruction(Instruction::Sub(_)) => Ok(500),
385 Command::Instruction(Instruction::SubWrapped(_)) => Ok(500),
386 Command::Instruction(Instruction::Ternary(_)) => Ok(500),
387 Command::Instruction(Instruction::Xor(_)) => Ok(500),
388 Command::Await(_) => Ok(500),
389 Command::Contains(command) => {
390 cost_in_size(stack, finalize, [command.key()], MAPPING_PER_BYTE_COST, mapping_base_cost)
391 }
392 Command::Get(command) => {
393 cost_in_size(stack, finalize, [command.key()], MAPPING_PER_BYTE_COST, mapping_base_cost)
394 }
395 Command::GetOrUse(command) => {
396 cost_in_size(stack, finalize, [command.key()], MAPPING_PER_BYTE_COST, mapping_base_cost)
397 }
398 Command::RandChaCha(_) => Ok(25_000),
399 Command::Remove(_) => Ok(SET_BASE_COST),
400 Command::Set(command) => {
401 cost_in_size(stack, finalize, [command.key(), command.value()], SET_PER_BYTE_COST, SET_BASE_COST)
402 }
403 Command::BranchEq(_) | Command::BranchNeq(_) => Ok(500),
404 Command::Position(_) => Ok(100),
405 }
406}
407
408pub fn cost_in_microcredits_v2<N: Network>(stack: &Stack<N>, function_name: &Identifier<N>) -> Result<u64> {
410 cost_in_microcredits(stack, function_name, ConsensusFeeVersion::V2)
411}
412
413pub fn cost_in_microcredits_v1<N: Network>(stack: &Stack<N>, function_name: &Identifier<N>) -> Result<u64> {
415 cost_in_microcredits(stack, function_name, ConsensusFeeVersion::V1)
416}
417
418fn cost_in_microcredits<N: Network>(
420 stack: &Stack<N>,
421 function_name: &Identifier<N>,
422 consensus_fee_version: ConsensusFeeVersion,
423) -> Result<u64> {
424 let mut finalize_cost = 0u64;
426 let mut finalizes = vec![(StackRef::Internal(stack), *function_name)];
428 let mut num_finalizes = 1;
430 while let Some((stack_ref, function_name)) = finalizes.pop() {
432 ensure!(
435 num_finalizes < Transaction::<N>::MAX_TRANSITIONS,
436 "The number of finalize blocks must be less than '{}'",
437 Transaction::<N>::MAX_TRANSITIONS
438 );
439 if let Some(finalize) = stack_ref.get_function_ref(&function_name)?.finalize_logic() {
441 for input in finalize.inputs() {
443 if let FinalizeType::Future(future) = input.finalize_type() {
444 let external_stack = stack_ref.get_external_stack(future.program_id())?;
446 num_finalizes += 1;
448 finalizes.push((StackRef::External(external_stack), *future.resource()));
450 }
451 }
452 for command in finalize.commands() {
454 finalize_cost = finalize_cost
456 .checked_add(cost_per_command(&stack_ref, finalize, command, consensus_fee_version)?)
457 .ok_or(anyhow!("Finalize cost overflowed"))?;
458 }
459 }
460 }
461 Ok(finalize_cost)
462}
463
464#[cfg(test)]
465mod tests {
466 use super::*;
467 use crate::test_helpers::get_execution;
468
469 use console::network::{CanaryV0, MainnetV0, TestnetV0};
470 use synthesizer_program::Program;
471
472 const SIZE_BOUNDARY_PROGRAM: &str = r#"
474program size_boundary.aleo;
475
476function under_five_thousand:
477 input r0 as group.public;
478 cast r0 r0 r0 r0 r0 r0 r0 r0 r0 into r1 as [group; 9u32];
479 cast r1 r1 r1 r1 r1 r1 r1 r1 r1 r1 into r2 as [[group; 9u32]; 10u32];
480 cast r0 r0 r0 r0 r0 r0 r0 into r3 as [group; 7u32];
481 output r2 as [[group; 9u32]; 10u32].public;
482 output r3 as [group; 7u32].public;
483
484function over_five_thousand:
485 input r0 as group.public;
486 cast r0 r0 r0 r0 r0 r0 r0 r0 r0 into r1 as [group; 9u32];
487 cast r1 r1 r1 r1 r1 r1 r1 r1 r1 r1 into r2 as [[group; 9u32]; 10u32];
488 cast r0 r0 r0 r0 r0 r0 r0 into r3 as [group; 7u32];
489 output r2 as [[group; 9u32]; 10u32].public;
490 output r3 as [group; 7u32].public;
491 output 5u64 as u64.public;
492 "#;
493 const STORAGE_COST_ABOVE_THRESHOLD: u64 = 5002;
495 const STORAGE_COST_MAX: u64 = 3_276_800;
497
498 fn test_storage_cost_bounds<N: Network>() {
499 let threshold = N::EXECUTION_STORAGE_PENALTY_THRESHOLD;
501 let threshold_lower_offset = threshold.saturating_sub(1);
502 let threshold_upper_offset = threshold.saturating_add(1);
503
504 assert_eq!(execution_storage_cost::<N>(0), 0);
506 assert_eq!(execution_storage_cost::<N>(1), 1);
507 assert_eq!(execution_storage_cost::<N>(threshold_lower_offset), threshold_lower_offset);
508 assert_eq!(execution_storage_cost::<N>(threshold), threshold);
509 assert_eq!(execution_storage_cost::<N>(threshold_upper_offset), STORAGE_COST_ABOVE_THRESHOLD);
510 assert_eq!(execution_storage_cost::<N>(N::MAX_TRANSACTION_SIZE as u64), STORAGE_COST_MAX);
511 }
512
513 #[test]
514 fn test_storage_cost_bounds_for_all_networks() {
515 test_storage_cost_bounds::<CanaryV0>();
516 test_storage_cost_bounds::<MainnetV0>();
517 test_storage_cost_bounds::<TestnetV0>();
518 }
519
520 #[test]
521 fn test_storage_costs_compute_correctly() {
522 let threshold = MainnetV0::EXECUTION_STORAGE_PENALTY_THRESHOLD;
524
525 let mut process = Process::load().unwrap();
527
528 let program = Program::from_str(SIZE_BOUNDARY_PROGRAM).unwrap();
530
531 let under_5000 = Identifier::from_str("under_five_thousand").unwrap();
533 let over_5000 = Identifier::from_str("over_five_thousand").unwrap();
534
535 let execution_under_5000 = get_execution(&mut process, &program, &under_5000, ["2group"].into_iter());
537 let execution_size_under_5000 = execution_under_5000.size_in_bytes().unwrap();
538 let (_, (storage_cost_under_5000, _)) = execution_cost_v2(&process, &execution_under_5000).unwrap();
539 let execution_over_5000 = get_execution(&mut process, &program, &over_5000, ["2group"].into_iter());
540 let execution_size_over_5000 = execution_over_5000.size_in_bytes().unwrap();
541 let (_, (storage_cost_over_5000, _)) = execution_cost_v2(&process, &execution_over_5000).unwrap();
542
543 assert!(execution_size_under_5000 < threshold);
545 assert!(execution_size_over_5000 > threshold);
546
547 assert_eq!(storage_cost_under_5000, execution_storage_cost::<MainnetV0>(execution_size_under_5000));
549 assert_eq!(storage_cost_over_5000, execution_storage_cost::<MainnetV0>(execution_size_over_5000));
550 }
551}