Skip to content
39 changes: 16 additions & 23 deletions dash-spv-ffi/dash_spv_ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@ typedef enum FFISyncStage {
Downloading = 2,
Validating = 3,
Storing = 4,
Complete = 5,
Failed = 6,
DownloadingFilterHeaders = 5,
DownloadingFilters = 6,
DownloadingBlocks = 7,
Complete = 8,
Failed = 9,
} FFISyncStage;

typedef enum DashSpvValidationMode {
Expand Down Expand Up @@ -70,32 +73,28 @@ typedef struct FFIString {
uintptr_t length;
} FFIString;

typedef struct FFISyncProgress {
uint32_t header_height;
uint32_t filter_header_height;
uint32_t masternode_height;
uint32_t peer_count;
bool filter_sync_available;
uint32_t filters_downloaded;
uint32_t last_synced_filter_height;
} FFISyncProgress;

typedef struct FFIDetailedSyncProgress {
uint32_t current_height;
uint32_t total_height;
double percentage;
double headers_per_second;
int64_t estimated_seconds_remaining;
enum FFISyncStage stage;
struct FFIString stage_message;
uint32_t connected_peers;
struct FFISyncProgress overview;
uint64_t total_headers;
int64_t sync_start_timestamp;
} FFIDetailedSyncProgress;

typedef struct FFISyncProgress {
uint32_t header_height;
uint32_t filter_header_height;
uint32_t masternode_height;
uint32_t peer_count;
bool headers_synced;
bool filter_headers_synced;
bool masternodes_synced;
bool filter_sync_available;
uint32_t filters_downloaded;
uint32_t last_synced_filter_height;
} FFISyncProgress;

typedef struct FFISpvStats {
uint32_t connected_peers;
uint32_t total_peers;
Expand Down Expand Up @@ -150,11 +149,6 @@ typedef void (*WalletTransactionCallback)(const char *wallet_id,
bool is_ours,
void *user_data);

typedef void (*FilterHeadersProgressCallback)(uint32_t filter_height,
uint32_t header_height,
double percentage,
void *user_data);

typedef struct FFIEventCallbacks {
BlockCallback on_block;
TransactionCallback on_transaction;
Expand All @@ -164,7 +158,6 @@ typedef struct FFIEventCallbacks {
MempoolRemovedCallback on_mempool_transaction_removed;
CompactFilterMatchedCallback on_compact_filter_matched;
WalletTransactionCallback on_wallet_transaction;
FilterHeadersProgressCallback on_filter_headers_progress;
void *user_data;
} FFIEventCallbacks;

Expand Down
39 changes: 16 additions & 23 deletions dash-spv-ffi/include/dash_spv_ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@ typedef enum FFISyncStage {
Downloading = 2,
Validating = 3,
Storing = 4,
Complete = 5,
Failed = 6,
DownloadingFilterHeaders = 5,
DownloadingFilters = 6,
DownloadingBlocks = 7,
Complete = 8,
Failed = 9,
} FFISyncStage;

typedef enum DashSpvValidationMode {
Expand Down Expand Up @@ -70,32 +73,28 @@ typedef struct FFIString {
uintptr_t length;
} FFIString;

typedef struct FFISyncProgress {
uint32_t header_height;
uint32_t filter_header_height;
uint32_t masternode_height;
uint32_t peer_count;
bool filter_sync_available;
uint32_t filters_downloaded;
uint32_t last_synced_filter_height;
} FFISyncProgress;

typedef struct FFIDetailedSyncProgress {
uint32_t current_height;
uint32_t total_height;
double percentage;
double headers_per_second;
int64_t estimated_seconds_remaining;
enum FFISyncStage stage;
struct FFIString stage_message;
uint32_t connected_peers;
struct FFISyncProgress overview;
uint64_t total_headers;
int64_t sync_start_timestamp;
} FFIDetailedSyncProgress;

typedef struct FFISyncProgress {
uint32_t header_height;
uint32_t filter_header_height;
uint32_t masternode_height;
uint32_t peer_count;
bool headers_synced;
bool filter_headers_synced;
bool masternodes_synced;
bool filter_sync_available;
uint32_t filters_downloaded;
uint32_t last_synced_filter_height;
} FFISyncProgress;

typedef struct FFISpvStats {
uint32_t connected_peers;
uint32_t total_peers;
Expand Down Expand Up @@ -150,11 +149,6 @@ typedef void (*WalletTransactionCallback)(const char *wallet_id,
bool is_ours,
void *user_data);

typedef void (*FilterHeadersProgressCallback)(uint32_t filter_height,
uint32_t header_height,
double percentage,
void *user_data);

typedef struct FFIEventCallbacks {
BlockCallback on_block;
TransactionCallback on_transaction;
Expand All @@ -164,7 +158,6 @@ typedef struct FFIEventCallbacks {
MempoolRemovedCallback on_mempool_transaction_removed;
CompactFilterMatchedCallback on_compact_filter_matched;
WalletTransactionCallback on_wallet_transaction;
FilterHeadersProgressCallback on_filter_headers_progress;
void *user_data;
} FFIEventCallbacks;

Expand Down
30 changes: 18 additions & 12 deletions dash-spv-ffi/src/bin/ffi_cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_void};
use std::ptr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;

Expand All @@ -16,17 +17,15 @@ enum NetworkOpt {
Regtest,
}

static SYNC_COMPLETED: AtomicBool = AtomicBool::new(false);

fn ffi_string_to_rust(s: *const c_char) -> String {
if s.is_null() {
return String::new();
}
unsafe { CStr::from_ptr(s) }.to_str().unwrap_or_default().to_owned()
}

extern "C" fn on_filter_headers_progress(filter: u32, headers: u32, pct: f64, _ud: *mut c_void) {
println!("filters: {} headers: {} progress: {:.2}%", filter, headers, pct * 100.0);
}

extern "C" fn on_detailed_progress(progress: *const FFIDetailedSyncProgress, _ud: *mut c_void) {
if progress.is_null() {
return;
Expand All @@ -35,10 +34,10 @@ extern "C" fn on_detailed_progress(progress: *const FFIDetailedSyncProgress, _ud
let p = &*progress;
println!(
"height {}/{} {:.2}% peers {} hps {:.1}",
p.current_height,
p.overview.header_height,
p.total_height,
p.percentage * 100.0,
p.connected_peers,
p.overview.peer_count,
p.headers_per_second
);
}
Expand All @@ -48,6 +47,7 @@ extern "C" fn on_completion(success: bool, msg: *const c_char, _ud: *mut c_void)
let m = ffi_string_to_rust(msg);
if success {
println!("Completed: {}", m);
SYNC_COMPLETED.store(true, Ordering::SeqCst);
} else {
eprintln!("Failed: {}", m);
}
Expand Down Expand Up @@ -171,7 +171,7 @@ fn main() {
std::process::exit(1);
}

// Set minimal event callbacks (progress via filter headers)
// Set minimal event callbacks
let callbacks = FFIEventCallbacks {
on_block: None,
on_transaction: None,
Expand All @@ -181,7 +181,6 @@ fn main() {
on_mempool_transaction_removed: None,
on_compact_filter_matched: None,
on_wallet_transaction: None,
on_filter_headers_progress: Some(on_filter_headers_progress),
user_data: ptr::null_mut(),
};
let _ = dash_spv_ffi_client_set_event_callbacks(client, callbacks);
Expand All @@ -193,6 +192,9 @@ fn main() {
std::process::exit(1);
}

// Ensure completion flag is reset before starting sync
SYNC_COMPLETED.store(false, Ordering::SeqCst);

// Run sync on this thread; detailed progress will print via callback
let rc = dash_spv_ffi_client_sync_to_tip_with_progress(
client,
Expand All @@ -211,10 +213,14 @@ fn main() {
let prog_ptr = dash_spv_ffi_client_get_sync_progress(client);
if !prog_ptr.is_null() {
let prog = &*prog_ptr;
let filters_complete = prog.filter_headers_synced
|| !prog.filter_sync_available
|| disable_filter_sync;
if prog.headers_synced && filters_complete {
let headers_done = SYNC_COMPLETED.load(Ordering::SeqCst);
let filters_complete = if disable_filter_sync || !prog.filter_sync_available {
false
} else {
prog.filter_header_height >= prog.header_height
&& prog.last_synced_filter_height >= prog.filter_header_height
};
if headers_done && (filters_complete || disable_filter_sync) {
dash_spv_ffi_sync_progress_destroy(prog_ptr);
break;
}
Expand Down
26 changes: 0 additions & 26 deletions dash-spv-ffi/src/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,6 @@ pub type WalletTransactionCallback = Option<
),
>;

pub type FilterHeadersProgressCallback = Option<
extern "C" fn(filter_height: u32, header_height: u32, percentage: f64, user_data: *mut c_void),
>;

#[repr(C)]
pub struct FFIEventCallbacks {
pub on_block: BlockCallback,
Expand All @@ -149,7 +145,6 @@ pub struct FFIEventCallbacks {
pub on_mempool_transaction_removed: MempoolRemovedCallback,
pub on_compact_filter_matched: CompactFilterMatchedCallback,
pub on_wallet_transaction: WalletTransactionCallback,
pub on_filter_headers_progress: FilterHeadersProgressCallback,
pub user_data: *mut c_void,
}

Expand Down Expand Up @@ -178,7 +173,6 @@ impl Default for FFIEventCallbacks {
on_mempool_transaction_removed: None,
on_compact_filter_matched: None,
on_wallet_transaction: None,
on_filter_headers_progress: None,
user_data: std::ptr::null_mut(),
}
}
Expand Down Expand Up @@ -389,23 +383,3 @@ impl FFIEventCallbacks {
}
}
}

impl FFIEventCallbacks {
pub fn call_filter_headers_progress(
&self,
filter_height: u32,
header_height: u32,
percentage: f64,
) {
if let Some(callback) = self.on_filter_headers_progress {
tracing::info!(
"📊 Calling filter headers progress callback: filter_height={}, header_height={}, pct={:.2}",
filter_height, header_height, percentage
);
callback(filter_height, header_height, percentage, self.user_data);
tracing::info!("✅ Filter headers progress callback completed");
} else {
tracing::debug!("Filter headers progress callback not set");
}
}
}
22 changes: 5 additions & 17 deletions dash-spv-ffi/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,17 +249,6 @@ impl FFIDashSpvClient {
} => {
callbacks.call_balance_update(confirmed, unconfirmed);
}
dash_spv::types::SpvEvent::FilterHeadersProgress {
filter_header_height,
header_height,
percentage,
} => {
callbacks.call_filter_headers_progress(
filter_header_height,
header_height,
percentage,
);
}
dash_spv::types::SpvEvent::TransactionDetected {
ref txid,
confirmed,
Expand Down Expand Up @@ -804,7 +793,10 @@ pub unsafe extern "C" fn dash_spv_ffi_client_sync_to_tip_with_progress(
match maybe_progress {
Some(progress) => {
// Handle callback in a thread-safe way
let should_stop = matches!(progress.sync_stage, SyncStage::Complete);
let should_stop = matches!(
progress.sync_stage,
SyncStage::Complete | SyncStage::Failed(_)
);

// Create FFI progress
let ffi_progress = Box::new(FFIDetailedSyncProgress::from(progress));
Expand Down Expand Up @@ -945,7 +937,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_sync_to_tip_with_progress(
FFIErrorCode::Success as i32
}

// Note: filter headers progress is forwarded via FFIEventCallbacks.on_filter_headers_progress
// Filter header progress updates are included in the detailed sync progress callback.

/// Cancels the sync operation.
///
Expand Down Expand Up @@ -1278,10 +1270,6 @@ pub unsafe extern "C" fn dash_spv_ffi_client_set_event_callbacks(
tracing::debug!(" Block callback: {}", callbacks.on_block.is_some());
tracing::debug!(" Transaction callback: {}", callbacks.on_transaction.is_some());
tracing::debug!(" Balance update callback: {}", callbacks.on_balance_update.is_some());
tracing::debug!(
" Filter headers progress callback: {}",
callbacks.on_filter_headers_progress.is_some()
);

let mut event_callbacks = client.event_callbacks.lock().unwrap();
*event_callbacks = callbacks;
Expand Down
Loading
Loading