1use crate::internal_prelude::*;
2use crate::kernel::kernel_callback_api::{
3 CheckReferenceEvent, CloseSubstateEvent, CreateNodeEvent, DrainSubstatesEvent, DropNodeEvent,
4 MoveModuleEvent, OpenSubstateEvent, ReadSubstateEvent, RemoveSubstateEvent, ScanKeysEvent,
5 ScanSortedSubstatesEvent, SetSubstateEvent, WriteSubstateEvent,
6};
7use crate::kernel::substate_io::SubstateDevice;
8use crate::system::actor::Actor;
9use crate::system::system_callback::SystemVersion;
10use crate::system::system_modules::transaction_runtime::Event;
11use crate::{
12 blueprints::package::*,
13 track::interface::{IOAccess, StoreCommit},
14};
15use lazy_static::lazy_static;
16
17const CPU_INSTRUCTIONS_TO_COST_UNIT: u32 = 34;
22
23lazy_static! {
24 pub static ref NATIVE_FUNCTION_BASE_COSTS: IndexMap<PackageAddress, IndexMap<&'static str, u32>> = {
25 let mut costs: IndexMap<PackageAddress, IndexMap<&'static str, u32>> = index_map_new();
26 include_str!("../../../../assets/native_function_base_costs.csv")
27 .split("\n")
28 .filter(|x| x.len() > 0)
29 .for_each(|x| {
30 let mut tokens = x.split(",");
31 let package_address =
32 PackageAddress::try_from_hex(tokens.next().unwrap().trim()).unwrap();
33 let export_name = tokens.next().unwrap().trim();
34 let cost = u32::from_str(tokens.next().unwrap().trim()).unwrap();
35 costs
36 .entry(package_address)
37 .or_default()
38 .insert(export_name, cost);
39 });
40 costs
41 };
42 pub static ref NATIVE_FUNCTION_BASE_COSTS_SIZE_DEPENDENT: IndexMap<PackageAddress, IndexMap<&'static str, (u32, u32)>> = {
43 let mut costs: IndexMap<PackageAddress, IndexMap<&'static str, (u32, u32)>> =
44 index_map_new();
45 costs
46 .entry(PACKAGE_PACKAGE)
47 .or_default()
48 .insert(PACKAGE_PUBLISH_NATIVE_IDENT, (875, 11477486));
49 costs
50 .entry(PACKAGE_PACKAGE)
51 .or_default()
52 .insert(PACKAGE_PUBLISH_WASM_ADVANCED_IDENT, (9063 / 6, 11072798));
54 costs
55 };
56}
57
58#[derive(Debug, Clone, ScryptoSbor)]
68pub struct FeeTable {
69 wasm_execution_units_divider: u32,
70}
71
72impl FeeTable {
73 pub fn new(version: SystemVersion) -> Self {
74 let wasm_execution_units_divider = match version {
75 SystemVersion::V1 => 3000,
79
80 SystemVersion::V2 | SystemVersion::V3 => 4500,
103 };
104
105 Self {
106 wasm_execution_units_divider,
107 }
108 }
109
110 pub fn latest() -> Self {
111 Self::cuttlefish()
112 }
113
114 pub fn cuttlefish() -> Self {
115 Self::new(SystemVersion::V2)
116 }
117
118 pub fn bottlenose() -> Self {
119 Self::new(SystemVersion::V1)
120 }
121
122 pub fn anemone() -> Self {
123 Self::new(SystemVersion::V1)
124 }
125
126 pub fn babylon() -> Self {
127 Self::new(SystemVersion::V1)
128 }
129
130 fn data_processing_cost(size: usize) -> u32 {
135 mul(cast(size), 2)
142 }
143
144 fn io_access_cost(&self, io_access: &IOAccess) -> u32 {
145 match io_access {
146 IOAccess::ReadFromDb(_, size) => {
147 add(cast(*size) / 10, 40_000)
151 }
152 IOAccess::ReadFromDbNotFound(_) => {
153 160_000
157 }
158 IOAccess::HeapSubstateUpdated { .. } | IOAccess::TrackSubstateUpdated { .. } => {
159 0
161 }
162 }
163 }
164
165 #[inline]
166 pub fn verify_tx_signatures_cost(&self, n: usize) -> u32 {
167 mul(cast(n), 7_000)
170 }
171
172 #[inline]
173 pub fn validate_tx_payload_cost(&self, size: usize) -> u32 {
174 mul(cast(size), 40)
181 }
182
183 #[inline]
184 pub fn check_reference(&self, event: &CheckReferenceEvent) -> u32 {
185 match event {
186 CheckReferenceEvent::IOAccess(io_access) => self.io_access_cost(io_access),
187 }
188 }
189
190 #[inline]
191 pub fn check_intent_validity(&self) -> u32 {
192 160000
194 }
195
196 #[inline]
197 pub fn check_timestamp(&self) -> u32 {
198 40_000
200 }
201
202 #[inline]
203 pub fn run_native_code_cost(
204 &self,
205 package_address: &PackageAddress,
206 export_name: &str,
207 input_size: &usize,
208 ) -> u32 {
209 let native_execution_units = NATIVE_FUNCTION_BASE_COSTS
210 .get(package_address)
211 .and_then(|x| x.get(export_name).cloned())
212 .unwrap_or_else(|| {
213 NATIVE_FUNCTION_BASE_COSTS_SIZE_DEPENDENT
214 .get(package_address)
215 .and_then(|x| x.get(export_name))
216 .and_then(|value| Some(add(value.1, mul(value.0, cast(*input_size)))))
217 .unwrap_or_else(|| {
218 panic!(
219 "Native function not found: {:?}::{}. ",
220 package_address, export_name
221 )
222 })
223 });
224
225 native_execution_units / CPU_INSTRUCTIONS_TO_COST_UNIT
226 }
227
228 #[inline]
229 pub fn run_wasm_code_cost(
230 &self,
231 _package_address: &PackageAddress,
232 _export_name: &str,
233 wasm_execution_units: u32,
234 ) -> u32 {
235 wasm_execution_units / self.wasm_execution_units_divider
236 }
237
238 #[inline]
239 pub fn instantiate_wasm_code_cost(&self, size: usize) -> u32 {
240 mul(cast(size), 2)
244 }
245
246 #[inline]
247 pub fn before_invoke_cost(&self, _actor: &Actor, input_size: usize) -> u32 {
248 Self::data_processing_cost(input_size)
249 }
250
251 #[inline]
252 pub fn after_invoke_cost(&self, input_size: usize) -> u32 {
253 Self::data_processing_cost(input_size)
254 }
255
256 #[inline]
257 pub fn allocate_node_id_cost(&self) -> u32 {
258 3312 / CPU_INSTRUCTIONS_TO_COST_UNIT
259 }
260
261 #[inline]
262 pub fn create_node_cost(&self, event: &CreateNodeEvent) -> u32 {
263 match event {
264 CreateNodeEvent::Start(_node_id, node_substates) => {
265 let total_substate_size = node_substates
266 .values()
267 .map(|x| x.values().map(|x| x.len()).sum::<usize>())
268 .sum::<usize>();
269 add(
270 15510 / CPU_INSTRUCTIONS_TO_COST_UNIT,
271 Self::data_processing_cost(total_substate_size),
272 )
273 }
274 CreateNodeEvent::IOAccess(io_access) => self.io_access_cost(io_access),
275 CreateNodeEvent::End(..) => 0,
276 }
277 }
278
279 #[inline]
280 pub fn pin_node_cost(&self, _node_id: &NodeId) -> u32 {
281 424 / CPU_INSTRUCTIONS_TO_COST_UNIT
282 }
283
284 #[inline]
285 pub fn drop_node_cost(&self, event: &DropNodeEvent) -> u32 {
286 match event {
287 DropNodeEvent::Start(..) => 0,
288 DropNodeEvent::IOAccess(io_access) => self.io_access_cost(io_access),
289 DropNodeEvent::End(_node_id, node_substates) => {
290 let total_substate_size = node_substates
291 .values()
292 .map(|x| x.values().map(|x| x.len()).sum::<usize>())
293 .sum::<usize>();
294 add(
295 38883 / CPU_INSTRUCTIONS_TO_COST_UNIT,
296 Self::data_processing_cost(total_substate_size),
297 )
298 }
299 }
300 }
301
302 #[inline]
303 pub fn move_module_cost(&self, event: &MoveModuleEvent) -> u32 {
304 match event {
305 MoveModuleEvent::IOAccess(io_access) => add(
306 4791 / CPU_INSTRUCTIONS_TO_COST_UNIT,
307 self.io_access_cost(io_access),
308 ),
309 }
310 }
311
312 #[inline]
313 pub fn open_substate_cost(&self, event: &OpenSubstateEvent) -> u32 {
314 match event {
315 OpenSubstateEvent::Start { .. } => 0,
316 OpenSubstateEvent::IOAccess(io_access) => self.io_access_cost(io_access),
317 OpenSubstateEvent::End { size, .. } => add(
318 10318 / CPU_INSTRUCTIONS_TO_COST_UNIT,
319 Self::data_processing_cost(*size),
320 ),
321 }
322 }
323
324 #[inline]
325 pub fn read_substate_cost(&self, event: &ReadSubstateEvent) -> u32 {
326 match event {
327 ReadSubstateEvent::OnRead { value, device, .. } => {
328 let base_cost: u32 = match device {
329 SubstateDevice::Heap => 2234,
330 SubstateDevice::Store => 3868,
331 };
332
333 add(
334 base_cost / CPU_INSTRUCTIONS_TO_COST_UNIT,
335 Self::data_processing_cost(value.len()),
336 )
337 }
338 ReadSubstateEvent::IOAccess(io_access) => self.io_access_cost(io_access),
339 }
340 }
341
342 #[inline]
343 pub fn write_substate_cost(&self, event: &WriteSubstateEvent) -> u32 {
344 match event {
345 WriteSubstateEvent::IOAccess(io_access) => self.io_access_cost(io_access),
346 WriteSubstateEvent::Start { value, .. } => add(
347 7441 / CPU_INSTRUCTIONS_TO_COST_UNIT,
348 Self::data_processing_cost(value.len()),
349 ),
350 }
351 }
352
353 #[inline]
354 pub fn close_substate_cost(&self, event: &CloseSubstateEvent) -> u32 {
355 match event {
356 CloseSubstateEvent::Start(..) => 4390 / CPU_INSTRUCTIONS_TO_COST_UNIT,
357 }
358 }
359
360 #[inline]
361 pub fn set_substate_cost(&self, event: &SetSubstateEvent) -> u32 {
362 match event {
363 SetSubstateEvent::Start(.., value) => add(
364 4530 / CPU_INSTRUCTIONS_TO_COST_UNIT,
365 Self::data_processing_cost(value.len()),
366 ),
367 SetSubstateEvent::IOAccess(io_access) => self.io_access_cost(io_access),
368 }
369 }
370
371 #[inline]
372 pub fn remove_substate_cost(&self, event: &RemoveSubstateEvent) -> u32 {
373 match event {
374 RemoveSubstateEvent::Start(..) => 24389 / CPU_INSTRUCTIONS_TO_COST_UNIT,
375 RemoveSubstateEvent::IOAccess(io_access) => self.io_access_cost(io_access),
376 }
377 }
378
379 #[inline]
380 pub fn mark_substate_as_transient_cost(
381 &self,
382 _node_id: &NodeId,
383 _partition_number: &PartitionNumber,
384 _substate_key: &SubstateKey,
385 ) -> u32 {
386 1896 / CPU_INSTRUCTIONS_TO_COST_UNIT
387 }
388
389 #[inline]
390 pub fn scan_keys_cost(&self, event: &ScanKeysEvent) -> u32 {
391 match event {
392 ScanKeysEvent::Start => 16938 / CPU_INSTRUCTIONS_TO_COST_UNIT,
393 ScanKeysEvent::IOAccess(io_access) => self.io_access_cost(io_access),
394 }
395 }
396
397 #[inline]
398 pub fn drain_substates_cost(&self, event: &DrainSubstatesEvent) -> u32 {
399 match event {
400 DrainSubstatesEvent::Start(count) => {
401 let cpu_instructions = add(9262, mul(9286, *count));
402 cpu_instructions / CPU_INSTRUCTIONS_TO_COST_UNIT
403 }
404 DrainSubstatesEvent::IOAccess(io_access) => self.io_access_cost(io_access),
405 }
406 }
407
408 #[inline]
409 pub fn scan_sorted_substates_cost(&self, event: &ScanSortedSubstatesEvent) -> u32 {
410 match event {
411 ScanSortedSubstatesEvent::Start => 6369 / CPU_INSTRUCTIONS_TO_COST_UNIT,
412 ScanSortedSubstatesEvent::IOAccess(io_access) => self.io_access_cost(io_access),
413 }
414 }
415
416 #[inline]
417 pub fn get_stack_id(&self) -> u32 {
418 500
419 }
420
421 #[inline]
422 pub fn get_owned_nodes(&self) -> u32 {
423 500
424 }
425
426 #[inline]
427 pub fn switch_stack(&self) -> u32 {
428 500
429 }
430
431 #[inline]
432 pub fn send_to_stack(&self, data_len: usize) -> u32 {
433 500 + Self::data_processing_cost(data_len)
434 }
435
436 #[inline]
437 pub fn set_call_frame_data(&self, data_len: usize) -> u32 {
438 500 + Self::data_processing_cost(data_len)
439 }
440
441 #[inline]
442 pub fn lock_fee_cost(&self) -> u32 {
443 500
444 }
445
446 #[inline]
447 pub fn query_fee_reserve_cost(&self) -> u32 {
448 500
449 }
450
451 #[inline]
452 pub fn query_costing_module(&self) -> u32 {
453 500
454 }
455
456 #[inline]
457 pub fn query_actor_cost(&self) -> u32 {
458 500
459 }
460
461 #[inline]
462 pub fn query_transaction_hash_cost(&self) -> u32 {
463 500
464 }
465
466 #[inline]
467 pub fn generate_ruid_cost(&self) -> u32 {
468 500
469 }
470
471 #[inline]
472 pub fn emit_event_cost(&self, size: usize) -> u32 {
473 500 + Self::data_processing_cost(size)
474 }
475
476 #[inline]
477 pub fn emit_log_cost(&self, size: usize) -> u32 {
478 500 + Self::data_processing_cost(size)
479 }
480
481 #[inline]
482 pub fn encode_bech32_address_cost(&self) -> u32 {
483 500
484 }
485
486 #[inline]
487 pub fn panic_cost(&self, size: usize) -> u32 {
488 500 + Self::data_processing_cost(size)
489 }
490
491 #[inline]
492 pub fn bls12381_v1_verify_cost(&self, size: usize) -> u32 {
493 let size = if size < 1024 { 1024 } else { cast(size) };
503 let instructions_cnt = add(mul(size, 36), 15650000);
504 instructions_cnt / CPU_INSTRUCTIONS_TO_COST_UNIT
506 }
507
508 #[inline]
509 pub fn bls12381_v1_aggregate_verify_cost(&self, sizes: &[usize]) -> u32 {
510 let mut instructions_cnt = 0u32;
533
534 for s in sizes {
535 instructions_cnt = add(add(instructions_cnt, mul(35, cast(*s))), 2620296);
536 }
537 let multiplier = cast(sizes.len() / 8);
538 instructions_cnt = add(instructions_cnt, mul(multiplier, 16850000));
539
540 instructions_cnt = add(
543 instructions_cnt,
544 match sizes.len() % 8 {
545 0 => 0,
546 1 => 3051556,
547 2 => 5020768,
548 3 => 6990111,
549 4 => 8959454,
550 5 => 10928798,
551 6 => 12898141,
552 7 => 14867484,
553 _ => unreachable!(),
554 },
555 );
556
557 instructions_cnt = add(instructions_cnt, 281125 + 583573 + 3027639 + 4280077);
559
560 instructions_cnt = mul(instructions_cnt / 100, 121);
562 instructions_cnt / CPU_INSTRUCTIONS_TO_COST_UNIT
564 }
565
566 #[inline]
567 pub fn bls12381_v1_fast_aggregate_verify_cost(&self, size: usize, keys_cnt: usize) -> u32 {
568 let size = if size < 1024 { 1024 } else { cast(size) };
579 let instructions_cnt = add(add(mul(size, 36), mul(cast(keys_cnt), 626056)), 15200000);
580 instructions_cnt / CPU_INSTRUCTIONS_TO_COST_UNIT
582 }
583
584 #[inline]
585 pub fn bls12381_g2_signature_aggregate_cost(&self, signatures_cnt: usize) -> u32 {
586 let instructions_cnt = sub(mul(cast(signatures_cnt), 879554), 500000);
595 instructions_cnt / CPU_INSTRUCTIONS_TO_COST_UNIT
597 }
598
599 #[inline]
600 pub fn keccak256_hash_cost(&self, size: usize) -> u32 {
601 let size = if size < 100 { 100 } else { cast(size) };
610 let instructions_cnt = add(mul(size, 47), 2642);
611 instructions_cnt / CPU_INSTRUCTIONS_TO_COST_UNIT
613 }
614
615 #[inline]
616 pub fn blake2b256_hash_cost(&self, size: usize) -> u32 {
617 let size = if size < 100 { 100 } else { cast(size) };
627 let instructions_cnt = add(mul(size, 15), 1600);
628 instructions_cnt / CPU_INSTRUCTIONS_TO_COST_UNIT
630 }
631
632 #[inline]
633 pub fn ed25519_verify_cost(&self, size: usize) -> u32 {
634 let instructions_cnt = add(mul(cast(size), 34), 500000);
642 instructions_cnt / CPU_INSTRUCTIONS_TO_COST_UNIT
644 }
645
646 #[inline]
647 pub fn secp256k1_ecdsa_verify_cost(&self) -> u32 {
648 let instructions_cnt = 500000;
653 instructions_cnt / CPU_INSTRUCTIONS_TO_COST_UNIT
655 }
656
657 #[inline]
658 pub fn secp256k1_ecdsa_verify_and_key_recover_cost(&self) -> u32 {
659 let instructions_cnt = 500000;
664 instructions_cnt / CPU_INSTRUCTIONS_TO_COST_UNIT
666 }
667
668 #[inline]
674 pub fn commit_state_updates_cost(&self, store_commit: &StoreCommit) -> u32 {
675 match store_commit {
679 StoreCommit::Insert { size, .. } => add(cast(*size) / 4, 100_000),
680 StoreCommit::Update { size, .. } => add(cast(*size) / 4, 100_000),
681 StoreCommit::Delete { .. } => 100_000,
682 }
683 }
684
685 #[inline]
686 pub fn commit_events_cost(&self, events: &Vec<Event>) -> u32 {
687 let mut sum = 0;
688 for event in events {
689 sum += add(cast(event.payload.len()) / 4, 5_000)
690 }
691 sum
692 }
693
694 #[inline]
695 pub fn commit_logs_cost(&self, logs: &Vec<(Level, String)>) -> u32 {
696 let mut sum = 0;
697 for log in logs {
698 sum += add(cast(log.1.len()) / 4, 1_000)
699 }
700 sum
701 }
702
703 #[inline]
704 pub fn commit_intent_status(&self, num_of_intent_statuses: usize) -> u32 {
705 mul(cast(num_of_intent_statuses), 100_000)
707 }
708}
709
710#[inline]
711fn cast(a: usize) -> u32 {
712 u32::try_from(a).unwrap_or(u32::MAX)
713}
714
715#[inline]
716fn add(a: u32, b: u32) -> u32 {
717 a.checked_add(b).unwrap_or(u32::MAX)
718}
719
720#[inline]
721fn sub(a: u32, b: u32) -> u32 {
722 a.checked_sub(b).unwrap_or(u32::MAX)
723}
724
725#[inline]
726fn mul(a: u32, b: u32) -> u32 {
727 a.checked_mul(b).unwrap_or(u32::MAX)
728}