use super::{check_proof_of_work, ChainWork, CompactTarget, PowError};
use crate::primitives::{from_hex, sha256d, Hash32, Reader, Writer, U256};
use crate::{Error, Result};
pub const HEADER_SIZE: usize = 80;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BlockHeader {
pub version: i32,
pub prev_hash: Hash32,
pub merkle_root: Hash32,
pub time: u32,
pub bits: u32,
pub nonce: u32,
}
impl BlockHeader {
pub fn from_binary(bytes: &[u8]) -> Result<Self> {
if bytes.len() != HEADER_SIZE {
return Err(Error::InvalidDataLength {
expected: HEADER_SIZE,
actual: bytes.len(),
});
}
Self::from_reader(&mut Reader::new(bytes))
}
pub fn from_hex(hex: &str) -> Result<Self> {
Self::from_binary(&from_hex(hex)?)
}
pub fn from_reader(reader: &mut Reader<'_>) -> Result<Self> {
let bytes = reader.read_bytes(HEADER_SIZE)?;
Ok(Self {
version: i32::from_le_bytes(bytes[..4].try_into().expect("four bytes")),
prev_hash: bytes[4..36].try_into().expect("32 bytes"),
merkle_root: bytes[36..68].try_into().expect("32 bytes"),
time: u32::from_le_bytes(bytes[68..72].try_into().expect("four bytes")),
bits: u32::from_le_bytes(bytes[72..76].try_into().expect("four bytes")),
nonce: u32::from_le_bytes(bytes[76..80].try_into().expect("four bytes")),
})
}
pub fn to_binary(&self) -> [u8; HEADER_SIZE] {
let mut bytes = [0; HEADER_SIZE];
bytes[..4].copy_from_slice(&self.version.to_le_bytes());
bytes[4..36].copy_from_slice(&self.prev_hash);
bytes[36..68].copy_from_slice(&self.merkle_root);
bytes[68..72].copy_from_slice(&self.time.to_le_bytes());
bytes[72..76].copy_from_slice(&self.bits.to_le_bytes());
bytes[76..80].copy_from_slice(&self.nonce.to_le_bytes());
bytes
}
pub fn to_hex(&self) -> String {
hex::encode(self.to_binary())
}
pub fn to_writer(&self, writer: &mut Writer) {
writer.write_bytes(&self.to_binary());
}
pub fn hash(&self) -> Hash32 {
sha256d(&self.to_binary())
}
pub fn id(&self) -> String {
self.hash_number().to_hex()
}
pub fn hash_number(&self) -> U256 {
U256::from_le_bytes(self.hash())
}
pub fn target(&self) -> CompactTarget {
CompactTarget::from_bits(self.bits)
}
pub fn work(&self) -> ChainWork {
ChainWork::from_bits(self.bits)
}
pub fn check_proof_of_work(&self, pow_limit: &U256) -> std::result::Result<(), PowError> {
check_proof_of_work(&self.hash(), self.bits, pow_limit)
}
pub fn prev_id(&self) -> String {
U256::from_le_bytes(self.prev_hash).to_hex()
}
pub fn merkle_root_hex(&self) -> String {
U256::from_le_bytes(self.merkle_root).to_hex()
}
}