Skip to content
Merged
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
8 changes: 8 additions & 0 deletions dash-spv/src/test_utils/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub struct MockNetworkManager {
connected_peer: SocketAddr,
headers_chain: Vec<BlockHeader>,
message_dispatcher: MessageDispatcher,
sent_messages: Vec<NetworkMessage>,
}

impl MockNetworkManager {
Expand All @@ -30,6 +31,7 @@ impl MockNetworkManager {
connected_peer: SocketAddr::new(std::net::Ipv4Addr::LOCALHOST.into(), 9999),
headers_chain: Vec::new(),
message_dispatcher: MessageDispatcher::default(),
sent_messages: Vec::new(),
}
}

Expand Down Expand Up @@ -87,6 +89,10 @@ impl MockNetworkManager {
Vec::new()
}
}

pub fn sent_messages(&self) -> &Vec<NetworkMessage> {
&self.sent_messages
}
}

impl Default for MockNetworkManager {
Expand Down Expand Up @@ -129,6 +135,8 @@ impl NetworkManager for MockNetworkManager {
}
}

self.sent_messages.push(message);

Ok(())
}

Expand Down
74 changes: 3 additions & 71 deletions dash-spv/tests/edge_case_filter_sync_test.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
//! Tests for edge case handling in filter header sync, particularly at the tip.

use dash_spv::network::{Message, MessageDispatcher, MessageType};
use dash_spv::test_utils::MockNetworkManager;
use dash_spv::{
client::ClientConfig,
error::NetworkResult,
network::NetworkManager,
storage::{BlockHeaderStorage, DiskStorageManager, FilterHeaderStorage},
sync::legacy::filters::FilterSyncManager,
};
Expand All @@ -15,74 +13,8 @@ use dashcore::{
use std::collections::HashSet;
use std::sync::Arc;
use tempfile::TempDir;
use tokio::sync::mpsc::UnboundedReceiver;
use tokio::sync::Mutex;

/// Mock network manager that captures sent messages
struct MockNetworkManager {
sent_messages: Arc<Mutex<Vec<NetworkMessage>>>,
message_dispatcher: MessageDispatcher,
}

impl MockNetworkManager {
fn new() -> Self {
Self {
sent_messages: Arc::new(Mutex::new(Vec::new())),
message_dispatcher: MessageDispatcher::default(),
}
}

async fn get_sent_messages(&self) -> Vec<NetworkMessage> {
self.sent_messages.lock().await.clone()
}
}

#[async_trait::async_trait]
impl NetworkManager for MockNetworkManager {
fn as_any(&self) -> &dyn std::any::Any {
self
}

async fn message_receiver(
&mut self,
message_types: &[MessageType],
) -> UnboundedReceiver<Message> {
self.message_dispatcher.message_receiver(message_types)
}

async fn connect(&mut self) -> NetworkResult<()> {
Ok(())
}

async fn disconnect(&mut self) -> NetworkResult<()> {
Ok(())
}

async fn send_message(&mut self, message: NetworkMessage) -> NetworkResult<()> {
self.sent_messages.lock().await.push(message);
Ok(())
}

fn is_connected(&self) -> bool {
true
}

fn peer_count(&self) -> usize {
1
}

async fn get_peer_best_height(&self) -> dash_spv::error::NetworkResult<Option<u32>> {
Ok(Some(100))
}

async fn has_peer_with_service(
&self,
_service_flags: dashcore::network::constants::ServiceFlags,
) -> bool {
true
}
}

#[tokio::test]
async fn test_filter_sync_at_tip_edge_case() {
let config = ClientConfig::new(Network::Dash);
Expand Down Expand Up @@ -115,7 +47,7 @@ async fn test_filter_sync_at_tip_edge_case() {
assert!(!result.unwrap(), "Should not start sync when already at tip");

// Verify no messages were sent
let sent_messages = network.get_sent_messages().await;
let sent_messages = network.sent_messages();
assert_eq!(sent_messages.len(), 0, "Should not send any messages when at tip");
}

Expand Down Expand Up @@ -146,7 +78,7 @@ async fn test_no_invalid_getcfheaders_at_tip() {
assert!(result.unwrap(), "Should start sync when behind by 1 block");

// Check the sent message
let sent_messages = network.get_sent_messages().await;
let sent_messages = network.sent_messages();
assert_eq!(sent_messages.len(), 1, "Should send exactly one message");

match &sent_messages[0] {
Expand Down
74 changes: 2 additions & 72 deletions dash-spv/tests/filter_header_verification_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,95 +8,25 @@
//! The failure indicates a race condition or inconsistency in how filter headers
//! are calculated, stored, or verified across multiple batches.

use dash_spv::network::{Message, MessageDispatcher};
use dash_spv::test_utils::MockNetworkManager;
use dash_spv::{
client::ClientConfig,
error::{NetworkError, SyncError},
network::{MessageType, NetworkManager},
error::SyncError,
storage::{BlockHeaderStorage, DiskStorageManager, FilterHeaderStorage},
sync::legacy::filters::FilterSyncManager,
};
use dashcore::{
block::Header as BlockHeader,
hash_types::{FilterHash, FilterHeader},
network::message::NetworkMessage,
network::message_filter::CFHeaders,
BlockHash, Network,
};
use dashcore_hashes::{sha256d, Hash};
use std::collections::HashSet;
use std::sync::Arc;
use tempfile::TempDir;
use tokio::sync::mpsc::UnboundedReceiver;
use tokio::sync::Mutex;

/// Mock network manager for testing filter sync
#[derive(Debug)]
struct MockNetworkManager {
sent_messages: Vec<NetworkMessage>,
message_dispatcher: MessageDispatcher,
}

impl MockNetworkManager {
fn new() -> Self {
Self {
sent_messages: Vec::new(),
message_dispatcher: MessageDispatcher::default(),
}
}

#[allow(dead_code)]
fn clear_sent_messages(&mut self) {
self.sent_messages.clear();
}
}

#[async_trait::async_trait]
impl NetworkManager for MockNetworkManager {
async fn connect(&mut self) -> Result<(), NetworkError> {
Ok(())
}

async fn disconnect(&mut self) -> Result<(), NetworkError> {
Ok(())
}

async fn send_message(&mut self, message: NetworkMessage) -> Result<(), NetworkError> {
self.sent_messages.push(message);
Ok(())
}

fn is_connected(&self) -> bool {
true
}

fn peer_count(&self) -> usize {
1
}

fn as_any(&self) -> &dyn std::any::Any {
self
}

async fn message_receiver(
&mut self,
message_types: &[MessageType],
) -> UnboundedReceiver<Message> {
self.message_dispatcher.message_receiver(message_types)
}

async fn get_peer_best_height(&self) -> dash_spv::error::NetworkResult<Option<u32>> {
Ok(Some(100))
}

async fn has_peer_with_service(
&self,
_service_flags: dashcore::network::constants::ServiceFlags,
) -> bool {
true
}
}

/// Create test filter headers with proper chain linkage
fn create_test_cfheaders_message(
start_height: u32,
Expand Down
Loading