Skip to content

Commit

Permalink
add common::Polynomial; use Vec<Scalar> for private polynomial
Browse files Browse the repository at this point in the history
  • Loading branch information
xoloki committed Oct 8, 2024
1 parent 91a37c8 commit 307fe19
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 30 deletions.
22 changes: 22 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,28 @@ use crate::{
/// A merkle root is a 256 bit hash
pub type MerkleRoot = [u8; 32];

/// A Polynomial where the parameters are not necessarily the same type as the args
pub struct Polynomial<Param, Arg> {
/// parameters for the polynomial
pub data: Vec<Param>,
_x: std::marker::PhantomData<Arg>,
}

impl<
Param: Clone + Zero + Add + std::ops::AddAssign<<Arg as std::ops::Mul<Param>>::Output>,
Arg: Clone + std::ops::Mul<Param>,
> Polynomial<Param, Arg>
{
/// evaluate the polynomial with the passed arg
pub fn eval(&self, x: Arg) -> Param {
let mut ret = Param::zero();
for i in 0..self.data.len() {
ret += x.clone() * self.data[i].clone();
}
ret
}
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
/// A commitment to a polynonial, with a Schnorr proof of ownership bound to the ID
pub struct PolyCommitment {
Expand Down
10 changes: 10 additions & 0 deletions src/compute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ pub fn poly(x: &Scalar, f: &Vec<Point>) -> Result<Point, PointError> {
Point::multimult(s, f.clone())
}

/// Evaluate the public polynomial `f` at scalar `x` using multi-exponentiation
#[allow(clippy::ptr_arg)]
pub fn private_poly(x: Scalar, f: &Vec<Scalar>) -> Scalar {
let mut sum = Scalar::zero();
for i in 0..f.len() {
sum += x * f[i];
}
sum
}

/// Create a BIP340 compliant tagged hash by double hashing the tag
pub fn tagged_hash(tag: &str) -> Sha256 {
let mut hasher = Sha256::new();
Expand Down
2 changes: 2 additions & 0 deletions src/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ impl Signable for Message {
pub struct DkgBegin {
/// DKG round ID
pub dkg_id: u64,
/// Keep the constant factor so DKG will produce the same key
pub keep_constant: bool,
}

impl Signable for DkgBegin {
Expand Down
1 change: 1 addition & 0 deletions src/state_machine/coordinator/fire.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ impl<Aggregator: AggregatorTrait> Coordinator<Aggregator> {
);
let dkg_begin = DkgBegin {
dkg_id: self.current_dkg_id,
keep_constant: false,
};
let dkg_begin_packet = Packet {
sig: dkg_begin
Expand Down
1 change: 1 addition & 0 deletions src/state_machine/coordinator/frost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ impl<Aggregator: AggregatorTrait> Coordinator<Aggregator> {
);
let dkg_begin = DkgBegin {
dkg_id: self.current_dkg_id,
keep_constant: false,
};

let dkg_begin_packet = Packet {
Expand Down
6 changes: 3 additions & 3 deletions src/state_machine/signer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,14 +260,14 @@ impl<SignerType: SignerTrait> Signer<SignerType> {
}

/// Reset internal state
pub fn reset<T: RngCore + CryptoRng>(&mut self, dkg_id: u64, rng: &mut T) {
pub fn reset<T: RngCore + CryptoRng>(&mut self, dkg_id: u64, keep_constant: bool, rng: &mut T) {
self.dkg_id = dkg_id;
self.commitments.clear();
self.decrypted_shares.clear();
self.decryption_keys.clear();
self.invalid_private_shares.clear();
self.public_nonces.clear();
self.signer.reset_polys(rng);
self.signer.reset_polys(keep_constant, rng);
self.dkg_public_shares.clear();
self.dkg_private_shares.clear();
self.dkg_private_begin_msg = None;
Expand Down Expand Up @@ -594,7 +594,7 @@ impl<SignerType: SignerTrait> Signer<SignerType> {
fn dkg_begin(&mut self, dkg_begin: &DkgBegin) -> Result<Vec<Message>, Error> {
let mut rng = OsRng;

self.reset(dkg_begin.dkg_id, &mut rng);
self.reset(dkg_begin.dkg_id, dkg_begin.keep_constant, &mut rng);
self.move_to(State::DkgPublicDistribute)?;

//let _party_state = self.signer.save();
Expand Down
5 changes: 2 additions & 3 deletions src/traits.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use core::{cmp::PartialEq, fmt::Debug};
use hashbrown::HashMap;
use polynomial::Polynomial;
use rand_core::{CryptoRng, RngCore};
use serde::{Deserialize, Serialize};

Expand All @@ -15,7 +14,7 @@ use crate::{
/// The saved state required to reconstruct a party
pub struct PartyState {
/// The party's private polynomial
pub polynomial: Option<Polynomial<Scalar>>,
pub polynomial: Option<Vec<Scalar>>,
/// The key IDS and associate private keys for this party
pub private_keys: Vec<(u32, Scalar)>,
/// The nonce being used by this party
Expand Down Expand Up @@ -72,7 +71,7 @@ pub trait Signer: Clone + Debug + PartialEq {
fn get_poly_commitments<RNG: RngCore + CryptoRng>(&self, rng: &mut RNG) -> Vec<PolyCommitment>;

/// Reset all polynomials for this signer
fn reset_polys<RNG: RngCore + CryptoRng>(&mut self, rng: &mut RNG);
fn reset_polys<RNG: RngCore + CryptoRng>(&mut self, keep_constant: bool, rng: &mut RNG);

/// Clear all polynomials for this signer
fn clear_polys(&mut self);
Expand Down
33 changes: 22 additions & 11 deletions src/v1.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use hashbrown::HashMap;
use num_traits::{One, Zero};
use polynomial::Polynomial;
use rand_core::{CryptoRng, RngCore};
use tracing::warn;

Expand All @@ -26,7 +25,7 @@ pub struct Party {
/// The public key
pub public_key: Point,
/// The polynomial used for Lagrange interpolation
pub f: Option<Polynomial<Scalar>>,
pub f: Option<Vec<Scalar>>,
num_keys: u32,
threshold: u32,
private_key: Scalar,
Expand Down Expand Up @@ -92,10 +91,8 @@ impl Party {
) -> Option<PolyCommitment> {
if let Some(poly) = &self.f {
Some(PolyCommitment {
id: ID::new(&self.id(), &poly.data()[0], rng),
poly: (0..poly.data().len())
.map(|i| &poly.data()[i] * G)
.collect(),
id: ID::new(&self.id(), &poly[0], rng),
poly: (0..poly.len()).map(|i| &poly[i] * G).collect(),
})
} else {
warn!("get_poly_commitment called with no polynomial");
Expand All @@ -104,8 +101,22 @@ impl Party {
}

/// Make a new polynomial
pub fn reset_poly<RNG: RngCore + CryptoRng>(&mut self, rng: &mut RNG) {
self.f = Some(VSS::random_poly(self.threshold - 1, rng));
pub fn reset_poly<RNG: RngCore + CryptoRng>(&mut self, keep_constant: bool, rng: &mut RNG) {
let constant = if let Some(poly) = &self.f {
if keep_constant {
Some(poly[0].clone())

Check failure on line 107 in src/v1.rs

View workflow job for this annotation

GitHub Actions / clippy

using `clone` on type `Scalar` which implements the `Copy` trait
} else {
None
}
} else {
None
};

if let Some(c) = constant {
self.f = Some(VSS::random_poly_with_constant(self.threshold - 1, c, rng));
} else {
self.f = Some(VSS::random_poly(self.threshold - 1, rng));
}
}

/// Clear the polynomial
Expand All @@ -118,7 +129,7 @@ impl Party {
if let Some(poly) = &self.f {
let mut shares = HashMap::new();
for i in 1..self.num_keys + 1 {
shares.insert(i, poly.eval(compute::id(i)));
shares.insert(i, compute::private_poly(compute::id(i), poly));
}
shares
} else {
Expand Down Expand Up @@ -546,9 +557,9 @@ impl traits::Signer for Signer {
polys
}

fn reset_polys<RNG: RngCore + CryptoRng>(&mut self, rng: &mut RNG) {
fn reset_polys<RNG: RngCore + CryptoRng>(&mut self, keep_constant: bool, rng: &mut RNG) {
for party in self.parties.iter_mut() {
party.reset_poly(rng);
party.reset_poly(keep_constant, rng);
}
}

Expand Down
29 changes: 20 additions & 9 deletions src/v2.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use hashbrown::HashMap;
use num_traits::{One, Zero};
use polynomial::Polynomial;
use rand_core::{CryptoRng, RngCore};
use tracing::warn;

Expand Down Expand Up @@ -29,7 +28,7 @@ pub struct Party {
num_keys: u32,
num_parties: u32,
threshold: u32,
f: Option<Polynomial<Scalar>>,
f: Option<Vec<Scalar>>,
private_keys: HashMap<u32, Scalar>,
group_key: Point,
nonce: Nonce,
Expand Down Expand Up @@ -72,10 +71,8 @@ impl Party {
) -> Option<PolyCommitment> {
if let Some(poly) = &self.f {
Some(PolyCommitment {
id: ID::new(&self.id(), &poly.data()[0], rng),
poly: (0..poly.data().len())
.map(|i| &poly.data()[i] * G)
.collect(),
id: ID::new(&self.id(), &poly[0], rng),
poly: (0..poly.len()).map(|i| &poly[i] * G).collect(),
})
} else {
warn!("get_poly_commitment called with no polynomial");
Expand All @@ -88,7 +85,7 @@ impl Party {
let mut shares = HashMap::new();
if let Some(poly) = &self.f {
for i in 1..self.num_keys + 1 {
shares.insert(i, poly.eval(compute::id(i)));
shares.insert(i, compute::private_poly(compute::id(i), poly));
}
} else {
warn!("get_poly_commitment called with no polynomial");
Expand Down Expand Up @@ -478,8 +475,22 @@ impl traits::Signer for Party {
}
}

fn reset_polys<RNG: RngCore + CryptoRng>(&mut self, rng: &mut RNG) {
self.f = Some(VSS::random_poly(self.threshold - 1, rng));
fn reset_polys<RNG: RngCore + CryptoRng>(&mut self, keep_constant: bool, rng: &mut RNG) {
let constant = if let Some(poly) = &self.f {
if keep_constant {
Some(poly[0].clone())

Check failure on line 481 in src/v2.rs

View workflow job for this annotation

GitHub Actions / clippy

using `clone` on type `Scalar` which implements the `Copy` trait
} else {
None
}
} else {
None
};

if let Some(c) = constant {
self.f = Some(VSS::random_poly_with_constant(self.threshold - 1, c, rng));
} else {
self.f = Some(VSS::random_poly(self.threshold - 1, rng));
}
}

fn clear_polys(&mut self) {
Expand Down
18 changes: 14 additions & 4 deletions src/vss.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use polynomial::Polynomial;
use rand_core::{CryptoRng, RngCore};

use crate::curve::scalar::Scalar;
Expand All @@ -8,8 +7,19 @@ pub struct VSS {}

impl VSS {
/// Construct a random polynomial of the passed degree `n`
pub fn random_poly<RNG: RngCore + CryptoRng>(n: u32, rng: &mut RNG) -> Polynomial<Scalar> {
let params: Vec<Scalar> = (0..n + 1).map(|_| Scalar::random(rng)).collect();
Polynomial::new(params)
pub fn random_poly<RNG: RngCore + CryptoRng>(n: u32, rng: &mut RNG) -> Vec<Scalar> {
(0..n + 1).map(|_| Scalar::random(rng)).collect()
}

/// Construct a random polynomial of the passed degree `n` using the passed constant term
pub fn random_poly_with_constant<RNG: RngCore + CryptoRng>(
n: u32,
constant: Scalar,
rng: &mut RNG,
) -> Vec<Scalar> {
let mut params: Vec<Scalar> = (0..n + 1).map(|_| Scalar::random(rng)).collect();
params[0] = constant;

params
}
}

0 comments on commit 307fe19

Please sign in to comment.