Skip to main content

eth_state_diff/
historical_log.rs

1//! Delta encoding for append-only historical logs.
2//!
3//! Both `historical_roots` (Phase0 to Bellatrix) and `historical_summaries`
4//! (Capella+) are append-only logs that grow by exactly one item per 8,192 slots.
5//! This module uses protocol math to calculate exactly how many items were
6//! appended, rather than comparing base and target byte arrays.
7
8use crate::types::{ArchivedHistoricalLogDiff, HistoricalLogDiff};
9
10/// The protocol-defined period for historical calculations (8192 slots).
11const SLOTS_PER_HISTORICAL_PERIOD: u64 = 8192;
12
13/// Calculates the expected length of the historical log at a given slot.
14#[inline]
15fn calculate_log_count(slot: u64, activation_slot: Option<u64>) -> u64 {
16    match activation_slot {
17        Some(act_slot) if slot <= act_slot => 0,
18        Some(act_slot) => (slot - act_slot) / SLOTS_PER_HISTORICAL_PERIOD,
19        None => (slot + 1) / SLOTS_PER_HISTORICAL_PERIOD,
20    }
21}
22
23/// Computes a historical log delta using protocol math.
24pub fn diff_historical_log(
25    base_slot: u64,
26    target_slot: u64,
27    target_ssz: &[u8],
28    item_ssz_size: usize,
29    activation_slot: Option<u64>,
30) -> HistoricalLogDiff {
31    let base_count = calculate_log_count(base_slot, activation_slot);
32    let target_count = calculate_log_count(target_slot, activation_slot);
33
34    let items_to_append = (target_count - base_count) as usize;
35
36    if items_to_append == 0 {
37        return HistoricalLogDiff::Unchanged;
38    }
39
40    let required_bytes = items_to_append * item_ssz_size;
41
42    debug_assert!(
43        target_ssz.len() >= required_bytes,
44        "Historical log math expects {required_bytes} bytes, but target_ssz is too short",
45    );
46
47    let start_byte = target_ssz.len() - required_bytes;
48    HistoricalLogDiff::Append(target_ssz[start_byte..].to_vec())
49}
50
51/// Applies a historical log delta in place.
52pub fn apply_historical_log(base: &mut Vec<u8>, delta: &ArchivedHistoricalLogDiff) {
53    match delta {
54        ArchivedHistoricalLogDiff::Unchanged => {}
55        ArchivedHistoricalLogDiff::Append(bytes) => {
56            base.extend_from_slice(bytes.as_slice());
57        }
58    }
59}