From 307fe1938864a192408aa2d5df9deabb6abf3b8b Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Tue, 8 Oct 2024 03:11:03 -0400 Subject: [PATCH 01/21] add common::Polynomial; use Vec for private polynomial --- src/common.rs | 22 +++++++++++++++++ src/compute.rs | 10 ++++++++ src/net.rs | 2 ++ src/state_machine/coordinator/fire.rs | 1 + src/state_machine/coordinator/frost.rs | 1 + src/state_machine/signer/mod.rs | 6 ++--- src/traits.rs | 5 ++-- src/v1.rs | 33 +++++++++++++++++--------- src/v2.rs | 29 +++++++++++++++------- src/vss.rs | 18 ++++++++++---- 10 files changed, 97 insertions(+), 30 deletions(-) diff --git a/src/common.rs b/src/common.rs index 0b6834a3..8320b85c 100644 --- a/src/common.rs +++ b/src/common.rs @@ -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 { + /// parameters for the polynomial + pub data: Vec, + _x: std::marker::PhantomData, +} + +impl< + Param: Clone + Zero + Add + std::ops::AddAssign<>::Output>, + Arg: Clone + std::ops::Mul, + > Polynomial +{ + /// 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 { diff --git a/src/compute.rs b/src/compute.rs index de4595a2..388b8b4d 100644 --- a/src/compute.rs +++ b/src/compute.rs @@ -130,6 +130,16 @@ pub fn poly(x: &Scalar, f: &Vec) -> Result { 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 { + 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(); diff --git a/src/net.rs b/src/net.rs index 794c3f7b..e8287e3a 100644 --- a/src/net.rs +++ b/src/net.rs @@ -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 { diff --git a/src/state_machine/coordinator/fire.rs b/src/state_machine/coordinator/fire.rs index 93e04a69..17f4a063 100644 --- a/src/state_machine/coordinator/fire.rs +++ b/src/state_machine/coordinator/fire.rs @@ -363,6 +363,7 @@ impl Coordinator { ); let dkg_begin = DkgBegin { dkg_id: self.current_dkg_id, + keep_constant: false, }; let dkg_begin_packet = Packet { sig: dkg_begin diff --git a/src/state_machine/coordinator/frost.rs b/src/state_machine/coordinator/frost.rs index 9409388d..cc5e7ae1 100644 --- a/src/state_machine/coordinator/frost.rs +++ b/src/state_machine/coordinator/frost.rs @@ -194,6 +194,7 @@ impl Coordinator { ); let dkg_begin = DkgBegin { dkg_id: self.current_dkg_id, + keep_constant: false, }; let dkg_begin_packet = Packet { diff --git a/src/state_machine/signer/mod.rs b/src/state_machine/signer/mod.rs index 2bd74f45..f68b18d4 100644 --- a/src/state_machine/signer/mod.rs +++ b/src/state_machine/signer/mod.rs @@ -260,14 +260,14 @@ impl Signer { } /// Reset internal state - pub fn reset(&mut self, dkg_id: u64, rng: &mut T) { + pub fn reset(&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; @@ -594,7 +594,7 @@ impl Signer { fn dkg_begin(&mut self, dkg_begin: &DkgBegin) -> Result, 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(); diff --git a/src/traits.rs b/src/traits.rs index 08a32361..bfbc9612 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -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}; @@ -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>, + pub polynomial: Option>, /// The key IDS and associate private keys for this party pub private_keys: Vec<(u32, Scalar)>, /// The nonce being used by this party @@ -72,7 +71,7 @@ pub trait Signer: Clone + Debug + PartialEq { fn get_poly_commitments(&self, rng: &mut RNG) -> Vec; /// Reset all polynomials for this signer - fn reset_polys(&mut self, rng: &mut RNG); + fn reset_polys(&mut self, keep_constant: bool, rng: &mut RNG); /// Clear all polynomials for this signer fn clear_polys(&mut self); diff --git a/src/v1.rs b/src/v1.rs index 65f5def9..cf974959 100644 --- a/src/v1.rs +++ b/src/v1.rs @@ -1,6 +1,5 @@ use hashbrown::HashMap; use num_traits::{One, Zero}; -use polynomial::Polynomial; use rand_core::{CryptoRng, RngCore}; use tracing::warn; @@ -26,7 +25,7 @@ pub struct Party { /// The public key pub public_key: Point, /// The polynomial used for Lagrange interpolation - pub f: Option>, + pub f: Option>, num_keys: u32, threshold: u32, private_key: Scalar, @@ -92,10 +91,8 @@ impl Party { ) -> Option { 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"); @@ -104,8 +101,22 @@ impl Party { } /// Make a new polynomial - pub fn reset_poly(&mut self, rng: &mut RNG) { - self.f = Some(VSS::random_poly(self.threshold - 1, rng)); + pub fn reset_poly(&mut self, keep_constant: bool, rng: &mut RNG) { + let constant = if let Some(poly) = &self.f { + if keep_constant { + Some(poly[0].clone()) + } 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 @@ -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 { @@ -546,9 +557,9 @@ impl traits::Signer for Signer { polys } - fn reset_polys(&mut self, rng: &mut RNG) { + fn reset_polys(&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); } } diff --git a/src/v2.rs b/src/v2.rs index f738a8c2..cc14df9d 100644 --- a/src/v2.rs +++ b/src/v2.rs @@ -1,6 +1,5 @@ use hashbrown::HashMap; use num_traits::{One, Zero}; -use polynomial::Polynomial; use rand_core::{CryptoRng, RngCore}; use tracing::warn; @@ -29,7 +28,7 @@ pub struct Party { num_keys: u32, num_parties: u32, threshold: u32, - f: Option>, + f: Option>, private_keys: HashMap, group_key: Point, nonce: Nonce, @@ -72,10 +71,8 @@ impl Party { ) -> Option { 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"); @@ -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"); @@ -478,8 +475,22 @@ impl traits::Signer for Party { } } - fn reset_polys(&mut self, rng: &mut RNG) { - self.f = Some(VSS::random_poly(self.threshold - 1, rng)); + fn reset_polys(&mut self, keep_constant: bool, rng: &mut RNG) { + let constant = if let Some(poly) = &self.f { + if keep_constant { + Some(poly[0].clone()) + } 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) { diff --git a/src/vss.rs b/src/vss.rs index 4ffbcb45..2bd7dd26 100644 --- a/src/vss.rs +++ b/src/vss.rs @@ -1,4 +1,3 @@ -use polynomial::Polynomial; use rand_core::{CryptoRng, RngCore}; use crate::curve::scalar::Scalar; @@ -8,8 +7,19 @@ pub struct VSS {} impl VSS { /// Construct a random polynomial of the passed degree `n` - pub fn random_poly(n: u32, rng: &mut RNG) -> Polynomial { - let params: Vec = (0..n + 1).map(|_| Scalar::random(rng)).collect(); - Polynomial::new(params) + pub fn random_poly(n: u32, rng: &mut RNG) -> Vec { + (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( + n: u32, + constant: Scalar, + rng: &mut RNG, + ) -> Vec { + let mut params: Vec = (0..n + 1).map(|_| Scalar::random(rng)).collect(); + params[0] = constant; + + params } } From 8b3aa33b3fe062ba24338b4a2f7690a169dad76a Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Tue, 8 Oct 2024 03:32:27 -0400 Subject: [PATCH 02/21] add commented out Polynomial::new; add Polynomial test --- src/common.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/src/common.rs b/src/common.rs index 8320b85c..b42ffbde 100644 --- a/src/common.rs +++ b/src/common.rs @@ -25,7 +25,7 @@ pub type MerkleRoot = [u8; 32]; /// A Polynomial where the parameters are not necessarily the same type as the args pub struct Polynomial { /// parameters for the polynomial - pub data: Vec, + pub params: Vec, _x: std::marker::PhantomData, } @@ -34,11 +34,21 @@ impl< Arg: Clone + std::ops::Mul, > Polynomial { + /* + /// evaluate the polynomial with the passed arg + pub fn new(n: usize, rng: &RNG) -> Self { + let data = (0..n).map(|_| Param::random(rng)).collect::>(); + Self { + data, + _x: std::marker::PhantomData, + } + } + */ /// 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(); + for i in 0..self.params.len() { + ret += x.clone() * self.params[i].clone(); } ret } @@ -343,6 +353,7 @@ pub mod test_helpers { #[cfg(test)] pub mod test { + use num_traits::Zero; use rand_core::OsRng; use crate::{ @@ -350,6 +361,43 @@ pub mod test { curve::{point::Point, scalar::Scalar}, }; + #[test] + #[allow(non_snake_case)] + fn polynomial() { + let mut rng = OsRng; + let n = 16usize; + + let params = (0..n) + .map(|_| Scalar::random(&mut rng)) + .collect::>(); + let poly = super::Polynomial { + params, + _x: std::marker::PhantomData, + }; + + let y = poly.eval(Scalar::from(1)); + let mut z = Scalar::zero(); + for i in 0..poly.params.len() { + z += poly.params[i]; + } + assert_eq!(y, z); + + let params = (0..n) + .map(|_| Point::from(Scalar::random(&mut rng))) + .collect::>(); + let poly = super::Polynomial { + params, + _x: std::marker::PhantomData, + }; + + let y = poly.eval(Scalar::from(1)); + let mut z = Point::zero(); + for i in 0..poly.params.len() { + z += poly.params[i]; + } + assert_eq!(y, z); + } + #[test] #[allow(non_snake_case)] fn tuple_proof() { From 1d6c447592477271ee69e640e935dca98b08fa00 Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Tue, 8 Oct 2024 10:26:26 -0400 Subject: [PATCH 03/21] fix state machine tests by adding keep_constant field to DkgBegin; fix compute::private_poly by exponentiating the arg --- Cargo.toml | 2 +- src/common.rs | 100 ++++++++++++++----------- src/compute.rs | 37 ++++++++- src/net.rs | 7 +- src/state_machine/coordinator/fire.rs | 10 ++- src/state_machine/coordinator/frost.rs | 10 ++- src/state_machine/mod.rs | 1 + src/state_machine/signer/mod.rs | 5 +- 8 files changed, 121 insertions(+), 51 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a7f90949..8305e0a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wsts" -version = "9.2.0" +version = "10.0.0" edition = "2021" authors = ["Joey Yandle "] license = "Apache-2.0" diff --git a/src/common.rs b/src/common.rs index b42ffbde..be11345e 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,6 +1,6 @@ use core::{ fmt::{Debug, Display, Formatter, Result as FmtResult}, - ops::Add, + ops::{Add, AddAssign, Mul}, }; use hashbrown::HashMap; use num_traits::{One, Zero}; @@ -30,25 +30,34 @@ pub struct Polynomial { } impl< - Param: Clone + Zero + Add + std::ops::AddAssign<>::Output>, - Arg: Clone + std::ops::Mul, + Param: Clone + Zero + Add + AddAssign<>::Output>, + Arg: Clone + Mul, > Polynomial { /* - /// evaluate the polynomial with the passed arg - pub fn new(n: usize, rng: &RNG) -> Self { - let data = (0..n).map(|_| Param::random(rng)).collect::>(); + /// evaluate the polynomial with the passed arg + pub fn new(n: usize, rng: &RNG) -> Self { + let data = (0..n).map(|_| Param::random(rng)).collect::>(); + Self { + data, + _x: std::marker::PhantomData, + } + } + */ + /// construct new polynomial from passed params + pub fn new(params: Vec) -> Self { Self { - data, + params, _x: std::marker::PhantomData, } - } - */ + } /// evaluate the polynomial with the passed arg pub fn eval(&self, x: Arg) -> Param { + //let mut pow = Scalar::one(); let mut ret = Param::zero(); for i in 0..self.params.len() { ret += x.clone() * self.params[i].clone(); + //pow *= x.clone(); } ret } @@ -353,49 +362,56 @@ pub mod test_helpers { #[cfg(test)] pub mod test { - use num_traits::Zero; + //use num_traits::Zero; use rand_core::OsRng; use crate::{ common::TupleProof, + //compute, curve::{point::Point, scalar::Scalar}, }; #[test] #[allow(non_snake_case)] fn polynomial() { - let mut rng = OsRng; - let n = 16usize; - - let params = (0..n) - .map(|_| Scalar::random(&mut rng)) - .collect::>(); - let poly = super::Polynomial { - params, - _x: std::marker::PhantomData, - }; - - let y = poly.eval(Scalar::from(1)); - let mut z = Scalar::zero(); - for i in 0..poly.params.len() { - z += poly.params[i]; - } - assert_eq!(y, z); - - let params = (0..n) - .map(|_| Point::from(Scalar::random(&mut rng))) - .collect::>(); - let poly = super::Polynomial { - params, - _x: std::marker::PhantomData, - }; - - let y = poly.eval(Scalar::from(1)); - let mut z = Point::zero(); - for i in 0..poly.params.len() { - z += poly.params[i]; - } - assert_eq!(y, z); + /* + let mut rng = OsRng; + let n = 16usize; + + let params = (0..n) + .map(|_| Scalar::random(&mut rng)) + .collect::>(); + let poly = super::Polynomial::new(params.clone()); + let y = poly.eval(Scalar::from(1)); + let mut z = Scalar::zero(); + for i in 0..poly.params.len() { + z += poly.params[i]; + } + assert_eq!(y, z); + + let b = compute::private_poly(Scalar::from(8), ¶ms); + assert_eq!(y, b); + + let public_params = params.iter().map(|p| p * G).collect::>(); + let public_poly: super::Polynomial = super::Polynomial::new(public_params.clone()); + let a = poly.eval(Scalar::from(8)); + let b = public_poly.eval(Scalar::from(8)); + assert_eq!(a * G, b); + + let b = compute::poly(&Scalar::from(8), &public_params); + assert_eq!(a * G, b.unwrap()); + + let params = (0..n) + .map(|_| Point::from(Scalar::random(&mut rng))) + .collect::>(); + let poly = super::Polynomial::new(params); + let y = poly.eval(Scalar::from(1)); + let mut z = Point::zero(); + for i in 0..poly.params.len() { + z += poly.params[i]; + } + assert_eq!(y, z); + */ } #[test] diff --git a/src/compute.rs b/src/compute.rs index 388b8b4d..f6a3ac1c 100644 --- a/src/compute.rs +++ b/src/compute.rs @@ -130,12 +130,14 @@ pub fn poly(x: &Scalar, f: &Vec) -> Result { Point::multimult(s, f.clone()) } -/// Evaluate the public polynomial `f` at scalar `x` using multi-exponentiation +/// Evaluate the private polynomial `f` at scalar `x` #[allow(clippy::ptr_arg)] pub fn private_poly(x: Scalar, f: &Vec) -> Scalar { + let mut pow = Scalar::one(); let mut sum = Scalar::zero(); for i in 0..f.len() { - sum += x * f[i]; + sum += pow * f[i]; + pow *= x; } sum } @@ -179,3 +181,34 @@ pub fn merkle_root(data: &[u8]) -> [u8; 32] { hasher.finalize().into() } + +#[cfg(test)] +pub mod test { + //use num_traits::Zero; + use rand_core::OsRng; + + use crate::{ + compute, + curve::{ + point::{Point, G}, + scalar::Scalar, + }, + }; + + #[test] + #[allow(non_snake_case)] + fn poly() { + let mut rng = OsRng; + let n = 16usize; + + let private_poly = (0..n) + .map(|_| Scalar::random(&mut rng)) + .collect::>(); + let poly = private_poly.iter().map(|p| p * G).collect::>(); + + let x = compute::private_poly(Scalar::from(8), &private_poly); + let y = compute::poly(&Scalar::from(8), &poly); + + assert_eq!(x * G, y.unwrap()); + } +} diff --git a/src/net.rs b/src/net.rs index e8287e3a..5e5c8a29 100644 --- a/src/net.rs +++ b/src/net.rs @@ -131,8 +131,10 @@ pub struct DkgBegin { impl Signable for DkgBegin { fn hash(&self, hasher: &mut Sha256) { + let keep_constant = if self.keep_constant { [1u8] } else { [0u8] }; hasher.update("DKG_BEGIN".as_bytes()); hasher.update(self.dkg_id.to_be_bytes()); + hasher.update(&keep_constant); } } @@ -631,7 +633,10 @@ mod test { #[test] fn dkg_begin_verify_msg() { let test_config = TestConfig::default(); - let dkg_begin = DkgBegin { dkg_id: 0 }; + let dkg_begin = DkgBegin { + dkg_id: 0, + keep_constant: false, + }; let dkg_private_begin = DkgPrivateBegin { dkg_id: 0, key_ids: Default::default(), diff --git a/src/state_machine/coordinator/fire.rs b/src/state_machine/coordinator/fire.rs index 17f4a063..061f1e2f 100644 --- a/src/state_machine/coordinator/fire.rs +++ b/src/state_machine/coordinator/fire.rs @@ -2697,7 +2697,10 @@ pub mod test { let (packets, results) = coordinator .process_inbound_messages(&[Packet { sig: vec![], - msg: Message::DkgBegin(DkgBegin { dkg_id: old_id }), + msg: Message::DkgBegin(DkgBegin { + dkg_id: old_id, + keep_constant: false, + }), }]) .unwrap(); assert!(packets.is_empty()); @@ -2709,7 +2712,10 @@ pub mod test { let (packets, results) = coordinator .process_inbound_messages(&[Packet { sig: vec![], - msg: Message::DkgBegin(DkgBegin { dkg_id: id }), + msg: Message::DkgBegin(DkgBegin { + dkg_id: id, + keep_constant: false, + }), }]) .unwrap(); assert!(packets.is_empty()); diff --git a/src/state_machine/coordinator/frost.rs b/src/state_machine/coordinator/frost.rs index cc5e7ae1..f328daa4 100644 --- a/src/state_machine/coordinator/frost.rs +++ b/src/state_machine/coordinator/frost.rs @@ -889,7 +889,10 @@ pub mod test { let (packets, results) = coordinator .process_inbound_messages(&[Packet { sig: vec![], - msg: Message::DkgBegin(DkgBegin { dkg_id: old_id }), + msg: Message::DkgBegin(DkgBegin { + dkg_id: old_id, + keep_constant: false, + }), }]) .unwrap(); assert!(packets.is_empty()); @@ -901,7 +904,10 @@ pub mod test { let (packets, results) = coordinator .process_inbound_messages(&[Packet { sig: vec![], - msg: Message::DkgBegin(DkgBegin { dkg_id: id }), + msg: Message::DkgBegin(DkgBegin { + dkg_id: id, + keep_constant: false, + }), }]) .unwrap(); assert!(packets.is_empty()); diff --git a/src/state_machine/mod.rs b/src/state_machine/mod.rs index 14da2b52..0d237e1e 100644 --- a/src/state_machine/mod.rs +++ b/src/state_machine/mod.rs @@ -51,6 +51,7 @@ pub enum SignError { } /// Result of a DKG or sign operation +#[derive(Debug, Clone)] pub enum OperationResult { /// DKG succeeded with the wrapped public key Dkg(Point), diff --git a/src/state_machine/signer/mod.rs b/src/state_machine/signer/mod.rs index f68b18d4..49a600bf 100644 --- a/src/state_machine/signer/mod.rs +++ b/src/state_machine/signer/mod.rs @@ -935,7 +935,10 @@ pub mod test { assert!(!signer.can_dkg_end()); // meet the conditions for DKG_END - let dkg_begin = Message::DkgBegin(DkgBegin { dkg_id: 1 }); + let dkg_begin = Message::DkgBegin(DkgBegin { + dkg_id: 1, + keep_constant: false, + }); let dkg_public_shares = signer .process(&dkg_begin) .expect("failed to process DkgBegin"); From 69c40d5c3613d3fdc4be50f47e85abce997c59ab Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Tue, 8 Oct 2024 10:31:01 -0400 Subject: [PATCH 04/21] clippy fixes --- src/net.rs | 2 +- src/v1.rs | 2 +- src/v2.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/net.rs b/src/net.rs index 5e5c8a29..abc87953 100644 --- a/src/net.rs +++ b/src/net.rs @@ -134,7 +134,7 @@ impl Signable for DkgBegin { let keep_constant = if self.keep_constant { [1u8] } else { [0u8] }; hasher.update("DKG_BEGIN".as_bytes()); hasher.update(self.dkg_id.to_be_bytes()); - hasher.update(&keep_constant); + hasher.update(keep_constant); } } diff --git a/src/v1.rs b/src/v1.rs index cf974959..df38726a 100644 --- a/src/v1.rs +++ b/src/v1.rs @@ -104,7 +104,7 @@ impl Party { pub fn reset_poly(&mut self, keep_constant: bool, rng: &mut RNG) { let constant = if let Some(poly) = &self.f { if keep_constant { - Some(poly[0].clone()) + Some(poly[0]) } else { None } diff --git a/src/v2.rs b/src/v2.rs index cc14df9d..aecd962d 100644 --- a/src/v2.rs +++ b/src/v2.rs @@ -478,7 +478,7 @@ impl traits::Signer for Party { fn reset_polys(&mut self, keep_constant: bool, rng: &mut RNG) { let constant = if let Some(poly) = &self.f { if keep_constant { - Some(poly[0].clone()) + Some(poly[0]) } else { None } From 7a53a8de4da175949c94f8272e5b59832bcf0a60 Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Tue, 8 Oct 2024 10:53:25 -0400 Subject: [PATCH 05/21] pass keep_constant from start_dkg_round down --- src/state_machine/coordinator/fire.rs | 58 +++++++++++++++++++------- src/state_machine/coordinator/frost.rs | 14 +++---- src/state_machine/coordinator/mod.rs | 10 +++-- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/src/state_machine/coordinator/fire.rs b/src/state_machine/coordinator/fire.rs index 061f1e2f..8ee8a0d8 100644 --- a/src/state_machine/coordinator/fire.rs +++ b/src/state_machine/coordinator/fire.rs @@ -227,7 +227,7 @@ impl Coordinator { // that we start the next round at the correct id. (Do this rather // than overwriting afterwards to ensure logging is accurate) self.current_dkg_id = dkg_begin.dkg_id.wrapping_sub(1); - let packet = self.start_dkg_round()?; + let packet = self.start_dkg_round(dkg_begin.keep_constant)?; return Ok((Some(packet), None)); } else if let Message::NonceRequest(nonce_request) = &packet.msg { if self.current_sign_id >= nonce_request.sign_id { @@ -249,7 +249,9 @@ impl Coordinator { return Ok((None, None)); } State::DkgPublicDistribute => { - let packet = self.start_public_shares()?; + // XXX does this ever happen? start_dkg_round should call start_public_shares + panic!("Got message in DkgPublicDistribute"); + let packet = self.start_public_shares(false)?; return Ok((Some(packet), None)); } State::DkgPublicGather => { @@ -353,7 +355,7 @@ impl Coordinator { } /// Ask signers to send DKG public shares - pub fn start_public_shares(&mut self) -> Result { + pub fn start_public_shares(&mut self, keep_constant: bool) -> Result { self.dkg_public_shares.clear(); self.party_polynomials.clear(); self.dkg_wait_signer_ids = (0..self.config.num_signers).collect(); @@ -363,7 +365,7 @@ impl Coordinator { ); let dkg_begin = DkgBegin { dkg_id: self.current_dkg_id, - keep_constant: false, + keep_constant, }; let dkg_begin_packet = Packet { sig: dkg_begin @@ -1197,11 +1199,11 @@ impl CoordinatorTrait for Coordinator { } /// Start a DKG round - fn start_dkg_round(&mut self) -> Result { + fn start_dkg_round(&mut self, keep_constant: bool) -> Result { self.current_dkg_id = self.current_dkg_id.wrapping_add(1); info!("Starting DKG round {}", self.current_dkg_id); self.move_to(State::DkgPublicDistribute)?; - self.start_public_shares() + self.start_public_shares(keep_constant) } /// Start a signing round @@ -1321,7 +1323,7 @@ pub mod test { coordinator.state = State::DkgPublicDistribute; // Must be in this state before calling start public shares - let result = coordinator.start_public_shares().unwrap(); + let result = coordinator.start_public_shares(false).unwrap(); assert!(matches!(result.msg, Message::DkgBegin(_))); assert_eq!(coordinator.get_state(), State::DkgPublicGather); @@ -1379,7 +1381,11 @@ pub mod test { setup::, SignerType>(num_signers, keys_per_signer); // We have started a dkg round - let message = coordinators.first_mut().unwrap().start_dkg_round().unwrap(); + let message = coordinators + .first_mut() + .unwrap() + .start_dkg_round(false) + .unwrap(); assert!(coordinators.first().unwrap().aggregate_public_key.is_none()); assert_eq!(coordinators.first().unwrap().state, State::DkgPublicGather); @@ -1457,7 +1463,11 @@ pub mod test { ); // Start a DKG round where we will not allow all signers to recv DkgBegin, so they will not respond with DkgPublicShares - let message = coordinators.first_mut().unwrap().start_dkg_round().unwrap(); + let message = coordinators + .first_mut() + .unwrap() + .start_dkg_round(false) + .unwrap(); assert!(coordinators.first().unwrap().aggregate_public_key.is_none()); assert_eq!(coordinators.first().unwrap().state, State::DkgPublicGather); @@ -1538,7 +1548,11 @@ pub mod test { ); // Start a DKG round where we will not allow all signers to recv DkgBegin, so they will not respond with DkgPublicShares - let message = coordinators.first_mut().unwrap().start_dkg_round().unwrap(); + let message = coordinators + .first_mut() + .unwrap() + .start_dkg_round(false) + .unwrap(); assert!(coordinators.first().unwrap().aggregate_public_key.is_none()); assert_eq!(coordinators.first().unwrap().state, State::DkgPublicGather); @@ -1691,7 +1705,11 @@ pub mod test { ); // Start a DKG round where we will not allow all signers to recv DkgBegin, so they will not respond with DkgPublicShares - let message = coordinators.first_mut().unwrap().start_dkg_round().unwrap(); + let message = coordinators + .first_mut() + .unwrap() + .start_dkg_round(false) + .unwrap(); assert!(coordinators.first().unwrap().aggregate_public_key.is_none()); assert_eq!(coordinators.first().unwrap().state, State::DkgPublicGather); @@ -1827,7 +1845,11 @@ pub mod test { setup::, SignerType>(num_signers, keys_per_signer); // We have started a dkg round - let message = coordinators.first_mut().unwrap().start_dkg_round().unwrap(); + let message = coordinators + .first_mut() + .unwrap() + .start_dkg_round(false) + .unwrap(); assert!(coordinators.first().unwrap().aggregate_public_key.is_none()); assert_eq!(coordinators.first().unwrap().state, State::DkgPublicGather); @@ -1949,7 +1971,11 @@ pub mod test { setup::, SignerType>(num_signers, keys_per_signer); // We have started a dkg round - let message = coordinators.first_mut().unwrap().start_dkg_round().unwrap(); + let message = coordinators + .first_mut() + .unwrap() + .start_dkg_round(false) + .unwrap(); assert!(coordinators.first().unwrap().aggregate_public_key.is_none()); assert_eq!(coordinators.first().unwrap().state, State::DkgPublicGather); @@ -2323,7 +2349,11 @@ pub mod test { let config = coordinators.first().unwrap().get_config(); // We have started a dkg round - let message = coordinators.first_mut().unwrap().start_dkg_round().unwrap(); + let message = coordinators + .first_mut() + .unwrap() + .start_dkg_round(false) + .unwrap(); assert!(coordinators.first().unwrap().aggregate_public_key.is_none()); assert_eq!(coordinators.first().unwrap().state, State::DkgPublicGather); diff --git a/src/state_machine/coordinator/frost.rs b/src/state_machine/coordinator/frost.rs index f328daa4..45075e1d 100644 --- a/src/state_machine/coordinator/frost.rs +++ b/src/state_machine/coordinator/frost.rs @@ -69,7 +69,7 @@ impl Coordinator { // that we start the next round at the correct id. (Do this rather // then overwriting afterwards to ensure logging is accurate) self.current_dkg_id = dkg_begin.dkg_id.wrapping_sub(1); - let packet = self.start_dkg_round()?; + let packet = self.start_dkg_round(dkg_begin.keep_constant)?; return Ok((Some(packet), None)); } else if let Message::NonceRequest(nonce_request) = &packet.msg { if self.current_sign_id >= nonce_request.sign_id { @@ -91,7 +91,7 @@ impl Coordinator { return Ok((None, None)); } State::DkgPublicDistribute => { - let packet = self.start_public_shares()?; + let packet = self.start_public_shares(false)?; return Ok((Some(packet), None)); } State::DkgPublicGather => { @@ -184,7 +184,7 @@ impl Coordinator { } /// Ask signers to send DKG public shares - pub fn start_public_shares(&mut self) -> Result { + pub fn start_public_shares(&mut self, keep_constant: bool) -> Result { self.dkg_public_shares.clear(); self.party_polynomials.clear(); self.ids_to_await = (0..self.config.num_signers).collect(); @@ -194,7 +194,7 @@ impl Coordinator { ); let dkg_begin = DkgBegin { dkg_id: self.current_dkg_id, - keep_constant: false, + keep_constant, }; let dkg_begin_packet = Packet { @@ -716,11 +716,11 @@ impl CoordinatorTrait for Coordinator { } /// Start a DKG round - fn start_dkg_round(&mut self) -> Result { + fn start_dkg_round(&mut self, keep_constant: bool) -> Result { self.current_dkg_id = self.current_dkg_id.wrapping_add(1); info!("Starting DKG round {}", self.current_dkg_id); self.move_to(State::DkgPublicDistribute)?; - self.start_public_shares() + self.start_public_shares(keep_constant) } /// Start a signing round @@ -827,7 +827,7 @@ pub mod test { coordinator.state = State::DkgPublicDistribute; // Must be in this state before calling start public shares - let result = coordinator.start_public_shares().unwrap(); + let result = coordinator.start_public_shares(false).unwrap(); assert!(matches!(result.msg, Message::DkgBegin(_))); assert_eq!(coordinator.get_state(), State::DkgPublicGather); diff --git a/src/state_machine/coordinator/mod.rs b/src/state_machine/coordinator/mod.rs index 0ef15a6d..df9988b0 100644 --- a/src/state_machine/coordinator/mod.rs +++ b/src/state_machine/coordinator/mod.rs @@ -280,7 +280,7 @@ pub trait Coordinator: Clone + Debug + PartialEq { fn get_state(&self) -> State; /// Trigger a DKG round - fn start_dkg_round(&mut self) -> Result; + fn start_dkg_round(&mut self, keep_constant: bool) -> Result; /// Trigger a signing round fn start_signing_round( @@ -415,7 +415,7 @@ pub mod test { let mut rng = OsRng; let config = Config::new(10, 40, 28, Scalar::random(&mut rng)); let mut coordinator = Coordinator::new(config); - let result = coordinator.start_dkg_round(); + let result = coordinator.start_dkg_round(false); assert!(result.is_ok()); if let Message::DkgBegin(dkg_begin) = result.unwrap().msg { @@ -593,7 +593,11 @@ pub mod test { setup::(num_signers, keys_per_signer); // We have started a dkg round - let message = coordinators.first_mut().unwrap().start_dkg_round().unwrap(); + let message = coordinators + .first_mut() + .unwrap() + .start_dkg_round(false) + .unwrap(); assert!(coordinators .first_mut() .unwrap() From 93a4d35780cdc3e3cf25eba276621f0fe8737a37 Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Tue, 8 Oct 2024 11:39:57 -0400 Subject: [PATCH 06/21] add tests to show that keep_constant works on signers and on full state machines --- src/state_machine/coordinator/fire.rs | 84 ++++++++++++++++++++++++++- src/traits.rs | 29 +++++++++ src/v1.rs | 5 ++ src/v2.rs | 5 ++ 4 files changed, 122 insertions(+), 1 deletion(-) diff --git a/src/state_machine/coordinator/fire.rs b/src/state_machine/coordinator/fire.rs index 8ee8a0d8..23ea4e8d 100644 --- a/src/state_machine/coordinator/fire.rs +++ b/src/state_machine/coordinator/fire.rs @@ -250,7 +250,7 @@ impl Coordinator { } State::DkgPublicDistribute => { // XXX does this ever happen? start_dkg_round should call start_public_shares - panic!("Got message in DkgPublicDistribute"); + //panic!("Got message in DkgPublicDistribute"); let packet = self.start_public_shares(false)?; return Ok((Some(packet), None)); } @@ -1435,6 +1435,88 @@ pub mod test { (coordinators, signers) } + #[test] + fn all_signers_dkg_keep_constant_v1() { + all_signers_dkg_keep_constant::(5, 2); + } + + #[test] + fn all_signers_dkg_keep_constant_v2() { + all_signers_dkg_keep_constant::(5, 2); + } + + fn all_signers_dkg_keep_constant( + num_signers: u32, + keys_per_signer: u32, + ) { + let (mut coordinators, mut signers) = + setup::, SignerType>(num_signers, keys_per_signer); + + let key0 = all_signers_rerun_dkg(&mut coordinators, &mut signers, false); + let key1 = all_signers_rerun_dkg(&mut coordinators, &mut signers, false); + let key2 = all_signers_rerun_dkg(&mut coordinators, &mut signers, true); + + assert!(key0 != key1); + assert_eq!(key1, key2); + } + + fn all_signers_rerun_dkg( + coordinators: &mut Vec>, + signers: &mut Vec>, + keep_constant: bool, + ) -> Point { + // We have started a dkg round + let message = coordinators + .first_mut() + .unwrap() + .start_dkg_round(keep_constant) + .unwrap(); + assert_eq!(coordinators.first().unwrap().state, State::DkgPublicGather); + + // Send the DKG Begin message to all signers and gather responses by sharing with all other signers and coordinators + let (outbound_messages, operation_results) = + feedback_messages(coordinators, signers, &[message]); + assert!(operation_results.is_empty()); + + // Successfully got an Aggregate Public Key... + assert_eq!(outbound_messages.len(), 1); + match &outbound_messages[0].msg { + Message::DkgPrivateBegin(_) => {} + _ => { + panic!("Expected DkgPrivateBegin message"); + } + } + // Send the DKG Private Begin message to all signers and share their responses with the coordinators and signers + let (outbound_messages, operation_results) = + feedback_messages(coordinators, signers, &outbound_messages); + assert_eq!(operation_results.len(), 0); + assert_eq!(outbound_messages.len(), 1); + match &outbound_messages[0].msg { + Message::DkgEndBegin(_) => {} + _ => { + panic!("Expected DkgEndBegin message"); + } + } + + // Send the DkgEndBegin message to all signers and share their responses with the coordinators and signers + let (outbound_messages, operation_results) = + feedback_messages(coordinators, signers, &outbound_messages); + assert_eq!(outbound_messages.len(), 0); + assert_eq!(operation_results.len(), 1); + match operation_results[0] { + OperationResult::Dkg(point) => { + assert_ne!(point, Point::default()); + for coordinator in coordinators.iter() { + assert_eq!(coordinator.get_aggregate_public_key(), Some(point)); + assert_eq!(coordinator.get_state(), State::Idle); + } + } + _ => panic!("Expected Dkg Operation result"), + } + + coordinators[0].get_aggregate_public_key().unwrap() + } + #[test] fn missing_public_keys_dkg_v1() { missing_public_keys_dkg::(10, 1); diff --git a/src/traits.rs b/src/traits.rs index bfbc9612..7435d606 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -298,4 +298,33 @@ pub mod test_helpers { }, } } + + /// Check that the keep_constant param of reset_polys works + pub fn reset_polys() { + let mut rng = OsRng; + let id = 1; + let key_ids = [1, 2, 3]; + let n: u32 = 10; + let n_p = 4; + let t: u32 = 7; + + let mut signer = Signer::new(id, &key_ids, n, n_p, t, &mut rng); + let comms0 = signer.get_poly_commitments(&mut rng); + + signer.reset_polys(false, &mut rng); + + let comms1 = signer.get_poly_commitments(&mut rng); + + for (comm0, comm1) in comms0.into_iter().zip(comms1.clone()) { + assert!(comm0.poly[0] != comm1.poly[0]); + } + + signer.reset_polys(true, &mut rng); + + let comms2 = signer.get_poly_commitments(&mut rng); + + for (comm1, comm2) in comms1.into_iter().zip(comms2) { + assert!(comm1.poly[0] == comm2.poly[0]); + } + } } diff --git a/src/v1.rs b/src/v1.rs index df38726a..0f414d23 100644 --- a/src/v1.rs +++ b/src/v1.rs @@ -794,6 +794,11 @@ mod tests { } } + #[test] + fn reset_polys() { + traits::test_helpers::reset_polys::(); + } + #[allow(non_snake_case)] #[test] fn aggregator_sign() { diff --git a/src/v2.rs b/src/v2.rs index aecd962d..e67da7a7 100644 --- a/src/v2.rs +++ b/src/v2.rs @@ -743,4 +743,9 @@ mod tests { traits::test_helpers::bad_polynomial_length::(gt); traits::test_helpers::bad_polynomial_length::(lt); } + + #[test] + fn reset_polys() { + traits::test_helpers::reset_polys::(); + } } From 995dd89cfb45f65f16192af7202505391cde6a58 Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Tue, 8 Oct 2024 11:53:34 -0400 Subject: [PATCH 07/21] fix common::Polynomial eval and reenable test --- src/common.rs | 79 ++++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/src/common.rs b/src/common.rs index be11345e..bd420a48 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,6 +1,6 @@ use core::{ fmt::{Debug, Display, Formatter, Result as FmtResult}, - ops::{Add, AddAssign, Mul}, + ops::{Add, AddAssign, Mul, MulAssign}, }; use hashbrown::HashMap; use num_traits::{One, Zero}; @@ -31,7 +31,7 @@ pub struct Polynomial { impl< Param: Clone + Zero + Add + AddAssign<>::Output>, - Arg: Clone + Mul, + Arg: Clone + One + Mul + MulAssign, > Polynomial { /* @@ -53,11 +53,11 @@ impl< } /// evaluate the polynomial with the passed arg pub fn eval(&self, x: Arg) -> Param { - //let mut pow = Scalar::one(); + let mut pow = Arg::one(); let mut ret = Param::zero(); for i in 0..self.params.len() { - ret += x.clone() * self.params[i].clone(); - //pow *= x.clone(); + ret += pow.clone() * self.params[i].clone(); + pow *= x.clone(); } ret } @@ -362,38 +362,42 @@ pub mod test_helpers { #[cfg(test)] pub mod test { - //use num_traits::Zero; + use num_traits::Zero; use rand_core::OsRng; use crate::{ common::TupleProof, - //compute, - curve::{point::Point, scalar::Scalar}, + compute, + curve::{ + point::{Point, G}, + scalar::Scalar, + }, }; #[test] #[allow(non_snake_case)] fn polynomial() { - /* - let mut rng = OsRng; - let n = 16usize; - - let params = (0..n) - .map(|_| Scalar::random(&mut rng)) - .collect::>(); - let poly = super::Polynomial::new(params.clone()); - let y = poly.eval(Scalar::from(1)); - let mut z = Scalar::zero(); - for i in 0..poly.params.len() { - z += poly.params[i]; - } - assert_eq!(y, z); + let mut rng = OsRng; + let n = 16usize; + + let params = (0..n) + .map(|_| Scalar::random(&mut rng)) + .collect::>(); + let poly = super::Polynomial::new(params.clone()); + let y = poly.eval(Scalar::from(1)); + let mut z = Scalar::zero(); + for i in 0..poly.params.len() { + z += poly.params[i]; + } + assert_eq!(y, z); + let a = poly.eval(Scalar::from(8)); let b = compute::private_poly(Scalar::from(8), ¶ms); - assert_eq!(y, b); + assert_eq!(a, b); - let public_params = params.iter().map(|p| p * G).collect::>(); - let public_poly: super::Polynomial = super::Polynomial::new(public_params.clone()); + let public_params = params.iter().map(|p| p * G).collect::>(); + let public_poly: super::Polynomial = + super::Polynomial::new(public_params.clone()); let a = poly.eval(Scalar::from(8)); let b = public_poly.eval(Scalar::from(8)); assert_eq!(a * G, b); @@ -401,17 +405,20 @@ pub mod test { let b = compute::poly(&Scalar::from(8), &public_params); assert_eq!(a * G, b.unwrap()); - let params = (0..n) - .map(|_| Point::from(Scalar::random(&mut rng))) - .collect::>(); - let poly = super::Polynomial::new(params); - let y = poly.eval(Scalar::from(1)); - let mut z = Point::zero(); - for i in 0..poly.params.len() { - z += poly.params[i]; - } - assert_eq!(y, z); - */ + let params = (0..n) + .map(|_| Point::from(Scalar::random(&mut rng))) + .collect::>(); + let poly = super::Polynomial::new(params.clone()); + let y = poly.eval(Scalar::from(1)); + let mut z = Point::zero(); + for i in 0..poly.params.len() { + z += poly.params[i]; + } + assert_eq!(y, z); + + let a = poly.eval(Scalar::from(8)); + let b = compute::poly(&Scalar::from(8), ¶ms); + assert_eq!(a, b.unwrap()); } #[test] From 4c85a3b840e7fc8519ff68f41d2908b72c7e0f42 Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Tue, 8 Oct 2024 12:04:56 -0400 Subject: [PATCH 08/21] fix comment on commented out Polynomial::random --- src/common.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common.rs b/src/common.rs index bd420a48..e1a0fae9 100644 --- a/src/common.rs +++ b/src/common.rs @@ -35,14 +35,14 @@ impl< > Polynomial { /* - /// evaluate the polynomial with the passed arg - pub fn new(n: usize, rng: &RNG) -> Self { + /// construct new random polynomial of the specified size + pub fn random(n: usize, rng: &RNG) -> Self { let data = (0..n).map(|_| Param::random(rng)).collect::>(); Self { data, _x: std::marker::PhantomData, } - } + } */ /// construct new polynomial from passed params pub fn new(params: Vec) -> Self { From 020d5e817ed07cd0ffe9cd58327a1e714cbfa485 Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Tue, 8 Oct 2024 12:16:34 -0400 Subject: [PATCH 09/21] add Random trait and use it to reenable Polynomial::random --- src/common.rs | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/common.rs b/src/common.rs index e1a0fae9..5b8c84f6 100644 --- a/src/common.rs +++ b/src/common.rs @@ -22,6 +22,24 @@ use crate::{ /// A merkle root is a 256 bit hash pub type MerkleRoot = [u8; 32]; +/// A trait that allows us to create random instances of implementors +pub trait Random { + /// Create a new instance with random data + fn fill(rng: &mut RNG) -> Self; +} + +impl Random for Point { + fn fill(rng: &mut RNG) -> Self { + Point::from(Scalar::random(rng)) + } +} + +impl Random for Scalar { + fn fill(rng: &mut RNG) -> Self { + Scalar::random(rng) + } +} + /// A Polynomial where the parameters are not necessarily the same type as the args pub struct Polynomial { /// parameters for the polynomial @@ -30,20 +48,19 @@ pub struct Polynomial { } impl< - Param: Clone + Zero + Add + AddAssign<>::Output>, + Param: Clone + Zero + Random + Add + AddAssign<>::Output>, Arg: Clone + One + Mul + MulAssign, > Polynomial { - /* /// construct new random polynomial of the specified size - pub fn random(n: usize, rng: &RNG) -> Self { - let data = (0..n).map(|_| Param::random(rng)).collect::>(); - Self { - data, - _x: std::marker::PhantomData, - } + pub fn random(n: usize, rng: &mut RNG) -> Self { + let params = (0..n).map(|_| Param::fill(rng)).collect::>(); + Self { + params, + _x: std::marker::PhantomData, + } } - */ + /// construct new polynomial from passed params pub fn new(params: Vec) -> Self { Self { From 39c117f3c4e8bafc67c359f8e5407bb060e11087 Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Tue, 8 Oct 2024 12:21:01 -0400 Subject: [PATCH 10/21] polys have degree not size --- src/common.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common.rs b/src/common.rs index 5b8c84f6..5793bd96 100644 --- a/src/common.rs +++ b/src/common.rs @@ -52,9 +52,9 @@ impl< Arg: Clone + One + Mul + MulAssign, > Polynomial { - /// construct new random polynomial of the specified size + /// construct new random polynomial of the specified degree pub fn random(n: usize, rng: &mut RNG) -> Self { - let params = (0..n).map(|_| Param::fill(rng)).collect::>(); + let params = (0..n + 1).map(|_| Param::fill(rng)).collect::>(); Self { params, _x: std::marker::PhantomData, From 0fa404385ec6404d021ff0455ce39622e9237cff Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Tue, 8 Oct 2024 12:27:55 -0400 Subject: [PATCH 11/21] use Polynomial::random in unit test --- src/common.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/common.rs b/src/common.rs index 5793bd96..b1e6f6a6 100644 --- a/src/common.rs +++ b/src/common.rs @@ -397,10 +397,8 @@ pub mod test { let mut rng = OsRng; let n = 16usize; - let params = (0..n) - .map(|_| Scalar::random(&mut rng)) - .collect::>(); - let poly = super::Polynomial::new(params.clone()); + let poly = super::Polynomial::::random(n - 1, &mut rng); + let params = poly.params.clone(); let y = poly.eval(Scalar::from(1)); let mut z = Scalar::zero(); for i in 0..poly.params.len() { @@ -422,10 +420,8 @@ pub mod test { let b = compute::poly(&Scalar::from(8), &public_params); assert_eq!(a * G, b.unwrap()); - let params = (0..n) - .map(|_| Point::from(Scalar::random(&mut rng))) - .collect::>(); - let poly = super::Polynomial::new(params.clone()); + let poly = super::Polynomial::random(n - 1, &mut rng); + let params = poly.params.clone(); let y = poly.eval(Scalar::from(1)); let mut z = Point::zero(); for i in 0..poly.params.len() { From 7ade470842d6e5af8df3f3888c3d66af34333bbb Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Tue, 8 Oct 2024 12:30:39 -0400 Subject: [PATCH 12/21] remove unused import --- src/compute.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/compute.rs b/src/compute.rs index f6a3ac1c..049c9a30 100644 --- a/src/compute.rs +++ b/src/compute.rs @@ -184,7 +184,6 @@ pub fn merkle_root(data: &[u8]) -> [u8; 32] { #[cfg(test)] pub mod test { - //use num_traits::Zero; use rand_core::OsRng; use crate::{ From 6f81a1d8e34dbd44e4c6df42eb436c4efddbc698 Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Wed, 9 Oct 2024 10:15:08 -0400 Subject: [PATCH 13/21] use common::Polynomial for private polys; add operators and helpers to Polynomial to make code cleaner --- src/common.rs | 37 ++++++++++++++++++++++++++++++++++--- src/traits.rs | 6 ++++-- src/v1.rs | 11 +++++++---- src/v2.rs | 8 ++++---- src/vss.rs | 16 ++++++++++------ 5 files changed, 59 insertions(+), 19 deletions(-) diff --git a/src/common.rs b/src/common.rs index b1e6f6a6..706d0401 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,6 +1,6 @@ use core::{ fmt::{Debug, Display, Formatter, Result as FmtResult}, - ops::{Add, AddAssign, Mul, MulAssign}, + ops::{Add, AddAssign, Index, Mul, MulAssign}, }; use hashbrown::HashMap; use num_traits::{One, Zero}; @@ -41,6 +41,7 @@ impl Random for Scalar { } /// A Polynomial where the parameters are not necessarily the same type as the args +#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] pub struct Polynomial { /// parameters for the polynomial pub params: Vec, @@ -53,7 +54,7 @@ impl< > Polynomial { /// construct new random polynomial of the specified degree - pub fn random(n: usize, rng: &mut RNG) -> Self { + pub fn random(n: u32, rng: &mut RNG) -> Self { let params = (0..n + 1).map(|_| Param::fill(rng)).collect::>(); Self { params, @@ -78,6 +79,32 @@ impl< } ret } + + /// length of the params + pub fn len(&self) -> usize { + self.params.len() + } +} + +impl Index for Polynomial { + type Output = Param; + fn index<'a>(&'a self, i: usize) -> &'a Param { + &self.params[i] + } +} + +impl Mul for Polynomial +where + Param: Clone + Zero + Random + Add + AddAssign<>::Output> + Mul, + Arg: Clone + One + Mul + Mul + MulAssign, + T: Clone + Zero + Random + Add + AddAssign<>::Output>, + Vec: FromIterator<>::Output>, +{ + type Output = Polynomial; + fn mul(self, x: T) -> Self::Output { + let params: Vec = self.params.iter().map(|p| p.clone() * x.clone()).collect(); + Polynomial::new(params) + } } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] @@ -395,7 +422,7 @@ pub mod test { #[allow(non_snake_case)] fn polynomial() { let mut rng = OsRng; - let n = 16usize; + let n = 16u32; let poly = super::Polynomial::::random(n - 1, &mut rng); let params = poly.params.clone(); @@ -417,6 +444,10 @@ pub mod test { let b = public_poly.eval(Scalar::from(8)); assert_eq!(a * G, b); + let mul_poly = poly * G; + let m = mul_poly.eval(Scalar::from(8)); + assert_eq!(a * G, m); + let b = compute::poly(&Scalar::from(8), &public_params); assert_eq!(a * G, b.unwrap()); diff --git a/src/traits.rs b/src/traits.rs index 7435d606..77c5aa29 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -4,7 +4,9 @@ use rand_core::{CryptoRng, RngCore}; use serde::{Deserialize, Serialize}; use crate::{ - common::{MerkleRoot, Nonce, PolyCommitment, PublicNonce, Signature, SignatureShare}, + common::{ + MerkleRoot, Nonce, PolyCommitment, Polynomial, PublicNonce, Signature, SignatureShare, + }, curve::{point::Point, scalar::Scalar}, errors::{AggregatorError, DkgError}, taproot::SchnorrProof, @@ -14,7 +16,7 @@ use crate::{ /// The saved state required to reconstruct a party pub struct PartyState { /// The party's private polynomial - pub polynomial: Option>, + pub polynomial: Option>, /// The key IDS and associate private keys for this party pub private_keys: Vec<(u32, Scalar)>, /// The nonce being used by this party diff --git a/src/v1.rs b/src/v1.rs index 0f414d23..6cc3a808 100644 --- a/src/v1.rs +++ b/src/v1.rs @@ -4,7 +4,10 @@ use rand_core::{CryptoRng, RngCore}; use tracing::warn; use crate::{ - common::{CheckPrivateShares, Nonce, PolyCommitment, PublicNonce, Signature, SignatureShare}, + common::{ + CheckPrivateShares, Nonce, PolyCommitment, Polynomial, PublicNonce, Signature, + SignatureShare, + }, compute, curve::{ point::{Point, G}, @@ -25,7 +28,7 @@ pub struct Party { /// The public key pub public_key: Point, /// The polynomial used for Lagrange interpolation - pub f: Option>, + pub f: Option>, num_keys: u32, threshold: u32, private_key: Scalar, @@ -92,7 +95,7 @@ impl Party { if let Some(poly) = &self.f { Some(PolyCommitment { id: ID::new(&self.id(), &poly[0], rng), - poly: (0..poly.len()).map(|i| &poly[i] * G).collect(), + poly: (poly.clone() * G).params, }) } else { warn!("get_poly_commitment called with no polynomial"); @@ -129,7 +132,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, compute::private_poly(compute::id(i), poly)); + shares.insert(i, poly.eval(compute::id(i))); } shares } else { diff --git a/src/v2.rs b/src/v2.rs index e67da7a7..7bd1797b 100644 --- a/src/v2.rs +++ b/src/v2.rs @@ -4,7 +4,7 @@ use rand_core::{CryptoRng, RngCore}; use tracing::warn; use crate::{ - common::{Nonce, PolyCommitment, PublicNonce, Signature, SignatureShare}, + common::{Nonce, PolyCommitment, Polynomial, PublicNonce, Signature, SignatureShare}, compute, curve::{ point::{Point, G}, @@ -28,7 +28,7 @@ pub struct Party { num_keys: u32, num_parties: u32, threshold: u32, - f: Option>, + f: Option>, private_keys: HashMap, group_key: Point, nonce: Nonce, @@ -72,7 +72,7 @@ impl Party { if let Some(poly) = &self.f { Some(PolyCommitment { id: ID::new(&self.id(), &poly[0], rng), - poly: (0..poly.len()).map(|i| &poly[i] * G).collect(), + poly: (poly.clone() * G).params, }) } else { warn!("get_poly_commitment called with no polynomial"); @@ -85,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, compute::private_poly(compute::id(i), poly)); + shares.insert(i, poly.eval(compute::id(i))); } } else { warn!("get_poly_commitment called with no polynomial"); diff --git a/src/vss.rs b/src/vss.rs index 2bd7dd26..dc419a56 100644 --- a/src/vss.rs +++ b/src/vss.rs @@ -1,5 +1,6 @@ use rand_core::{CryptoRng, RngCore}; +use crate::common::Polynomial; use crate::curve::scalar::Scalar; /// A verifiable secret share algorithm @@ -7,8 +8,11 @@ pub struct VSS {} impl VSS { /// Construct a random polynomial of the passed degree `n` - pub fn random_poly(n: u32, rng: &mut RNG) -> Vec { - (0..n + 1).map(|_| Scalar::random(rng)).collect() + pub fn random_poly( + n: u32, + rng: &mut RNG, + ) -> Polynomial { + Polynomial::random(n, rng) } /// Construct a random polynomial of the passed degree `n` using the passed constant term @@ -16,10 +20,10 @@ impl VSS { n: u32, constant: Scalar, rng: &mut RNG, - ) -> Vec { - let mut params: Vec = (0..n + 1).map(|_| Scalar::random(rng)).collect(); - params[0] = constant; + ) -> Polynomial { + let mut poly = Polynomial::random(n, rng); + poly.params[0] = constant; - params + poly } } From 2089718960c9fb0eef3ad6b222f099cbbf3f5814 Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Wed, 9 Oct 2024 10:20:58 -0400 Subject: [PATCH 14/21] clippy wants an is_empty if there's a len, and doesn't like needless lifetimes --- src/common.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/common.rs b/src/common.rs index 706d0401..1d4de910 100644 --- a/src/common.rs +++ b/src/common.rs @@ -84,11 +84,16 @@ impl< pub fn len(&self) -> usize { self.params.len() } + + /// is the length of the polynomial zero + pub fn is_empty(&self) -> bool { + self.params.is_empty() + } } impl Index for Polynomial { type Output = Param; - fn index<'a>(&'a self, i: usize) -> &'a Param { + fn index(&self, i: usize) -> &Param { &self.params[i] } } From 2b6d21334f84adb5f06b3c97c46c5c3a9fa4be68 Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Wed, 9 Oct 2024 11:49:14 -0400 Subject: [PATCH 15/21] use where clause for long trait bounds --- src/common.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/common.rs b/src/common.rs index 1d4de910..4cd24c95 100644 --- a/src/common.rs +++ b/src/common.rs @@ -48,10 +48,10 @@ pub struct Polynomial { _x: std::marker::PhantomData, } -impl< - Param: Clone + Zero + Random + Add + AddAssign<>::Output>, - Arg: Clone + One + Mul + MulAssign, - > Polynomial +impl Polynomial +where + Param: Clone + Zero + Random + Add + AddAssign<>::Output>, + Arg: Clone + One + Mul + MulAssign, { /// construct new random polynomial of the specified degree pub fn random(n: u32, rng: &mut RNG) -> Self { From 50adba30bbe5770b843d355fa67bc2bdc814d7ba Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Wed, 9 Oct 2024 13:25:10 -0400 Subject: [PATCH 16/21] make polynomial mul completely generic so it can return a different value from the arg --- src/common.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/common.rs b/src/common.rs index 4cd24c95..3b708797 100644 --- a/src/common.rs +++ b/src/common.rs @@ -98,16 +98,22 @@ impl Index for Polynomial { } } -impl Mul for Polynomial +impl Mul for Polynomial where - Param: Clone + Zero + Random + Add + AddAssign<>::Output> + Mul, - Arg: Clone + One + Mul + Mul + MulAssign, - T: Clone + Zero + Random + Add + AddAssign<>::Output>, - Vec: FromIterator<>::Output>, + Param: Clone + + Zero + + Random + + Add + + AddAssign<>::Output> + + Mul, + Arg: Clone + One + Mul + Mul + MulAssign, + Operand: Clone, + OpResult: Clone + Zero + Random + Add + AddAssign<>::Output>, + Vec: FromIterator<>::Output>, { - type Output = Polynomial; - fn mul(self, x: T) -> Self::Output { - let params: Vec = self.params.iter().map(|p| p.clone() * x.clone()).collect(); + type Output = Polynomial; + fn mul(self, x: Operand) -> Self::Output { + let params: Vec = self.params.iter().map(|p| p.clone() * x.clone()).collect(); Polynomial::new(params) } } From cf05e0d8ada09442e21c1dcb559cce7d6e79eab0 Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Wed, 9 Oct 2024 15:03:10 -0400 Subject: [PATCH 17/21] add Mul impl for &Polynomial to avoid cloning a reference poly --- src/common.rs | 20 ++++++++++++++++++++ src/v1.rs | 2 +- src/v2.rs | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/common.rs b/src/common.rs index 3b708797..371ba9ef 100644 --- a/src/common.rs +++ b/src/common.rs @@ -98,6 +98,26 @@ impl Index for Polynomial { } } +impl Mul for &Polynomial +where + Param: Clone + + Zero + + Random + + Add + + AddAssign<>::Output> + + Mul, + Arg: Clone + One + Mul + Mul + MulAssign, + Operand: Clone, + OpResult: Clone + Zero + Random + Add + AddAssign<>::Output>, + Vec: FromIterator<>::Output>, +{ + type Output = Polynomial; + fn mul(self, x: Operand) -> Self::Output { + let params: Vec = self.params.iter().map(|p| p.clone() * x.clone()).collect(); + Polynomial::new(params) + } +} + impl Mul for Polynomial where Param: Clone diff --git a/src/v1.rs b/src/v1.rs index 6cc3a808..c7ebb750 100644 --- a/src/v1.rs +++ b/src/v1.rs @@ -95,7 +95,7 @@ impl Party { if let Some(poly) = &self.f { Some(PolyCommitment { id: ID::new(&self.id(), &poly[0], rng), - poly: (poly.clone() * G).params, + poly: (poly * G).params, }) } else { warn!("get_poly_commitment called with no polynomial"); diff --git a/src/v2.rs b/src/v2.rs index 7bd1797b..f72a4483 100644 --- a/src/v2.rs +++ b/src/v2.rs @@ -72,7 +72,7 @@ impl Party { if let Some(poly) = &self.f { Some(PolyCommitment { id: ID::new(&self.id(), &poly[0], rng), - poly: (poly.clone() * G).params, + poly: (poly * G).params, }) } else { warn!("get_poly_commitment called with no polynomial"); From 85ae892d159cdab1f6cc65f51423d568cd71c75b Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Wed, 9 Oct 2024 16:57:40 -0400 Subject: [PATCH 18/21] remove compute::private_poly since we can just use common::Polynomial --- src/common.rs | 34 +++++++++++++++++----------------- src/compute.rs | 33 +++++++++------------------------ 2 files changed, 26 insertions(+), 41 deletions(-) diff --git a/src/common.rs b/src/common.rs index 371ba9ef..6141fc0a 100644 --- a/src/common.rs +++ b/src/common.rs @@ -456,43 +456,43 @@ pub mod test { let n = 16u32; let poly = super::Polynomial::::random(n - 1, &mut rng); - let params = poly.params.clone(); - let y = poly.eval(Scalar::from(1)); + let x = Scalar::from(8); + let y = poly.eval(x); let mut z = Scalar::zero(); + let mut pow = Scalar::from(1); for i in 0..poly.params.len() { - z += poly.params[i]; + z += pow * poly.params[i]; + pow *= x; } assert_eq!(y, z); - let a = poly.eval(Scalar::from(8)); - let b = compute::private_poly(Scalar::from(8), ¶ms); - assert_eq!(a, b); - - let public_params = params.iter().map(|p| p * G).collect::>(); + let public_params = poly.params.iter().map(|p| p * G).collect::>(); let public_poly: super::Polynomial = super::Polynomial::new(public_params.clone()); - let a = poly.eval(Scalar::from(8)); - let b = public_poly.eval(Scalar::from(8)); + let a = poly.eval(x); + let b = public_poly.eval(x); assert_eq!(a * G, b); let mul_poly = poly * G; - let m = mul_poly.eval(Scalar::from(8)); - assert_eq!(a * G, m); + let b = mul_poly.eval(x); + assert_eq!(a * G, b); - let b = compute::poly(&Scalar::from(8), &public_params); + let b = compute::poly(&x, &public_params); assert_eq!(a * G, b.unwrap()); let poly = super::Polynomial::random(n - 1, &mut rng); let params = poly.params.clone(); - let y = poly.eval(Scalar::from(1)); + let y = poly.eval(x); let mut z = Point::zero(); + let mut pow = Scalar::from(1); for i in 0..poly.params.len() { - z += poly.params[i]; + z += pow * poly.params[i]; + pow *= x; } assert_eq!(y, z); - let a = poly.eval(Scalar::from(8)); - let b = compute::poly(&Scalar::from(8), ¶ms); + let a = poly.eval(x); + let b = compute::poly(&x, ¶ms); assert_eq!(a, b.unwrap()); } diff --git a/src/compute.rs b/src/compute.rs index 049c9a30..b11632fa 100644 --- a/src/compute.rs +++ b/src/compute.rs @@ -130,18 +130,6 @@ pub fn poly(x: &Scalar, f: &Vec) -> Result { Point::multimult(s, f.clone()) } -/// Evaluate the private polynomial `f` at scalar `x` -#[allow(clippy::ptr_arg)] -pub fn private_poly(x: Scalar, f: &Vec) -> Scalar { - let mut pow = Scalar::one(); - let mut sum = Scalar::zero(); - for i in 0..f.len() { - sum += pow * f[i]; - pow *= x; - } - sum -} - /// Create a BIP340 compliant tagged hash by double hashing the tag pub fn tagged_hash(tag: &str) -> Sha256 { let mut hasher = Sha256::new(); @@ -187,27 +175,24 @@ pub mod test { use rand_core::OsRng; use crate::{ + common::Polynomial, compute, - curve::{ - point::{Point, G}, - scalar::Scalar, - }, + curve::{point::G, scalar::Scalar}, }; #[test] #[allow(non_snake_case)] fn poly() { let mut rng = OsRng; - let n = 16usize; + let n = 16u32; - let private_poly = (0..n) - .map(|_| Scalar::random(&mut rng)) - .collect::>(); - let poly = private_poly.iter().map(|p| p * G).collect::>(); + let private_poly = Polynomial::::random(n - 1, &mut rng); + let public_poly = &private_poly * G; - let x = compute::private_poly(Scalar::from(8), &private_poly); - let y = compute::poly(&Scalar::from(8), &poly); + let x = Scalar::from(8); + let a = private_poly.eval(x); + let b = compute::poly(&x, &public_poly.params); - assert_eq!(x * G, y.unwrap()); + assert_eq!(a * G, b.unwrap()); } } From 9658791a68b6784c0fa0993b83e57a07a1e2a208 Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Wed, 9 Oct 2024 22:27:50 -0400 Subject: [PATCH 19/21] expand on TupleProof comments and change challenge var to c --- src/common.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/common.rs b/src/common.rs index 6141fc0a..36b2a860 100644 --- a/src/common.rs +++ b/src/common.rs @@ -277,19 +277,20 @@ impl Signature { #[allow(non_snake_case)] /// A Chaum-Pedersen proof that (G, A=a*G, B=b*G, K=(a*b)*G) is a DH tuple +/// It consists of two Schnorr proofs. The first shows knowledge of `a`, and the second is just the first multiplied by `b` #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct TupleProof { /// R = r*G for a random scalar r pub R: Point, - /// rB = r*B + /// rB = r*B = b*R pub rB: Point, - /// z = r + a*s where s = H(G,A,B,K,R) as per Fiat-Shamir + /// z = r + a*c where c = H(G,A,B,K,R) as per Fiat-Shamir pub z: Scalar, } impl TupleProof { #[allow(non_snake_case)] - /// Construct a Chaum-Pedersen proof that (G, A, B, K) is a DH tuple + /// Construct a Chaum-Pedersen proof that (A, B, K) is a DH tuple pub fn new( a: &Scalar, A: &Point, @@ -299,21 +300,21 @@ impl TupleProof { ) -> Self { let r = Scalar::random(rng); let R = r * G; - let s = Self::challenge(A, B, K, &R); + let c = Self::challenge(A, B, K, &R); Self { R, rB: r * B, - z: r + a * s, + z: r + a * c, } } #[allow(non_snake_case)] /// Verify the proof using the transcript and public parameters pub fn verify(&self, A: &Point, B: &Point, K: &Point) -> bool { - let s = Self::challenge(A, B, K, &self.R); + let c = Self::challenge(A, B, K, &self.R); - (self.z * G == self.R + s * A) && (self.z * B == self.rB + s * K) + (self.z * G == self.R + c * A) && (self.z * B == self.rB + c * K) } #[allow(non_snake_case)] From 64dd754d6752dd0c0b0c3dcfb76adbaac386ba3b Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Wed, 9 Oct 2024 22:33:05 -0400 Subject: [PATCH 20/21] swap ordering of a and c in TupleProof to match normal Schnorr usage --- src/common.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common.rs b/src/common.rs index 36b2a860..248dc316 100644 --- a/src/common.rs +++ b/src/common.rs @@ -284,7 +284,7 @@ pub struct TupleProof { pub R: Point, /// rB = r*B = b*R pub rB: Point, - /// z = r + a*c where c = H(G,A,B,K,R) as per Fiat-Shamir + /// z = r + c*a where c = H(G,A,B,K,R) as per Fiat-Shamir pub z: Scalar, } @@ -305,7 +305,7 @@ impl TupleProof { Self { R, rB: r * B, - z: r + a * c, + z: r + c * a, } } From 06b1e89390703170682d0a97c8af4144f416dbee Mon Sep 17 00:00:00 2001 From: Joey Yandle Date: Thu, 10 Oct 2024 12:51:22 -0400 Subject: [PATCH 21/21] return error if we're in DkgPublicDistribute during process_message loop --- src/state_machine/coordinator/fire.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/state_machine/coordinator/fire.rs b/src/state_machine/coordinator/fire.rs index 23ea4e8d..25fe350b 100644 --- a/src/state_machine/coordinator/fire.rs +++ b/src/state_machine/coordinator/fire.rs @@ -249,10 +249,7 @@ impl Coordinator { return Ok((None, None)); } State::DkgPublicDistribute => { - // XXX does this ever happen? start_dkg_round should call start_public_shares - //panic!("Got message in DkgPublicDistribute"); - let packet = self.start_public_shares(false)?; - return Ok((Some(packet), None)); + return Err(Error::BadStateChange("should never be in ephemeral DkgPublicDistribute during process_message loop".to_string())); } State::DkgPublicGather => { self.gather_public_shares(packet)?;