zakura_network/zakura/header_sync/
wire.rs1use super::{config::*, error::*, events::HeaderSyncRequestId, validation::*, *};
2
3pub const ZAKURA_STREAM_HEADER_SYNC: u16 = 5;
5pub const ZAKURA_HEADER_SYNC_STREAM_VERSION: u16 = 7;
18
19pub const MSG_HS_STATUS: u8 = 1;
21pub const MSG_HS_GET_HEADERS: u8 = 2;
23pub const MSG_HS_HEADERS: u8 = 3;
25pub const MSG_HS_NEW_BLOCK: u8 = 4;
27
28pub const MAX_HS_MESSAGE_BYTES: usize = 2 * 1024 * 1024;
30pub const DEFAULT_HS_RANGE: u32 = 1000;
32pub const MAX_HS_RANGE: u32 = 4000;
34pub const DEFAULT_HS_MAX_INFLIGHT: u16 = 10;
36
37pub(super) const HEADER_SYNC_MESSAGE_TYPE_BYTES: usize = 1;
38pub(super) const HEADER_SYNC_REQUEST_ID_BYTES: usize = 8;
39pub(super) const HEADER_SYNC_COUNT_BYTES: usize = 4;
40pub(super) const HEADER_SYNC_HAS_ROOTS_BYTES: usize = 1;
41pub(super) const HEADER_SYNC_BODY_SIZE_BYTES: usize = 4;
42pub(super) const HEADER_SYNC_BLOCK_COMMITMENT_ROOTS_BYTES: usize =
45 4 + 32 + 32 + 32 + 8 + 8 + 8 + 32;
46pub(super) const COMMON_HEADER_BYTES: usize = 1_487;
47pub(super) const REGTEST_HEADER_BYTES: usize = 177;
48pub(super) const LOCAL_MAX_HS_INFLIGHT_PER_PEER: u16 = 16;
49pub(super) const HEADER_SYNC_MAX_RESIDENT_BATCHES: u32 = 16;
50pub(super) const HEADER_SYNC_RETRY_AVOIDANCE: Duration = Duration::from_millis(50);
51pub(super) const STATUS_PUBLICATION_RETRY_DELAY: Duration = Duration::from_millis(50);
52pub(super) const HEADER_SYNC_SEEN_HASH_CAPACITY: usize = 4096;
53pub(super) const DEFAULT_HS_REQUEST_TIMEOUT: Duration = Duration::from_secs(30);
54pub(super) const EMPTY_HEADERS_RETRY_DELAY: Duration = Duration::from_secs(1);
55pub(super) const DEFAULT_HS_STATUS_REFRESH_INTERVAL: Duration = Duration::from_secs(30);
56pub(super) const DEFAULT_HS_INBOUND_STATUS_MIN_INTERVAL: Duration = Duration::from_secs(5);
60pub(super) const DEFAULT_HS_INBOUND_NEW_BLOCK_MIN_INTERVAL: Duration = Duration::from_secs(5);
61
62const _: () = assert!(MAX_HS_MESSAGE_BYTES < LOCAL_MAX_MESSAGE_BYTES as usize);
63const _: () = assert!(
64 HEADER_SYNC_MESSAGE_TYPE_BYTES
65 + HEADER_SYNC_REQUEST_ID_BYTES
66 + HEADER_SYNC_COUNT_BYTES
67 + (COMMON_HEADER_BYTES
68 + HEADER_SYNC_BODY_SIZE_BYTES
69 + HEADER_SYNC_BLOCK_COMMITMENT_ROOTS_BYTES)
70 * (DEFAULT_HS_RANGE as usize)
71 < MAX_HS_MESSAGE_BYTES
72);
73
74#[derive(Clone, Debug, Eq, PartialEq)]
76pub enum HeaderSyncMessage {
77 Status(HeaderSyncStatus),
79 GetHeaders {
81 start_height: block::Height,
83 count: u32,
85 want_tree_aux_roots: bool,
90 },
91 Headers {
96 headers: Vec<Arc<block::Header>>,
98 body_sizes: Vec<u32>,
100 tree_aux_roots: Vec<BlockCommitmentRoots>,
102 },
103 NewBlock(Arc<block::Block>),
105}
106
107impl HeaderSyncMessage {
108 pub fn message_type(&self) -> u8 {
110 match self {
111 Self::Status(_) => MSG_HS_STATUS,
112 Self::GetHeaders { .. } => MSG_HS_GET_HEADERS,
113 Self::Headers { .. } => MSG_HS_HEADERS,
114 Self::NewBlock(_) => MSG_HS_NEW_BLOCK,
115 }
116 }
117
118 pub fn encode(
123 &self,
124 request_id: Option<HeaderSyncRequestId>,
125 ) -> Result<Vec<u8>, HeaderSyncWireError> {
126 let mut bytes = Vec::new();
127 bytes.write_u8(self.message_type())?;
128 match self {
129 Self::Status(status) => status.encode_to(&mut bytes)?,
130 Self::GetHeaders {
131 start_height,
132 count,
133 want_tree_aux_roots,
134 } => {
135 validate_get_headers_count(*count)?;
136 bytes.write_u64::<LittleEndian>(
137 request_id
138 .ok_or(HeaderSyncWireError::MissingRequestId {
139 message: "GetHeaders",
140 })?
141 .get(),
142 )?;
143 write_height(&mut bytes, *start_height)?;
144 bytes.write_u32::<LittleEndian>(*count)?;
145 bytes.write_u8(u8::from(*want_tree_aux_roots))?;
146 }
147 Self::Headers {
148 headers,
149 body_sizes,
150 tree_aux_roots,
151 } => {
152 validate_headers_len(headers.len(), usize_from_u32(MAX_HS_RANGE, "headers cap")?)?;
153 validate_body_sizes_len(headers.len(), body_sizes.len())?;
154 validate_tree_aux_roots_len(headers.len(), tree_aux_roots.len())?;
155 bytes.write_u64::<LittleEndian>(
156 request_id
157 .ok_or(HeaderSyncWireError::MissingRequestId { message: "Headers" })?
158 .get(),
159 )?;
160 bytes.write_u32::<LittleEndian>(u32_from_usize(headers.len(), "headers count")?)?;
161 bytes.write_u8(u8::from(!tree_aux_roots.is_empty()))?;
162 for (header, body_size) in headers.iter().zip(body_sizes) {
163 header.zcash_serialize(&mut bytes)?;
164 bytes.write_u32::<LittleEndian>(*body_size)?;
165 }
166 for roots in tree_aux_roots {
167 roots.zcash_serialize(&mut bytes)?;
168 }
169 }
170 Self::NewBlock(block) => {
171 block.zcash_serialize(&mut bytes)?;
172 }
173 }
174 if bytes.len() > MAX_HS_MESSAGE_BYTES {
175 return Err(HeaderSyncWireError::OversizedPayload {
176 actual: bytes.len(),
177 max: MAX_HS_MESSAGE_BYTES,
178 });
179 }
180 Ok(bytes)
181 }
182
183 pub fn decode(
187 bytes: &[u8],
188 context: HeaderSyncDecodeContext,
189 ) -> Result<(Self, Option<HeaderSyncRequestId>), HeaderSyncWireError> {
190 if bytes.len() > MAX_HS_MESSAGE_BYTES {
191 return Err(HeaderSyncWireError::OversizedPayload {
192 actual: bytes.len(),
193 max: MAX_HS_MESSAGE_BYTES,
194 });
195 }
196 let mut reader = Cursor::new(bytes);
197 let message_type = reader.read_u8()?;
198 let mut request_id = None;
199 let message = match message_type {
200 MSG_HS_STATUS => Self::Status(HeaderSyncStatus::decode_from(&mut reader)?),
201 MSG_HS_GET_HEADERS => {
202 request_id = HeaderSyncRequestId::new(reader.read_u64::<LittleEndian>()?);
203 if request_id.is_none() {
204 return Err(HeaderSyncWireError::MissingRequestId {
205 message: "GetHeaders",
206 });
207 }
208 let start_height = read_height(&mut reader)?;
209 let count = reader.read_u32::<LittleEndian>()?;
210 let want_tree_aux_roots = read_bool_marker(&mut reader, "want_tree_aux_roots")?;
211 validate_get_headers_count(count)?;
212 Self::GetHeaders {
213 start_height,
214 count,
215 want_tree_aux_roots,
216 }
217 }
218 MSG_HS_HEADERS => {
219 request_id = HeaderSyncRequestId::new(reader.read_u64::<LittleEndian>()?);
220 if request_id.is_none() {
221 return Err(HeaderSyncWireError::MissingRequestId { message: "Headers" });
222 }
223 let count = usize_from_u32(reader.read_u32::<LittleEndian>()?, "headers count")?;
224 let has_roots = read_bool_marker(&mut reader, "has_roots")?;
225 let Some(max_headers) = context.headers_response_limit()? else {
226 return Err(HeaderSyncWireError::UnsolicitedHeaders);
227 };
228 if has_roots && !context.wants_tree_aux_roots() {
229 return Err(HeaderSyncWireError::UnrequestedTreeAuxRoots);
230 }
231 validate_headers_len(count, max_headers)?;
232 let mut headers = Vec::with_capacity(count);
233 let mut body_sizes = Vec::with_capacity(count);
234 let mut tree_aux_roots = if has_roots {
235 Vec::with_capacity(count)
236 } else {
237 Vec::new()
238 };
239 for _ in 0..count {
240 headers.push(Arc::new(block::Header::zcash_deserialize(&mut reader)?));
241 body_sizes.push(reader.read_u32::<LittleEndian>()?);
242 }
243 if has_roots {
244 for _ in 0..count {
245 tree_aux_roots.push(BlockCommitmentRoots::zcash_deserialize(&mut reader)?);
246 }
247 }
248 validate_tree_aux_roots_len(count, tree_aux_roots.len())?;
249 if let Some(requested) = context.requested {
250 validate_tree_aux_root_heights(requested.start_height, &tree_aux_roots)?;
251 }
252 Self::Headers {
253 headers,
254 body_sizes,
255 tree_aux_roots,
256 }
257 }
258 MSG_HS_NEW_BLOCK => {
259 Self::NewBlock(Arc::new(block::Block::zcash_deserialize(&mut reader)?))
260 }
261 value => return Err(HeaderSyncWireError::UnknownMessageType(value)),
262 };
263 reject_trailing(bytes, &reader)?;
264 Ok((message, request_id))
265 }
266
267 pub fn peek_headers_request_id(
269 bytes: &[u8],
270 ) -> Result<HeaderSyncRequestId, HeaderSyncWireError> {
271 let mut reader = Cursor::new(bytes);
272 let message_type = reader.read_u8()?;
273 if message_type != MSG_HS_HEADERS {
274 return Err(HeaderSyncWireError::UnknownMessageType(message_type));
275 }
276 HeaderSyncRequestId::new(reader.read_u64::<LittleEndian>()?)
277 .ok_or(HeaderSyncWireError::MissingRequestId { message: "Headers" })
278 }
279
280 pub fn encode_frame(
282 &self,
283 request_id: Option<HeaderSyncRequestId>,
284 ) -> Result<Frame, HeaderSyncWireError> {
285 Ok(Frame {
286 message_type: u16::from(self.message_type()),
287 flags: 0,
288 payload: self.encode(request_id)?,
289 })
290 }
291
292 pub fn decode_frame(
295 frame: Frame,
296 context: HeaderSyncDecodeContext,
297 ) -> Result<(Self, Option<HeaderSyncRequestId>), HeaderSyncWireError> {
298 if frame.flags != 0 {
299 return Err(HeaderSyncWireError::UnsupportedFlags(frame.flags));
300 }
301 let (message, request_id) = Self::decode(&frame.payload, context)?;
302 let frame_message_type = u8::try_from(frame.message_type)
303 .map_err(|_| HeaderSyncWireError::UnknownFrameMessageType(frame.message_type))?;
304 if frame_message_type != message.message_type() {
305 return Err(HeaderSyncWireError::MismatchedFrameMessageType {
306 frame: frame.message_type,
307 payload: message.message_type(),
308 });
309 }
310 Ok((message, request_id))
311 }
312}