From e6f51a91d1a1fca4595dc147d4cf5385ecb1a4e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= Date: Wed, 8 Nov 2023 08:45:54 -0500 Subject: [PATCH] feat: put abomonation under a feature --- .github/workflows/rust.yml | 2 ++ Cargo.toml | 6 +++-- examples/poseidon_constants_serde.rs | 34 +++++++++++++++++----------- src/hash_type.rs | 14 ++++++++---- src/lib.rs | 4 +++- src/mds.rs | 28 +++++++++++++---------- src/poseidon.rs | 17 +++++++++----- 7 files changed, 66 insertions(+), 39 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 6c14c3da..ffef55fe 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -58,6 +58,8 @@ jobs: - name: Doctests run: | cargo test --doc + - name: Abomonation feature + run: cargo run --features "abomonation" --example poseidon_constants_serde clippy: runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index 072c5ed0..95795606 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,8 +22,8 @@ log = { workspace = true } pasta_curves = { workspace = true, features = ["serde"] } serde = { version = "1.0", features = ["derive"] } trait-set = "0.3.0" -abomonation = "0.7.3" -abomonation_derive = { version = "0.1.0", package = "abomonation_derive_ng" } +abomonation = { version = "0.7.3", optional = true } +abomonation_derive = { version = "0.1.0", package = "abomonation_derive_ng", optional = true } [dev-dependencies] bincode = "1.3.3" @@ -70,6 +70,8 @@ strengthened = [] bls = ["blstrs/gpu"] pasta = ["pasta_curves/gpu"] portable = ["blstrs/portable"] +# Unsafe Abomonation-based serialization +abomonation = ["dep:abomonation", "dep:abomonation_derive"] [workspace] resolver = "2" diff --git a/examples/poseidon_constants_serde.rs b/examples/poseidon_constants_serde.rs index fbe526f2..9b6b3c31 100644 --- a/examples/poseidon_constants_serde.rs +++ b/examples/poseidon_constants_serde.rs @@ -1,22 +1,30 @@ +// This should only run with the abomonation feature, see https://github.com/rust-lang/cargo/issues/4663 +#[cfg(feature = "abomonation")] use abomonation::{decode, encode}; +#[cfg(feature = "abomonation")] use blstrs::Scalar as Fr; +#[cfg(feature = "abomonation")] use generic_array::typenum::U24; +#[cfg(feature = "abomonation")] use neptune::{poseidon::PoseidonConstants, Strength}; fn main() { - let mut bytes = Vec::new(); - unsafe { - let constants = PoseidonConstants::::new_with_strength(Strength::Standard); - encode(&constants, &mut bytes).unwrap() - }; - println!("Encoded!"); - println!("Read size: {}", bytes.len()); + #[cfg(feature = "abomonation")] + { + let mut bytes = Vec::new(); + unsafe { + let constants = PoseidonConstants::::new_with_strength(Strength::Standard); + encode(&constants, &mut bytes).unwrap() + }; + println!("Encoded!"); + println!("Read size: {}", bytes.len()); - if let Some((result, remaining)) = unsafe { decode::>(&mut bytes) } { - let constants = PoseidonConstants::::new_with_strength(Strength::Standard); - assert!(result.clone() == constants, "not equal!"); - assert!(remaining.is_empty()); - } else { - println!("Something terrible happened"); + if let Some((result, remaining)) = unsafe { decode::>(&mut bytes) } { + let constants = PoseidonConstants::::new_with_strength(Strength::Standard); + assert!(result.clone() == constants, "not equal!"); + assert!(remaining.is_empty()); + } else { + println!("Something terrible happened"); + } } } diff --git a/src/hash_type.rs b/src/hash_type.rs index 8c6e678d..0aca94ee 100644 --- a/src/hash_type.rs +++ b/src/hash_type.rs @@ -11,14 +11,17 @@ /// `Strength` with `HashType` so that hashes with `Strength` other than `Standard` (currently only `Strengthened`) /// may still express the full range of hash function types. use crate::{Arity, Strength}; +#[cfg(feature = "abomonation")] use abomonation::Abomonation; +#[cfg(feature = "abomonation")] use abomonation_derive::Abomonation; use ff::PrimeField; use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Abomonation)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "abomonation", derive(Abomonation))] #[serde(bound(serialize = "F: Serialize", deserialize = "F: Deserialize<'de>"))] -#[abomonation_omit_bounds] +#[cfg_attr(feature = "abomonation", abomonation_omit_bounds)] pub enum HashType> { MerkleTree, MerkleTreeSparse(u64), @@ -70,8 +73,9 @@ impl> HashType { } } -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Abomonation)] -#[abomonation_omit_bounds] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "abomonation", derive(Abomonation))] +#[cfg_attr(feature = "abomonation", abomonation_omit_bounds)] pub enum CType> { Arbitrary(u64), // See: https://github.com/bincode-org/bincode/issues/424 @@ -79,7 +83,7 @@ pub enum CType> { // the generated code ends up being correct. But, in the future, do not // carelessly add new variants to this enum. #[serde(skip)] - #[abomonation_skip] + #[cfg_attr(feature = "abomonation", abomonation_skip)] _Phantom((F, A)), } diff --git a/src/lib.rs b/src/lib.rs index 1e0895a8..b2798b31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ pub use crate::poseidon::{Arity, Poseidon}; use crate::round_constants::generate_constants; use crate::round_numbers::{round_numbers_base, round_numbers_strengthened}; +#[cfg(feature = "abomonation")] use abomonation_derive::Abomonation; #[cfg(test)] use blstrs::Scalar as Fr; @@ -99,7 +100,8 @@ 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, Abomonation)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "abomonation", derive(Abomonation))] pub enum Strength { Standard, Strengthened, diff --git a/src/mds.rs b/src/mds.rs index 1b276baf..1f1cd593 100644 --- a/src/mds.rs +++ b/src/mds.rs @@ -1,7 +1,9 @@ // Allow `&Matrix` in function signatures. #![allow(clippy::ptr_arg)] +#[cfg(feature = "abomonation")] use abomonation::Abomonation; +#[cfg(feature = "abomonation")] use abomonation_derive::Abomonation; use ff::PrimeField; use serde::{Deserialize, Serialize}; @@ -12,20 +14,21 @@ use crate::matrix::{ transpose, Matrix, }; -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Abomonation)] -#[abomonation_bounds(where F::Repr: Abomonation)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "abomonation", derive(Abomonation))] +#[cfg_attr(feature = "abomonation", abomonation_bounds(where F::Repr: Abomonation))] pub struct MdsMatrices { - #[abomonate_with(Vec>)] + #[cfg_attr(feature = "abomonation", abomonate_with(Vec>))] pub m: Matrix, - #[abomonate_with(Vec>)] + #[cfg_attr(feature = "abomonation", abomonate_with(Vec>))] pub m_inv: Matrix, - #[abomonate_with(Vec>)] + #[cfg_attr(feature = "abomonation", abomonate_with(Vec>))] pub m_hat: Matrix, - #[abomonate_with(Vec>)] + #[cfg_attr(feature = "abomonation", abomonate_with(Vec>))] pub m_hat_inv: Matrix, - #[abomonate_with(Vec>)] + #[cfg_attr(feature = "abomonation", abomonate_with(Vec>))] pub m_prime: Matrix, - #[abomonate_with(Vec>)] + #[cfg_attr(feature = "abomonation", abomonate_with(Vec>))] pub m_double_prime: Matrix, } @@ -55,14 +58,15 @@ pub(crate) fn derive_mds_matrices(m: Matrix) -> MdsMatrices /// 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, Abomonation)] -#[abomonation_bounds(where F::Repr: Abomonation)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "abomonation", derive(Abomonation))] +#[cfg_attr(feature = "abomonation", abomonation_bounds(where F::Repr: Abomonation))] pub struct SparseMatrix { /// `w_hat` is the first column of the M'' matrix. It will be directly multiplied (scalar product) with a row of state elements. - #[abomonate_with(Vec)] + #[cfg_attr(feature = "abomonation", abomonate_with(Vec))] pub w_hat: Vec, /// `v_rest` contains all but the first (already included in `w_hat`). - #[abomonate_with(Vec)] + #[cfg_attr(feature = "abomonation", abomonate_with(Vec))] pub v_rest: Vec, } diff --git a/src/poseidon.rs b/src/poseidon.rs index 050cdbb6..1b420254 100644 --- a/src/poseidon.rs +++ b/src/poseidon.rs @@ -8,7 +8,9 @@ use crate::poseidon_alt::{hash_correct, hash_optimized_dynamic}; use crate::preprocessing::compress_round_constants; 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 ff::PrimeField; use generic_array::{sequence::GenericSequence, typenum, ArrayLength, GenericArray}; @@ -83,21 +85,22 @@ where /// and [`Arity`] as [`Poseidon`] instance that consumes it. /// /// See original [Poseidon paper](https://eprint.iacr.org/2019/458.pdf) for more details. -#[derive(Debug, Clone, PartialEq, Eq, Abomonation)] -#[abomonation_bounds(where F::Repr: Abomonation)] +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "abomonation", derive(Abomonation))] +#[cfg_attr(feature = "abomonation", abomonation_bounds(where F::Repr: Abomonation))] pub struct PoseidonConstants> { pub mds_matrices: MdsMatrices, - #[abomonate_with(Option>)] + #[cfg_attr(feature = "abomonation", abomonate_with(Option>))] pub round_constants: Option>, // TODO: figure out how to automatically allocate `None` - #[abomonate_with(Vec)] + #[cfg_attr(feature = "abomonation", abomonate_with(Vec))] pub compressed_round_constants: Vec, - #[abomonate_with(Matrix)] + #[cfg_attr(feature = "abomonation", abomonate_with(Matrix))] pub pre_sparse_matrix: Matrix, pub sparse_matrixes: Vec>, pub strength: Strength, /// The domain tag is the first element of a Poseidon permutation. /// This extra element is necessary for 128-bit security. - #[abomonate_with(F::Repr)] + #[cfg_attr(feature = "abomonation", abomonate_with(F::Repr))] pub domain_tag: F, pub full_rounds: usize, pub half_full_rounds: usize, @@ -953,6 +956,7 @@ mod tests { use super::*; use crate::sponge::vanilla::SpongeTrait; use crate::*; + #[cfg(feature = "abomonation")] use abomonation::{decode, encode}; use blstrs::Scalar as Fr; use ff::Field; @@ -1313,6 +1317,7 @@ mod tests { ); } + #[cfg(feature = "abomonation")] #[test] fn roundtrip_abomonation() { let mut constants = PoseidonConstants::::new();