solana_bpf_loader_program/syscalls/
logging.rs

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