1use revm::bytecode::{Bytecode, opcode::OPCODE_INFO};
2
3#[derive(Debug)]
4pub struct Stats {
5 pub byte_len: usize,
6 pub opcode_count: usize,
7 pub max_stack_depth: usize,
8}
9
10#[derive(Debug)]
11pub enum StatsError {
12 UnknownOpcode(u8),
13}
14
15impl std::fmt::Display for StatsError {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 match self {
18 StatsError::UnknownOpcode(opcode) => {
19 write!(f, "Unknown opcode: 0x{opcode:02x}")
20 }
21 }
22 }
23}
24
25impl std::error::Error for StatsError {}
26
27pub fn compute_stats(bytecode: &Bytecode) -> Result<Stats, StatsError> {
28 let opcode_count = compute_opcode_count(bytecode);
30
31 let byte_len = get_byte_len(bytecode);
33
34 let max_stack_depth = compute_max_stack_depth(bytecode)?;
36
37 Ok(Stats {
38 byte_len,
39 opcode_count,
40 max_stack_depth,
41 })
42}
43
44fn compute_opcode_count(bytecode: &Bytecode) -> usize {
45 let iter = bytecode.iter_opcodes();
46 iter.count()
47}
48
49fn get_byte_len(bytecode: &Bytecode) -> usize {
50 bytecode.bytecode().as_ref().len()
51}
52
53fn compute_max_stack_depth(bytecode: &Bytecode) -> Result<usize, StatsError> {
54 let mut iter = bytecode.iter_opcodes();
55 let mut max_depth: i32 = 0;
56 let mut depth: i32 = 0;
57
58 while let Some(opcode) = iter.peek_opcode() {
59 let opcode_info = OPCODE_INFO[opcode.get() as usize];
60
61 match opcode_info {
62 Some(opcode_info) => {
63 depth += opcode_info.io_diff() as i32;
64 }
65 None => {
66 return Err(StatsError::UnknownOpcode(opcode.get()));
68 }
69 }
70
71 max_depth = max_depth.max(depth);
72 iter.next();
73 }
74
75 Ok(max_depth as usize)
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 use revm::primitives::Bytes;
82
83 #[test]
84 fn test_simple_bytecode_stats() {
85 let bytes = hex::decode("60FF00").unwrap();
87 let bytecode = Bytecode::new_raw_checked(Bytes::from(bytes)).unwrap();
88
89 let stats = compute_stats(&bytecode).unwrap();
90 assert_eq!(stats.byte_len, 3);
91 assert_eq!(stats.opcode_count, 2);
92 assert_eq!(stats.max_stack_depth, 1); }
94
95 #[test]
96 fn test_complex_bytecode_stats() {
97 let bytes = hex::decode("600160020100").unwrap();
99 let bytecode = Bytecode::new_raw_checked(Bytes::from(bytes)).unwrap();
100
101 let stats = compute_stats(&bytecode).unwrap();
102 assert_eq!(stats.byte_len, 6);
103 assert_eq!(stats.opcode_count, 4);
104 assert_eq!(stats.max_stack_depth, 2); }
106
107 #[test]
108 fn test_stack_operations() {
109 let bytes = hex::decode("6001600280900100").unwrap();
111 let bytecode = Bytecode::new_raw_checked(Bytes::from(bytes)).unwrap();
112
113 let stats = compute_stats(&bytecode).unwrap();
114 assert_eq!(stats.byte_len, 8);
115 assert_eq!(stats.opcode_count, 6);
116 assert_eq!(stats.max_stack_depth, 3); }
118
119 #[test]
120 fn test_memory_operations() {
121 let bytes = hex::decode("602060005260005100").unwrap();
123 let bytecode = Bytecode::new_raw_checked(Bytes::from(bytes)).unwrap();
124
125 let stats = compute_stats(&bytecode).unwrap();
126 assert_eq!(stats.byte_len, 9);
127 assert_eq!(stats.opcode_count, 6);
128 assert_eq!(stats.max_stack_depth, 2); }
130
131 #[test]
132 fn test_push_operations() {
133 let mut bytes = vec![0x60, 0xFF]; bytes.extend_from_slice(&[0x61, 0xAB, 0xCD]); bytes.push(0x7F); bytes.extend_from_slice(&[0xFF; 32]); bytes.push(0x00); let bytecode = Bytecode::new_raw_checked(Bytes::from(bytes)).unwrap();
141
142 let stats = compute_stats(&bytecode).unwrap();
143 assert_eq!(stats.byte_len, 39); assert_eq!(stats.opcode_count, 4);
145 assert_eq!(stats.max_stack_depth, 3); }
147
148 #[test]
149 fn test_arithmetic_operations() {
150 let bytes = hex::decode("600560030160020200").unwrap();
152 let bytecode = Bytecode::new_raw_checked(Bytes::from(bytes)).unwrap();
153
154 let stats = compute_stats(&bytecode).unwrap();
155 assert_eq!(stats.byte_len, 9);
156 assert_eq!(stats.opcode_count, 6);
157 assert_eq!(stats.max_stack_depth, 2); }
159
160 #[test]
161 fn test_single_opcode() {
162 let bytes = hex::decode("00").unwrap();
164 let bytecode = Bytecode::new_raw_checked(Bytes::from(bytes)).unwrap();
165
166 let stats = compute_stats(&bytecode).unwrap();
167 assert_eq!(stats.byte_len, 1);
168 assert_eq!(stats.opcode_count, 1);
169 assert_eq!(stats.max_stack_depth, 0); }
171
172 #[test]
173 fn test_large_bytecode() {
174 let mut bytes = Vec::new();
176
177 for i in 0..20 {
179 bytes.push(0x60); bytes.push(i as u8); }
182 bytes.push(0x00); let bytecode = Bytecode::new_raw_checked(Bytes::from(bytes)).unwrap();
185
186 let stats = compute_stats(&bytecode).unwrap();
187 assert_eq!(stats.byte_len, 41); assert_eq!(stats.opcode_count, 21); assert_eq!(stats.max_stack_depth, 20); }
191
192 #[test]
193 fn test_compute_opcode_count() {
194 let bytes = hex::decode("60FF61ABCD00").unwrap(); let bytecode = Bytecode::new_raw_checked(Bytes::from(bytes)).unwrap();
196
197 let count = compute_opcode_count(&bytecode);
198 assert_eq!(count, 3);
199 }
200
201 #[test]
202 fn test_get_byte_len() {
203 let bytes = hex::decode("60FF61ABCD00").unwrap();
204 let bytecode = Bytecode::new_raw_checked(Bytes::from(bytes)).unwrap();
205
206 let len = get_byte_len(&bytecode);
207 assert_eq!(len, 6);
208 }
209
210 #[test]
211 fn test_compute_max_stack_depth() {
212 let bytes = hex::decode("60FF00").unwrap(); let bytecode = Bytecode::new_raw_checked(Bytes::from(bytes)).unwrap();
214
215 let depth = compute_max_stack_depth(&bytecode).unwrap();
216 assert_eq!(depth, 1);
217 }
218
219 #[test]
220 fn test_zero_stack_depth() {
221 let bytes = hex::decode("00").unwrap(); let bytecode = Bytecode::new_raw_checked(Bytes::from(bytes)).unwrap();
223
224 let depth = compute_max_stack_depth(&bytecode).unwrap();
225 assert_eq!(depth, 0);
226 }
227
228 #[test]
229 fn test_error_display() {
230 let error = StatsError::UnknownOpcode(0xFF);
231 assert_eq!(format!("{}", error), "Unknown opcode: 0xff");
232 }
233
234 #[test]
235 fn test_stats_struct_access() {
236 let stats = Stats {
237 byte_len: 10,
238 opcode_count: 5,
239 max_stack_depth: 3,
240 };
241
242 assert_eq!(stats.byte_len, 10);
243 assert_eq!(stats.opcode_count, 5);
244 assert_eq!(stats.max_stack_depth, 3);
245 }
246}