solana_bpf_loader_program/syscalls/
logging.rs

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