1- use crate :: { set_last_error, FFIArray , FFIErrorCode } ;
2- use dash_spv:: chain:: checkpoints :: { mainnet_checkpoints , testnet_checkpoints , CheckpointManager } ;
1+ use crate :: { set_last_error, FFIErrorCode } ;
2+ use dash_spv:: chain:: CheckpointManager ;
33use dashcore:: hashes:: Hash ;
4- use dashcore:: Network ;
54use key_wallet_ffi:: FFINetwork ;
65
76/// FFI representation of a checkpoint (height + block hash)
@@ -11,15 +10,6 @@ pub struct FFICheckpoint {
1110 pub block_hash : [ u8 ; 32 ] ,
1211}
1312
14- fn manager_for_network ( network : FFINetwork ) -> Result < CheckpointManager , String > {
15- let net: Network = network. into ( ) ;
16- match net {
17- Network :: Dash => Ok ( CheckpointManager :: new ( mainnet_checkpoints ( ) ) ) ,
18- Network :: Testnet => Ok ( CheckpointManager :: new ( testnet_checkpoints ( ) ) ) ,
19- _ => Err ( "Checkpoints are only available for Dash and Testnet" . to_string ( ) ) ,
20- }
21- }
22-
2313/// Get the latest checkpoint for the given network.
2414///
2515/// # Safety
@@ -31,26 +21,7 @@ pub unsafe extern "C" fn dash_spv_ffi_checkpoint_latest(
3121 out_height : * mut u32 ,
3222 out_hash : * mut u8 , // expects at least 32 bytes
3323) -> i32 {
34- if out_height. is_null ( ) || out_hash. is_null ( ) {
35- set_last_error ( "Null output pointer provided" ) ;
36- return FFIErrorCode :: NullPointer as i32 ;
37- }
38- let mgr = match manager_for_network ( network) {
39- Ok ( m) => m,
40- Err ( e) => {
41- set_last_error ( & e) ;
42- return FFIErrorCode :: InvalidArgument as i32 ;
43- }
44- } ;
45- if let Some ( cp) = mgr. last_checkpoint ( ) {
46- * out_height = cp. height ;
47- let hash = cp. block_hash . to_byte_array ( ) ;
48- std:: ptr:: copy_nonoverlapping ( hash. as_ptr ( ) , out_hash, 32 ) ;
49- FFIErrorCode :: Success as i32
50- } else {
51- set_last_error ( "No checkpoints available for network" ) ;
52- FFIErrorCode :: NotImplemented as i32
53- }
24+ dash_spv_ffi_checkpoint_before_height ( network, u32:: MAX , out_height, out_hash)
5425}
5526
5627/// Get the last checkpoint at or before a given height.
@@ -69,22 +40,14 @@ pub unsafe extern "C" fn dash_spv_ffi_checkpoint_before_height(
6940 set_last_error ( "Null output pointer provided" ) ;
7041 return FFIErrorCode :: NullPointer as i32 ;
7142 }
72- let mgr = match manager_for_network ( network) {
73- Ok ( m) => m,
74- Err ( e) => {
75- set_last_error ( & e) ;
76- return FFIErrorCode :: InvalidArgument as i32 ;
77- }
78- } ;
79- if let Some ( cp) = mgr. last_checkpoint_before_height ( height) {
80- * out_height = cp. height ;
81- let hash = cp. block_hash . to_byte_array ( ) ;
82- std:: ptr:: copy_nonoverlapping ( hash. as_ptr ( ) , out_hash, 32 ) ;
83- FFIErrorCode :: Success as i32
84- } else {
85- set_last_error ( "No checkpoint at or before given height" ) ;
86- FFIErrorCode :: ValidationError as i32
87- }
43+
44+ let mgr = CheckpointManager :: new ( network. into ( ) ) ;
45+
46+ let ( height, cp) = mgr. last_checkpoint_before_height ( height) ;
47+ * out_height = height;
48+ let hash = cp. hash ( ) . to_byte_array ( ) ;
49+ std:: ptr:: copy_nonoverlapping ( hash. as_ptr ( ) , out_hash, 32 ) ;
50+ FFIErrorCode :: Success as i32
8851}
8952
9053/// Get the last checkpoint at or before a given UNIX timestamp (seconds).
@@ -103,60 +66,12 @@ pub unsafe extern "C" fn dash_spv_ffi_checkpoint_before_timestamp(
10366 set_last_error ( "Null output pointer provided" ) ;
10467 return FFIErrorCode :: NullPointer as i32 ;
10568 }
106- let mgr = match manager_for_network ( network) {
107- Ok ( m) => m,
108- Err ( e) => {
109- set_last_error ( & e) ;
110- return FFIErrorCode :: InvalidArgument as i32 ;
111- }
112- } ;
113- if let Some ( cp) = mgr. last_checkpoint_before_timestamp ( timestamp) {
114- * out_height = cp. height ;
115- let hash = cp. block_hash . to_byte_array ( ) ;
116- std:: ptr:: copy_nonoverlapping ( hash. as_ptr ( ) , out_hash, 32 ) ;
117- FFIErrorCode :: Success as i32
118- } else {
119- set_last_error ( "No checkpoint at or before given timestamp" ) ;
120- FFIErrorCode :: ValidationError as i32
121- }
122- }
12369
124- /// Get all checkpoints between two heights (inclusive).
125- ///
126- /// Returns an `FFIArray` of `FFICheckpoint` items. The caller owns the memory and
127- /// must free the array buffer using `dash_spv_ffi_array_destroy` when done.
128- #[ no_mangle]
129- pub extern "C" fn dash_spv_ffi_checkpoints_between_heights (
130- network : FFINetwork ,
131- start_height : u32 ,
132- end_height : u32 ,
133- ) -> FFIArray {
134- match manager_for_network ( network) {
135- Ok ( mgr) => {
136- // Collect checkpoints within inclusive range
137- let mut out: Vec < FFICheckpoint > = Vec :: new ( ) ;
138- for & h in mgr. checkpoint_heights ( ) {
139- if h >= start_height && h <= end_height {
140- if let Some ( cp) = mgr. get_checkpoint ( h) {
141- out. push ( FFICheckpoint {
142- height : cp. height ,
143- block_hash : cp. block_hash . to_byte_array ( ) ,
144- } ) ;
145- }
146- }
147- }
148- FFIArray :: new ( out)
149- }
150- Err ( e) => {
151- set_last_error ( & e) ;
152- // Return empty array on error
153- FFIArray {
154- data : std:: ptr:: null_mut ( ) ,
155- len : 0 ,
156- capacity : 0 ,
157- elem_size : std:: mem:: size_of :: < FFICheckpoint > ( ) ,
158- elem_align : std:: mem:: align_of :: < FFICheckpoint > ( ) ,
159- }
160- }
161- }
70+ let mgr = CheckpointManager :: new ( network. into ( ) ) ;
71+
72+ let ( height, cp) = mgr. last_checkpoint_before_timestamp ( timestamp) ;
73+ * out_height = height;
74+ let hash = cp. hash ( ) . to_byte_array ( ) ;
75+ std:: ptr:: copy_nonoverlapping ( hash. as_ptr ( ) , out_hash, 32 ) ;
76+ FFIErrorCode :: Success as i32
16277}
0 commit comments