@@ -22,6 +22,32 @@ use crate::{
2222
2323use super :: { Chain , Context } ;
2424
25+ /// Result of processing a block with the chainstate manager
26+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
27+ pub struct ProcessBlockResult {
28+ /// Whether the block was accepted
29+ pub accepted : bool ,
30+ /// Whether this is a new block
31+ pub new_block : bool ,
32+ }
33+
34+ impl ProcessBlockResult {
35+ /// Returns true if the block was accepted and is new
36+ pub fn is_new_block ( & self ) -> bool {
37+ self . accepted && self . new_block
38+ }
39+
40+ /// Returns true if the block was accepted but was already known
41+ pub fn is_duplicate ( & self ) -> bool {
42+ self . accepted && !self . new_block
43+ }
44+
45+ /// Returns true if the block was rejected
46+ pub fn is_rejected ( & self ) -> bool {
47+ !self . accepted
48+ }
49+ }
50+
2551/// The chainstate manager is the central object for doing validation tasks as
2652/// well as retrieving data from the chain. Internally it is a complex data
2753/// structure with diverse functionality.
@@ -54,12 +80,16 @@ impl ChainstateManager {
5480 /// also be retrieved through a registered validation interface. If the block
5581 /// fails to validate the `block_checked` callback's ['BlockValidationState'] will
5682 /// contain details.
57- pub fn process_block ( & self , block : & Block ) -> ( bool /* accepted */ , bool /* duplicate */ ) {
83+ pub fn process_block ( & self , block : & Block ) -> ProcessBlockResult {
5884 let mut new_block: i32 = 0 ;
5985 let accepted = unsafe {
6086 btck_chainstate_manager_process_block ( self . inner , block. as_ptr ( ) , & mut new_block)
6187 } ;
62- ( c_helpers:: success ( accepted) , c_helpers:: enabled ( new_block) )
88+
89+ ProcessBlockResult {
90+ accepted : c_helpers:: success ( accepted) ,
91+ new_block : c_helpers:: enabled ( new_block) ,
92+ }
6393 }
6494
6595 /// May be called after load_chainstate to initialize the
@@ -273,4 +303,91 @@ mod tests {
273303 let chainman = ChainstateManager :: new ( opts) ;
274304 assert ! ( chainman. is_ok( ) ) ;
275305 }
306+
307+ #[ test]
308+ fn test_process_block_result_new_block ( ) {
309+ let result = ProcessBlockResult {
310+ accepted : true ,
311+ new_block : true ,
312+ } ;
313+
314+ assert ! ( result. accepted) ;
315+ assert ! ( result. new_block) ;
316+ assert ! ( result. is_new_block( ) ) ;
317+ assert ! ( !result. is_duplicate( ) ) ;
318+ assert ! ( !result. is_rejected( ) ) ;
319+ }
320+
321+ #[ test]
322+ fn test_process_block_result_duplicate ( ) {
323+ let result = ProcessBlockResult {
324+ accepted : true ,
325+ new_block : false ,
326+ } ;
327+
328+ assert ! ( result. accepted) ;
329+ assert ! ( !result. new_block) ;
330+ assert ! ( !result. is_new_block( ) ) ;
331+ assert ! ( result. is_duplicate( ) ) ;
332+ assert ! ( !result. is_rejected( ) ) ;
333+ }
334+
335+ #[ test]
336+ fn test_process_block_result_rejected ( ) {
337+ let result = ProcessBlockResult {
338+ accepted : false ,
339+ new_block : false ,
340+ } ;
341+
342+ assert ! ( !result. accepted) ;
343+ assert ! ( !result. is_new_block( ) ) ;
344+ assert ! ( !result. is_duplicate( ) ) ;
345+ assert ! ( result. is_rejected( ) ) ;
346+ }
347+
348+ #[ test]
349+ fn test_process_block_result_rejected_new_block_flag ( ) {
350+ // Edge case: rejected but new_block=true (shouldn't happen in practice)
351+ let result = ProcessBlockResult {
352+ accepted : false ,
353+ new_block : true ,
354+ } ;
355+
356+ assert ! ( !result. accepted) ;
357+ assert ! ( result. new_block) ;
358+ assert ! ( !result. is_new_block( ) ) ; // Not considered new if rejected
359+ assert ! ( !result. is_duplicate( ) ) ; // Not considered duplicate if rejected
360+ assert ! ( result. is_rejected( ) ) ;
361+ }
362+
363+ #[ test]
364+ fn test_process_block_result_equality ( ) {
365+ let result1 = ProcessBlockResult {
366+ accepted : true ,
367+ new_block : true ,
368+ } ;
369+ let result2 = ProcessBlockResult {
370+ accepted : true ,
371+ new_block : true ,
372+ } ;
373+ let result3 = ProcessBlockResult {
374+ accepted : false ,
375+ new_block : false ,
376+ } ;
377+
378+ assert_eq ! ( result1, result2) ;
379+ assert_ne ! ( result1, result3) ;
380+ }
381+
382+ #[ test]
383+ fn test_process_block_result_debug ( ) {
384+ let result = ProcessBlockResult {
385+ accepted : true ,
386+ new_block : true ,
387+ } ;
388+
389+ let debug_str = format ! ( "{:?}" , result) ;
390+ assert ! ( debug_str. contains( "accepted" ) ) ;
391+ assert ! ( debug_str. contains( "new_block" ) ) ;
392+ }
276393}
0 commit comments