Skip to main content

yevm_core/
cache.rs

1use ahash::{AHashMap as HashMap, AHashSet as HashSet};
2
3use crate::{
4    call::Head,
5    chain::Fetched,
6    state::{Account, State},
7    trace::{Event, Target, Trace, filter},
8};
9use futures::channel::mpsc;
10use yevm_base::{Acc, Int, math::lift};
11use yevm_misc::buf::Buf;
12
13#[derive(Default)]
14struct Slot {
15    original: Int,
16    current: Int,
17}
18
19struct AccountEntry {
20    account: Account,
21    storage: HashMap<Int, Slot>,
22}
23
24impl AccountEntry {
25    fn new(account: Account) -> Self {
26        Self {
27            account,
28            storage: HashMap::new(),
29        }
30    }
31}
32
33impl Default for AccountEntry {
34    fn default() -> Self {
35        Self {
36            account: Account {
37                value: Int::ZERO,
38                nonce: Int::ZERO,
39                code: (vec![].into(), Int::ZERO),
40            },
41            storage: HashMap::new(),
42        }
43    }
44}
45
46enum Revert {
47    WarmAcc(Acc),
48    WarmKey(Acc, Int),
49    Store(Acc, Int, Int),
50    Nonce(Acc, Int),
51    Value(Acc, Int),
52    Temp(Acc, Int, Int),
53    Code(Acc, Int),
54    Create(Acc),
55    Delete(Acc),
56}
57
58#[derive(Default)]
59pub struct Cache {
60    accounts: HashMap<Acc, AccountEntry>,
61    transient: HashMap<(Acc, Int), Int>,
62    warm_accs: HashSet<Acc>,
63    warm_keys: HashSet<(Acc, Int)>,
64    created: HashSet<Acc>,
65    destroyed: HashSet<Acc>,
66    hash: HashMap<u64, Int>,
67    depth: usize,
68    pub logs: Vec<(Buf, Vec<Int>)>,
69    pub events: Vec<Trace>,
70    pub sender: Option<mpsc::Sender<Trace>>,
71    pub filter: u32,
72    pub fetched: Vec<Fetched>,
73    pub index: usize,
74    offline: bool,
75    chain_id: u64,
76}
77
78impl Cache {
79    pub fn new() -> Self {
80        Self::default()
81    }
82
83    pub fn with_sender(sender: mpsc::Sender<Trace>, filter: u32) -> Self {
84        Self {
85            sender: Some(sender),
86            filter,
87            ..Self::default()
88        }
89    }
90
91    pub fn insert_account(&mut self, addr: Acc, account: Account) {
92        let entry = self.accounts.entry(addr).or_default();
93        entry.account = account;
94    }
95
96    pub fn account(&self, addr: &Acc) -> Option<&Account> {
97        self.accounts.get(addr).map(|e| &e.account)
98    }
99
100    pub fn storage(&self, addr: &Acc, key: &Int) -> Option<Int> {
101        self.accounts.get(addr)?.storage.get(key).map(|s| s.current)
102    }
103
104    pub fn reset(&mut self) {
105        self.transient.clear();
106        self.warm_accs.clear();
107        self.warm_keys.clear();
108        self.created.clear();
109        self.destroyed.clear();
110        self.depth = 0;
111        self.logs.clear();
112        self.events.clear();
113
114        // TODO: FIXME: re-work original slot value tracking to avoid this
115        for (_, account) in self.accounts.iter_mut() {
116            for (_, slot) in account.storage.iter_mut() {
117                slot.original = slot.current;
118            }
119        }
120    }
121}
122
123impl State for Cache {
124    // Storage: returns (current, original)
125    fn get(&mut self, acc: &Acc, key: &Int) -> Option<(Int, Int)> {
126        let entry = self.accounts.get(acc)?;
127        let (cur, org) = entry.storage.get(key).map(|s| (s.current, s.original))?;
128        self.emit(Event::Get(Target::Store {
129            acc: *acc,
130            key: *key,
131            val: cur,
132        }));
133        Some((cur, org))
134    }
135
136    fn put(&mut self, acc: &Acc, key: &Int, val: Int) -> Option<Int> {
137        let entry = self.accounts.entry(*acc).or_default();
138        let slot = entry.storage.entry(*key).or_default();
139        let prev = slot.current;
140        slot.current = val;
141        self.emit(Event::Put(
142            Target::Store {
143                acc: *acc,
144                key: *key,
145                val: prev,
146            },
147            val,
148        ));
149        Some(prev)
150    }
151
152    fn init(&mut self, acc: &Acc, key: &Int, val: Int) {
153        let entry = self.accounts.entry(*acc).or_default();
154        entry.storage.insert(
155            *key,
156            Slot {
157                original: val,
158                current: val,
159            },
160        );
161    }
162
163    fn tget(&mut self, acc: &Acc, key: &Int) -> Option<Int> {
164        let val = self.transient.get(&(*acc, *key)).copied();
165        self.emit(Event::Get(Target::Temp {
166            acc: *acc,
167            key: *key,
168            val: val.unwrap_or_default(),
169        }));
170        val
171    }
172
173    fn tput(&mut self, acc: Acc, key: Int, val: Int) -> Option<Int> {
174        let prev = self.transient.insert((acc, key), val);
175        self.emit(Event::Put(
176            Target::Temp {
177                acc,
178                key,
179                val: prev.unwrap_or_default(),
180            },
181            val,
182        ));
183        prev
184    }
185
186    // Account mutations
187    fn inc_nonce(&mut self, acc: &Acc, by: Int) -> Int {
188        let (old, new) = {
189            let entry = self.accounts.entry(*acc).or_default();
190            let old = entry.account.nonce;
191            let f = lift(|[a, b]| a + b);
192            let new = f([old, by]);
193            entry.account.nonce = new;
194            (old, new)
195        };
196        self.emit(Event::Put(
197            Target::Nonce {
198                acc: *acc,
199                val: old,
200            },
201            new,
202        ));
203        new
204    }
205
206    fn set_value(&mut self, acc: &Acc, value: Int) -> Int {
207        let prev = {
208            let entry = self.accounts.entry(*acc).or_default();
209            let prev = entry.account.value;
210            entry.account.value = value;
211            prev
212        };
213        self.emit(Event::Put(
214            Target::Value {
215                acc: *acc,
216                val: prev,
217            },
218            value,
219        ));
220        prev
221    }
222
223    fn set_code(&mut self, acc: &Acc, code: Buf, hash: Int) -> Int {
224        let prev = {
225            let entry = self.accounts.entry(*acc).or_default();
226            let (_, prev) = entry.account.code;
227            entry.account.code = (code, hash);
228            prev
229        };
230        self.emit(Event::Put(
231            Target::Code {
232                acc: *acc,
233                hash: prev,
234            },
235            hash,
236        ));
237        // TODO: use code cache for by-hash lookups
238        prev
239    }
240
241    fn set_auth(&mut self, src: &Acc, dst: &Acc) {
242        let mut code = vec![0; 23];
243        // EIP-7702 delegation designator: 0xef0100 || address (20 bytes)
244        code[..3].copy_from_slice(&[0xEF, 0x01, 0x00]);
245        code[3..].copy_from_slice(dst.as_ref());
246        self.set_code(src, code.into(), Int::ZERO);
247    }
248
249    fn merge(&mut self, acc: &Acc, chain: Account) {
250        self.accounts.entry(*acc).or_default().account = chain;
251    }
252
253    fn balance(&mut self, acc: &Acc) -> Option<Int> {
254        let val = self.accounts.get(acc).map(|e| e.account.value);
255        self.emit(Event::Get(Target::Value {
256            acc: *acc,
257            val: val.unwrap_or_default(),
258        }));
259        val
260    }
261
262    fn nonce(&mut self, acc: &Acc) -> Option<Int> {
263        let val = self.accounts.get(acc).map(|e| e.account.nonce);
264        self.emit(Event::Get(Target::Nonce {
265            acc: *acc,
266            val: val.unwrap_or_default(),
267        }));
268        val
269    }
270
271    fn code(&mut self, acc: &Acc) -> Option<(Buf, Int)> {
272        let (code, hash) = self.accounts.get(acc).map(|e| e.account.code.clone())?;
273        self.emit(Event::Get(Target::Code { acc: *acc, hash }));
274        if !code.is_empty() {
275            self.emit(Event::Code(code.clone(), hash));
276        }
277        Some((code, hash))
278    }
279
280    fn acc(&mut self, acc: &Acc) -> Option<Account> {
281        self.accounts.get(acc).map(|e| Account {
282            value: e.account.value,
283            nonce: e.account.nonce,
284            code: e.account.code.clone(),
285        })
286    }
287
288    fn is_cold_acc(&self, acc: &Acc) -> bool {
289        !self.warm_accs.contains(acc)
290    }
291
292    fn is_cold_key(&self, acc: &Acc, key: &Int) -> bool {
293        !self.warm_keys.contains(&(*acc, *key))
294    }
295
296    fn warm_acc(&mut self, acc: &Acc) -> bool {
297        let cold = self.warm_accs.insert(*acc);
298        if cold {
299            self.emit(Event::WarmAcc(*acc));
300        }
301        cold
302    }
303
304    fn warm_key(&mut self, acc: &Acc, key: &Int) -> bool {
305        let cold = self.warm_keys.insert((*acc, *key));
306        if cold {
307            self.emit(Event::WarmKey(*acc, *key));
308        }
309        cold
310    }
311
312    fn create(&mut self, acc: Acc, info: Account) {
313        if !info.nonce.is_zero() {
314            self.emit(Event::Put(
315                Target::Nonce {
316                    acc,
317                    val: Int::ZERO,
318                },
319                info.nonce,
320            ));
321        }
322        if !info.value.is_zero() {
323            self.emit(Event::Put(
324                Target::Value {
325                    acc,
326                    val: Int::ZERO,
327                },
328                info.value,
329            ));
330        }
331        self.emit(Event::Create(acc));
332        self.accounts.insert(acc, AccountEntry::new(info));
333        self.created.insert(acc);
334    }
335
336    fn destroy(&mut self, acc: &Acc) {
337        self.destroyed.insert(*acc);
338        self.emit(Event::Delete(*acc));
339    }
340
341    fn created(&self) -> Vec<Acc> {
342        self.created.iter().cloned().collect()
343    }
344
345    fn destroyed(&self) -> Vec<Acc> {
346        self.destroyed.iter().cloned().collect()
347    }
348
349    fn head(&self, number: u64) -> Option<Head> {
350        self.hash.get(&number).map(|&hash| Head {
351            number: number.into(),
352            hash,
353            ..Head::default()
354        })
355    }
356
357    fn hash(&mut self, number: u64, hash: Int) {
358        self.hash.insert(number, hash);
359    }
360
361    fn auth(&self, acc: &Acc) -> Option<Acc> {
362        let entry = self.accounts.get(acc)?;
363        let (code, _) = &entry.account.code;
364        if code.0.len() == 23 && code.0.starts_with(&[0xEF, 0x01, 0x00]) {
365            let acc = Acc::from(&code.0[3..]);
366            if acc.is_zero() { None } else { Some(acc) }
367        } else {
368            None
369        }
370    }
371
372    fn log(&mut self, data: Buf, topics: Vec<Int>) {
373        self.emit(Event::Log(topics.clone(), data.clone()));
374        self.logs.push((data, topics));
375    }
376
377    fn get_depth(&mut self) -> usize {
378        self.depth
379    }
380
381    fn set_depth(&mut self, depth: usize) {
382        self.depth = depth;
383    }
384
385    fn emit(&mut self, mut event: Event) -> usize {
386        let id = self.events.len();
387        if let Event::Step(step) = &mut event {
388            step.debug.push(format!("depth={}", self.depth));
389        }
390        let trace = Trace {
391            seq: id,
392            event,
393            depth: self.depth,
394            reverted: false,
395        };
396        if self.filter & trace.event.filter_bit() != 0
397            && let Some(sender) = self.sender.as_mut()
398        {
399            let _ = sender.try_send(trace.clone());
400        }
401        self.events.push(trace);
402        id
403    }
404
405    fn save_fetched(&mut self, fetched: Fetched) {
406        self.fetched.push(fetched);
407    }
408
409    fn next_fetched(&mut self) -> Option<Fetched> {
410        self.index += 1;
411        self.fetched.get(self.index).cloned()
412    }
413
414    fn prefetched(&mut self, fetched: Vec<Fetched>) {
415        self.fetched = fetched;
416        self.offline = true;
417        self.index = 1; // skip chain id & block
418    }
419
420    fn is_offline(&self) -> bool {
421        self.offline
422    }
423
424    fn checkpoint(&mut self) -> usize {
425        self.events.len()
426    }
427
428    fn revert_to(&mut self, cp: usize) {
429        if cp >= self.events.len() {
430            return;
431        }
432        let to = self.events.len();
433
434        // Count logs added since checkpoint (to truncate self.logs)
435        let logs_to_remove = self.events[cp..]
436            .iter()
437            .filter(|t| !t.reverted)
438            .filter(|t| matches!(t.event, Event::Log(..)))
439            .count();
440        self.logs
441            .truncate(self.logs.len().saturating_sub(logs_to_remove));
442
443        // Collect undo operations (immutable borrow of events ends here)
444        let undos: Vec<Revert> = self.events[cp..]
445            .iter()
446            .filter(|t| !t.reverted)
447            .filter_map(|trace| match &trace.event {
448                Event::Put(Target::Store { acc, key, val }, _) => {
449                    Some(Revert::Store(*acc, *key, *val))
450                }
451                Event::Put(Target::Nonce { acc, val }, _) => Some(Revert::Nonce(*acc, *val)),
452                Event::Put(Target::Value { acc, val }, _) => Some(Revert::Value(*acc, *val)),
453                Event::Put(Target::Temp { acc, key, val }, _) => {
454                    Some(Revert::Temp(*acc, *key, *val))
455                }
456                Event::Put(Target::Code { acc, hash }, _) => Some(Revert::Code(*acc, *hash)),
457                Event::WarmAcc(acc) => Some(Revert::WarmAcc(*acc)),
458                Event::WarmKey(acc, key) => Some(Revert::WarmKey(*acc, *key)),
459                Event::Create(acc) => Some(Revert::Create(*acc)),
460                Event::Delete(acc) => Some(Revert::Delete(*acc)),
461                _ => None,
462            })
463            .collect();
464
465        // Mark all reverted traces
466        for t in &mut self.events[cp..] {
467            t.reverted = true;
468        }
469
470        // Apply undos in reverse order
471        for undo in undos.into_iter().rev() {
472            match undo {
473                Revert::Store(acc, key, val) => {
474                    if let Some(entry) = self.accounts.get_mut(&acc)
475                        && let Some(slot) = entry.storage.get_mut(&key)
476                    {
477                        slot.current = val;
478                    }
479                }
480                Revert::Nonce(acc, val) => {
481                    if let Some(entry) = self.accounts.get_mut(&acc) {
482                        entry.account.nonce = val;
483                    }
484                }
485                Revert::Value(acc, val) => {
486                    if let Some(entry) = self.accounts.get_mut(&acc) {
487                        entry.account.value = val;
488                    }
489                }
490                Revert::Temp(acc, key, val) => {
491                    if val.is_zero() {
492                        self.transient.remove(&(acc, key));
493                    } else {
494                        self.transient.insert((acc, key), val);
495                    }
496                }
497                Revert::Code(acc, _prev_hash) => {
498                    if let Some(entry) = self.accounts.get_mut(&acc) {
499                        entry.account.code = (Buf::default(), Int::ZERO);
500                    }
501                }
502                Revert::Create(acc) => {
503                    self.created.remove(&acc);
504                    self.accounts.remove(&acc);
505                }
506                Revert::Delete(acc) => {
507                    self.destroyed.remove(&acc);
508                }
509                Revert::WarmAcc(acc) => {
510                    self.warm_accs.remove(&acc);
511                }
512                Revert::WarmKey(acc, key) => {
513                    self.warm_keys.remove(&(acc, key));
514                }
515            }
516        }
517
518        if self.filter & filter::REVERT != 0
519            && let Some(sender) = self.sender.as_mut()
520        {
521            let _ = sender.try_send(Trace {
522                seq: cp,
523                event: Event::Undo(cp, to),
524                depth: self.depth,
525                reverted: true,
526            });
527        }
528    }
529
530    fn apply(&mut self) {
531        let destroyed = std::mem::take(&mut self.destroyed);
532        for acc in destroyed {
533            if let Some(entry) = self.accounts.get_mut(&acc) {
534                // do not reset nonce for self-destructed contracts
535                entry.account.value = Int::ZERO;
536                entry.account.code = (Buf::default(), Int::ZERO);
537                entry.storage.clear();
538            }
539            self.created.remove(&acc);
540        }
541    }
542
543    fn set_chain_id(&mut self, id: u64) {
544        self.chain_id = id;
545    }
546
547    fn get_chain_id(&self) -> u64 {
548        self.chain_id
549    }
550
551    fn is_tracing(&self) -> bool {
552        self.sender.is_some()
553    }
554}
555
556pub type Env = Vec<(Acc, Account, Vec<(Int, Int)>)>;
557
558impl Cache {
559    pub fn snapshot(&self) -> Env {
560        let mut ret = Vec::with_capacity(self.accounts.len());
561        for (acc, entry) in &self.accounts {
562            let mut kv = Vec::with_capacity(entry.storage.len());
563            for (key, slot) in &entry.storage {
564                kv.push((*key, slot.current));
565            }
566            kv.sort_by_key(|(k, _)| *k);
567            ret.push((*acc, entry.account.clone(), kv));
568        }
569        ret.sort_by_key(|(acc, _, _)| *acc);
570        ret
571    }
572}