revm_bytecode/
eof.rs

1//! EOF bytecode.
2//!
3//! Contains body, header and raw bytes.
4//!
5//! Also contains verification logic and pretty printer.
6mod body;
7mod code_info;
8mod decode_helpers;
9mod header;
10/// Pritty printer for the EOF bytecode. Enabled by `std` feature.
11pub mod printer;
12/// Verification logic for the EOF bytecode.
13pub mod verification;
14
15pub use body::EofBody;
16pub use code_info::CodeInfo;
17pub use header::{
18    EofHeader, CODE_SECTION_SIZE, CONTAINER_SECTION_SIZE, KIND_CODE, KIND_CODE_INFO,
19    KIND_CONTAINER, KIND_DATA, KIND_TERMINAL,
20};
21pub use verification::*;
22
23use core::cmp::min;
24use primitives::{b256, bytes, Bytes, B256};
25use std::{fmt, vec, vec::Vec};
26
27/// Hash of EF00 bytes that is used for EXTCODEHASH when called from legacy bytecode
28pub const EOF_MAGIC_HASH: B256 =
29    b256!("0x9dbf3648db8210552e9c4f75c6a1c3057c0ca432043bd648be15fe7be05646f5");
30
31/// EOF Magic in [u16] form
32pub const EOF_MAGIC: u16 = 0xEF00;
33
34/// EOF magic number in array form
35pub static EOF_MAGIC_BYTES: Bytes = bytes!("ef00");
36
37/// EVM Object Format (EOF) container
38///
39/// It consists of a header, body and the raw original bytes.
40#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
41#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
42pub struct Eof {
43    /// Header of the EOF container
44    pub header: EofHeader,
45    /// Body of the EOF container
46    pub body: EofBody,
47    /// Raw bytes of the EOF container. Chunks of raw Bytes are used in Body to reference
48    /// parts of code, data and container sections.
49    pub raw: Bytes,
50}
51
52impl Default for Eof {
53    fn default() -> Self {
54        let body = EofBody {
55            // Types section with zero inputs, zero outputs and zero max stack size.
56            code_info: vec![CodeInfo::default()],
57            code_section: vec![1],
58            // One code section with a STOP byte.
59            code: Bytes::from_static(&[0x00]),
60            code_offset: 0,
61            container_section: vec![],
62            data_section: Bytes::new(),
63            is_data_filled: true,
64        };
65        body.into_eof()
66    }
67}
68
69impl Eof {
70    /// Creates a new EOF container from the given body.
71    pub fn new(body: EofBody) -> Self {
72        body.into_eof()
73    }
74
75    /// Validates the EOF container.
76    pub fn validate(&self) -> Result<(), EofError> {
77        validate_eof(self)
78    }
79
80    /// Validates the raw EOF bytes.
81    pub fn validate_raw(bytes: Bytes) -> Result<Eof, EofError> {
82        validate_raw_eof(bytes)
83    }
84
85    /// Validates the EOF container with the given code type.   
86    pub fn validate_mode(&self, mode: CodeType) -> Result<(), EofError> {
87        validate_eof_inner(self, Some(mode))
88    }
89
90    /// Returns len of the header and body in bytes.
91    pub fn size(&self) -> usize {
92        self.header.size() + self.header.body_size()
93    }
94
95    /// Returns raw EOF bytes.
96    pub fn raw(&self) -> &Bytes {
97        &self.raw
98    }
99
100    /// Returns a slice of the raw bytes.
101    /// If offset is greater than the length of the raw bytes, an empty slice is returned.
102    /// If len is greater than the length of the raw bytes, the slice is truncated to the length of the raw bytes.
103    pub fn data_slice(&self, offset: usize, len: usize) -> &[u8] {
104        self.body
105            .data_section
106            .get(offset..)
107            .and_then(|bytes| bytes.get(..min(len, bytes.len())))
108            .unwrap_or(&[])
109    }
110
111    /// Returns a slice of the data section.
112    pub fn data(&self) -> &[u8] {
113        &self.body.data_section
114    }
115
116    /// Slow encodes EOF bytes.
117    pub fn encode_slow(&self) -> Bytes {
118        let mut buffer: Vec<u8> = Vec::with_capacity(self.size());
119        self.header.encode(&mut buffer);
120        self.body.encode(&mut buffer);
121        buffer.into()
122    }
123
124    /// Decodes EOF that have additional dangling bytes.
125    ///
126    /// Assume that data section is fully filled.
127    pub fn decode_dangling(mut raw: Bytes) -> Result<(Self, Bytes), EofDecodeError> {
128        let (header, _) = EofHeader::decode(&raw)?;
129        let eof_size = header.body_size() + header.size();
130        if eof_size > raw.len() {
131            return Err(EofDecodeError::MissingInput);
132        }
133        let dangling_data = raw.split_off(eof_size);
134        let body = EofBody::decode(&raw, &header)?;
135        Ok((Self { header, body, raw }, dangling_data))
136    }
137
138    /// Decodes EOF from raw bytes.
139    pub fn decode(raw: Bytes) -> Result<Self, EofDecodeError> {
140        let (header, _) = EofHeader::decode(&raw)?;
141        let body = EofBody::decode(&raw, &header)?;
142        Ok(Self { header, body, raw })
143    }
144}
145
146/// EOF decode errors
147#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
148#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
149pub enum EofDecodeError {
150    /// Short input while processing EOF
151    MissingInput,
152    /// Short body while processing EOF
153    MissingBodyWithoutData,
154    /// Body size is more than specified in the header
155    DanglingData,
156    /// Invalid code info data
157    InvalidCodeInfo,
158    /// Invalid code info input value
159    InvalidCodeInfoInputValue {
160        /// Number of inputs
161        value: u8,
162    },
163    /// Invalid code info input value
164    InvalidCodeInfoOutputValue {
165        /// Number of outputs
166        value: u8,
167    },
168    /// Invalid code info input value
169    InvalidCodeInfoMaxIncrementValue {
170        /// MaxIncrementValue
171        value: u16,
172    },
173    /// Invalid code info input value can't be greater than [`primitives::STACK_LIMIT`]
174    InvalidCodeInfoStackOverflow {
175        /// Number of inputs
176        inputs: u8,
177        /// Max stack increment
178        max_stack_increment: u16,
179    },
180    /// Invalid code info size
181    InvalidCodeInfoSize,
182    /// Invalid EOF magic number
183    InvalidEOFMagicNumber,
184    /// Invalid EOF version
185    InvalidEOFVersion,
186    /// Invalid number for types kind
187    InvalidTypesKind,
188    /// Invalid number for code kind
189    InvalidCodeKind,
190    /// Invalid terminal code
191    InvalidTerminalByte,
192    /// Invalid data kind
193    InvalidDataKind,
194    /// Invalid kind after code
195    InvalidKindAfterCode {
196        /// Invalid unexpected kind type.
197        invalid_kind: u8,
198    },
199    /// Mismatch of code and info sizes
200    MismatchCodeAndInfoSize,
201    /// There should be at least one size
202    NonSizes,
203    /// Missing size
204    ShortInputForSizes,
205    /// Size cant be zero
206    ZeroSize,
207    /// Invalid code number
208    TooManyCodeSections,
209    /// Invalid number of code sections
210    ZeroCodeSections,
211    /// Invalid container number
212    TooManyContainerSections,
213    /// Invalid initcode size
214    InvalidEOFSize,
215}
216
217impl fmt::Display for EofDecodeError {
218    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219        let s = match self {
220            Self::MissingInput => "Short input while processing EOF",
221            Self::MissingBodyWithoutData => "Short body while processing EOF",
222            Self::DanglingData => "Body size is more than specified in the header",
223            Self::InvalidCodeInfo => "Invalid types section data",
224            Self::InvalidCodeInfoInputValue { value } => {
225                return write!(f, "Invalid code info input value: {}", value);
226            }
227            Self::InvalidCodeInfoOutputValue { value } => {
228                return write!(f, "Invalid code info output value: {}", value);
229            }
230            Self::InvalidCodeInfoMaxIncrementValue { value } => {
231                return write!(f, "Invalid code info max increment value: {}", value);
232            }
233            Self::InvalidCodeInfoStackOverflow {
234                inputs,
235                max_stack_increment,
236            } => {
237                return write!(
238                    f,
239                    "Invalid code info stack overflow: inputs: {}, max_stack_increment: {}",
240                    inputs, max_stack_increment
241                );
242            }
243            Self::InvalidCodeInfoSize => "Invalid types section size",
244            Self::InvalidEOFMagicNumber => "Invalid EOF magic number",
245            Self::InvalidEOFVersion => "Invalid EOF version",
246            Self::InvalidTypesKind => "Invalid number for types kind",
247            Self::InvalidCodeKind => "Invalid number for code kind",
248            Self::InvalidTerminalByte => "Invalid terminal code",
249            Self::InvalidDataKind => "Invalid data kind",
250            Self::InvalidKindAfterCode { invalid_kind } => {
251                return write!(f, "Invalid kind after code: {}", invalid_kind);
252            }
253            Self::MismatchCodeAndInfoSize => "Mismatch of code and types sizes",
254            Self::NonSizes => "There should be at least one size",
255            Self::ShortInputForSizes => "Missing size",
256            Self::ZeroSize => "Size cant be zero",
257            Self::TooManyCodeSections => "Invalid code number",
258            Self::ZeroCodeSections => "Invalid number of code sections",
259            Self::TooManyContainerSections => "Invalid container number",
260            Self::InvalidEOFSize => "Invalid initcode size",
261        };
262        f.write_str(s)
263    }
264}
265
266impl core::error::Error for EofDecodeError {}
267
268#[cfg(test)]
269mod test {
270
271    use super::*;
272    use primitives::bytes;
273
274    #[test]
275    fn decode_eof() {
276        let bytes = bytes!("ef00010100040200010001ff00000000800000fe");
277        let eof = Eof::decode(bytes.clone()).unwrap();
278        assert_eq!(bytes, eof.encode_slow());
279    }
280
281    #[test]
282    fn decode_eof_dangling() {
283        //0xEF000101 | u16  | 0x02 | u16 | u16 * cnum | 0x03 | u16 | cnum* u32 | 0xff | u16 | 0x00
284        let test_cases = [
285            (
286                bytes!("ef00010100040200010001ff00000000800000fe"),
287                bytes!("010203"),
288                false,
289            ),
290            (
291                bytes!("ef00010100040200010001ff00000000800000fe"),
292                bytes!(""),
293                false,
294            ),
295            (
296                bytes!("ef00010100040200010001ff00000000800000"),
297                bytes!(""),
298                true,
299            ),
300        ];
301
302        for (eof_bytes, dangling_data, is_err) in test_cases {
303            let mut raw = eof_bytes.to_vec();
304            raw.extend(&dangling_data);
305            let raw = Bytes::from(raw);
306
307            let result = Eof::decode_dangling(raw.clone());
308            assert_eq!(result.is_err(), is_err);
309            if is_err {
310                continue;
311            }
312            let (decoded_eof, decoded_dangling) = result.unwrap();
313            assert_eq!(eof_bytes, decoded_eof.encode_slow());
314            assert_eq!(decoded_dangling, dangling_data);
315        }
316    }
317
318    #[test]
319    fn data_slice() {
320        //0xEF000101 | u16  | 0x02 | u16 | u16 * cnum | 0x03 | u16 | cnum* u32 | 0xff | u16 | 0x00
321        let bytes = bytes!("ef00010100040200010001ff00000000800000fe");
322        let mut eof = Eof::decode(bytes.clone()).unwrap();
323        eof.body.data_section = bytes!("01020304");
324        assert_eq!(eof.data_slice(0, 1), &[0x01]);
325        assert_eq!(eof.data_slice(0, 4), &[0x01, 0x02, 0x03, 0x04]);
326        assert_eq!(eof.data_slice(0, 5), &[0x01, 0x02, 0x03, 0x04]);
327        assert_eq!(eof.data_slice(1, 2), &[0x02, 0x03]);
328
329        const EMPTY: &[u8] = &[];
330        assert_eq!(eof.data_slice(10, 2), EMPTY);
331        assert_eq!(eof.data_slice(1, 0), EMPTY);
332        assert_eq!(eof.data_slice(10, 0), EMPTY);
333    }
334}