Skip to content
Draft
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: 2 additions & 6 deletions dash-spv-ffi/src/broadcast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,13 @@ pub unsafe extern "C" fn dash_spv_ffi_client_broadcast_transaction(
let client = &(*client);
let inner = client.inner.clone();

let result: Result<(), dash_spv::SpvError> = client.runtime.block_on(async {
let result: dash_spv::Result<()> = client.runtime.block_on(async {
// Take the client out to avoid holding the lock across await
let spv_client = {
let mut guard = inner.lock().unwrap();
match guard.take() {
Some(client) => client,
None => {
return Err(dash_spv::SpvError::Storage(dash_spv::StorageError::NotFound(
"Client not initialized".to_string(),
)))
}
None => return Err(dash_spv::Error::UninitializedClient),
}
};

Expand Down
76 changes: 18 additions & 58 deletions dash-spv-ffi/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_new(
DashSpvClient::new(client_config, network, storage, wallet).await
}
(Err(e), _) => Err(e),
(_, Err(e)) => Err(dash_spv::SpvError::Storage(e)),
(_, Err(e)) => Err(e.into()),
}
});

Expand Down Expand Up @@ -379,7 +379,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_drain_events(client: *mut FFIDashSp
FFIErrorCode::Success as i32
}

fn stop_client_internal(client: &mut FFIDashSpvClient) -> Result<(), dash_spv::SpvError> {
fn stop_client_internal(client: &mut FFIDashSpvClient) -> dash_spv::Result<()> {
client.shutdown_token.cancel();

// Ensure callbacks are cleared so no further progress/completion notifications fire.
Expand All @@ -399,11 +399,7 @@ fn stop_client_internal(client: &mut FFIDashSpvClient) -> Result<(), dash_spv::S
let mut guard = inner.lock().unwrap();
match guard.take() {
Some(client) => client,
None => {
return Err(dash_spv::SpvError::Storage(dash_spv::StorageError::NotFound(
"Client not initialized".to_string(),
)))
}
None => return Err(dash_spv::Error::UninitializedClient),
}
};
let res = spv_client.stop().await;
Expand Down Expand Up @@ -440,9 +436,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_update_config(
let mut guard = client.inner.lock().unwrap();
match guard.take() {
Some(client) => client,
None => {
return Err(dash_spv::SpvError::Config("Client not initialized".to_string()))
}
None => return Err(dash_spv::Error::UninitializedClient),
}
};

Expand Down Expand Up @@ -479,11 +473,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_start(client: *mut FFIDashSpvClient
let mut guard = inner.lock().unwrap();
match guard.take() {
Some(client) => client,
None => {
return Err(dash_spv::SpvError::Storage(dash_spv::StorageError::NotFound(
"Client not initialized".to_string(),
)))
}
None => return Err(dash_spv::Error::UninitializedClient),
}
};
let res = spv_client.start().await;
Expand Down Expand Up @@ -558,9 +548,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_test_sync(client: *mut FFIDashSpvCl
let mut guard = client.inner.lock().unwrap();
match guard.take() {
Some(client) => client,
None => {
return Err(dash_spv::SpvError::Config("Client not initialized".to_string()))
}
None => return Err(dash_spv::Error::UninitializedClient),
}
};
tracing::info!("Starting test sync...");
Expand Down Expand Up @@ -596,7 +584,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_test_sync(client: *mut FFIDashSpvCl
} else {
let msg = "No headers downloaded".to_string();
tracing::error!("❌ {}", msg);
Err(dash_spv::SpvError::Sync(dash_spv::SyncError::Network(msg)))
Err(dash_spv::Error::Sync(dash_spv::SyncError::Network(msg)))
};

// put client back
Expand Down Expand Up @@ -764,11 +752,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_sync_to_tip_with_progress(
let mut guard = inner.lock().unwrap();
match guard.take() {
Some(client) => client,
None => {
return Err(dash_spv::SpvError::Config(
"Client not initialized".to_string(),
))
}
None => return Err(dash_spv::Error::UninitializedClient),
}
};
let (_command_sender, command_receiver) = tokio::sync::mpsc::unbounded_channel();
Expand Down Expand Up @@ -892,11 +876,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_get_sync_progress(
let mut guard = inner.lock().unwrap();
match guard.take() {
Some(c) => c,
None => {
return Err(dash_spv::SpvError::Storage(dash_spv::StorageError::NotFound(
"Client not initialized".to_string(),
)))
}
None => return Err(dash_spv::Error::UninitializedClient),
}
};
let res = spv_client.sync_progress().await;
Expand Down Expand Up @@ -932,11 +912,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_get_stats(
let mut guard = inner.lock().unwrap();
match guard.take() {
Some(client) => client,
None => {
return Err(dash_spv::SpvError::Storage(dash_spv::StorageError::NotFound(
"Client not initialized".to_string(),
)))
}
None => return Err(dash_spv::Error::UninitializedClient),
}
};
let res = spv_client.stats().await;
Expand Down Expand Up @@ -978,9 +954,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_get_tip_hash(
let mut guard = inner.lock().unwrap();
match guard.take() {
Some(c) => c,
None => {
return Err(dash_spv::SpvError::Config("Client not initialized".to_string()))
}
None => return Err(dash_spv::Error::UninitializedClient),
}
};
let tip = spv_client.tip_hash().await;
Expand Down Expand Up @@ -1031,9 +1005,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_get_tip_height(
let mut guard = inner.lock().unwrap();
match guard.take() {
Some(c) => c,
None => {
return Err(dash_spv::SpvError::Config("Client not initialized".to_string()))
}
None => return Err(dash_spv::Error::UninitializedClient),
}
};
let height = spv_client.tip_height().await;
Expand Down Expand Up @@ -1070,9 +1042,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_clear_storage(client: *mut FFIDashS
let mut guard = inner.lock().unwrap();
match guard.take() {
Some(c) => c,
None => {
return Err(dash_spv::SpvError::Config("Client not initialized".to_string()))
}
None => return Err(dash_spv::Error::UninitializedClient),
}
};

Expand Down Expand Up @@ -1232,15 +1202,13 @@ pub unsafe extern "C" fn dash_spv_ffi_client_rescan_blockchain(
let client = &(*client);
let inner = client.inner.clone();

let result: Result<(), dash_spv::SpvError> = client.runtime.block_on(async {
let result: dash_spv::Result<()> = client.runtime.block_on(async {
let mut guard = inner.lock().unwrap();
if let Some(ref mut _spv_client) = *guard {
// TODO: rescan_from_height not yet implemented in dash-spv
Err(dash_spv::SpvError::Config("Not implemented".to_string()))
Err(dash_spv::Error::Config("Not implemented".to_string()))
} else {
Err(dash_spv::SpvError::Storage(dash_spv::StorageError::NotFound(
"Client not initialized".to_string(),
)))
Err(dash_spv::Error::UninitializedClient)
}
});

Expand Down Expand Up @@ -1274,11 +1242,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_enable_mempool_tracking(
let mut guard = inner.lock().unwrap();
match guard.take() {
Some(client) => client,
None => {
return Err(dash_spv::SpvError::Storage(dash_spv::StorageError::NotFound(
"Client not initialized".to_string(),
)))
}
None => return Err(dash_spv::Error::UninitializedClient),
}
};
let res = spv_client.enable_mempool_tracking(mempool_strategy).await;
Expand Down Expand Up @@ -1332,11 +1296,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_record_send(
let mut guard = inner.lock().unwrap();
match guard.take() {
Some(client) => client,
None => {
return Err(dash_spv::SpvError::Storage(dash_spv::StorageError::NotFound(
"Client not initialized".to_string(),
)))
}
None => return Err(dash_spv::Error::UninitializedClient),
}
};
let res = spv_client.record_send(txid).await;
Expand Down
27 changes: 12 additions & 15 deletions dash-spv-ffi/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use dash_spv::error::SpvError;
use std::ffi::CString;
use std::os::raw::c_char;
use std::sync::Mutex;
Expand Down Expand Up @@ -49,21 +48,19 @@ pub extern "C" fn dash_spv_ffi_clear_error() {
clear_last_error();
}

impl From<SpvError> for FFIErrorCode {
fn from(err: SpvError) -> Self {
impl From<dash_spv::Error> for FFIErrorCode {
fn from(err: dash_spv::Error) -> Self {
match err {
SpvError::ChannelFailure(_, _) => FFIErrorCode::RuntimeError,
SpvError::Network(_) => FFIErrorCode::NetworkError,
SpvError::Storage(_) => FFIErrorCode::StorageError,
SpvError::Validation(_) => FFIErrorCode::ValidationError,
SpvError::Sync(_) => FFIErrorCode::SyncError,
SpvError::Io(_) => FFIErrorCode::RuntimeError,
SpvError::Config(_) => FFIErrorCode::ConfigError,
SpvError::Parse(_) => FFIErrorCode::ValidationError,
SpvError::Logging(_) => FFIErrorCode::RuntimeError,
SpvError::Wallet(_) => FFIErrorCode::WalletError,
SpvError::QuorumLookupError(_) => FFIErrorCode::ValidationError,
SpvError::General(_) => FFIErrorCode::Unknown,
dash_spv::Error::ChannelFailure(_, _) => FFIErrorCode::RuntimeError,
dash_spv::Error::Network(_) => FFIErrorCode::NetworkError,
dash_spv::Error::Storage(_) => FFIErrorCode::StorageError,
dash_spv::Error::Validation(_) => FFIErrorCode::ValidationError,
dash_spv::Error::Sync(_) => FFIErrorCode::SyncError,
dash_spv::Error::Config(_) => FFIErrorCode::ConfigError,
dash_spv::Error::Logging(_) => FFIErrorCode::RuntimeError,
dash_spv::Error::QuorumLookupError(_) => FFIErrorCode::ValidationError,
dash_spv::Error::UninitializedClient => FFIErrorCode::RuntimeError,
dash_spv::Error::TaskFailed(_) => FFIErrorCode::RuntimeError,
}
}
}
Expand Down
15 changes: 6 additions & 9 deletions dash-spv-ffi/tests/unit/test_error_handling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,24 +109,21 @@ mod tests {
assert_eq!(FFIErrorCode::Unknown as i32, 99);

// Test conversions from SpvError
use dash_spv::{NetworkError, SpvError, StorageError, SyncError, ValidationError};
use dash_spv::{NetworkError, StorageError, SyncError, ValidationError};

let net_err = SpvError::Network(NetworkError::ConnectionFailed("test".to_string()));
let net_err = dash_spv::Error::Network(NetworkError::ConnectionFailed("test".to_string()));
assert_eq!(FFIErrorCode::from(net_err) as i32, FFIErrorCode::NetworkError as i32);

let storage_err = SpvError::Storage(StorageError::NotFound("test".to_string()));
let storage_err = dash_spv::Error::Storage(StorageError::NotFound("test".to_string()));
assert_eq!(FFIErrorCode::from(storage_err) as i32, FFIErrorCode::StorageError as i32);

let val_err = SpvError::Validation(ValidationError::InvalidProofOfWork);
let val_err = dash_spv::Error::Validation(ValidationError::InvalidProofOfWork);
assert_eq!(FFIErrorCode::from(val_err) as i32, FFIErrorCode::ValidationError as i32);

let sync_err = SpvError::Sync(SyncError::Timeout("Test timeout".to_string()));
let sync_err = dash_spv::Error::Sync(SyncError::Timeout("Test timeout".to_string()));
assert_eq!(FFIErrorCode::from(sync_err) as i32, FFIErrorCode::SyncError as i32);

let io_err = SpvError::Io(std::io::Error::other("test"));
assert_eq!(FFIErrorCode::from(io_err) as i32, FFIErrorCode::RuntimeError as i32);

let config_err = SpvError::Config("test".to_string());
let config_err = dash_spv::Error::Config("test".to_string());
assert_eq!(FFIErrorCode::from(config_err) as i32, FFIErrorCode::ConfigError as i32);
}

Expand Down
4 changes: 4 additions & 0 deletions dash-spv/clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
disallowed-types = [
{ path = "std::sync::RwLock", reason = "This struct is blocking and can be poisoned", replacement = "tokio::sync::RwLock" },
{ path = "std::sync::Mutex", reason = "This struct is blocking and can be poisoned", replacement = "tokio::sync::Mutex" },
]
Loading
Loading