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 {
254 time: 0,
255 services,
256 ip,
257 port,
258 })
259}
260
261pub fn serialize_version(v: &crate::network::VersionMessage) -> Result<Vec<u8>> {
273 use crate::varint::write_varint;
274
275 let mut buf = Vec::new();
276
277 buf.extend_from_slice(&(v.version as i32).to_le_bytes());
280
281 buf.extend_from_slice(&v.services.to_le_bytes());
283
284 buf.extend_from_slice(&v.timestamp.to_le_bytes());
286
287 buf.extend_from_slice(&serialize_network_address(&v.addr_recv));
289
290 buf.extend_from_slice(&serialize_network_address(&v.addr_from));
292
293 buf.extend_from_slice(&v.nonce.to_le_bytes());
295
296 let user_agent_bytes = v.user_agent.as_bytes();
298 write_varint(&mut buf, user_agent_bytes.len() as u64)?;
299 buf.extend_from_slice(user_agent_bytes);
300
301 buf.extend_from_slice(&v.start_height.to_le_bytes());
303
304 buf.push(if v.relay { 1 } else { 0 });
306
307 Ok(buf)
308}
309
310pub fn deserialize_version(data: &[u8]) -> Result<crate::network::VersionMessage> {
312 use crate::varint::read_varint;
313 use std::io::Cursor;
314
315 let mut cursor = Cursor::new(data);
316
317 let mut version_bytes = [0u8; 4];
319 cursor.read_exact(&mut version_bytes).map_err(|e| {
320 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
321 "Failed to read version: {e}"
322 ))))
323 })?;
324 let version = i32::from_le_bytes(version_bytes) as u32;
325
326 let mut services_bytes = [0u8; 8];
328 cursor.read_exact(&mut services_bytes).map_err(|e| {
329 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
330 "Failed to read services: {e}"
331 ))))
332 })?;
333 let services = u64::from_le_bytes(services_bytes);
334
335 let mut timestamp_bytes = [0u8; 8];
337 cursor.read_exact(&mut timestamp_bytes).map_err(|e| {
338 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
339 "Failed to read timestamp: {e}"
340 ))))
341 })?;
342 let timestamp = i64::from_le_bytes(timestamp_bytes);
343
344 let mut addr_recv_bytes = [0u8; 26];
346 cursor.read_exact(&mut addr_recv_bytes).map_err(|e| {
347 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
348 "Failed to read addr_recv: {e}"
349 ))))
350 })?;
351 let addr_recv = deserialize_network_address(&addr_recv_bytes)?;
352
353 let mut addr_from_bytes = [0u8; 26];
355 cursor.read_exact(&mut addr_from_bytes).map_err(|e| {
356 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
357 "Failed to read addr_from: {e}"
358 ))))
359 })?;
360 let addr_from = deserialize_network_address(&addr_from_bytes)?;
361
362 let mut nonce_bytes = [0u8; 8];
364 cursor.read_exact(&mut nonce_bytes).map_err(|e| {
365 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
366 "Failed to read nonce: {e}"
367 ))))
368 })?;
369 let nonce = u64::from_le_bytes(nonce_bytes);
370
371 let user_agent_len = read_varint(&mut cursor)?;
373 if user_agent_len > 10000 {
374 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
375 Cow::Owned("User agent too long".to_string()),
376 )));
377 }
378 let mut user_agent_bytes = vec![0u8; user_agent_len as usize];
379 cursor.read_exact(&mut user_agent_bytes).map_err(|e| {
380 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
381 "Failed to read user_agent: {e}"
382 ))))
383 })?;
384 let user_agent = String::from_utf8(user_agent_bytes).map_err(|e| {
385 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
386 "Invalid user_agent UTF-8: {e}"
387 ))))
388 })?;
389
390 let mut start_height_bytes = [0u8; 4];
392 cursor.read_exact(&mut start_height_bytes).map_err(|e| {
393 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
394 "Failed to read start_height: {e}"
395 ))))
396 })?;
397 let start_height = i32::from_le_bytes(start_height_bytes);
398
399 let relay = {
401 let mut relay_byte = [0u8; 1];
402 match cursor.read_exact(&mut relay_byte) {
403 Ok(_) => relay_byte[0] != 0,
404 Err(_) => true, }
406 };
407
408 Ok(crate::network::VersionMessage {
409 version,
410 services,
411 timestamp,
412 addr_recv,
413 addr_from,
414 nonce,
415 user_agent,
416 start_height,
417 relay,
418 })
419}
420
421pub fn serialize_addr(a: &crate::network::AddrMessage) -> Result<Vec<u8>> {
424 use crate::varint::write_varint;
425
426 let mut buf = Vec::new();
427 write_varint(&mut buf, a.addresses.len() as u64)?;
428
429 for addr in &a.addresses {
430 buf.extend_from_slice(&addr.time.to_le_bytes());
431 buf.extend_from_slice(&addr.services.to_le_bytes());
433 buf.extend_from_slice(&addr.ip);
435 buf.extend_from_slice(&addr.port.to_be_bytes());
437 }
438 Ok(buf)
439}
440pub fn deserialize_addr(data: &[u8]) -> Result<crate::network::AddrMessage> {
441 use crate::varint::read_varint;
442 use std::io::Read;
443
444 let mut cursor = std::io::Cursor::new(data);
445 let count = read_varint(&mut cursor)?;
446 if count > 1000 {
447 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
448 Cow::Owned("Too many addresses in addr".to_string()),
449 )));
450 }
451
452 let mut addresses = Vec::with_capacity(count as usize);
453 for _ in 0..count {
454 let mut time_bytes = [0u8; 4];
455 cursor.read_exact(&mut time_bytes).map_err(|e| {
456 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
457 "Addr time: {e}"
458 ))))
459 })?;
460 let time = u32::from_le_bytes(time_bytes);
461
462 let mut services_bytes = [0u8; 8];
463 cursor.read_exact(&mut services_bytes).map_err(|e| {
464 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
465 "Addr services: {e}"
466 ))))
467 })?;
468 let services = u64::from_le_bytes(services_bytes);
469
470 let mut ip = [0u8; 16];
471 cursor.read_exact(&mut ip).map_err(|e| {
472 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
473 "Addr ip: {e}"
474 ))))
475 })?;
476
477 let mut port_bytes = [0u8; 2];
478 cursor.read_exact(&mut port_bytes).map_err(|e| {
479 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
480 "Addr port: {e}"
481 ))))
482 })?;
483 let port = u16::from_be_bytes(port_bytes);
484
485 addresses.push(crate::network::NetworkAddress {
486 services,
487 ip,
488 port,
489 time,
490 });
491 }
492 Ok(crate::network::AddrMessage { addresses })
493}
494
495pub fn serialize_addrv2(addrv2: &crate::network::AddrV2Message) -> Result<Vec<u8>> {
498 use crate::varint::write_varint;
499
500 let mut buf = Vec::new();
501
502 write_varint(&mut buf, addrv2.addresses.len() as u64)?;
504
505 for addr in &addrv2.addresses {
507 buf.extend_from_slice(&addr.time.to_le_bytes());
509
510 buf.extend_from_slice(&addr.services.to_le_bytes());
512
513 buf.push(addr.address_type as u8);
515
516 buf.extend_from_slice(&addr.address);
518
519 buf.extend_from_slice(&addr.port.to_be_bytes());
521 }
522
523 Ok(buf)
524}
525
526pub fn deserialize_addrv2(data: &[u8]) -> Result<crate::network::AddrV2Message> {
528 use crate::varint::read_varint;
529 use std::io::Cursor;
530
531 let mut cursor = Cursor::new(data);
532
533 let count = read_varint(&mut cursor)?;
535 if count > 1000 {
536 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
537 Cow::Owned("Too many addresses in addrv2".to_string()),
538 )));
539 }
540
541 let mut addresses = Vec::with_capacity(count as usize);
542
543 for _ in 0..count {
545 let mut time_bytes = [0u8; 4];
547 cursor.read_exact(&mut time_bytes).map_err(|e| {
548 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
549 "Failed to read time: {e}"
550 ))))
551 })?;
552 let time = u32::from_le_bytes(time_bytes);
553
554 let mut services_bytes = [0u8; 8];
556 cursor.read_exact(&mut services_bytes).map_err(|e| {
557 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
558 "Failed to read services: {e}"
559 ))))
560 })?;
561 let services = u64::from_le_bytes(services_bytes);
562
563 let mut addr_type_byte = [0u8; 1];
565 cursor.read_exact(&mut addr_type_byte).map_err(|e| {
566 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
567 "Failed to read address_type: {e}"
568 ))))
569 })?;
570 let address_type =
571 crate::network::AddressType::from_u8(addr_type_byte[0]).ok_or_else(|| {
572 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
573 "Invalid address type: {}",
574 addr_type_byte[0]
575 ))))
576 })?;
577
578 let addr_len = address_type.address_length();
580 let mut address = vec![0u8; addr_len];
581 cursor.read_exact(&mut address).map_err(|e| {
582 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
583 "Failed to read address: {e}"
584 ))))
585 })?;
586
587 let mut port_bytes = [0u8; 2];
589 cursor.read_exact(&mut port_bytes).map_err(|e| {
590 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
591 "Failed to read port: {e}"
592 ))))
593 })?;
594 let port = u16::from_be_bytes(port_bytes);
595
596 let addr_v2 =
598 crate::network::NetworkAddressV2::new(time, services, address_type, address, port)?;
599
600 addresses.push(addr_v2);
601 }
602
603 Ok(crate::network::AddrV2Message { addresses })
604}
605
606pub fn serialize_inv(i: &crate::network::InvMessage) -> Result<Vec<u8>> {
609 use crate::varint::write_varint;
610
611 let capacity = 9 + (36 * i.inventory.len()); let mut buf = Vec::with_capacity(capacity);
613
614 write_varint(&mut buf, i.inventory.len() as u64)?;
615
616 for item in &i.inventory {
617 buf.extend_from_slice(&item.inv_type.to_le_bytes());
618 buf.extend_from_slice(&item.hash);
619 }
620
621 Ok(buf)
622}
623
624pub fn deserialize_inv(data: &[u8]) -> Result<crate::network::InvMessage> {
626 use crate::varint::read_varint;
627 use std::io::Cursor;
628
629 if data.is_empty() {
630 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
631 Cow::Owned("Inv message is empty".to_string()),
632 )));
633 }
634
635 let mut cursor = Cursor::new(data);
636
637 let count = read_varint(&mut cursor)? as usize;
638
639 if count > 50000 {
641 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
642 Cow::Owned(format!("Too many inventory items: {count}")),
643 )));
644 }
645
646 let mut inventory = Vec::with_capacity(count);
647
648 for _ in 0..count {
649 let mut type_bytes = [0u8; 4];
650 std::io::Read::read_exact(&mut cursor, &mut type_bytes).map_err(|e| {
651 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
652 })?;
653 let inv_type = u32::from_le_bytes(type_bytes);
654
655 let mut hash = [0u8; 32];
656 std::io::Read::read_exact(&mut cursor, &mut hash).map_err(|e| {
657 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
658 })?;
659
660 inventory.push(crate::network::InventoryVector { inv_type, hash });
661 }
662
663 Ok(crate::network::InvMessage { inventory })
664}
665
666pub fn serialize_getdata(g: &crate::network::GetDataMessage) -> Result<Vec<u8>> {
669 use crate::varint::write_varint;
670
671 let capacity = 9 + (36 * g.inventory.len());
672 let mut buf = Vec::with_capacity(capacity);
673
674 write_varint(&mut buf, g.inventory.len() as u64)?;
675
676 for item in &g.inventory {
677 buf.extend_from_slice(&item.inv_type.to_le_bytes());
678 buf.extend_from_slice(&item.hash);
679 }
680
681 Ok(buf)
682}
683
684pub fn deserialize_getdata(data: &[u8]) -> Result<crate::network::GetDataMessage> {
686 use crate::varint::read_varint;
687 use std::io::Cursor;
688
689 if data.is_empty() {
690 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
691 Cow::Owned("GetData message is empty".to_string()),
692 )));
693 }
694
695 let mut cursor = Cursor::new(data);
696
697 let count = read_varint(&mut cursor)? as usize;
698
699 if count > 50000 {
700 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
701 Cow::Owned(format!("Too many inventory items: {count}")),
702 )));
703 }
704
705 let mut inventory = Vec::with_capacity(count);
706
707 for _ in 0..count {
708 let mut type_bytes = [0u8; 4];
709 std::io::Read::read_exact(&mut cursor, &mut type_bytes).map_err(|e| {
710 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
711 })?;
712 let inv_type = u32::from_le_bytes(type_bytes);
713
714 let mut hash = [0u8; 32];
715 std::io::Read::read_exact(&mut cursor, &mut hash).map_err(|e| {
716 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
717 })?;
718
719 inventory.push(crate::network::InventoryVector { inv_type, hash });
720 }
721
722 Ok(crate::network::GetDataMessage { inventory })
723}
724
725pub fn serialize_getheaders(gh: &crate::network::GetHeadersMessage) -> Result<Vec<u8>> {
728 use crate::varint::write_varint;
729 use std::io::Cursor;
730
731 let capacity = 4 + 9 + (32 * gh.block_locator_hashes.len()) + 32;
733 let mut buf = Vec::with_capacity(capacity);
734
735 buf.extend_from_slice(&(gh.version as i32).to_le_bytes());
737
738 let mut cursor = Cursor::new(&mut buf);
740 cursor.set_position(4);
741 write_varint(&mut buf, gh.block_locator_hashes.len() as u64)?;
742
743 for hash in &gh.block_locator_hashes {
745 buf.extend_from_slice(hash);
746 }
747
748 buf.extend_from_slice(&gh.hash_stop);
750
751 Ok(buf)
752}
753
754pub fn deserialize_getheaders(data: &[u8]) -> Result<crate::network::GetHeadersMessage> {
756 use crate::varint::read_varint;
757 use std::io::Cursor;
758
759 if data.len() < 4 + 1 + 32 {
760 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
761 Cow::Owned("GetHeaders message too short".to_string()),
762 )));
763 }
764
765 let mut cursor = Cursor::new(data);
766
767 let mut version_bytes = [0u8; 4];
769 std::io::Read::read_exact(&mut cursor, &mut version_bytes).map_err(|e| {
770 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
771 })?;
772 let version = i32::from_le_bytes(version_bytes) as u32;
773
774 let hash_count = read_varint(&mut cursor)? as usize;
776
777 if hash_count > 2000 {
779 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
780 Cow::Owned(format!("Too many locator hashes: {hash_count}")),
781 )));
782 }
783
784 let mut block_locator_hashes = Vec::with_capacity(hash_count);
786 for _ in 0..hash_count {
787 let mut hash = [0u8; 32];
788 std::io::Read::read_exact(&mut cursor, &mut hash).map_err(|e| {
789 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
790 })?;
791 block_locator_hashes.push(hash);
792 }
793
794 let mut hash_stop = [0u8; 32];
796 std::io::Read::read_exact(&mut cursor, &mut hash_stop).map_err(|e| {
797 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
798 })?;
799
800 Ok(crate::network::GetHeadersMessage {
801 version,
802 block_locator_hashes,
803 hash_stop,
804 })
805}
806
807pub fn serialize_headers(h: &crate::network::HeadersMessage) -> Result<Vec<u8>> {
810 use crate::varint::write_varint;
811
812 let capacity = 9 + (81 * h.headers.len());
814 let mut buf = Vec::with_capacity(capacity);
815
816 write_varint(&mut buf, h.headers.len() as u64)?;
818
819 for header in &h.headers {
821 buf.extend_from_slice(&(header.version as i32).to_le_bytes());
823 buf.extend_from_slice(&header.prev_block_hash);
825 buf.extend_from_slice(&header.merkle_root);
827 buf.extend_from_slice(&(header.timestamp as u32).to_le_bytes());
829 buf.extend_from_slice(&(header.bits as u32).to_le_bytes());
831 buf.extend_from_slice(&(header.nonce as u32).to_le_bytes());
833 buf.push(0);
835 }
836
837 Ok(buf)
838}
839
840pub fn deserialize_headers(data: &[u8]) -> Result<crate::network::HeadersMessage> {
842 use crate::varint::read_varint;
843 use std::io::Cursor;
844
845 if data.is_empty() {
846 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
847 Cow::Owned("Headers message is empty".to_string()),
848 )));
849 }
850
851 let mut cursor = Cursor::new(data);
852
853 let header_count = read_varint(&mut cursor)? as usize;
855
856 if header_count > 2000 {
858 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
859 Cow::Owned(format!("Too many headers: {header_count}")),
860 )));
861 }
862
863 let mut headers = Vec::with_capacity(header_count);
864
865 for _ in 0..header_count {
866 let mut version_bytes = [0u8; 4];
868 std::io::Read::read_exact(&mut cursor, &mut version_bytes).map_err(|e| {
869 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
870 })?;
871 let version = i32::from_le_bytes(version_bytes) as i64;
872
873 let mut prev_block_hash = [0u8; 32];
875 std::io::Read::read_exact(&mut cursor, &mut prev_block_hash).map_err(|e| {
876 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
877 })?;
878
879 let mut merkle_root = [0u8; 32];
881 std::io::Read::read_exact(&mut cursor, &mut merkle_root).map_err(|e| {
882 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
883 })?;
884
885 let mut timestamp_bytes = [0u8; 4];
887 std::io::Read::read_exact(&mut cursor, &mut timestamp_bytes).map_err(|e| {
888 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
889 })?;
890 let timestamp = u32::from_le_bytes(timestamp_bytes) as u64;
891
892 let mut bits_bytes = [0u8; 4];
894 std::io::Read::read_exact(&mut cursor, &mut bits_bytes).map_err(|e| {
895 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
896 })?;
897 let bits = u32::from_le_bytes(bits_bytes) as u64;
898
899 let mut nonce_bytes = [0u8; 4];
901 std::io::Read::read_exact(&mut cursor, &mut nonce_bytes).map_err(|e| {
902 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
903 })?;
904 let nonce = u32::from_le_bytes(nonce_bytes) as u64;
905
906 let _tx_count = read_varint(&mut cursor)?;
908
909 headers.push(crate::BlockHeader {
910 version,
911 prev_block_hash,
912 merkle_root,
913 timestamp,
914 bits,
915 nonce,
916 });
917 }
918
919 Ok(crate::network::HeadersMessage { headers })
920}
921
922pub fn serialize_block_witnesses(
927 b: &crate::Block,
928 witnesses: &[Vec<blvm_consensus::segwit::Witness>],
929) -> Result<Vec<u8>> {
930 use crate::serialization::serialize_block_with_witnesses;
931
932 let include_witness = !witnesses.is_empty() && witnesses.iter().any(|tx_w| !tx_w.is_empty());
933
934 let padded;
936 let ws: &[Vec<blvm_consensus::segwit::Witness>] = if witnesses.len() < b.transactions.len() {
937 padded = {
938 let mut v = witnesses.to_vec();
939 v.resize(b.transactions.len(), Vec::new());
940 v
941 };
942 &padded
943 } else {
944 witnesses
945 };
946
947 Ok(serialize_block_with_witnesses(b, ws, include_witness))
948}
949
950pub fn deserialize_block_with_witnesses_pair(
955 data: &[u8],
956) -> Result<(crate::Block, Vec<Vec<blvm_consensus::segwit::Witness>>)> {
957 use crate::serialization::block::deserialize_block_with_witnesses;
958
959 deserialize_block_with_witnesses(data).map_err(|e| {
960 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
961 })
962}
963
964pub fn deserialize_block(data: &[u8]) -> Result<crate::Block> {
969 let (block, _witnesses) = deserialize_block_with_witnesses_pair(data)?;
970 Ok(block)
971}
972
973pub fn serialize_tx(tx: &crate::Transaction) -> Result<Vec<u8>> {
974 Ok(crate::serialization::serialize_transaction(tx))
975}
976
977pub fn serialize_tx_with_witness(
979 tx: &crate::Transaction,
980 witnesses: &[crate::segwit::Witness],
981) -> Result<Vec<u8>> {
982 let has_witness =
983 witnesses.len() == tx.inputs.len() && witnesses.iter().any(|stack| !stack.is_empty());
984 if has_witness {
985 crate::serialization::serialize_transaction_with_witness(tx, witnesses).map_err(|e| {
986 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
987 })
988 } else {
989 serialize_tx(tx)
990 }
991}
992
993pub fn deserialize_tx(data: &[u8]) -> Result<crate::Transaction> {
994 deserialize_tx_with_witness(data).map(|(tx, _)| tx)
995}
996
997pub fn deserialize_tx_with_witness(
999 data: &[u8],
1000) -> Result<(crate::Transaction, Vec<crate::segwit::Witness>)> {
1001 crate::serialization::deserialize_transaction_with_witness(data)
1002 .map(|(tx, witnesses, _)| (tx, witnesses))
1003 .map_err(|e| {
1004 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1005 })
1006}
1007
1008pub fn serialize_ping(p: &crate::network::PingMessage) -> Result<Vec<u8>> {
1010 Ok(p.nonce.to_le_bytes().to_vec())
1011}
1012
1013pub fn deserialize_ping(data: &[u8]) -> Result<crate::network::PingMessage> {
1015 if data.len() < 8 {
1016 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1017 Cow::Owned(format!("Ping message too short: {} bytes", data.len())),
1018 )));
1019 }
1020
1021 let nonce = u64::from_le_bytes([
1022 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
1023 ]);
1024
1025 Ok(crate::network::PingMessage { nonce })
1026}
1027
1028pub fn serialize_pong(p: &crate::network::PongMessage) -> Result<Vec<u8>> {
1030 Ok(p.nonce.to_le_bytes().to_vec())
1031}
1032
1033pub fn deserialize_pong(data: &[u8]) -> Result<crate::network::PongMessage> {
1035 if data.len() < 8 {
1036 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1037 Cow::Owned(format!("Pong message too short: {} bytes", data.len())),
1038 )));
1039 }
1040
1041 let nonce = u64::from_le_bytes([
1042 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
1043 ]);
1044
1045 Ok(crate::network::PongMessage { nonce })
1046}
1047
1048pub fn serialize_feefilter(f: &crate::network::FeeFilterMessage) -> Result<Vec<u8>> {
1050 Ok(f.feerate.to_le_bytes().to_vec())
1051}
1052pub fn deserialize_feefilter(data: &[u8]) -> Result<crate::network::FeeFilterMessage> {
1053 if data.len() < 8 {
1054 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1055 Cow::Owned("FeeFilter message too short".to_string()),
1056 )));
1057 }
1058 let feerate = u64::from_le_bytes([
1059 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
1060 ]);
1061 Ok(crate::network::FeeFilterMessage { feerate })
1062}
1063
1064pub fn serialize_getblocks(gb: &crate::network::GetBlocksMessage) -> Result<Vec<u8>> {
1066 use crate::varint::write_varint;
1067
1068 let mut buf = Vec::new();
1069 buf.extend_from_slice(&gb.version.to_le_bytes());
1070 write_varint(&mut buf, gb.block_locator_hashes.len() as u64)?;
1071 for hash in &gb.block_locator_hashes {
1072 buf.extend_from_slice(hash);
1073 }
1074 buf.extend_from_slice(&gb.hash_stop);
1075 Ok(buf)
1076}
1077pub fn deserialize_getblocks(data: &[u8]) -> Result<crate::network::GetBlocksMessage> {
1078 use crate::varint::read_varint;
1079 use std::io::Read;
1080
1081 if data.len() < 4 {
1082 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1083 Cow::Owned("GetBlocks message too short".to_string()),
1084 )));
1085 }
1086 let mut cursor = std::io::Cursor::new(data);
1087 let version = u32::from_le_bytes([data[0], data[1], data[2], data[3]]);
1088 cursor.set_position(4);
1089
1090 let count = read_varint(&mut cursor)? as usize;
1091 if count > 101 {
1092 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1093 Cow::Owned("GetBlocks locator too long".to_string()),
1094 )));
1095 }
1096 let mut block_locator_hashes = Vec::with_capacity(count);
1097 for _ in 0..count {
1098 let mut hash = [0u8; 32];
1099 cursor.read_exact(&mut hash).map_err(|e| {
1100 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
1101 "GetBlocks: {e}"
1102 ))))
1103 })?;
1104 block_locator_hashes.push(hash);
1105 }
1106 let mut hash_stop = [0u8; 32];
1107 cursor.read_exact(&mut hash_stop).map_err(|e| {
1108 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
1109 "GetBlocks hash_stop: {e}"
1110 ))))
1111 })?;
1112
1113 Ok(crate::network::GetBlocksMessage {
1114 version,
1115 block_locator_hashes,
1116 hash_stop,
1117 })
1118}
1119
1120pub fn serialize_notfound(nf: &crate::network::NotFoundMessage) -> Result<Vec<u8>> {
1123 use crate::varint::write_varint;
1124
1125 let capacity = 9 + (36 * nf.inventory.len());
1126 let mut buf = Vec::with_capacity(capacity);
1127
1128 write_varint(&mut buf, nf.inventory.len() as u64)?;
1129
1130 for item in &nf.inventory {
1131 buf.extend_from_slice(&item.inv_type.to_le_bytes());
1132 buf.extend_from_slice(&item.hash);
1133 }
1134
1135 Ok(buf)
1136}
1137
1138pub fn deserialize_notfound(data: &[u8]) -> Result<crate::network::NotFoundMessage> {
1140 use crate::varint::read_varint;
1141 use std::io::Cursor;
1142
1143 if data.is_empty() {
1144 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1145 Cow::Owned("NotFound message is empty".to_string()),
1146 )));
1147 }
1148
1149 let mut cursor = Cursor::new(data);
1150
1151 let count = read_varint(&mut cursor)? as usize;
1152
1153 if count > 50000 {
1154 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1155 Cow::Owned(format!("Too many inventory items: {count}")),
1156 )));
1157 }
1158
1159 let mut inventory = Vec::with_capacity(count);
1160
1161 for _ in 0..count {
1162 let mut type_bytes = [0u8; 4];
1163 std::io::Read::read_exact(&mut cursor, &mut type_bytes).map_err(|e| {
1164 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1165 })?;
1166 let inv_type = u32::from_le_bytes(type_bytes);
1167
1168 let mut hash = [0u8; 32];
1169 std::io::Read::read_exact(&mut cursor, &mut hash).map_err(|e| {
1170 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1171 })?;
1172
1173 inventory.push(crate::network::InventoryVector { inv_type, hash });
1174 }
1175
1176 Ok(crate::network::NotFoundMessage { inventory })
1177}
1178
1179pub fn serialize_reject(r: &crate::network::RejectMessage) -> Result<Vec<u8>> {
1181 use crate::varint::write_varint;
1182
1183 let mut buf = Vec::with_capacity(12 + 1 + 9 + r.reason.len() + 32);
1184 let msg_bytes = r.message.as_bytes();
1185 if msg_bytes.len() > 12 {
1186 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1187 Cow::Owned("Reject message field too long".to_string()),
1188 )));
1189 }
1190 buf.extend_from_slice(msg_bytes);
1191 buf.extend_from_slice(&[0u8; 12][msg_bytes.len()..]);
1192
1193 buf.push(r.code);
1194
1195 write_varint(&mut buf, r.reason.len() as u64)?;
1196 buf.extend_from_slice(r.reason.as_bytes());
1197
1198 if let Some(ref h) = r.extra_data {
1199 buf.extend_from_slice(h);
1200 }
1201 Ok(buf)
1202}
1203pub fn deserialize_reject(data: &[u8]) -> Result<crate::network::RejectMessage> {
1204 use crate::varint::read_varint;
1205
1206 if data.len() < 13 {
1207 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1208 Cow::Owned("Reject message too short".to_string()),
1209 )));
1210 }
1211 let message = String::from_utf8_lossy(&data[0..12])
1212 .trim_end_matches('\0')
1213 .to_string();
1214 let code = data[12];
1215 let mut cursor = std::io::Cursor::new(&data[13..]);
1216 let reason_len_u64 = read_varint(&mut cursor)?;
1217 let pos: usize = 13_usize.saturating_add(cursor.position() as usize);
1218 if reason_len_u64 > (data.len() as u64).saturating_sub(pos as u64) {
1219 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1220 Cow::Owned("Reject reason truncated".to_string()),
1221 )));
1222 }
1223 let reason_len: usize = reason_len_u64.try_into().map_err(|_| {
1224 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1225 "Reject reason length out of range".to_string(),
1226 )))
1227 })?;
1228 let end = pos.checked_add(reason_len).ok_or_else(|| {
1229 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1230 "Reject reason length out of range".to_string(),
1231 )))
1232 })?;
1233 if end > data.len() {
1234 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1235 Cow::Owned("Reject reason truncated".to_string()),
1236 )));
1237 }
1238 let reason = String::from_utf8_lossy(&data[pos..end]).to_string();
1239 let pos = end;
1240 let extra_data = if data.len() >= pos + 32 {
1241 Some({
1242 let mut h = [0u8; 32];
1243 h.copy_from_slice(&data[pos..pos + 32]);
1244 h
1245 })
1246 } else {
1247 None
1248 };
1249 Ok(crate::network::RejectMessage {
1250 message,
1251 code,
1252 reason,
1253 extra_data,
1254 })
1255}
1256
1257pub fn serialize_sendcmpct(sc: &crate::network::SendCmpctMessage) -> Result<Vec<u8>> {
1259 let mut buf = Vec::with_capacity(9);
1260 buf.push(sc.prefer_cmpct);
1261 buf.extend_from_slice(&sc.version.to_le_bytes());
1262 Ok(buf)
1263}
1264pub fn deserialize_sendcmpct(data: &[u8]) -> Result<crate::network::SendCmpctMessage> {
1265 if data.len() < 9 {
1266 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1267 Cow::Owned("SendCmpct message too short".to_string()),
1268 )));
1269 }
1270 Ok(crate::network::SendCmpctMessage {
1271 prefer_cmpct: data[0],
1272 version: u64::from_le_bytes([
1273 data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8],
1274 ]),
1275 })
1276}
1277
1278pub fn serialize_cmpctblock(cb: &crate::network::CmpctBlockMessage) -> Result<Vec<u8>> {
1280 use crate::varint::write_varint;
1281
1282 let mut buf = Vec::new();
1283 buf.extend_from_slice(&crate::serialization::serialize_block_header(&cb.header));
1284 buf.extend_from_slice(&cb.nonce.to_le_bytes());
1285 write_varint(&mut buf, cb.short_ids.len() as u64)?;
1286 for sid in &cb.short_ids {
1287 buf.extend_from_slice(sid);
1288 }
1289 write_varint(&mut buf, cb.prefilled_txs.len() as u64)?;
1290 let mut last_index = -1i64;
1291 for pt in &cb.prefilled_txs {
1292 let diff = (pt.index as i64) - last_index - 1;
1293 write_varint(&mut buf, diff as u64)?;
1294 last_index = pt.index as i64;
1295 let tx_bytes = match &pt.witness {
1296 Some(wit) if wit.iter().any(|w| !w.is_empty()) => {
1297 crate::serialization::serialize_transaction_with_witness(&pt.tx, wit)?
1298 }
1299 _ => crate::serialization::serialize_transaction(&pt.tx),
1300 };
1301 buf.extend_from_slice(&tx_bytes);
1302 }
1303 Ok(buf)
1304}
1305pub fn deserialize_cmpctblock(data: &[u8]) -> Result<crate::network::CmpctBlockMessage> {
1306 use crate::varint::read_varint;
1307 use std::io::Read;
1308
1309 const MAX_CMPCT_SHORTIDS: u64 = 50_000;
1311 const MAX_CMPCT_PREFILLED: u64 = 50_000;
1312
1313 if data.len() < 80 + 8 {
1314 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1315 Cow::Owned("CmpctBlock message too short".to_string()),
1316 )));
1317 }
1318 let header = crate::serialization::deserialize_block_header(&data[0..80]).map_err(|e| {
1319 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1320 })?;
1321 let nonce = u64::from_le_bytes([
1322 data[80], data[81], data[82], data[83], data[84], data[85], data[86], data[87],
1323 ]);
1324 let mut cursor = std::io::Cursor::new(&data[88..]);
1325 let shortids_len_u64 = read_varint(&mut cursor)?;
1326 if shortids_len_u64 > MAX_CMPCT_SHORTIDS {
1327 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1328 Cow::Owned("CmpctBlock too many shortids".to_string()),
1329 )));
1330 }
1331 let shortids_len: usize = shortids_len_u64.try_into().map_err(|_| {
1332 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1333 "CmpctBlock shortid count out of range".to_string(),
1334 )))
1335 })?;
1336 let rem_after_count = data.len().saturating_sub(88 + cursor.position() as usize);
1337 let need_shortids = shortids_len.checked_mul(6).ok_or_else(|| {
1338 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1339 "CmpctBlock shortid size overflow".to_string(),
1340 )))
1341 })?;
1342 if need_shortids > rem_after_count {
1343 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1344 Cow::Owned("CmpctBlock shortids truncated".to_string()),
1345 )));
1346 }
1347 let mut short_ids = Vec::with_capacity(shortids_len);
1348 for _ in 0..shortids_len {
1349 let mut sid = [0u8; 6];
1350 cursor.read_exact(&mut sid).map_err(|e| {
1351 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(format!(
1352 "CmpctBlock shortid: {e}"
1353 ))))
1354 })?;
1355 short_ids.push(sid);
1356 }
1357 let prefilled_len_u64 = read_varint(&mut cursor)?;
1358 if prefilled_len_u64 > MAX_CMPCT_PREFILLED {
1359 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1360 Cow::Owned("CmpctBlock too many prefilled txs".to_string()),
1361 )));
1362 }
1363 let prefilled_len: usize = prefilled_len_u64.try_into().map_err(|_| {
1364 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1365 "CmpctBlock prefilled count out of range".to_string(),
1366 )))
1367 })?;
1368 let mut prefilled_txs = Vec::with_capacity(prefilled_len);
1369 let mut last_index: i64 = -1;
1370 let mut pos;
1371 for _ in 0..prefilled_len {
1372 let diff = read_varint(&mut cursor)? as i64;
1373 if diff < 0 {
1374 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1375 Cow::Owned("CmpctBlock prefilled index diff invalid".to_string()),
1376 )));
1377 }
1378 let index = last_index
1379 .checked_add(diff)
1380 .and_then(|v| v.checked_add(1))
1381 .ok_or_else(|| {
1382 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1383 "CmpctBlock prefilled index overflow".to_string(),
1384 )))
1385 })?;
1386 if index > 0xffff {
1387 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1388 Cow::Owned("CmpctBlock prefilled index too large".to_string()),
1389 )));
1390 }
1391 last_index = index;
1392 pos = cursor.position() as usize;
1393 let slice = &data[88..];
1394 if pos >= slice.len() {
1395 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1396 Cow::Owned("CmpctBlock prefilled tx truncated".to_string()),
1397 )));
1398 }
1399 let (tx, witnesses, consumed) = crate::serialization::deserialize_transaction_with_witness(
1403 &slice[pos..],
1404 )
1405 .map_err(|e| {
1406 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1407 })?;
1408 cursor.set_position((pos + consumed) as u64);
1409 let witness = witnesses.iter().any(|w| !w.is_empty()).then_some(witnesses);
1410 prefilled_txs.push(crate::network::PrefilledTransaction {
1411 index: index as u16,
1412 tx,
1413 witness,
1414 });
1415 }
1416 Ok(crate::network::CmpctBlockMessage {
1417 header,
1418 nonce,
1419 short_ids,
1420 prefilled_txs,
1421 })
1422}
1423
1424pub fn serialize_getblocktxn(gbt: &crate::network::GetBlockTxnMessage) -> Result<Vec<u8>> {
1426 use crate::varint::write_varint;
1427
1428 let mut buf = Vec::new();
1429 buf.extend_from_slice(&gbt.block_hash);
1430 write_varint(&mut buf, gbt.indices.len() as u64)?;
1431 let mut last: i64 = -1;
1432 for &idx in &gbt.indices {
1433 let diff = (idx as i64) - last - 1;
1434 if diff < 0 {
1435 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1436 Cow::Owned("GetBlockTxn indices must be strictly increasing".to_string()),
1437 )));
1438 }
1439 write_varint(&mut buf, diff as u64)?;
1440 last = idx as i64;
1441 }
1442 Ok(buf)
1443}
1444pub fn deserialize_getblocktxn(data: &[u8]) -> Result<crate::network::GetBlockTxnMessage> {
1445 use crate::varint::read_varint;
1446
1447 if data.len() < 32 {
1448 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1449 Cow::Owned("GetBlockTxn message too short".to_string()),
1450 )));
1451 }
1452 let mut block_hash = [0u8; 32];
1453 block_hash.copy_from_slice(&data[0..32]);
1454 let mut cursor = std::io::Cursor::new(&data[32..]);
1455 let count = read_varint(&mut cursor)? as usize;
1456 if count > 50000 {
1457 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1458 Cow::Owned("GetBlockTxn too many indices".to_string()),
1459 )));
1460 }
1461 let mut indices = Vec::with_capacity(count);
1462 let mut last: i64 = -1;
1463 for _ in 0..count {
1464 let diff = read_varint(&mut cursor)? as i64;
1465 if diff < 0 {
1466 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1467 Cow::Owned("GetBlockTxn index diff invalid".to_string()),
1468 )));
1469 }
1470 last = last
1471 .checked_add(diff)
1472 .and_then(|v| v.checked_add(1))
1473 .ok_or_else(|| {
1474 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(
1475 "GetBlockTxn index overflow".to_string(),
1476 )))
1477 })?;
1478 if last > 0xffff {
1479 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1480 Cow::Owned("GetBlockTxn index too large".to_string()),
1481 )));
1482 }
1483 indices.push(last as u16);
1484 }
1485 Ok(crate::network::GetBlockTxnMessage {
1486 block_hash,
1487 indices,
1488 })
1489}
1490
1491pub fn serialize_blocktxn(bt: &crate::network::BlockTxnMessage) -> Result<Vec<u8>> {
1493 use crate::varint::write_varint;
1494
1495 let mut buf = Vec::new();
1496 buf.extend_from_slice(&bt.block_hash);
1497 write_varint(&mut buf, bt.transactions.len() as u64)?;
1498 match (&bt.witnesses, bt.transactions.len()) {
1499 (Some(witnesses), len) if witnesses.len() == len => {
1500 for (tx, wit) in bt.transactions.iter().zip(witnesses.iter()) {
1501 buf.extend_from_slice(&crate::serialization::serialize_transaction_with_witness(
1502 tx, wit,
1503 )?);
1504 }
1505 }
1506 _ => {
1507 for tx in &bt.transactions {
1508 buf.extend_from_slice(&crate::serialization::serialize_transaction(tx));
1509 }
1510 }
1511 }
1512 Ok(buf)
1513}
1514pub fn deserialize_blocktxn(data: &[u8]) -> Result<crate::network::BlockTxnMessage> {
1515 use crate::varint::read_varint;
1516
1517 if data.len() < 32 {
1518 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1519 Cow::Owned("BlockTxn message too short".to_string()),
1520 )));
1521 }
1522 let mut block_hash = [0u8; 32];
1523 block_hash.copy_from_slice(&data[0..32]);
1524 let mut cursor = std::io::Cursor::new(&data[32..]);
1525 let count = read_varint(&mut cursor)? as usize;
1526 if count > 50_000 {
1528 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1529 Cow::Owned("BlockTxn too many transactions".to_string()),
1530 )));
1531 }
1532 let mut transactions = Vec::with_capacity(count);
1533 let mut all_witnesses = Vec::with_capacity(count);
1534 let mut pos = 32 + (cursor.position() as usize);
1535 for _ in 0..count {
1536 if pos >= data.len() {
1537 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1538 Cow::Owned("BlockTxn truncated".to_string()),
1539 )));
1540 }
1541 let (tx, witnesses, consumed) = crate::serialization::deserialize_transaction_with_witness(
1544 &data[pos..],
1545 )
1546 .map_err(|e| {
1547 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1548 })?;
1549 pos += consumed;
1550 transactions.push(tx);
1551 all_witnesses.push(witnesses);
1552 }
1553 let witnesses = all_witnesses
1554 .iter()
1555 .any(|w| w.iter().any(|s| !s.is_empty()))
1556 .then_some(all_witnesses);
1557 Ok(crate::network::BlockTxnMessage {
1558 block_hash,
1559 transactions,
1560 witnesses,
1561 })
1562}
1563
1564#[cfg(feature = "utxo-commitments")]
1565fn serialize_getutxoset(gus: &crate::commons::GetUTXOSetMessage) -> Result<Vec<u8>> {
1566 let mut buf = Vec::with_capacity(40);
1567 buf.extend_from_slice(&gus.height.to_le_bytes());
1568 buf.extend_from_slice(&gus.block_hash);
1569 Ok(buf)
1570}
1571#[cfg(feature = "utxo-commitments")]
1572fn deserialize_getutxoset(data: &[u8]) -> Result<crate::commons::GetUTXOSetMessage> {
1573 if data.len() < 40 {
1574 return Err(ProtocolError::Consensus(ConsensusError::Serialization(
1575 Cow::Owned("GetUTXOSet message too short".to_string()),
1576 )));
1577 }
1578 let height = u64::from_le_bytes([
1579 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
1580 ]);
1581 let mut block_hash = [0u8; 32];
1582 block_hash.copy_from_slice(&data[8..40]);
1583 Ok(crate::commons::GetUTXOSetMessage { height, block_hash })
1584}
1585
1586#[cfg(feature = "utxo-commitments")]
1587fn serialize_utxoset(us: &crate::commons::UTXOSetMessage) -> Result<Vec<u8>> {
1588 bincode::serialize(us).map_err(|e| {
1589 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1590 })
1591}
1592#[cfg(feature = "utxo-commitments")]
1593fn deserialize_utxoset(data: &[u8]) -> Result<crate::commons::UTXOSetMessage> {
1594 bincode::deserialize(data).map_err(|e| {
1595 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1596 })
1597}
1598
1599#[cfg(feature = "utxo-commitments")]
1600fn serialize_getfilteredblock(gfb: &crate::commons::GetFilteredBlockMessage) -> Result<Vec<u8>> {
1601 bincode::serialize(gfb).map_err(|e| {
1602 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1603 })
1604}
1605#[cfg(feature = "utxo-commitments")]
1606fn deserialize_getfilteredblock(data: &[u8]) -> Result<crate::commons::GetFilteredBlockMessage> {
1607 bincode::deserialize(data).map_err(|e| {
1608 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1609 })
1610}
1611
1612#[cfg(feature = "utxo-commitments")]
1613fn serialize_filteredblock(fb: &crate::commons::FilteredBlockMessage) -> Result<Vec<u8>> {
1614 bincode::serialize(fb).map_err(|e| {
1615 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1616 })
1617}
1618#[cfg(feature = "utxo-commitments")]
1619fn deserialize_filteredblock(data: &[u8]) -> Result<crate::commons::FilteredBlockMessage> {
1620 bincode::deserialize(data).map_err(|e| {
1621 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1622 })
1623}
1624
1625fn serialize_getbanlist(gbl: &crate::commons::GetBanListMessage) -> Result<Vec<u8>> {
1626 bincode::serialize(gbl).map_err(|e| {
1627 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1628 })
1629}
1630fn deserialize_getbanlist(data: &[u8]) -> Result<crate::commons::GetBanListMessage> {
1631 bincode::deserialize(data).map_err(|e| {
1632 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1633 })
1634}
1635
1636fn serialize_banlist(bl: &crate::commons::BanListMessage) -> Result<Vec<u8>> {
1637 bincode::serialize(bl).map_err(|e| {
1638 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1639 })
1640}
1641fn deserialize_banlist(data: &[u8]) -> Result<crate::commons::BanListMessage> {
1642 bincode::deserialize(data).map_err(|e| {
1643 ProtocolError::Consensus(ConsensusError::Serialization(Cow::Owned(e.to_string())))
1644 })
1645}
1646
1647#[cfg(test)]
1648mod blocktxn_count {
1649 use super::deserialize_blocktxn;
1650
1651 fn minimal_tx() -> Vec<u8> {
1652 let mut tx = Vec::new();
1653 tx.extend_from_slice(&1i32.to_le_bytes());
1654 tx.push(0);
1655 tx.push(0);
1656 tx.extend_from_slice(&0u32.to_le_bytes());
1657 tx
1658 }
1659
1660 #[test]
1661 fn twelve_thousand_transactions_decode() {
1662 let one = minimal_tx();
1663 let mut payload = vec![0u8; 32];
1664 payload.push(0xfd);
1665 payload.extend_from_slice(&12_239u16.to_le_bytes());
1666 for _ in 0..12_239 {
1667 payload.extend_from_slice(&one);
1668 }
1669 let msg = deserialize_blocktxn(&payload).expect("12239 transactions fit");
1670 assert_eq!(msg.transactions.len(), 12_239);
1671
1672 let mut over = vec![0u8; 32];
1673 over.push(0xfd);
1674 over.extend_from_slice(&50_001u16.to_le_bytes());
1675 let err = deserialize_blocktxn(&over).unwrap_err();
1676 let text = format!("{err:?}");
1677 assert!(text.contains("too many"), "{text}");
1678 }
1679}