1mod body;
7mod code_info;
8mod decode_helpers;
9mod header;
10pub mod printer;
12pub 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
27pub const EOF_MAGIC_HASH: B256 =
29 b256!("0x9dbf3648db8210552e9c4f75c6a1c3057c0ca432043bd648be15fe7be05646f5");
30
31pub const EOF_MAGIC: u16 = 0xEF00;
33
34pub static EOF_MAGIC_BYTES: Bytes = bytes!("ef00");
36
37#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
41#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
42pub struct Eof {
43 pub header: EofHeader,
45 pub body: EofBody,
47 pub raw: Bytes,
50}
51
52impl Default for Eof {
53 fn default() -> Self {
54 let body = EofBody {
55 code_info: vec![CodeInfo::default()],
57 code_section: vec![1],
58 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 pub fn new(body: EofBody) -> Self {
72 body.into_eof()
73 }
74
75 pub fn validate(&self) -> Result<(), EofError> {
77 validate_eof(self)
78 }
79
80 pub fn validate_raw(bytes: Bytes) -> Result<Eof, EofError> {
82 validate_raw_eof(bytes)
83 }
84
85 pub fn validate_mode(&self, mode: CodeType) -> Result<(), EofError> {
87 validate_eof_inner(self, Some(mode))
88 }
89
90 pub fn size(&self) -> usize {
92 self.header.size() + self.header.body_size()
93 }
94
95 pub fn raw(&self) -> &Bytes {
97 &self.raw
98 }
99
100 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 pub fn data(&self) -> &[u8] {
113 &self.body.data_section
114 }
115
116 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 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 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#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
148#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
149pub enum EofDecodeError {
150 MissingInput,
152 MissingBodyWithoutData,
154 DanglingData,
156 InvalidCodeInfo,
158 InvalidCodeInfoInputValue {
160 value: u8,
162 },
163 InvalidCodeInfoOutputValue {
165 value: u8,
167 },
168 InvalidCodeInfoMaxIncrementValue {
170 value: u16,
172 },
173 InvalidCodeInfoStackOverflow {
175 inputs: u8,
177 max_stack_increment: u16,
179 },
180 InvalidCodeInfoSize,
182 InvalidEOFMagicNumber,
184 InvalidEOFVersion,
186 InvalidTypesKind,
188 InvalidCodeKind,
190 InvalidTerminalByte,
192 InvalidDataKind,
194 InvalidKindAfterCode {
196 invalid_kind: u8,
198 },
199 MismatchCodeAndInfoSize,
201 NonSizes,
203 ShortInputForSizes,
205 ZeroSize,
207 TooManyCodeSections,
209 ZeroCodeSections,
211 TooManyContainerSections,
213 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 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 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}