Skip to main content

solana_syscalls/
logging.rs

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