blvm_primitives/crypto/mod.rs
1//! Cryptographic hash functions with CPU feature detection and optimizations
2//!
3//! Provides optimized SHA256 implementations that automatically select
4//! the best available implementation based on CPU features:
5//! - AVX2 SIMD (8-way parallel) - fastest on modern CPUs
6//! - SSE4 SIMD (4-way parallel) - fallback for older CPUs
7//! - Generic (sha2 crate with asm) - baseline for all CPUs
8//!
9//! The sha2 crate with "asm" feature already includes optimized assembly,
10//! but we can add batch processing and CPU feature detection for better
11//! performance in batch scenarios.
12
13use sha2::{Digest, Sha256};
14
15#[cfg(target_arch = "x86_64")]
16pub mod avx2_batch;
17#[cfg(target_arch = "x86_64")]
18pub mod hash_compare;
19#[cfg(target_arch = "x86_64")]
20pub mod sha256_avx2;
21#[cfg(target_arch = "x86_64")]
22pub mod sha_ni;
23#[cfg(target_arch = "x86_64")]
24pub mod simd_bytes;
25
26pub mod int_ops;
27
28/// CPU feature detection for runtime optimization selection
29pub mod cpu_features {
30 /// Check if AVX2 is available
31 ///
32 /// Hot-path function called during hash operation dispatch.
33 /// Always inline for maximum performance.
34 #[cfg(target_arch = "x86_64")]
35 #[inline(always)]
36 pub fn has_avx2() -> bool {
37 std::arch::is_x86_feature_detected!("avx2")
38 }
39
40 /// Check if SSE4.1 is available
41 ///
42 /// Hot-path function called during hash operation dispatch.
43 /// Always inline for maximum performance.
44 #[cfg(target_arch = "x86_64")]
45 #[inline(always)]
46 pub fn has_sse41() -> bool {
47 std::arch::is_x86_feature_detected!("sse4.1")
48 }
49
50 /// Check if Intel SHA-NI is available
51 ///
52 /// Hot-path function called during hash operation dispatch.
53 /// Always inline for maximum performance.
54 #[cfg(target_arch = "x86_64")]
55 #[inline(always)]
56 pub fn has_sha_ni() -> bool {
57 std::arch::is_x86_feature_detected!("sha")
58 }
59
60 #[cfg(not(target_arch = "x86_64"))]
61 pub fn has_avx2() -> bool {
62 false
63 }
64
65 #[cfg(not(target_arch = "x86_64"))]
66 pub fn has_sse41() -> bool {
67 false
68 }
69
70 #[cfg(not(target_arch = "x86_64"))]
71 pub fn has_sha_ni() -> bool {
72 false
73 }
74}
75
76/// Optimized SHA256 hasher with CPU feature detection
77pub struct OptimizedSha256;
78
79impl OptimizedSha256 {
80 /// Create a new SHA256 hasher with automatic CPU feature detection
81 pub fn new() -> Self {
82 Self
83 }
84
85 /// Hash data using the best available implementation
86 ///
87 /// Priority:
88 /// 1. SHA-NI (Intel SHA Extensions) - 10-15x faster for single hashes
89 /// 2. sha2 crate with asm - baseline fallback
90 ///
91 /// For batch operations, see batch_sha256 in optimizations module.
92 pub fn hash(&self, data: &[u8]) -> [u8; 32] {
93 #[cfg(target_arch = "x86_64")]
94 {
95 // Try SHA-NI first (hardware accelerated, optimal for single hashes)
96 if sha_ni::is_sha_ni_available() {
97 return sha_ni::sha256(data);
98 }
99 }
100
101 // Fallback: sha2 crate with asm optimizations
102 let mut hasher = Sha256::new();
103 hasher.update(data);
104 let hash = hasher.finalize();
105 let mut result = [0u8; 32];
106 result.copy_from_slice(&hash);
107 result
108 }
109
110 /// Compute double SHA256 (SHA256(SHA256(data)))
111 ///
112 /// Uses SHA-NI if available for optimal single-hash performance.
113 pub fn hash256(&self, data: &[u8]) -> [u8; 32] {
114 #[cfg(target_arch = "x86_64")]
115 {
116 if sha_ni::is_sha_ni_available() {
117 return sha_ni::hash256(data);
118 }
119 }
120
121 let first = self.hash(data);
122 self.hash(&first)
123 }
124}
125
126impl Default for OptimizedSha256 {
127 fn default() -> Self {
128 Self::new()
129 }
130}
131
132/// Convenience function for single SHA256 hash
133pub fn sha256(data: &[u8]) -> [u8; 32] {
134 OptimizedSha256::new().hash(data)
135}
136
137/// Convenience function for double SHA256 hash (Bitcoin standard)
138pub fn hash256(data: &[u8]) -> [u8; 32] {
139 OptimizedSha256::new().hash256(data)
140}