/// Computes a participant's threshold signing key from the DKG transcript.
///
/// # Arguments
/// * `transcript` - The transcript of the distributed key generation ceremony.
/// * `receiver_index` - The index of the receiver whose signing key is
///   computed.
/// * `fs_secret_key` - The forward-secure decryption key of the given
///   `receiver_index`.
/// * `epoch` - The forward-secure decryption epoch to use.
///
/// # Errors
/// * `CspDkgLoadPrivateKeyError::InvalidTranscriptError` if decryption of the
///   share fails, or the share is invalid.
///
/// # Panics
/// * If Langrange interpolation fails (because of duplicate x-coordinates).
/// * Transcript serialization fails (during creation of an error message).
Computes a participant's threshold signing key from the DKG transcript.
Computes a participant ' s threshold signing key from the DKG transcript .
pub fn compute_threshold_signing_key(
    transcript: &g20::Transcript,
    receiver_index: NodeIndex,
    fs_secret_key: &ForwardSecureSecretKey,
    epoch: g20::Epoch,
) -> Result<threshold_types::SecretKeyBytes, ni_dkg_errors::CspDkgLoadPrivateKeyError> {
    // Get my shares
    let shares_from_each_dealer: Result<BTreeMap<NodeIndex, threshold_types::SecretKey>, _> =
        transcript
            .receiver_data
            .iter()
            .map(|(dealer_index, encrypted_shares)| {
                let fs_plaintext = decrypt(
                    encrypted_shares,
                    fs_secret_key,
                    receiver_index,
                    epoch,
                    &dealer_index.to_be_bytes(),
                )
                .map_err(|error| match error {
                    ni_dkg_errors::DecryptError::EpochTooOld {
                        ciphertext_epoch,
                        secret_key_epoch,
                    } => ni_dkg_errors::CspDkgLoadPrivateKeyError::EpochTooOldError {
                        ciphertext_epoch,
                        secret_key_epoch,
                    },
                    error => {
                        let message = format!(
                            "Dealing #{}: could not get share for receiver #{}.\n {:#?}",
                            dealer_index, receiver_index, error
                        );
                        let error = InvalidArgumentError { message };
                        ni_dkg_errors::CspDkgLoadPrivateKeyError::InvalidTranscriptError(error)
                    }
                })?;
                let secret_key = FrBytes::from(&fs_plaintext);
                let secret_key = fr_from_bytes(&secret_key.0);
                if secret_key.is_err() {
                    let message = format!(
                        "Dealing #{}: has invalid share for receiver #{}.",
                        dealer_index, receiver_index
                    );
                    let error = InvalidArgumentError { message };
                    return Err(
                        ni_dkg_errors::CspDkgLoadPrivateKeyError::InvalidTranscriptError(error),
                    );
                };
                let secret_key = secret_key.expect("Unwrap of None");
                Ok((*dealer_index, secret_key))
            })
            .collect();
    let shares_from_each_dealer = shares_from_each_dealer?;
    // Interpolate
    let combined_shares = {
        let lagrange_coefficients = {
            let reshare_x: Vec<threshold_types::SecretKey> = shares_from_each_dealer
                .keys()
                .copied()
                .map(x_for_index)
                .collect();
            threshold_types::PublicCoefficients::lagrange_coefficients_at_zero(&reshare_x)
                .expect("Cannot fail because all x are distinct.")
        };
        let mut combined_shares = threshold_types::SecretKey::zero();
        for ((_dealer_index, mut share), factor) in shares_from_each_dealer
            .into_iter()
            .zip(lagrange_coefficients)
        {
            // Aggregate the shares:
            share.mul_assign(&factor);
            combined_shares.add_assign(&share);
        }
        threshold_types::SecretKeyBytes::from(combined_shares)
    };
    Ok(combined_shares)
}
pub fn compute_threshold_signing_key ( transcript : & g20 :: Transcript , receiver_index : NodeIndex , fs_secret_key : & ForwardSecureSecretKey , epoch : g20 :: Epoch , ) -> Result < threshold_types :: SecretKeyBytes , ni_dkg_errors :: CspDkgLoadPrivateKeyError > { // Get my shares let shares_from_each_dealer : Result < BTreeMap < NodeIndex , threshold_types :: SecretKey > , _ > = transcript . receiver_data . iter ( ) . map ( | ( dealer_index , encrypted_shares ) | { let fs_plaintext = decrypt ( encrypted_shares , fs_secret_key , receiver_index , epoch , & dealer_index . to_be_bytes ( ) , ) . map_err ( | error | match error { ni_dkg_errors :: DecryptError :: EpochTooOld { ciphertext_epoch , secret_key_epoch , } => ni_dkg_errors :: CspDkgLoadPrivateKeyError :: EpochTooOldError { ciphertext_epoch , secret_key_epoch , } , error => { let message = format ! ( " \n " dealer_index receiver_index error ) ; let error = InvalidArgumentError { message } ; ni_dkg_errors :: CspDkgLoadPrivateKeyError :: InvalidTranscriptError ( error ) } } ) ? ; let secret_key = FrBytes :: from ( & fs_plaintext ) ; let secret_key = fr_from_bytes ( & secret_key . 0 ) ; if secret_key . is_err ( ) { let message = format ! ( " " dealer_index receiver_index ) ; let error = InvalidArgumentError { message } ; return Err ( ni_dkg_errors :: CspDkgLoadPrivateKeyError :: InvalidTranscriptError ( error ) , ) ; } ; let secret_key = secret_key . expect ( " " ) ; Ok ( ( * dealer_index , secret_key ) ) } ) . collect ( ) ; let shares_from_each_dealer = shares_from_each_dealer ? ; // Interpolate let combined_shares = { let lagrange_coefficients = { let reshare_x : Vec < threshold_types :: SecretKey > = shares_from_each_dealer . keys ( ) . copied ( ) . map ( x_for_index ) . collect ( ) ; threshold_types :: PublicCoefficients :: lagrange_coefficients_at_zero ( & reshare_x ) . expect ( " " ) } ; let mut combined_shares = threshold_types :: SecretKey :: zero ( ) ; for ( ( _dealer_index , mut share ) , factor ) in shares_from_each_dealer . into_iter ( ) . zip ( lagrange_coefficients ) { // Aggregate the shares: share . mul_assign ( & factor ) ; combined_shares . add_assign ( & share ) ; } threshold_types :: SecretKeyBytes :: from ( combined_shares ) } ; Ok ( combined_shares ) }
Computes a participant's threshold signing key from the DKG transcript.
Computes a participant ' s threshold signing key from the DKG transcript .
transcript
&g20::Transcript
receiver_index
NodeIndex
fs_secret_key
&ForwardSecureSecretKey
epoch
g20::Epoch
errors
`CspDkgLoadPrivateKeyError::InvalidTranscriptError` if decryption of the
share fails, or the share is invalid.
` CspDkgLoadPrivateKeyError :: InvalidTranscriptError ` if decryption of the share fails or the share is invalid .
panics
If Langrange interpolation fails (because of duplicate x-coordinates).
Transcript serialization fails (during creation of an error message).
If Langrange interpolation fails ( because of duplicate x - coordinates ) . Transcript serialization fails ( during creation of an error message ) .