1use crate::pages::{GearPagesAmount, WasmPagesAmount};
7use core::{fmt::Debug, marker::PhantomData};
8use paste::paste;
9
10#[derive(Clone, Copy, PartialEq, Eq)]
12pub struct CostOf<T> {
13 cost: u64,
14 _phantom: PhantomData<T>,
15}
16
17impl<T> CostOf<T> {
18 pub const fn new(cost: u64) -> Self {
20 Self {
21 cost,
22 _phantom: PhantomData,
23 }
24 }
25
26 pub const fn cost_for_one(&self) -> u64 {
28 self.cost
29 }
30}
31
32impl<T: Into<u32>> CostOf<T> {
33 pub fn cost_for(&self, num: T) -> u64 {
35 self.cost.saturating_mul(Into::<u32>::into(num).into())
36 }
37}
38
39impl<T> Debug for CostOf<T> {
40 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
41 f.write_fmt(format_args!("{}", &self.cost))
42 }
43}
44
45impl<T> From<u64> for CostOf<T> {
46 fn from(cost: u64) -> Self {
47 CostOf::new(cost)
48 }
49}
50
51impl<T> From<CostOf<T>> for u64 {
52 fn from(value: CostOf<T>) -> Self {
53 value.cost
54 }
55}
56
57impl<T> Default for CostOf<T> {
58 fn default() -> Self {
59 CostOf::new(0)
60 }
61}
62
63#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, derive_more::From, derive_more::Into)]
65pub struct CallsAmount(u32);
66
67impl CostOf<CallsAmount> {
68 pub fn with_bytes(&self, per_byte: CostOf<BytesAmount>, amount: BytesAmount) -> u64 {
70 self.cost_for_one()
71 .saturating_add(per_byte.cost_for(amount))
72 }
73}
74
75#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, derive_more::From, derive_more::Into)]
77pub struct BytesAmount(u32);
78
79#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, derive_more::From, derive_more::Into)]
81pub struct BlocksAmount(u32);
82
83#[derive(Debug, Clone, Default, PartialEq, Eq)]
85pub struct SyscallCosts {
86 pub alloc: CostOf<CallsAmount>,
88
89 pub free: CostOf<CallsAmount>,
91
92 pub free_range: CostOf<CallsAmount>,
94
95 pub free_range_per_page: CostOf<WasmPagesAmount>,
97
98 pub gr_reserve_gas: CostOf<CallsAmount>,
100
101 pub gr_unreserve_gas: CostOf<CallsAmount>,
103
104 pub gr_system_reserve_gas: CostOf<CallsAmount>,
106
107 pub gr_gas_available: CostOf<CallsAmount>,
109
110 pub gr_message_id: CostOf<CallsAmount>,
112
113 pub gr_program_id: CostOf<CallsAmount>,
115
116 pub gr_source: CostOf<CallsAmount>,
118
119 pub gr_value: CostOf<CallsAmount>,
121
122 pub gr_value_available: CostOf<CallsAmount>,
124
125 pub gr_size: CostOf<CallsAmount>,
127
128 pub gr_read: CostOf<CallsAmount>,
130
131 pub gr_read_per_byte: CostOf<BytesAmount>,
133
134 pub gr_env_vars: CostOf<CallsAmount>,
136
137 pub gr_block_height: CostOf<CallsAmount>,
139
140 pub gr_block_timestamp: CostOf<CallsAmount>,
142
143 pub gr_random: CostOf<CallsAmount>,
145
146 pub gr_reply_deposit: CostOf<CallsAmount>,
148
149 pub gr_send: CostOf<CallsAmount>,
151
152 pub gr_send_per_byte: CostOf<BytesAmount>,
154
155 pub gr_send_wgas: CostOf<CallsAmount>,
157
158 pub gr_send_wgas_per_byte: CostOf<BytesAmount>,
160
161 pub gr_send_init: CostOf<CallsAmount>,
163
164 pub gr_send_push: CostOf<CallsAmount>,
166
167 pub gr_send_push_per_byte: CostOf<BytesAmount>,
169
170 pub gr_send_commit: CostOf<CallsAmount>,
172
173 pub gr_send_commit_wgas: CostOf<CallsAmount>,
175
176 pub gr_reservation_send: CostOf<CallsAmount>,
178
179 pub gr_reservation_send_per_byte: CostOf<BytesAmount>,
181
182 pub gr_reservation_send_commit: CostOf<CallsAmount>,
184
185 pub gr_send_input: CostOf<CallsAmount>,
187
188 pub gr_send_input_wgas: CostOf<CallsAmount>,
190
191 pub gr_send_push_input: CostOf<CallsAmount>,
193
194 pub gr_send_push_input_per_byte: CostOf<BytesAmount>,
196
197 pub gr_reply: CostOf<CallsAmount>,
199
200 pub gr_reply_per_byte: CostOf<BytesAmount>,
202
203 pub gr_reply_wgas: CostOf<CallsAmount>,
205
206 pub gr_reply_wgas_per_byte: CostOf<BytesAmount>,
208
209 pub gr_reply_commit: CostOf<CallsAmount>,
211
212 pub gr_reply_commit_wgas: CostOf<CallsAmount>,
214
215 pub gr_reservation_reply: CostOf<CallsAmount>,
217
218 pub gr_reservation_reply_per_byte: CostOf<BytesAmount>,
220
221 pub gr_reservation_reply_commit: CostOf<CallsAmount>,
223
224 pub gr_reply_push: CostOf<CallsAmount>,
226
227 pub gr_reply_push_per_byte: CostOf<BytesAmount>,
229
230 pub gr_reply_input: CostOf<CallsAmount>,
232
233 pub gr_reply_input_wgas: CostOf<CallsAmount>,
235
236 pub gr_reply_push_input: CostOf<CallsAmount>,
238
239 pub gr_reply_push_input_per_byte: CostOf<BytesAmount>,
241
242 pub gr_reply_to: CostOf<CallsAmount>,
244
245 pub gr_signal_code: CostOf<CallsAmount>,
247
248 pub gr_signal_from: CostOf<CallsAmount>,
250
251 pub gr_debug: CostOf<CallsAmount>,
253
254 pub gr_debug_per_byte: CostOf<BytesAmount>,
256
257 pub gr_reply_code: CostOf<CallsAmount>,
259
260 pub gr_exit: CostOf<CallsAmount>,
262
263 pub gr_leave: CostOf<CallsAmount>,
265
266 pub gr_wait: CostOf<CallsAmount>,
268
269 pub gr_wait_for: CostOf<CallsAmount>,
271
272 pub gr_wait_up_to: CostOf<CallsAmount>,
274
275 pub gr_wake: CostOf<CallsAmount>,
277
278 pub gr_create_program: CostOf<CallsAmount>,
280
281 pub gr_create_program_payload_per_byte: CostOf<BytesAmount>,
283
284 pub gr_create_program_salt_per_byte: CostOf<BytesAmount>,
286
287 pub gr_create_program_wgas: CostOf<CallsAmount>,
289
290 pub gr_create_program_wgas_payload_per_byte: CostOf<BytesAmount>,
292
293 pub gr_create_program_wgas_salt_per_byte: CostOf<BytesAmount>,
295}
296
297#[derive(Debug, Copy, Clone)]
299pub enum CostToken {
300 Null,
302 Alloc,
304 Free,
306 FreeRange,
308 ReserveGas,
310 UnreserveGas,
312 SystemReserveGas,
314 GasAvailable,
316 MsgId,
318 ActorId,
320 Source,
322 Value,
324 ValueAvailable,
326 Size,
328 Read,
330 EnvVars,
332 BlockHeight,
334 BlockTimestamp,
336 Random,
338 ReplyDeposit,
340 Send(BytesAmount),
342 SendWGas(BytesAmount),
344 SendInit,
346 SendPush(BytesAmount),
348 SendCommit,
350 SendCommitWGas,
352 ReservationSend(BytesAmount),
354 ReservationSendCommit,
356 SendInput,
358 SendInputWGas,
360 SendPushInput,
362 Reply(BytesAmount),
364 ReplyWGas(BytesAmount),
366 ReplyPush(BytesAmount),
368 ReplyCommit,
370 ReplyCommitWGas,
372 ReservationReply(BytesAmount),
374 ReservationReplyCommit,
376 ReplyInput,
378 ReplyInputWGas,
380 ReplyPushInput,
382 ReplyTo,
384 SignalCode,
386 SignalFrom,
388 Debug(BytesAmount),
390 ReplyCode,
392 Exit,
394 Leave,
396 Wait,
398 WaitFor,
400 WaitUpTo,
402 Wake,
404 CreateProgram(BytesAmount, BytesAmount),
406 CreateProgramWGas(BytesAmount, BytesAmount),
408}
409
410impl SyscallCosts {
411 pub fn cost_for_token(&self, token: CostToken) -> u64 {
413 use CostToken::*;
414
415 macro_rules! cost_with_per_byte {
416 ($name:ident, $len:expr) => {
417 paste! {
418 self.$name.with_bytes(self.[< $name _per_byte >], $len)
419 }
420 };
421 }
422
423 match token {
424 Null => 0,
425 Alloc => self.alloc.cost_for_one(),
426 Free => self.free.cost_for_one(),
427 FreeRange => self.free_range.cost_for_one(),
428 ReserveGas => self.gr_reserve_gas.cost_for_one(),
429 UnreserveGas => self.gr_unreserve_gas.cost_for_one(),
430 SystemReserveGas => self.gr_system_reserve_gas.cost_for_one(),
431 GasAvailable => self.gr_gas_available.cost_for_one(),
432 MsgId => self.gr_message_id.cost_for_one(),
433 ActorId => self.gr_program_id.cost_for_one(),
434 Source => self.gr_source.cost_for_one(),
435 Value => self.gr_value.cost_for_one(),
436 ValueAvailable => self.gr_value_available.cost_for_one(),
437 Size => self.gr_size.cost_for_one(),
438 Read => self.gr_read.cost_for_one(),
439 EnvVars => self.gr_env_vars.cost_for_one(),
440 BlockHeight => self.gr_block_height.cost_for_one(),
441 BlockTimestamp => self.gr_block_timestamp.cost_for_one(),
442 Random => self.gr_random.cost_for_one(),
443 ReplyDeposit => self.gr_reply_deposit.cost_for_one(),
444 Send(len) => cost_with_per_byte!(gr_send, len),
445 SendWGas(len) => cost_with_per_byte!(gr_send_wgas, len),
446 SendInit => self.gr_send_init.cost_for_one(),
447 SendPush(len) => cost_with_per_byte!(gr_send_push, len),
448 SendCommit => self.gr_send_commit.cost_for_one(),
449 SendCommitWGas => self.gr_send_commit_wgas.cost_for_one(),
450 ReservationSend(len) => cost_with_per_byte!(gr_reservation_send, len),
451 ReservationSendCommit => self.gr_reservation_send_commit.cost_for_one(),
452 SendInput => self.gr_send_input.cost_for_one(),
453 SendInputWGas => self.gr_send_input_wgas.cost_for_one(),
454 SendPushInput => self.gr_send_push_input.cost_for_one(),
455 Reply(len) => cost_with_per_byte!(gr_reply, len),
456 ReplyWGas(len) => cost_with_per_byte!(gr_reply_wgas, len),
457 ReplyPush(len) => cost_with_per_byte!(gr_reply_push, len),
458 ReplyCommit => self.gr_reply_commit.cost_for_one(),
459 ReplyCommitWGas => self.gr_reply_commit_wgas.cost_for_one(),
460 ReservationReply(len) => cost_with_per_byte!(gr_reservation_reply, len),
461 ReservationReplyCommit => self.gr_reservation_reply_commit.cost_for_one(),
462 ReplyInput => self.gr_reply_input.cost_for_one(),
463 ReplyInputWGas => self.gr_reply_input_wgas.cost_for_one(),
464 ReplyPushInput => self.gr_reply_push_input.cost_for_one(),
465 ReplyTo => self.gr_reply_to.cost_for_one(),
466 SignalCode => self.gr_signal_code.cost_for_one(),
467 SignalFrom => self.gr_signal_from.cost_for_one(),
468 Debug(len) => cost_with_per_byte!(gr_debug, len),
469 ReplyCode => self.gr_reply_code.cost_for_one(),
470 Exit => self.gr_exit.cost_for_one(),
471 Leave => self.gr_leave.cost_for_one(),
472 Wait => self.gr_wait.cost_for_one(),
473 WaitFor => self.gr_wait_for.cost_for_one(),
474 WaitUpTo => self.gr_wait_up_to.cost_for_one(),
475 Wake => self.gr_wake.cost_for_one(),
476 CreateProgram(payload, salt) => CostOf::from(
477 self.gr_create_program
478 .with_bytes(self.gr_create_program_payload_per_byte, payload),
479 )
480 .with_bytes(self.gr_create_program_salt_per_byte, salt),
481 CreateProgramWGas(payload, salt) => CostOf::from(
482 self.gr_create_program_wgas
483 .with_bytes(self.gr_create_program_wgas_payload_per_byte, payload),
484 )
485 .with_bytes(self.gr_create_program_wgas_salt_per_byte, salt),
486 }
487 }
488}
489
490#[derive(Debug, Default, Clone, PartialEq, Eq)]
492pub struct PagesCosts {
493 pub load_page_data: CostOf<GearPagesAmount>,
495 pub upload_page_data: CostOf<GearPagesAmount>,
497 pub mem_grow: CostOf<GearPagesAmount>,
499 pub mem_grow_per_page: CostOf<GearPagesAmount>,
501 pub parachain_read_heuristic: CostOf<GearPagesAmount>,
503}
504
505#[derive(Debug, Default, Clone, PartialEq, Eq)]
507pub struct LazyPagesCosts {
508 pub signal_read: CostOf<GearPagesAmount>,
510 pub signal_write: CostOf<GearPagesAmount>,
512 pub signal_write_after_read: CostOf<GearPagesAmount>,
514 pub host_func_read: CostOf<GearPagesAmount>,
516 pub host_func_write: CostOf<GearPagesAmount>,
518 pub host_func_write_after_read: CostOf<GearPagesAmount>,
520 pub load_page_storage_data: CostOf<GearPagesAmount>,
522}
523
524#[derive(Debug, Default, Clone, PartialEq, Eq)]
526pub struct IoCosts {
527 pub common: PagesCosts,
529 pub lazy_pages: LazyPagesCosts,
531}
532
533#[derive(Debug, Default, Clone, PartialEq, Eq)]
535pub struct RentCosts {
536 pub waitlist: CostOf<BlocksAmount>,
538 pub dispatch_stash: CostOf<BlocksAmount>,
540 pub reservation: CostOf<BlocksAmount>,
542}
543
544#[derive(Debug, Default, Clone, PartialEq, Eq)]
546pub struct ExtCosts {
547 pub syscalls: SyscallCosts,
549 pub rent: RentCosts,
551 pub mem_grow: CostOf<CallsAmount>,
553 pub mem_grow_per_page: CostOf<WasmPagesAmount>,
555}
556
557#[derive(Debug, Default, Clone, PartialEq, Eq)]
559pub struct InstantiationCosts {
560 pub code_section_per_byte: CostOf<BytesAmount>,
562 pub data_section_per_byte: CostOf<BytesAmount>,
564 pub global_section_per_byte: CostOf<BytesAmount>,
566 pub table_section_per_byte: CostOf<BytesAmount>,
568 pub element_section_per_byte: CostOf<BytesAmount>,
570 pub type_section_per_byte: CostOf<BytesAmount>,
572}
573
574#[derive(Clone, Debug, Default, PartialEq, Eq)]
576pub struct DbCosts {
577 pub read: CostOf<CallsAmount>,
579 pub read_per_byte: CostOf<BytesAmount>,
581 pub write: CostOf<CallsAmount>,
583 pub write_per_byte: CostOf<BytesAmount>,
585}
586
587#[derive(Clone, Debug, Default, PartialEq, Eq)]
589pub struct InstrumentationCosts {
590 pub base: CostOf<CallsAmount>,
592 pub per_byte: CostOf<BytesAmount>,
594}
595
596#[derive(Clone, Debug, Default, PartialEq, Eq)]
598pub struct ProcessCosts {
599 pub ext: ExtCosts,
601 pub lazy_pages: LazyPagesCosts,
603 pub instantiation: InstantiationCosts,
605 pub db: DbCosts,
607 pub instrumentation: InstrumentationCosts,
609 pub load_allocations_per_interval: CostOf<u32>,
611}