Skip to content

Commit aa0d946

Browse files
committed
add optimizations
1 parent f2f103f commit aa0d946

4 files changed

Lines changed: 48 additions & 19 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ num-bigint = { version = "0.4.6", features = ["serde"] }
2828
num-traits = "0.2.19"
2929
parking_lot = "0.12"
3030
rand = "0.8"
31+
rayon = "1.10"
3132
serde = { version = "1", features = ["derive"] }
3233
serde_cbor = "0.11.2"
3334
serde_json = { version = "1", features = ["raw_value"] }

blssig/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ bls12_381.workspace = true
1616
filecoin-f3-gpbft = { path = "../gpbft", version = "0.1.0" }
1717
hashlink.workspace = true
1818
parking_lot.workspace = true
19+
rayon.workspace = true
1920
thiserror.workspace = true
2021

2122
[dev-dependencies]

blssig/src/bdn/mod.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use blake2::Blake2xs;
1414
use blake2::digest::{ExtendableOutput, Update, XofReader};
1515
use bls_signatures::{PublicKey, Serialize, Signature};
1616
use bls12_381::{G1Projective, G2Projective, Scalar};
17+
use rayon::prelude::*;
1718

1819
/// BDN aggregation context for managing signature and public key aggregation
1920
pub struct BDNAggregation {
@@ -118,13 +119,15 @@ impl BDNAggregation {
118119
}
119120

120121
pub fn calc_terms(pub_keys: &[PublicKey], coefficients: &[Scalar]) -> Vec<PublicKey> {
121-
let mut terms = vec![];
122-
for (i, pub_key) in pub_keys.iter().enumerate() {
123-
let pub_key_point: G1Projective = (*pub_key).into();
124-
let pub_c = pub_key_point * coefficients[i];
125-
let term = pub_c + pub_key_point;
126-
terms.push(term.into());
127-
}
128-
terms
122+
pub_keys
123+
.par_iter()
124+
.enumerate()
125+
.map(|(i, pub_key)| {
126+
let pub_key_point: G1Projective = (*pub_key).into();
127+
let pub_c = pub_key_point * coefficients[i];
128+
let term = pub_c + pub_key_point;
129+
term.into()
130+
})
131+
.collect()
129132
}
130133
}

blssig/src/verifier/mod.rs

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2019-2024 ChainSafe Systems
22
// SPDX-License-Identifier: Apache-2.0, MIT
33

4+
use std::sync::Arc;
45
use bls_signatures::{PublicKey, Serialize, Signature, verify_messages};
56
use filecoin_f3_gpbft::PubKey;
67
use filecoin_f3_gpbft::api::Verifier;
@@ -43,11 +44,14 @@ pub enum BLSError {
4344
///
4445
/// This verifier implements the same scheme used by `go-f3/blssig`, with:
4546
/// - BLS12_381 curve
46-
/// - G1 for public keys, G2 for signatures
47+
/// - G1 for public keys, G2 for signatures
4748
/// - BDN aggregation for rogue-key attack prevention
4849
pub struct BLSVerifier {
4950
/// Cache for deserialized public key points to avoid expensive repeated operations
5051
point_cache: RwLock<LruCache<Vec<u8>, PublicKey>>,
52+
/// Cache for current power table's BDN aggregation
53+
/// Only caches the current since power tables don't tend to repeat after rotation
54+
bdn_cache: RwLock<Option<(Vec<PubKey>, Arc<BDNAggregation>)>>,
5155
}
5256

5357
impl Default for BLSVerifier {
@@ -70,6 +74,7 @@ impl BLSVerifier {
7074
Self {
7175
// key size: 48, value size: 196, total estimated: 1.83 MiB
7276
point_cache: RwLock::new(LruCache::new(MAX_POINT_CACHE_SIZE)),
77+
bdn_cache: RwLock::new(None),
7378
}
7479
}
7580

@@ -120,6 +125,34 @@ impl BLSVerifier {
120125
fn deserialize_signature(&self, sig: &[u8]) -> Result<Signature, BLSError> {
121126
Signature::from_bytes(sig).map_err(BLSError::SignatureDeserialization)
122127
}
128+
129+
/// Gets a cached BDN aggregation or creates and caches it
130+
fn get_or_cache_bdn(&self, power_table: &[PubKey]) -> Result<Arc<BDNAggregation>, BLSError> {
131+
// Check cache first
132+
if let Some((cached_power_table, cached_bdn)) = self.bdn_cache.read().as_ref() {
133+
if cached_power_table == power_table {
134+
return Ok(cached_bdn.clone());
135+
}
136+
}
137+
138+
// Deserialize and create new BDN aggregation
139+
let mut typed_pub_keys = vec![];
140+
for pub_key in power_table {
141+
if pub_key.0.len() != BLS_PUBLIC_KEY_LENGTH {
142+
return Err(BLSError::InvalidPublicKeyLength(pub_key.0.len()));
143+
}
144+
typed_pub_keys.push(self.get_or_cache_public_key(&pub_key.0)?);
145+
}
146+
147+
let bdn = Arc::new(BDNAggregation::new(typed_pub_keys)?);
148+
149+
// Cache it
150+
self.bdn_cache
151+
.write()
152+
.replace((power_table.to_vec(), bdn.clone()));
153+
154+
Ok(bdn)
155+
}
123156
}
124157

125158
impl Verifier for BLSVerifier {
@@ -178,16 +211,7 @@ impl Verifier for BLSVerifier {
178211
return Err(BLSError::EmptySigners);
179212
}
180213

181-
let mut typed_pub_keys = vec![];
182-
for pub_key in power_table {
183-
if pub_key.0.len() != BLS_PUBLIC_KEY_LENGTH {
184-
return Err(BLSError::InvalidPublicKeyLength(pub_key.0.len()));
185-
}
186-
187-
typed_pub_keys.push(self.get_or_cache_public_key(&pub_key.0)?);
188-
}
189-
190-
let bdn = BDNAggregation::new(typed_pub_keys)?;
214+
let bdn = self.get_or_cache_bdn(power_table)?;
191215
let agg_pub_key = bdn.aggregate_pub_keys(signer_indices)?;
192216
let agg_pub_key_bytes = PubKey(agg_pub_key.as_bytes().to_vec());
193217
self.verify_single(&agg_pub_key_bytes, payload, agg_sig)

0 commit comments

Comments
 (0)