Skip to content

Commit 5bded03

Browse files
committed
feat: aggregate and verify aggregate attempt
Signed-off-by: pedro bufulin <pedro@semiotic.ai>
1 parent 5ea175a commit 5bded03

File tree

2 files changed

+93
-10
lines changed

2 files changed

+93
-10
lines changed

h2s2/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
pub mod holographic_homomorphic_signature_scheme;
2-
pub mod nc1;
2+
pub mod ncs;

h2s2/src/nc1.rs renamed to h2s2/src/ncs.rs

Lines changed: 92 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn hash_to_g1<P: Pairing, D: Digest>(message_data: Vec<u8>) -> P::G1Affine {
2323
g1_point.unwrap()
2424
}
2525

26-
pub struct NC1<P: Pairing, D: Digest> {
26+
pub struct NCS<P: Pairing, D: Digest> {
2727
_pairing: PhantomData<P>,
2828
_hash: PhantomData<D>,
2929
}
@@ -40,7 +40,7 @@ pub struct H2S2Parameters<P: Pairing> {
4040
}
4141

4242
impl<P: Pairing, D: Digest + Send + Sync> HolographicHomomorphicSignatureScheme<P, D>
43-
for NC1<P, D>
43+
for NCS<P, D>
4444
{
4545
type Parameters = H2S2Parameters<P>;
4646
type PublicKey = P::G2;
@@ -49,6 +49,7 @@ impl<P: Pairing, D: Digest + Send + Sync> HolographicHomomorphicSignatureScheme<
4949
type Message = P::ScalarField;
5050
type Weight = usize;
5151

52+
// n represents the max_lanes amount
5253
fn setup<R: Rng>(rng: &mut R, n: usize) -> Result<Self::Parameters, Box<dyn Error>> {
5354
// Generate the G2 generator
5455
let g2_generator = P::G2::rand(rng);
@@ -191,19 +192,54 @@ impl<P: Pairing, D: Digest + Send + Sync> HolographicHomomorphicSignatureScheme<
191192
fn verify_aggregate(
192193
pp: &Self::Parameters,
193194
pk: &Self::PublicKey,
195+
// TODO: is the tag necessary for the verify_aggregate?1
194196
tag: &[u8],
195197
message_aggregate: &[Self::Message],
196198
hash_aggregate: &P::G1,
197199
signature: &Self::Signature,
198200
) -> Result<bool, Box<dyn Error>> {
199-
Ok(true)
201+
// Compute the message commitment for the aggregated message
202+
let mut message_commitment = P::G1::zero();
203+
for (i, m) in message_aggregate.iter().enumerate() {
204+
// Multiply each message part with its respective generator
205+
let mut message_point = pp.g1_generators[i].clone();
206+
message_point = message_point.mul(*m);
207+
message_commitment += message_point;
208+
}
209+
210+
// Combine the hash aggregate with the message commitment
211+
let combined_point = *hash_aggregate + message_commitment;
212+
213+
// Compute the pairings for verification
214+
let lhs_pairing = P::pairing(*signature, pp.g2_generator);
215+
let rhs_pairing = P::pairing(combined_point, *pk);
216+
217+
// Verify that the pairings match
218+
Ok(lhs_pairing == rhs_pairing)
200219
}
201220

202221
fn evaluate(
203222
signatures: &[Self::Signature],
204223
weights: &[Self::Weight],
205224
) -> Result<Self::Signature, Box<dyn Error>> {
206-
Ok(P::G1::default())
225+
// Ensure the inputs are valid
226+
if signatures.len() != weights.len() {
227+
return Err("Signatures and weights must have the same length".into());
228+
}
229+
230+
// Initialize the aggregate signature as the identity element in G1
231+
let mut aggregate_signature = P::G1::zero();
232+
233+
// Iterate over signatures and weights
234+
for (sig, &weight) in signatures.iter().zip(weights.iter()) {
235+
// Convert the weight to a scalar field element
236+
let weight_scalar = P::ScalarField::from(weight as u64);
237+
238+
// Perform the weighted addition to the aggregate signature
239+
aggregate_signature += sig.mul(weight_scalar);
240+
}
241+
242+
Ok(aggregate_signature)
207243
}
208244
}
209245

@@ -219,7 +255,7 @@ mod tests {
219255

220256
static PARAMS: Lazy<H2S2Parameters<Bn254>> = Lazy::new(|| {
221257
let mut rng = test_rng();
222-
NC1::<Bn254, Blake2b512>::setup(&mut rng, N).expect("Setup failed")
258+
NCS::<Bn254, Blake2b512>::setup(&mut rng, N).expect("Setup failed")
223259
});
224260

225261
#[test]
@@ -243,7 +279,7 @@ mod tests {
243279
let params = &*PARAMS;
244280
let allocation_id = b"example_allocation_id";
245281

246-
let hash_aggregate = NC1::<Bn254, Blake2b512>::precompute(&params, allocation_id, N)
282+
let hash_aggregate = NCS::<Bn254, Blake2b512>::precompute(&params, allocation_id, N)
247283
.expect("Precompute failed");
248284

249285
println!("Precomputed Hash Aggregate: {:?}", hash_aggregate);
@@ -253,18 +289,19 @@ mod tests {
253289
let params = &*PARAMS;
254290
let allocation_id = b"example_allocation_id";
255291
let index = b"lane_1";
256-
let message = vec![ark_bn254::Fr::from(42u64), ark_bn254::Fr::from(7u64)];
292+
let message: Vec<ark_ff::Fp<ark_ff::MontBackend<ark_bn254::FrConfig, 4>, 4>> =
293+
vec![ark_bn254::Fr::from(42u64), ark_bn254::Fr::from(7u64)];
257294

258295
let sk = params.secret_key.unwrap();
259296
let pk = params.public_key;
260297

261298
// Sign the message
262299
let signature =
263-
NC1::<Bn254, Blake2b512>::sign(&params, &sk, allocation_id, index, &message)
300+
NCS::<Bn254, Blake2b512>::sign(&params, &sk, allocation_id, index, &message)
264301
.expect("Sign failed");
265302

266303
// Verify the signature
267-
let is_valid = NC1::<Bn254, Blake2b512>::verify(
304+
let is_valid = NCS::<Bn254, Blake2b512>::verify(
268305
&params,
269306
&pk,
270307
allocation_id,
@@ -277,4 +314,50 @@ mod tests {
277314
assert!(is_valid, "Signature verification failed!");
278315
println!("Signature successfully verified!");
279316
}
317+
318+
#[test]
319+
fn test_aggregate() {
320+
let params = &*PARAMS;
321+
let sk = params.secret_key.unwrap();
322+
let pk = params.public_key;
323+
let allocation_id = b"example_allocation_id";
324+
let index = b"lane_1";
325+
let messages: Vec<_> = vec![ark_bn254::Fr::from(42u64), ark_bn254::Fr::from(7u64)];
326+
327+
// Generate individual signatures
328+
let signatures: Vec<_> = (0..N)
329+
.map(|_| {
330+
NCS::<Bn254, Blake2b512>::sign(&params, &sk, allocation_id, index, &messages)
331+
.expect("Sign failed")
332+
})
333+
.collect();
334+
335+
// Generate weights (all set to 1)
336+
let weights: Vec<usize> = vec![1; N];
337+
338+
// Aggregate the signatures
339+
let aggregated_signature =
340+
NCS::<Bn254, Blake2b512>::evaluate(&signatures, &weights).expect("Evaluate failed");
341+
342+
// Precompute the hash aggregate
343+
let hash_aggregate = NCS::<Bn254, Blake2b512>::precompute(&params, allocation_id, N)
344+
.expect("Precompute failed");
345+
346+
// Aggregate the messages (sum all messages into one scalar)
347+
let message_aggregate: ark_bn254::Fr = messages.iter().copied().sum();
348+
349+
// Verify the aggregated signature
350+
let is_valid = NCS::<Bn254, Blake2b512>::verify_aggregate(
351+
&params,
352+
&pk,
353+
allocation_id,
354+
&[message_aggregate],
355+
&hash_aggregate,
356+
&aggregated_signature,
357+
)
358+
.expect("Verify failed");
359+
360+
assert!(is_valid, "Aggregated signature verification failed!");
361+
println!("Aggregated signature successfully verified!");
362+
}
280363
}

0 commit comments

Comments
 (0)