Skip to content

Commit 04f194c

Browse files
authored
refactor: build DiskStorageManager from config path (#366)
* config storage_path is no longer an option and the DiskStorageManager is built using the config * main.rs udpated
1 parent 4fcf5e4 commit 04f194c

21 files changed

+134
-178
lines changed

dash-spv-ffi/src/client.rs

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -147,35 +147,12 @@ pub unsafe extern "C" fn dash_spv_ffi_client_new(
147147
}
148148
};
149149

150-
let mut client_config = config.clone_inner();
151-
152-
let storage_path = client_config.storage_path.clone().unwrap_or_else(|| {
153-
// Create a unique temporary directory if none was provided
154-
static PATH_COUNTER: AtomicU64 = AtomicU64::new(0);
155-
156-
let mut path = std::env::temp_dir();
157-
path.push("dash-spv");
158-
path.push(
159-
format!(
160-
"{:?}-{}-{}",
161-
client_config.network,
162-
std::process::id(),
163-
PATH_COUNTER.fetch_add(1, Ordering::Relaxed)
164-
)
165-
.to_lowercase(),
166-
);
167-
tracing::warn!(
168-
"dash-spv FFI config missing storage path, falling back to temp dir {:?}",
169-
path
170-
);
171-
path
172-
});
173-
client_config.storage_path = Some(storage_path.clone());
150+
let client_config = config.clone_inner();
174151

