@@ -213,6 +213,38 @@ pub(crate) fn getblockstats(ctx: &Arc<Context>, params: &Value) -> Result<Value,
213213 "utxo_size_inc" : 0
214214 } ) )
215215}
216+ pub ( crate ) fn verifychain ( ctx : & Arc < Context > , params : & Value ) -> Result < Value , RpcError > {
217+ let array = params_array ( params) ?;
218+ let _checklevel = array. first ( ) . and_then ( JsonValueTrait :: as_u64) . unwrap_or ( 3 ) ;
219+ let nblocks_param = array. get ( 1 ) . and_then ( JsonValueTrait :: as_u64) . unwrap_or ( 6 ) ;
220+ let Ok ( nblocks) = u32:: try_from ( nblocks_param) else {
221+ return Err ( RpcError :: InvalidParams ( "nblocks exceeds u32" ) ) ;
222+ } ;
223+ let tree = ctx. block_tree . read ( ) ;
224+ let Some ( applied) = ctx. applied_tip . load_full ( ) else {
225+ // No applied tip yet; trivially passes.
226+ return Ok ( json ! ( true ) ) ;
227+ } ;
228+ let mut cursor = applied. tip_id ;
229+ let mut checked: u32 = 0 ;
230+ loop {
231+ if checked >= nblocks {
232+ break ;
233+ }
234+ let Ok ( node) = tree. node ( cursor) else {
235+ return Ok ( json ! ( false ) ) ;
236+ } ;
237+ if node. header . validate_pow ( node. header . target ( ) ) . is_err ( ) {
238+ return Ok ( json ! ( false ) ) ;
239+ }
240+ checked = checked. saturating_add ( 1 ) ;
241+ let Some ( parent_id) = node. parent else {
242+ break ;
243+ } ;
244+ cursor = parent_id;
245+ }
246+ Ok ( json ! ( true ) )
247+ }
216248
217249pub ( crate ) fn gettxoutsetinfo ( ctx : & Arc < Context > , params : & Value ) -> Result < Value , RpcError > {
218250 ensure_no_params ( params) ?;
@@ -766,6 +798,29 @@ mod getchaintips_tests {
766798 }
767799}
768800
801+ #[ cfg( test) ]
802+ mod verifychain_tests {
803+ use alloc:: sync:: Arc ;
804+
805+ use super :: * ;
806+
807+ #[ test]
808+ fn verifychain_returns_true_on_empty_chain ( ) {
809+ let ctx = Arc :: new ( Context :: new ( ) ) ;
810+ let result =
811+ verifychain ( & ctx, & json ! ( [ ] ) ) . unwrap_or_else ( |err| panic ! ( "verifychain failed: {err}" ) ) ;
812+ assert_eq ! ( result. as_bool( ) , Some ( true ) ) ;
813+ }
814+
815+ #[ test]
816+ fn verifychain_accepts_default_params ( ) {
817+ let ctx = Arc :: new ( Context :: new ( ) ) ;
818+ let result = verifychain ( & ctx, & json ! ( [ 3 , 6 ] ) )
819+ . unwrap_or_else ( |err| panic ! ( "verifychain failed: {err}" ) ) ;
820+ assert_eq ! ( result. as_bool( ) , Some ( true ) ) ;
821+ }
822+ }
823+
769824fn compute_branchlen (
770825 tree : & bitcoin_rs_chain:: BlockTree ,
771826 leaf_id : bitcoin_rs_chain:: NodeId ,
0 commit comments