Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions dash-spv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ key-wallet-manager = { path = "../key-wallet-manager" }
# BLS signatures
blsful = { git = "https://github.com/dashpay/agora-blsful", rev = "0c34a7a488a0bd1c9a9a2196e793b303ad35c900" }

# BIP324 v2 P2P encrypted transport
bip324 = { git = "https://github.com/rust-bitcoin/bip324", rev = "8c469432", features = ["std", "tokio"] }

# CLI
clap = { version = "4.0", features = ["derive", "env"] }

Expand Down
17 changes: 17 additions & 0 deletions dash-spv/src/client/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::time::Duration;
use dashcore::Network;
// Serialization removed due to complex Address types

use crate::network::transport::TransportPreference;
use crate::types::ValidationMode;

/// Strategy for handling mempool (unconfirmed) transactions.
Expand Down Expand Up @@ -152,6 +153,10 @@ pub struct ClientConfig {

/// Timeout for QRInfo requests (default: 30 seconds).
pub qr_info_timeout: Duration,

/// Transport preference for peer connections (V1, V2, or V2 with fallback).
/// Default is V2Preferred: try V2 encrypted transport first, fall back to V1.
pub transport_preference: TransportPreference,
}

impl Default for ClientConfig {
Expand Down Expand Up @@ -201,6 +206,8 @@ impl Default for ClientConfig {
// QRInfo defaults (simplified per plan)
qr_info_extra_share: false, // Matches DMLviewer.patch default
qr_info_timeout: Duration::from_secs(30),
// Transport preference (BIP324 v2 encrypted by default with v1 fallback)
transport_preference: TransportPreference::default(),
}
}
}
Expand Down Expand Up @@ -342,6 +349,16 @@ impl ClientConfig {
self
}

/// Set transport preference for peer connections.
///
/// - `V2Preferred` (default): Try BIP324 v2 encrypted transport first, fall back to v1
/// - `V2Only`: Require BIP324 v2 encrypted transport, fail if peer doesn't support it
/// - `V1Only`: Use traditional unencrypted v1 transport only
pub fn with_transport_preference(mut self, preference: TransportPreference) -> Self {
self.transport_preference = preference;
self
}

/// Validate the configuration.
pub fn validate(&self) -> Result<(), String> {
// Note: Empty peers list is now valid - DNS discovery will be used automatically
Expand Down
13 changes: 13 additions & 0 deletions dash-spv/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,19 @@ pub enum NetworkError {

#[error("System time error: {0}")]
SystemTime(String),

// BIP324 V2 transport errors
#[error("V2 handshake failed: {0}")]
V2HandshakeFailed(String),

#[error("V2 decryption failed: {0}")]
V2DecryptionFailed(String),

#[error("V2 encryption failed: {0}")]
V2EncryptionFailed(String),

#[error("V2 not supported by peer")]
V2NotSupported,
}

/// Storage-related errors.
Expand Down
10 changes: 9 additions & 1 deletion dash-spv/src/network/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::network::pool::PeerPool;
use crate::network::reputation::{
misbehavior_scores, positive_scores, PeerReputationManager, ReputationAware,
};
use crate::network::transport::TransportPreference;
use crate::network::{HandshakeManager, NetworkManager, Peer};
use crate::types::PeerInfo;

Expand Down Expand Up @@ -71,6 +72,8 @@ pub struct PeerNetworkManager {
exclusive_mode: bool,
/// Cached count of currently connected peers for fast, non-blocking queries
connected_peer_count: Arc<AtomicUsize>,
/// Transport preference for peer connections (V1, V2, or V2 with fallback)
transport_preference: TransportPreference,
}

impl PeerNetworkManager {
Expand Down Expand Up @@ -124,6 +127,7 @@ impl PeerNetworkManager {
user_agent: config.user_agent.clone(),
exclusive_mode,
connected_peer_count: Arc::new(AtomicUsize::new(0)),
transport_preference: config.transport_preference,
})
}

Expand Down Expand Up @@ -210,13 +214,16 @@ impl PeerNetworkManager {
let mempool_strategy = self.mempool_strategy;
let user_agent = self.user_agent.clone();
let connected_peer_count = self.connected_peer_count.clone();
let transport_preference = self.transport_preference;

// Spawn connection task
let mut tasks = self.tasks.lock().await;
tasks.spawn(async move {
log::debug!("Attempting to connect to {}", addr);

match Peer::connect(addr, CONNECTION_TIMEOUT.as_secs(), network).await {
match Peer::connect(addr, CONNECTION_TIMEOUT.as_secs(), network, transport_preference)
.await
{
Ok(mut peer) => {
// Perform handshake
let mut handshake_manager =
Expand Down Expand Up @@ -1036,6 +1043,7 @@ impl Clone for PeerNetworkManager {
user_agent: self.user_agent.clone(),
exclusive_mode: self.exclusive_mode,
connected_peer_count: self.connected_peer_count.clone(),
transport_preference: self.transport_preference,
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions dash-spv/src/network/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub mod peer;
pub mod persist;
pub mod pool;
pub mod reputation;
pub mod transport;

#[cfg(test)]
mod tests;
Expand All @@ -25,6 +26,7 @@ use dashcore::BlockHash;
pub use handshake::{HandshakeManager, HandshakeState};
pub use manager::PeerNetworkManager;
pub use peer::Peer;
pub use transport::{Transport, TransportPreference, V1Transport};

/// Network manager trait for abstracting network operations.
#[async_trait]
Expand Down
Loading