hotshot_query_service/data_source/fetching/
state_cert.rs

1// Copyright (c) 2022 Espresso Systems (espressosys.com)
2// This file is part of the HotShot Query Service library.
3//
4// This program is free software: you can redistribute it and/or modify it under the terms of the GNU
5// General Public License as published by the Free Software Foundation, either version 3 of the
6// License, or (at your option) any later version.
7// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
8// even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9// General Public License for more details.
10// You should have received a copy of the GNU General Public License along with this program. If not,
11// see <https://www.gnu.org/licenses/>.
12
13//! Fetching for light client state update certificates.
14
15use std::{future::IntoFuture, sync::Arc};
16
17use async_trait::async_trait;
18use futures::future::FutureExt;
19use hotshot_types::traits::node_implementation::{ConsensusTime, NodeType};
20
21use super::Storable;
22use crate::{
23    availability::{QueryableHeader, QueryablePayload, StateCertQueryData},
24    data_source::{
25        fetching::{
26            AvailabilityProvider, FetchRequest, Fetchable, Fetcher, Notifiers, PassiveFetch,
27        },
28        storage::{
29            pruning::PrunedHeightStorage, AvailabilityStorage, NodeStorage,
30            UpdateAvailabilityStorage,
31        },
32        VersionedDataSource,
33    },
34    fetching::request::StateCertRequest,
35    Header, Payload, QueryResult,
36};
37
38impl FetchRequest for StateCertRequest {}
39
40#[async_trait]
41impl<Types> Fetchable<Types> for StateCertQueryData<Types>
42where
43    Types: NodeType,
44    Header<Types>: QueryableHeader<Types>,
45    Payload<Types>: QueryablePayload<Types>,
46{
47    type Request = StateCertRequest;
48
49    /// Does this object satisfy the given request?
50    fn satisfies(&self, req: Self::Request) -> bool {
51        self.0.epoch.u64() == req.0
52    }
53
54    async fn active_fetch<S, P>(
55        _tx: &mut impl AvailabilityStorage<Types>,
56        _fetcher: Arc<Fetcher<Types, S, P>>,
57        _req: Self::Request,
58    ) -> anyhow::Result<()>
59    where
60        S: VersionedDataSource + 'static,
61        for<'a> S::Transaction<'a>: UpdateAvailabilityStorage<Types>,
62        for<'a> S::ReadOnly<'a>:
63            AvailabilityStorage<Types> + NodeStorage<Types> + PrunedHeightStorage,
64        P: AvailabilityProvider<Types>,
65    {
66        // We dont do anything for now if the state cert is not in the database
67        Ok(())
68    }
69
70    /// Wait for someone else to fetch the object.
71    async fn passive_fetch(notifiers: &Notifiers<Types>, req: Self::Request) -> PassiveFetch<Self> {
72        notifiers
73            .state_cert
74            .wait_for(move |data| data.satisfies(req))
75            .await
76            .into_future()
77            .boxed()
78    }
79
80    async fn load<S>(storage: &mut S, req: Self::Request) -> QueryResult<Self>
81    where
82        S: AvailabilityStorage<Types>,
83    {
84        storage.get_state_cert(req.0).await
85    }
86}
87
88impl<Types> Storable<Types> for StateCertQueryData<Types>
89where
90    Types: NodeType,
91{
92    fn name() -> &'static str {
93        "State cert"
94    }
95
96    async fn notify(&self, notifiers: &Notifiers<Types>) {
97        notifiers.state_cert.notify(self).await;
98    }
99
100    async fn store(
101        self,
102        storage: &mut (impl UpdateAvailabilityStorage<Types> + Send),
103        _leaf_only: bool,
104    ) -> anyhow::Result<()> {
105        storage.insert_state_cert(self).await
106    }
107}