Skip to content

Commit

Permalink
Add Aggregator trait (#21)
Browse files Browse the repository at this point in the history
* add aggregator trait; rename v1/v2 SignatureAggregator; inc major rev since API is changing

* fmt fixes

* add traits::Signer::new so we can have a consistent way of creating Signers

* split Aggregator::new into a new that can't fail, and an init that can, since we can't return a result with Self from a trait

* remove most non-snake case variables, only leave R which is the default terminology for schnorr proofs

* remove another unnecessary snake case annotation
  • Loading branch information
xoloki authored Sep 25, 2023
1 parent ab0eaef commit 9459a78
Show file tree
Hide file tree
Showing 7 changed files with 292 additions and 224 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wsts"
version = "3.0.0"
version = "4.0.0"
edition = "2021"
authors = ["Joey Yandle <[email protected]>"]
license = "Apache-2.0"
Expand Down
13 changes: 6 additions & 7 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,25 @@ use crate::compute::challenge;
use crate::schnorr::ID;

#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(non_snake_case)]
/// A commitment to a polynonial, with a Schnorr proof of ownership bound to the ID
pub struct PolyCommitment {
/// The party ID with a schnorr proof
pub id: ID,
/// The public polynomial which commits to the secret polynomial
pub A: Vec<Point>,
pub poly: Vec<Point>,
}

impl PolyCommitment {
/// Verify the wrapped schnorr ID
pub fn verify(&self) -> bool {
self.id.verify(&self.A[0])
self.id.verify(&self.poly[0])
}
}

impl Display for PolyCommitment {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "{}", self.id.id)?;
for p in &self.A {
for p in &self.poly {
write!(f, " {}", p)?;
}
Ok(())
Expand Down Expand Up @@ -183,9 +182,9 @@ impl<'a> CheckPrivateShares<'a> {
/// Construct a new CheckPrivateShares object
pub fn new(id: Scalar, shares: &HashMap<u32, Scalar>, polys: &'a [PolyCommitment]) -> Self {
let n: u32 = shares.len().try_into().unwrap();
let t: u32 = polys[0].A.len().try_into().unwrap();
let t: u32 = polys[0].poly.len().try_into().unwrap();
let x = id;
let mut powers = Vec::with_capacity(polys[0].A.len());
let mut powers = Vec::with_capacity(polys[0].poly.len());
let mut pow = Scalar::one();

for _ in 0..t {
Expand Down Expand Up @@ -228,7 +227,7 @@ impl<'a> MultiMult for CheckPrivateShares<'a> {
let j = i / u;
let k = i % u;

&self.polys[j].A[k]
&self.polys[j].poly[k]
} else {
&G
}
Expand Down
10 changes: 6 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rand_core::OsRng;
use std::{env, time};

use wsts::{common::test_helpers::gen_signer_ids, v1, v2};
use wsts::{common::test_helpers::gen_signer_ids, traits::Aggregator, v1, v2};

#[allow(non_snake_case)]
fn main() {
Expand Down Expand Up @@ -41,15 +41,16 @@ fn main() {
let dkg_time = dkg_start.elapsed();
let mut signers = signers[..(K * 3 / 4).try_into().unwrap()].to_vec();

let mut aggregator = v1::SignatureAggregator::new(N, T, A).expect("aggregator ctor failed");
let mut aggregator = v1::Aggregator::new(N, T);
aggregator.init(A).expect("aggregator init failed");

let party_sign_start = time::Instant::now();
let (nonces, sig_shares) = v1::test_helpers::sign(msg, &mut signers, &mut rng);
let party_sign_time = party_sign_start.elapsed();

let group_sign_start = time::Instant::now();
let _sig = aggregator
.sign(msg, &nonces, &sig_shares)
.sign(msg, &nonces, &sig_shares, &[])
.expect("v1 group sign failed");
let group_sign_time = group_sign_start.elapsed();

Expand All @@ -76,7 +77,8 @@ fn main() {
let dkg_time = dkg_start.elapsed();
let mut signers = signers[..(K * 3 / 4).try_into().unwrap()].to_vec();

let mut aggregator = v2::SignatureAggregator::new(N, T, A).expect("aggregator ctor failed");
let mut aggregator = v2::Aggregator::new(N, T);
aggregator.init(A).expect("aggregator init failed");

let party_sign_start = time::Instant::now();
let (nonces, sig_shares, key_ids) = v2::test_helpers::sign(msg, &mut signers, &mut rng);
Expand Down
12 changes: 6 additions & 6 deletions src/taproot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ pub mod test_helpers {
mod test {
use super::{test_helpers, SchnorrProof};

use crate::{compute, traits::Signer, v1, v2};
use crate::{compute, traits::Aggregator, traits::Signer, v1, v2};
use rand_core::OsRng;

#[test]
Expand Down Expand Up @@ -192,11 +192,11 @@ mod test {
};

let mut S = [signers[0].clone(), signers[1].clone(), signers[3].clone()].to_vec();
let mut sig_agg =
v1::SignatureAggregator::new(N, T, A.clone()).expect("aggregator ctor failed");
let mut sig_agg = v1::Aggregator::new(N, T);
sig_agg.init(A.clone()).expect("aggregator init failed");
let tweaked_public_key = compute::tweaked_public_key(&sig_agg.poly[0], merkle_root);
let (nonces, sig_shares) = test_helpers::sign(&msg, &mut S, &mut rng, merkle_root);
let proof = match sig_agg.sign_taproot(&msg, &nonces, &sig_shares, merkle_root) {
let proof = match sig_agg.sign_taproot(&msg, &nonces, &sig_shares, &[], merkle_root) {
Err(e) => panic!("Aggregator sign failed: {:?}", e),
Ok(proof) => proof,
};
Expand Down Expand Up @@ -255,8 +255,8 @@ mod test {

let mut S = [signers[0].clone(), signers[1].clone(), signers[3].clone()].to_vec();
let key_ids = S.iter().flat_map(|s| s.get_key_ids()).collect::<Vec<u32>>();
let mut sig_agg =
v2::SignatureAggregator::new(Nk, T, A.clone()).expect("aggregator ctor failed");
let mut sig_agg = v2::Aggregator::new(Nk, T);
sig_agg.init(A.clone()).expect("aggregator init failed");
let tweaked_public_key = compute::tweaked_public_key(&sig_agg.poly[0], merkle_root);
let (nonces, sig_shares) = test_helpers::sign(&msg, &mut S, &mut rng, merkle_root);
let proof = match sig_agg.sign_taproot(&msg, &nonces, &sig_shares, &key_ids, merkle_root) {
Expand Down
45 changes: 42 additions & 3 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,23 @@ use p256k1::{point::Point, scalar::Scalar};
use rand_core::{CryptoRng, RngCore};

use crate::{
common::{PolyCommitment, PublicNonce, SignatureShare},
errors::DkgError,
common::{PolyCommitment, PublicNonce, Signature, SignatureShare},
errors::{AggregatorError, DkgError},
taproot::SchnorrProof,
};

/// A trait which provides a common interface for `v1` and `v2`
/// A trait which provides a common `Signer` interface for `v1` and `v2`
pub trait Signer {
/// Create a new `Signer`
fn new<RNG: RngCore + CryptoRng>(
party_id: u32,
key_ids: &[u32],
num_signers: u32,
num_keys: u32,
threshold: u32,
rng: &mut RNG,
) -> Self;

/// Get the signer ID for this signer
fn get_id(&self) -> u32;

Expand Down Expand Up @@ -61,3 +72,31 @@ pub trait Signer {
merkle_root: Option<[u8; 32]>,
) -> Vec<SignatureShare>;
}

/// A trait which provides a common `Aggregator` interface for `v1` and `v2`
pub trait Aggregator {
/// Construct an Aggregator with the passed parameters
fn new(num_keys: u32, threshold: u32) -> Self;

/// Initialize an Aggregator with the passed polynomial commitments
fn init(&mut self, poly_comms: Vec<PolyCommitment>) -> Result<(), AggregatorError>;

/// Check and aggregate the signature shares into a `Signature`
fn sign(
&mut self,
msg: &[u8],
nonces: &[PublicNonce],
sig_shares: &[SignatureShare],
key_ids: &[u32],
) -> Result<Signature, AggregatorError>;

/// Check and aggregate the signature shares into a `SchnorrProof`
fn sign_taproot(
&mut self,
msg: &[u8],
nonces: &[PublicNonce],
sig_shares: &[SignatureShare],
key_ids: &[u32],
merkle_root: Option<[u8; 32]>,
) -> Result<SchnorrProof, AggregatorError>;
}
Loading

0 comments on commit 9459a78

Please sign in to comment.