Replace indices by "id"s.

The previous implementation was using an "index" to refer to a particular FROST
participant. These references are handled in a different manner now, so they
were changed to "id"s (identifiers).
This commit is contained in:
Marek 2021-06-15 13:11:31 +01:00
parent 55cca1b3ba
commit 4ff263fa62
2 changed files with 49 additions and 52 deletions

View File

@ -62,11 +62,12 @@ impl From<jubjub::ExtendedPoint> for Public {
/// reconstruct the secret; in this case we use Shamir's secret sharing. /// reconstruct the secret; in this case we use Shamir's secret sharing.
#[derive(Clone)] #[derive(Clone)]
pub struct Share { pub struct Share {
receiver_index: u64, /// The receiver id.
receiver_id: u64,
/// Secret Key. /// Secret Key.
pub(crate) value: Secret, value: Secret,
/// The commitments to be distributed among signers. /// The commitments to be distributed among signers.
pub(crate) commitment: ShareCommitment, commitment: ShareCommitment,
} }
/// A Jubjub point that is a commitment to one coefficient of our secret /// A Jubjub point that is a commitment to one coefficient of our secret
@ -105,8 +106,8 @@ pub struct GroupCommitment(pub(crate) jubjub::AffinePoint);
pub struct SharePackage { pub struct SharePackage {
/// The public signing key that represents the entire group. /// The public signing key that represents the entire group.
pub(crate) group_public: VerificationKey<SpendAuth>, pub(crate) group_public: VerificationKey<SpendAuth>,
/// Denotes the participant index each share is owned by. /// Denotes the participant id each share is owned by.
pub index: u64, pub id: u64,
/// This participant's public key. /// This participant's public key.
pub(crate) public: Public, pub(crate) public: Public,
/// This participant's share. /// This participant's share.
@ -128,7 +129,7 @@ impl TryFrom<SharePackage> for KeyPackage {
verify_share(&sharepackage.share)?; verify_share(&sharepackage.share)?;
Ok(KeyPackage { Ok(KeyPackage {
index: sharepackage.index, id: sharepackage.id,
secret_share: sharepackage.share.value, secret_share: sharepackage.share.value,
public: sharepackage.public, public: sharepackage.public,
group_public: sharepackage.group_public, group_public: sharepackage.group_public,
@ -144,7 +145,7 @@ impl TryFrom<SharePackage> for KeyPackage {
/// [`KeyPackage`]s, which they store to later use during signing. /// [`KeyPackage`]s, which they store to later use during signing.
#[allow(dead_code)] #[allow(dead_code)]
pub struct KeyPackage { pub struct KeyPackage {
index: u64, id: u64,
secret_share: Secret, secret_share: Secret,
public: Public, public: Public,
group_public: VerificationKey<SpendAuth>, group_public: VerificationKey<SpendAuth>,
@ -189,13 +190,13 @@ pub fn keygen_with_dealer<R: RngCore + CryptoRng>(
for share in shares { for share in shares {
let signer_public = Public(SpendAuth::basepoint() * share.value.0); let signer_public = Public(SpendAuth::basepoint() * share.value.0);
sharepackages.push(SharePackage { sharepackages.push(SharePackage {
index: share.receiver_index, id: share.receiver_id,
share: share.clone(), share: share.clone(),
public: signer_public, public: signer_public,
group_public, group_public,
}); });
signer_pubkeys.insert(share.receiver_index, signer_public); signer_pubkeys.insert(share.receiver_id, signer_public);
} }
Ok(( Ok((
@ -216,7 +217,7 @@ pub fn keygen_with_dealer<R: RngCore + CryptoRng>(
fn verify_share(share: &Share) -> Result<(), &'static str> { fn verify_share(share: &Share) -> Result<(), &'static str> {
let f_result = SpendAuth::basepoint() * share.value.0; let f_result = SpendAuth::basepoint() * share.value.0;
let x = Scalar::from(share.receiver_index as u64); let x = Scalar::from(share.receiver_id as u64);
let (_, result) = share.commitment.0.iter().fold( let (_, result) = share.commitment.0.iter().fold(
(Scalar::one(), jubjub::ExtendedPoint::identity()), (Scalar::one(), jubjub::ExtendedPoint::identity()),
@ -328,7 +329,7 @@ fn generate_shares<R: RngCore + CryptoRng>(
value += secret.0; value += secret.0;
shares.push(Share { shares.push(Share {
receiver_index: id, receiver_id: id,
value: Secret(value), value: Secret(value),
commitment: commitment.clone(), commitment: commitment.clone(),
}); });
@ -390,19 +391,19 @@ impl SigningNonces {
/// SigningCommitment can be used for exactly *one* signature. /// SigningCommitment can be used for exactly *one* signature.
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct SigningCommitments { pub struct SigningCommitments {
/// The participant index /// The participant id.
pub(crate) index: u64, id: u64,
/// The hiding point. /// The hiding point.
pub(crate) hiding: jubjub::ExtendedPoint, hiding: jubjub::ExtendedPoint,
/// The binding point. /// The binding point.
pub(crate) binding: jubjub::ExtendedPoint, binding: jubjub::ExtendedPoint,
} }
impl From<(u64, &SigningNonces)> for SigningCommitments { impl From<(u64, &SigningNonces)> for SigningCommitments {
/// For SpendAuth signatures only, not Binding signatures, in RedJubjub/Zcash. /// For SpendAuth signatures only, not Binding signatures, in RedJubjub/Zcash.
fn from((index, nonces): (u64, &SigningNonces)) -> Self { fn from((id, nonces): (u64, &SigningNonces)) -> Self {
Self { Self {
index, id,
hiding: SpendAuth::basepoint() * nonces.hiding, hiding: SpendAuth::basepoint() * nonces.hiding,
binding: SpendAuth::basepoint() * nonces.binding, binding: SpendAuth::basepoint() * nonces.binding,
} }
@ -429,8 +430,8 @@ pub struct SignatureResponse(pub(crate) Scalar);
/// with all other signer's shares into the joint signature. /// with all other signer's shares into the joint signature.
#[derive(Clone, Copy, Default)] #[derive(Clone, Copy, Default)]
pub struct SignatureShare { pub struct SignatureShare {
/// Represents the participant index. /// Represents the participant id.
pub(crate) index: u64, pub(crate) id: u64,
/// This participant's signature over the message. /// This participant's signature over the message.
pub(crate) signature: SignatureResponse, pub(crate) signature: SignatureResponse,
} }
@ -467,18 +468,14 @@ impl SignatureShare {
/// perform the first round. Batching entails generating more than one /// perform the first round. Batching entails generating more than one
/// nonce/commitment pair at a time. Nonces should be stored in secret storage /// nonce/commitment pair at a time. Nonces should be stored in secret storage
/// for later use, whereas the commitments are published. /// for later use, whereas the commitments are published.
<<<<<<< HEAD
=======
/// ///
>>>>>>> 316082b (Change the type of the identifiers from u8 to u64)
/// The number of nonces is limited to 255. This limit can be increased if it /// The number of nonces is limited to 255. This limit can be increased if it
/// turns out to be too conservative. /// turns out to be too conservative.
// TODO: Make sure the above is a correct statement, fix if needed in: // TODO: Make sure the above is a correct statement, fix if needed in:
// https://github.com/ZcashFoundation/redjubjub/issues/111 // https://github.com/ZcashFoundation/redjubjub/issues/111
pub fn preprocess<R>( pub fn preprocess<R>(
num_nonces: u8, num_nonces: u8,
participant_index: u64, participant_id: u64,
rng: &mut R, rng: &mut R,
) -> (Vec<SigningNonces>, Vec<SigningCommitments>) ) -> (Vec<SigningNonces>, Vec<SigningCommitments>)
where where
@ -489,7 +486,7 @@ where
for _ in 0..num_nonces { for _ in 0..num_nonces {
let nonces = SigningNonces::new(rng); let nonces = SigningNonces::new(rng);
signing_commitments.push(SigningCommitments::from((participant_index, &nonces))); signing_commitments.push(SigningCommitments::from((participant_id, &nonces)));
signing_nonces.push(nonces); signing_nonces.push(nonces);
} }
@ -498,7 +495,7 @@ where
/// Generates the binding factor that ensures each signature share is strongly /// Generates the binding factor that ensures each signature share is strongly
/// bound to a signing set, specific set of commitments, and a specific message. /// bound to a signing set, specific set of commitments, and a specific message.
fn gen_rho_i(index: u64, signing_package: &SigningPackage) -> Scalar { fn gen_rho_i(id: u64, signing_package: &SigningPackage) -> Scalar {
// Hash signature message with HStar before deriving the binding factor. // Hash signature message with HStar before deriving the binding factor.
// //
// To avoid a collision with other inputs to the hash that generates the // To avoid a collision with other inputs to the hash that generates the
@ -512,11 +509,11 @@ fn gen_rho_i(index: u64, signing_package: &SigningPackage) -> Scalar {
let mut hasher = HStar::default(); let mut hasher = HStar::default();
hasher hasher
.update("FROST_rho".as_bytes()) .update("FROST_rho".as_bytes())
.update(index.to_be_bytes()) .update(id.to_be_bytes())
.update(message_hash.to_bytes()); .update(message_hash.to_bytes());
for item in signing_package.signing_commitments.iter() { for item in signing_package.signing_commitments.iter() {
hasher.update(item.index.to_be_bytes()); hasher.update(item.id.to_be_bytes());
let hiding_bytes = jubjub::AffinePoint::from(item.hiding).to_bytes(); let hiding_bytes = jubjub::AffinePoint::from(item.hiding).to_bytes();
hasher.update(hiding_bytes); hasher.update(hiding_bytes);
let binding_bytes = jubjub::AffinePoint::from(item.binding).to_bytes(); let binding_bytes = jubjub::AffinePoint::from(item.binding).to_bytes();
@ -543,8 +540,8 @@ fn gen_group_commitment(
} }
let rho_i = bindings let rho_i = bindings
.get(&commitment.index) .get(&commitment.id)
.ok_or("No matching commitment index")?; .ok_or("No matching commitment id")?;
accumulator += commitment.hiding + (commitment.binding * rho_i) accumulator += commitment.hiding + (commitment.binding * rho_i)
} }
@ -568,17 +565,17 @@ fn gen_challenge(
/// Generates the lagrange coefficient for the i'th participant. /// Generates the lagrange coefficient for the i'th participant.
fn gen_lagrange_coeff( fn gen_lagrange_coeff(
signer_index: u64, signer_id: u64,
signing_package: &SigningPackage, signing_package: &SigningPackage,
) -> Result<Scalar, &'static str> { ) -> Result<Scalar, &'static str> {
let mut num = Scalar::one(); let mut num = Scalar::one();
let mut den = Scalar::one(); let mut den = Scalar::one();
for commitment in signing_package.signing_commitments.iter() { for commitment in signing_package.signing_commitments.iter() {
if commitment.index == signer_index { if commitment.id == signer_id {
continue; continue;
} }
num *= Scalar::from(commitment.index as u64); num *= Scalar::from(commitment.id as u64);
den *= Scalar::from(commitment.index as u64) - Scalar::from(signer_index as u64); den *= Scalar::from(commitment.id as u64) - Scalar::from(signer_id as u64);
} }
if den == Scalar::zero() { if den == Scalar::zero() {
@ -608,11 +605,11 @@ pub fn sign(
HashMap::with_capacity(signing_package.signing_commitments.len()); HashMap::with_capacity(signing_package.signing_commitments.len());
for comm in signing_package.signing_commitments.iter() { for comm in signing_package.signing_commitments.iter() {
let rho_i = gen_rho_i(comm.index, &signing_package); let rho_i = gen_rho_i(comm.id, &signing_package);
bindings.insert(comm.index, rho_i); bindings.insert(comm.id, rho_i);
} }
let lambda_i = gen_lagrange_coeff(share_package.index, &signing_package)?; let lambda_i = gen_lagrange_coeff(share_package.id, &signing_package)?;
let group_commitment = gen_group_commitment(&signing_package, &bindings)?; let group_commitment = gen_group_commitment(&signing_package, &bindings)?;
@ -623,7 +620,7 @@ pub fn sign(
); );
let participant_rho_i = bindings let participant_rho_i = bindings
.get(&share_package.index) .get(&share_package.id)
.ok_or("No matching binding!")?; .ok_or("No matching binding!")?;
// The Schnorr signature share // The Schnorr signature share
@ -632,7 +629,7 @@ pub fn sign(
+ (lambda_i * share_package.share.value.0 * challenge); + (lambda_i * share_package.share.value.0 * challenge);
Ok(SignatureShare { Ok(SignatureShare {
index: share_package.index, id: share_package.id,
signature: SignatureResponse(signature), signature: SignatureResponse(signature),
}) })
} }
@ -661,8 +658,8 @@ pub fn aggregate(
HashMap::with_capacity(signing_package.signing_commitments.len()); HashMap::with_capacity(signing_package.signing_commitments.len());
for comm in signing_package.signing_commitments.iter() { for comm in signing_package.signing_commitments.iter() {
let rho_i = gen_rho_i(comm.index, &signing_package); let rho_i = gen_rho_i(comm.id, &signing_package);
bindings.insert(comm.index, rho_i); bindings.insert(comm.id, rho_i);
} }
let group_commitment = gen_group_commitment(&signing_package, &bindings)?; let group_commitment = gen_group_commitment(&signing_package, &bindings)?;
@ -670,16 +667,16 @@ pub fn aggregate(
let challenge = gen_challenge(&signing_package, &group_commitment, &pubkeys.group_public); let challenge = gen_challenge(&signing_package, &group_commitment, &pubkeys.group_public);
for signing_share in signing_shares { for signing_share in signing_shares {
let signer_pubkey = pubkeys.signer_pubkeys[&signing_share.index]; let signer_pubkey = pubkeys.signer_pubkeys[&signing_share.id];
let lambda_i = gen_lagrange_coeff(signing_share.index, &signing_package)?; let lambda_i = gen_lagrange_coeff(signing_share.id, &signing_package)?;
let signer_commitment = signing_package let signer_commitment = signing_package
.signing_commitments .signing_commitments
.iter() .iter()
.find(|comm| comm.index == signing_share.index) .find(|comm| comm.id == signing_share.id)
.ok_or("No matching signing commitment for signer")?; .ok_or("No matching signing commitment for signer")?;
let commitment_i = let commitment_i =
signer_commitment.hiding + (signer_commitment.binding * bindings[&signing_share.index]); signer_commitment.hiding + (signer_commitment.binding * bindings[&signing_share.id]);
signing_share.check_is_valid(&signer_pubkey, lambda_i, commitment_i, challenge)?; signing_share.check_is_valid(&signer_pubkey, lambda_i, commitment_i, challenge)?;
} }
@ -719,9 +716,9 @@ mod tests {
if j == i { if j == i {
continue; continue;
} }
num *= Scalar::from(shares[j].receiver_index as u64); num *= Scalar::from(shares[j].receiver_id as u64);
den *= Scalar::from(shares[j].receiver_index as u64) den *= Scalar::from(shares[j].receiver_id as u64)
- Scalar::from(shares[i].receiver_index as u64); - Scalar::from(shares[i].receiver_id as u64);
} }
if den == Scalar::zero() { if den == Scalar::zero() {
return Err("Duplicate shares provided"); return Err("Duplicate shares provided");

View File

@ -19,8 +19,8 @@ fn check_sign_with_dealer() {
for share in &shares { for share in &shares {
// Generate one (1) nonce and one SigningCommitments instance for each // Generate one (1) nonce and one SigningCommitments instance for each
// participant, up to _threshold_. // participant, up to _threshold_.
let (nonce, commitment) = frost::preprocess(1, share.index, &mut rng); let (nonce, commitment) = frost::preprocess(1, share.id, &mut rng);
nonces.insert(share.index, nonce); nonces.insert(share.id, nonce);
commitments.push(commitment[0]); commitments.push(commitment[0]);
} }
@ -35,10 +35,10 @@ fn check_sign_with_dealer() {
}; };
// Round 2: each participant generates their signature share // Round 2: each participant generates their signature share
for (participant_index, nonce) in nonces { for (participant_id, nonce) in nonces {
let share_package = shares let share_package = shares
.iter() .iter()
.find(|share| participant_index == share.index) .find(|share| participant_id == share.id)
.unwrap(); .unwrap();
let nonce_to_use = nonce[0]; let nonce_to_use = nonce[0];
// Each participant generates their signature share. // Each participant generates their signature share.