1use crate::ConsensusError;
13use crate::Result;
14use crate::error::ProtocolError;
15use crate::network::NetworkMessage;
16use std::borrow::Cow;
17use std::io::Read;
18use std::sync::Arc;
19
20mod frame_header;
21pub use frame_header::{MAX_MESSAGE_PAYLOAD, MESSAGE_HEADER_SIZE, calculate_checksum};
22
23pub fn serialize_message(message: &NetworkMessage, magic_bytes: [u8; 4]) -> Result<Vec<u8>> {
25 use crate::network::*;
26
27 let (command, payload) = match message {
29 NetworkMessage::Version(v) => ("version", serialize_version(v)?),
30 NetworkMessage::VerAck => ("verack", vec![]),
31 NetworkMessage::Addr(a) => ("addr", serialize_addr(a)?),
32 NetworkMessage::AddrV2(a) => ("addrv2", serialize_addrv2(a)?),
33 NetworkMessage::Inv(i) => ("inv", serialize_inv(i)?),
34 NetworkMessage::GetData(g) => ("getdata", serialize_getdata(g)?),
35 NetworkMessage::GetHeaders(gh) => ("getheaders", serialize_getheaders(gh)?),
36 NetworkMessage::Headers(h) => ("headers", serialize_headers(h)?),
37 NetworkMessage::Block(b, witnesses) => ("block", serialize_block_witnesses(b, witnesses)?),
38 NetworkMessage::Tx(tx) => ("tx", serialize_tx(tx)?),
39 NetworkMessage::Ping(p) => ("ping", serialize_ping(p)?),
40 NetworkMessage::Pong(p) => ("pong", serialize_pong(p)?),
41 NetworkMessage::MemPool => ("mempool", vec![]),
42 NetworkMessage::FeeFilter(f) => ("feefilter", serialize_feefilter(f)?),
43 NetworkMessage::GetBlocks(gb) => ("getblocks", serialize_getblocks(gb)?),
44 NetworkMessage::GetAddr => ("getaddr", vec![]),
45 NetworkMessage::NotFound(nf) => ("notfound", serialize_notfound(nf)?),
46 NetworkMessage::Reject(r) => ("reject", serialize_reject(r)?),
47 NetworkMessage::SendHeaders => ("sendheaders", vec![]),
48 NetworkMessage::SendCmpct(sc) => ("sendcmpct", serialize_sendcmpct(sc)?),
49 NetworkMessage::CmpctBlock(cb) => ("cmpctblock", serialize_cmpctblock(cb)?),
50 NetworkMessage::GetBlockTxn(gbt) => ("getblocktxn", serialize_getblocktxn(gbt)?),
51 NetworkMessage::BlockTxn(bt) => ("blocktxn", serialize_blocktxn(bt)?),
52 #[cfg(feature = "utxo-commitments")]
53 NetworkMessage::GetUTXOSet(gus) => ("getutxoset", serialize_getutxoset(gus)?),
54 #[cfg(feature = "utxo-commitments")]
55 NetworkMessage::UTXOSet(us) => ("utxoset", serialize_utxoset(us)?),
56 #[cfg(feature = "utxo-commitments")]
57 NetworkMessage::GetFilteredBlock(gfb) => {
58 ("getfilteredblock", serialize_getfilteredblock(gfb)?)
59 }
60 #[cfg(feature = "utxo-commitments")]
61 NetworkMessage::FilteredBlock(fb) => ("filteredblock", serialize_filteredblock(fb)?),
62 NetworkMessage::GetBanList(gbl) => ("getbanlist", serialize_getbanlist(gbl)?),
63 NetworkMessage::BanList(bl) => ("banlist", serialize_banlist(bl)?),
64 };
65
66 if payload.len() > MAX_MESSAGE_PAYLOAD {
68 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
69 Cow::Owned(format!(
70 "Message payload too large: {} bytes",
71 payload.len()
72 )),
73 )));
74 }
75
76 let checksum = calculate_checksum(&payload);
78
79 let mut message_bytes = Vec::with_capacity(MESSAGE_HEADER_SIZE + payload.len());
81
82 message_bytes.extend_from_slice(&magic_bytes);
84
85 let mut command_bytes = [0u8; 12];
87 let cmd_len = command.len().min(12);
88 command_bytes[..cmd_len].copy_from_slice(&command.as_bytes()[..cmd_len]);
89 message_bytes.extend_from_slice(&command_bytes);
90
91 message_bytes.extend_from_slice(&(payload.len() as u32).to_le_bytes());
93
94 message_bytes.extend_from_slice(&checksum);
96
97 message_bytes.extend_from_slice(&payload);
99
100 Ok(message_bytes)
101}
102
103pub fn deserialize_message<R: Read>(
105 reader: &mut R,
106 expected_magic: [u8; 4],
107) -> Result<(NetworkMessage, usize)> {
108 use crate::network::*;
109
110 let mut header = [0u8; MESSAGE_HEADER_SIZE];
112 reader.read_exact(&mut header).map_err(|e| {
113 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
114 "IO error: {e}"
115 ))))
116 })?;
117
118 let magic = [header[0], header[1], header[2], header[3]];
120 if magic != expected_magic {
121 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
122 Cow::Owned(format!(
123 "Invalid magic bytes: {magic:?}, expected {expected_magic:?}"
124 )),
125 )));
126 }
127
128 let command_bytes = &header[4..16];
130 let command_len = command_bytes.iter().position(|&b| b == 0).unwrap_or(12);
131 let command = std::str::from_utf8(&command_bytes[..command_len]).map_err(|e| {
132 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
133 "Invalid command: {e}"
134 ))))
135 })?;
136
137 let length_bytes = [header[16], header[17], header[18], header[19]];
139 let payload_length = u32::from_le_bytes(length_bytes) as usize;
140
141 if payload_length > MAX_MESSAGE_PAYLOAD {
142 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
143 Cow::Owned(format!("Payload length too large: {payload_length} bytes")),
144 )));
145 }
146
147 let checksum = [header[20], header[21], header[22], header[23]];
149
150 let mut payload = vec![0u8; payload_length];
152 if payload_length > 0 {
153 reader.read_exact(&mut payload).map_err(|e| {
154 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
155 "IO error: {e}"
156 ))))
157 })?;
158 }
159
160 let calculated_checksum = calculate_checksum(&payload);
162 if calculated_checksum != checksum {
163 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
164 Cow::Owned("Checksum mismatch".to_string()),
165 )));
166 }
167
168 let message = match command {
170 "version" => NetworkMessage::Version(deserialize_version(&payload)?),
171 "verack" => NetworkMessage::VerAck,
172 "addr" => NetworkMessage::Addr(deserialize_addr(&payload)?),
173 "addrv2" => NetworkMessage::AddrV2(deserialize_addrv2(&payload)?),
174 "inv" => NetworkMessage::Inv(deserialize_inv(&payload)?),
175 "getdata" => NetworkMessage::GetData(deserialize_getdata(&payload)?),
176 "getheaders" => NetworkMessage::GetHeaders(deserialize_getheaders(&payload)?),
177 "headers" => NetworkMessage::Headers(deserialize_headers(&payload)?),
178 "block" => {
179 let (block, witnesses) = deserialize_block_with_witnesses_pair(&payload)?;
180 NetworkMessage::Block(Arc::new(block), witnesses)
181 }
182 "tx" => NetworkMessage::Tx(Arc::new(deserialize_tx(&payload)?)),
183 "ping" => NetworkMessage::Ping(deserialize_ping(&payload)?),
184 "pong" => NetworkMessage::Pong(deserialize_pong(&payload)?),
185 "mempool" => NetworkMessage::MemPool,
186 "feefilter" => NetworkMessage::FeeFilter(deserialize_feefilter(&payload)?),
187 "getblocks" => NetworkMessage::GetBlocks(deserialize_getblocks(&payload)?),
188 "getaddr" => NetworkMessage::GetAddr,
189 "notfound" => NetworkMessage::NotFound(deserialize_notfound(&payload)?),
190 "reject" => NetworkMessage::Reject(deserialize_reject(&payload)?),
191 "sendheaders" => NetworkMessage::SendHeaders,
192 "sendcmpct" => NetworkMessage::SendCmpct(deserialize_sendcmpct(&payload)?),
193 "cmpctblock" => NetworkMessage::CmpctBlock(deserialize_cmpctblock(&payload)?),
194 "getblocktxn" => NetworkMessage::GetBlockTxn(deserialize_getblocktxn(&payload)?),
195 "blocktxn" => NetworkMessage::BlockTxn(deserialize_blocktxn(&payload)?),
196 #[cfg(feature = "utxo-commitments")]
197 "getutxoset" => NetworkMessage::GetUTXOSet(deserialize_getutxoset(&payload)?),
198 #[cfg(feature = "utxo-commitments")]
199 "utxoset" => NetworkMessage::UTXOSet(deserialize_utxoset(&payload)?),
200 #[cfg(feature = "utxo-commitments")]
201 "getfilteredblock" => {
202 NetworkMessage::GetFilteredBlock(deserialize_getfilteredblock(&payload)?)
203 }
204 #[cfg(feature = "utxo-commitments")]
205 "filteredblock" => NetworkMessage::FilteredBlock(deserialize_filteredblock(&payload)?),
206 "getbanlist" => NetworkMessage::GetBanList(deserialize_getbanlist(&payload)?),
207 "banlist" => NetworkMessage::BanList(deserialize_banlist(&payload)?),
208 _ => {
209 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
210 Cow::Owned(format!("Unknown command: {command}")),
211 )));
212 }
213 };
214
215 Ok((message, MESSAGE_HEADER_SIZE + payload_length))
216}
217
218fn serialize_network_address(addr: &crate::network::NetworkAddress) -> Vec<u8> {
223 let mut buf = Vec::with_capacity(26);
224 buf.extend_from_slice(&addr.services.to_le_bytes());
226 buf.extend_from_slice(&addr.ip);
228 buf.extend_from_slice(&addr.port.to_be_bytes());
230 buf
231}
232
233fn deserialize_network_address(data: &[u8]) -> Result<crate::network::NetworkAddress> {
235 if data.len() < 26 {
236 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
237 Cow::Owned("NetworkAddress too short".to_string()),
238 )));
239 }
240
241 let services = u64::from_le_bytes([
243 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
244 ]);
245
246 let mut ip = [0u8; 16];
248 ip.copy_from_slice(&data[8..24]);
249
250 let port = u16::from_be_bytes([data[24], data[25]]);
252
253 Ok(crate::network::NetworkAddress { services, ip, port })
254}
255
256pub fn serialize_version(v: &crate::network::VersionMessage) -> Result<Vec<u8>> {
268 use crate::varint::write_varint;
269
270 let mut buf = Vec::new();
271
272 buf.extend_from_slice(&(v.version as i32).to_le_bytes());
275
276 buf.extend_from_slice(&v.services.to_le_bytes());
278
279 buf.extend_from_slice(&v.timestamp.to_le_bytes());
281
282 buf.extend_from_slice(&serialize_network_address(&v.addr_recv));
284
285 buf.extend_from_slice(&serialize_network_address(&v.addr_from));
287
288 buf.extend_from_slice(&v.nonce.to_le_bytes());
290
291 let user_agent_bytes = v.user_agent.as_bytes();
293 write_varint(&mut buf, user_agent_bytes.len() as u64)?;
294 buf.extend_from_slice(user_agent_bytes);
295
296 buf.extend_from_slice(&v.start_height.to_le_bytes());
298
299 buf.push(if v.relay { 1 } else { 0 });
301
302 Ok(buf)
303}
304
305pub fn deserialize_version(data: &[u8]) -> Result<crate::network::VersionMessage> {
307 use crate::varint::read_varint;
308 use std::io::Cursor;
309
310 let mut cursor = Cursor::new(data);
311
312 let mut version_bytes = [0u8; 4];
314 cursor.read_exact(&mut version_bytes).map_err(|e| {
315 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
316 "Failed to read version: {e}"
317 ))))
318 })?;
319 let version = i32::from_le_bytes(version_bytes) as u32;
320
321 let mut services_bytes = [0u8; 8];
323 cursor.read_exact(&mut services_bytes).map_err(|e| {
324 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
325 "Failed to read services: {e}"
326 ))))
327 })?;
328 let services = u64::from_le_bytes(services_bytes);
329
330 let mut timestamp_bytes = [0u8; 8];
332 cursor.read_exact(&mut timestamp_bytes).map_err(|e| {
333 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
334 "Failed to read timestamp: {e}"
335 ))))
336 })?;
337 let timestamp = i64::from_le_bytes(timestamp_bytes);
338
339 let mut addr_recv_bytes = [0u8; 26];
341 cursor.read_exact(&mut addr_recv_bytes).map_err(|e| {
342 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
343 "Failed to read addr_recv: {e}"
344 ))))
345 })?;
346 let addr_recv = deserialize_network_address(&addr_recv_bytes)?;
347
348 let mut addr_from_bytes = [0u8; 26];
350 cursor.read_exact(&mut addr_from_bytes).map_err(|e| {
351 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
352 "Failed to read addr_from: {e}"
353 ))))
354 })?;
355 let addr_from = deserialize_network_address(&addr_from_bytes)?;
356
357 let mut nonce_bytes = [0u8; 8];
359 cursor.read_exact(&mut nonce_bytes).map_err(|e| {
360 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
361 "Failed to read nonce: {e}"
362 ))))
363 })?;
364 let nonce = u64::from_le_bytes(nonce_bytes);
365
366 let user_agent_len = read_varint(&mut cursor)?;
368 if user_agent_len > 10000 {
369 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
370 Cow::Owned("User agent too long".to_string()),
371 )));
372 }
373 let mut user_agent_bytes = vec![0u8; user_agent_len as usize];
374 cursor.read_exact(&mut user_agent_bytes).map_err(|e| {
375 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
376 "Failed to read user_agent: {e}"
377 ))))
378 })?;
379 let user_agent = String::from_utf8(user_agent_bytes).map_err(|e| {
380 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
381 "Invalid user_agent UTF-8: {e}"
382 ))))
383 })?;
384
385 let mut start_height_bytes = [0u8; 4];
387 cursor.read_exact(&mut start_height_bytes).map_err(|e| {
388 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
389 "Failed to read start_height: {e}"
390 ))))
391 })?;
392 let start_height = i32::from_le_bytes(start_height_bytes);
393
394 let relay = {
396 let mut relay_byte = [0u8; 1];
397 match cursor.read_exact(&mut relay_byte) {
398 Ok(_) => relay_byte[0] != 0,
399 Err(_) => true, }
401 };
402
403 Ok(crate::network::VersionMessage {
404 version,
405 services,
406 timestamp,
407 addr_recv,
408 addr_from,
409 nonce,
410 user_agent,
411 start_height,
412 relay,
413 })
414}
415
416pub fn serialize_addr(a: &crate::network::AddrMessage) -> Result<Vec<u8>> {
419 use crate::varint::write_varint;
420
421 let mut buf = Vec::new();
422 write_varint(&mut buf, a.addresses.len() as u64)?;
423
424 for addr in &a.addresses {
425 buf.extend_from_slice(&0u32.to_le_bytes());
427 buf.extend_from_slice(&addr.services.to_le_bytes());
429 buf.extend_from_slice(&addr.ip);
431 buf.extend_from_slice(&addr.port.to_be_bytes());
433 }
434 Ok(buf)
435}
436pub fn deserialize_addr(data: &[u8]) -> Result<crate::network::AddrMessage> {
437 use crate::varint::read_varint;
438 use std::io::Read;
439
440 let mut cursor = std::io::Cursor::new(data);
441 let count = read_varint(&mut cursor)?;
442 if count > 1000 {
443 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
444 Cow::Owned("Too many addresses in addr".to_string()),
445 )));
446 }
447
448 let mut addresses = Vec::with_capacity(count as usize);
449 for _ in 0..count {
450 let mut time_bytes = [0u8; 4];
451 cursor.read_exact(&mut time_bytes).map_err(|e| {
452 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
453 "Addr time: {e}"
454 ))))
455 })?;
456 let _time = u32::from_le_bytes(time_bytes);
457
458 let mut services_bytes = [0u8; 8];
459 cursor.read_exact(&mut services_bytes).map_err(|e| {
460 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
461 "Addr services: {e}"
462 ))))
463 })?;
464 let services = u64::from_le_bytes(services_bytes);
465
466 let mut ip = [0u8; 16];
467 cursor.read_exact(&mut ip).map_err(|e| {
468 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
469 "Addr ip: {e}"
470 ))))
471 })?;
472
473 let mut port_bytes = [0u8; 2];
474 cursor.read_exact(&mut port_bytes).map_err(|e| {
475 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
476 "Addr port: {e}"
477 ))))
478 })?;
479 let port = u16::from_be_bytes(port_bytes);
480
481 addresses.push(crate::network::NetworkAddress { services, ip, port });
482 }
483 Ok(crate::network::AddrMessage { addresses })
484}
485
486pub fn serialize_addrv2(addrv2: &crate::network::AddrV2Message) -> Result<Vec<u8>> {
489 use crate::varint::write_varint;
490
491 let mut buf = Vec::new();
492
493 write_varint(&mut buf, addrv2.addresses.len() as u64)?;
495
496 for addr in &addrv2.addresses {
498 buf.extend_from_slice(&addr.time.to_le_bytes());
500
501 buf.extend_from_slice(&addr.services.to_le_bytes());
503
504 buf.push(addr.address_type as u8);
506
507 buf.extend_from_slice(&addr.address);
509
510 buf.extend_from_slice(&addr.port.to_be_bytes());
512 }
513
514 Ok(buf)
515}
516
517pub fn deserialize_addrv2(data: &[u8]) -> Result<crate::network::AddrV2Message> {
519 use crate::varint::read_varint;
520 use std::io::Cursor;
521
522 let mut cursor = Cursor::new(data);
523
524 let count = read_varint(&mut cursor)?;
526 if count > 1000 {
527 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
528 Cow::Owned("Too many addresses in addrv2".to_string()),
529 )));
530 }
531
532 let mut addresses = Vec::with_capacity(count as usize);
533
534 for _ in 0..count {
536 let mut time_bytes = [0u8; 4];
538 cursor.read_exact(&mut time_bytes).map_err(|e| {
539 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
540 "Failed to read time: {e}"
541 ))))
542 })?;
543 let time = u32::from_le_bytes(time_bytes);
544
545 let mut services_bytes = [0u8; 8];
547 cursor.read_exact(&mut services_bytes).map_err(|e| {
548 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
549 "Failed to read services: {e}"
550 ))))
551 })?;
552 let services = u64::from_le_bytes(services_bytes);
553
554 let mut addr_type_byte = [0u8; 1];
556 cursor.read_exact(&mut addr_type_byte).map_err(|e| {
557 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
558 "Failed to read address_type: {e}"
559 ))))
560 })?;
561 let address_type =
562 crate::network::AddressType::from_u8(addr_type_byte[0]).ok_or_else(|| {
563 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
564 "Invalid address type: {}",
565 addr_type_byte[0]
566 ))))
567 })?;
568
569 let addr_len = address_type.address_length();
571 let mut address = vec![0u8; addr_len];
572 cursor.read_exact(&mut address).map_err(|e| {
573 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
574 "Failed to read address: {e}"
575 ))))
576 })?;
577
578 let mut port_bytes = [0u8; 2];
580 cursor.read_exact(&mut port_bytes).map_err(|e| {
581 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
582 "Failed to read port: {e}"
583 ))))
584 })?;
585 let port = u16::from_be_bytes(port_bytes);
586
587 let addr_v2 =
589 crate::network::NetworkAddressV2::new(time, services, address_type, address, port)?;
590
591 addresses.push(addr_v2);
592 }
593
594 Ok(crate::network::AddrV2Message { addresses })
595}
596
597pub fn serialize_inv(i: &crate::network::InvMessage) -> Result<Vec<u8>> {
600 use crate::varint::write_varint;
601
602 let capacity = 9 + (36 * i.inventory.len()); let mut buf = Vec::with_capacity(capacity);
604
605 write_varint(&mut buf, i.inventory.len() as u64)?;
606
607 for item in &i.inventory {
608 buf.extend_from_slice(&item.inv_type.to_le_bytes());
609 buf.extend_from_slice(&item.hash);
610 }
611
612 Ok(buf)
613}
614
615pub fn deserialize_inv(data: &[u8]) -> Result<crate::network::InvMessage> {
617 use crate::varint::read_varint;
618 use std::io::Cursor;
619
620 if data.is_empty() {
621 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
622 Cow::Owned("Inv message is empty".to_string()),
623 )));
624 }
625
626 let mut cursor = Cursor::new(data);
627
628 let count = read_varint(&mut cursor)? as usize;
629
630 if count > 50000 {
632 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
633 Cow::Owned(format!("Too many inventory items: {count}")),
634 )));
635 }
636
637 let mut inventory = Vec::with_capacity(count);
638
639 for _ in 0..count {
640 let mut type_bytes = [0u8; 4];
641 std::io::Read::read_exact(&mut cursor, &mut type_bytes).map_err(|e| {
642 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
643 })?;
644 let inv_type = u32::from_le_bytes(type_bytes);
645
646 let mut hash = [0u8; 32];
647 std::io::Read::read_exact(&mut cursor, &mut hash).map_err(|e| {
648 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
649 })?;
650
651 inventory.push(crate::network::InventoryVector { inv_type, hash });
652 }
653
654 Ok(crate::network::InvMessage { inventory })
655}
656
657pub fn serialize_getdata(g: &crate::network::GetDataMessage) -> Result<Vec<u8>> {
660 use crate::varint::write_varint;
661
662 let capacity = 9 + (36 * g.inventory.len());
663 let mut buf = Vec::with_capacity(capacity);
664
665 write_varint(&mut buf, g.inventory.len() as u64)?;
666
667 for item in &g.inventory {
668 buf.extend_from_slice(&item.inv_type.to_le_bytes());
669 buf.extend_from_slice(&item.hash);
670 }
671
672 Ok(buf)
673}
674
675pub fn deserialize_getdata(data: &[u8]) -> Result<crate::network::GetDataMessage> {
677 use crate::varint::read_varint;
678 use std::io::Cursor;
679
680 if data.is_empty() {
681 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
682 Cow::Owned("GetData message is empty".to_string()),
683 )));
684 }
685
686 let mut cursor = Cursor::new(data);
687
688 let count = read_varint(&mut cursor)? as usize;
689
690 if count > 50000 {
691 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
692 Cow::Owned(format!("Too many inventory items: {count}")),
693 )));
694 }
695
696 let mut inventory = Vec::with_capacity(count);
697
698 for _ in 0..count {
699 let mut type_bytes = [0u8; 4];
700 std::io::Read::read_exact(&mut cursor, &mut type_bytes).map_err(|e| {
701 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
702 })?;
703 let inv_type = u32::from_le_bytes(type_bytes);
704
705 let mut hash = [0u8; 32];
706 std::io::Read::read_exact(&mut cursor, &mut hash).map_err(|e| {
707 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
708 })?;
709
710 inventory.push(crate::network::InventoryVector { inv_type, hash });
711 }
712
713 Ok(crate::network::GetDataMessage { inventory })
714}
715
716pub fn serialize_getheaders(gh: &crate::network::GetHeadersMessage) -> Result<Vec<u8>> {
719 use crate::varint::write_varint;
720 use std::io::Cursor;
721
722 let capacity = 4 + 9 + (32 * gh.block_locator_hashes.len()) + 32;
724 let mut buf = Vec::with_capacity(capacity);
725
726 buf.extend_from_slice(&(gh.version as i32).to_le_bytes());
728
729 let mut cursor = Cursor::new(&mut buf);
731 cursor.set_position(4);
732 write_varint(&mut buf, gh.block_locator_hashes.len() as u64)?;
733
734 for hash in &gh.block_locator_hashes {
736 buf.extend_from_slice(hash);
737 }
738
739 buf.extend_from_slice(&gh.hash_stop);
741
742 Ok(buf)
743}
744
745pub fn deserialize_getheaders(data: &[u8]) -> Result<crate::network::GetHeadersMessage> {
747 use crate::varint::read_varint;
748 use std::io::Cursor;
749
750 if data.len() < 4 + 1 + 32 {
751 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
752 Cow::Owned("GetHeaders message too short".to_string()),
753 )));
754 }
755
756 let mut cursor = Cursor::new(data);
757
758 let mut version_bytes = [0u8; 4];
760 std::io::Read::read_exact(&mut cursor, &mut version_bytes).map_err(|e| {
761 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
762 })?;
763 let version = i32::from_le_bytes(version_bytes) as u32;
764
765 let hash_count = read_varint(&mut cursor)? as usize;
767
768 if hash_count > 2000 {
770 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
771 Cow::Owned(format!("Too many locator hashes: {hash_count}")),
772 )));
773 }
774
775 let mut block_locator_hashes = Vec::with_capacity(hash_count);
777 for _ in 0..hash_count {
778 let mut hash = [0u8; 32];
779 std::io::Read::read_exact(&mut cursor, &mut hash).map_err(|e| {
780 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
781 })?;
782 block_locator_hashes.push(hash);
783 }
784
785 let mut hash_stop = [0u8; 32];
787 std::io::Read::read_exact(&mut cursor, &mut hash_stop).map_err(|e| {
788 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
789 })?;
790
791 Ok(crate::network::GetHeadersMessage {
792 version,
793 block_locator_hashes,
794 hash_stop,
795 })
796}
797
798pub fn serialize_headers(h: &crate::network::HeadersMessage) -> Result<Vec<u8>> {
801 use crate::varint::write_varint;
802
803 let capacity = 9 + (81 * h.headers.len());
805 let mut buf = Vec::with_capacity(capacity);
806
807 write_varint(&mut buf, h.headers.len() as u64)?;
809
810 for header in &h.headers {
812 buf.extend_from_slice(&(header.version as i32).to_le_bytes());
814 buf.extend_from_slice(&header.prev_block_hash);
816 buf.extend_from_slice(&header.merkle_root);
818 buf.extend_from_slice(&(header.timestamp as u32).to_le_bytes());
820 buf.extend_from_slice(&(header.bits as u32).to_le_bytes());
822 buf.extend_from_slice(&(header.nonce as u32).to_le_bytes());
824 buf.push(0);
826 }
827
828 Ok(buf)
829}
830
831pub fn deserialize_headers(data: &[u8]) -> Result<crate::network::HeadersMessage> {
833 use crate::varint::read_varint;
834 use std::io::Cursor;
835
836 if data.is_empty() {
837 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
838 Cow::Owned("Headers message is empty".to_string()),
839 )));
840 }
841
842 let mut cursor = Cursor::new(data);
843
844 let header_count = read_varint(&mut cursor)? as usize;
846
847 if header_count > 2000 {
849 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
850 Cow::Owned(format!("Too many headers: {header_count}")),
851 )));
852 }
853
854 let mut headers = Vec::with_capacity(header_count);
855
856 for _ in 0..header_count {
857 let mut version_bytes = [0u8; 4];
859 std::io::Read::read_exact(&mut cursor, &mut version_bytes).map_err(|e| {
860 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
861 })?;
862 let version = i32::from_le_bytes(version_bytes) as i64;
863
864 let mut prev_block_hash = [0u8; 32];
866 std::io::Read::read_exact(&mut cursor, &mut prev_block_hash).map_err(|e| {
867 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
868 })?;
869
870 let mut merkle_root = [0u8; 32];
872 std::io::Read::read_exact(&mut cursor, &mut merkle_root).map_err(|e| {
873 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
874 })?;
875
876 let mut timestamp_bytes = [0u8; 4];
878 std::io::Read::read_exact(&mut cursor, &mut timestamp_bytes).map_err(|e| {
879 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
880 })?;
881 let timestamp = u32::from_le_bytes(timestamp_bytes) as u64;
882
883 let mut bits_bytes = [0u8; 4];
885 std::io::Read::read_exact(&mut cursor, &mut bits_bytes).map_err(|e| {
886 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
887 })?;
888 let bits = u32::from_le_bytes(bits_bytes) as u64;
889
890 let mut nonce_bytes = [0u8; 4];
892 std::io::Read::read_exact(&mut cursor, &mut nonce_bytes).map_err(|e| {
893 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
894 })?;
895 let nonce = u32::from_le_bytes(nonce_bytes) as u64;
896
897 let _tx_count = read_varint(&mut cursor)?;
899
900 headers.push(crate::BlockHeader {
901 version,
902 prev_block_hash,
903 merkle_root,
904 timestamp,
905 bits,
906 nonce,
907 });
908 }
909
910 Ok(crate::network::HeadersMessage { headers })
911}
912
913pub fn serialize_block_witnesses(
918 b: &crate::Block,
919 witnesses: &[Vec<blvm_consensus::segwit::Witness>],
920) -> Result<Vec<u8>> {
921 use crate::serialization::serialize_block_with_witnesses;
922
923 let include_witness = !witnesses.is_empty() && witnesses.iter().any(|tx_w| !tx_w.is_empty());
924
925 let padded;
927 let ws: &[Vec<blvm_consensus::segwit::Witness>] = if witnesses.len() < b.transactions.len() {
928 padded = {
929 let mut v = witnesses.to_vec();
930 v.resize(b.transactions.len(), Vec::new());
931 v
932 };
933 &padded
934 } else {
935 witnesses
936 };
937
938 Ok(serialize_block_with_witnesses(b, ws, include_witness))
939}
940
941pub fn deserialize_block_with_witnesses_pair(
946 data: &[u8],
947) -> Result<(crate::Block, Vec<Vec<blvm_consensus::segwit::Witness>>)> {
948 use crate::serialization::block::deserialize_block_with_witnesses;
949
950 deserialize_block_with_witnesses(data).map_err(|e| {
951 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
952 })
953}
954
955pub fn deserialize_block(data: &[u8]) -> Result<crate::Block> {
960 let (block, _witnesses) = deserialize_block_with_witnesses_pair(data)?;
961 Ok(block)
962}
963
964pub fn serialize_tx(tx: &crate::Transaction) -> Result<Vec<u8>> {
965 Ok(crate::serialization::serialize_transaction(tx))
966}
967pub fn deserialize_tx(data: &[u8]) -> Result<crate::Transaction> {
968 crate::serialization::deserialize_transaction(data).map_err(|e| {
969 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
970 })
971}
972
973pub fn serialize_ping(p: &crate::network::PingMessage) -> Result<Vec<u8>> {
975 Ok(p.nonce.to_le_bytes().to_vec())
976}
977
978pub fn deserialize_ping(data: &[u8]) -> Result<crate::network::PingMessage> {
980 if data.len() < 8 {
981 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
982 Cow::Owned(format!("Ping message too short: {} bytes", data.len())),
983 )));
984 }
985
986 let nonce = u64::from_le_bytes([
987 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
988 ]);
989
990 Ok(crate::network::PingMessage { nonce })
991}
992
993pub fn serialize_pong(p: &crate::network::PongMessage) -> Result<Vec<u8>> {
995 Ok(p.nonce.to_le_bytes().to_vec())
996}
997
998pub fn deserialize_pong(data: &[u8]) -> Result<crate::network::PongMessage> {
1000 if data.len() < 8 {
1001 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1002 Cow::Owned(format!("Pong message too short: {} bytes", data.len())),
1003 )));
1004 }
1005
1006 let nonce = u64::from_le_bytes([
1007 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
1008 ]);
1009
1010 Ok(crate::network::PongMessage { nonce })
1011}
1012
1013pub fn serialize_feefilter(f: &crate::network::FeeFilterMessage) -> Result<Vec<u8>> {
1015 Ok(f.feerate.to_le_bytes().to_vec())
1016}
1017pub fn deserialize_feefilter(data: &[u8]) -> Result<crate::network::FeeFilterMessage> {
1018 if data.len() < 8 {
1019 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1020 Cow::Owned("FeeFilter message too short".to_string()),
1021 )));
1022 }
1023 let feerate = u64::from_le_bytes([
1024 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
1025 ]);
1026 Ok(crate::network::FeeFilterMessage { feerate })
1027}
1028
1029pub fn serialize_getblocks(gb: &crate::network::GetBlocksMessage) -> Result<Vec<u8>> {
1031 use crate::varint::write_varint;
1032
1033 let mut buf = Vec::new();
1034 buf.extend_from_slice(&gb.version.to_le_bytes());
1035 write_varint(&mut buf, gb.block_locator_hashes.len() as u64)?;
1036 for hash in &gb.block_locator_hashes {
1037 buf.extend_from_slice(hash);
1038 }
1039 buf.extend_from_slice(&gb.hash_stop);
1040 Ok(buf)
1041}
1042pub fn deserialize_getblocks(data: &[u8]) -> Result<crate::network::GetBlocksMessage> {
1043 use crate::varint::read_varint;
1044 use std::io::Read;
1045
1046 if data.len() < 4 {
1047 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1048 Cow::Owned("GetBlocks message too short".to_string()),
1049 )));
1050 }
1051 let mut cursor = std::io::Cursor::new(data);
1052 let version = u32::from_le_bytes([data[0], data[1], data[2], data[3]]);
1053 cursor.set_position(4);
1054
1055 let count = read_varint(&mut cursor)? as usize;
1056 if count > 101 {
1057 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1058 Cow::Owned("GetBlocks locator too long".to_string()),
1059 )));
1060 }
1061 let mut block_locator_hashes = Vec::with_capacity(count);
1062 for _ in 0..count {
1063 let mut hash = [0u8; 32];
1064 cursor.read_exact(&mut hash).map_err(|e| {
1065 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
1066 "GetBlocks: {e}"
1067 ))))
1068 })?;
1069 block_locator_hashes.push(hash);
1070 }
1071 let mut hash_stop = [0u8; 32];
1072 cursor.read_exact(&mut hash_stop).map_err(|e| {
1073 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
1074 "GetBlocks hash_stop: {e}"
1075 ))))
1076 })?;
1077
1078 Ok(crate::network::GetBlocksMessage {
1079 version,
1080 block_locator_hashes,
1081 hash_stop,
1082 })
1083}
1084
1085pub fn serialize_notfound(nf: &crate::network::NotFoundMessage) -> Result<Vec<u8>> {
1088 use crate::varint::write_varint;
1089
1090 let capacity = 9 + (36 * nf.inventory.len());
1091 let mut buf = Vec::with_capacity(capacity);
1092
1093 write_varint(&mut buf, nf.inventory.len() as u64)?;
1094
1095 for item in &nf.inventory {
1096 buf.extend_from_slice(&item.inv_type.to_le_bytes());
1097 buf.extend_from_slice(&item.hash);
1098 }
1099
1100 Ok(buf)
1101}
1102
1103pub fn deserialize_notfound(data: &[u8]) -> Result<crate::network::NotFoundMessage> {
1105 use crate::varint::read_varint;
1106 use std::io::Cursor;
1107
1108 if data.is_empty() {
1109 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1110 Cow::Owned("NotFound message is empty".to_string()),
1111 )));
1112 }
1113
1114 let mut cursor = Cursor::new(data);
1115
1116 let count = read_varint(&mut cursor)? as usize;
1117
1118 if count > 50000 {
1119 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1120 Cow::Owned(format!("Too many inventory items: {count}")),
1121 )));
1122 }
1123
1124 let mut inventory = Vec::with_capacity(count);
1125
1126 for _ in 0..count {
1127 let mut type_bytes = [0u8; 4];
1128 std::io::Read::read_exact(&mut cursor, &mut type_bytes).map_err(|e| {
1129 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1130 })?;
1131 let inv_type = u32::from_le_bytes(type_bytes);
1132
1133 let mut hash = [0u8; 32];
1134 std::io::Read::read_exact(&mut cursor, &mut hash).map_err(|e| {
1135 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1136 })?;
1137
1138 inventory.push(crate::network::InventoryVector { inv_type, hash });
1139 }
1140
1141 Ok(crate::network::NotFoundMessage { inventory })
1142}
1143
1144pub fn serialize_reject(r: &crate::network::RejectMessage) -> Result<Vec<u8>> {
1146 use crate::varint::write_varint;
1147
1148 let mut buf = Vec::with_capacity(12 + 1 + 9 + r.reason.len() + 32);
1149 let msg_bytes = r.message.as_bytes();
1150 if msg_bytes.len() > 12 {
1151 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1152 Cow::Owned("Reject message field too long".to_string()),
1153 )));
1154 }
1155 buf.extend_from_slice(msg_bytes);
1156 buf.extend_from_slice(&[0u8; 12][msg_bytes.len()..]);
1157
1158 buf.push(r.code);
1159
1160 write_varint(&mut buf, r.reason.len() as u64)?;
1161 buf.extend_from_slice(r.reason.as_bytes());
1162
1163 if let Some(ref h) = r.extra_data {
1164 buf.extend_from_slice(h);
1165 }
1166 Ok(buf)
1167}
1168pub fn deserialize_reject(data: &[u8]) -> Result<crate::network::RejectMessage> {
1169 use crate::varint::read_varint;
1170
1171 if data.len() < 13 {
1172 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1173 Cow::Owned("Reject message too short".to_string()),
1174 )));
1175 }
1176 let message = String::from_utf8_lossy(&data[0..12])
1177 .trim_end_matches('\0')
1178 .to_string();
1179 let code = data[12];
1180 let mut cursor = std::io::Cursor::new(&data[13..]);
1181 let reason_len_u64 = read_varint(&mut cursor)?;
1182 let pos: usize = 13_usize.saturating_add(cursor.position() as usize);
1183 if reason_len_u64 > (data.len() as u64).saturating_sub(pos as u64) {
1184 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1185 Cow::Owned("Reject reason truncated".to_string()),
1186 )));
1187 }
1188 let reason_len: usize = reason_len_u64.try_into().map_err(|_| {
1189 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1190 "Reject reason length out of range".to_string(),
1191 )))
1192 })?;
1193 let end = pos.checked_add(reason_len).ok_or_else(|| {
1194 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1195 "Reject reason length out of range".to_string(),
1196 )))
1197 })?;
1198 if end > data.len() {
1199 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1200 Cow::Owned("Reject reason truncated".to_string()),
1201 )));
1202 }
1203 let reason = String::from_utf8_lossy(&data[pos..end]).to_string();
1204 let pos = end;
1205 let extra_data = if data.len() >= pos + 32 {
1206 Some({
1207 let mut h = [0u8; 32];
1208 h.copy_from_slice(&data[pos..pos + 32]);
1209 h
1210 })
1211 } else {
1212 None
1213 };
1214 Ok(crate::network::RejectMessage {
1215 message,
1216 code,
1217 reason,
1218 extra_data,
1219 })
1220}
1221
1222pub fn serialize_sendcmpct(sc: &crate::network::SendCmpctMessage) -> Result<Vec<u8>> {
1224 let mut buf = Vec::with_capacity(9);
1225 buf.push(sc.prefer_cmpct);
1226 buf.extend_from_slice(&sc.version.to_le_bytes());
1227 Ok(buf)
1228}
1229pub fn deserialize_sendcmpct(data: &[u8]) -> Result<crate::network::SendCmpctMessage> {
1230 if data.len() < 9 {
1231 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1232 Cow::Owned("SendCmpct message too short".to_string()),
1233 )));
1234 }
1235 Ok(crate::network::SendCmpctMessage {
1236 prefer_cmpct: data[0],
1237 version: u64::from_le_bytes([
1238 data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8],
1239 ]),
1240 })
1241}
1242
1243pub fn serialize_cmpctblock(cb: &crate::network::CmpctBlockMessage) -> Result<Vec<u8>> {
1245 use crate::varint::write_varint;
1246
1247 let mut buf = Vec::new();
1248 buf.extend_from_slice(&crate::serialization::serialize_block_header(&cb.header));
1249 buf.extend_from_slice(&cb.nonce.to_le_bytes());
1250 write_varint(&mut buf, cb.short_ids.len() as u64)?;
1251 for sid in &cb.short_ids {
1252 buf.extend_from_slice(sid);
1253 }
1254 write_varint(&mut buf, cb.prefilled_txs.len() as u64)?;
1255 let mut last_index = -1i64;
1256 for pt in &cb.prefilled_txs {
1257 let diff = (pt.index as i64) - last_index - 1;
1258 write_varint(&mut buf, diff as u64)?;
1259 last_index = pt.index as i64;
1260 let tx_bytes = match &pt.witness {
1261 Some(wit) if wit.iter().any(|w| !w.is_empty()) => {
1262 crate::serialization::serialize_transaction_with_witness(&pt.tx, wit)
1263 }
1264 _ => crate::serialization::serialize_transaction(&pt.tx),
1265 };
1266 buf.extend_from_slice(&tx_bytes);
1267 }
1268 Ok(buf)
1269}
1270pub fn deserialize_cmpctblock(data: &[u8]) -> Result<crate::network::CmpctBlockMessage> {
1271 use crate::varint::read_varint;
1272 use std::io::Read;
1273
1274 const MAX_CMPCT_SHORTIDS: u64 = 50_000;
1276 const MAX_CMPCT_PREFILLED: u64 = 50_000;
1277
1278 if data.len() < 80 + 8 {
1279 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1280 Cow::Owned("CmpctBlock message too short".to_string()),
1281 )));
1282 }
1283 let header = crate::serialization::deserialize_block_header(&data[0..80]).map_err(|e| {
1284 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1285 })?;
1286 let nonce = u64::from_le_bytes([
1287 data[80], data[81], data[82], data[83], data[84], data[85], data[86], data[87],
1288 ]);
1289 let mut cursor = std::io::Cursor::new(&data[88..]);
1290 let shortids_len_u64 = read_varint(&mut cursor)?;
1291 if shortids_len_u64 > MAX_CMPCT_SHORTIDS {
1292 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1293 Cow::Owned("CmpctBlock too many shortids".to_string()),
1294 )));
1295 }
1296 let shortids_len: usize = shortids_len_u64.try_into().map_err(|_| {
1297 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1298 "CmpctBlock shortid count out of range".to_string(),
1299 )))
1300 })?;
1301 let rem_after_count = data.len().saturating_sub(88 + cursor.position() as usize);
1302 let need_shortids = shortids_len.checked_mul(6).ok_or_else(|| {
1303 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1304 "CmpctBlock shortid size overflow".to_string(),
1305 )))
1306 })?;
1307 if need_shortids > rem_after_count {
1308 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1309 Cow::Owned("CmpctBlock shortids truncated".to_string()),
1310 )));
1311 }
1312 let mut short_ids = Vec::with_capacity(shortids_len);
1313 for _ in 0..shortids_len {
1314 let mut sid = [0u8; 6];
1315 cursor.read_exact(&mut sid).map_err(|e| {
1316 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
1317 "CmpctBlock shortid: {e}"
1318 ))))
1319 })?;
1320 short_ids.push(sid);
1321 }
1322 let prefilled_len_u64 = read_varint(&mut cursor)?;
1323 if prefilled_len_u64 > MAX_CMPCT_PREFILLED {
1324 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1325 Cow::Owned("CmpctBlock too many prefilled txs".to_string()),
1326 )));
1327 }
1328 let prefilled_len: usize = prefilled_len_u64.try_into().map_err(|_| {
1329 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1330 "CmpctBlock prefilled count out of range".to_string(),
1331 )))
1332 })?;
1333 let mut prefilled_txs = Vec::with_capacity(prefilled_len);
1334 let mut last_index: i64 = -1;
1335 let mut pos;
1336 for _ in 0..prefilled_len {
1337 let diff = read_varint(&mut cursor)? as i64;
1338 if diff < 0 {
1339 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1340 Cow::Owned("CmpctBlock prefilled index diff invalid".to_string()),
1341 )));
1342 }
1343 let index = last_index
1344 .checked_add(diff)
1345 .and_then(|v| v.checked_add(1))
1346 .ok_or_else(|| {
1347 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1348 "CmpctBlock prefilled index overflow".to_string(),
1349 )))
1350 })?;
1351 if index > 0xffff {
1352 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1353 Cow::Owned("CmpctBlock prefilled index too large".to_string()),
1354 )));
1355 }
1356 last_index = index;
1357 pos = cursor.position() as usize;
1358 let slice = &data[88..];
1359 if pos >= slice.len() {
1360 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1361 Cow::Owned("CmpctBlock prefilled tx truncated".to_string()),
1362 )));
1363 }
1364 let (tx, witnesses, consumed) = crate::serialization::deserialize_transaction_with_witness(
1368 &slice[pos..],
1369 )
1370 .map_err(|e| {
1371 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1372 })?;
1373 cursor.set_position((pos + consumed) as u64);
1374 let witness = witnesses.iter().any(|w| !w.is_empty()).then_some(witnesses);
1375 prefilled_txs.push(crate::network::PrefilledTransaction {
1376 index: index as u16,
1377 tx,
1378 witness,
1379 });
1380 }
1381 Ok(crate::network::CmpctBlockMessage {
1382 header,
1383 nonce,
1384 short_ids,
1385 prefilled_txs,
1386 })
1387}
1388
1389pub fn serialize_getblocktxn(gbt: &crate::network::GetBlockTxnMessage) -> Result<Vec<u8>> {
1391 use crate::varint::write_varint;
1392
1393 let mut buf = Vec::new();
1394 buf.extend_from_slice(&gbt.block_hash);
1395 write_varint(&mut buf, gbt.indices.len() as u64)?;
1396 let mut last: i64 = -1;
1397 for &idx in &gbt.indices {
1398 let diff = (idx as i64) - last - 1;
1399 if diff < 0 {
1400 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1401 Cow::Owned("GetBlockTxn indices must be strictly increasing".to_string()),
1402 )));
1403 }
1404 write_varint(&mut buf, diff as u64)?;
1405 last = idx as i64;
1406 }
1407 Ok(buf)
1408}
1409pub fn deserialize_getblocktxn(data: &[u8]) -> Result<crate::network::GetBlockTxnMessage> {
1410 use crate::varint::read_varint;
1411
1412 if data.len() < 32 {
1413 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1414 Cow::Owned("GetBlockTxn message too short".to_string()),
1415 )));
1416 }
1417 let mut block_hash = [0u8; 32];
1418 block_hash.copy_from_slice(&data[0..32]);
1419 let mut cursor = std::io::Cursor::new(&data[32..]);
1420 let count = read_varint(&mut cursor)? as usize;
1421 if count > 50000 {
1422 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1423 Cow::Owned("GetBlockTxn too many indices".to_string()),
1424 )));
1425 }
1426 let mut indices = Vec::with_capacity(count);
1427 let mut last: i64 = -1;
1428 for _ in 0..count {
1429 let diff = read_varint(&mut cursor)? as i64;
1430 if diff < 0 {
1431 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1432 Cow::Owned("GetBlockTxn index diff invalid".to_string()),
1433 )));
1434 }
1435 last = last
1436 .checked_add(diff)
1437 .and_then(|v| v.checked_add(1))
1438 .ok_or_else(|| {
1439 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1440 "GetBlockTxn index overflow".to_string(),
1441 )))
1442 })?;
1443 if last > 0xffff {
1444 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1445 Cow::Owned("GetBlockTxn index too large".to_string()),
1446 )));
1447 }
1448 indices.push(last as u16);
1449 }
1450 Ok(crate::network::GetBlockTxnMessage {
1451 block_hash,
1452 indices,
1453 })
1454}
1455
1456pub fn serialize_blocktxn(bt: &crate::network::BlockTxnMessage) -> Result<Vec<u8>> {
1458 use crate::varint::write_varint;
1459
1460 let mut buf = Vec::new();
1461 buf.extend_from_slice(&bt.block_hash);
1462 write_varint(&mut buf, bt.transactions.len() as u64)?;
1463 match (&bt.witnesses, bt.transactions.len()) {
1464 (Some(witnesses), len) if witnesses.len() == len => {
1465 for (tx, wit) in bt.transactions.iter().zip(witnesses.iter()) {
1466 buf.extend_from_slice(&crate::serialization::serialize_transaction_with_witness(
1467 tx, wit,
1468 ));
1469 }
1470 }
1471 _ => {
1472 for tx in &bt.transactions {
1473 buf.extend_from_slice(&crate::serialization::serialize_transaction(tx));
1474 }
1475 }
1476 }
1477 Ok(buf)
1478}
1479pub fn deserialize_blocktxn(data: &[u8]) -> Result<crate::network::BlockTxnMessage> {
1480 use crate::varint::read_varint;
1481
1482 if data.len() < 32 {
1483 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1484 Cow::Owned("BlockTxn message too short".to_string()),
1485 )));
1486 }
1487 let mut block_hash = [0u8; 32];
1488 block_hash.copy_from_slice(&data[0..32]);
1489 let mut cursor = std::io::Cursor::new(&data[32..]);
1490 let count = read_varint(&mut cursor)? as usize;
1491 if count > 2000 {
1492 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1493 Cow::Owned("BlockTxn too many transactions".to_string()),
1494 )));
1495 }
1496 let mut transactions = Vec::with_capacity(count);
1497 let mut all_witnesses = Vec::with_capacity(count);
1498 let mut pos = 32 + (cursor.position() as usize);
1499 for _ in 0..count {
1500 if pos >= data.len() {
1501 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1502 Cow::Owned("BlockTxn truncated".to_string()),
1503 )));
1504 }
1505 let (tx, witnesses, consumed) = crate::serialization::deserialize_transaction_with_witness(
1508 &data[pos..],
1509 )
1510 .map_err(|e| {
1511 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1512 })?;
1513 pos += consumed;
1514 transactions.push(tx);
1515 all_witnesses.push(witnesses);
1516 }
1517 let witnesses = all_witnesses
1518 .iter()
1519 .any(|w| w.iter().any(|s| !s.is_empty()))
1520 .then_some(all_witnesses);
1521 Ok(crate::network::BlockTxnMessage {
1522 block_hash,
1523 transactions,
1524 witnesses,
1525 })
1526}
1527
1528#[cfg(feature = "utxo-commitments")]
1529fn serialize_getutxoset(gus: &crate::commons::GetUTXOSetMessage) -> Result<Vec<u8>> {
1530 let mut buf = Vec::with_capacity(40);
1531 buf.extend_from_slice(&gus.height.to_le_bytes());
1532 buf.extend_from_slice(&gus.block_hash);
1533 Ok(buf)
1534}
1535#[cfg(feature = "utxo-commitments")]
1536fn deserialize_getutxoset(data: &[u8]) -> Result<crate::commons::GetUTXOSetMessage> {
1537 if data.len() < 40 {
1538 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1539 Cow::Owned("GetUTXOSet message too short".to_string()),
1540 )));
1541 }
1542 let height = u64::from_le_bytes([
1543 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
1544 ]);
1545 let mut block_hash = [0u8; 32];
1546 block_hash.copy_from_slice(&data[8..40]);
1547 Ok(crate::commons::GetUTXOSetMessage { height, block_hash })
1548}
1549
1550#[cfg(feature = "utxo-commitments")]
1551fn serialize_utxoset(us: &crate::commons::UTXOSetMessage) -> Result<Vec<u8>> {
1552 bincode::serialize(us).map_err(|e| {
1553 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1554 })
1555}
1556#[cfg(feature = "utxo-commitments")]
1557fn deserialize_utxoset(data: &[u8]) -> Result<crate::commons::UTXOSetMessage> {
1558 bincode::deserialize(data).map_err(|e| {
1559 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1560 })
1561}
1562
1563#[cfg(feature = "utxo-commitments")]
1564fn serialize_getfilteredblock(gfb: &crate::commons::GetFilteredBlockMessage) -> Result<Vec<u8>> {
1565 bincode::serialize(gfb).map_err(|e| {
1566 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1567 })
1568}
1569#[cfg(feature = "utxo-commitments")]
1570fn deserialize_getfilteredblock(data: &[u8]) -> Result<crate::commons::GetFilteredBlockMessage> {
1571 bincode::deserialize(data).map_err(|e| {
1572 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1573 })
1574}
1575
1576#[cfg(feature = "utxo-commitments")]
1577fn serialize_filteredblock(fb: &crate::commons::FilteredBlockMessage) -> Result<Vec<u8>> {
1578 bincode::serialize(fb).map_err(|e| {
1579 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1580 })
1581}
1582#[cfg(feature = "utxo-commitments")]
1583fn deserialize_filteredblock(data: &[u8]) -> Result<crate::commons::FilteredBlockMessage> {
1584 bincode::deserialize(data).map_err(|e| {
1585 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1586 })
1587}
1588
1589fn serialize_getbanlist(gbl: &crate::commons::GetBanListMessage) -> Result<Vec<u8>> {
1590 bincode::serialize(gbl).map_err(|e| {
1591 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1592 })
1593}
1594fn deserialize_getbanlist(data: &[u8]) -> Result<crate::commons::GetBanListMessage> {
1595 bincode::deserialize(data).map_err(|e| {
1596 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1597 })
1598}
1599
1600fn serialize_banlist(bl: &crate::commons::BanListMessage) -> Result<Vec<u8>> {
1601 bincode::serialize(bl).map_err(|e| {
1602 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1603 })
1604}
1605fn deserialize_banlist(data: &[u8]) -> Result<crate::commons::BanListMessage> {
1606 bincode::deserialize(data).map_err(|e| {
1607 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1608 })
1609}