Skip to content

Commit 05e95c9

Browse files
feat(dash-spv): Add BIP324 v2 encrypted P2P transport
Implement BIP324 encrypted transport for dash-spv peer connections: - Add Transport trait abstracting v1/v2 protocol differences - Implement V1Transport (extracted from existing peer.rs code) - Implement V2Transport with ChaCha20-Poly1305 encryption - Add V2 handshake with ElligatorSwift key exchange - Add Dash-specific short message IDs (128-167) - Add TransportPreference config (V2Preferred, V2Only, V1Only) - Default to V2Preferred with automatic fallback to v1 Key implementation details: - Cache decrypted packet length to prevent cipher state desync - Support all Dash short IDs matching Dash Core's V2_DASH_IDS - Proper handling of bip324 crate's packet type header byte 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 8009033 commit 05e95c9

File tree

13 files changed

+2388
-417
lines changed

13 files changed

+2388
-417
lines changed

dash-spv/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ key-wallet-manager = { path = "../key-wallet-manager" }
1818
# BLS signatures
1919
blsful = { git = "https://github.com/dashpay/agora-blsful", rev = "0c34a7a488a0bd1c9a9a2196e793b303ad35c900" }
2020

21+
# BIP324 v2 P2P encrypted transport
22+
bip324 = { git = "https://github.com/rust-bitcoin/bip324", rev = "8c469432", features = ["std", "tokio"] }
23+
2124
# CLI
2225
clap = { version = "4.0", features = ["derive", "env"] }
2326

dash-spv/src/client/config.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::time::Duration;
77
use dashcore::Network;
88
// Serialization removed due to complex Address types
99

10+
use crate::network::transport::TransportPreference;
1011
use crate::types::ValidationMode;
1112

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

153154
/// Timeout for QRInfo requests (default: 30 seconds).
154155
pub qr_info_timeout: Duration,
156+
157+
/// Transport preference for peer connections (V1, V2, or V2 with fallback).
158+
/// Default is V2Preferred: try V2 encrypted transport first, fall back to V1.
159+
pub transport_preference: TransportPreference,
155160
}
156161

157162
impl Default for ClientConfig {
@@ -201,6 +206,8 @@ impl Default for ClientConfig {
201206
// QRInfo defaults (simplified per plan)
202207
qr_info_extra_share: false, // Matches DMLviewer.patch default
203208
qr_info_timeout: Duration::from_secs(30),
209+
// Transport preference (BIP324 v2 encrypted by default with v1 fallback)
210+
transport_preference: TransportPreference::default(),
204211
}
205212
}
206213
}
@@ -342,6 +349,16 @@ impl ClientConfig {
342349
self
343350
}
344351

352+
/// Set transport preference for peer connections.
353+
///
354+
/// - `V2Preferred` (default): Try BIP324 v2 encrypted transport first, fall back to v1
355+
/// - `V2Only`: Require BIP324 v2 encrypted transport, fail if peer doesn't support it
356+
/// - `V1Only`: Use traditional unencrypted v1 transport only
357+
pub fn with_transport_preference(mut self, preference: TransportPreference) -> Self {
358+
self.transport_preference = preference;
359+
self
360+
}
361+
345362
/// Validate the configuration.
346363
pub fn validate(&self) -> Result<(), String> {
347364
// Note: Empty peers list is now valid - DNS discovery will be used automatically

dash-spv/src/error.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,19 @@ pub enum NetworkError {
104104

105105
#[error("System time error: {0}")]
106106
SystemTime(String),
107+
108+
// BIP324 V2 transport errors
109+
#[error("V2 handshake failed: {0}")]
110+
V2HandshakeFailed(String),
111+
112+
#[error("V2 decryption failed: {0}")]
113+
V2DecryptionFailed(String),
114+
115+
#[error("V2 encryption failed: {0}")]
116+
V2EncryptionFailed(String),
117+
118+
#[error("V2 not supported by peer")]
119+
V2NotSupported,
107120
}
108121

109122
/// Storage-related errors.

dash-spv/src/network/manager.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use crate::network::pool::PeerPool;
2727
use crate::network::reputation::{
2828
misbehavior_scores, positive_scores, PeerReputationManager, ReputationAware,
2929
};
30+
use crate::network::transport::TransportPreference;
3031
use crate::network::{HandshakeManager, NetworkManager, Peer};
3132
use crate::types::PeerInfo;
3233

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

7679
impl PeerNetworkManager {
@@ -124,6 +127,7 @@ impl PeerNetworkManager {
124127
user_agent: config.user_agent.clone(),
125128
exclusive_mode,
126129
connected_peer_count: Arc::new(AtomicUsize::new(0)),
130+
transport_preference: config.transport_preference,
127131
})
128132
}
129133

@@ -210,13 +214,16 @@ impl PeerNetworkManager {
210214
let mempool_strategy = self.mempool_strategy;
211215
let user_agent = self.user_agent.clone();
212216
let connected_peer_count = self.connected_peer_count.clone();
217+
let transport_preference = self.transport_preference;
213218

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

219-
match Peer::connect(addr, CONNECTION_TIMEOUT.as_secs(), network).await {
224+
match Peer::connect(addr, CONNECTION_TIMEOUT.as_secs(), network, transport_preference)
225+
.await
226+
{
220227
Ok(mut peer) => {
221228
// Perform handshake
222229
let mut handshake_manager =
@@ -1036,6 +1043,7 @@ impl Clone for PeerNetworkManager {
10361043
user_agent: self.user_agent.clone(),
10371044
exclusive_mode: self.exclusive_mode,
10381045
connected_peer_count: self.connected_peer_count.clone(),
1046+
transport_preference: self.transport_preference,
10391047
}
10401048
}
10411049
}

dash-spv/src/network/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub mod peer;
99
pub mod persist;
1010
pub mod pool;
1111
pub mod reputation;
12+
pub mod transport;
1213

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

2931
/// Network manager trait for abstracting network operations.
3032
#[async_trait]

0 commit comments

Comments
 (0)