tendermint_light_client/
state.rs

1//! State maintained by the light client.
2
3use std::collections::{HashMap, HashSet};
4
5use contracts::*;
6
7use crate::{
8    store::LightStore,
9    verifier::types::{Height, LightBlock},
10};
11
12/// Records which blocks were needed to verify a target block, eg. during bisection.
13pub type VerificationTrace = HashMap<Height, HashSet<Height>>;
14
15/// The state managed by the light client.
16#[derive(Debug)]
17pub struct State {
18    /// Store for light blocks.
19    pub light_store: Box<dyn LightStore>,
20
21    /// Records which blocks were needed to verify a target block, eg. during bisection.
22    pub verification_trace: VerificationTrace,
23}
24
25impl State {
26    /// Create a new state from the given light store with an empty verification trace.
27    pub fn new(light_store: impl LightStore + 'static) -> Self {
28        Self {
29            light_store: Box::new(light_store),
30            verification_trace: VerificationTrace::new(),
31        }
32    }
33
34    /// Record that the block at `height` was needed to verify the block at `target_height`.
35    ///
36    /// ## Preconditions
37    /// - `height` <= `target_height`
38    #[requires(height <= target_height)]
39    pub fn trace_block(&mut self, target_height: Height, height: Height) {
40        self.verification_trace
41            .entry(target_height)
42            .or_insert_with(|| {
43                let mut trace = HashSet::new();
44                trace.insert(target_height);
45                trace
46            })
47            .insert(height);
48    }
49
50    /// Get the verification trace for the block at `target_height`.
51    pub fn get_trace(&self, target_height: Height) -> Vec<LightBlock> {
52        let mut trace = self
53            .verification_trace
54            .get(&target_height)
55            .unwrap_or(&HashSet::new())
56            .iter()
57            .flat_map(|&height| self.light_store.get_trusted_or_verified(height))
58            .collect::<Vec<_>>();
59
60        trace.sort_by_key(|lb| lb.height());
61        trace
62    }
63}