Skip to main content

evm_fork_cache/cold_start/
mod.rs

1//! Protocol-neutral cold-start sync for [`EvmCache`](crate::cache::EvmCache).
2//!
3//! Cold start declares rounds of authoritative slot work — verify, probe,
4//! probe_roots, accounts, discover — and drives a bounded multi-round loop via
5//! a pure [`ColdStartPlanner`]. Every verify and probe slot yields a per-slot
6//! [`SlotOutcome`] distinguishing a genuine on-chain zero ([`SlotFetch::Zero`])
7//! from a fetch failure ([`SlotFetch::FetchFailed`]) — closing the "archive-miss"
8//! gap where a transient fetch failure was indistinguishable from absence.
9//!
10//! The module is gated behind the `reactive` feature. The per-slot
11//! [`SlotOutcome`] / [`SlotFetch`] surface lives ungated in
12//! [`crate::freshness`] and is re-exported here for consumer ergonomics.
13//!
14//! Background schedulers can split provider work from canonical mutation with
15//! [`StorageRoundFetcher`] and [`AccountProofRoundFetcher`]. Both operate on
16//! exact canonical block hashes without borrowing an
17//! [`EvmCache`](crate::cache::EvmCache); their
18//! [`PreparedStoragePatch`] / [`PreparedAccountPatch`] artifacts are applied
19//! later by the cache owner through stale-baseline-checked atomic write seams.
20//!
21//! # Design
22//!
23//! - The driver performs every fetch and call; planners are pure and IO-free,
24//!   handed only a [`StateView`](crate::events::StateView) and a
25//!   [`ColdStartResults`].
26//! - Verify-phase changes are injected via the dual-layer
27//!   [`inject_storage_batch_fresh`](crate::cache::EvmCache::inject_storage_batch_fresh)
28//!   and are visible to the next `on_results` through the state view.
29//! - A run can be pinned to a block hash via [`ColdStartPin::Hash`]; with
30//!   `require_canonical: true`, a reorged hash makes the run fail fast. This is
31//!   the cold-start reorg defense by design.
32//!
33//! # Runtime requirement
34//!
35//! Like the rest of the crate's RPC seams, cold-start fetching drives async work
36//! synchronously and must run on a **multi-thread** tokio runtime.
37//!
38//! # Example
39//!
40//! A planner that authoritatively warms a fixed working set of slots in one round.
41//! (See `examples/cold_start.rs` for the runnable discover-then-verify version.)
42//!
43//! ```
44//! use alloy_primitives::{Address, U256};
45//! use evm_fork_cache::cache::EvmCache;
46//! use evm_fork_cache::events::StateView;
47//! use evm_fork_cache::{
48//!     ColdStartConfig, ColdStartError, ColdStartPlan, ColdStartPlanner, ColdStartResults,
49//!     ColdStartStep,
50//! };
51//!
52//! struct WarmSlots {
53//!     slots: Vec<(Address, U256)>,
54//! }
55//!
56//! impl ColdStartPlanner for WarmSlots {
57//!     fn initial_plan(&mut self, _state: &dyn StateView) -> ColdStartPlan {
58//!         // Round 1: re-fetch these slots authoritatively and inject the fresh values.
59//!         ColdStartPlan { verify: self.slots.clone(), ..Default::default() }
60//!     }
61//!     fn on_results(&mut self, _r: &ColdStartResults, _s: &dyn StateView) -> ColdStartStep {
62//!         ColdStartStep::Done
63//!     }
64//! }
65//!
66//! // `run_cold_start` needs a live cache on a multi-thread runtime; this helper
67//! // shows the call shape (it is never invoked, so the doctest needs no runtime).
68//! # fn warm(cache: &mut EvmCache, slots: Vec<(Address, U256)>) -> Result<(), ColdStartError> {
69//! let mut planner = WarmSlots { slots };
70//! let report = cache.run_cold_start(&mut planner, ColdStartConfig::default())?;
71//! assert_eq!(report.rounds, 1);
72//! # Ok(())
73//! # }
74//! ```
75
76mod account_round;
77mod config;
78mod driver;
79mod error;
80mod plan;
81mod planner;
82mod results;
83pub mod roots;
84mod storage_round;
85
86pub use account_round::{
87    AccountCodeClaim, AccountProofOutcome, AccountProofRoundFetch, AccountProofRoundFetchError,
88    AccountProofRoundFetcher, AccountProofRoundRequest, PreparedAccountPatch,
89    PreparedAccountPatchError, PreparedAccountValue,
90};
91pub use config::{ColdStartConfig, ColdStartPin, ColdStartRoundSummary, ColdStartRunReport};
92pub use error::ColdStartError;
93pub use plan::{ColdStartCall, ColdStartPlan};
94pub use planner::{ColdStartPlanner, ColdStartStep};
95pub use results::{ColdStartCallResult, ColdStartResults, RoundOutcome};
96pub use roots::{RootBaseline, RootBaselinePlanner, RootProbeOutcome};
97pub use storage_round::{
98    PreparedStoragePatch, PreparedStoragePatchError, PreparedStorageValue, StorageRoundFetch,
99    StorageRoundFetchError, StorageRoundFetcher, StorageRoundRequest, StorageSlotRequest,
100};
101
102// The per-slot fetch surface is ungated in `freshness`; re-export so
103// `evm_fork_cache::cold_start::SlotFetch` resolves for consumers.
104pub use crate::freshness::{SlotFetch, SlotOutcome};