File tree Expand file tree Collapse file tree 11 files changed +109
-1
lines changed Expand file tree Collapse file tree 11 files changed +109
-1
lines changed Original file line number Diff line number Diff line change @@ -43,6 +43,14 @@ impl Callback for Balances {
43
43
Ok ( ( ) )
44
44
}
45
45
46
+ fn on_header (
47
+ & mut self ,
48
+ _header : & bitcoin:: blockdata:: block:: Header ,
49
+ _block_height : u64 ,
50
+ ) -> anyhow:: Result < ( ) > {
51
+ Ok ( ( ) )
52
+ }
53
+
46
54
/// For each transaction in the block
47
55
/// 1. apply input transactions (remove (TxID == prevTxIDOut and prevOutID == spentOutID))
48
56
/// 2. apply output transactions (add (TxID + curOutID -> HashMapVal))
Original file line number Diff line number Diff line change @@ -17,6 +17,13 @@ pub trait Callback {
17
17
/// Gets called shortly before the blocks are parsed.
18
18
fn on_start ( & mut self , block_height : u64 ) -> anyhow:: Result < ( ) > ;
19
19
20
+ /// Gets called if a new header is available.
21
+ fn on_header (
22
+ & mut self ,
23
+ _header : & bitcoin:: blockdata:: block:: Header ,
24
+ _block_height : u64 ,
25
+ ) -> anyhow:: Result < ( ) > ;
26
+
20
27
/// Gets called if a new block is available.
21
28
fn on_block ( & mut self , block : & bitcoin:: Block , block_height : u64 ) -> anyhow:: Result < ( ) > ;
22
29
Original file line number Diff line number Diff line change @@ -18,6 +18,14 @@ impl Callback for OpReturn {
18
18
Ok ( ( ) )
19
19
}
20
20
21
+ fn on_header (
22
+ & mut self ,
23
+ _header : & bitcoin:: blockdata:: block:: Header ,
24
+ _block_height : u64 ,
25
+ ) -> anyhow:: Result < ( ) > {
26
+ Ok ( ( ) )
27
+ }
28
+
21
29
fn on_block ( & mut self , block : & bitcoin:: Block , block_height : u64 ) -> anyhow:: Result < ( ) > {
22
30
for tx in & block. txdata {
23
31
for out in & tx. output {
Original file line number Diff line number Diff line change @@ -186,6 +186,14 @@ impl Callback for SimpleStats {
186
186
Ok ( ( ) )
187
187
}
188
188
189
+ fn on_header (
190
+ & mut self ,
191
+ _header : & bitcoin:: blockdata:: block:: Header ,
192
+ _block_height : u64 ,
193
+ ) -> anyhow:: Result < ( ) > {
194
+ Ok ( ( ) )
195
+ }
196
+
189
197
fn on_block ( & mut self , block : & bitcoin:: Block , block_height : u64 ) -> anyhow:: Result < ( ) > {
190
198
self . n_valid_blocks += 1 ;
191
199
self . n_tx += block. txdata . len ( ) ;
Original file line number Diff line number Diff line change @@ -45,6 +45,14 @@ impl crate::callbacks::Callback for UnspentCsvDump {
45
45
Ok ( ( ) )
46
46
}
47
47
48
+ fn on_header (
49
+ & mut self ,
50
+ _header : & bitcoin:: blockdata:: block:: Header ,
51
+ _block_height : u64 ,
52
+ ) -> anyhow:: Result < ( ) > {
53
+ Ok ( ( ) )
54
+ }
55
+
48
56
/// For each transaction in the block
49
57
/// 1. apply input transactions (remove (TxID == prevTxIDOut and prevOutID == spentOutID))
50
58
/// 2. apply output transactions (add (TxID + curOutID -> HashMapVal))
Original file line number Diff line number Diff line change @@ -41,6 +41,15 @@ impl BlkFile {
41
41
}
42
42
}
43
43
44
+ pub fn read_header (
45
+ & mut self ,
46
+ offset : u64 ,
47
+ ) -> anyhow:: Result < bitcoin:: blockdata:: block:: Header > {
48
+ let reader = self . open ( ) ?;
49
+ reader. seek ( SeekFrom :: Start ( offset) ) ?;
50
+ reader. read_header ( )
51
+ }
52
+
44
53
pub fn read_block ( & mut self , offset : u64 ) -> anyhow:: Result < bitcoin:: Block > {
45
54
let reader = self . open ( ) ?;
46
55
reader. seek ( SeekFrom :: Start ( offset) ) ?;
Original file line number Diff line number Diff line change @@ -21,6 +21,21 @@ impl ChainStorage {
21
21
} )
22
22
}
23
23
24
+ /// Returns the header of a given height.
25
+ #[ must_use]
26
+ pub fn get_header ( & mut self , height : u64 ) -> Option < bitcoin:: blockdata:: block:: Header > {
27
+ // Read block
28
+ let block_meta = self . chain_index . get ( height) ?;
29
+ let blk_file = self . blk_files . get_mut ( & block_meta. blk_index ) ?;
30
+ let header = blk_file. read_header ( block_meta. data_offset ) . ok ( ) ?;
31
+
32
+ // Check if blk file can be closed
33
+ if height == self . chain_index . max_height_by_blk ( block_meta. blk_index ) {
34
+ blk_file. close ( ) ;
35
+ }
36
+ Some ( header)
37
+ }
38
+
24
39
/// Returns the block of a given height.
25
40
#[ must_use]
26
41
pub fn get_block ( & mut self , height : u64 ) -> Option < bitcoin:: Block > {
Original file line number Diff line number Diff line change @@ -53,7 +53,9 @@ impl BlockchainParser {
53
53
tracing:: debug!( target: "parser" , "Starting worker ..." ) ;
54
54
55
55
self . on_start ( self . cur_height ) ?;
56
- while let Some ( block) = self . chain_storage . get_block ( self . cur_height ) {
56
+ while let Some ( header) = self . chain_storage . get_header ( self . cur_height ) {
57
+ self . on_header ( & header, self . cur_height ) ?;
58
+ let block = self . chain_storage . get_block ( self . cur_height ) . unwrap ( ) ;
57
59
self . on_block ( & block, self . cur_height ) ?;
58
60
self . cur_height += 1 ;
59
61
}
@@ -79,6 +81,17 @@ impl BlockchainParser {
79
81
Ok ( ( ) )
80
82
}
81
83
84
+ /// Triggers the on_block() callback and updates statistics.
85
+ fn on_header (
86
+ & mut self ,
87
+ header : & bitcoin:: blockdata:: block:: Header ,
88
+ height : u64 ,
89
+ ) -> anyhow:: Result < ( ) > {
90
+ self . callback . on_header ( header, height) ?;
91
+ tracing:: trace!( target: "parser" , "on_header(height={}) called" , height) ;
92
+ Ok ( ( ) )
93
+ }
94
+
82
95
/// Triggers the on_block() callback and updates statistics.
83
96
fn on_block ( & mut self , block : & bitcoin:: Block , height : u64 ) -> anyhow:: Result < ( ) > {
84
97
self . callback . on_block ( block, height) ?;
Original file line number Diff line number Diff line change @@ -6,6 +6,11 @@ pub trait BlockchainRead: std::io::Read {
6
6
fn read_block ( & mut self ) -> anyhow:: Result < bitcoin:: Block > {
7
7
Ok ( bitcoin:: Block :: consensus_decode ( self ) . unwrap ( ) )
8
8
}
9
+
10
+ /// Reads a block as specified here: https://en.bitcoin.it/wiki/Protocol_specification#block
11
+ fn read_header ( & mut self ) -> anyhow:: Result < bitcoin:: blockdata:: block:: Header > {
12
+ Ok ( bitcoin:: blockdata:: block:: Header :: consensus_decode ( self ) . unwrap ( ) )
13
+ }
9
14
}
10
15
11
16
/// All types that implement `Read` get methods defined in `BlockchainRead`
Original file line number Diff line number Diff line change @@ -79,6 +79,16 @@ fn test_bitcoin_genesis() {
79
79
assert_eq ! ( 0x0000_0000 , genesis. txdata[ 0 ] . lock_time. to_consensus_u32( ) ) ;
80
80
}
81
81
82
+ #[ test]
83
+ fn test_genesis_header ( ) {
84
+ let header = STORAGE . lock ( ) . unwrap ( ) . get_header ( 0 ) . unwrap ( ) ;
85
+ assert_eq ! (
86
+ header,
87
+ bitcoin:: blockdata:: constants:: genesis_block( bitcoin:: network:: constants:: Network :: Bitcoin )
88
+ . header
89
+ ) ;
90
+ }
91
+
82
92
#[ test]
83
93
fn test_blockdata_parsing ( ) {
84
94
for height in 0 ..=169 {
@@ -97,3 +107,10 @@ fn test_blockdata_parsing() {
97
107
40 * bitcoin:: Amount :: ONE_BTC . to_sat( )
98
108
) ;
99
109
}
110
+
111
+ #[ test]
112
+ fn test_timing ( ) {
113
+ for height in 0 ..=169 {
114
+ STORAGE . lock ( ) . unwrap ( ) . get_header ( height) . unwrap ( ) ;
115
+ }
116
+ }
You can’t perform that action at this time.
0 commit comments