1#[cfg(feature = "protocol-verification")]
10use blvm_spec_lock::spec_locked;
11
12use crate::wire::{
13 deserialize_addrv2, deserialize_cmpctblock, deserialize_feefilter, deserialize_getblocks,
14 deserialize_getdata, deserialize_getheaders, deserialize_headers, deserialize_inv,
15 deserialize_notfound, deserialize_reject, deserialize_sendcmpct, deserialize_tx,
16 serialize_addrv2, serialize_cmpctblock, serialize_feefilter, serialize_getblocks,
17 serialize_getdata, serialize_getheaders, serialize_inv, serialize_notfound, serialize_reject,
18 serialize_sendcmpct, serialize_tx,
19};
20use crate::{BlockHeader, Hash, Transaction};
21use anyhow::Result;
22use serde::{Deserialize, Serialize};
23
24pub use crate::p2p_framing::{
25 BITCOIN_MAGIC_MAINNET, BITCOIN_MAGIC_REGTEST, BITCOIN_MAGIC_TESTNET,
26 BITCOIN_P2P_MAGIC_MAINNET_LE, MAX_ADDR_TO_SEND, MAX_HEADERS_RESULTS, MAX_INV_SZ,
27 MAX_PROTOCOL_MESSAGE_LENGTH,
28};
29
30pub use crate::service_flags::commons::{
31 NODE_BAN_LIST_SHARING, NODE_FIBRE, NODE_GOVERNANCE, NODE_PACKAGE_RELAY,
32};
33
34#[cfg(feature = "dandelion")]
35pub use crate::service_flags::commons::NODE_DANDELION;
36
37#[cfg(feature = "utxo-commitments")]
38pub use crate::service_flags::commons::NODE_UTXO_COMMITMENTS;
39
40#[cfg(feature = "erlay")]
41pub use crate::service_flags::commons::NODE_ERLAY;
42
43pub use crate::p2p_commands::cmd;
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
47pub enum ProtocolMessage {
48 Version(VersionMessage),
49 Verack,
50 Ping(PingMessage),
51 Pong(PongMessage),
52 GetHeaders(GetHeadersMessage),
53 Headers(HeadersMessage),
54 GetBlocks(GetBlocksMessage),
55 Block(BlockMessage),
56 GetData(GetDataMessage),
57 Inv(InvMessage),
58 NotFound(NotFoundMessage),
59 Reject(RejectMessage),
61 Tx(TxMessage),
62 FeeFilter(FeeFilterMessage),
64 MemPool,
66 SendHeaders,
68 SendCmpct(SendCmpctMessage),
70 CmpctBlock(CompactBlockMessage),
71 GetBlockTxn(GetBlockTxnMessage),
72 BlockTxn(BlockTxnMessage),
73 GetUTXOSet(GetUTXOSetMessage),
75 UTXOSet(UTXOSetMessage),
76 GetUTXOProof(GetUTXOProofMessage),
77 UTXOProof(UTXOProofMessage),
78 GetFilteredBlock(GetFilteredBlockMessage),
79 FilteredBlock(FilteredBlockMessage),
80 GetCfilters(GetCfiltersMessage),
82 Cfilter(CfilterMessage),
83 GetCfheaders(GetCfheadersMessage),
84 Cfheaders(CfheadersMessage),
85 GetCfcheckpt(GetCfcheckptMessage),
86 Cfcheckpt(CfcheckptMessage),
87 GetPaymentRequest(GetPaymentRequestMessage),
89 PaymentRequest(PaymentRequestMessage),
90 Payment(PaymentMessage),
91 PaymentACK(PaymentACKMessage),
92 #[cfg(feature = "ctv")]
94 PaymentProof(PaymentProofMessage),
95 SettlementNotification(SettlementNotificationMessage),
96 SendPkgTxn(SendPkgTxnMessage),
98 PkgTxn(PkgTxnMessage),
99 PkgTxnReject(PkgTxnRejectMessage),
100 GetBanList(GetBanListMessage),
102 BanList(BanListMessage),
103 MeshPacket(Vec<u8>), GetAddr,
107 Addr(AddrMessage),
108 AddrV2(AddrV2Message),
110 GetModule(GetModuleMessage),
112 Module(ModuleMessage),
113 GetModuleByHash(GetModuleByHashMessage),
114 ModuleByHash(ModuleByHashMessage),
115 ModuleInv(ModuleInvMessage),
116 GetModuleList(GetModuleListMessage),
117 ModuleList(ModuleListMessage),
118 #[cfg(feature = "erlay")]
120 SendTxRcncl(SendTxRcnclMessage),
121 #[cfg(feature = "erlay")]
122 ReqRecon(ReqReconMessage),
123 #[cfg(feature = "erlay")]
124 ReqSkt(ReqSktMessage),
125 #[cfg(feature = "erlay")]
126 Sketch(SketchMessage),
127}
128
129pub use crate::network::NetworkAddress;
130
131pub use crate::{
134 BlockMessage, CompactBlockMessage, FilterPreferences, GetFilteredBlockMessage,
135 GetUTXOProofMessage, GetUTXOSetMessage, TxMessage, UTXOCommitment, UTXOProofMessage,
136 UTXOSetMessage,
137};
138
139#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
141pub struct VersionMessage {
142 pub version: i32,
143 pub services: u64,
144 pub timestamp: i64,
145 pub addr_recv: NetworkAddress,
146 pub addr_from: NetworkAddress,
147 pub nonce: u64,
148 pub user_agent: String,
149 pub start_height: i32,
150 pub relay: bool,
151}
152
153impl VersionMessage {
154 #[cfg(feature = "utxo-commitments")]
156 pub fn supports_utxo_commitments(&self) -> bool {
157 (self.services & NODE_UTXO_COMMITMENTS) != 0
158 }
159
160 pub fn supports_ban_list_sharing(&self) -> bool {
162 (self.services & NODE_BAN_LIST_SHARING) != 0
163 }
164
165 pub fn supports_compact_filters(&self) -> bool {
167 use crate::bip157::NODE_COMPACT_FILTERS;
168 (self.services & NODE_COMPACT_FILTERS) != 0
169 }
170
171 pub fn supports_package_relay(&self) -> bool {
173 (self.services & NODE_PACKAGE_RELAY) != 0
174 }
175
176 pub fn supports_fibre(&self) -> bool {
178 (self.services & NODE_FIBRE) != 0
179 }
180
181 #[cfg(feature = "dandelion")]
182 pub fn supports_dandelion(&self) -> bool {
184 (self.services & NODE_DANDELION) != 0
185 }
186}
187
188pub use crate::network::{
190 AddrMessage, AddrV2Message, BlockTxnMessage, FeeFilterMessage, GetBlockTxnMessage,
191 GetBlocksMessage, GetDataMessage, GetHeadersMessage, HeadersMessage, InvMessage,
192 InventoryVector, NotFoundMessage, PingMessage, PongMessage, RejectMessage, SendCmpctMessage,
193};
194
195#[derive(Debug, Clone, Serialize, Deserialize)]
197pub struct FilteredBlockMessage {
198 pub request_id: u64,
200 pub header: BlockHeader,
202 pub commitment: UTXOCommitment,
204 pub transactions: Vec<Transaction>,
206 pub transaction_indices: Vec<u32>,
208 pub spam_summary: SpamSummary,
210 pub bip158_filter: Option<Bip158FilterData>,
217}
218
219#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct Bip158FilterData {
222 pub filter_type: u8,
224 pub filter_data: Vec<u8>,
226 pub num_elements: u32,
228}
229
230#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
234pub struct GetCfiltersMessage {
235 pub filter_type: u8,
237 pub start_height: u32,
239 pub stop_hash: Hash,
241}
242
243#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
245pub struct CfilterMessage {
246 pub filter_type: u8,
248 pub block_hash: Hash,
250 pub filter_data: Vec<u8>,
252 pub num_elements: u32,
254}
255
256#[derive(Debug, Clone, Serialize, Deserialize)]
258pub struct GetCfheadersMessage {
259 pub filter_type: u8,
261 pub start_height: u32,
263 pub stop_hash: Hash,
265}
266
267#[derive(Debug, Clone, Serialize, Deserialize)]
269pub struct CfheadersMessage {
270 pub filter_type: u8,
272 pub stop_hash: Hash,
274 pub prev_header: FilterHeaderData,
276 pub filter_headers: Vec<Hash>,
278}
279
280#[derive(Debug, Clone, Serialize, Deserialize)]
282pub struct FilterHeaderData {
283 pub filter_hash: Hash,
285 pub prev_header_hash: Hash,
287}
288
289#[derive(Debug, Clone, Serialize, Deserialize)]
291pub struct GetCfcheckptMessage {
292 pub filter_type: u8,
294 pub stop_hash: Hash,
296}
297
298#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct CfcheckptMessage {
301 pub filter_type: u8,
303 pub stop_hash: Hash,
305 pub filter_header_hashes: Vec<Hash>,
307}
308
309#[derive(Debug, Clone, Serialize, Deserialize)]
313pub struct GetPaymentRequestMessage {
314 #[serde(with = "serde_bytes")]
316 pub merchant_pubkey: Vec<u8>,
317 #[serde(with = "serde_bytes")]
319 pub payment_id: Vec<u8>,
320 pub network: String,
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize)]
326pub struct PaymentRequestMessage {
327 pub payment_request: crate::payment::PaymentRequest,
329 #[serde(with = "serde_bytes")]
331 pub merchant_signature: Vec<u8>,
332 #[serde(with = "serde_bytes")]
334 pub merchant_pubkey: Vec<u8>,
335 #[serde(with = "serde_bytes")]
337 pub payment_id: Vec<u8>,
338 #[cfg(feature = "ctv")]
340 #[serde(default)]
341 pub covenant_proof: Option<crate::payment::CovenantProof>,
342}
343
344#[derive(Debug, Clone, Serialize, Deserialize)]
346pub struct PaymentMessage {
347 pub payment: crate::payment::Payment,
349 #[serde(with = "serde_bytes")]
351 pub payment_id: Vec<u8>,
352 #[serde(with = "serde_bytes")]
354 pub customer_signature: Option<Vec<u8>>,
355}
356
357#[derive(Debug, Clone, Serialize, Deserialize)]
359pub struct PaymentACKMessage {
360 pub payment_ack: crate::payment::PaymentACK,
362 #[serde(with = "serde_bytes")]
364 pub payment_id: Vec<u8>,
365 #[serde(with = "serde_bytes")]
367 pub merchant_signature: Vec<u8>,
368}
369
370#[cfg(feature = "ctv")]
374#[derive(Debug, Clone, Serialize, Deserialize)]
375pub struct PaymentProofMessage {
376 pub request_id: u64,
378 pub payment_request_id: String,
380 pub covenant_proof: crate::payment::CovenantProof,
382 pub transaction_template: Option<crate::payment::TransactionTemplate>,
384}
385
386#[derive(Debug, Clone, Serialize, Deserialize)]
388pub struct SettlementNotificationMessage {
389 pub payment_request_id: String,
391 pub transaction_hash: Option<Hash>,
393 pub confirmation_count: u32,
395 pub block_hash: Option<Hash>,
397 pub status: String, }
400
401#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
405pub struct SendPkgTxnMessage {
406 #[serde(with = "serde_bytes")]
408 pub package_id: Vec<u8>,
409 pub tx_hashes: Vec<Hash>,
411}
412
413#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
415pub struct PkgTxnMessage {
416 #[serde(with = "serde_bytes")]
418 pub package_id: Vec<u8>,
419 pub transactions: Vec<Vec<u8>>,
422}
423
424#[derive(Debug, Clone, Serialize, Deserialize)]
426pub struct PkgTxnRejectMessage {
427 #[serde(with = "serde_bytes")]
429 pub package_id: Vec<u8>,
430 pub reason: u8,
432 pub reason_text: Option<String>,
434}
435
436#[derive(Debug, Clone, Serialize, Deserialize)]
440pub struct GetModuleMessage {
441 pub request_id: u64,
443 pub name: String,
445 pub version: Option<String>,
447 pub payment_id: Option<String>,
450}
451
452#[derive(Debug, Clone, Serialize, Deserialize)]
454pub struct ModuleMessage {
455 pub request_id: u64,
457 pub name: String,
459 pub version: String,
461 pub hash: Hash,
463 pub manifest_hash: Hash,
465 pub binary_hash: Hash,
467 pub manifest: Vec<u8>,
469 pub binary: Option<Vec<u8>>,
471}
472
473#[derive(Debug, Clone, Serialize, Deserialize)]
475pub struct GetModuleByHashMessage {
476 pub request_id: u64,
478 pub hash: Hash,
480 pub include_binary: bool,
482}
483
484#[derive(Debug, Clone, Serialize, Deserialize)]
486pub struct ModuleByHashMessage {
487 pub request_id: u64,
489 pub hash: Hash,
491 pub manifest: Vec<u8>,
493 pub binary: Option<Vec<u8>>,
495}
496
497#[derive(Debug, Clone, Serialize, Deserialize)]
499pub struct ModuleInvMessage {
500 pub modules: Vec<ModuleInventoryItem>,
502}
503
504#[derive(Debug, Clone, Serialize, Deserialize)]
506pub struct ModuleInventoryItem {
507 pub name: String,
509 pub version: String,
511 pub hash: Hash,
513}
514
515#[derive(Debug, Clone, Serialize, Deserialize)]
517pub struct GetModuleListMessage {
518 pub name_prefix: Option<String>,
520 pub max_count: Option<u32>,
522}
523
524#[derive(Debug, Clone, Serialize, Deserialize)]
526pub struct ModuleListMessage {
527 pub modules: Vec<ModuleInventoryItem>,
529}
530
531#[cfg(feature = "erlay")]
535#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
536pub struct SendTxRcnclMessage {
537 pub version: u16,
539 #[serde(with = "serde_bytes")]
541 pub salt: [u8; 16],
542 pub min_field_size: u8,
544 pub max_field_size: u8,
546}
547
548#[cfg(feature = "erlay")]
550#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
551pub struct ReqReconMessage {
552 #[serde(with = "serde_bytes")]
554 pub salt: [u8; 16],
555 pub local_set_size: u32,
557 pub field_size: u8,
559}
560
561#[cfg(feature = "erlay")]
563#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
564pub struct ReqSktMessage {
565 #[serde(with = "serde_bytes")]
567 pub salt: [u8; 16],
568 pub remote_set_size: u32,
570 pub field_size: u8,
572}
573
574#[cfg(feature = "erlay")]
576#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
577pub struct SketchMessage {
578 #[serde(with = "serde_bytes")]
580 pub salt: [u8; 16],
581 #[serde(with = "serde_bytes")]
583 pub sketch: Vec<u8>,
584 pub field_size: u8,
586}
587
588#[derive(Debug, Clone, Serialize, Deserialize)]
590pub struct SpamSummary {
591 pub filtered_count: u32,
593 pub filtered_size: u64,
595 pub by_type: SpamBreakdown,
597}
598
599#[derive(Debug, Clone, Serialize, Deserialize)]
601pub struct SpamBreakdown {
602 pub ordinals: u32,
603 pub inscriptions: u32,
604 pub dust: u32,
605 pub brc20: u32,
606}
607
608pub struct TcpFramedParser;
610
611impl TcpFramedParser {
612 #[cfg_attr(
615 feature = "protocol-verification",
616 spec_locked("10.1.1", "ParseMessage")
617 )]
618 #[cfg_attr(
619 feature = "protocol-verification",
620 blvm_spec_lock::ensures(data.len() >= 24 || result.is_err())
621 )]
622 pub fn parse_message(data: &[u8], allowed_commands: &[&str]) -> Result<ProtocolMessage> {
623 use tracing::{debug, warn};
624
625 if data.len() >= 4 {
626 let magic = u32::from_le_bytes([data[0], data[1], data[2], data[3]]);
627 debug!(
628 "Parsing message: magic=0x{:08x}, total_len={}",
629 magic,
630 data.len()
631 );
632 if magic != BITCOIN_P2P_MAGIC_MAINNET_LE {
633 let header_hex: String = data.iter().take(24).map(|b| format!("{b:02x}")).collect();
634 warn!(
635 "Invalid magic number 0x{:08x}, expected 0x{:08x}. Header hex: {}",
636 magic, BITCOIN_P2P_MAGIC_MAINNET_LE, header_hex
637 );
638 }
639 }
640
641 let (command, payload) =
642 crate::p2p_frame::parse_p2p_frame(data, BITCOIN_P2P_MAGIC_MAINNET_LE, |c| {
643 allowed_commands.contains(&c)
644 })
645 .map_err(|e| anyhow::anyhow!("{}", e))?;
646
647 debug!("Message command: '{}', data_len={}", command, data.len());
648
649 match command {
651 cmd::VERSION => {
652 use crate::wire::deserialize_version;
654
655 let version_msg = deserialize_version(payload)?;
656
657 Ok(ProtocolMessage::Version(VersionMessage {
658 version: version_msg.version as i32, services: version_msg.services,
660 timestamp: version_msg.timestamp,
661 addr_recv: version_msg.addr_recv,
662 addr_from: version_msg.addr_from,
663 nonce: version_msg.nonce,
664 user_agent: version_msg.user_agent,
665 start_height: version_msg.start_height,
666 relay: version_msg.relay,
667 }))
668 }
669 cmd::VERACK => Ok(ProtocolMessage::Verack),
670 cmd::SENDHEADERS => Ok(ProtocolMessage::SendHeaders),
671 cmd::PING => {
672 let wire_msg = crate::wire::deserialize_ping(payload)
674 .map_err(|e| anyhow::anyhow!("Failed to deserialize ping: {}", e))?;
675 Ok(ProtocolMessage::Ping(PingMessage {
676 nonce: wire_msg.nonce,
677 }))
678 }
679 cmd::PONG => {
680 let wire_msg = crate::wire::deserialize_pong(payload)
682 .map_err(|e| anyhow::anyhow!("Failed to deserialize pong: {}", e))?;
683 Ok(ProtocolMessage::Pong(PongMessage {
684 nonce: wire_msg.nonce,
685 }))
686 }
687 cmd::GETHEADERS => {
688 let wire_msg = deserialize_getheaders(payload)
689 .map_err(|e| anyhow::anyhow!("Failed to deserialize getheaders: {}", e))?;
690 Ok(ProtocolMessage::GetHeaders(wire_msg))
691 }
692 cmd::HEADERS => {
693 let wire_msg = deserialize_headers(payload)
694 .map_err(|e| anyhow::anyhow!("Failed to deserialize headers: {}", e))?;
695 Ok(ProtocolMessage::Headers(wire_msg))
696 }
697 cmd::GETBLOCKS => {
698 let wire_msg = deserialize_getblocks(payload)
699 .map_err(|e| anyhow::anyhow!("Failed to deserialize getblocks: {}", e))?;
700 Ok(ProtocolMessage::GetBlocks(wire_msg))
701 }
702 cmd::BLOCK => {
703 let (block, witnesses) =
705 crate::serialization::deserialize_block_with_witnesses(payload)
706 .map_err(|e| anyhow::anyhow!("Failed to deserialize block: {}", e))?;
707 Ok(ProtocolMessage::Block(BlockMessage { block, witnesses }))
708 }
709 cmd::GETDATA => {
710 let msg = deserialize_getdata(payload)
711 .map_err(|e| anyhow::anyhow!("Failed to deserialize getdata: {}", e))?;
712 Ok(ProtocolMessage::GetData(msg))
713 }
714 cmd::INV => {
715 let msg = deserialize_inv(payload)
716 .map_err(|e| anyhow::anyhow!("Failed to deserialize inv: {}", e))?;
717 Ok(ProtocolMessage::Inv(msg))
718 }
719 cmd::NOTFOUND => {
720 let msg = deserialize_notfound(payload)
721 .map_err(|e| anyhow::anyhow!("Failed to deserialize notfound: {}", e))?;
722 Ok(ProtocolMessage::NotFound(msg))
723 }
724 cmd::REJECT => {
725 let msg = deserialize_reject(payload)
726 .map_err(|e| anyhow::anyhow!("Failed to deserialize reject: {}", e))?;
727 Ok(ProtocolMessage::Reject(msg))
728 }
729 cmd::TX => {
730 let transaction = deserialize_tx(payload)
731 .map_err(|e| anyhow::anyhow!("Failed to deserialize tx: {}", e))?;
732 Ok(ProtocolMessage::Tx(TxMessage { transaction }))
733 }
734 cmd::MEMPOOL => Ok(ProtocolMessage::MemPool),
735 cmd::FEEFILTER => {
736 let msg = deserialize_feefilter(payload)
737 .map_err(|e| anyhow::anyhow!("Failed to deserialize feefilter: {}", e))?;
738 Ok(ProtocolMessage::FeeFilter(msg))
739 }
740 cmd::SENDCMPCT => {
742 let msg = deserialize_sendcmpct(payload)
743 .map_err(|e| anyhow::anyhow!("Failed to deserialize sendcmpct: {}", e))?;
744 Ok(ProtocolMessage::SendCmpct(msg))
745 }
746 cmd::CMPCTBLOCK => {
747 let wire_msg = deserialize_cmpctblock(payload)
748 .map_err(|e| anyhow::anyhow!("Failed to deserialize cmpctblock: {}", e))?;
749 let compact_block = crate::bip152::CompactBlock::from(&wire_msg);
750 Ok(ProtocolMessage::CmpctBlock(CompactBlockMessage {
751 compact_block,
752 }))
753 }
754 cmd::GETBLOCKTXN => {
755 let wire_msg = crate::wire::deserialize_getblocktxn(payload)
756 .map_err(|e| anyhow::anyhow!("Failed to deserialize getblocktxn: {}", e))?;
757 Ok(ProtocolMessage::GetBlockTxn(wire_msg))
758 }
759 cmd::BLOCKTXN => {
760 let wire_msg = crate::wire::deserialize_blocktxn(payload)
761 .map_err(|e| anyhow::anyhow!("Failed to deserialize blocktxn: {}", e))?;
762 Ok(ProtocolMessage::BlockTxn(wire_msg))
763 }
764 cmd::GETUTXOSET => Ok(ProtocolMessage::GetUTXOSet(bincode::deserialize(payload)?)),
766 cmd::UTXOSET => Ok(ProtocolMessage::UTXOSet(bincode::deserialize(payload)?)),
767 cmd::GETUTXOPROOF => Ok(ProtocolMessage::GetUTXOProof(bincode::deserialize(
768 payload,
769 )?)),
770 cmd::UTXOPROOF => Ok(ProtocolMessage::UTXOProof(bincode::deserialize(payload)?)),
771 cmd::GETFILTEREDBLOCK => Ok(ProtocolMessage::GetFilteredBlock(bincode::deserialize(
772 payload,
773 )?)),
774 cmd::FILTEREDBLOCK => Ok(ProtocolMessage::FilteredBlock(bincode::deserialize(
775 payload,
776 )?)),
777 cmd::GETCFILTERS => Ok(ProtocolMessage::GetCfilters(bincode::deserialize(payload)?)),
779 cmd::CFILTER => Ok(ProtocolMessage::Cfilter(bincode::deserialize(payload)?)),
780 cmd::GETCFHEADERS => Ok(ProtocolMessage::GetCfheaders(bincode::deserialize(
781 payload,
782 )?)),
783 cmd::CFHEADERS => Ok(ProtocolMessage::Cfheaders(bincode::deserialize(payload)?)),
784 cmd::GETCFCHECKPT => Ok(ProtocolMessage::GetCfcheckpt(bincode::deserialize(
785 payload,
786 )?)),
787 cmd::CFCHECKPT => Ok(ProtocolMessage::Cfcheckpt(bincode::deserialize(payload)?)),
788 cmd::GETPAYMENTREQUEST => Ok(ProtocolMessage::GetPaymentRequest(bincode::deserialize(
790 payload,
791 )?)),
792 cmd::PAYMENTREQUEST => Ok(ProtocolMessage::PaymentRequest(bincode::deserialize(
793 payload,
794 )?)),
795 cmd::PAYMENT => Ok(ProtocolMessage::Payment(bincode::deserialize(payload)?)),
796 cmd::PAYMENTACK => Ok(ProtocolMessage::PaymentACK(bincode::deserialize(payload)?)),
797 #[cfg(feature = "ctv")]
798 cmd::PAYMENTPROOF => Ok(ProtocolMessage::PaymentProof(bincode::deserialize(
799 payload,
800 )?)),
801 cmd::SETTLEMENTNOTIFICATION => Ok(ProtocolMessage::SettlementNotification(
802 bincode::deserialize(payload)?,
803 )),
804 cmd::SENDPKGTXN => Ok(ProtocolMessage::SendPkgTxn(bincode::deserialize(payload)?)),
806 cmd::PKGTXN => Ok(ProtocolMessage::PkgTxn(bincode::deserialize(payload)?)),
807 cmd::PKGTXNREJECT => Ok(ProtocolMessage::PkgTxnReject(bincode::deserialize(
808 payload,
809 )?)),
810 cmd::GETBANLIST => Ok(ProtocolMessage::GetBanList(bincode::deserialize(payload)?)),
812 cmd::BANLIST => Ok(ProtocolMessage::BanList(bincode::deserialize(payload)?)),
813 cmd::GETADDR => Ok(ProtocolMessage::GetAddr),
814 cmd::ADDR => {
815 let wire_msg = crate::wire::deserialize_addr(payload)
816 .map_err(|e| anyhow::anyhow!("Failed to deserialize addr: {}", e))?;
817 Ok(ProtocolMessage::Addr(wire_msg))
818 }
819 cmd::ADDRV2 => {
820 let wire_msg = deserialize_addrv2(payload)
821 .map_err(|e| anyhow::anyhow!("Failed to deserialize addrv2: {}", e))?;
822 Ok(ProtocolMessage::AddrV2(wire_msg))
823 }
824 cmd::GETMODULE => Ok(ProtocolMessage::GetModule(bincode::deserialize(payload)?)),
826 cmd::MODULE => Ok(ProtocolMessage::Module(bincode::deserialize(payload)?)),
827 cmd::GETMODULEBYHASH => Ok(ProtocolMessage::GetModuleByHash(bincode::deserialize(
828 payload,
829 )?)),
830 cmd::MODULEBYHASH => Ok(ProtocolMessage::ModuleByHash(bincode::deserialize(
831 payload,
832 )?)),
833 cmd::MODULEINV => Ok(ProtocolMessage::ModuleInv(bincode::deserialize(payload)?)),
834 cmd::GETMODULELIST => Ok(ProtocolMessage::GetModuleList(bincode::deserialize(
835 payload,
836 )?)),
837 cmd::MODULELIST => Ok(ProtocolMessage::ModuleList(bincode::deserialize(payload)?)),
838 cmd::MESH => Ok(ProtocolMessage::MeshPacket(payload.to_vec())),
840 #[cfg(feature = "erlay")]
841 cmd::SENDTXRCNCL => Ok(ProtocolMessage::SendTxRcncl(bincode::deserialize(payload)?)),
842 #[cfg(feature = "erlay")]
843 cmd::REQRECON => Ok(ProtocolMessage::ReqRecon(bincode::deserialize(payload)?)),
844 #[cfg(feature = "erlay")]
845 cmd::REQSKT => Ok(ProtocolMessage::ReqSkt(bincode::deserialize(payload)?)),
846 #[cfg(feature = "erlay")]
847 cmd::SKETCH => Ok(ProtocolMessage::Sketch(bincode::deserialize(payload)?)),
848 _ => Err(anyhow::anyhow!("Unknown command: {}", command)),
849 }
850 }
851
852 pub fn serialize_message(message: &ProtocolMessage) -> Result<Vec<u8>> {
854 let (command, payload) = match message {
855 ProtocolMessage::Version(msg) => {
856 use crate::network::VersionMessage as WireVersionMessage;
858 use crate::wire::serialize_version;
859
860 let version_msg = WireVersionMessage {
861 version: msg.version as u32,
862 services: msg.services,
863 timestamp: msg.timestamp,
864 addr_recv: msg.addr_recv.clone(),
865 addr_from: msg.addr_from.clone(),
866 nonce: msg.nonce,
867 user_agent: msg.user_agent.clone(),
868 start_height: msg.start_height,
869 relay: msg.relay,
870 };
871
872 let payload = serialize_version(&version_msg)?;
876 (cmd::VERSION, payload)
877 }
878 ProtocolMessage::Verack => (cmd::VERACK, vec![]),
879 ProtocolMessage::SendHeaders => (cmd::SENDHEADERS, vec![]),
880 ProtocolMessage::Ping(msg) => (
881 cmd::PING,
882 crate::wire::serialize_ping(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
883 ),
884 ProtocolMessage::Pong(msg) => (
885 cmd::PONG,
886 crate::wire::serialize_pong(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
887 ),
888 ProtocolMessage::GetHeaders(msg) => (
889 cmd::GETHEADERS,
890 serialize_getheaders(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
891 ),
892 ProtocolMessage::Headers(msg) => (
893 cmd::HEADERS,
894 crate::wire::serialize_headers(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
895 ),
896 ProtocolMessage::GetBlocks(msg) => (
897 cmd::GETBLOCKS,
898 serialize_getblocks(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
899 ),
900 ProtocolMessage::Block(msg) => {
901 let payload = crate::serialization::serialize_block_with_witnesses(
903 &msg.block,
904 &msg.witnesses,
905 true,
906 );
907 (cmd::BLOCK, payload)
908 }
909 ProtocolMessage::GetData(msg) => (
910 cmd::GETDATA,
911 serialize_getdata(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
912 ),
913 ProtocolMessage::Inv(msg) => (
914 cmd::INV,
915 serialize_inv(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
916 ),
917 ProtocolMessage::NotFound(msg) => (
918 cmd::NOTFOUND,
919 serialize_notfound(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
920 ),
921 ProtocolMessage::Reject(msg) => (
922 cmd::REJECT,
923 serialize_reject(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
924 ),
925 ProtocolMessage::Tx(msg) => (
926 cmd::TX,
927 serialize_tx(&msg.transaction).map_err(|e| anyhow::anyhow!("{}", e))?,
928 ),
929 ProtocolMessage::FeeFilter(msg) => (
930 cmd::FEEFILTER,
931 serialize_feefilter(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
932 ),
933 ProtocolMessage::MemPool => (cmd::MEMPOOL, vec![]),
934 ProtocolMessage::SendCmpct(msg) => (
936 cmd::SENDCMPCT,
937 serialize_sendcmpct(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
938 ),
939 ProtocolMessage::CmpctBlock(msg) => {
940 use crate::network::CmpctBlockMessage;
941 let wire_msg = CmpctBlockMessage::try_from(msg.compact_block.clone())
942 .map_err(|e| anyhow::anyhow!("{}", e))?;
943 let payload =
944 serialize_cmpctblock(&wire_msg).map_err(|e| anyhow::anyhow!("{}", e))?;
945 (cmd::CMPCTBLOCK, payload)
946 }
947 ProtocolMessage::GetBlockTxn(msg) => (
948 cmd::GETBLOCKTXN,
949 crate::wire::serialize_getblocktxn(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
950 ),
951 ProtocolMessage::BlockTxn(msg) => (
952 cmd::BLOCKTXN,
953 crate::wire::serialize_blocktxn(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
954 ),
955 ProtocolMessage::GetUTXOSet(msg) => (cmd::GETUTXOSET, bincode::serialize(msg)?),
957 ProtocolMessage::UTXOSet(msg) => (cmd::UTXOSET, bincode::serialize(msg)?),
958 ProtocolMessage::GetUTXOProof(msg) => (cmd::GETUTXOPROOF, bincode::serialize(msg)?),
959 ProtocolMessage::UTXOProof(msg) => (cmd::UTXOPROOF, bincode::serialize(msg)?),
960 ProtocolMessage::GetFilteredBlock(msg) => {
961 (cmd::GETFILTEREDBLOCK, bincode::serialize(msg)?)
962 }
963 ProtocolMessage::FilteredBlock(msg) => (cmd::FILTEREDBLOCK, bincode::serialize(msg)?),
964 ProtocolMessage::GetCfilters(msg) => (cmd::GETCFILTERS, bincode::serialize(msg)?),
966 ProtocolMessage::Cfilter(msg) => (cmd::CFILTER, bincode::serialize(msg)?),
967 ProtocolMessage::GetCfheaders(msg) => (cmd::GETCFHEADERS, bincode::serialize(msg)?),
968 ProtocolMessage::Cfheaders(msg) => (cmd::CFHEADERS, bincode::serialize(msg)?),
969 ProtocolMessage::GetCfcheckpt(msg) => (cmd::GETCFCHECKPT, bincode::serialize(msg)?),
970 ProtocolMessage::Cfcheckpt(msg) => (cmd::CFCHECKPT, bincode::serialize(msg)?),
971 ProtocolMessage::GetPaymentRequest(msg) => {
973 (cmd::GETPAYMENTREQUEST, bincode::serialize(msg)?)
974 }
975 ProtocolMessage::PaymentRequest(msg) => (cmd::PAYMENTREQUEST, bincode::serialize(msg)?),
976 ProtocolMessage::Payment(msg) => (cmd::PAYMENT, bincode::serialize(msg)?),
977 ProtocolMessage::PaymentACK(msg) => (cmd::PAYMENTACK, bincode::serialize(msg)?),
978 #[cfg(feature = "ctv")]
980 ProtocolMessage::PaymentProof(msg) => (cmd::PAYMENTPROOF, bincode::serialize(msg)?),
981 ProtocolMessage::SettlementNotification(msg) => {
982 (cmd::SETTLEMENTNOTIFICATION, bincode::serialize(msg)?)
983 }
984 ProtocolMessage::SendPkgTxn(msg) => (cmd::SENDPKGTXN, bincode::serialize(msg)?),
986 ProtocolMessage::PkgTxn(msg) => (cmd::PKGTXN, bincode::serialize(msg)?),
987 ProtocolMessage::PkgTxnReject(msg) => (cmd::PKGTXNREJECT, bincode::serialize(msg)?),
988 ProtocolMessage::GetBanList(msg) => (cmd::GETBANLIST, bincode::serialize(msg)?),
990 ProtocolMessage::BanList(msg) => (cmd::BANLIST, bincode::serialize(msg)?),
991 ProtocolMessage::GetAddr => (cmd::GETADDR, vec![]),
993 ProtocolMessage::Addr(msg) => (
994 cmd::ADDR,
995 crate::wire::serialize_addr(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
996 ),
997 ProtocolMessage::AddrV2(msg) => (
998 cmd::ADDRV2,
999 serialize_addrv2(msg).map_err(|e| anyhow::anyhow!("{}", e))?,
1000 ),
1001 ProtocolMessage::GetModule(msg) => (cmd::GETMODULE, bincode::serialize(msg)?),
1003 ProtocolMessage::Module(msg) => (cmd::MODULE, bincode::serialize(msg)?),
1004 ProtocolMessage::GetModuleByHash(msg) => {
1005 (cmd::GETMODULEBYHASH, bincode::serialize(msg)?)
1006 }
1007 ProtocolMessage::ModuleByHash(msg) => (cmd::MODULEBYHASH, bincode::serialize(msg)?),
1008 ProtocolMessage::ModuleInv(msg) => (cmd::MODULEINV, bincode::serialize(msg)?),
1009 ProtocolMessage::GetModuleList(msg) => (cmd::GETMODULELIST, bincode::serialize(msg)?),
1010 ProtocolMessage::ModuleList(msg) => (cmd::MODULELIST, bincode::serialize(msg)?),
1011 ProtocolMessage::MeshPacket(_) => {
1012 return Err(anyhow::anyhow!("MeshPacket handled separately"));
1013 }
1014 #[cfg(feature = "erlay")]
1015 ProtocolMessage::SendTxRcncl(msg) => (cmd::SENDTXRCNCL, bincode::serialize(msg)?),
1016 #[cfg(feature = "erlay")]
1017 ProtocolMessage::ReqRecon(msg) => (cmd::REQRECON, bincode::serialize(msg)?),
1018 #[cfg(feature = "erlay")]
1019 ProtocolMessage::ReqSkt(msg) => (cmd::REQSKT, bincode::serialize(msg)?),
1020 #[cfg(feature = "erlay")]
1021 ProtocolMessage::Sketch(msg) => (cmd::SKETCH, bincode::serialize(msg)?),
1022 };
1023
1024 crate::p2p_frame::build_p2p_frame(BITCOIN_MAGIC_MAINNET, command, &payload)
1025 .map_err(|e| anyhow::anyhow!("{}", e))
1026 }
1027
1028 #[cfg_attr(
1033 feature = "protocol-verification",
1034 spec_locked("10.1.1", "CalculateChecksum")
1035 )]
1036 #[cfg_attr(
1037 feature = "protocol-verification",
1038 blvm_spec_lock::ensures(result.len() == 4)
1039 )]
1040 pub fn calculate_checksum(payload: &[u8]) -> [u8; 4] {
1041 crate::p2p_frame::bitcoin_p2p_payload_checksum(payload)
1042 }
1043}
1044
1045#[derive(Debug, Clone, Serialize, Deserialize)]
1049pub struct GetBanListMessage {
1050 pub request_full: bool,
1052 pub min_ban_duration: u64,
1054}
1055
1056#[derive(Debug, Clone, Serialize, Deserialize)]
1058pub struct BanListMessage {
1059 pub is_full: bool,
1061 pub ban_list_hash: Hash,
1063 pub ban_entries: Vec<BanEntry>,
1065 pub timestamp: u64,
1067}
1068
1069#[derive(Debug, Clone, Serialize, Deserialize)]
1071pub struct BanEntry {
1072 pub addr: NetworkAddress,
1074 pub unban_timestamp: u64,
1076 pub reason: Option<String>,
1078}