use frost_core::round2::compute_signature_share;
use frost_core::{
compute_binding_factor_list, compute_group_commitment, derive_interpolating_value, Challenge,
};
use frost_secp256k1::keys::{KeyPackage, PublicKeyPackage};
use frost_secp256k1::round1::SigningNonces;
use frost_secp256k1::round2::SignatureShare;
use std::collections::HashMap;
pub type Scalar = frost_core::Scalar<frost_secp256k1::Secp256K1Sha256>;
#[cfg(feature = "serde")]
pub type ScalarSerialization =
frost_core::serialization::ScalarSerialization<frost_secp256k1::Secp256K1Sha256>;
pub use frost_core;
pub use frost_secp256k1;
pub use frost_secp256k1::round1;
pub use frost_secp256k1::{Error, Identifier, SigningKey, SigningPackage};
pub use schnorr_evm as schnorr;
pub use schnorr_evm::*;
pub mod keys {
pub use frost_secp256k1::keys::*;
}
pub mod round2 {
use super::*;
pub fn sign(
signing_package: &SigningPackage,
signer_nonces: &SigningNonces,
key_package: &KeyPackage,
) -> Result<SignatureShare, Error> {
if signing_package.signing_commitments().len() < *key_package.min_signers() as usize {
return Err(Error::IncorrectNumberOfCommitments);
}
let commitment = signing_package
.signing_commitments()
.get(key_package.identifier())
.ok_or(Error::MissingCommitment)?;
if commitment != &signer_nonces.into() {
return Err(Error::IncorrectCommitment);
}
let binding_factor_list =
compute_binding_factor_list(signing_package, key_package.verifying_key(), &[]);
let binding_factor = binding_factor_list
.get(key_package.identifier())
.ok_or(Error::UnknownIdentifier)?
.clone();
let group_commitment = compute_group_commitment(signing_package, &binding_factor_list)?;
let lambda_i = derive_interpolating_value(key_package.identifier(), signing_package)?;
let group_public = VerifyingKey::new(key_package.verifying_key().to_element());
let challenge = Challenge::from_scalar(group_public.challenge(
VerifyingKey::message_hash(signing_package.message().as_slice()),
group_commitment.to_element(),
));
let signature_share = compute_signature_share(
signer_nonces,
binding_factor,
lambda_i,
key_package,
challenge,
);
Ok(signature_share)
}
pub use frost_secp256k1::round2::SignatureShare;
}
pub fn aggregate(
signing_package: &SigningPackage,
signature_shares: &HashMap<Identifier, SignatureShare>,
pubkeys: &PublicKeyPackage,
) -> Result<Signature, Error> {
if signing_package.signing_commitments().len() != signature_shares.len() {
return Err(Error::UnknownIdentifier);
}
if !signing_package.signing_commitments().keys().all(|id| {
return signature_shares.contains_key(id) && pubkeys.verifying_shares().contains_key(id);
}) {
return Err(Error::UnknownIdentifier);
}
let binding_factor_list =
compute_binding_factor_list(signing_package, pubkeys.verifying_key(), &[]);
let group_commitment = compute_group_commitment(signing_package, &binding_factor_list)?;
let mut z = Scalar::ZERO;
for signature_share in signature_shares.values() {
z += signature_share.share();
}
let group_public = VerifyingKey::new(pubkeys.verifying_key().to_element());
let challenge = group_public.challenge(
VerifyingKey::message_hash(signing_package.message().as_slice()),
group_commitment.to_element(),
);
let signature = Signature::new(challenge, z);
let verification_result = group_public
.verify(signing_package.message(), &signature)
.map_err(|_| Error::MalformedSignature);
if let Err(err) = verification_result {
for (signature_share_identifier, signature_share) in signature_shares {
let signer_pubkey = pubkeys
.verifying_shares()
.get(signature_share_identifier)
.unwrap();
let lambda_i = derive_interpolating_value(signature_share_identifier, signing_package)?;
let binding_factor = binding_factor_list
.get(signature_share_identifier)
.ok_or(Error::UnknownIdentifier)?
.clone();
let r_share = signing_package
.signing_commitment(signature_share_identifier)
.ok_or(Error::UnknownIdentifier)?
.to_group_commitment_share(&binding_factor);
signature_share.verify(
*signature_share_identifier,
&r_share,
signer_pubkey,
lambda_i,
&Challenge::from_scalar(challenge),
)?;
}
return Err(err);
}
Ok(signature)
}