Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: make it #[no_std] compatible #280

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ jobs:
- run: nvcc --version
- name: CUDA tests
run: |
cargo nextest run --release --no-default-features --features cuda,pasta,bls,arity2,arity4,arity8,arity11,arity16,arity24,arity36
cargo nextest run --release --no-default-features --features std,cuda,pasta,bls,arity2,arity4,arity8,arity11,arity16,arity24,arity36

# Runs the test suite on a self-hosted GPU machine with CUDA and OpenCL enabled (that is using the OpenCL backend for NVIDIA GPUs)
test-opencl:
Expand Down Expand Up @@ -152,4 +152,4 @@ jobs:
- run: clinfo
- name: OpenCL tests
run: |
cargo nextest run --release --all-features
cargo nextest run --release --no-default-features std,strengthened,abomonation,opencl,pasta,bls,arity2,arity4,arity8,arity11,arity16,arity24,arity36
18 changes: 10 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
[package]
name = "neptune"
description = "Poseidon hashing over BLS12-381 for Filecoin."
version = "13.0.0"
version = "14.0.0"
authors = ["porcuquine <[email protected]>"]
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://github.com/argumentcomputer/neptune"
rust-version = "1.71.0"
rust-version = "1.73.0"

[dependencies]
bellpepper = { workspace = true }
bellpepper-core = { workspace = true }
bellpepper = { workspace = true, optional = true }
bellpepper-core = { workspace = true, optional = true }
blake2s_simd = { workspace = true }
blstrs = { workspace = true, optional = true }
byteorder = { workspace = true }
ec-gpu = { workspace = true, optional = true }
ec-gpu-gen = { workspace = true, optional = true }
ff ={ workspace = true }
libm = { workspace = true }
ff = { workspace = true }
generic-array = { workspace = true }
pasta_curves = { workspace = true, features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
serde = { version = "1.0", features = ["derive"], optional = true }
trait-set = "0.3.0"
abomonation = { version = "0.7.3", optional = true }
abomonation_derive = { version = "0.1.0", package = "abomonation_derive_ng", optional = true }
Expand Down Expand Up @@ -57,7 +57,7 @@ incremental = false
codegen-units = 1

[features]
default = ["bls", "pasta"]
default = ["std", "bls", "pasta"]
cuda = ["ec-gpu-gen/cuda", "ec-gpu"]
opencl = ["ec-gpu-gen/opencl", "ec-gpu"]
# The supported arities for Poseidon running on the GPU are specified at compile-time.
Expand All @@ -74,6 +74,7 @@ strengthened = []
bls = ["blstrs/gpu"]
pasta = ["pasta_curves/gpu"]
portable = ["blstrs/portable"]
std = ["dep:serde", "dep:bellpepper", "dep:bellpepper-core"]
# Unsafe Abomonation-based serialization
abomonation = ["dep:abomonation", "dep:abomonation_derive"]

Expand All @@ -90,6 +91,7 @@ bellpepper = { version = "0.4.0", default-features = false }
blake2s_simd = "1.0.1"
blstrs = { version = "0.7.0" }
ff = "0.13.0"
libm = "0.2.8"
generic-array = "1.0"
pasta_curves = { version = "0.5" }
ec-gpu = { version = "0.2.0" }
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[toolchain]
# The default profile includes rustc, rust-std, cargo, rust-docs, rustfmt and clippy.
profile = "default"
channel = "1.76"
channel = "1.78"
2 changes: 1 addition & 1 deletion src/column_tree_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ where
let end = start + column_count;

if end > self.leaf_count {
return Err(Error::Other("too many columns".to_string()));
return Err(Error::Other("too many columns"));
}

match self.column_batcher {
Expand Down
11 changes: 7 additions & 4 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{error, fmt};
use core::fmt;

#[derive(Debug, Clone)]
#[cfg(any(feature = "cuda", feature = "opencl"))]
Expand Down Expand Up @@ -47,10 +47,11 @@ pub enum Error {
FullBuffer,
/// Attempt to reference an index element that is out of bounds
IndexOutOfBounds,
#[cfg(any(feature = "cuda", feature = "opencl"))]
GpuError(String),
#[cfg(any(feature = "cuda", feature = "opencl"))]
ClError(ClError),
Other(String),
Other(&'static str),
}

#[cfg(any(feature = "cuda", feature = "opencl"))]
Expand All @@ -67,16 +68,18 @@ impl From<ec_gpu_gen::EcError> for Error {
}
}

impl error::Error for Error {}
#[cfg(feature = "std")]
impl std::error::Error for Error {}

impl fmt::Display for Error {
impl core::fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
th7nder marked this conversation as resolved.
Show resolved Hide resolved
match self {
Error::FullBuffer => write!(
f,
"The size of the buffer cannot be greater than the hash arity."
),
Error::IndexOutOfBounds => write!(f, "The referenced index is outs of bounds."),
#[cfg(any(feature = "cuda", feature = "opencl"))]
Error::GpuError(s) => write!(f, "GPU Error: {s}"),
#[cfg(any(feature = "cuda", feature = "opencl"))]
Error::ClError(e) => write!(f, "OpenCL Error: {e}"),
Expand Down
14 changes: 10 additions & 4 deletions src/hash_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ use abomonation::Abomonation;
#[cfg(feature = "abomonation")]
use abomonation_derive::Abomonation;
use ff::PrimeField;
#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "std",
serde(bound(serialize = "F: Serialize", deserialize = "F: Deserialize<'de>"))
)]
#[cfg_attr(feature = "abomonation", derive(Abomonation))]
#[serde(bound(serialize = "F: Serialize", deserialize = "F: Deserialize<'de>"))]
#[cfg_attr(feature = "abomonation", abomonation_omit_bounds)]
pub enum HashType<F: PrimeField, A: Arity<F>> {
MerkleTree,
Expand Down Expand Up @@ -73,7 +78,8 @@ impl<F: PrimeField, A: Arity<F>> HashType<F, A> {
}
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "abomonation", derive(Abomonation))]
#[cfg_attr(feature = "abomonation", abomonation_omit_bounds)]
pub enum CType<F: PrimeField, A: Arity<F>> {
Expand All @@ -82,7 +88,7 @@ pub enum CType<F: PrimeField, A: Arity<F>> {
// This is a bit of a hack, but since `serde(skip)` tags the last variant arm,
// the generated code ends up being correct. But, in the future, do not
// carelessly add new variants to this enum.
#[serde(skip)]
#[cfg_attr(feature = "std", serde(skip))]
#[cfg_attr(feature = "abomonation", abomonation_skip)]
_Phantom((F, A)),
}
Expand Down
20 changes: 15 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![allow(dead_code)]
#![allow(unused_imports)]

extern crate alloc;
pub use alloc::vec::Vec;

pub use crate::poseidon::{Arity, Poseidon};
use crate::round_constants::generate_constants;
use crate::round_numbers::{round_numbers_base, round_numbers_strengthened};
Expand All @@ -11,8 +15,8 @@ use blstrs::Scalar as Fr;
pub use error::Error;
use ff::PrimeField;
use generic_array::GenericArray;
#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};
use std::fmt;
use trait_set::trait_set;

// See https://www.lurklurk.org/effective-rust/re-export.html
Expand Down Expand Up @@ -45,8 +49,11 @@ compile_error!("The `strengthened` feature needs the `cuda` and/or `opencl` feat
compile_error!("The `cuda` and `opencl` features need the `bls` and/or `pasta` feature to be set");

/// Poseidon circuit
#[cfg(feature = "std")]
pub mod circuit;
#[cfg(feature = "std")]
pub mod circuit2;
#[cfg(feature = "std")]
pub mod circuit2_witness;
pub mod error;
mod matrix;
Expand All @@ -60,6 +67,7 @@ mod round_constants;
mod round_numbers;

/// Sponge
#[cfg(any(test, feature = "std"))]
pub mod sponge;

/// Hash types and domain separation tags.
Expand Down Expand Up @@ -97,21 +105,23 @@ trait_set! {
pub trait NeptuneField = PrimeField + ec_gpu::GpuName;
}

#[cfg(feature = "std")]
mod serde_impl;

pub(crate) const TEST_SEED: [u8; 16] = [
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 0xe5,
];

#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "abomonation", derive(Abomonation))]
pub enum Strength {
Standard,
Strengthened,
}

impl fmt::Display for Strength {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl core::fmt::Display for Strength {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Standard => write!(f, "standard"),
Self::Strengthened => write!(f, "strengthened"),
Expand Down Expand Up @@ -183,7 +193,7 @@ fn round_constants<F: PrimeField>(arity: usize, strength: &Strength) -> Vec<F> {

let fr_num_bits = F::NUM_BITS;
let field_size = {
assert!(fr_num_bits <= u32::from(std::u16::MAX));
assert!(fr_num_bits <= u32::from(core::u16::MAX));
// It's safe to convert to u16 for compatibility with other types.
fr_num_bits as u16
};
Expand Down
7 changes: 4 additions & 3 deletions src/matrix.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Allow `&Matrix` in function signatures.
#![allow(clippy::ptr_arg)]

use crate::Vec;
use ff::PrimeField;

/// Matrix functions here are, at least for now, quick and dirty — intended only to support precomputation of poseidon optimization.
Expand Down Expand Up @@ -116,7 +117,7 @@ pub(crate) fn left_apply_matrix<F: PrimeField>(m: &Matrix<F>, v: &[F]) -> Vec<F>
"Matrix can only be applied to vector of same size."
);

let mut result = vec![F::ZERO; v.len()];
let mut result = alloc::vec![F::ZERO; v.len()];

for (result, row) in result.iter_mut().zip(m.iter()) {
for (mat_val, vec_val) in row.iter().zip(v) {
Expand All @@ -137,7 +138,7 @@ pub(crate) fn apply_matrix<F: PrimeField>(m: &Matrix<F>, v: &[F]) -> Vec<F> {
"Matrix can only be applied to vector of same size."
);

let mut result = vec![F::ZERO; v.len()];
let mut result = alloc::vec![F::ZERO; v.len()];
for (j, val) in result.iter_mut().enumerate() {
for (i, row) in m.iter().enumerate() {
let mut tmp = row[j];
Expand Down Expand Up @@ -165,7 +166,7 @@ pub(crate) fn transpose<F: PrimeField>(matrix: &Matrix<F>) -> Matrix<F> {

#[allow(clippy::needless_range_loop)]
pub(crate) fn make_identity<F: PrimeField>(size: usize) -> Matrix<F> {
let mut result = vec![vec![F::ZERO; size]; size];
let mut result = alloc::vec![alloc::vec![F::ZERO; size]; size];
for i in 0..size {
result[i][i] = F::ONE;
}
Expand Down
14 changes: 9 additions & 5 deletions src/mds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ use abomonation::Abomonation;
#[cfg(feature = "abomonation")]
use abomonation_derive::Abomonation;
use ff::PrimeField;
#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};

use crate::matrix;
use crate::matrix::{
apply_matrix, invert, is_identity, is_invertible, is_square, left_apply_matrix, mat_mul, minor,
transpose, Matrix,
};
use crate::Vec;

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "abomonation", derive(Abomonation))]
#[cfg_attr(feature = "abomonation", abomonation_bounds(where F::Repr: Abomonation))]
pub struct MdsMatrices<F: PrimeField> {
Expand Down Expand Up @@ -58,7 +61,8 @@ pub(crate) fn derive_mds_matrices<F: PrimeField>(m: Matrix<F>) -> MdsMatrices<F>
/// This means its first row and column are each dense, and the interior matrix
/// (minor to the element in both the row and column) is the identity.
/// We will pluralize this compact structure `sparse_matrixes` to distinguish from `sparse_matrices` from which they are created.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "abomonation", derive(Abomonation))]
#[cfg_attr(feature = "abomonation", abomonation_bounds(where F::Repr: Abomonation))]
pub struct SparseMatrix<F: PrimeField> {
Expand Down Expand Up @@ -174,12 +178,12 @@ fn make_prime<F: PrimeField>(m: &Matrix<F>) -> Matrix<F> {
.enumerate()
.map(|(i, row)| match i {
0 => {
let mut new_row = vec![F::ZERO; row.len()];
let mut new_row = alloc::vec![F::ZERO; row.len()];
new_row[0] = F::ONE;
new_row
}
_ => {
let mut new_row = vec![F::ZERO; row.len()];
let mut new_row = alloc::vec![F::ZERO; row.len()];
new_row[1..].copy_from_slice(&row[1..]);
new_row
}
Expand All @@ -201,7 +205,7 @@ fn make_double_prime<F: PrimeField>(m: &Matrix<F>, m_hat_inv: &Matrix<F>) -> Mat
new_row
}
_ => {
let mut new_row = vec![F::ZERO; row.len()];
let mut new_row = alloc::vec![F::ZERO; row.len()];
new_row[0] = w_hat[i - 1];
new_row[i] = F::ONE;
new_row
Expand Down
11 changes: 7 additions & 4 deletions src/poseidon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@ use crate::mds::{
};
use crate::poseidon_alt::{hash_correct, hash_optimized_dynamic};
use crate::preprocessing::compress_round_constants;
use crate::Vec;
use crate::{matrix, quintic_s_box, BatchHasher, Strength, DEFAULT_STRENGTH};
use crate::{round_constants, round_numbers, Error};
#[cfg(feature = "abomonation")]
use abomonation::Abomonation;
#[cfg(feature = "abomonation")]
use abomonation_derive::Abomonation;
use core::marker::PhantomData;
use ff::PrimeField;
use generic_array::{sequence::GenericSequence, typenum, ArrayLength, GenericArray};
#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
use typenum::marker_traits::Unsigned;
use typenum::*;

Expand Down Expand Up @@ -868,12 +870,12 @@ where
}
}

let _ = std::mem::replace(&mut self.elements, result);
let _ = core::mem::replace(&mut self.elements, result);
}

pub(crate) fn product_mds_with_matrix_left(&mut self, matrix: &Matrix<F>) {
let result = left_apply_matrix(matrix, &self.elements);
let _ = std::mem::replace(
let _ = core::mem::replace(
&mut self.elements,
GenericArray::<F, A::ConstantsSize>::generate(|i| result[i]),
);
Expand All @@ -900,9 +902,10 @@ where
val.add_assign(&tmp);
}

let _ = std::mem::replace(&mut self.elements, result);
let _ = core::mem::replace(&mut self.elements, result);
}

#[cfg(feature = "std")]
pub(crate) fn debug(&self, msg: &str) {
dbg!(msg, &self.constants_offset, &self.elements);
}
Expand Down
1 change: 1 addition & 0 deletions src/poseidon_alt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! These are tested (in `poseidon::test`) to be equivalent to the 'static optimized' version
//! used for actual hashing by the neptune library.
use crate::poseidon::{Arity, Poseidon};
use crate::Vec;
use crate::{matrix, quintic_s_box};
use ff::PrimeField;

Expand Down
Loading
Loading