use crate::hash::sha256d;
use crate::signet::{self, BLOCK_DATA_LEN};
use crate::{BlockHash, Error, HeaderFamily, Target, VERSION_HEADER_V2_FLAG};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StockHeader {
pub version: u32,
pub prev_block_hash: BlockHash,
pub merkle_root: [u8; 32],
pub time: u32,
pub bits: u32,
pub nonce: u32,
}
impl StockHeader {
pub const WIRE_SIZE: usize = 80;
pub fn decode(bytes: &[u8]) -> Result<Self, Error> {
if bytes.len() != Self::WIRE_SIZE {
return Err(Error::WrongLength {
family: HeaderFamily::Stock,
expected: Self::WIRE_SIZE,
actual: bytes.len(),
});
}
let version = u32_at(bytes, 0);
if version & VERSION_HEADER_V2_FLAG != 0 {
return Err(Error::VersionBit31Set);
}
Ok(StockHeader {
version,
prev_block_hash: BlockHash::from_wire(arr32(bytes, 4)),
merkle_root: arr32(bytes, 36),
time: u32_at(bytes, 68),
bits: u32_at(bytes, 72),
nonce: u32_at(bytes, 76),
})
}
pub fn encode(&self) -> [u8; 80] {
let mut out = [0u8; 80];
out[..72].copy_from_slice(&self.signet_preimage(self.merkle_root));
out[72..76].copy_from_slice(&self.bits.to_le_bytes());
out[76..].copy_from_slice(&self.nonce.to_le_bytes());
out
}
pub fn hash(&self) -> BlockHash {
BlockHash::from_wire(sha256d(&self.encode()))
}
pub fn target(&self) -> Result<Target, Error> {
Target::from_compact(self.bits)
}
pub fn meets_target(&self) -> bool {
self.target().is_ok_and(|t| self.hash().meets(&t))
}
pub fn check_pow(&self, pow_limit: &Target) -> Result<(), Error> {
crate::check_pow(self.bits, self.hash(), pow_limit)
}
pub fn signet_preimage(&self, stripped_merkle_root: [u8; 32]) -> [u8; BLOCK_DATA_LEN] {
let mut out = [0u8; BLOCK_DATA_LEN];
out[..4].copy_from_slice(&self.version.to_le_bytes());
out[4..36].copy_from_slice(&self.prev_block_hash.to_wire());
out[36..68].copy_from_slice(&stripped_merkle_root);
out[68..].copy_from_slice(&self.time.to_le_bytes());
out
}
pub fn block_data(&self, stripped_merkle_root: [u8; 32]) -> [u8; 32] {
signet::block_data(&self.signet_preimage(stripped_merkle_root))
}
}
pub(crate) fn u32_at(b: &[u8], at: usize) -> u32 {
u32::from_le_bytes([b[at], b[at + 1], b[at + 2], b[at + 3]])
}
pub(crate) fn u16_at(b: &[u8], at: usize) -> u16 {
u16::from_le_bytes([b[at], b[at + 1]])
}
pub(crate) fn arr32(b: &[u8], at: usize) -> [u8; 32] {
let mut out = [0u8; 32];
out.copy_from_slice(&b[at..at + 32]);
out
}
pub(crate) fn arr16(b: &[u8], at: usize) -> [u8; 16] {
let mut out = [0u8; 16];
out.copy_from_slice(&b[at..at + 16]);
out
}