From e1896dbb58a6ac654650146604f82257fcef2be2 Mon Sep 17 00:00:00 2001 From: xdustinface Date: Mon, 29 Dec 2025 17:55:21 +0100 Subject: [PATCH] fix: avoid X11 hash with wrong input size in tests The thread sanitizer in #253 found the issues fixed in here. X11 hash requires exactly 80 bytes (block header size). The tests adjusted in this PR were incorrectly passing small data leading to out of bounds memory reads. Now they just use `test_block_hash` helper to pass a mock hash. --- dash-spv/Cargo.toml | 1 + dash-spv/src/chain/chainlock_test.rs | 14 ++++++-------- dash-spv/src/chain/checkpoint_test.rs | 15 ++++++++------- test-utils/src/fixtures.rs | 7 +++++++ 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/dash-spv/Cargo.toml b/dash-spv/Cargo.toml index 7af44f2fe..5d6851de3 100644 --- a/dash-spv/Cargo.toml +++ b/dash-spv/Cargo.toml @@ -65,6 +65,7 @@ tokio-test = "0.4" env_logger = "0.10" hex = "0.4" test-case = "3.3" +dashcore-test-utils = { path = "../test-utils" } [[bench]] name = "storage" diff --git a/dash-spv/src/chain/chainlock_test.rs b/dash-spv/src/chain/chainlock_test.rs index c216ba542..2e840d743 100644 --- a/dash-spv/src/chain/chainlock_test.rs +++ b/dash-spv/src/chain/chainlock_test.rs @@ -2,8 +2,8 @@ mod tests { use super::super::*; use crate::{storage::DiskStorageManager, types::ChainState}; - use dashcore::{BlockHash, ChainLock, Network}; - use dashcore_hashes::Hash; + use dashcore::{ChainLock, Network}; + use dashcore_test_utils::fixtures::test_block_hash; #[tokio::test] async fn test_chainlock_processing() { @@ -16,7 +16,7 @@ mod tests { // Create a test ChainLock let chainlock = ChainLock { block_height: 1000, - block_hash: BlockHash::from_raw_hash(dashcore_hashes::hash_x11::Hash::hash(&[1, 2, 3])), + block_hash: test_block_hash(1), signature: dashcore::bls_sig_utils::BLSSignature::from([0; 96]), }; @@ -49,7 +49,7 @@ mod tests { // Process first ChainLock at height 1000 let chainlock1 = ChainLock { block_height: 1000, - block_hash: BlockHash::from_raw_hash(dashcore_hashes::hash_x11::Hash::hash(&[1, 2, 3])), + block_hash: test_block_hash(1), signature: dashcore::bls_sig_utils::BLSSignature::from([0; 96]), }; chainlock_manager @@ -60,7 +60,7 @@ mod tests { // Process second ChainLock at height 2000 let chainlock2 = ChainLock { block_height: 2000, - block_hash: BlockHash::from_raw_hash(dashcore_hashes::hash_x11::Hash::hash(&[4, 5, 6])), + block_hash: test_block_hash(2), signature: dashcore::bls_sig_utils::BLSSignature::from([1; 96]), }; chainlock_manager @@ -88,9 +88,7 @@ mod tests { for height in [1000, 2000, 3000] { let chainlock = ChainLock { block_height: height, - block_hash: BlockHash::from_raw_hash(dashcore_hashes::hash_x11::Hash::hash( - &height.to_le_bytes(), - )), + block_hash: test_block_hash(height), signature: dashcore::bls_sig_utils::BLSSignature::from([0; 96]), }; chainlock_manager diff --git a/dash-spv/src/chain/checkpoint_test.rs b/dash-spv/src/chain/checkpoint_test.rs index 0218a04b6..bdc96746f 100644 --- a/dash-spv/src/chain/checkpoint_test.rs +++ b/dash-spv/src/chain/checkpoint_test.rs @@ -5,22 +5,23 @@ mod tests { use super::super::checkpoints::*; use dashcore::{BlockHash, CompactTarget, Target}; use dashcore_hashes::Hash; + use dashcore_test_utils::fixtures::test_block_hash; fn create_test_checkpoint(height: u32, timestamp: u32) -> Checkpoint { - let hash_bytes = dashcore_hashes::hash_x11::Hash::hash(&height.to_le_bytes()); - let prev_bytes = if height > 0 { - dashcore_hashes::hash_x11::Hash::hash(&(height - 1).to_le_bytes()) + let block_hash = test_block_hash(height); + let prev_blockhash = if height > 0 { + test_block_hash(height - 1) } else { - dashcore_hashes::hash_x11::Hash::all_zeros() + BlockHash::all_zeros() }; Checkpoint { height, - block_hash: BlockHash::from_raw_hash(hash_bytes), - prev_blockhash: BlockHash::from_raw_hash(prev_bytes), + block_hash, + prev_blockhash, timestamp, target: Target::from_compact(CompactTarget::from_consensus(0x1d00ffff)), - merkle_root: Some(BlockHash::from_raw_hash(hash_bytes)), + merkle_root: Some(block_hash), chain_work: format!("0x{:064x}", height * 1000), masternode_list_name: if height.is_multiple_of(100000) && height > 0 { Some(format!("ML{}__70230", height)) diff --git a/test-utils/src/fixtures.rs b/test-utils/src/fixtures.rs index 03f16a7f9..4f4324abc 100644 --- a/test-utils/src/fixtures.rs +++ b/test-utils/src/fixtures.rs @@ -38,6 +38,13 @@ pub fn testnet_genesis_hash() -> BlockHash { BlockHash::from_slice(&reversed).unwrap() } +/// Create a deterministic test block hash from a u32 identifier +pub fn test_block_hash(id: u32) -> BlockHash { + let mut bytes = [0u8; 32]; + bytes[..4].copy_from_slice(&id.to_le_bytes()); + BlockHash::from_byte_array(bytes) +} + /// Common test transaction IDs pub mod txids { use super::*;