11#![ no_main]
22
3- use std:: sync:: { Arc , Once } ;
3+ use std:: sync:: Arc ;
44
55use libfuzzer_sys:: fuzz_target;
66
77use arbitrary:: Arbitrary ;
88
99use bitcoinkernel:: {
10- disable_logging,
1110 notifications:: types:: { BlockValidationStateExt , BlockValidationStateRef } ,
12- Block , ChainType , ChainstateManager , ChainstateManagerOptions , Context , ContextBuilder ,
13- KernelError , ValidationMode ,
11+ Block , ChainType , Context , ContextBuilder , ValidationMode ,
1412} ;
13+ use fuzz_common:: { cleanup_dir, create_chainstate_manager, init_logging, ChainstateSetupConfig } ;
1514
16- fn create_context ( chain_type : ChainType ) -> Arc < Context > {
15+ pub fn create_context_with_notifications ( chain_type : ChainType ) -> std :: sync :: Arc < Context > {
1716 Arc :: new (
1817 ContextBuilder :: new ( )
1918 . chain_type ( chain_type)
@@ -32,85 +31,32 @@ fn create_context(chain_type: ChainType) -> Arc<Context> {
3231 )
3332}
3433
35- #[ derive( Debug , Arbitrary ) ]
36- pub enum FuzzChainType {
37- MAINNET ,
38- TESTNET ,
39- REGTEST ,
40- SIGNET ,
41- }
42-
43- impl Into < ChainType > for FuzzChainType {
44- fn into ( self ) -> ChainType {
45- match self {
46- FuzzChainType :: MAINNET => ChainType :: Mainnet ,
47- FuzzChainType :: TESTNET => ChainType :: Testnet ,
48- FuzzChainType :: REGTEST => ChainType :: Regtest ,
49- FuzzChainType :: SIGNET => ChainType :: Signet ,
50- }
51- }
52- }
53-
5434#[ derive( Debug , Arbitrary ) ]
5535pub struct ChainstateManagerInput {
56- pub data_dir : String ,
57- pub chain_type : FuzzChainType ,
36+ pub setup : ChainstateSetupConfig ,
5837 pub blocks : Vec < Vec < u8 > > ,
59- pub wipe_block_index : bool ,
60- pub wipe_chainstate_index : bool ,
61- pub block_tree_db_in_memory : bool ,
62- pub chainstate_db_in_memory : bool ,
63- pub worker_threads : i32 ,
6438}
6539
66- static INIT : Once = Once :: new ( ) ;
67-
6840fuzz_target ! ( |data: ChainstateManagerInput | {
69- INIT . call_once( || {
70- disable_logging( ) ;
71- } ) ;
72-
73- let context = create_context( data. chain_type. into( ) ) ;
74- // Sanitize the input string by removing dots and slashes
75- let sanitized_string: String = data
76- . data_dir
77- . chars( )
78- . filter( |c| * c != '.' && * c != '/' )
79- . take( 60 )
80- . collect( ) ;
41+ init_logging( ) ;
42+ let context = create_context_with_notifications( data. setup. chain_type. clone( ) . into( ) ) ;
43+ let data_dir = data. setup. create_fuzz_data_dir( "chainstate" ) ;
8144
82- let data_dir = format!( "/tmp/rust_kernel_fuzz/{}" , sanitized_string) ;
83- let blocks_dir = format!( "{}/blocks" , data_dir) ;
84- let chainman_opts = match ChainstateManagerOptions :: new( & context, & data_dir, & blocks_dir) {
85- Ok ( opts) => opts,
86- Err ( KernelError :: CStringCreationFailed ( _) ) => return ,
87- Err ( err) => panic!( "this should never happen: {}" , err) ,
88- }
89- . wipe_db( data. wipe_block_index, data. wipe_chainstate_index)
90- . block_tree_db_in_memory( data. block_tree_db_in_memory)
91- . chainstate_db_in_memory( data. chainstate_db_in_memory)
92- . worker_threads( data. worker_threads) ;
93- let chainman = match ChainstateManager :: new( chainman_opts) {
94- Err ( KernelError :: Internal ( _) ) => {
95- return ;
96- }
97- Err ( err) => {
98- let _ = std:: fs:: remove_dir_all( data_dir) ;
99- panic!( "this should never happen: {}" , err) ;
100- }
101- Ok ( chainman) => chainman,
45+ let Some ( chainman) = create_chainstate_manager( & context, & data. setup, & data_dir) else {
46+ return ;
10247 } ;
10348
104- if let Err ( err ) = chainman. import_blocks( ) {
105- let _ = std :: fs :: remove_dir_all ( data_dir) ;
106- panic! ( "this should never happen: {}" , err ) ;
49+ if chainman. import_blocks( ) . is_err ( ) {
50+ cleanup_dir ( & data_dir) ;
51+ return ;
10752 }
10853
109- for block in data . blocks {
110- if let Ok ( block) = Block :: try_from( block . as_slice( ) ) {
54+ for block_data in blocks {
55+ if let Ok ( block) = Block :: try_from( block_data . as_slice( ) ) {
11156 let _ = chainman. process_block( & block) ;
11257 }
11358 }
59+
11460 drop( chainman) ;
115- let _ = std :: fs :: remove_dir_all ( data_dir) ;
61+ cleanup_dir ( & data_dir) ;
11662} ) ;
0 commit comments