1use bytecode::{CodeType, Eof};
3use context_interface::LocalContextTr;
4use core::cell::RefCell;
5use primitives::{keccak256, Bytes, HashMap, B256};
6use std::{rc::Rc, vec::Vec};
7
8#[derive(Clone, Debug)]
10pub struct LocalContext {
11 pub initcode_mapping: HashMap<B256, Initcode>,
15 pub shared_memory_buffer: Rc<RefCell<Vec<u8>>>,
17}
18
19impl Default for LocalContext {
20 fn default() -> Self {
21 Self {
22 initcode_mapping: HashMap::default(),
23 shared_memory_buffer: Rc::new(RefCell::new(Vec::with_capacity(1024 * 4))),
24 }
25 }
26}
27
28impl LocalContextTr for LocalContext {
29 fn insert_initcodes(&mut self, initcodes: &[Bytes]) {
30 self.initcode_mapping = initcodes
31 .iter()
32 .map(|b| (keccak256(b), Initcode::new(b.clone())))
33 .collect();
34 }
35
36 fn clear(&mut self) {
37 self.initcode_mapping.clear();
38 unsafe { self.shared_memory_buffer.borrow_mut().set_len(0) };
40 }
41
42 fn get_validated_initcode(&mut self, hash: B256) -> Option<Bytes> {
43 let initcode = self.initcode_mapping.get_mut(&hash)?;
44 initcode.validate().cloned()
45 }
46
47 fn shared_memory_buffer(&mut self) -> &Rc<RefCell<Vec<u8>>> {
48 &self.shared_memory_buffer
49 }
50}
51
52impl LocalContext {
53 pub fn new(initcode: &[Bytes]) -> Self {
55 let mut s = Self::default();
56 s.insert_initcodes(initcode);
57 s
58 }
59}
60
61#[derive(Clone, Debug, PartialEq, Eq)]
63pub enum InitcodeStatus {
64 Valid,
66 Invalid,
68 PendingValidation,
70}
71
72#[derive(Clone, Debug)]
74pub struct Initcode {
75 bytes: Bytes,
77 status: InitcodeStatus,
79}
80
81impl Initcode {
82 pub fn new(initcode: Bytes) -> Self {
84 Self {
85 bytes: initcode,
86 status: InitcodeStatus::PendingValidation,
87 }
88 }
89
90 pub fn validate(&mut self) -> Option<&Bytes> {
94 match self.status {
95 InitcodeStatus::Valid => return Some(&self.bytes),
96 InitcodeStatus::Invalid => return None,
97 InitcodeStatus::PendingValidation => (),
98 }
99
100 let Ok(eof) = Eof::decode(self.bytes.clone()) else {
102 self.status = InitcodeStatus::Invalid;
103 return None;
104 };
105
106 if eof.validate_mode(CodeType::Initcode).is_err() {
108 self.status = InitcodeStatus::Invalid;
109 return None;
110 }
111 self.status = InitcodeStatus::Valid;
113 Some(&self.bytes)
114 }
115}