revm_primitives/bytecode/
eof.rs

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