Skip to content

Commit f5b3df0

Browse files
authored
Add test vectors for SHAKE-128. (#75)
1 parent bdc6405 commit f5b3df0

File tree

12 files changed

+592
-55
lines changed

12 files changed

+592
-55
lines changed

Cargo.toml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,23 @@ spongefish-derive = { path = "derive" }
6666
spongefish-poseidon2 = { path = "poseidon2" }
6767
spongefish-circuit = { path = "circuit" }
6868
# p256 = "^0.13"
69-
p3-baby-bear = "^0.3"
70-
p3-field = "^0.3"
71-
p3-koala-bear = "^0.3"
72-
p3-mersenne-31 = "^0.3"
73-
p3-poseidon2 = "^0.3"
74-
p3-symmetric = "^0.3"
69+
p3-baby-bear = "^0.4"
70+
p3-field = "^0.4"
71+
p3-koala-bear = "^0.4"
72+
p3-mersenne-31 = "^0.4"
73+
p3-poseidon2 = "^0.4"
74+
p3-symmetric = "^0.4"
7575
pallas = "^0.32"
7676
rand = "^0.8.5"
7777
rayon = "^1.10.0"
7878
sha2 = "^0.10.7"
7979
sha3 = "^0.10.8"
8080
zeroize = "^1.8.1"
8181
risc0-zkp = "3.0.3"
82+
libtest-mimic = "0.8.1"
83+
serde = { version = "1.0", features = ["derive"] }
84+
serde_json = "1.0"
85+
spin = { version = "0.9", default-features = false, features = ["rwlock"] }
8286

8387

8488
# Un-comment below for pulling zkp libraries from git.

circuit/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ workspace = true
1010
[dependencies]
1111
p3-field = { workspace = true }
1212
spongefish = { workspace = true, features = ["derive"] }
13+
spin = { workspace = true }
1314

1415
# Optional Plonky3/BabyBear support
1516
p3-baby-bear = { workspace = true, optional = true }

circuit/src/allocator.rs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
//! Defines the allocator and wires to be used for computing the key-derivation steps.
22
3-
use alloc::{rc::Rc, vec::Vec};
4-
use core::{cell::RefCell, usize};
3+
use alloc::{sync::Arc, vec::Vec};
54

5+
use spin::RwLock;
66
use spongefish::Unit;
77

88
/// A symbolic wire over which we perform out computation.
99
/// Wraps over a [`usize`]
10-
#[derive(Clone, Copy, Default, PartialEq, Eq, Unit)]
10+
#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, Unit)]
1111
pub struct FieldVar(pub usize);
1212

1313
impl core::fmt::Debug for FieldVar {
@@ -16,52 +16,56 @@ impl core::fmt::Debug for FieldVar {
1616
}
1717
}
1818

19-
// /// A witness-instance pair that builds at the same time the instance and the relation.
20-
// ///
21-
// /// # Semantics
22-
// ///
23-
// /// When we deref this object, we are talking about its value.
24-
// /// When we get the ref of this object, we are talking about its symbolic value.
25-
// #[derive(Clone, Debug, Unit)]
26-
// pub struct WitnessInstancePair<T: Unit>(FieldVar, T);
27-
2819
/// Allocator for field variables.
2920
///
3021
/// Creates a new wire identifier when requested,
3122
/// and keeps tracks of the wires that have been declared as public.
3223
#[derive(Clone)]
3324
pub struct VarAllocator<T> {
34-
state: Rc<RefCell<AllocatorState<T>>>,
25+
state: Arc<RwLock<AllocatorState<T>>>,
3526
}
3627

3728
struct AllocatorState<T> {
3829
vars_count: usize,
3930
public_values: Vec<(FieldVar, T)>,
4031
}
4132

42-
impl<T: Clone> VarAllocator<T> {
33+
impl<T: Clone + Unit> Default for VarAllocator<T> {
34+
fn default() -> Self {
35+
Self::new()
36+
}
37+
}
38+
39+
impl<T: Clone + Unit> VarAllocator<T> {
40+
#[must_use]
4341
pub fn new() -> Self {
42+
let zero_var = FieldVar::ZERO;
4443
Self {
45-
state: Rc::new(RefCell::new(AllocatorState {
46-
vars_count: 0,
47-
public_values: Vec::new(),
44+
state: Arc::new(RwLock::new(AllocatorState {
45+
vars_count: 1,
46+
public_values: Vec::from([(zero_var, T::ZERO)]),
4847
})),
4948
}
5049
}
5150

51+
#[must_use]
5252
pub fn new_field_var(&self) -> FieldVar {
53-
let mut state = self.state.borrow_mut();
53+
let mut state = self.state.write();
5454
let var = FieldVar(state.vars_count);
5555
state.vars_count += 1;
5656
var
5757
}
5858

59+
#[must_use]
5960
pub fn allocate_vars<const N: usize>(&self) -> [FieldVar; N] {
6061
let mut buf = [FieldVar::default(); N];
61-
buf.iter_mut().for_each(|x| *x = self.new_field_var());
62+
for x in &mut buf {
63+
*x = self.new_field_var();
64+
}
6265
buf
6366
}
6467

68+
#[must_use]
6569
pub fn allocate_vars_vec(&self, count: usize) -> Vec<FieldVar> {
6670
(0..count).map(|_| self.new_field_var()).collect()
6771
}
@@ -78,12 +82,13 @@ impl<T: Clone> VarAllocator<T> {
7882
vars
7983
}
8084

85+
#[must_use]
8186
pub fn vars_count(&self) -> usize {
82-
self.state.borrow().vars_count
87+
self.state.read().vars_count
8388
}
8489

8590
pub fn set_public_var(&self, val: FieldVar, var: T) {
86-
self.state.borrow_mut().public_values.push((val, var));
91+
self.state.write().public_values.push((val, var));
8792
}
8893

8994
pub fn set_public_vars<Val, Var>(
@@ -94,20 +99,15 @@ impl<T: Clone> VarAllocator<T> {
9499
Var: core::borrow::Borrow<FieldVar>,
95100
Val: core::borrow::Borrow<T>,
96101
{
97-
self.state.borrow_mut().public_values.extend(
102+
self.state.write().public_values.extend(
98103
vars.into_iter()
99104
.zip(vals)
100105
.map(|(var, val)| (*var.borrow(), val.borrow().clone())),
101-
)
106+
);
102107
}
103108

109+
#[must_use]
104110
pub fn public_vars(&self) -> Vec<(FieldVar, T)> {
105-
self.state
106-
.borrow()
107-
.public_values
108-
.iter()
109-
.cloned()
110-
.map(|(var, val)| (var, val.clone()))
111-
.collect()
111+
self.state.read().public_values.clone()
112112
}
113113
}

circuit/src/permutation.rs

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Builders for permutation evaluation relations.
2-
use alloc::{rc::Rc, vec::Vec};
3-
use core::cell::RefCell;
2+
use alloc::{sync::Arc, vec::Vec};
43

4+
use spin::RwLock;
55
use spongefish::{Permutation, Unit};
66

77
use crate::allocator::{FieldVar, VarAllocator};
@@ -11,7 +11,15 @@ use crate::allocator::{FieldVar, VarAllocator};
1111
#[derive(Clone)]
1212
pub struct PermutationInstanceBuilder<T, const WIDTH: usize> {
1313
allocator: VarAllocator<T>,
14-
constraints: Rc<RefCell<PermutationInstance<WIDTH>>>,
14+
constraints: Arc<RwLock<PermutationInstance<WIDTH>>>,
15+
}
16+
17+
type QueryAnswerPair<U, const WIDTH: usize> = ([U; WIDTH], [U; WIDTH]);
18+
19+
#[derive(Clone)]
20+
pub struct PermutationWitnessBuilder<P: Permutation<WIDTH>, const WIDTH: usize> {
21+
trace: Arc<RwLock<Vec<QueryAnswerPair<P::U, WIDTH>>>>,
22+
permutation: P,
1523
}
1624

1725
/// The internal state of the instance,
@@ -29,43 +37,91 @@ impl<T: Unit, const WIDTH: usize> Permutation<WIDTH> for PermutationInstanceBuil
2937
}
3038
}
3139

32-
impl<T: Clone, const WIDTH: usize> Default for PermutationInstanceBuilder<T, WIDTH> {
40+
impl<P: Permutation<WIDTH>, const WIDTH: usize> Permutation<WIDTH>
41+
for PermutationWitnessBuilder<P, WIDTH>
42+
{
43+
type U = P::U;
44+
45+
fn permute(&self, state: &[Self::U; WIDTH]) -> [Self::U; WIDTH] {
46+
self.allocate_permutation(state)
47+
}
48+
}
49+
50+
impl<T: Clone + Unit, const WIDTH: usize> Default for PermutationInstanceBuilder<T, WIDTH> {
3351
fn default() -> Self {
3452
Self::new()
3553
}
3654
}
3755

38-
impl<T: Clone, const WIDTH: usize> PermutationInstanceBuilder<T, WIDTH> {
56+
impl<T: Clone + Unit, const WIDTH: usize> PermutationInstanceBuilder<T, WIDTH> {
57+
#[must_use]
3958
pub fn with_allocator(allocator: VarAllocator<T>) -> Self {
4059
Self {
41-
allocator: allocator.clone(),
60+
allocator,
4261
constraints: Default::default(),
4362
}
4463
}
4564

65+
#[must_use]
4666
pub fn new() -> Self {
4767
Self::with_allocator(VarAllocator::new())
4868
}
4969

50-
pub fn allocator(&self) -> &VarAllocator<T> {
70+
#[must_use]
71+
pub const fn allocator(&self) -> &VarAllocator<T> {
5172
&self.allocator
5273
}
5374

75+
#[must_use]
5476
pub fn allocate_permutation(&self, &input: &[FieldVar; WIDTH]) -> [FieldVar; WIDTH] {
5577
let output = self.allocator.allocate_vars();
56-
self.constraints.borrow_mut().state.push((input, output));
78+
self.constraints.write().state.push((input, output));
5779
output
5880
}
5981

6082
pub fn add_permutation(&self, input: [FieldVar; WIDTH], output: [FieldVar; WIDTH]) {
61-
self.constraints.borrow_mut().state.push((input, output));
83+
self.constraints.write().state.push((input, output));
6284
}
6385

86+
#[must_use]
6487
pub fn constraints(&self) -> impl AsRef<[([FieldVar; WIDTH], [FieldVar; WIDTH])]> {
65-
self.constraints.borrow_mut().state.clone()
88+
self.constraints.read().state.clone()
6689
}
6790

91+
#[must_use]
6892
pub fn public_vars(&self) -> Vec<(FieldVar, T)> {
6993
self.allocator.public_vars()
7094
}
7195
}
96+
97+
impl<P: Permutation<WIDTH>, const WIDTH: usize> From<P> for PermutationWitnessBuilder<P, WIDTH> {
98+
fn from(value: P) -> Self {
99+
Self::new(value)
100+
}
101+
}
102+
103+
impl<P: Permutation<WIDTH>, const WIDTH: usize> PermutationWitnessBuilder<P, WIDTH> {
104+
#[must_use]
105+
pub fn new(permutation: P) -> Self {
106+
Self {
107+
trace: Default::default(),
108+
permutation,
109+
}
110+
}
111+
112+
#[must_use]
113+
pub fn allocate_permutation(&self, input: &[P::U; WIDTH]) -> [P::U; WIDTH] {
114+
let output = self.permutation.permute(input);
115+
self.add_permutation(input, &output);
116+
output
117+
}
118+
119+
pub fn add_permutation(&self, input: &[P::U; WIDTH], output: &[P::U; WIDTH]) {
120+
self.trace.write().push((input.clone(), output.clone()));
121+
}
122+
123+
#[must_use]
124+
pub fn trace(&self) -> impl AsRef<[QueryAnswerPair<P::U, WIDTH>]> {
125+
self.trace.read().clone()
126+
}
127+
}

circuit/tests/builder.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use p3_baby_bear::BabyBear;
22
use spongefish::{DuplexSponge, DuplexSpongeInterface};
3-
43
use spongefish_circuit::permutation::PermutationInstanceBuilder;
54

65
#[test]
@@ -43,6 +42,9 @@ pub fn test_xof() {
4342
assert_eq!(inst_builder.constraints().as_ref().len(), 2);
4443

4544
// the instance is a set of:
46-
println!("input/otutput vars: {:?}", inst_builder.constraints().as_ref());
45+
println!(
46+
"input/otutput vars: {:?}",
47+
inst_builder.constraints().as_ref()
48+
);
4749
println!("public vars: {:?}", inst_builder.allocator().public_vars());
4850
}

derive/src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ fn generate_encoding_impl(input: &DeriveInput) -> TokenStream2 {
4343
};
4444

4545
let bound = quote!(::spongefish::Encoding<[u8]>);
46-
let generics = add_trait_bounds_for_fields(input.generics.clone(), &encoding_bounds, &bound);
46+
let generics =
47+
add_trait_bounds_for_fields(input.generics.clone(), &encoding_bounds, &bound);
4748
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
4849

4950
quote! {
@@ -177,7 +178,8 @@ fn generate_decoding_impl(input: &DeriveInput) -> TokenStream2 {
177178
};
178179

179180
let bound = quote!(::spongefish::Decoding<[u8]>);
180-
let generics = add_trait_bounds_for_fields(input.generics.clone(), &decoding_bounds, &bound);
181+
let generics =
182+
add_trait_bounds_for_fields(input.generics.clone(), &decoding_bounds, &bound);
181183
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
182184

183185
quote! {
@@ -252,7 +254,8 @@ fn generate_narg_deserialize_impl(input: &DeriveInput) -> TokenStream2 {
252254
};
253255

254256
let bound = quote!(::spongefish::NargDeserialize);
255-
let generics = add_trait_bounds_for_fields(input.generics.clone(), &deserialize_bounds, &bound);
257+
let generics =
258+
add_trait_bounds_for_fields(input.generics.clone(), &deserialize_bounds, &bound);
256259
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
257260

258261
quote! {

spongefish/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ pallas = { workspace = true }
9393
ark-vesta = { workspace = true }
9494
sha3 = { workspace = true }
9595
ark-secp256k1 = { workspace = true }
96+
libtest-mimic = { workspace = true }
97+
serde = { workspace = true }
98+
serde_json = { workspace = true }
9699

97100
[package.metadata.docs.rs]
98101
all-features = true

spongefish/src/drivers/p3_baby_bear.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl Decoding<[u8]> for BabyBear {
3838

3939
fn decode(buf: Self::Repr) -> Self {
4040
let n = u64::from_le_bytes(buf);
41-
return BabyBear::new((n % (BabyBear::ORDER_U32 as u64)) as u32);
41+
Self::new((n % u64::from(Self::ORDER_U32)) as u32)
4242
}
4343
}
4444

@@ -53,11 +53,11 @@ impl NargDeserialize for BabyBear {
5353
let value = u32::from_le_bytes(repr);
5454

5555
// Check that the value is in the valid range
56-
if value >= BabyBear::ORDER_U32 {
56+
if value >= Self::ORDER_U32 {
5757
return Err(VerificationError);
5858
}
5959

60-
Ok(BabyBear::new(value))
60+
Ok(Self::new(value))
6161
}
6262
}
6363

spongefish/src/tests.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use alloc::string::String;
2+
23
use rand::RngCore;
34

45
#[test]
@@ -77,7 +78,7 @@ fn domain_separator_accepts_variable_sessions() {
7778
assert_eq!(literal_session, from_str);
7879

7980
let session_owned = String::from("shared session");
80-
let from_owned = crate::domain_separator!("variable sessions"; session_owned.clone())
81+
let from_owned = crate::domain_separator!("variable sessions"; session_owned)
8182
.instance(&instance)
8283
.session
8384
.expect("owned session missing");

spongefish/tests/derive_generics.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ fn codec_derive_handles_generic_types() {
2727
assert_eq!(roundtrip.value, tagged.value);
2828
assert!(buf.is_empty());
2929

30+
#[allow(clippy::items_after_statements)]
3031
fn assert_codec<T: Codec>(_: &T) {}
3132
assert_codec(&tagged);
3233
}

0 commit comments

Comments
 (0)