1use super::bip158::CompactBlockFilter;
9use crate::Hash;
10use sha2::{Digest, Sha256};
11
12#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct FilterHeader {
15 pub filter_hash: Hash,
17 pub prev_header_hash: Hash,
19}
20
21impl FilterHeader {
22 pub fn new(filter: &CompactBlockFilter, prev_header: Option<&FilterHeader>) -> Self {
24 let mut hasher = Sha256::new();
26 hasher.update(&filter.filter_data);
27 let first_hash = hasher.finalize();
28
29 let mut hasher2 = Sha256::new();
30 hasher2.update(first_hash);
31 let filter_hash_bytes = hasher2.finalize();
32
33 let mut filter_hash = [0u8; 32];
34 filter_hash.copy_from_slice(&filter_hash_bytes);
35
36 let prev_header_hash = if let Some(prev) = prev_header {
38 let mut combined = Vec::new();
40 combined.extend_from_slice(&prev.filter_hash);
41 combined.extend_from_slice(&prev.prev_header_hash);
42
43 let mut hasher = Sha256::new();
44 hasher.update(&combined);
45 let first_hash = hasher.finalize();
46
47 let mut hasher2 = Sha256::new();
48 hasher2.update(first_hash);
49 let header_hash_bytes = hasher2.finalize();
50
51 let mut header_hash = [0u8; 32];
52 header_hash.copy_from_slice(&header_hash_bytes);
53 header_hash
54 } else {
55 [0u8; 32]
57 };
58
59 FilterHeader {
60 filter_hash,
61 prev_header_hash,
62 }
63 }
64
65 pub fn header_hash(&self) -> Hash {
67 let mut combined = Vec::new();
68 combined.extend_from_slice(&self.filter_hash);
69 combined.extend_from_slice(&self.prev_header_hash);
70
71 let mut hasher = Sha256::new();
72 hasher.update(&combined);
73 let first_hash = hasher.finalize();
74
75 let mut hasher2 = Sha256::new();
76 hasher2.update(first_hash);
77 let hash_bytes = hasher2.finalize();
78
79 let mut header_hash = [0u8; 32];
80 header_hash.copy_from_slice(&hash_bytes);
81 header_hash
82 }
83}
84
85#[derive(Debug, Clone, Copy, PartialEq, Eq)]
87pub enum FilterType {
88 Basic = 0,
90}
91
92impl FilterType {
93 pub fn from_u8(value: u8) -> Option<Self> {
94 match value {
95 0 => Some(FilterType::Basic),
96 _ => None,
97 }
98 }
99
100 pub fn to_u8(self) -> u8 {
101 self as u8
102 }
103}
104
105#[derive(Debug, Clone)]
107pub struct GetCfilters {
108 pub filter_type: FilterType,
110 pub start_height: u32,
112 pub stop_hash: Hash,
114}
115
116#[derive(Debug, Clone)]
118pub struct CFilter {
119 pub filter_type: FilterType,
121 pub block_hash: Hash,
123 pub filter: CompactBlockFilter,
125}
126
127#[derive(Debug, Clone)]
129pub struct GetCfheaders {
130 pub filter_type: FilterType,
132 pub start_height: u32,
134 pub stop_hash: Hash,
136}
137
138#[derive(Debug, Clone)]
140pub struct Cfheaders {
141 pub filter_type: FilterType,
143 pub stop_hash: Hash,
145 pub prev_header: FilterHeader,
147 pub filter_headers: Vec<Hash>,
149}
150
151#[derive(Debug, Clone)]
153pub struct GetCfcheckpt {
154 pub filter_type: FilterType,
156 pub stop_hash: Hash,
158}
159
160#[derive(Debug, Clone)]
162pub struct Cfcheckpt {
163 pub filter_type: FilterType,
165 pub stop_hash: Hash,
167 pub filter_header_hashes: Vec<Hash>,
169}
170
171pub const NODE_COMPACT_FILTERS: u64 = 1 << 6;
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 #[test]
179 fn test_filter_header() {
180 let empty_filter = CompactBlockFilter {
181 filter_data: vec![1, 2, 3],
182 num_elements: 0,
183 };
184
185 let header1 = FilterHeader::new(&empty_filter, None);
186 let header2 = FilterHeader::new(&empty_filter, Some(&header1));
187
188 assert_eq!(header1.filter_hash, header2.filter_hash);
190 assert_ne!(header1.header_hash(), header2.header_hash());
192 assert_eq!(header2.prev_header_hash, header1.header_hash());
193 }
194}