@@ -69,7 +69,7 @@ struct BlockValue {
6969    #[ cfg( not( feature = "liquid" ) ) ]  
7070    bits :  u32 , 
7171    #[ cfg( not( feature = "liquid" ) ) ]  
72-     difficulty :  u64 , 
72+     difficulty :  f64 , 
7373
7474    #[ cfg( feature = "liquid" ) ]  
7575    #[ serde( skip_serializing_if = "Option::is_none" ) ]  
@@ -78,7 +78,7 @@ struct BlockValue {
7878
7979impl  BlockValue  { 
8080    #[ cfg_attr( feature = "liquid" ,  allow( unused_variables) ) ]  
81-     fn  new ( blockhm :  BlockHeaderMeta ,   network :   Network )  -> Self  { 
81+     fn  new ( blockhm :  BlockHeaderMeta )  -> Self  { 
8282        let  header = blockhm. header_entry . header ( ) ; 
8383        BlockValue  { 
8484            id :  header. block_hash ( ) . to_hex ( ) , 
@@ -106,14 +106,35 @@ impl BlockValue {
106106            #[ cfg( not( feature = "liquid" ) ) ]  
107107            nonce :  header. nonce , 
108108            #[ cfg( not( feature = "liquid" ) ) ]  
109-             difficulty :  header . difficulty ( bitcoin :: Network :: from ( network ) ) , 
109+             difficulty :  difficulty_new ( header ) , 
110110
111111            #[ cfg( feature = "liquid" ) ]  
112112            ext :  Some ( json ! ( header. ext) ) , 
113113        } 
114114    } 
115115} 
116116
117+ /// Calculate the difficulty of a BlockHeader 
118+ /// using Bitcoin Core code ported to Rust. 
119+ /// 
120+ /// https://github.com/bitcoin/bitcoin/blob/v25.0/src/rpc/blockchain.cpp#L75-L97 
121+ #[ cfg_attr( feature = "liquid" ,  allow( dead_code) ) ]  
122+ fn  difficulty_new ( bh :  & bitcoin:: BlockHeader )  -> f64  { 
123+     let  mut  n_shift = bh. bits  >> 24  &  0xff ; 
124+     let  mut  d_diff = ( 0x0000ffff  as  f64 )  / ( ( bh. bits  &  0x00ffffff )  as  f64 ) ; 
125+ 
126+     while  n_shift < 29  { 
127+         d_diff *= 256.0 ; 
128+         n_shift += 1 ; 
129+     } 
130+     while  n_shift > 29  { 
131+         d_diff /= 256.0 ; 
132+         n_shift -= 1 ; 
133+     } 
134+ 
135+     d_diff
136+ } 
137+ 
117138#[ derive( Serialize ,  Deserialize ) ]  
118139struct  TransactionValue  { 
119140    txid :  Txid , 
@@ -681,7 +702,7 @@ fn handle_request(
681702                . chain ( ) 
682703                . get_block_with_meta ( & hash) 
683704                . ok_or_else ( || HttpError :: not_found ( "Block not found" . to_string ( ) ) ) ?; 
684-             let  block_value = BlockValue :: new ( blockhm,  config . network_type ) ; 
705+             let  block_value = BlockValue :: new ( blockhm) ; 
685706            json_response ( block_value,  TTL_LONG ) 
686707        } 
687708        ( & Method :: GET ,  Some ( & "block" ) ,  Some ( hash) ,  Some ( & "status" ) ,  None ,  None )  => { 
@@ -1325,7 +1346,7 @@ fn blocks(
13251346        current_hash = blockhm. header_entry . header ( ) . prev_blockhash ; 
13261347
13271348        #[ allow( unused_mut) ]  
1328-         let  mut  value = BlockValue :: new ( blockhm,  config . network_type ) ; 
1349+         let  mut  value = BlockValue :: new ( blockhm) ; 
13291350
13301351        #[ cfg( feature = "liquid" ) ]  
13311352        { 
@@ -1533,4 +1554,128 @@ mod tests {
15331554
15341555        assert ! ( err. is_err( ) ) ; 
15351556    } 
1557+ 
1558+     #[ test]  
1559+     fn  test_difficulty_new ( )  { 
1560+         use  super :: difficulty_new; 
1561+ 
1562+         let  vectors = [ 
1563+             ( 
1564+                 // bits in header 
1565+                 0x17053894 , 
1566+                 // expected output (Rust) 
1567+                 53911173001054.586 , 
1568+                 // Block hash where found (for getblockheader) 
1569+                 "0000000000000000000050b050758dd2ccb0ba96ad5e95db84efd2f6c05e4e90" , 
1570+                 // difficulty returned by Bitcoin Core v25 
1571+                 "53911173001054.59" , 
1572+             ) , 
1573+             ( 
1574+                 0x1a0c2a12 , 
1575+                 1379192.2882280778 , 
1576+                 "0000000000000bc7636ffbc1cf90cf4a2674de7fcadbc6c9b63d31f07cb3c2c2" , 
1577+                 "1379192.288228078" , 
1578+             ) , 
1579+             ( 
1580+                 0x19262222 , 
1581+                 112628548.66634709 , 
1582+                 "000000000000000996b1f06771a81bcf7b15c5f859b6f8329016f01b0442ca72" , 
1583+                 "112628548.6663471" , 
1584+             ) , 
1585+             ( 
1586+                 0x1d00c428 , 
1587+                 1.3050621315915245 , 
1588+                 "0000000034014d731a3e1ad6078662ce19b08179dcc7ec0f5f717d4b58060736" , 
1589+                 "1.305062131591525" , 
1590+             ) , 
1591+             ( 
1592+                 0 , 
1593+                 f64:: INFINITY , 
1594+                 "[No Blockhash]" , 
1595+                 "[No Core difficulty, just checking edge cases]" , 
1596+             ) , 
1597+             ( 
1598+                 0x00000001 , 
1599+                 4.523059468369196e74 , 
1600+                 "[No Blockhash]" , 
1601+                 "[No Core difficulty, just checking edge cases]" , 
1602+             ) , 
1603+             ( 
1604+                 0x1d00ffff , 
1605+                 1.0 , 
1606+                 "[No Blockhash]" , 
1607+                 "[No Core difficulty, just checking MAX_TARGET]" , 
1608+             ) , 
1609+             ( 
1610+                 0x1c7fff80 , 
1611+                 2.0 , 
1612+                 "[No Blockhash]" , 
1613+                 "[No Core difficulty, just checking MAX_TARGET >> 1]" , 
1614+             ) , 
1615+             ( 
1616+                 0x1b00ffff , 
1617+                 65536.0 , 
1618+                 "[No Blockhash]" , 
1619+                 "[No Core difficulty, just checking MAX_TARGET >> 16]" , 
1620+             ) , 
1621+             ( 
1622+                 0x1a7fff80 , 
1623+                 131072.0 , 
1624+                 "[No Blockhash]" , 
1625+                 "[No Core difficulty, just checking MAX_TARGET >> 17]" , 
1626+             ) , 
1627+             ( 
1628+                 0x1d01fffe , 
1629+                 0.5 , 
1630+                 "[No Blockhash]" , 
1631+                 "[No Core difficulty, just checking MAX_TARGET << 1]" , 
1632+             ) , 
1633+             ( 
1634+                 0x1f000080 , 
1635+                 0.007812380790710449 , 
1636+                 "[No Blockhash]" , 
1637+                 "[No Core difficulty, just checking 2**255]" , 
1638+             ) , 
1639+             ( 
1640+                 0x1e00ffff , 
1641+                 0.00390625 ,  // 2.0**-8 
1642+                 "[No Blockhash]" , 
1643+                 "[No Core difficulty, just checking MAX_TARGET << 8]" , 
1644+             ) , 
1645+             ( 
1646+                 0x1e00ff00 , 
1647+                 0.0039215087890625 , 
1648+                 "[No Blockhash]" , 
1649+                 "[No Core difficulty, just checking MAX_TARGET << 8 - two `f` chars]" , 
1650+             ) , 
1651+             ( 
1652+                 0x1f0000ff , 
1653+                 0.0039215087890625 , 
1654+                 "[No Blockhash]" , 
1655+                 "[No Core difficulty, just checking MAX_TARGET << 8]" , 
1656+             ) , 
1657+         ] ; 
1658+ 
1659+         let  to_bh = |b| bitcoin:: BlockHeader  { 
1660+             version :  1 , 
1661+             prev_blockhash :  "0000000000000000000000000000000000000000000000000000000000000000" 
1662+                 . parse ( ) 
1663+                 . unwrap ( ) , 
1664+             merkle_root :  "0000000000000000000000000000000000000000000000000000000000000000" 
1665+                 . parse ( ) 
1666+                 . unwrap ( ) , 
1667+             time :  0 , 
1668+             bits :  b, 
1669+             nonce :  0 , 
1670+         } ; 
1671+ 
1672+         for  ( bits,  expected,  hash,  core_difficulty)  in  vectors { 
1673+             let  result = difficulty_new ( & to_bh ( bits) ) ; 
1674+             assert_eq ! ( 
1675+                 result,  expected, 
1676+                 "Block {} difficulty is {} but Core difficulty is {}" , 
1677+                 hash,  result,  core_difficulty, 
1678+             ) ; 
1679+         } 
1680+     } 
15361681} 
0 commit comments