use anyhow::Context;
use std::marker::PhantomData;
#[cfg(feature = "future_snark")]
use anyhow::anyhow;
use crate::{
AggregateVerificationKey, ClosedKeyRegistration, LotteryIndex, MembershipDigest, Parameters,
Signer, SingleSignature, Stake, StmResult, VerificationKeyForConcatenation,
proof_system::{ConcatenationClerk, ConcatenationProof},
};
#[cfg(feature = "future_snark")]
use crate::AggregateSignatureError;
#[cfg(feature = "future_snark")]
use crate::proof_system::{SnarkClerk, SnarkProver};
use super::{AggregateSignature, AggregateSignatureType};
#[derive(Debug, Clone)]
pub struct Clerk<D: MembershipDigest> {
concatenation_proof_clerk: ConcatenationClerk,
#[cfg(feature = "future_snark")]
snark_proof_clerk: Option<SnarkClerk>,
phantom_data: PhantomData<D>,
}
impl<D: MembershipDigest> Clerk<D> {
pub fn new_clerk_from_signer(signer: &Signer<D>) -> Self {
Self {
concatenation_proof_clerk: ConcatenationClerk::new_clerk_from_signer(signer),
#[cfg(feature = "future_snark")]
snark_proof_clerk: signer
.closed_key_registration
.has_snark_verification_keys()
.then(|| SnarkClerk::new_clerk_from_signer(signer)),
phantom_data: PhantomData,
}
}
pub fn new_clerk_from_closed_key_registration(
parameters: &Parameters,
closed_registration: &ClosedKeyRegistration,
) -> Self {
Self {
concatenation_proof_clerk: ConcatenationClerk::new_clerk_from_closed_key_registration(
parameters,
closed_registration,
),
#[cfg(feature = "future_snark")]
snark_proof_clerk: closed_registration.has_snark_verification_keys().then(|| {
SnarkClerk::new_clerk_from_closed_key_registration(parameters, closed_registration)
}),
phantom_data: PhantomData,
}
}
pub fn aggregate_signatures_with_type(
&self,
sigs: &[SingleSignature],
msg: &[u8],
aggregate_signature_type: AggregateSignatureType,
) -> StmResult<AggregateSignature<D>> {
match aggregate_signature_type {
AggregateSignatureType::Concatenation => {
Ok(AggregateSignature::Concatenation(Box::new(
ConcatenationProof::aggregate_signatures(
self.get_concatenation_clerk(),
sigs,
msg,
)
.with_context(|| {
format!(
"Signatures failed to aggregate for type {}",
AggregateSignatureType::Concatenation
)
})?,
)))
}
#[cfg(feature = "future_snark")]
AggregateSignatureType::Snark => {
let clerk = self
.get_snark_clerk()
.ok_or_else(|| anyhow!(AggregateSignatureError::MissingSnarkClerk))?;
let merkle_tree_depth = clerk
.closed_key_registration
.number_of_registered_parties()
.next_power_of_two()
.trailing_zeros();
SnarkProver::try_new_non_deterministic(&clerk.parameters, merkle_tree_depth)?
.aggregate_signatures(clerk, sigs, msg)
.map(|p| AggregateSignature::Snark(Box::new(p)))
.with_context(|| {
format!(
"Signatures failed to aggregate for type {}",
AggregateSignatureType::Snark
)
})
}
}
}
pub fn get_concatenation_clerk(&self) -> &ConcatenationClerk {
&self.concatenation_proof_clerk
}
#[cfg(feature = "future_snark")]
pub fn get_snark_clerk(&self) -> Option<&SnarkClerk> {
self.snark_proof_clerk.as_ref()
}
pub fn compute_aggregate_verification_key(&self) -> AggregateVerificationKey<D> {
AggregateVerificationKey::new(
self.concatenation_proof_clerk
.compute_aggregate_verification_key_for_concatenation(),
#[cfg(feature = "future_snark")]
self.snark_proof_clerk
.as_ref()
.map(|clerk| clerk.compute_aggregate_verification_key_for_snark()),
)
}
pub fn get_concatenation_registered_party_for_index(
&self,
party_index: &LotteryIndex,
) -> StmResult<(VerificationKeyForConcatenation, Stake)> {
let entry = self
.get_concatenation_clerk()
.closed_key_registration
.get_registration_entry_for_index(party_index)?;
Ok((
entry.get_verification_key_for_concatenation(),
entry.get_stake(),
))
}
#[cfg(test)]
pub fn update_k(&mut self, k: u64) {
self.concatenation_proof_clerk.update_k(k);
}
#[cfg(test)]
pub fn update_m(&mut self, m: u64) {
self.concatenation_proof_clerk.update_m(m);
}
}