1use crate::pages::{GearPagesAmount, WasmPagesAmount};
22use core::{fmt::Debug, marker::PhantomData};
23use paste::paste;
24
25#[derive(Clone, Copy, PartialEq, Eq)]
27pub struct CostOf<T> {
28 cost: u64,
29 _phantom: PhantomData<T>,
30}
31
32impl<T> CostOf<T> {
33 pub const fn new(cost: u64) -> Self {
35 Self {
36 cost,
37 _phantom: PhantomData,
38 }
39 }
40
41 pub const fn cost_for_one(&self) -> u64 {
43 self.cost
44 }
45}
46
47impl<T: Into<u32>> CostOf<T> {
48 pub fn cost_for(&self, num: T) -> u64 {
50 self.cost.saturating_mul(Into::<u32>::into(num).into())
51 }
52}
53
54impl<T> Debug for CostOf<T> {
55 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
56 f.write_fmt(format_args!("{}", &self.cost))
57 }
58}
59
60impl<T> From<u64> for CostOf<T> {
61 fn from(cost: u64) -> Self {
62 CostOf::new(cost)
63 }
64}
65
66impl<T> From<CostOf<T>> for u64 {
67 fn from(value: CostOf<T>) -> Self {
68 value.cost
69 }
70}
71
72impl<T> Default for CostOf<T> {
73 fn default() -> Self {
74 CostOf::new(0)
75 }
76}
77
78#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, derive_more::From, derive_more::Into)]
80pub struct CallsAmount(u32);
81
82impl CostOf<CallsAmount> {
83 pub fn with_bytes(&self, per_byte: CostOf<BytesAmount>, amount: BytesAmount) -> u64 {
85 self.cost_for_one()
86 .saturating_add(per_byte.cost_for(amount))
87 }
88}
89
90#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, derive_more::From, derive_more::Into)]
92pub struct BytesAmount(u32);
93
94#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, derive_more::From, derive_more::Into)]
96pub struct BlocksAmount(u32);
97
98#[derive(Debug, Clone, Default, PartialEq, Eq)]
100pub struct SyscallCosts {
101 pub alloc: CostOf<CallsAmount>,
103
104 pub free: CostOf<CallsAmount>,
106
107 pub free_range: CostOf<CallsAmount>,
109
110 pub free_range_per_page: CostOf<WasmPagesAmount>,
112
113 pub gr_reserve_gas: CostOf<CallsAmount>,
115
116 pub gr_unreserve_gas: CostOf<CallsAmount>,
118
119 pub gr_system_reserve_gas: CostOf<CallsAmount>,
121
122 pub gr_gas_available: CostOf<CallsAmount>,
124
125 pub gr_message_id: CostOf<CallsAmount>,
127
128 pub gr_program_id: CostOf<CallsAmount>,
130
131 pub gr_source: CostOf<CallsAmount>,
133
134 pub gr_value: CostOf<CallsAmount>,
136
137 pub gr_value_available: CostOf<CallsAmount>,
139
140 pub gr_size: CostOf<CallsAmount>,
142
143 pub gr_read: CostOf<CallsAmount>,
145
146 pub gr_read_per_byte: CostOf<BytesAmount>,
148
149 pub gr_env_vars: CostOf<CallsAmount>,
151
152 pub gr_block_height: CostOf<CallsAmount>,
154
155 pub gr_block_timestamp: CostOf<CallsAmount>,
157
158 pub gr_random: CostOf<CallsAmount>,
160
161 pub gr_reply_deposit: CostOf<CallsAmount>,
163
164 pub gr_send: CostOf<CallsAmount>,
166
167 pub gr_send_per_byte: CostOf<BytesAmount>,
169
170 pub gr_send_wgas: CostOf<CallsAmount>,
172
173 pub gr_send_wgas_per_byte: CostOf<BytesAmount>,
175
176 pub gr_send_init: CostOf<CallsAmount>,
178
179 pub gr_send_push: CostOf<CallsAmount>,
181
182 pub gr_send_push_per_byte: CostOf<BytesAmount>,
184
185 pub gr_send_commit: CostOf<CallsAmount>,
187
188 pub gr_send_commit_wgas: CostOf<CallsAmount>,
190
191 pub gr_reservation_send: CostOf<CallsAmount>,
193
194 pub gr_reservation_send_per_byte: CostOf<BytesAmount>,
196
197 pub gr_reservation_send_commit: CostOf<CallsAmount>,
199
200 pub gr_send_input: CostOf<CallsAmount>,
202
203 pub gr_send_input_wgas: CostOf<CallsAmount>,
205
206 pub gr_send_push_input: CostOf<CallsAmount>,
208
209 pub gr_send_push_input_per_byte: CostOf<BytesAmount>,
211
212 pub gr_reply: CostOf<CallsAmount>,
214
215 pub gr_reply_per_byte: CostOf<BytesAmount>,
217
218 pub gr_reply_wgas: CostOf<CallsAmount>,
220
221 pub gr_reply_wgas_per_byte: CostOf<BytesAmount>,
223
224 pub gr_reply_commit: CostOf<CallsAmount>,
226
227 pub gr_reply_commit_wgas: CostOf<CallsAmount>,
229
230 pub gr_reservation_reply: CostOf<CallsAmount>,
232
233 pub gr_reservation_reply_per_byte: CostOf<BytesAmount>,
235
236 pub gr_reservation_reply_commit: CostOf<CallsAmount>,
238
239 pub gr_reply_push: CostOf<CallsAmount>,
241
242 pub gr_reply_push_per_byte: CostOf<BytesAmount>,
244
245 pub gr_reply_input: CostOf<CallsAmount>,
247
248 pub gr_reply_input_wgas: CostOf<CallsAmount>,
250
251 pub gr_reply_push_input: CostOf<CallsAmount>,
253
254 pub gr_reply_push_input_per_byte: CostOf<BytesAmount>,
256
257 pub gr_reply_to: CostOf<CallsAmount>,
259
260 pub gr_signal_code: CostOf<CallsAmount>,
262
263 pub gr_signal_from: CostOf<CallsAmount>,
265
266 pub gr_debug: CostOf<CallsAmount>,
268
269 pub gr_debug_per_byte: CostOf<BytesAmount>,
271
272 pub gr_reply_code: CostOf<CallsAmount>,
274
275 pub gr_exit: CostOf<CallsAmount>,
277
278 pub gr_leave: CostOf<CallsAmount>,
280
281 pub gr_wait: CostOf<CallsAmount>,
283
284 pub gr_wait_for: CostOf<CallsAmount>,
286
287 pub gr_wait_up_to: CostOf<CallsAmount>,
289
290 pub gr_wake: CostOf<CallsAmount>,
292
293 pub gr_create_program: CostOf<CallsAmount>,
295
296 pub gr_create_program_payload_per_byte: CostOf<BytesAmount>,
298
299 pub gr_create_program_salt_per_byte: CostOf<BytesAmount>,
301
302 pub gr_create_program_wgas: CostOf<CallsAmount>,
304
305 pub gr_create_program_wgas_payload_per_byte: CostOf<BytesAmount>,
307
308 pub gr_create_program_wgas_salt_per_byte: CostOf<BytesAmount>,
310}
311
312#[derive(Debug, Copy, Clone)]
314pub enum CostToken {
315 Null,
317 Alloc,
319 Free,
321 FreeRange,
323 ReserveGas,
325 UnreserveGas,
327 SystemReserveGas,
329 GasAvailable,
331 MsgId,
333 ActorId,
335 Source,
337 Value,
339 ValueAvailable,
341 Size,
343 Read,
345 EnvVars,
347 BlockHeight,
349 BlockTimestamp,
351 Random,
353 ReplyDeposit,
355 Send(BytesAmount),
357 SendWGas(BytesAmount),
359 SendInit,
361 SendPush(BytesAmount),
363 SendCommit,
365 SendCommitWGas,
367 ReservationSend(BytesAmount),
369 ReservationSendCommit,
371 SendInput,
373 SendInputWGas,
375 SendPushInput,
377 Reply(BytesAmount),
379 ReplyWGas(BytesAmount),
381 ReplyPush(BytesAmount),
383 ReplyCommit,
385 ReplyCommitWGas,
387 ReservationReply(BytesAmount),
389 ReservationReplyCommit,
391 ReplyInput,
393 ReplyInputWGas,
395 ReplyPushInput,
397 ReplyTo,
399 SignalCode,
401 SignalFrom,
403 Debug(BytesAmount),
405 ReplyCode,
407 Exit,
409 Leave,
411 Wait,
413 WaitFor,
415 WaitUpTo,
417 Wake,
419 CreateProgram(BytesAmount, BytesAmount),
421 CreateProgramWGas(BytesAmount, BytesAmount),
423}
424
425impl SyscallCosts {
426 pub fn cost_for_token(&self, token: CostToken) -> u64 {
428 use CostToken::*;
429
430 macro_rules! cost_with_per_byte {
431 ($name:ident, $len:expr) => {
432 paste! {
433 self.$name.with_bytes(self.[< $name _per_byte >], $len)
434 }
435 };
436 }
437
438 match token {
439 Null => 0,
440 Alloc => self.alloc.cost_for_one(),
441 Free => self.free.cost_for_one(),
442 FreeRange => self.free_range.cost_for_one(),
443 ReserveGas => self.gr_reserve_gas.cost_for_one(),
444 UnreserveGas => self.gr_unreserve_gas.cost_for_one(),
445 SystemReserveGas => self.gr_system_reserve_gas.cost_for_one(),
446 GasAvailable => self.gr_gas_available.cost_for_one(),
447 MsgId => self.gr_message_id.cost_for_one(),
448 ActorId => self.gr_program_id.cost_for_one(),
449 Source => self.gr_source.cost_for_one(),
450 Value => self.gr_value.cost_for_one(),
451 ValueAvailable => self.gr_value_available.cost_for_one(),
452 Size => self.gr_size.cost_for_one(),
453 Read => self.gr_read.cost_for_one(),
454 EnvVars => self.gr_env_vars.cost_for_one(),
455 BlockHeight => self.gr_block_height.cost_for_one(),
456 BlockTimestamp => self.gr_block_timestamp.cost_for_one(),
457 Random => self.gr_random.cost_for_one(),
458 ReplyDeposit => self.gr_reply_deposit.cost_for_one(),
459 Send(len) => cost_with_per_byte!(gr_send, len),
460 SendWGas(len) => cost_with_per_byte!(gr_send_wgas, len),
461 SendInit => self.gr_send_init.cost_for_one(),
462 SendPush(len) => cost_with_per_byte!(gr_send_push, len),
463 SendCommit => self.gr_send_commit.cost_for_one(),
464 SendCommitWGas => self.gr_send_commit_wgas.cost_for_one(),
465 ReservationSend(len) => cost_with_per_byte!(gr_reservation_send, len),
466 ReservationSendCommit => self.gr_reservation_send_commit.cost_for_one(),
467 SendInput => self.gr_send_input.cost_for_one(),
468 SendInputWGas => self.gr_send_input_wgas.cost_for_one(),
469 SendPushInput => self.gr_send_push_input.cost_for_one(),
470 Reply(len) => cost_with_per_byte!(gr_reply, len),
471 ReplyWGas(len) => cost_with_per_byte!(gr_reply_wgas, len),
472 ReplyPush(len) => cost_with_per_byte!(gr_reply_push, len),
473 ReplyCommit => self.gr_reply_commit.cost_for_one(),
474 ReplyCommitWGas => self.gr_reply_commit_wgas.cost_for_one(),
475 ReservationReply(len) => cost_with_per_byte!(gr_reservation_reply, len),
476 ReservationReplyCommit => self.gr_reservation_reply_commit.cost_for_one(),
477 ReplyInput => self.gr_reply_input.cost_for_one(),
478 ReplyInputWGas => self.gr_reply_input_wgas.cost_for_one(),
479 ReplyPushInput => self.gr_reply_push_input.cost_for_one(),
480 ReplyTo => self.gr_reply_to.cost_for_one(),
481 SignalCode => self.gr_signal_code.cost_for_one(),
482 SignalFrom => self.gr_signal_from.cost_for_one(),
483 Debug(len) => cost_with_per_byte!(gr_debug, len),
484 ReplyCode => self.gr_reply_code.cost_for_one(),
485 Exit => self.gr_exit.cost_for_one(),
486 Leave => self.gr_leave.cost_for_one(),
487 Wait => self.gr_wait.cost_for_one(),
488 WaitFor => self.gr_wait_for.cost_for_one(),
489 WaitUpTo => self.gr_wait_up_to.cost_for_one(),
490 Wake => self.gr_wake.cost_for_one(),
491 CreateProgram(payload, salt) => CostOf::from(
492 self.gr_create_program
493 .with_bytes(self.gr_create_program_payload_per_byte, payload),
494 )
495 .with_bytes(self.gr_create_program_salt_per_byte, salt),
496 CreateProgramWGas(payload, salt) => CostOf::from(
497 self.gr_create_program_wgas
498 .with_bytes(self.gr_create_program_wgas_payload_per_byte, payload),
499 )
500 .with_bytes(self.gr_create_program_wgas_salt_per_byte, salt),
501 }
502 }
503}
504
505#[derive(Debug, Default, Clone, PartialEq, Eq)]
507pub struct PagesCosts {
508 pub load_page_data: CostOf<GearPagesAmount>,
510 pub upload_page_data: CostOf<GearPagesAmount>,
512 pub mem_grow: CostOf<GearPagesAmount>,
514 pub mem_grow_per_page: CostOf<GearPagesAmount>,
516 pub parachain_read_heuristic: CostOf<GearPagesAmount>,
518}
519
520#[derive(Debug, Default, Clone, PartialEq, Eq)]
522pub struct LazyPagesCosts {
523 pub signal_read: CostOf<GearPagesAmount>,
525 pub signal_write: CostOf<GearPagesAmount>,
527 pub signal_write_after_read: CostOf<GearPagesAmount>,
529 pub host_func_read: CostOf<GearPagesAmount>,
531 pub host_func_write: CostOf<GearPagesAmount>,
533 pub host_func_write_after_read: CostOf<GearPagesAmount>,
535 pub load_page_storage_data: CostOf<GearPagesAmount>,
537}
538
539#[derive(Debug, Default, Clone, PartialEq, Eq)]
541pub struct IoCosts {
542 pub common: PagesCosts,
544 pub lazy_pages: LazyPagesCosts,
546}
547
548#[derive(Debug, Default, Clone, PartialEq, Eq)]
550pub struct RentCosts {
551 pub waitlist: CostOf<BlocksAmount>,
553 pub dispatch_stash: CostOf<BlocksAmount>,
555 pub reservation: CostOf<BlocksAmount>,
557}
558
559#[derive(Debug, Default, Clone, PartialEq, Eq)]
561pub struct ExtCosts {
562 pub syscalls: SyscallCosts,
564 pub rent: RentCosts,
566 pub mem_grow: CostOf<CallsAmount>,
568 pub mem_grow_per_page: CostOf<WasmPagesAmount>,
570}
571
572#[derive(Debug, Default, Clone, PartialEq, Eq)]
574pub struct InstantiationCosts {
575 pub code_section_per_byte: CostOf<BytesAmount>,
577 pub data_section_per_byte: CostOf<BytesAmount>,
579 pub global_section_per_byte: CostOf<BytesAmount>,
581 pub table_section_per_byte: CostOf<BytesAmount>,
583 pub element_section_per_byte: CostOf<BytesAmount>,
585 pub type_section_per_byte: CostOf<BytesAmount>,
587}
588
589#[derive(Clone, Debug, Default, PartialEq, Eq)]
591pub struct DbCosts {
592 pub read: CostOf<CallsAmount>,
594 pub read_per_byte: CostOf<BytesAmount>,
596 pub write: CostOf<CallsAmount>,
598 pub write_per_byte: CostOf<BytesAmount>,
600}
601
602#[derive(Clone, Debug, Default, PartialEq, Eq)]
604pub struct InstrumentationCosts {
605 pub base: CostOf<CallsAmount>,
607 pub per_byte: CostOf<BytesAmount>,
609}
610
611#[derive(Clone, Debug, Default, PartialEq, Eq)]
613pub struct ProcessCosts {
614 pub ext: ExtCosts,
616 pub lazy_pages: LazyPagesCosts,
618 pub instantiation: InstantiationCosts,
620 pub db: DbCosts,
622 pub instrumentation: InstrumentationCosts,
624 pub load_allocations_per_interval: CostOf<u32>,
626}