Skip to content

Commit

Permalink
feat: put abomonation under a feature
Browse files Browse the repository at this point in the history
  • Loading branch information
huitseeker committed Nov 8, 2023
1 parent bde73e0 commit e6f51a9
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 39 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down
34 changes: 21 additions & 13 deletions examples/poseidon_constants_serde.rs
Original file line number Diff line number Diff line change
@@ -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::<Fr, U24>::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::<Fr, U24>::new_with_strength(Strength::Standard);
encode(&constants, &mut bytes).unwrap()
};
println!("Encoded!");
println!("Read size: {}", bytes.len());

if let Some((result, remaining)) = unsafe { decode::<PoseidonConstants<Fr, U24>>(&mut bytes) } {
let constants = PoseidonConstants::<Fr, U24>::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::<PoseidonConstants<Fr, U24>>(&mut bytes) } {
let constants = PoseidonConstants::<Fr, U24>::new_with_strength(Strength::Standard);
assert!(result.clone() == constants, "not equal!");
assert!(remaining.is_empty());
} else {
println!("Something terrible happened");
}
}
}
14 changes: 9 additions & 5 deletions src/hash_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<F: PrimeField, A: Arity<F>> {
MerkleTree,
MerkleTreeSparse(u64),
Expand Down Expand Up @@ -70,16 +73,17 @@ impl<F: PrimeField, A: Arity<F>> HashType<F, A> {
}
}

#[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<F: PrimeField, A: Arity<F>> {
Arbitrary(u64),
// See: https://github.com/bincode-org/bincode/issues/424
// 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)]
#[abomonation_skip]
#[cfg_attr(feature = "abomonation", abomonation_skip)]
_Phantom((F, A)),
}

Expand Down
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
28 changes: 16 additions & 12 deletions src/mds.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand All @@ -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<F: PrimeField> {
#[abomonate_with(Vec<Vec<F::Repr>>)]
#[cfg_attr(feature = "abomonation", abomonate_with(Vec<Vec<F::Repr>>))]
pub m: Matrix<F>,
#[abomonate_with(Vec<Vec<F::Repr>>)]
#[cfg_attr(feature = "abomonation", abomonate_with(Vec<Vec<F::Repr>>))]
pub m_inv: Matrix<F>,
#[abomonate_with(Vec<Vec<F::Repr>>)]
#[cfg_attr(feature = "abomonation", abomonate_with(Vec<Vec<F::Repr>>))]
pub m_hat: Matrix<F>,
#[abomonate_with(Vec<Vec<F::Repr>>)]
#[cfg_attr(feature = "abomonation", abomonate_with(Vec<Vec<F::Repr>>))]
pub m_hat_inv: Matrix<F>,
#[abomonate_with(Vec<Vec<F::Repr>>)]
#[cfg_attr(feature = "abomonation", abomonate_with(Vec<Vec<F::Repr>>))]
pub m_prime: Matrix<F>,
#[abomonate_with(Vec<Vec<F::Repr>>)]
#[cfg_attr(feature = "abomonation", abomonate_with(Vec<Vec<F::Repr>>))]
pub m_double_prime: Matrix<F>,
}

Expand Down Expand Up @@ -55,14 +58,15 @@ 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, 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<F: PrimeField> {
/// `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<F::Repr>)]
#[cfg_attr(feature = "abomonation", abomonate_with(Vec<F::Repr>))]
pub w_hat: Vec<F>,
/// `v_rest` contains all but the first (already included in `w_hat`).
#[abomonate_with(Vec<F::Repr>)]
#[cfg_attr(feature = "abomonation", abomonate_with(Vec<F::Repr>))]
pub v_rest: Vec<F>,
}

Expand Down
17 changes: 11 additions & 6 deletions src/poseidon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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<F: PrimeField, A: Arity<F>> {
pub mds_matrices: MdsMatrices<F>,
#[abomonate_with(Option<Vec<F::Repr>>)]
#[cfg_attr(feature = "abomonation", abomonate_with(Option<Vec<F::Repr>>))]
pub round_constants: Option<Vec<F>>, // TODO: figure out how to automatically allocate `None`
#[abomonate_with(Vec<F::Repr>)]
#[cfg_attr(feature = "abomonation", abomonate_with(Vec<F::Repr>))]
pub compressed_round_constants: Vec<F>,
#[abomonate_with(Matrix<F::Repr>)]
#[cfg_attr(feature = "abomonation", abomonate_with(Matrix<F::Repr>))]
pub pre_sparse_matrix: Matrix<F>,
pub sparse_matrixes: Vec<SparseMatrix<F>>,
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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1313,6 +1317,7 @@ mod tests {
);
}

#[cfg(feature = "abomonation")]
#[test]
fn roundtrip_abomonation() {
let mut constants = PoseidonConstants::<Fr, U2>::new();
Expand Down

0 comments on commit e6f51a9

Please sign in to comment.