diff --git a/fastcrypto-tbls/src/dkg.rs b/fastcrypto-tbls/src/dkg.rs index 9525862bbd..e237425707 100644 --- a/fastcrypto-tbls/src/dkg.rs +++ b/fastcrypto-tbls/src/dkg.rs @@ -26,6 +26,8 @@ use tap::prelude::*; /// Generics below use `G: GroupElement' for the group of the VSS public key, and `EG: GroupElement' /// for the group of the ECIES public key. +// TODO: Add a description of the protocol. + /// Party in the DKG protocol. #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Party { @@ -47,7 +49,6 @@ pub struct Party { pub struct Message { pub sender: PartyId, /// The commitment of the secret polynomial created by the sender. - // TODO: [security] add a proof of possession/knowledge? pub vss_pk: PublicPoly, /// The encrypted shares created by the sender. Sorted according to the receivers. pub encrypted_shares: MultiRecipientEncryption, @@ -125,6 +126,8 @@ pub struct Output { pub shares: Option>>, // None if some shares are missing. } +// TODO: Handle parties with zero weights (currently rejected by Nodes::new()). + /// A dealer in the DKG ceremony. /// /// Can be instantiated with G1Curve or G2Curve. @@ -152,7 +155,7 @@ where .ok_or(FastCryptoError::InvalidInput)? .id; // Check that the threshold makes sense. - if t >= nodes.n() || t == 0 { + if t >= nodes.total_weight() || t == 0 { return Err(FastCryptoError::InvalidInput); } // TODO: [comm opt] Instead of generating the polynomial at random, use PRF generated values @@ -166,7 +169,7 @@ where my_id, nodes.hash(), t, - nodes.n(), + nodes.total_weight(), random_oracle, enc_pk, vss_pk.c0(), @@ -182,6 +185,7 @@ where }) } + /// The threshold needed to reconstruct the full key/signature. pub fn t(&self) -> u32 { self.t } @@ -304,7 +308,7 @@ where let encrypted_shares = &message .encrypted_shares .get_encryption(self.id as usize) - .expect("checked above that there are enough encryptions"); + .expect("checked in sanity_check_message that there are enough encryptions"); let decrypted_shares = Self::decrypt_and_get_share(&self.enc_sk, encrypted_shares).ok(); if decrypted_shares.is_none() @@ -420,10 +424,9 @@ where complaints: Vec::new(), }; for m in &filtered_messages.0 { - if m.complaint.is_some() { + if let Some(complaint) = &m.complaint { debug!("DKG: Including a complaint on party {}", m.message.sender); - let complaint = m.complaint.clone().expect("checked above"); - conf.complaints.push(complaint); + conf.complaints.push(complaint.clone()); } } Ok((conf, filtered_messages)) @@ -492,27 +495,28 @@ where let accuser_pk = id_to_pk .get(&accuser) .expect("checked above that accuser is valid id"); - let related_m1 = id_to_m1.get(&accused); // If the claim refers to a non existing message, it's an invalid complaint. - let valid_complaint = related_m1.is_some() && { - let encrypted_shares = &related_m1 - .expect("checked above that is not None") - .encrypted_shares - .get_encryption(accuser as usize) - .expect("checked earlier that there are enough encryptions"); - Self::check_complaint_proof( - &complaint.proof, - accuser_pk, - &self.nodes.share_ids_of(accuser), - &related_m1.expect("checked above that is not None").vss_pk, - encrypted_shares, - &self.random_oracle.extend(&format!( - "recovery of id {} received from {}", - accuser, accused - )), - rng, - ) - .is_ok() + let valid_complaint = match id_to_m1.get(&accused) { + Some(related_m1) => { + let encrypted_shares = &related_m1 + .encrypted_shares + .get_encryption(accuser as usize) + .expect("checked earlier that there are enough encryptions"); + Self::check_complaint_proof( + &complaint.proof, + accuser_pk, + &self.nodes.share_ids_of(accuser), + &related_m1.vss_pk, + encrypted_shares, + &self.random_oracle.extend(&format!( + "recovery of id {} received from {}", + accuser, accused + )), + rng, + ) + .is_ok() + } + None => false, }; match valid_complaint { // Ignore accused from now on, and continue processing complaints from the diff --git a/fastcrypto-tbls/src/dl_verification.rs b/fastcrypto-tbls/src/dl_verification.rs index 5c300899e2..c71d5e44a5 100644 --- a/fastcrypto-tbls/src/dl_verification.rs +++ b/fastcrypto-tbls/src/dl_verification.rs @@ -16,8 +16,9 @@ fn dot(v1: &[S], v2: &[S]) -> S { .fold(S::zero(), |acc, (a, b)| acc + *a * *b) } -/// Given a set of indexes and a vector of random scalars , -/// returns the vector v such that = \sum ri * p(ai) for a polynomial p with coefficients c. +/// Given a set of indexes (a1, a2, ..., an) and a vector of random scalars (r1, r2, ..., rn), +/// returns the vector v such that = \sum ri * p(ai) for the polynomial p with coefficients c +/// and the given degree. pub(crate) fn batch_coefficients(r: &[S], indexes: &[S], degree: u32) -> Vec { assert!(r.len() == indexes.len() && degree > 0); // Should never happen let mut multiplies = r.to_vec(); diff --git a/fastcrypto-tbls/src/nidkg.rs b/fastcrypto-tbls/src/nidkg.rs index 98e74956ed..2239e15b83 100644 --- a/fastcrypto-tbls/src/nidkg.rs +++ b/fastcrypto-tbls/src/nidkg.rs @@ -105,7 +105,7 @@ where .ok_or(FastCryptoError::InvalidInput)? .id; let nodes = Nodes::new(nodes)?; - let n = nodes.n(); + let n = nodes.total_weight(); if t >= n { return Err(FastCryptoError::InvalidInput); } @@ -184,9 +184,9 @@ where // Compute the cut-and-choose challenge bits. let ro = self .random_oracle - .extend(format!("-{}-cut-and-choose", self.id).as_str()); + .extend(format!("_{}_cut_and_choose", self.id).as_str()); let seed = ro.evaluate(&msg_before_fiat_shamir); - let challenge = Self::challenge(seed.as_slice(), self.nodes.n()); + let challenge = Self::challenge(seed.as_slice(), self.nodes.total_weight()); // Reveal the scalars corresponding to the challenge bits. let processed_pairs = izip!( @@ -227,7 +227,7 @@ where ) -> FastCryptoResult<()> { // Check the degree of the sender's polynomial.. verify_deg_t_poly( - self.nodes.n() - self.t - 1, + self.nodes.total_weight() - self.t - 1, &msg.partial_pks, &self.precomputed_dual_code_coefficients, rng, @@ -240,9 +240,9 @@ where }; let ro = self .random_oracle - .extend(format!("-{}-cut-and-choose", msg.sender).as_str()); + .extend(format!("_{}_cut_and_choose", msg.sender).as_str()); let seed = ro.evaluate(&msg_before_fiat_shamir); - let challenge = Self::challenge(seed.as_slice(), self.nodes.n()); + let challenge = Self::challenge(seed.as_slice(), self.nodes.total_weight()); let mut pairs_to_check = Vec::new(); let mut tuples_to_check = Vec::new(); @@ -315,7 +315,7 @@ where pub fn compute_final_pks(&self, messages: &[Message]) -> (G, Vec) { assert!(self.is_above_t(messages).is_ok()); - let partial_pks = (0..self.nodes.n()) + let partial_pks = (0..self.nodes.total_weight()) .map(|i| { messages .iter() diff --git a/fastcrypto-tbls/src/nizk.rs b/fastcrypto-tbls/src/nizk.rs index 8e44e67c46..aa5c2877ee 100644 --- a/fastcrypto-tbls/src/nizk.rs +++ b/fastcrypto-tbls/src/nizk.rs @@ -11,7 +11,7 @@ use tracing::debug; /// NIZKPoK for the DDH tuple [G, H=eG, xG, xH]. /// - Prover selects a random r and sends A=rG, B=rH. /// - Prover computes challenge c and sends z=r+c*x. -/// - Verifier checks that zG=A+c(xG) and zeG=B+c(xH). +/// - Verifier checks that zG=A+c(xG) and zH=B+c(xH). /// The NIZK is (A, B, z) where c is implicitly computed using a random oracle. #[derive(Debug, Clone, PartialEq, Eq, Serialize)] pub(crate) struct DdhTupleNizk(G, G, G::ScalarType); @@ -21,6 +21,7 @@ where G: GroupElement + Serialize, ::ScalarType: FiatShamirChallenge, { + /// Create a new NIZKPoK for the DDH tuple [G, H=eG, xG, xH] using the given RNG and random oracle. pub fn create( x: &G::ScalarType, h: &G, @@ -38,6 +39,7 @@ where DdhTupleNizk(a, b, z) } + /// Verify this NIZKPoK. pub fn verify( &self, h: &G, @@ -51,13 +53,13 @@ where } let challenge = Self::fiat_shamir_challenge(h, x_g, x_h, &self.0, &self.1, random_oracle); debug!("NIZK: Verifying a proof of {h:?} {x_g:?} {x_h:?} with challenge {challenge:?}"); - if !Self::is_valid_relation( + if !is_valid_relation( &self.0, // A x_g, &G::generator(), &self.2, // z &challenge, - ) || !Self::is_valid_relation( + ) || !is_valid_relation( &self.1, // B x_h, h, &self.2, // z &challenge, @@ -80,13 +82,6 @@ where let output = random_oracle.evaluate(&(G::generator(), h, x_g, x_h, a, b)); G::ScalarType::fiat_shamir_reduction_to_group_element(&output) } - - /// Checks if e1 + e2*c = z e3 - fn is_valid_relation(e1: &G, e2: &G, e3: &G, z: &G::ScalarType, c: &G::ScalarType) -> bool { - let left = *e1 + *e2 * c; - let right = *e3 * z; - left == right - } } impl<'de, G> Deserialize<'de> for DdhTupleNizk @@ -121,6 +116,7 @@ where G: GroupElement + Serialize, ::ScalarType: FiatShamirChallenge, { + /// Create a new NIZKPoK for the DL [G, xG] using the given RNG and random oracle. pub fn create( x: &G::ScalarType, x_g: &G, // passed since probably already computed @@ -148,7 +144,7 @@ where } let challenge = Self::fiat_shamir_challenge(x_g, &self.0, aux_ro_input, random_oracle); debug!("NIZK: Verifying a proof of {x_g:?} with challenge {challenge:?}"); - if (G::generator() * self.1) != (self.0 + *x_g * challenge) { + if !is_valid_relation(&self.0, x_g, &G::generator(), &self.1, &challenge) { Err(FastCryptoError::InvalidProof) } else { Ok(()) @@ -185,3 +181,16 @@ where Ok(DLNizk(tuple.0, tuple.1)) } } + +/// Checks if e1 + c e2 = z e3 +fn is_valid_relation( + e1: &G, + e2: &G, + e3: &G, + z: &G::ScalarType, + c: &G::ScalarType, +) -> bool { + let left = *e1 + *e2 * c; + let right = *e3 * z; + left == right +} diff --git a/fastcrypto-tbls/src/nodes.rs b/fastcrypto-tbls/src/nodes.rs index 50118ff18e..213536bd7a 100644 --- a/fastcrypto-tbls/src/nodes.rs +++ b/fastcrypto-tbls/src/nodes.rs @@ -8,10 +8,10 @@ use fastcrypto::error::{FastCryptoError, FastCryptoResult}; use fastcrypto::groups::GroupElement; use fastcrypto::hash::{Blake2b256, Digest, HashFunction}; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; pub type PartyId = u16; +/// Public parameters of a party. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Node { pub id: PartyId, @@ -19,11 +19,12 @@ pub struct Node { pub weight: u16, } +/// Wrapper for a set of nodes. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Nodes { - nodes: Vec>, // Party ids are 0..len(nodes)-1 - n: u32, // Share ids are 1..n - share_id_to_party_id: HashMap, + nodes: Vec>, // Party ids are 0..len(nodes)-1 + total_weight: u32, // Share ids are 1..total_weight + accumulated_weights: Vec, // Accumulated sum of all nodes' weights. Used to map share ids to party ids. } impl Nodes { @@ -36,37 +37,41 @@ impl Nodes { return Err(FastCryptoError::InvalidInput); } // Make sure we never overflow, as we don't expect to have more than 1000 nodes - if nodes.len() > 1000 { + if nodes.is_empty() || nodes.len() > 1000 { + return Err(FastCryptoError::InvalidInput); + } + // Check that all weights are non-zero + if nodes.iter().any(|n| n.weight == 0) { return Err(FastCryptoError::InvalidInput); } - // Get the total weight of the nodes - let n = nodes.iter().map(|n| n.weight as u32).sum::(); - let share_id_to_party_id = Self::get_share_id_to_party_id(&nodes); + // We use accumulated weights to map share ids to party ids. + let accumulated_weights = Self::get_accumulated_weights(&nodes); + let total_weight = *accumulated_weights + .last() + .expect("Number of nodes is non-zero"); Ok(Self { nodes, - n, - share_id_to_party_id, + total_weight, + accumulated_weights, }) } - fn get_share_id_to_party_id(nodes: &Vec>) -> HashMap { - let mut curr_share_id = 1; - let mut share_id_to_party_id = HashMap::new(); - for n in nodes { - for _ in 1..=n.weight { - let share_id = ShareIndex::new(curr_share_id).expect("nonzero"); - share_id_to_party_id.insert(share_id, n.id); - curr_share_id += 1; - } - } - share_id_to_party_id + fn get_accumulated_weights(nodes: &[Node]) -> Vec { + nodes + .iter() + .map(|n| n.weight as u32) + .scan(0, |accumulated_weight, weight| { + *accumulated_weight += weight; + Some(*accumulated_weight) + }) + .collect::>() } /// Total weight of the nodes. - pub fn n(&self) -> u32 { - self.n + pub fn total_weight(&self) -> u32 { + self.total_weight } /// Number of nodes. @@ -76,15 +81,18 @@ impl Nodes { /// Get an iterator on the share ids. pub fn share_ids_iter(&self) -> impl Iterator { - (1..=self.n).map(|i| ShareIndex::new(i).expect("nonzero")) + (1..=self.total_weight).map(|i| ShareIndex::new(i).expect("nonzero")) } /// Get the node corresponding to a share id. pub fn share_id_to_node(&self, share_id: &ShareIndex) -> FastCryptoResult<&Node> { - self.share_id_to_party_id - .get(share_id) - .map(|id| self.node_id_to_node(*id)) - .ok_or(FastCryptoError::InvalidInput)? + let node_id: PartyId = match self.accumulated_weights.binary_search(&share_id.get()) { + Ok(i) => i, + Err(i) => i, + } + .try_into() + .map_err(|_| InvalidInput)?; + self.node_id_to_node(node_id) } pub fn node_id_to_node(&self, party_id: PartyId) -> FastCryptoResult<&Node> { @@ -124,6 +132,10 @@ impl Nodes { pub fn reduce(&self, t: u16, allowed_delta: u16) -> (Self, u16) { let mut max_d = 1; for d in 2..=40 { + // TODO: [perf] Remove once the DKG & Nodes can work with zero weights. + if self.nodes.iter().any(|n| n.weight < d) { + break; + } let sum = self.nodes.iter().map(|n| n.weight % d).sum::(); if sum <= allowed_delta { max_d = d; @@ -138,14 +150,14 @@ impl Nodes { weight: n.weight / max_d, }) .collect::>(); - let share_id_to_party_id = Self::get_share_id_to_party_id(&nodes); - let n = nodes.iter().map(|n| n.weight as u32).sum::(); + let accumulated_weights = Self::get_accumulated_weights(&nodes); + let total_weight = nodes.iter().map(|n| n.weight as u32).sum::(); let new_t = t / max_d + (t % max_d != 0) as u16; ( Self { nodes, - n, - share_id_to_party_id, + total_weight, + accumulated_weights, }, new_t, ) diff --git a/fastcrypto-tbls/src/polynomial.rs b/fastcrypto-tbls/src/polynomial.rs index d54e621b12..bb0818daec 100644 --- a/fastcrypto-tbls/src/polynomial.rs +++ b/fastcrypto-tbls/src/polynomial.rs @@ -64,6 +64,7 @@ impl Poly { /// Evaluates the polynomial at the specified value. pub fn eval(&self, i: ShareIndex) -> Eval { + // Use Horner's Method to evaluate the polynomial. let xi = C::ScalarType::from(i.get().into()); let res = self .0 @@ -87,10 +88,7 @@ impl Poly { } // Check for duplicates. let mut ids_set = HashSet::new(); - shares.iter().map(|s| &s.index).for_each(|id| { - ids_set.insert(id); - }); - if ids_set.len() != shares.len() { + if !shares.iter().map(|s| &s.index).all(|id| ids_set.insert(id)) { return Err(FastCryptoError::InvalidInput); // expected unique ids } diff --git a/fastcrypto-tbls/src/random_oracle.rs b/fastcrypto-tbls/src/random_oracle.rs index 343c9b2246..196b46272c 100644 --- a/fastcrypto-tbls/src/random_oracle.rs +++ b/fastcrypto-tbls/src/random_oracle.rs @@ -8,13 +8,14 @@ use std::fmt::Debug; /// Random Oracle from SHA3-512. /// - prefix should be globally unique. -/// - evaluate serializes the given input and outputs SHA3-512(prefix_len as u8 | prefix | input). +/// - evaluate serializes the given input and outputs SHA3-512(prefix_len as big-endian u32 | prefix | input). /// - Subprotocols may use a prefix that is extended from the prefix of its parent protocol, by /// deriving a new instance using extend, which simply concatenates the strings with the separator /// "-". E.g., RandomOracle::new("abc").extend("def") = RandomOracle::new("abc-def"). /// /// The caller must make sure to: -/// - Choose distinct prefix & extension strings, preferably without "-" in them. +/// - Choose distinct prefix & extension strings, preferably without "-" in them (asserted in debug +/// mode). /// - Ensure that the length of prefix & extension is small enough to fit in u32. /// Violating this constraint will cause a panic. @@ -24,7 +25,9 @@ pub struct RandomOracle { } impl RandomOracle { + /// Create a fresh random oracle with a given "session id"/prefix. pub fn new(initial_prefix: &str) -> Self { + debug_assert!(!initial_prefix.contains('-')); // Since we shouldn't get such long prefixes, it's safe to assert here. assert!(initial_prefix.len() < u32::MAX as usize); Self { @@ -32,6 +35,7 @@ impl RandomOracle { } } + /// Evaluate the random oracle on a given input. pub fn evaluate(&self, obj: &T) -> [u8; 64] { let mut hasher = Sha3_512::default(); let len: u32 = self @@ -46,7 +50,9 @@ impl RandomOracle { hasher.finalize().into() } + /// Derive a new random oracle from the current one and additional string (can be done multiple times). pub fn extend(&self, extension: &str) -> Self { + debug_assert!(!extension.contains('-')); // Since we shouldn't get such long prefixes, it's safe to assert here. assert!(self.prefix.len() + extension.len() + 1 < u32::MAX as usize); Self { diff --git a/fastcrypto-tbls/src/tbls.rs b/fastcrypto-tbls/src/tbls.rs index 5c13da2f4d..93e96b6251 100644 --- a/fastcrypto-tbls/src/tbls.rs +++ b/fastcrypto-tbls/src/tbls.rs @@ -23,18 +23,9 @@ pub trait ThresholdBls { /// `Signature` represents the group over which the signatures are represented. type Signature: GroupElement + HashToGroupElement + MultiScalarMul; - /// Curve dependent implementation of computing and comparing the pairings as part of the - /// signature verification. - fn verify_pairings( - pk: &Self::Public, - sig: &Self::Signature, - msg: &[u8], - ) -> FastCryptoResult<()>; - - /// Verify a signature on a given message. - fn verify(public: &Self::Public, msg: &[u8], sig: &Self::Signature) -> FastCryptoResult<()> { - Self::verify_pairings(public, sig, msg).map_err(|_| FastCryptoError::InvalidSignature) - } + /// Verify a signature on a given message. This is standard BLS signature verification + /// over the used curve construction. + fn verify(public: &Self::Public, msg: &[u8], sig: &Self::Signature) -> FastCryptoResult<()>; /// Sign a message using the private share/partial key. fn partial_sign(share: &Share, msg: &[u8]) -> PartialSignature { diff --git a/fastcrypto-tbls/src/tests/nodes_tests.rs b/fastcrypto-tbls/src/tests/nodes_tests.rs index a84e44e2cc..546d621693 100644 --- a/fastcrypto-tbls/src/tests/nodes_tests.rs +++ b/fastcrypto-tbls/src/tests/nodes_tests.rs @@ -34,6 +34,10 @@ fn test_new_failures() { let mut nodes_vec = get_nodes::(20); nodes_vec.remove(7); assert!(Nodes::new(nodes_vec).is_err()); + // start id is not 0 + let mut nodes_vec = get_nodes::(20); + nodes_vec.remove(0); + assert!(Nodes::new(nodes_vec).is_err()); // duplicate id let mut nodes_vec = get_nodes::(20); nodes_vec[19].id = 1; @@ -41,6 +45,13 @@ fn test_new_failures() { // too many nodes let nodes_vec = get_nodes::(20000); assert!(Nodes::new(nodes_vec).is_err()); + // too little + let nodes_vec: Vec> = Vec::new(); + assert!(Nodes::new(nodes_vec).is_err()); + // with zero weight + let mut nodes_vec = get_nodes::(20); + nodes_vec[19].weight = 0; + assert!(Nodes::new(nodes_vec).is_err()); } #[test] @@ -59,7 +70,7 @@ fn test_new_order() { fn test_interfaces() { let nodes_vec = get_nodes::(100); let nodes = Nodes::new(nodes_vec.clone()).unwrap(); - assert_eq!(nodes.n(), 5050); + assert_eq!(nodes.total_weight(), 5050); assert_eq!(nodes.num_nodes(), 100); assert!(nodes .share_ids_iter() @@ -84,6 +95,18 @@ fn test_interfaces() { .unwrap(), &nodes_vec[2] ); + assert_eq!( + nodes + .share_id_to_node(&NonZeroU32::new(5050).unwrap()) + .unwrap(), + &nodes_vec[99] + ); + assert!(nodes + .share_id_to_node(&NonZeroU32::new(5051).unwrap()) + .is_err()); + assert!(nodes + .share_id_to_node(&NonZeroU32::new(15051).unwrap()) + .is_err()); assert_eq!(nodes.node_id_to_node(1).unwrap(), &nodes_vec[1]); @@ -98,7 +121,7 @@ fn test_reduce() { for number_of_nodes in [10, 50, 100, 150, 200, 250, 300, 350, 400] { let node_vec = get_nodes::(number_of_nodes); let nodes = Nodes::new(node_vec).unwrap(); - let t = (nodes.n() / 3) as u16; + let t = (nodes.total_weight() / 3) as u16; // No extra gap, should return the inputs let (new_nodes, new_t) = nodes.reduce(t, 1); @@ -106,11 +129,11 @@ fn test_reduce() { assert_eq!(t, new_t); // 10% gap - let (new_nodes, _new_t) = nodes.reduce(t, (nodes.n() / 10) as u16); + let (new_nodes, _new_t) = nodes.reduce(t, (nodes.total_weight() / 10) as u16); // Estimate the real factor d let d = nodes.iter().last().unwrap().weight / new_nodes.iter().last().unwrap().weight; // The loss per node is on average (d - 1) / 2 // We use 9 instead of 10 to compensate wrong value of d - assert!((d - 1) / 2 * number_of_nodes < ((nodes.n() / 9) as u16)); + assert!((d - 1) / 2 * number_of_nodes < ((nodes.total_weight() / 9) as u16)); } } diff --git a/fastcrypto-tbls/src/tests/random_oracle_tests.rs b/fastcrypto-tbls/src/tests/random_oracle_tests.rs index cf3d119f6e..6fca4bcfbd 100644 --- a/fastcrypto-tbls/src/tests/random_oracle_tests.rs +++ b/fastcrypto-tbls/src/tests/random_oracle_tests.rs @@ -12,8 +12,6 @@ fn test_random_oracle() { assert_ne!(ro1.evaluate(&"alice"), ro2.evaluate(&"alice")); let ro3 = ro1.extend("def"); assert_ne!(ro1.evaluate(&"alice"), ro3.evaluate(&"alice")); - let ro4 = RandomOracle::new("abc-def"); - assert_eq!(ro3.evaluate(&"alice"), ro4.evaluate(&"alice")); } #[test] @@ -24,8 +22,6 @@ fn test_empty_strings() { let ro3 = ro2.extend(""); assert_ne!(ro3.evaluate(&"alice"), ro2.evaluate(&"alice")); - let ro4 = RandomOracle::new("def-"); - assert_eq!(ro3.evaluate(&"alice"), ro4.evaluate(&"alice")); } #[test] diff --git a/fastcrypto-tbls/src/types.rs b/fastcrypto-tbls/src/types.rs index 959070c7ab..dd40392546 100644 --- a/fastcrypto-tbls/src/types.rs +++ b/fastcrypto-tbls/src/types.rs @@ -18,11 +18,7 @@ impl tbls::ThresholdBls for ThresholdBls12381MinSig { type Public = bls12381::G2Element; type Signature = bls12381::G1Element; - fn verify_pairings( - pk: &Self::Public, - sig: &Self::Signature, - msg: &[u8], - ) -> FastCryptoResult<()> { + fn verify(pk: &Self::Public, msg: &[u8], sig: &Self::Signature) -> FastCryptoResult<()> { let hashed_message = Self::Signature::hash_to_group_element(msg); // e(sig, g2) let left = sig.pairing(&Self::Public::generator());