1use std::fmt::Debug;
2use std::ops::RangeBounds;
3use std::{collections::BTreeMap, fmt::Display};
4
5use bitcoin::{block::Header, BlockHash};
6
7use crate::prelude::FutureResult;
8
9use super::{BlockHeaderChanges, PersistedPeer};
10
11pub trait HeaderStore: Debug + Send + Sync {
13 type Error: Debug + Display;
15 fn load<'a>(
17 &'a mut self,
18 range: impl RangeBounds<u32> + Send + Sync + 'a,
19 ) -> FutureResult<'a, BTreeMap<u32, Header>, Self::Error>;
20
21 fn stage(&mut self, changes: BlockHeaderChanges);
23
24 fn write(&mut self) -> FutureResult<'_, (), Self::Error>;
26
27 fn height_of<'a>(
29 &'a mut self,
30 hash: &'a BlockHash,
31 ) -> FutureResult<'a, Option<u32>, Self::Error>;
32
33 fn hash_at(&mut self, height: u32) -> FutureResult<'_, Option<BlockHash>, Self::Error>;
35
36 fn header_at(&mut self, height: u32) -> FutureResult<'_, Option<Header>, Self::Error>;
38}
39
40pub trait PeerStore: Debug + Send + Sync {
42 type Error: Debug + Display;
44 fn update(&mut self, peer: PersistedPeer) -> FutureResult<'_, (), Self::Error>;
46
47 fn random(&mut self) -> FutureResult<'_, PersistedPeer, Self::Error>;
49
50 fn num_unbanned(&mut self) -> FutureResult<'_, u32, Self::Error>;
52}
53
54#[cfg(test)]
55mod test {
56 use super::*;
57 use std::convert::Infallible;
58
59 #[derive(Debug)]
61 pub enum UnitPeerStoreError {
62 NoPeers,
64 }
65
66 impl core::fmt::Display for UnitPeerStoreError {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 match self {
69 UnitPeerStoreError::NoPeers => write!(f, "no peers in unit database."),
70 }
71 }
72 }
73
74 impl PeerStore for () {
75 type Error = UnitPeerStoreError;
76 fn update(&mut self, _peer: PersistedPeer) -> FutureResult<'_, (), Self::Error> {
77 async fn do_update() -> Result<(), UnitPeerStoreError> {
78 Ok(())
79 }
80 Box::pin(do_update())
81 }
82
83 fn random(&mut self) -> FutureResult<'_, PersistedPeer, Self::Error> {
84 async fn do_random() -> Result<PersistedPeer, UnitPeerStoreError> {
85 Err(UnitPeerStoreError::NoPeers)
86 }
87 Box::pin(do_random())
88 }
89
90 fn num_unbanned(&mut self) -> FutureResult<'_, u32, Self::Error> {
91 async fn do_num_unbanned() -> Result<u32, UnitPeerStoreError> {
92 Ok(0)
93 }
94 Box::pin(do_num_unbanned())
95 }
96 }
97
98 impl HeaderStore for () {
99 type Error = Infallible;
100 fn load<'a>(
101 &'a mut self,
102 _range: impl RangeBounds<u32> + Send + Sync + 'a,
103 ) -> FutureResult<'a, BTreeMap<u32, Header>, Self::Error> {
104 async fn do_load() -> Result<BTreeMap<u32, Header>, Infallible> {
105 Ok(BTreeMap::new())
106 }
107 Box::pin(do_load())
108 }
109
110 fn stage(&mut self, _changes: BlockHeaderChanges) {}
111
112 fn write(&mut self) -> FutureResult<'_, (), Self::Error> {
113 async fn do_write() -> Result<(), Infallible> {
114 Ok(())
115 }
116 Box::pin(do_write())
117 }
118
119 fn height_of<'a>(
120 &'a mut self,
121 _block_hash: &'a BlockHash,
122 ) -> FutureResult<'a, Option<u32>, Self::Error> {
123 async fn do_height_of() -> Result<Option<u32>, Infallible> {
124 Ok(None)
125 }
126 Box::pin(do_height_of())
127 }
128
129 fn hash_at(&mut self, _height: u32) -> FutureResult<'_, Option<BlockHash>, Self::Error> {
130 async fn do_hast_at() -> Result<Option<BlockHash>, Infallible> {
131 Ok(None)
132 }
133 Box::pin(do_hast_at())
134 }
135
136 fn header_at(&mut self, _height: u32) -> FutureResult<'_, Option<Header>, Self::Error> {
137 async fn do_header_at() -> Result<Option<Header>, Infallible> {
138 Ok(None)
139 }
140 Box::pin(do_header_at())
141 }
142 }
143}