@@ -9,6 +9,7 @@ use std::collections::HashMap;
9
9
use std:: convert:: TryFrom ;
10
10
use std:: io:: { Read , Seek , SeekFrom } ;
11
11
use std:: ops:: DerefMut ;
12
+ use std:: sync:: OnceLock ;
12
13
13
14
/// The bitcoin block and additional metadata returned by the [crate::iter()] method
14
15
#[ derive( Debug , Eq , PartialEq ) ]
@@ -22,7 +23,7 @@ pub struct BlockExtra {
22
23
/// avoiding the performance costs and use visitor directly on the bytes with [`bitcoin_slices`]
23
24
block_bytes : Vec < u8 > ,
24
25
25
- block : Option < Block > ,
26
+ block : OnceLock < Block > ,
26
27
27
28
/// The bitcoin block hash, same as `block.block_hash()` but result from hashing is cached
28
29
pub ( crate ) block_hash : BlockHash ,
@@ -77,7 +78,7 @@ impl TryFrom<FsBlock> for BlockExtra {
77
78
Ok ( BlockExtra {
78
79
version : fs_block. serialization_version ,
79
80
block_bytes,
80
- block : None ,
81
+ block : OnceLock :: new ( ) ,
81
82
block_hash : fs_block. hash ,
82
83
size : ( fs_block. end - fs_block. start ) as u32 ,
83
84
next : fs_block. next ,
@@ -98,13 +99,10 @@ impl BlockExtra {
98
99
99
100
/// Returns the block from the bytes
100
101
///
101
- /// This is an expensive operations, re-use the results instead of calling it multiple times
102
- pub fn block ( & self ) -> Option < & Block > {
103
- self . block . as_ref ( )
104
- }
105
-
106
- pub fn init_block ( & mut self ) {
107
- self . block = Some ( Block :: consensus_decode ( & mut & self . block_bytes [ ..] ) . unwrap ( ) ) ;
102
+ /// This is an expensive operation, re-use the results instead of calling it multiple times
103
+ pub fn block ( & self ) -> & Block {
104
+ self . block
105
+ . get_or_init ( || Block :: consensus_decode ( & mut & self . block_bytes [ ..] ) . unwrap ( ) )
108
106
}
109
107
110
108
pub fn block_bytes ( & self ) -> & [ u8 ] {
@@ -180,9 +178,7 @@ impl BlockExtra {
180
178
///
181
179
/// requires serializing the block bytes, consider using a visitor on the bytes for performance
182
180
pub fn iter_tx ( & self ) -> impl Iterator < Item = ( & Txid , & Transaction ) > {
183
- self . txids
184
- . iter ( )
185
- . zip ( self . block ( ) . expect ( "block not loaded" ) . txdata . iter ( ) )
181
+ self . txids . iter ( ) . zip ( self . block ( ) . txdata . iter ( ) )
186
182
}
187
183
}
188
184
@@ -246,7 +242,7 @@ impl Decodable for BlockExtra {
246
242
let mut b = BlockExtra {
247
243
version,
248
244
block_bytes,
249
- block : None ,
245
+ block : OnceLock :: new ( ) ,
250
246
block_hash,
251
247
size,
252
248
next : Decodable :: consensus_decode ( d) ?,
@@ -325,6 +321,7 @@ pub mod test {
325
321
use bitcoin:: hashes:: Hash ;
326
322
use bitcoin:: { BlockHash , CompactTarget } ;
327
323
use std:: collections:: HashMap ;
324
+ use std:: sync:: OnceLock ;
328
325
329
326
#[ test]
330
327
fn block_extra_round_trip ( ) {
@@ -358,7 +355,7 @@ pub mod test {
358
355
BlockExtra {
359
356
version : 0 ,
360
357
block_bytes,
361
- block : None ,
358
+ block : OnceLock :: new ( ) ,
362
359
block_hash : BlockHash :: all_zeros ( ) ,
363
360
size,
364
361
next : vec ! [ BlockHash :: all_zeros( ) ] ,
0 commit comments