Skip to content

Commit 382a712

Browse files
committed
fix BDNAggregate::aggregate_sigs
1 parent f2d5f47 commit 382a712

File tree

3 files changed

+64
-9
lines changed

3 files changed

+64
-9
lines changed

blssig/src/bdn/mod.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use rayon::prelude::*;
1818

1919
/// BDN aggregation context for managing signature and public key aggregation
2020
pub struct BDNAggregation {
21-
pub(crate) pub_keys: Vec<PublicKey>,
2221
pub(crate) coefficients: Vec<Scalar>,
2322
pub(crate) terms: Vec<PublicKey>,
2423
}
@@ -33,25 +32,33 @@ impl BDNAggregation {
3332
let terms = Self::calc_terms(&pub_keys, &coefficients);
3433

3534
Ok(Self {
36-
pub_keys,
3735
coefficients,
3836
terms,
3937
})
4038
}
4139

4240
/// Aggregates signatures using BDN aggregation with coefficients.
43-
/// Computes: sum((coef_i + 1) * sig_i)
44-
pub fn aggregate_sigs(&self, sigs: Vec<Signature>) -> Result<Signature, BLSError> {
45-
if sigs.len() != self.pub_keys.len() {
41+
/// Computes: sum((coef_i + 1) * sig_i) for signatures at the given indices
42+
pub fn aggregate_sigs(
43+
&self,
44+
indices: &[u64],
45+
sigs: &[Signature],
46+
) -> Result<Signature, BLSError> {
47+
if sigs.len() != indices.len() {
4648
return Err(BLSError::LengthMismatch {
47-
pub_keys: self.pub_keys.len(),
49+
pub_keys: indices.len(),
4850
sigs: sigs.len(),
4951
});
5052
}
5153

5254
let mut agg_point = G2Projective::identity();
53-
for (i, sig) in sigs.iter().enumerate() {
54-
let coef = self.coefficients[i];
55+
for (sig, &idx) in sigs.iter().zip(indices.iter()) {
56+
let idx = idx as usize;
57+
if idx >= self.coefficients.len() {
58+
return Err(BLSError::SignerIndexOutOfRange(idx));
59+
}
60+
61+
let coef = self.coefficients[idx];
5562
let sig_point: G2Projective = (*sig).into();
5663
let sig_c = sig_point * coef;
5764
let sig_c = sig_c + sig_point;

blssig/src/verifier/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ impl Verifier for BLSVerifier {
193193
}
194194

195195
let bdn = BDNAggregation::new(typed_pub_keys)?;
196-
let agg_sig = bdn.aggregate_sigs(typed_sigs)?;
196+
let indices: Vec<u64> = (0..typed_sigs.len() as u64).collect();
197+
let agg_sig = bdn.aggregate_sigs(&indices, &typed_sigs)?;
197198
Ok(agg_sig.as_bytes())
198199
}
199200

blssig/src/verifier/tests.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0, MIT
33

44
use super::BLSVerifier;
5+
use crate::bdn::BDNAggregation;
56
use bls_signatures::{PrivateKey, Serialize};
67
use filecoin_f3_gpbft::PubKey;
78
use filecoin_f3_gpbft::api::Verifier;
@@ -68,3 +69,49 @@ fn test_invalid_signature() {
6869
"corrupted signature should fail verification"
6970
);
7071
}
72+
73+
#[test]
74+
fn test_aggregate_signature_verification() {
75+
let verifier = BLSVerifier::new();
76+
let message = b"consensus message";
77+
78+
// Generate 10 validators for the power table
79+
let mut signers = Vec::new();
80+
let mut power_table = Vec::new();
81+
for _ in 0..10 {
82+
let private_key = PrivateKey::generate(&mut rand::thread_rng());
83+
let signer = BLSSigner::new(private_key);
84+
power_table.push(signer.public_key().clone());
85+
signers.push(signer);
86+
}
87+
88+
// Only 5 validators sign (indices 0, 2, 4, 6, 8)
89+
let signers_subset = vec![0u64, 2, 4, 6, 8];
90+
let sigs: Vec<Vec<u8>> = signers_subset
91+
.iter()
92+
.map(|&i| signers[i as usize].sign(message))
93+
.collect();
94+
95+
// Aggregate using BDN with full power table
96+
let typed_pub_keys: Vec<_> = power_table
97+
.iter()
98+
.map(|pk| bls_signatures::PublicKey::from_bytes(&pk.0).unwrap())
99+
.collect();
100+
let typed_sigs: Vec<_> = sigs
101+
.iter()
102+
.map(|sig| bls_signatures::Signature::from_bytes(sig).unwrap())
103+
.collect();
104+
105+
let bdn = BDNAggregation::new(typed_pub_keys).expect("BDN creation should succeed");
106+
let agg_sig = bdn
107+
.aggregate_sigs(&signers_subset, &typed_sigs)
108+
.expect("aggregation should succeed");
109+
110+
// Verify aggregate using full power table and signer indices
111+
let result =
112+
verifier.verify_aggregate(message, &agg_sig.as_bytes(), &power_table, &signers_subset);
113+
assert!(
114+
result.is_ok(),
115+
"aggregate signature verification should succeed"
116+
);
117+
}

0 commit comments

Comments
 (0)