Skip to content

Commit 3bfe7ec

Browse files
haurogcome-maizmichaelsproul
authored
Enable RISC-V build (#8)
* Add x86_64 dependency for cpufeature as it is only used for this plattform * Update Cargo.toml Co-authored-by: Leonardo Arias <leo@flashbots.net> * Remove detect-cpufeatures feature * Only compile sha2 dep on x86 * Fix compilation issue on x86 --------- Co-authored-by: Leonardo Arias <leo@flashbots.net> Co-authored-by: Michael Sproul <michael@sigmaprime.io>
1 parent b6b5ff2 commit 3bfe7ec

File tree

3 files changed

+58
-36
lines changed

3 files changed

+58
-36
lines changed

Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ categories = ["cryptography::cryptocurrencies"]
1212

1313
[dependencies]
1414
lazy_static = { version = "1.1", optional = true }
15-
cpufeatures = { version = "0.2", optional = true }
1615
ring = "0.17"
16+
17+
[target.'cfg(target_arch = "x86_64")'.dependencies]
18+
cpufeatures = "0.2"
1719
sha2 = "0.10"
1820

1921
[dev-dependencies]
@@ -23,6 +25,5 @@ rustc-hex = "2"
2325
wasm-bindgen-test = "0.3.33"
2426

2527
[features]
26-
default = ["zero_hash_cache", "detect-cpufeatures"]
28+
default = ["zero_hash_cache"]
2729
zero_hash_cache = ["lazy_static"]
28-
detect-cpufeatures = ["cpufeatures"]

src/lib.rs

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77
//! Now this crate serves primarily as a wrapper over two SHA256 crates: `sha2` and `ring` – which
88
//! it switches between at runtime based on the availability of SHA intrinsics.
99
10+
mod sha2_impl;
11+
1012
pub use self::DynamicContext as Context;
11-
use sha2::Digest;
13+
14+
#[cfg(target_arch = "x86_64")]
15+
use sha2_impl::Sha2CrateImpl;
1216

1317
#[cfg(feature = "zero_hash_cache")]
1418
use lazy_static::lazy_static;
@@ -54,35 +58,6 @@ pub trait Sha256 {
5458
fn hash_fixed(&self, input: &[u8]) -> [u8; HASH_LEN];
5559
}
5660

57-
/// Implementation of SHA256 using the `sha2` crate (fastest on CPUs with SHA extensions).
58-
struct Sha2CrateImpl;
59-
60-
impl Sha256Context for sha2::Sha256 {
61-
fn new() -> Self {
62-
sha2::Digest::new()
63-
}
64-
65-
fn update(&mut self, bytes: &[u8]) {
66-
sha2::Digest::update(self, bytes)
67-
}
68-
69-
fn finalize(self) -> [u8; HASH_LEN] {
70-
sha2::Digest::finalize(self).into()
71-
}
72-
}
73-
74-
impl Sha256 for Sha2CrateImpl {
75-
type Context = sha2::Sha256;
76-
77-
fn hash(&self, input: &[u8]) -> Vec<u8> {
78-
Self::Context::digest(input).into_iter().collect()
79-
}
80-
81-
fn hash_fixed(&self, input: &[u8]) -> [u8; HASH_LEN] {
82-
Self::Context::digest(input).into()
83-
}
84-
}
85-
8661
/// Implementation of SHA256 using the `ring` crate (fastest on CPUs without SHA extensions).
8762
pub struct RingImpl;
8863

@@ -120,34 +95,39 @@ impl Sha256 for RingImpl {
12095

12196
/// Default dynamic implementation that switches between available implementations.
12297
pub enum DynamicImpl {
98+
#[cfg(target_arch = "x86_64")]
12399
Sha2,
124100
Ring,
125101
}
126102

127103
// Runtime latch for detecting the availability of SHA extensions on x86_64.
128104
//
129105
// Inspired by the runtime switch within the `sha2` crate itself.
130-
#[cfg(all(feature = "detect-cpufeatures", target_arch = "x86_64"))]
106+
#[cfg(target_arch = "x86_64")]
131107
cpufeatures::new!(x86_sha_extensions, "sha", "sse2", "ssse3", "sse4.1");
132108

133109
#[inline(always)]
134110
pub fn have_sha_extensions() -> bool {
135-
#[cfg(all(feature = "detect-cpufeatures", target_arch = "x86_64"))]
111+
#[cfg(target_arch = "x86_64")]
136112
return x86_sha_extensions::get();
137113

138-
#[cfg(not(all(feature = "detect-cpufeatures", target_arch = "x86_64")))]
114+
#[cfg(not(target_arch = "x86_64"))]
139115
return false;
140116
}
141117

142118
impl DynamicImpl {
143119
/// Choose the best available implementation based on the currently executing CPU.
144120
#[inline(always)]
145121
pub fn best() -> Self {
122+
#[cfg(target_arch = "x86_64")]
146123
if have_sha_extensions() {
147124
Self::Sha2
148125
} else {
149126
Self::Ring
150127
}
128+
129+
#[cfg(not(target_arch = "x86_64"))]
130+
Self::Ring
151131
}
152132
}
153133

@@ -157,6 +137,7 @@ impl Sha256 for DynamicImpl {
157137
#[inline(always)]
158138
fn hash(&self, input: &[u8]) -> Vec<u8> {
159139
match self {
140+
#[cfg(target_arch = "x86_64")]
160141
Self::Sha2 => Sha2CrateImpl.hash(input),
161142
Self::Ring => RingImpl.hash(input),
162143
}
@@ -165,6 +146,7 @@ impl Sha256 for DynamicImpl {
165146
#[inline(always)]
166147
fn hash_fixed(&self, input: &[u8]) -> [u8; HASH_LEN] {
167148
match self {
149+
#[cfg(target_arch = "x86_64")]
168150
Self::Sha2 => Sha2CrateImpl.hash_fixed(input),
169151
Self::Ring => RingImpl.hash_fixed(input),
170152
}
@@ -175,27 +157,31 @@ impl Sha256 for DynamicImpl {
175157
///
176158
/// This enum ends up being 8 bytes larger than the largest inner context.
177159
pub enum DynamicContext {
160+
#[cfg(target_arch = "x86_64")]
178161
Sha2(sha2::Sha256),
179162
Ring(ring::digest::Context),
180163
}
181164

182165
impl Sha256Context for DynamicContext {
183166
fn new() -> Self {
184167
match DynamicImpl::best() {
168+
#[cfg(target_arch = "x86_64")]
185169
DynamicImpl::Sha2 => Self::Sha2(Sha256Context::new()),
186170
DynamicImpl::Ring => Self::Ring(Sha256Context::new()),
187171
}
188172
}
189173

190174
fn update(&mut self, bytes: &[u8]) {
191175
match self {
176+
#[cfg(target_arch = "x86_64")]
192177
Self::Sha2(ctxt) => Sha256Context::update(ctxt, bytes),
193178
Self::Ring(ctxt) => Sha256Context::update(ctxt, bytes),
194179
}
195180
}
196181

197182
fn finalize(self) -> [u8; HASH_LEN] {
198183
match self {
184+
#[cfg(target_arch = "x86_64")]
199185
Self::Sha2(ctxt) => Sha256Context::finalize(ctxt),
200186
Self::Ring(ctxt) => Sha256Context::finalize(ctxt),
201187
}

src/sha2_impl.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// This implementation should only be compiled on x86_64 due to its dependency on the `sha2` and
2+
// `cpufeatures` crates which do not compile on some architectures like RISC-V.
3+
#![cfg(target_arch = "x86_64")]
4+
5+
use crate::{Sha256, Sha256Context, HASH_LEN};
6+
use sha2::Digest;
7+
8+
/// Implementation of SHA256 using the `sha2` crate (fastest on x86_64 CPUs with SHA extensions).
9+
pub struct Sha2CrateImpl;
10+
11+
impl Sha256Context for sha2::Sha256 {
12+
fn new() -> Self {
13+
sha2::Digest::new()
14+
}
15+
16+
fn update(&mut self, bytes: &[u8]) {
17+
sha2::Digest::update(self, bytes)
18+
}
19+
20+
fn finalize(self) -> [u8; HASH_LEN] {
21+
sha2::Digest::finalize(self).into()
22+
}
23+
}
24+
25+
impl Sha256 for Sha2CrateImpl {
26+
type Context = sha2::Sha256;
27+
28+
fn hash(&self, input: &[u8]) -> Vec<u8> {
29+
Self::Context::digest(input).into_iter().collect()
30+
}
31+
32+
fn hash_fixed(&self, input: &[u8]) -> [u8; HASH_LEN] {
33+
Self::Context::digest(input).into()
34+
}
35+
}

0 commit comments

Comments
 (0)