#[doc(hidden)]
pub mod matrix;
#[doc(hidden)]
pub mod xoshiro;
pub mod wasm;
use std::cmp::max;
use crate::matrix::Matrix;
use kaspa_consensus_core::{hashing, header::Header, BlockLevel};
use kaspa_hashes::PowHash;
use kaspa_math::Uint256;
pub struct State {
pub(crate) matrix: Matrix,
pub(crate) target: Uint256,
pub(crate) hasher: PowHash,
}
impl State {
#[inline]
pub fn new(header: &Header) -> Self {
let target = Uint256::from_compact_target_bits(header.bits);
let pre_pow_hash = hashing::header::hash_override_nonce_time(header, 0, 0);
let hasher = PowHash::new(pre_pow_hash, header.timestamp);
let matrix = Matrix::generate(pre_pow_hash);
Self { matrix, target, hasher }
}
#[inline]
#[must_use]
pub fn calculate_pow(&self, nonce: u64) -> Uint256 {
let hash = self.hasher.clone().finalize_with_nonce(nonce);
let hash = self.matrix.heavy_hash(hash);
Uint256::from_le_bytes(hash.as_bytes())
}
#[inline]
#[must_use]
pub fn check_pow(&self, nonce: u64) -> (bool, Uint256) {
let pow = self.calculate_pow(nonce);
(pow <= self.target, pow)
}
}
pub fn calc_block_level(header: &Header, max_block_level: BlockLevel) -> BlockLevel {
if header.parents_by_level.is_empty() {
return max_block_level; }
let state = State::new(header);
let (_, pow) = state.check_pow(header.nonce);
let signed_block_level = max_block_level as i64 - pow.bits() as i64;
max(signed_block_level, 0) as BlockLevel
}