Skip to main content

filecoin_f3_lightclient/
lib.rs

1// Copyright 2019-2024 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4mod rpc_to_internal;
5
6extern crate core;
7
8use anyhow::{Context, Result};
9use filecoin_f3_blssig::BLSVerifier;
10use filecoin_f3_certs as certs;
11use filecoin_f3_certs::validate_finality_certificates;
12use filecoin_f3_gpbft::{ECChain, NetworkName, PowerEntries};
13use filecoin_f3_rpc::RPCClient;
14
15pub struct LightClient {
16    rpc: RPCClient,
17    network: NetworkName,
18    verifier: BLSVerifier,
19}
20
21#[derive(Debug, Clone)]
22pub struct LightClientState {
23    pub instance: u64,
24    pub chain: Option<ECChain>,
25    pub power_table: PowerEntries,
26}
27
28impl LightClient {
29    pub fn new(endpoint: &str, network_name: &str) -> Result<Self> {
30        Ok(Self {
31            rpc: RPCClient::new(endpoint)?,
32            network: network_name.to_string().parse().context("network_name")?,
33            verifier: BLSVerifier::new(),
34        })
35    }
36
37    pub async fn initialize(&mut self, instance: u64) -> Result<LightClientState> {
38        let power_table = self.rpc.get_power_table(instance).await?;
39        let power_table = power_table
40            .into_iter()
41            .map(rpc_to_internal::convert_power_entry)
42            .collect::<Result<Vec<_>, _>>()?;
43
44        Ok(LightClientState {
45            instance,
46            chain: None,
47            power_table: PowerEntries(power_table),
48        })
49    }
50
51    pub async fn get_certificate(&self, instance: u64) -> Result<certs::FinalityCertificate> {
52        let rpc_cert = self.rpc.get_certificate(instance).await?;
53        rpc_to_internal::convert_certificate(rpc_cert)
54    }
55
56    pub fn validate_certificates(
57        &mut self,
58        state: &LightClientState,
59        certs: &[certs::FinalityCertificate],
60    ) -> certs::Result<LightClientState> {
61        let (new_instance, new_chain, new_power_table) = validate_finality_certificates(
62            &self.verifier,
63            self.network,
64            state.power_table.clone(),
65            state.instance,
66            state.chain.as_ref().and_then(|c| c.last()),
67            certs,
68        )?;
69
70        Ok(LightClientState {
71            instance: new_instance,
72            chain: Some(new_chain),
73            power_table: new_power_table,
74        })
75    }
76}