175152
let client_result = runtime.block_on(async move {
176153
// Construct concrete implementations for generics
177154
let network = dash_spv::network::PeerNetworkManager::new(&client_config).await;
178-
let storage = DiskStorageManager::new(storage_path.clone()).await;
155+
let storage = DiskStorageManager::new(&client_config).await;
179156
let wallet = key_wallet_manager::wallet_manager::WalletManager::<
180157
key_wallet::wallet::managed_wallet_info::ManagedWalletInfo,
181158
>::new(client_config.network);

dash-spv-ffi/src/config.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ pub unsafe extern "C" fn dash_spv_ffi_config_set_data_dir(
7777
let config = unsafe { &mut *((*config).inner as *mut ClientConfig) };
7878
match CStr::from_ptr(path).to_str() {
7979
Ok(path_str) => {
80-
config.storage_path = Some(path_str.into());
80+
config.storage_path = path_str.into();
8181
FFIErrorCode::Success as i32
8282
}
8383
Err(e) => {
@@ -331,13 +331,7 @@ pub unsafe extern "C" fn dash_spv_ffi_config_get_data_dir(
331331
}
332332

333333
let config = unsafe { &*((*config).inner as *const ClientConfig) };
334-
match &config.storage_path {
335-
Some(dir) => FFIString::new(&dir.to_string_lossy()),
336-
None => FFIString {
337-
ptr: std::ptr::null_mut(),
338-
length: 0,
339-
},
340-
}
334+
FFIString::new(&config.storage_path.to_string_lossy())
341335
}
342336

343337
/// Destroys an FFIClientConfig and frees its memory

dash-spv-ffi/tests/test_wallet_manager.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ mod tests {
1111
FFIError, FFINetwork, FFIWalletManager,
1212
};
1313
use key_wallet_manager::wallet_manager::WalletManager;
14-
use std::ffi::CStr;
14+
use std::ffi::{CStr, CString};
15+
use tempfile::TempDir;
1516

1617
#[test]
1718
fn test_get_wallet_manager() {
@@ -20,6 +21,12 @@ mod tests {
2021
let config = dash_spv_ffi_config_testnet();
2122
assert!(!config.is_null());
2223

24+
let temp_dir = TempDir::new().unwrap();
25+
dash_spv_ffi_config_set_data_dir(
26+
config,
27+
CString::new(temp_dir.path().to_str().unwrap()).unwrap().as_ptr(),
28+
);
29+
2330
// Create a client
2431
let client = dash_spv_ffi_client_new(config);
2532
assert!(!client.is_null());
@@ -51,6 +58,12 @@ mod tests {
5158
let config = dash_spv_ffi_config_testnet();
5259
assert!(!config.is_null());
5360

61+
let temp_dir = TempDir::new().unwrap();
62+
dash_spv_ffi_config_set_data_dir(
63+
config,
64+
CString::new(temp_dir.path().to_str().unwrap()).unwrap().as_ptr(),
65+
);
66+
5467
let client = dash_spv_ffi_client_new(config);
5568
assert!(!client.is_null());
5669

dash-spv/benches/storage.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::time::Duration;
33
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
44
use dash_spv::{
55
storage::{BlockHeaderStorage, DiskStorageManager, StorageManager},
6-
Hash,
6+
ClientConfig, Hash,
77
};
88
use dashcore::{block::Version, BlockHash, CompactTarget, Header};
99
use rand::{rngs::StdRng, Rng, SeedableRng};
@@ -34,7 +34,9 @@ fn bench_disk_storage(c: &mut Criterion) {
3434
c.bench_function("storage/disk/store", |b| {
3535
b.to_async(&rt).iter_batched(
3636
|| async {
37-
DiskStorageManager::new(TempDir::new().unwrap().path().to_path_buf()).await.unwrap()
37+
let config =
38+
ClientConfig::testnet().with_storage_path(TempDir::new().unwrap().path());
39+
DiskStorageManager::new(&config).await.unwrap()
3840
},
3941
|a| async {
4042
let mut storage = a.await;
@@ -47,10 +49,10 @@ fn bench_disk_storage(c: &mut Criterion) {
4749
)
4850
});
4951

50-
let temp_dir = TempDir::new().unwrap();
52+
let config = ClientConfig::testnet().with_storage_path(TempDir::new().unwrap().path());
5153

5254
let mut storage = rt.block_on(async {
53-
let mut storage = DiskStorageManager::new(temp_dir.path().to_path_buf()).await.unwrap();
55+
let mut storage = DiskStorageManager::new(&config).await.unwrap();
5456

5557
for chunk in headers.chunks(CHUNK_SIZE as usize) {
5658
storage.store_headers(chunk).await.unwrap();

dash-spv/examples/filter_sync.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
2222
)?;
2323

2424
// Create configuration with filter support
25-
let config = ClientConfig::mainnet().without_masternodes(); // Skip masternode sync for this example
25+
let config = ClientConfig::mainnet()
26+
.with_storage_path("./.tmp/filter-sync-example-storage")
27+
.without_masternodes(); // Skip masternode sync for this example
2628

2729
// Create network manager
2830
let network_manager = PeerNetworkManager::new(&config).await?;
2931

3032
// Create storage manager
31-
let storage_manager = DiskStorageManager::new("./.tmp/filter-sync-example-storage").await?;
33+
let storage_manager = DiskStorageManager::new(&config).await?;
3234

3335
// Create wallet manager
3436
let wallet = Arc::new(RwLock::new(WalletManager::<ManagedWalletInfo>::new(config.network)));

dash-spv/examples/simple_sync.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
1717

1818
// Create a simple configuration
1919
let config = ClientConfig::mainnet()
20+
.with_storage_path("./.tmp/simple-sync-example-storage")
2021
.without_filters() // Skip filter sync for this example
2122
.without_masternodes(); // Skip masternode sync for this example
2223

2324
// Create network manager
2425
let network_manager = PeerNetworkManager::new(&config).await?;
2526

2627
// Create storage manager
27-
let storage_manager = DiskStorageManager::new("./.tmp/simple-sync-example-storage").await?;
28+
let storage_manager = DiskStorageManager::new(&config).await?;
2829

2930
// Create wallet manager
3031
let wallet = Arc::new(RwLock::new(WalletManager::<ManagedWalletInfo>::new(config.network)));

dash-spv/examples/spv_with_wallet.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
1717
let _logging_guard = dash_spv::init_console_logging(LevelFilter::INFO)?;
1818

1919
// Create SPV client configuration
20-
let mut config = ClientConfig::testnet();
21-
config.storage_path = Some("/tmp/dash-spv-example".into());
22-
config.validation_mode = dash_spv::types::ValidationMode::Full;
23-
config.enable_filters = true;
20+
let config = ClientConfig::testnet()
21+
.with_storage_path("./.tmp/spv-with-wallet-example-storage")
22+
.with_validation_mode(dash_spv::ValidationMode::Full);
2423

2524
// Create network manager
2625
let network_manager = PeerNetworkManager::new(&config).await?;
2726

2827
// Create storage manager - use disk storage for persistence
29-
let storage_manager = DiskStorageManager::new("./.tmp/spv-with-wallet-example-storage").await?;
28+
let storage_manager = DiskStorageManager::new(&config).await?;
3029

3130
// Create wallet manager
3231
let wallet = Arc::new(RwLock::new(WalletManager::<ManagedWalletInfo>::new(config.network)));

dash-spv/src/client/config.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ pub struct ClientConfig {
3434
/// If no peers are configured, no outbound connections will be made.
3535
pub restrict_to_configured_peers: bool,
3636

37-
/// Optional path for persistent storage.
38-
pub storage_path: Option<PathBuf>,
37+
/// Path for persistent storage. Defaults to ./dash-spv-storage
38+
pub storage_path: PathBuf,
3939

4040
/// Validation mode.
4141
pub validation_mode: ValidationMode,
@@ -80,7 +80,7 @@ impl Default for ClientConfig {
8080
network: Network::Dash,
8181
peers: vec![],
8282
restrict_to_configured_peers: false,
83-
storage_path: None,
83+
storage_path: PathBuf::from("./dash-spv-storage"),
8484
validation_mode: ValidationMode::Full,
8585
enable_filters: true,
8686
enable_masternodes: true,
@@ -136,8 +136,8 @@ impl ClientConfig {
136136
}
137137

138138
/// Set storage path.
139-
pub fn with_storage_path(mut self, path: PathBuf) -> Self {
140-
self.storage_path = Some(path);
139+
pub fn with_storage_path(mut self, path: impl Into<PathBuf>) -> Self {
140+
self.storage_path = path.into();
141141
self
142142
}
143143

@@ -206,6 +206,13 @@ impl ClientConfig {
206206
);
207207
}
208208

209+
std::fs::create_dir_all(&self.storage_path).map_err(|e| {
210+
format!(
211+
"A valid storage path must be provided to the ClientConfig {:?}: {e}",
212+
self.storage_path
213+
)
214+
})?;
215+
209216
Ok(())
210217
}
211218

dash-spv/src/client/config_test.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ mod tests {
5555
.with_mempool_persistence(true)
5656
.with_start_height(100000);
5757

58-
assert_eq!(config.storage_path, Some(path));
58+
assert_eq!(config.storage_path, path);
5959
assert_eq!(config.validation_mode, ValidationMode::Basic);
6060

6161
// Mempool settings
@@ -88,12 +88,6 @@ mod tests {
8888
assert!(!config.enable_masternodes);
8989
}
9090

91-
#[test]
92-
fn test_validation_valid_config() {
93-
let config = ClientConfig::default();
94-
assert!(config.validate().is_ok());
95-
}
96-
9791
#[test]
9892
fn test_validation_invalid_max_peers() {
9993
let config = ClientConfig {

dash-spv/src/client/mod.rs

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,14 @@ mod message_handler_test;
6464
#[cfg(test)]
6565
mod tests {
6666
use super::{ClientConfig, DashSpvClient};
67+
use crate::client::config::MempoolStrategy;
6768
use crate::storage::DiskStorageManager;
6869
use crate::{test_utils::MockNetworkManager, types::UnconfirmedTransaction};
69-
use dashcore::{Address, Amount, Network, Transaction, TxOut};
70+
use dashcore::{Address, Amount, Transaction, TxOut};
7071
use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo;
7172
use key_wallet_manager::wallet_manager::WalletManager;
7273
use std::sync::Arc;
74+
use tempfile::TempDir;
7375
use tokio::sync::RwLock;
7476

7577
// Tests for get_mempool_balance function
@@ -80,13 +82,11 @@ mod tests {
8082

8183
#[tokio::test]
8284
async fn client_exposes_shared_wallet_manager() {
83-
let config = ClientConfig {
84-
network: Network::Dash,
85-
enable_filters: false,
86-
enable_masternodes: false,
87-
enable_mempool_tracking: false,
88-
..Default::default()
89-
};
85+
let config = ClientConfig::mainnet()
86+
.without_filters()
87+
.without_masternodes()
88+
.with_mempool_tracking(MempoolStrategy::FetchAll)
89+
.with_storage_path(TempDir::new().unwrap().path());
9090

9191
let network_manager = MockNetworkManager::new();
9292
let storage =
@@ -108,17 +108,14 @@ mod tests {
108108
// This test validates the get_mempool_balance logic by directly testing
109109
// the balance calculation code using a mocked mempool state.
110110

111-
let config = ClientConfig {
112-
network: Network::Testnet,
113-
enable_filters: false,
114-
enable_masternodes: false,
115-
enable_mempool_tracking: true,
116-
..Default::default()
117-
};
111+
let config = ClientConfig::testnet()
112+
.without_filters()
113+
.without_masternodes()
114+
.with_mempool_tracking(MempoolStrategy::FetchAll)
115+
.with_storage_path(TempDir::new().unwrap().path());
118116

119117
let network_manager = MockNetworkManager::new();
120-
let storage =
121-
DiskStorageManager::with_temp_dir().await.expect("Failed to create tmp storage");
118+
let storage = DiskStorageManager::new(&config).await.expect("Failed to create tmp storage");
122119
let wallet = Arc::new(RwLock::new(WalletManager::<ManagedWalletInfo>::new(config.network)));
123120

124121
let test_address = Address::dummy(config.network, 0);

0 commit comments

Comments
 (0)