evm_fork_cache/cold_start/plan.rs
1//! What a cold-start round declares it wants done.
2//!
3//! A [`ColdStartPlan`] is a pure, IO-free description handed to the driver. All
4//! phases are optional and an empty plan is a valid no-op round.
5
6use alloy_primitives::{Address, Bytes, U256};
7
8/// A single round of cold-start work, declared by a
9/// [`ColdStartPlanner`](crate::cold_start::ColdStartPlanner).
10///
11/// All phases are optional; an empty plan is a valid no-op round. The driver
12/// executes the phases in a fixed order:
13/// **accounts → verify → probe → probe_roots → discover**.
14///
15/// - `verify` slots are authoritatively re-fetched, classified, and (when changed)
16/// injected into the cache via the dual-layer
17/// [`inject_storage_batch_fresh`](crate::cache::EvmCache::inject_storage_batch_fresh).
18/// - `probe` slots are classified at the pinned block **without** injecting.
19/// - `probe_roots` accounts have their storage root observed via the
20/// account-proof fetcher at the pinned block, without injecting anything.
21/// - `accounts` are pre-seeded into the cache before discovery runs.
22/// - `discover` view-calls capture the `(address, slot)` pairs and accounts they
23/// touch.
24///
25/// ```
26/// use alloy_primitives::{Address, Bytes, U256};
27/// use evm_fork_cache::{ColdStartCall, ColdStartPlan};
28///
29/// // Verify one known slot and discover more via a read-only view-call.
30/// let plan = ColdStartPlan {
31/// verify: vec![(Address::repeat_byte(0x11), U256::from(0))],
32/// discover: vec![ColdStartCall {
33/// from: Address::ZERO,
34/// to: Address::repeat_byte(0x11),
35/// calldata: Bytes::new(),
36/// restrict_to: None,
37/// }],
38/// ..Default::default()
39/// };
40/// assert_eq!(plan.verify.len(), 1);
41/// assert_eq!(plan.discover.len(), 1);
42/// ```
43#[derive(Clone, Debug, Default)]
44pub struct ColdStartPlan {
45 /// Slots to authoritatively re-fetch, classify, and inject when changed.
46 pub verify: Vec<(Address, U256)>,
47 /// Slots to classify at the pinned block without injecting.
48 pub probe: Vec<(Address, U256)>,
49 /// Accounts whose storage root is probed via the account-proof fetcher at
50 /// the pinned block, without injecting anything.
51 pub probe_roots: Vec<Address>,
52 /// Accounts to pre-seed into the cache before discovery.
53 pub accounts: Vec<Address>,
54 /// View-calls whose touched slots and accounts are captured.
55 pub discover: Vec<ColdStartCall>,
56}
57
58/// A read-only view-call whose touched storage and accounts are captured during
59/// the discover phase.
60///
61/// When `restrict_to` is `Some`, the captured `slots` and `accounts` are filtered
62/// to the named addresses; an empty restricted capture is observable as an empty
63/// access list (distinct from a non-empty discovery).
64#[derive(Clone, Debug)]
65pub struct ColdStartCall {
66 /// Transaction sender.
67 pub from: Address,
68 /// Call target.
69 pub to: Address,
70 /// Calldata.
71 pub calldata: Bytes,
72 /// When set, filters captured slots and accounts to these addresses.
73 pub restrict_to: Option<Vec<Address>>,
74}