1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use tendermint::block::Height;
use tendermint::evidence::Evidence;
use tendermint::hash::Hash;
use tendermint_light_client::errors::Error;
use tendermint_light_client::instance::Instance;
use tendermint_light_client::light_client::TargetOrLatest;
use tendermint_light_client::state::State;
use tendermint_light_client::store::memory::MemoryStore;
use tendermint_light_client::verifier::types::LightBlock;
use tendermint_rpc::{Client, Error as RpcError, HttpClient};

/// A interface over a light client instance and its RPC client.
#[derive(Debug)]
pub struct Provider {
    chain_id: String,
    instance: Instance,
    rpc_client: HttpClient,
}

impl Provider {
    pub fn new(chain_id: String, instance: Instance, rpc_client: HttpClient) -> Self {
        Self {
            chain_id,
            instance,
            rpc_client,
        }
    }

    pub fn chain_id(&self) -> &str {
        &self.chain_id
    }

    pub fn peer_id(&self) -> &tendermint::node::Id {
        self.instance.peer_id()
    }

    pub async fn report_evidence(&self, evidence: Evidence) -> Result<Hash, RpcError> {
        self.rpc_client
            .broadcast_evidence(evidence)
            .await
            .map(|response| response.hash)
    }

    pub fn fetch_light_block(&self, height: Height) -> Result<LightBlock, Error> {
        let mut state = State::new(MemoryStore::new());

        self.instance
            .light_client
            .get_or_fetch_block(height, &mut state)
            .map(|(lb, _)| lb)
    }

    pub fn verify_to_highest(&mut self) -> Result<LightBlock, Error> {
        self.instance
            .light_client
            .verify_to_highest(&mut self.instance.state)
    }

    pub fn verify_to_height(&mut self, height: Height) -> Result<LightBlock, Error> {
        self.instance
            .light_client
            .verify_to_target(height, &mut self.instance.state)
    }

    pub fn verify_to_height_with_state(
        &self,
        height: Height,
        state: &mut State,
    ) -> Result<LightBlock, Error> {
        self.instance.light_client.verify_to_target(height, state)
    }

    pub fn get_target_block_or_latest(&mut self, height: Height) -> Result<TargetOrLatest, Error> {
        self.instance
            .light_client
            .get_target_block_or_latest(height, &mut self.instance.state)
    }

    pub fn get_trace(&self, height: Height) -> Vec<LightBlock> {
        self.instance.state.get_trace(height)
    }

    pub fn latest_trusted(&self) -> Option<LightBlock> {
        self.instance.latest_trusted()
    }
}