Skip to main content

ethrex_levm/
debug.rs

1use crate::errors::InternalError;
2use ethrex_common::U256;
3
4/// Special constant for debugging. 0xFEDEBEBECAFEDECEBADA
5/// It has to match with the constant set in the Solidity contract for this purpose.
6pub const MAGIC_PRINT_OFFSET: U256 = U256([0xBEBECAFEDECEBADA, 0xFEDE, 0, 0]);
7
8#[derive(Default)]
9pub struct DebugMode {
10    pub enabled: bool,
11    /// Accumulates chunks of data to print in one byte array.
12    pub print_buffer: Vec<u8>,
13    /// When enabled, store what's read into the buffer. Print the whole buffer when disabling this.
14    pub print_mode: bool,
15}
16
17impl DebugMode {
18    pub fn disabled() -> Self {
19        Self {
20            enabled: false,
21            ..Default::default()
22        }
23    }
24
25    /// Returns true if the call resulted in a debug operation. False otherwise.
26    ///
27    /// Note: This function is marked cold because it is rarely called (in prod).
28    #[cold]
29    pub fn handle_debug(&mut self, offset: U256, value: U256) -> Result<bool, InternalError> {
30        if !self.enabled {
31            return Ok(false);
32        }
33
34        if offset == MAGIC_PRINT_OFFSET {
35            if !self.print_mode {
36                self.print_mode = true;
37            } else {
38                if let Ok(s) = std::str::from_utf8(&self.print_buffer) {
39                    println!("PRINTED -> {s}");
40                } else {
41                    // Theoretically this shouldn't happen but I'll leave this JIC.
42                    println!("PRINTED (failed) -> {:?}", self.print_buffer);
43                }
44                self.print_buffer.clear();
45                self.print_mode = false;
46            }
47
48            return Ok(true);
49        }
50
51        if self.print_mode {
52            // Accumulate chunks in buffer until there are no more chunks left, then print.
53            let to_print = value.to_big_endian();
54            self.print_buffer.extend_from_slice(&to_print);
55
56            return Ok(true);
57        }
58
59        Ok(false)
60    }
61}