Skip to main content

solana_syscalls/
logging.rs

1use {
2    super::*, solana_program_runtime::memory::translate_vm_slice, solana_sbpf::vm::ContextObject,
3};
4
5/// Log a user's info message
6pub struct SyscallLog {}
7impl BuiltinFunctionDefinition<InvokeContext<'_, '_>> for SyscallLog {
8    type Error = Error;
9    fn rust(
10        invoke_context: &mut InvokeContext<'_, '_>,
11        addr: u64,
12        len: u64,
13        _arg3: u64,
14        _arg4: u64,
15        _arg5: u64,
16    ) -> Result<u64, Error> {
17        let cost = invoke_context
18            .get_execution_cost()
19            .syscall_base_cost
20            .max(len);
21        invoke_context.compute_meter.consume_checked(cost)?;
22
23        let check_aligned = invoke_context.get_check_aligned();
24        let memory_mapping = invoke_context.memory_contexts.memory_mapping()?;
25        translate_string_and_do(
26            memory_mapping,
27            addr,
28            len,
29            check_aligned,
30            &mut |string: &str| {
31                stable_log::program_log(&invoke_context.get_log_collector(), string);
32                Ok(0)
33            },
34        )?;
35        Ok(0)
36    }
37}
38
39/// Log 5 64-bit values
40pub struct SyscallLogU64 {}
41impl BuiltinFunctionDefinition<InvokeContext<'_, '_>> for SyscallLogU64 {
42    type Error = Error;
43    fn rust(
44        invoke_context: &mut InvokeContext<'_, '_>,
45        arg1: u64,
46        arg2: u64,
47        arg3: u64,
48        arg4: u64,
49        arg5: u64,
50    ) -> Result<u64, Error> {
51        let cost = invoke_context.get_execution_cost().log_64_units;
52        invoke_context.compute_meter.consume_checked(cost)?;
53
54        stable_log::program_log(
55            &invoke_context.get_log_collector(),
56            &format!("{arg1:#x}, {arg2:#x}, {arg3:#x}, {arg4:#x}, {arg5:#x}"),
57        );
58        Ok(0)
59    }
60}
61
62/// Log current compute consumption
63pub struct SyscallLogBpfComputeUnits {}
64impl BuiltinFunctionDefinition<InvokeContext<'_, '_>> for SyscallLogBpfComputeUnits {
65    type Error = Error;
66    fn rust(
67        invoke_context: &mut InvokeContext<'_, '_>,
68        _arg1: u64,
69        _arg2: u64,
70        _arg3: u64,
71        _arg4: u64,
72        _arg5: u64,
73    ) -> Result<u64, Error> {
74        let cost = invoke_context.get_execution_cost().syscall_base_cost;
75        invoke_context.compute_meter.consume_checked(cost)?;
76
77        ic_logger_msg!(
78            invoke_context.get_log_collector(),
79            "Program consumption: {} units remaining",
80            invoke_context.get_remaining(),
81        );
82        Ok(0)
83    }
84}
85
86/// Log a [`Pubkey`] as a base58 string
87pub struct SyscallLogPubkey {}
88impl BuiltinFunctionDefinition<InvokeContext<'_, '_>> for SyscallLogPubkey {
89    type Error = Error;
90    fn rust(
91        invoke_context: &mut InvokeContext<'_, '_>,
92        pubkey_addr: u64,
93        _arg2: u64,
94        _arg3: u64,
95        _arg4: u64,
96        _arg5: u64,
97    ) -> Result<u64, Error> {
98        let cost = invoke_context.get_execution_cost().log_pubkey_units;
99        invoke_context.compute_meter.consume_checked(cost)?;
100
101        let check_aligned = invoke_context.get_check_aligned();
102        let memory_mapping = invoke_context.memory_contexts.memory_mapping()?;
103        let pubkey = translate_type::<Pubkey>(memory_mapping, pubkey_addr, check_aligned)?;
104        stable_log::program_log(&invoke_context.get_log_collector(), &pubkey.to_string());
105        Ok(0)
106    }
107}
108
109/// Log data handling
110pub struct SyscallLogData {}
111impl BuiltinFunctionDefinition<InvokeContext<'_, '_>> for SyscallLogData {
112    type Error = Error;
113    fn rust(
114        invoke_context: &mut InvokeContext<'_, '_>,
115        addr: u64,
116        len: u64,
117        _arg3: u64,
118        _arg4: u64,
119        _arg5: u64,
120    ) -> Result<u64, Error> {
121        let execution_cost = invoke_context.get_execution_cost();
122
123        invoke_context
124            .compute_meter
125            .consume_checked(execution_cost.syscall_base_cost)?;
126
127        let check_aligned = invoke_context.get_check_aligned();
128        let memory_mapping = invoke_context.memory_contexts.memory_mapping()?;
129        let untranslated_fields =
130            translate_slice::<VmSlice<u8>>(memory_mapping, addr, len, check_aligned)?;
131
132        let cost = execution_cost
133            .syscall_base_cost
134            .saturating_mul(untranslated_fields.len() as u64);
135        invoke_context.compute_meter.consume_checked(cost)?;
136        let cost = untranslated_fields
137            .iter()
138            .fold(0u64, |total, e| total.saturating_add(e.len()));
139        invoke_context.compute_meter.consume_checked(cost)?;
140
141        let mut fields = Vec::with_capacity(untranslated_fields.len());
142
143        for untranslated_field in untranslated_fields {
144            fields.push(translate_vm_slice(
145                untranslated_field,
146                memory_mapping,
147                check_aligned,
148            )?);
149        }
150
151        let log_collector = invoke_context.get_log_collector();
152
153        stable_log::program_data(&log_collector, &fields);
154
155        Ok(0)
156    }
157}