revm_bytecode/
eof.rs

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