cuprated/blockchain/
chain_service.rs1use std::task::{Context, Poll};
2
3use futures::{future::BoxFuture, FutureExt, TryFutureExt};
4use tower::Service;
5
6use cuprate_blockchain::service::BlockchainReadHandle;
7use cuprate_fast_sync::validate_entries;
8use cuprate_p2p::block_downloader::{ChainSvcRequest, ChainSvcResponse};
9use cuprate_p2p_core::NetworkZone;
10use cuprate_types::blockchain::{BlockchainReadRequest, BlockchainResponse};
11
12#[derive(Clone)]
17pub struct ChainService(pub BlockchainReadHandle);
18
19impl<N: NetworkZone> Service<ChainSvcRequest<N>> for ChainService {
20 type Response = ChainSvcResponse<N>;
21 type Error = tower::BoxError;
22 type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
23
24 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
25 self.0.poll_ready(cx).map_err(Into::into)
26 }
27
28 fn call(&mut self, req: ChainSvcRequest<N>) -> Self::Future {
29 let map_res = |res: BlockchainResponse| match res {
30 BlockchainResponse::CompactChainHistory {
31 block_ids,
32 cumulative_difficulty,
33 } => ChainSvcResponse::CompactHistory {
34 block_ids,
35 cumulative_difficulty,
36 },
37 BlockchainResponse::FindFirstUnknown(res) => ChainSvcResponse::FindFirstUnknown(res),
38 _ => unreachable!(),
39 };
40
41 match req {
42 ChainSvcRequest::CompactHistory => self
43 .0
44 .call(BlockchainReadRequest::CompactChainHistory)
45 .map_ok(map_res)
46 .map_err(Into::into)
47 .boxed(),
48 ChainSvcRequest::FindFirstUnknown(req) => self
49 .0
50 .call(BlockchainReadRequest::FindFirstUnknown(req))
51 .map_ok(map_res)
52 .map_err(Into::into)
53 .boxed(),
54 ChainSvcRequest::CumulativeDifficulty => self
55 .0
56 .call(BlockchainReadRequest::CompactChainHistory)
57 .map_ok(|res| {
58 let BlockchainResponse::CompactChainHistory {
61 cumulative_difficulty,
62 ..
63 } = res
64 else {
65 unreachable!()
66 };
67
68 ChainSvcResponse::CumulativeDifficulty(cumulative_difficulty)
69 })
70 .map_err(Into::into)
71 .boxed(),
72 ChainSvcRequest::ValidateEntries(entries, start_height) => {
73 let mut blockchain_read_handle = self.0.clone();
74
75 async move {
76 let (valid, unknown) =
77 validate_entries(entries, start_height, &mut blockchain_read_handle)
78 .await?;
79
80 Ok(ChainSvcResponse::ValidateEntries { valid, unknown })
81 }
82 .boxed()
83 }
84 }
85 }
86}