@@ -109,11 +109,13 @@ use std::{
109109} ;
110110
111111use libbitcoinkernel_sys:: {
112- btck_Block, btck_BlockHash, btck_BlockSpentOutputs, btck_Coin, btck_TransactionSpentOutputs,
113- btck_block_copy, btck_block_count_transactions, btck_block_create, btck_block_destroy,
114- btck_block_get_hash, btck_block_get_transaction_at, btck_block_hash_copy,
115- btck_block_hash_create, btck_block_hash_destroy, btck_block_hash_equals,
116- btck_block_hash_to_bytes, btck_block_spent_outputs_copy, btck_block_spent_outputs_count,
112+ btck_Block, btck_BlockHash, btck_BlockHeader, btck_BlockSpentOutputs, btck_Coin,
113+ btck_TransactionSpentOutputs, btck_block_copy, btck_block_count_transactions,
114+ btck_block_create, btck_block_destroy, btck_block_get_hash, btck_block_get_header,
115+ btck_block_get_transaction_at, btck_block_hash_copy, btck_block_hash_create,
116+ btck_block_hash_destroy, btck_block_hash_equals, btck_block_hash_to_bytes,
117+ btck_block_header_copy, btck_block_header_create, btck_block_header_destroy,
118+ btck_block_header_get_hash, btck_block_spent_outputs_copy, btck_block_spent_outputs_count,
117119 btck_block_spent_outputs_destroy, btck_block_spent_outputs_get_transaction_spent_outputs_at,
118120 btck_block_to_bytes, btck_coin_confirmation_height, btck_coin_copy, btck_coin_destroy,
119121 btck_coin_get_output, btck_coin_is_coinbase, btck_transaction_spent_outputs_copy,
@@ -270,6 +272,15 @@ impl AsPtr<btck_BlockHash> for BlockHash {
270272 }
271273}
272274
275+ impl < ' a > FromPtr < btck_BlockHash > for BlockHashRef < ' a > {
276+ unsafe fn from_ptr ( ptr : * const btck_BlockHash ) -> Self {
277+ BlockHashRef {
278+ inner : ptr,
279+ marker : PhantomData ,
280+ }
281+ }
282+ }
283+
273284impl FromMutPtr < btck_BlockHash > for BlockHash {
274285 unsafe fn from_ptr ( ptr : * mut btck_BlockHash ) -> Self {
275286 BlockHash { inner : ptr }
@@ -377,15 +388,6 @@ impl<'a> AsPtr<btck_BlockHash> for BlockHashRef<'a> {
377388 }
378389}
379390
380- impl < ' a > FromPtr < btck_BlockHash > for BlockHashRef < ' a > {
381- unsafe fn from_ptr ( ptr : * const btck_BlockHash ) -> Self {
382- BlockHashRef {
383- inner : ptr,
384- marker : PhantomData ,
385- }
386- }
387- }
388-
389391impl < ' a > BlockHashExt for BlockHashRef < ' a > { }
390392
391393impl < ' a > Clone for BlockHashRef < ' a > {
@@ -420,6 +422,114 @@ impl<'a> Eq for BlockHashRef<'a> {}
420422
421423impl < ' a > Copy for BlockHashRef < ' a > { }
422424
425+ /// Common operations for block headers, implemented by both owned and borrow types.
426+ pub trait BlockHeaderExt : AsPtr < btck_BlockHeader > {
427+ /// Return the block hash of the header.
428+ fn hash ( & self ) -> BlockHash {
429+ unsafe { BlockHash :: from_ptr ( btck_block_header_get_hash ( self . as_ptr ( ) ) ) }
430+ }
431+ }
432+
433+ /// A Bitcoin block header.
434+ ///
435+ /// Block headers can be created from raw serialized data or retrieved from the
436+ /// chain or blocks.
437+ pub struct BlockHeader {
438+ inner : * mut btck_BlockHeader ,
439+ }
440+
441+ unsafe impl Send for BlockHeader { }
442+ unsafe impl Sync for BlockHeader { }
443+
444+ impl BlockHeader {
445+ pub fn new ( header_bytes : & [ u8 ] ) -> Result < Self , KernelError > {
446+ let inner = unsafe {
447+ btck_block_header_create ( header_bytes. as_ptr ( ) as * const c_void , header_bytes. len ( ) )
448+ } ;
449+
450+ if inner. is_null ( ) {
451+ Err ( KernelError :: Internal (
452+ "Failed to create header from bytes" . to_string ( ) ,
453+ ) )
454+ } else {
455+ Ok ( BlockHeader { inner } )
456+ }
457+ }
458+
459+ pub fn as_ref ( & self ) -> BlockHeaderRef < ' _ > {
460+ unsafe { BlockHeaderRef :: from_ptr ( self . inner as * const _ ) }
461+ }
462+ }
463+
464+ impl FromMutPtr < btck_BlockHeader > for BlockHeader {
465+ unsafe fn from_ptr ( ptr : * mut btck_BlockHeader ) -> Self {
466+ BlockHeader { inner : ptr }
467+ }
468+ }
469+
470+ impl AsPtr < btck_BlockHeader > for BlockHeader {
471+ fn as_ptr ( & self ) -> * const btck_BlockHeader {
472+ self . inner as * const _
473+ }
474+ }
475+
476+ impl BlockHeaderExt for BlockHeader { }
477+
478+ impl Clone for BlockHeader {
479+ fn clone ( & self ) -> Self {
480+ BlockHeader {
481+ inner : unsafe { btck_block_header_copy ( self . inner ) } ,
482+ }
483+ }
484+ }
485+
486+ impl Drop for BlockHeader {
487+ fn drop ( & mut self ) {
488+ unsafe { btck_block_header_destroy ( self . inner ) }
489+ }
490+ }
491+
492+ pub struct BlockHeaderRef < ' a > {
493+ inner : * const btck_BlockHeader ,
494+ marker : PhantomData < & ' a ( ) > ,
495+ }
496+
497+ unsafe impl < ' a > Send for BlockHeaderRef < ' a > { }
498+ unsafe impl < ' a > Sync for BlockHeaderRef < ' a > { }
499+
500+ impl < ' a > BlockHeaderRef < ' a > {
501+ pub fn to_owned ( & self ) -> BlockHeader {
502+ BlockHeader {
503+ inner : unsafe { btck_block_header_copy ( self . inner ) } ,
504+ }
505+ }
506+ }
507+
508+ impl < ' a > AsPtr < btck_BlockHeader > for BlockHeaderRef < ' a > {
509+ fn as_ptr ( & self ) -> * const btck_BlockHeader {
510+ self . inner
511+ }
512+ }
513+
514+ impl < ' a > FromPtr < btck_BlockHeader > for BlockHeaderRef < ' a > {
515+ unsafe fn from_ptr ( ptr : * const btck_BlockHeader ) -> Self {
516+ BlockHeaderRef {
517+ inner : ptr,
518+ marker : PhantomData ,
519+ }
520+ }
521+ }
522+
523+ impl < ' a > BlockHeaderExt for BlockHeaderRef < ' a > { }
524+
525+ impl < ' a > Copy for BlockHeaderRef < ' a > { }
526+
527+ impl < ' a > Clone for BlockHeaderRef < ' a > {
528+ fn clone ( & self ) -> Self {
529+ * self
530+ }
531+ }
532+
423533/// A block containing a header and transactions.
424534///
425535/// Blocks are the fundamental units of the block chain, linking together
@@ -542,6 +652,10 @@ impl Block {
542652 unsafe { btck_block_count_transactions ( self . inner ) }
543653 }
544654
655+ pub fn header ( & self ) -> BlockHeader {
656+ unsafe { BlockHeader :: from_ptr ( btck_block_get_header ( self . inner ) ) }
657+ }
658+
545659 /// Returns a reference to the transaction at the specified index.
546660 ///
547661 /// # Arguments
@@ -1574,6 +1688,23 @@ mod tests {
15741688
15751689 test_owned_trait_requirements ! ( test_block_requirements, Block , btck_Block) ;
15761690
1691+ test_owned_trait_requirements ! (
1692+ test_block_header_requirements,
1693+ BlockHeader ,
1694+ btck_BlockHeader
1695+ ) ;
1696+ test_ref_trait_requirements ! (
1697+ test_block_header_ref_requirements,
1698+ BlockHeaderRef <' static >,
1699+ btck_BlockHeader
1700+ ) ;
1701+
1702+ test_owned_clone_and_send ! (
1703+ test_block_header_clone_send,
1704+ Block :: new( & read_block_data( ) [ 0 ] ) . unwrap( ) . header( ) ,
1705+ Block :: new( & read_block_data( ) [ 1 ] ) . unwrap( )
1706+ ) ;
1707+
15771708 test_owned_trait_requirements ! (
15781709 test_block_spent_outputs_requirements,
15791710 BlockSpentOutputs ,
0 commit comments