Skip to main content

blvm_protocol/utxo_commitments/
network_integration.rs

1//! Network Integration Helpers for UTXO Commitments
2//!
3//! Provides helper functions and types for integrating UTXO commitments
4//! with the P2P network layer in blvm-node.
5
6#[cfg(feature = "utxo-commitments")]
7use crate::spam_filter::{SpamFilter, SpamSummary};
8#[cfg(feature = "utxo-commitments")]
9use crate::utxo_commitments::data_structures::{
10    UtxoCommitment, UtxoCommitmentError, UtxoCommitmentResult,
11};
12#[cfg(feature = "utxo-commitments")]
13use blvm_consensus::types::{BlockHeader, Hash as HashType, Natural, Transaction};
14#[cfg(feature = "utxo-commitments")]
15/// Filtered block structure
16#[derive(Debug, Clone)]
17pub struct FilteredBlock {
18    pub header: BlockHeader,
19    pub commitment: UtxoCommitment,
20    pub transactions: Vec<Transaction>,
21    pub transaction_indices: Vec<u32>,
22    pub spam_summary: SpamSummary,
23}
24
25/// Network client interface for UTXO commitments
26///
27/// In a full implementation, this would be implemented by the blvm-node's
28/// network manager to send/receive P2P messages.
29///
30/// Note: This trait is designed for static dispatch. For dynamic dispatch,
31/// use the helper functions below or wrap in a type-erased async trait.
32pub trait UtxoCommitmentsNetworkClient: Send + Sync {
33    /// Request UTXO set from a peer at specific height
34    ///
35    /// This is a synchronous interface that returns a Future.
36    /// In practice, implementers will use async/await internally.
37    fn request_utxo_set(
38        &self,
39        peer_id: &str,
40        height: Natural,
41        block_hash: HashType,
42    ) -> std::pin::Pin<
43        Box<dyn std::future::Future<Output = UtxoCommitmentResult<UtxoCommitment>> + Send + '_>,
44    >;
45
46    /// Request filtered block from a peer
47    fn request_filtered_block(
48        &self,
49        peer_id: &str,
50        block_hash: HashType,
51    ) -> std::pin::Pin<
52        Box<dyn std::future::Future<Output = UtxoCommitmentResult<FilteredBlock>> + Send + '_>,
53    >;
54
55    /// Request full block from a peer (with witnesses)
56    ///
57    /// Returns the full block and its witnesses for complete validation.
58    /// This is required for full transaction validation during sync forward.
59    fn request_full_block(
60        &self,
61        peer_id: &str,
62        block_hash: HashType,
63    ) -> std::pin::Pin<
64        Box<dyn std::future::Future<Output = UtxoCommitmentResult<FullBlock>> + Send + '_>,
65    >;
66
67    /// Get list of connected peer IDs
68    fn get_peer_ids(&self) -> Vec<String>;
69}
70
71/// Full block structure with witnesses
72///
73/// Used for complete block validation during sync forward.
74/// The commitment is computed after validation, not included here.
75#[derive(Debug, Clone)]
76pub struct FullBlock {
77    pub block: blvm_consensus::types::Block,
78    pub witnesses: Vec<Vec<blvm_consensus::segwit::Witness>>,
79}
80
81/// Helper function to request UTXO sets from multiple peers
82///
83/// Takes a function that can request UTXO sets (for flexibility)
84pub async fn request_utxo_sets_from_peers_fn<F, Fut>(
85    request_fn: F,
86    peers: &[String],
87    height: Natural,
88    block_hash: HashType,
89) -> Vec<(String, UtxoCommitmentResult<UtxoCommitment>)>
90where
91    F: Fn(&str, Natural, HashType) -> Fut,
92    Fut: std::future::Future<Output = UtxoCommitmentResult<UtxoCommitment>>,
93{
94    let mut results = Vec::new();
95
96    for peer_id in peers {
97        let result = request_fn(peer_id, height, block_hash).await;
98        results.push((peer_id.clone(), result));
99    }
100
101    results
102}
103
104/// Helper to process filtered block and verify commitment
105pub fn process_and_verify_filtered_block(
106    filtered_block: &FilteredBlock,
107    expected_height: Natural,
108    _spam_filter: &SpamFilter,
109) -> UtxoCommitmentResult<bool> {
110    // Verify block header height matches expected
111    // (In real implementation, would verify full header chain)
112
113    // Verify commitment height matches
114    if filtered_block.commitment.block_height != expected_height {
115        return Err(UtxoCommitmentError::VerificationFailed(format!(
116            "Commitment height mismatch: expected {}, got {}",
117            expected_height, filtered_block.commitment.block_height
118        )));
119    }
120
121    // Verify transactions are properly filtered
122    // (In real implementation, would re-apply filter and compare)
123
124    // Verify commitment block hash matches header
125    let computed_hash = compute_block_hash(&filtered_block.header);
126    if filtered_block.commitment.block_hash != computed_hash {
127        return Err(UtxoCommitmentError::VerificationFailed(format!(
128            "Block hash mismatch: expected {:?}, got {:?}",
129            computed_hash, filtered_block.commitment.block_hash
130        )));
131    }
132
133    Ok(true)
134}
135
136/// Compute block header hash (double SHA256)
137fn compute_block_hash(header: &BlockHeader) -> HashType {
138    use sha2::{Digest, Sha256};
139
140    let mut bytes = Vec::with_capacity(80);
141    bytes.extend_from_slice(&header.version.to_le_bytes());
142    bytes.extend_from_slice(&header.prev_block_hash);
143    bytes.extend_from_slice(&header.merkle_root);
144    bytes.extend_from_slice(&header.timestamp.to_le_bytes());
145    bytes.extend_from_slice(&header.bits.to_le_bytes());
146    bytes.extend_from_slice(&header.nonce.to_le_bytes());
147
148    let first_hash = Sha256::digest(&bytes);
149    let second_hash = Sha256::digest(&first_hash);
150
151    let mut hash = [0u8; 32];
152    hash.copy_from_slice(&second_hash);
153    hash
154}